aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/ast/AST.h4
-rw-r--r--libsolidity/ast/ASTVisitor.h2
-rw-r--r--libsolidity/ast/Types.cpp41
-rw-r--r--libsolidity/ast/Types.h8
-rw-r--r--libsolidity/codegen/LValue.h1
-rw-r--r--libsolidity/formal/SolverInterface.h1
-rw-r--r--libsolidity/formal/SymbolicVariable.h1
-rw-r--r--libsolidity/parsing/Parser.cpp119
-rw-r--r--libsolidity/parsing/Parser.h20
9 files changed, 99 insertions, 98 deletions
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index a53987bf..fa0d6921 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -146,6 +146,7 @@ private:
class Scopable
{
public:
+ virtual ~Scopable() = default;
/// @returns the scope this declaration resides in. Can be nullptr if it is the global scope.
/// Available only after name and type resolution step.
ASTNode const* scope() const { return m_scope; }
@@ -307,6 +308,7 @@ private:
class VariableScope
{
public:
+ virtual ~VariableScope() = default;
void addLocalVariable(VariableDeclaration const& _localVariable) { m_localVariables.push_back(&_localVariable); }
std::vector<VariableDeclaration const*> const& localVariables() const { return m_localVariables; }
@@ -320,6 +322,7 @@ private:
class Documented
{
public:
+ virtual ~Documented() = default;
explicit Documented(ASTPointer<ASTString> const& _documentation): m_documentation(_documentation) {}
/// @return A shared pointer of an ASTString.
@@ -336,6 +339,7 @@ protected:
class ImplementationOptional
{
public:
+ virtual ~ImplementationOptional() = default;
explicit ImplementationOptional(bool _implemented): m_implemented(_implemented) {}
/// @return whether this node is fully implemented or not
diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h
index b1389f0f..6c0ce6f8 100644
--- a/libsolidity/ast/ASTVisitor.h
+++ b/libsolidity/ast/ASTVisitor.h
@@ -43,6 +43,7 @@ namespace solidity
class ASTVisitor
{
public:
+ virtual ~ASTVisitor() = default;
virtual bool visit(SourceUnit& _node) { return visitNode(_node); }
virtual bool visit(PragmaDirective& _node) { return visitNode(_node); }
virtual bool visit(ImportDirective& _node) { return visitNode(_node); }
@@ -147,6 +148,7 @@ protected:
class ASTConstVisitor
{
public:
+ virtual ~ASTConstVisitor() = default;
virtual bool visit(SourceUnit const& _node) { return visitNode(_node); }
virtual bool visit(PragmaDirective const& _node) { return visitNode(_node); }
virtual bool visit(ImportDirective const& _node) { return visitNode(_node); }
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 425e5045..11d7160c 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -627,8 +627,7 @@ bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
bool FixedPointType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo.category() == category() ||
- _convertTo.category() == Category::Integer ||
- _convertTo.category() == Category::FixedBytes;
+ (_convertTo.category() == Category::Integer && !dynamic_cast<IntegerType const&>(_convertTo).isAddress());
}
TypePointer FixedPointType::unaryOperatorResult(Token::Value _operator) const
@@ -682,13 +681,7 @@ bigint FixedPointType::minIntegerValue() const
TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
{
- if (
- _other->category() != Category::RationalNumber &&
- _other->category() != category() &&
- _other->category() != Category::Integer
- )
- return TypePointer();
- auto commonType = Type::commonType(shared_from_this(), _other); //might be fixed point or integer
+ auto commonType = Type::commonType(shared_from_this(), _other);
if (!commonType)
return TypePointer();
@@ -696,19 +689,16 @@ TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePoi
// All fixed types can be compared
if (Token::isCompareOp(_operator))
return commonType;
- if (Token::isBitOp(_operator) || Token::isBooleanOp(_operator))
+ if (Token::isBitOp(_operator) || Token::isBooleanOp(_operator) || _operator == Token::Exp)
return TypePointer();
- if (auto fixType = dynamic_pointer_cast<FixedPointType const>(commonType))
- {
- if (Token::Exp == _operator)
- return TypePointer();
- }
- else if (auto intType = dynamic_pointer_cast<IntegerType const>(commonType))
- if (intType->isAddress())
- return TypePointer();
return commonType;
}
+std::shared_ptr<IntegerType> FixedPointType::asIntegerType() const
+{
+ return std::make_shared<IntegerType>(numBits(), isSigned() ? IntegerType::Modifier::Signed : IntegerType::Modifier::Unsigned);
+}
+
tuple<bool, rational> RationalNumberType::parseRational(string const& _value)
{
rational value;
@@ -1148,7 +1138,7 @@ u256 RationalNumberType::literalValue(Literal const*) const
auto fixed = fixedPointType();
solAssert(fixed, "");
int fractionalDigits = fixed->fractionalDigits();
- shiftedValue = (m_value.numerator() / m_value.denominator()) * pow(bigint(10), fractionalDigits);
+ shiftedValue = m_value.numerator() * pow(bigint(10), fractionalDigits) / m_value.denominator();
}
// we ignore the literal and hope that the type was correctly determined
@@ -1274,17 +1264,12 @@ bool StringLiteralType::isValidUTF8() const
return dev::validateUTF8(m_value);
}
-shared_ptr<FixedBytesType> FixedBytesType::smallestTypeForLiteral(string const& _literal)
-{
- if (_literal.length() <= 32)
- return make_shared<FixedBytesType>(_literal.length());
- return shared_ptr<FixedBytesType>();
-}
-
FixedBytesType::FixedBytesType(int _bytes): m_bytes(_bytes)
{
- solAssert(m_bytes >= 0 && m_bytes <= 32,
- "Invalid byte number for fixed bytes type: " + dev::toString(m_bytes));
+ solAssert(
+ m_bytes > 0 && m_bytes <= 32,
+ "Invalid byte number for fixed bytes type: " + dev::toString(m_bytes)
+ );
}
bool FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 345f84a1..ca6822c9 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -138,6 +138,7 @@ private:
class Type: private boost::noncopyable, public std::enable_shared_from_this<Type>
{
public:
+ virtual ~Type() = default;
enum class Category
{
Integer, RationalNumber, StringLiteral, Bool, FixedPoint, Array,
@@ -396,6 +397,9 @@ public:
/// smallest value in general.
bigint minIntegerValue() const;
+ /// @returns the smallest integer type that can hold this type with fractional parts shifted to integers.
+ std::shared_ptr<IntegerType> asIntegerType() const;
+
private:
int m_totalBits;
int m_fractionalDigits;
@@ -502,10 +506,6 @@ class FixedBytesType: public Type
public:
virtual Category category() const override { return Category::FixedBytes; }
- /// @returns the smallest bytes type for the given literal or an empty pointer
- /// if no type fits.
- static std::shared_ptr<FixedBytesType> smallestTypeForLiteral(std::string const& _literal);
-
explicit FixedBytesType(int _bytes);
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h
index f8b68362..c576f9de 100644
--- a/libsolidity/codegen/LValue.h
+++ b/libsolidity/codegen/LValue.h
@@ -49,6 +49,7 @@ protected:
m_context(_compilerContext), m_dataType(_dataType) {}
public:
+ virtual ~LValue() {}
/// @returns the number of stack slots occupied by the lvalue reference
virtual unsigned sizeOnStack() const { return 1; }
/// Copies the value of the current lvalue to the top of the stack and, if @a _remove is true,
diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h
index e127bb55..16796684 100644
--- a/libsolidity/formal/SolverInterface.h
+++ b/libsolidity/formal/SolverInterface.h
@@ -193,6 +193,7 @@ DEV_SIMPLE_EXCEPTION(SolverError);
class SolverInterface
{
public:
+ virtual ~SolverInterface() = default;
virtual void reset() = 0;
virtual void push() = 0;
diff --git a/libsolidity/formal/SymbolicVariable.h b/libsolidity/formal/SymbolicVariable.h
index e4e4ea8d..e29ded26 100644
--- a/libsolidity/formal/SymbolicVariable.h
+++ b/libsolidity/formal/SymbolicVariable.h
@@ -40,6 +40,7 @@ public:
Declaration const& _decl,
smt::SolverInterface& _interface
);
+ virtual ~SymbolicVariable() = default;
smt::Expression operator()(int _seq) const
{
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 618a0896..a9ee9016 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -1057,16 +1057,16 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
if (m_scanner->currentToken() != Token::Identifier)
fatalParserError("Expected event name or path.");
- vector<ASTPointer<PrimaryExpression>> path;
+ IndexAccessedPath iap;
while (true)
{
- path.push_back(parseIdentifier());
+ iap.path.push_back(parseIdentifier());
if (m_scanner->currentToken() != Token::Period)
break;
m_scanner->next();
};
- auto eventName = expressionFromIndexAccessStructure(path, {});
+ auto eventName = expressionFromIndexAccessStructure(iap);
expectToken(Token::LParen);
vector<ASTPointer<Expression>> arguments;
@@ -1098,46 +1098,17 @@ ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const&
default:
break;
}
+
// At this point, we have 'Identifier "["' or 'Identifier "." Identifier' or 'ElementoryTypeName "["'.
- // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )+'
+ // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )*'
// until we can decide whether to hand this over to ExpressionStatement or create a
// VariableDeclarationStatement out of it.
- vector<ASTPointer<PrimaryExpression>> path;
- bool startedWithElementary = false;
- if (m_scanner->currentToken() == Token::Identifier)
- path.push_back(parseIdentifier());
- else
- {
- startedWithElementary = true;
- unsigned firstNum;
- unsigned secondNum;
- tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
- ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum);
- path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(elemToken));
- m_scanner->next();
- }
- while (!startedWithElementary && m_scanner->currentToken() == Token::Period)
- {
- m_scanner->next();
- path.push_back(parseIdentifier());
- }
- vector<pair<ASTPointer<Expression>, SourceLocation>> indices;
- while (m_scanner->currentToken() == Token::LBrack)
- {
- expectToken(Token::LBrack);
- ASTPointer<Expression> index;
- if (m_scanner->currentToken() != Token::RBrack)
- index = parseExpression();
- SourceLocation indexLocation = path.front()->location();
- indexLocation.end = endPosition();
- indices.push_back(make_pair(index, indexLocation));
- expectToken(Token::RBrack);
- }
+ IndexAccessedPath iap = parseIndexAccessedPath();
if (m_scanner->currentToken() == Token::Identifier || Token::isLocationSpecifier(m_scanner->currentToken()))
- return parseVariableDeclarationStatement(_docString, typeNameIndexAccessStructure(path, indices));
+ return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap));
else
- return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(path, indices));
+ return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap));
}
ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement(
@@ -1529,32 +1500,65 @@ Parser::LookAheadInfo Parser::peekStatementType() const
return LookAheadInfo::ExpressionStatement;
}
-ASTPointer<TypeName> Parser::typeNameIndexAccessStructure(
- vector<ASTPointer<PrimaryExpression>> const& _path,
- vector<pair<ASTPointer<Expression>, SourceLocation>> const& _indices
-)
+Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
+{
+ IndexAccessedPath iap;
+ if (m_scanner->currentToken() == Token::Identifier)
+ {
+ iap.path.push_back(parseIdentifier());
+ while (m_scanner->currentToken() == Token::Period)
+ {
+ m_scanner->next();
+ iap.path.push_back(parseIdentifier());
+ }
+ }
+ else
+ {
+ unsigned firstNum;
+ unsigned secondNum;
+ tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
+ ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum);
+ iap.path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(elemToken));
+ m_scanner->next();
+ }
+ while (m_scanner->currentToken() == Token::LBrack)
+ {
+ expectToken(Token::LBrack);
+ ASTPointer<Expression> index;
+ if (m_scanner->currentToken() != Token::RBrack)
+ index = parseExpression();
+ SourceLocation indexLocation = iap.path.front()->location();
+ indexLocation.end = endPosition();
+ iap.indices.push_back(make_pair(index, indexLocation));
+ expectToken(Token::RBrack);
+ }
+
+ return iap;
+}
+
+ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap)
{
- solAssert(!_path.empty(), "");
+ solAssert(!_iap.path.empty(), "");
RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this);
- SourceLocation location = _path.front()->location();
- location.end = _path.back()->location().end;
+ SourceLocation location = _iap.path.front()->location();
+ location.end = _iap.path.back()->location().end;
nodeFactory.setLocation(location);
ASTPointer<TypeName> type;
- if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_path.front().get()))
+ if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_iap.path.front().get()))
{
- solAssert(_path.size() == 1, "");
+ solAssert(_iap.path.size() == 1, "");
type = nodeFactory.createNode<ElementaryTypeName>(typeName->typeName());
}
else
{
vector<ASTString> path;
- for (auto const& el: _path)
+ for (auto const& el: _iap.path)
path.push_back(dynamic_cast<Identifier const&>(*el).name());
type = nodeFactory.createNode<UserDefinedTypeName>(path);
}
- for (auto const& lengthExpression: _indices)
+ for (auto const& lengthExpression: _iap.indices)
{
nodeFactory.setLocation(lengthExpression.second);
type = nodeFactory.createNode<ArrayTypeName>(type, lengthExpression.first);
@@ -1563,26 +1567,25 @@ ASTPointer<TypeName> Parser::typeNameIndexAccessStructure(
}
ASTPointer<Expression> Parser::expressionFromIndexAccessStructure(
- vector<ASTPointer<PrimaryExpression>> const& _path,
- vector<pair<ASTPointer<Expression>, SourceLocation>> const& _indices
+ Parser::IndexAccessedPath const& _iap
)
{
- solAssert(!_path.empty(), "");
+ solAssert(!_iap.path.empty(), "");
RecursionGuard recursionGuard(*this);
- ASTNodeFactory nodeFactory(*this, _path.front());
- ASTPointer<Expression> expression(_path.front());
- for (size_t i = 1; i < _path.size(); ++i)
+ ASTNodeFactory nodeFactory(*this, _iap.path.front());
+ ASTPointer<Expression> expression(_iap.path.front());
+ for (size_t i = 1; i < _iap.path.size(); ++i)
{
- SourceLocation location(_path.front()->location());
- location.end = _path[i]->location().end;
+ SourceLocation location(_iap.path.front()->location());
+ location.end = _iap.path[i]->location().end;
nodeFactory.setLocation(location);
- Identifier const& identifier = dynamic_cast<Identifier const&>(*_path[i]);
+ Identifier const& identifier = dynamic_cast<Identifier const&>(*_iap.path[i]);
expression = nodeFactory.createNode<MemberAccess>(
expression,
make_shared<ASTString>(identifier.name())
);
}
- for (auto const& index: _indices)
+ for (auto const& index: _iap.indices)
{
nodeFactory.setLocation(index.second);
expression = nodeFactory.createNode<IndexAccess>(expression, index.first);
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index eb120a61..c4254231 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -145,21 +145,25 @@ private:
{
IndexAccessStructure, VariableDeclarationStatement, ExpressionStatement
};
+ /// Structure that represents a.b.c[x][y][z]. Can be converted either to an expression
+ /// or to a type name. Path cannot be empty, but indices can be empty.
+ struct IndexAccessedPath
+ {
+ std::vector<ASTPointer<PrimaryExpression>> path;
+ std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> indices;
+ };
/// Performs limited look-ahead to distinguish between variable declaration and expression statement.
/// For source code of the form "a[][8]" ("IndexAccessStructure"), this is not possible to
/// decide with constant look-ahead.
LookAheadInfo peekStatementType() const;
+ /// @returns an IndexAccessedPath as a prestage to parsing a variable declaration (type name)
+ /// or an expression;
+ IndexAccessedPath parseIndexAccessedPath();
/// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]".
- ASTPointer<TypeName> typeNameIndexAccessStructure(
- std::vector<ASTPointer<PrimaryExpression>> const& _path,
- std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
- );
+ ASTPointer<TypeName> typeNameFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices);
/// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]".
- ASTPointer<Expression> expressionFromIndexAccessStructure(
- std::vector<ASTPointer<PrimaryExpression>> const& _path,
- std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
- );
+ ASTPointer<Expression> expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices);
std::string currentTokenName();
Token::Value expectAssignmentOperator();