diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/ast/AST.h | 4 | ||||
-rw-r--r-- | libsolidity/ast/ASTVisitor.h | 2 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 41 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 8 | ||||
-rw-r--r-- | libsolidity/codegen/LValue.h | 1 | ||||
-rw-r--r-- | libsolidity/formal/SolverInterface.h | 1 | ||||
-rw-r--r-- | libsolidity/formal/SymbolicVariable.h | 1 | ||||
-rw-r--r-- | libsolidity/parsing/Parser.cpp | 119 | ||||
-rw-r--r-- | libsolidity/parsing/Parser.h | 20 |
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(); |