From 3d97e9a77b6103639d9f9406b27241a41bed389b Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 24 Feb 2021 16:28:13 +0100 Subject: [PATCH] Properly parse address member. --- Changelog.md | 1 + libsolidity/parsing/Parser.cpp | 39 +++++++++++++------ libsolidity/parsing/Parser.h | 2 + .../functionTypes/address_member.sol | 12 ++++++ 4 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 test/libsolidity/semanticTests/functionTypes/address_member.sol diff --git a/Changelog.md b/Changelog.md index 049d8f22e..536837c71 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,7 @@ Bugfixes: * SMTChecker: Fix missing type constraints on block and transaction variables in the deployment phase. * AST: Added ``referencedDeclaration`` for enum members. * Code Generator: Fix internal error when functions are passed as parameters of other callables, when the function types can be implicitly converted, but not identical. + * Parser: Properly parse ``.address`` in some situations. * Type Checker: Make function-hash collision errors into fatal type errors. diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 623060f0b..6dc0dfa6b 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -961,6 +961,14 @@ ASTPointer Parser::parseIdentifier() return nodeFactory.createNode(expectIdentifierToken()); } +ASTPointer Parser::parseIdentifierOrAddress() +{ + RecursionGuard recursionGuard(*this); + ASTNodeFactory nodeFactory(*this); + nodeFactory.markEndPosition(); + return nodeFactory.createNode(expectIdentifierTokenOrAddress()); +} + ASTPointer Parser::parseUserDefinedTypeName() { ASTNodeFactory nodeFactory(*this); @@ -979,7 +987,7 @@ ASTPointer Parser::parseIdentifierPath() { m_scanner->next(); nodeFactory.markEndPosition(); - identifierPath.push_back(*expectIdentifierToken()); + identifierPath.push_back(*expectIdentifierTokenOrAddress()); } return nodeFactory.createNode(identifierPath); } @@ -1751,13 +1759,7 @@ ASTPointer Parser::parseLeftHandSideExpression( { m_scanner->next(); nodeFactory.markEndPosition(); - if (m_scanner->currentToken() == Token::Address) - { - expression = nodeFactory.createNode(expression, make_shared("address")); - m_scanner->next(); - } - else - expression = nodeFactory.createNode(expression, expectIdentifierToken()); + expression = nodeFactory.createNode(expression, expectIdentifierTokenOrAddress()); break; } case Token::LParen: @@ -2081,7 +2083,7 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath() while (m_scanner->currentToken() == Token::Period) { m_scanner->next(); - iap.path.push_back(parseIdentifier()); + iap.path.push_back(parseIdentifierOrAddress()); } } else @@ -2199,11 +2201,26 @@ ASTPointer Parser::createEmptyParameterList() ASTPointer Parser::expectIdentifierToken() { - // do not advance on success - expectToken(Token::Identifier, false); + expectToken(Token::Identifier, false /* do not advance */); return getLiteralAndAdvance(); } +ASTPointer Parser::expectIdentifierTokenOrAddress() +{ + ASTPointer result; + if (m_scanner->currentToken() == Token::Address) + { + result = make_shared("address"); + m_scanner->next(); + } + else + { + expectToken(Token::Identifier, false /* do not advance */); + result = getLiteralAndAdvance(); + } + return result; +} + ASTPointer Parser::getLiteralAndAdvance() { ASTPointer identifier = make_shared(m_scanner->currentLiteral()); diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 77152d38f..77d6cd17c 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -105,6 +105,7 @@ private: ASTPointer parseUsingDirective(); ASTPointer parseModifierInvocation(); ASTPointer parseIdentifier(); + ASTPointer parseIdentifierOrAddress(); ASTPointer parseUserDefinedTypeName(); ASTPointer parseIdentifierPath(); ASTPointer parseTypeNameSuffix(ASTPointer type, ASTNodeFactory& nodeFactory); @@ -201,6 +202,7 @@ private: ASTPointer expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); ASTPointer expectIdentifierToken(); + ASTPointer expectIdentifierTokenOrAddress(); ASTPointer getLiteralAndAdvance(); ///@} diff --git a/test/libsolidity/semanticTests/functionTypes/address_member.sol b/test/libsolidity/semanticTests/functionTypes/address_member.sol new file mode 100644 index 000000000..38b01db73 --- /dev/null +++ b/test/libsolidity/semanticTests/functionTypes/address_member.sol @@ -0,0 +1,12 @@ +contract C { + function f() public view returns (address a1, address a2) { + a1 = this.f.address; + this.f.address; + [this.f.address][0]; + a2 = [this.f.address][0]; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 90572315268751552425567948436632610904688605307, 90572315268751552425567948436632610904688605307