From 3da2b67b674f20a59a22e80e399c7d215011b50c Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 30 Jul 2020 12:12:55 +0100 Subject: [PATCH 1/9] simplify parser --- libyul/AsmParser.cpp | 33 +++++++------------ .../invalid/bare_instructions_disallowed.sol | 2 +- .../invalid/unbalanced_negative_stack.sol | 2 +- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 00cdb4a22..19d0ced20 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -265,10 +265,12 @@ Expression Parser::parseExpression() RecursionGuard recursionGuard(*this); ElementaryOperation operation = parseElementaryOperation(); - if (holds_alternative(operation) || currentToken() == Token::LParen) - return parseCall(std::move(operation)); - else if (holds_alternative(operation)) + if (holds_alternative(operation)) + { + if (currentToken() == Token::LParen) + return parseCall(std::move(operation)); return std::get(operation); + } else { yulAssert(holds_alternative(operation), ""); @@ -284,16 +286,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() { case Token::Identifier: { - YulString literal{currentLiteral()}; - if (m_dialect.builtin(literal)) - { - Identifier identifier{currentLocation(), literal}; - advance(); - expectToken(Token::LParen, false); - return FunctionCall{identifier.location, identifier, {}}; - } - else - ret = Identifier{currentLocation(), literal}; + ret = Identifier{currentLocation(), YulString{currentLiteral()}}; advance(); break; } @@ -422,17 +415,13 @@ Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) { RecursionGuard recursionGuard(*this); - FunctionCall ret; - if (holds_alternative(_initialOp)) - { - ret.functionName = std::move(std::get(_initialOp)); - ret.location = ret.functionName.location; - } - else if (holds_alternative(_initialOp)) - ret = std::move(std::get(_initialOp)); - else + if (!holds_alternative(_initialOp)) fatalParserError(9980_error, "Function name expected."); + FunctionCall ret; + ret.functionName = std::move(std::get(_initialOp)); + ret.location = ret.functionName.location; + expectToken(Token::LParen); if (currentToken() != Token::RParen) { diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol index a55586af9..87884efee 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// ParserError 2314: (95-98): Expected '(' but got identifier +// ParserError 6913: (95-98): Call or assignment expected. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol index 3f92beec2..80dd3a587 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol @@ -6,4 +6,4 @@ contract test { } } // ---- -// ParserError 2314: (85-86): Expected '(' but got '}' +// ParserError 6913: (85-86): Call or assignment expected. From 75e00573884677b6854a6aea1e4c006978f54f1e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 30 Jul 2020 12:20:15 +0100 Subject: [PATCH 2/9] Rename parseElementaryOperation to parseLiteralOrIdentifier --- libyul/AsmParser.cpp | 16 ++++++++-------- libyul/AsmParser.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 19d0ced20..94dff259d 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -138,11 +138,11 @@ Statement Parser::parseStatement() default: break; } + // Options left: - // Simple instruction (might turn into functional), - // literal, - // identifier (might turn into label or functional assignment) - ElementaryOperation elementary(parseElementaryOperation()); + // Expression/FunctionCall + // Assignment + ElementaryOperation elementary(parseLiteralOrIdentifier()); switch (currentToken()) { @@ -184,7 +184,7 @@ Statement Parser::parseStatement() expectToken(Token::Comma); - elementary = parseElementaryOperation(); + elementary = parseLiteralOrIdentifier(); } expectToken(Token::AssemblyAssign); @@ -225,7 +225,7 @@ Case Parser::parseCase() else if (currentToken() == Token::Case) { advance(); - ElementaryOperation literal = parseElementaryOperation(); + ElementaryOperation literal = parseLiteralOrIdentifier(); if (!holds_alternative(literal)) fatalParserError(4805_error, "Literal expected."); _case.value = make_unique(std::get(std::move(literal))); @@ -264,7 +264,7 @@ Expression Parser::parseExpression() { RecursionGuard recursionGuard(*this); - ElementaryOperation operation = parseElementaryOperation(); + ElementaryOperation operation = parseLiteralOrIdentifier(); if (holds_alternative(operation)) { if (currentToken() == Token::LParen) @@ -278,7 +278,7 @@ Expression Parser::parseExpression() } } -Parser::ElementaryOperation Parser::parseElementaryOperation() +Parser::ElementaryOperation Parser::parseLiteralOrIdentifier() { RecursionGuard recursionGuard(*this); ElementaryOperation ret; diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 705711b52..2720e9760 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -84,7 +84,7 @@ protected: Expression parseExpression(); /// Parses an elementary operation, i.e. a literal, identifier, instruction or /// builtin functian call (only the name). - ElementaryOperation parseElementaryOperation(); + ElementaryOperation parseLiteralOrIdentifier(); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); Expression parseCall(ElementaryOperation&& _initialOp); From baa7251f1d2600b7fe1c94026342b0a283368145 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 31 Aug 2020 15:29:12 +0100 Subject: [PATCH 3/9] More clean up --- libyul/AsmParser.cpp | 12 ++++++------ libyul/AsmParser.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 94dff259d..58babaaac 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -149,7 +149,7 @@ Statement Parser::parseStatement() case Token::LParen: { Expression expr = parseCall(std::move(elementary)); - return ExpressionStatement{locationOf(expr), expr}; + return ExpressionStatement{locationOf(expr), move(expr)}; } case Token::Comma: case Token::AssemblyAssign: @@ -192,7 +192,7 @@ Statement Parser::parseStatement() assignment.value = make_unique(parseExpression()); assignment.location.end = locationOf(*assignment.value).end; - return Statement{std::move(assignment)}; + return Statement{move(assignment)}; } default: fatalParserError(6913_error, "Call or assignment expected."); @@ -201,13 +201,13 @@ Statement Parser::parseStatement() if (holds_alternative(elementary)) { - Identifier& identifier = std::get(elementary); + Identifier identifier = std::get(move(elementary)); return ExpressionStatement{identifier.location, { move(identifier) }}; } else if (holds_alternative(elementary)) { - Expression expr = std::get(elementary); - return ExpressionStatement{locationOf(expr), expr}; + Literal literal = std::get(move(elementary)); + return ExpressionStatement{literal.location, { move(literal) }}; } else { @@ -411,7 +411,7 @@ FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) +FunctionCall Parser::parseCall(Parser::ElementaryOperation&& _initialOp) { RecursionGuard recursionGuard(*this); diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 2720e9760..2dcbcd191 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -87,7 +87,7 @@ protected: ElementaryOperation parseLiteralOrIdentifier(); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); - Expression parseCall(ElementaryOperation&& _initialOp); + FunctionCall parseCall(ElementaryOperation&& _initialOp); TypedName parseTypedName(); YulString expectAsmIdentifier(); From 43353bb6cae0e8915160a478bf993f5e028cb355 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 4 Nov 2020 16:55:03 +0000 Subject: [PATCH 4/9] update tests --- scripts/error_codes.py | 2 +- .../syntaxTests/inlineAssembly/assignment_from_opcode_like.sol | 2 +- .../syntaxTests/inlineAssembly/assignment_to_opcode_like.sol | 2 +- test/libyul/yulSyntaxTests/builtin_identifier_3.yul | 2 +- test/libyul/yulSyntaxTests/builtin_identifier_6.yul | 3 +-- test/libyul/yulSyntaxTests/builtin_identifier_7.yul | 3 +-- test/libyul/yulSyntaxTests/for_expr_invalid_5.yul | 3 ++- test/libyul/yulSyntaxTests/functional_partial.yul | 2 +- test/libyul/yulSyntaxTests/if_statement_invalid_1.yul | 3 ++- test/libyul/yulSyntaxTests/if_statement_invalid_4.yul | 3 ++- test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul | 2 +- 11 files changed, 14 insertions(+), 13 deletions(-) diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 23c1657a7..9b106d0c0 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -223,7 +223,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "1123", "1220", "1584", "1823", "1988", "2657", "2800", "3356", "3893", "3996", "4010", "4802", - "5073", "5272", "5622", "6272", "7128", + "5073", "5272", "5622", "7128", "7589", "7593", "7653", "8065", "8084", "8140", "8312", "8592", "9085", "9390" } diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol index 3296252ea..e9d6f1983 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// ParserError 2314: (118-119): Expected '(' but got '}' +// Warning 8261: (52-62): Variable is shadowed in inline assembly by an instruction of the same name diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_opcode_like.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_opcode_like.sol index 7a783b9fe..51028e50c 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_opcode_like.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_opcode_like.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// ParserError 2314: (101-103): Expected '(' but got ':=' +// ParserError 6272: (101-103): Cannot assign to builtin function "mload". diff --git a/test/libyul/yulSyntaxTests/builtin_identifier_3.yul b/test/libyul/yulSyntaxTests/builtin_identifier_3.yul index 283d64b49..ece40e793 100644 --- a/test/libyul/yulSyntaxTests/builtin_identifier_3.yul +++ b/test/libyul/yulSyntaxTests/builtin_identifier_3.yul @@ -2,4 +2,4 @@ function f(x) { f(add) } } // ---- -// ParserError 2314: (24-25): Expected '(' but got ')' +// DeclarationError 8198: (21-24): Identifier not found. diff --git a/test/libyul/yulSyntaxTests/builtin_identifier_6.yul b/test/libyul/yulSyntaxTests/builtin_identifier_6.yul index 8f3395d79..e261354fc 100644 --- a/test/libyul/yulSyntaxTests/builtin_identifier_6.yul +++ b/test/libyul/yulSyntaxTests/builtin_identifier_6.yul @@ -1,6 +1,5 @@ { - // Test for the unreachable 6272_error add := 1 } // ---- -// ParserError 2314: (47-49): Expected '(' but got ':=' +// ParserError 6272: (7-9): Cannot assign to builtin function "add". diff --git a/test/libyul/yulSyntaxTests/builtin_identifier_7.yul b/test/libyul/yulSyntaxTests/builtin_identifier_7.yul index 391b190d9..c34da0363 100644 --- a/test/libyul/yulSyntaxTests/builtin_identifier_7.yul +++ b/test/libyul/yulSyntaxTests/builtin_identifier_7.yul @@ -1,7 +1,6 @@ { - // Test for the unreachable 6272_error function f() -> a, b {} add, mul := f() } // ---- -// ParserError 2314: (71-72): Expected '(' but got ',' +// ParserError 6272: (31-32): Cannot assign to builtin function "add". diff --git a/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul b/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul index acf9be847..7f89fb3f4 100644 --- a/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul +++ b/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul @@ -2,4 +2,5 @@ for {} mload {} {} } // ---- -// ParserError 2314: (16-17): Expected '(' but got '{' +// DeclarationError 8198: (10-15): Identifier not found. +// TypeError 1733: (10-15): Expected a value of boolean type "bool" but got "u256" diff --git a/test/libyul/yulSyntaxTests/functional_partial.yul b/test/libyul/yulSyntaxTests/functional_partial.yul index f66225658..5f65cb13f 100644 --- a/test/libyul/yulSyntaxTests/functional_partial.yul +++ b/test/libyul/yulSyntaxTests/functional_partial.yul @@ -2,4 +2,4 @@ let x := byte } // ---- -// ParserError 2314: (20-21): Expected '(' but got '}' +// DeclarationError 8198: (15-19): Identifier not found. diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul index 5f73fcf2a..8d40479cd 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul @@ -2,4 +2,5 @@ if mload {} } // ---- -// ParserError 2314: (15-16): Expected '(' but got '{' +// DeclarationError 8198: (9-14): Identifier not found. +// TypeError 1733: (9-14): Expected a value of boolean type "bool" but got "u256" diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul index ed9deeda6..546537203 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul @@ -2,4 +2,5 @@ if calldatasize {} } // ---- -// ParserError 2314: (22-23): Expected '(' but got '{' +// DeclarationError 8198: (9-21): Identifier not found. +// TypeError 1733: (9-21): Expected a value of boolean type "bool" but got "u256" diff --git a/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul b/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul index 842fa02f3..905b9ed1f 100644 --- a/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul +++ b/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul @@ -4,4 +4,4 @@ default {} } // ---- -// ParserError 2314: (23-27): Expected '(' but got reserved keyword 'case' +// DeclarationError 8198: (13-18): Identifier not found. From e2a756a705789e7601cc57ddd45c6f4e9ff727c6 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 5 Nov 2020 01:25:53 +0000 Subject: [PATCH 5/9] Remove dead code --- libyul/AsmParser.cpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 58babaaac..e19f5b8ce 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -199,21 +199,8 @@ Statement Parser::parseStatement() break; } - if (holds_alternative(elementary)) - { - Identifier identifier = std::get(move(elementary)); - return ExpressionStatement{identifier.location, { move(identifier) }}; - } - else if (holds_alternative(elementary)) - { - Literal literal = std::get(move(elementary)); - return ExpressionStatement{literal.location, { move(literal) }}; - } - else - { - yulAssert(false, "Invalid elementary operation."); - return {}; - } + yulAssert(false, ""); + return {}; } Case Parser::parseCase() From 6c0a3bd0430fb0ddb1f1742931274c4f9d5950f6 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 5 Nov 2020 01:38:57 +0000 Subject: [PATCH 6/9] Ensure that builtins must be executed --- libyul/AsmParser.cpp | 2 ++ .../syntaxTests/inlineAssembly/assignment_from_opcode_like.sol | 2 +- test/libyul/yulSyntaxTests/builtin_identifier_3.yul | 2 +- test/libyul/yulSyntaxTests/for_expr_invalid_5.yul | 3 +-- test/libyul/yulSyntaxTests/functional_partial.yul | 2 +- test/libyul/yulSyntaxTests/if_statement_invalid_1.yul | 3 +-- test/libyul/yulSyntaxTests/if_statement_invalid_4.yul | 3 +-- test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul | 2 +- 8 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index e19f5b8ce..4dcc6b19a 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -256,6 +256,8 @@ Expression Parser::parseExpression() { if (currentToken() == Token::LParen) return parseCall(std::move(operation)); + else if (auto const& name = std::get(operation).name; m_dialect.builtin(name)) + fatalParserError(7104_error, "Builtin function \"" + name.str() + "\" must be called."); return std::get(operation); } else diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol index e9d6f1983..306604931 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// Warning 8261: (52-62): Variable is shadowed in inline assembly by an instruction of the same name +// ParserError 7104: (118-119): Builtin function "mload" must be called. diff --git a/test/libyul/yulSyntaxTests/builtin_identifier_3.yul b/test/libyul/yulSyntaxTests/builtin_identifier_3.yul index ece40e793..04236a8ba 100644 --- a/test/libyul/yulSyntaxTests/builtin_identifier_3.yul +++ b/test/libyul/yulSyntaxTests/builtin_identifier_3.yul @@ -2,4 +2,4 @@ function f(x) { f(add) } } // ---- -// DeclarationError 8198: (21-24): Identifier not found. +// ParserError 7104: (24-25): Builtin function "add" must be called. diff --git a/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul b/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul index 7f89fb3f4..44d8ad7c1 100644 --- a/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul +++ b/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul @@ -2,5 +2,4 @@ for {} mload {} {} } // ---- -// DeclarationError 8198: (10-15): Identifier not found. -// TypeError 1733: (10-15): Expected a value of boolean type "bool" but got "u256" +// ParserError 7104: (16-17): Builtin function "mload" must be called. diff --git a/test/libyul/yulSyntaxTests/functional_partial.yul b/test/libyul/yulSyntaxTests/functional_partial.yul index 5f65cb13f..1bf1c64d6 100644 --- a/test/libyul/yulSyntaxTests/functional_partial.yul +++ b/test/libyul/yulSyntaxTests/functional_partial.yul @@ -2,4 +2,4 @@ let x := byte } // ---- -// DeclarationError 8198: (15-19): Identifier not found. +// ParserError 7104: (20-21): Builtin function "byte" must be called. diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul index 8d40479cd..ef5e5e4da 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul @@ -2,5 +2,4 @@ if mload {} } // ---- -// DeclarationError 8198: (9-14): Identifier not found. -// TypeError 1733: (9-14): Expected a value of boolean type "bool" but got "u256" +// ParserError 7104: (15-16): Builtin function "mload" must be called. diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul index 546537203..757eab328 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul @@ -2,5 +2,4 @@ if calldatasize {} } // ---- -// DeclarationError 8198: (9-21): Identifier not found. -// TypeError 1733: (9-21): Expected a value of boolean type "bool" but got "u256" +// ParserError 7104: (22-23): Builtin function "calldatasize" must be called. diff --git a/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul b/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul index 905b9ed1f..0886db409 100644 --- a/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul +++ b/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul @@ -4,4 +4,4 @@ default {} } // ---- -// DeclarationError 8198: (13-18): Identifier not found. +// ParserError 7104: (23-27): Builtin function "mload" must be called. From 61ed1f19864e48cf092417c3db903cc41a832472 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 5 Nov 2020 11:57:01 +0000 Subject: [PATCH 7/9] cleanup --- libyul/AsmParser.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 4dcc6b19a..e1bcabaf2 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -256,9 +256,14 @@ Expression Parser::parseExpression() { if (currentToken() == Token::LParen) return parseCall(std::move(operation)); - else if (auto const& name = std::get(operation).name; m_dialect.builtin(name)) - fatalParserError(7104_error, "Builtin function \"" + name.str() + "\" must be called."); - return std::get(operation); + auto identifier = std::get(operation); + if (m_dialect.builtin(identifier.name)) + fatalParserError( + 7104_error, + identifier.location, + "Builtin function \"" + identifier.name.str() + "\" must be called." + ); + return identifier; } else { From a9be2e4bb8952011bab8bd6bc5382057e500f6ba Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 9 Nov 2020 23:38:08 +0000 Subject: [PATCH 8/9] update tests --- .../syntaxTests/inlineAssembly/assignment_from_opcode_like.sol | 2 +- test/libyul/yulSyntaxTests/builtin_identifier_3.yul | 2 +- test/libyul/yulSyntaxTests/for_expr_invalid_5.yul | 2 +- test/libyul/yulSyntaxTests/functional_partial.yul | 2 +- test/libyul/yulSyntaxTests/if_statement_invalid_1.yul | 2 +- test/libyul/yulSyntaxTests/if_statement_invalid_4.yul | 2 +- test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol index 306604931..cb675ab29 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// ParserError 7104: (118-119): Builtin function "mload" must be called. +// ParserError 7104: (104-109): Builtin function "mload" must be called. diff --git a/test/libyul/yulSyntaxTests/builtin_identifier_3.yul b/test/libyul/yulSyntaxTests/builtin_identifier_3.yul index 04236a8ba..c7969b8ef 100644 --- a/test/libyul/yulSyntaxTests/builtin_identifier_3.yul +++ b/test/libyul/yulSyntaxTests/builtin_identifier_3.yul @@ -2,4 +2,4 @@ function f(x) { f(add) } } // ---- -// ParserError 7104: (24-25): Builtin function "add" must be called. +// ParserError 7104: (21-24): Builtin function "add" must be called. diff --git a/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul b/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul index 44d8ad7c1..5d739e81e 100644 --- a/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul +++ b/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul @@ -2,4 +2,4 @@ for {} mload {} {} } // ---- -// ParserError 7104: (16-17): Builtin function "mload" must be called. +// ParserError 7104: (10-15): Builtin function "mload" must be called. diff --git a/test/libyul/yulSyntaxTests/functional_partial.yul b/test/libyul/yulSyntaxTests/functional_partial.yul index 1bf1c64d6..ea28283d4 100644 --- a/test/libyul/yulSyntaxTests/functional_partial.yul +++ b/test/libyul/yulSyntaxTests/functional_partial.yul @@ -2,4 +2,4 @@ let x := byte } // ---- -// ParserError 7104: (20-21): Builtin function "byte" must be called. +// ParserError 7104: (15-19): Builtin function "byte" must be called. diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul index ef5e5e4da..0a4f33844 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul @@ -2,4 +2,4 @@ if mload {} } // ---- -// ParserError 7104: (15-16): Builtin function "mload" must be called. +// ParserError 7104: (9-14): Builtin function "mload" must be called. diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul index 757eab328..b84004a8d 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul @@ -2,4 +2,4 @@ if calldatasize {} } // ---- -// ParserError 7104: (22-23): Builtin function "calldatasize" must be called. +// ParserError 7104: (9-21): Builtin function "calldatasize" must be called. diff --git a/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul b/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul index 0886db409..9378297ca 100644 --- a/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul +++ b/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul @@ -4,4 +4,4 @@ default {} } // ---- -// ParserError 7104: (23-27): Builtin function "mload" must be called. +// ParserError 7104: (13-18): Builtin function "mload" must be called. From 5071709b2593cf9f7b15e1f8f3b84b2a5a6388ca Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 3 Dec 2020 17:44:11 +0100 Subject: [PATCH 9/9] Remove FunctionCall from ElementaryOperation. --- libyul/AsmParser.cpp | 57 ++++++++++++++++++++++---------------------- libyul/AsmParser.h | 6 ++--- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index e1bcabaf2..c43066ee0 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -142,7 +143,7 @@ Statement Parser::parseStatement() // Options left: // Expression/FunctionCall // Assignment - ElementaryOperation elementary(parseLiteralOrIdentifier()); + variant elementary(parseLiteralOrIdentifier()); switch (currentToken()) { @@ -212,7 +213,7 @@ Case Parser::parseCase() else if (currentToken() == Token::Case) { advance(); - ElementaryOperation literal = parseLiteralOrIdentifier(); + variant literal = parseLiteralOrIdentifier(); if (!holds_alternative(literal)) fatalParserError(4805_error, "Literal expected."); _case.value = make_unique(std::get(std::move(literal))); @@ -251,38 +252,37 @@ Expression Parser::parseExpression() { RecursionGuard recursionGuard(*this); - ElementaryOperation operation = parseLiteralOrIdentifier(); - if (holds_alternative(operation)) - { - if (currentToken() == Token::LParen) - return parseCall(std::move(operation)); - auto identifier = std::get(operation); - if (m_dialect.builtin(identifier.name)) - fatalParserError( - 7104_error, - identifier.location, - "Builtin function \"" + identifier.name.str() + "\" must be called." - ); - return identifier; - } - else - { - yulAssert(holds_alternative(operation), ""); - return std::get(operation); - } + variant operation = parseLiteralOrIdentifier(); + return visit(GenericVisitor{ + [&](Identifier& _identifier) -> Expression + { + if (currentToken() == Token::LParen) + return parseCall(std::move(operation)); + if (m_dialect.builtin(_identifier.name)) + fatalParserError( + 7104_error, + _identifier.location, + "Builtin function \"" + _identifier.name.str() + "\" must be called." + ); + return move(_identifier); + }, + [&](Literal& _literal) -> Expression + { + return move(_literal); + } + }, operation); } -Parser::ElementaryOperation Parser::parseLiteralOrIdentifier() +variant Parser::parseLiteralOrIdentifier() { RecursionGuard recursionGuard(*this); - ElementaryOperation ret; switch (currentToken()) { case Token::Identifier: { - ret = Identifier{currentLocation(), YulString{currentLiteral()}}; + Identifier identifier{currentLocation(), YulString{currentLiteral()}}; advance(); - break; + return identifier; } case Token::StringLiteral: case Token::Number: @@ -322,8 +322,7 @@ Parser::ElementaryOperation Parser::parseLiteralOrIdentifier() literal.type = expectAsmIdentifier(); } - ret = std::move(literal); - break; + return literal; } case Token::HexStringLiteral: fatalParserError(3772_error, "Hex literals are not valid in this context."); @@ -331,7 +330,7 @@ Parser::ElementaryOperation Parser::parseLiteralOrIdentifier() default: fatalParserError(1856_error, "Literal or identifier expected."); } - return ret; + return {}; } VariableDeclaration Parser::parseVariableDeclaration() @@ -405,7 +404,7 @@ FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -FunctionCall Parser::parseCall(Parser::ElementaryOperation&& _initialOp) +FunctionCall Parser::parseCall(variant&& _initialOp) { RecursionGuard recursionGuard(*this); diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 2dcbcd191..d1294b111 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -61,8 +61,6 @@ public: std::unique_ptr parse(std::shared_ptr const& _scanner, bool _reuseScanner); protected: - using ElementaryOperation = std::variant; - langutil::SourceLocation currentLocation() const override { return m_locationOverride ? *m_locationOverride : ParserBase::currentLocation(); @@ -84,10 +82,10 @@ protected: Expression parseExpression(); /// Parses an elementary operation, i.e. a literal, identifier, instruction or /// builtin functian call (only the name). - ElementaryOperation parseLiteralOrIdentifier(); + std::variant parseLiteralOrIdentifier(); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); - FunctionCall parseCall(ElementaryOperation&& _initialOp); + FunctionCall parseCall(std::variant&& _initialOp); TypedName parseTypedName(); YulString expectAsmIdentifier();