diff --git a/Changelog.md b/Changelog.md index 727465660..9cbf4bb59 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: * AST: Export NatSpec comments above each statement as their documentation. + * Inline Assembly: Do not warn anymore about variables or functions being shadowed by EVM opcodes. * Optimizer: Simple inlining when jumping to small blocks that jump again after a few side-effect free opcodes. diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index e639ba5e1..03bf34f92 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -195,27 +195,6 @@ Declaration const* NameAndTypeResolver::pathFromCurrentScope(vector c return nullptr; } -void NameAndTypeResolver::warnVariablesNamedLikeInstructions() const -{ - for (auto const& instruction: evmasm::c_instructions) - { - string const instructionName{boost::algorithm::to_lower_copy(instruction.first)}; - auto declarations = nameFromCurrentScope(instructionName, true); - for (Declaration const* const declaration: declarations) - { - solAssert(!!declaration, ""); - if (dynamic_cast(declaration)) - // Don't warn the user for what the user did not. - continue; - m_errorReporter.warning( - 8261_error, - declaration->location(), - "Variable is shadowed in inline assembly by an instruction of the same name" - ); - } - } -} - void NameAndTypeResolver::warnHomonymDeclarations() const { DeclarationContainer::Homonyms homonyms; diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index da90c690b..6644e281f 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -92,9 +92,6 @@ public: /// @note Returns a null pointer if any component in the path was not unique or not found. Declaration const* pathFromCurrentScope(std::vector const& _path) const; - /// Generate and store warnings about variables that are named like instructions. - void warnVariablesNamedLikeInstructions() const; - /// Generate and store warnings about declarations with the same name. void warnHomonymDeclarations() const; diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 930534924..aaa9c6ef9 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -185,8 +185,6 @@ void ReferencesResolver::endVisit(IdentifierPath const& _path) bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) { - m_resolver.warnVariablesNamedLikeInstructions(); - m_yulAnnotation = &_inlineAssembly.annotation(); (*this)(_inlineAssembly.operations()); m_yulAnnotation = nullptr; diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index fb520227f..cf5a7b88d 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -379,58 +379,6 @@ BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma) BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file does not specify required compiler version!")); } -BOOST_AUTO_TEST_CASE(returndatasize_as_variable) -{ - char const* text = R"( - contract C { function f() public pure { uint returndatasize; returndatasize; assembly { pop(returndatasize()) }}} - )"; - vector> expectations(vector>{ - {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"} - }); - if (!solidity::test::CommonOptions::get().evmVersion().supportsReturndata()) - { - expectations.emplace_back(make_pair(Error::Type::TypeError, std::string("\"returndatasize\" instruction is only available for Byzantium-compatible VMs"))); - expectations.emplace_back(make_pair(Error::Type::TypeError, std::string("Expected expression to evaluate to one value, but got 0 values instead."))); - } - CHECK_ALLOW_MULTI(text, expectations); -} - -BOOST_AUTO_TEST_CASE(create2_as_variable) -{ - char const* text = R"( - contract c { function f() public { uint create2; create2; assembly { pop(create2(0, 0, 0, 0)) } }} - )"; - // This needs special treatment, because the message mentions the EVM version, - // so cannot be run via isoltest. - vector> expectations(vector>{ - {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"} - }); - if (!solidity::test::CommonOptions::get().evmVersion().hasCreate2()) - { - expectations.emplace_back(make_pair(Error::Type::TypeError, std::string("\"create2\" instruction is only available for Constantinople-compatible VMs"))); - expectations.emplace_back(make_pair(Error::Type::TypeError, std::string("Expected expression to evaluate to one value, but got 0 values instead."))); - } - CHECK_ALLOW_MULTI(text, expectations); -} - -BOOST_AUTO_TEST_CASE(extcodehash_as_variable) -{ - char const* text = R"( - contract c { function f() public view { uint extcodehash; extcodehash; assembly { pop(extcodehash(0)) } }} - )"; - // This needs special treatment, because the message mentions the EVM version, - // so cannot be run via isoltest. - vector> expectations(vector>{ - {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"} - }); - if (!solidity::test::CommonOptions::get().evmVersion().hasExtCodeHash()) - { - expectations.emplace_back(make_pair(Error::Type::TypeError, std::string("\"extcodehash\" instruction is only available for Constantinople-compatible VMs"))); - expectations.emplace_back(make_pair(Error::Type::TypeError, std::string("Expected expression to evaluate to one value, but got 0 values instead."))); - } - CHECK_ALLOW_MULTI(text, expectations); -} - BOOST_AUTO_TEST_CASE(getter_is_memory_type) { char const* text = R"( diff --git a/test/libsolidity/semanticTests/inlineAssembly/shadowing_local_function_opcode.sol b/test/libsolidity/semanticTests/inlineAssembly/shadowing_local_function_opcode.sol new file mode 100644 index 000000000..0354b2b34 --- /dev/null +++ b/test/libsolidity/semanticTests/inlineAssembly/shadowing_local_function_opcode.sol @@ -0,0 +1,13 @@ +contract C { + function add(uint, uint) public pure returns (uint) { return 7; } + function g() public pure returns (uint x, uint y) { + x = add(1, 2); + assembly { + y := add(1, 2) + } + } +} +// ==== +// compileViaYul: also +// ---- +// g() -> 7, 3 diff --git a/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol b/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol new file mode 100644 index 000000000..96a384c54 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol @@ -0,0 +1,9 @@ +contract c { + function f() public { + uint create2; create2; + assembly { pop(create2(0, 0, 0, 0)) } + } +} +// ==== +// EVMVersion: >=constantinople +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_pre_istanbul.sol b/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_pre_istanbul.sol new file mode 100644 index 000000000..50093c42a --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_pre_istanbul.sol @@ -0,0 +1,11 @@ +contract c { + function f() public { + uint create2; create2; + assembly { pop(create2(0, 0, 0, 0)) } + } +} +// ==== +// EVMVersion: =byzantium +// ---- +// TypeError 6166: (78-85): The "create2" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium"). +// TypeError 3950: (78-97): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol b/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol new file mode 100644 index 000000000..2cdd41444 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol @@ -0,0 +1,9 @@ +contract c { + function f() public view { + uint extcodehash; + extcodehash; + assembly { pop(extcodehash(0)) } + } +} +// ==== +// EVMVersion: >=constantinople diff --git a/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_pre_constantinople.sol b/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_pre_constantinople.sol new file mode 100644 index 000000000..62432b4dc --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_pre_constantinople.sol @@ -0,0 +1,12 @@ +contract c { + function f() public view { + uint extcodehash; + extcodehash; + assembly { pop(extcodehash(0)) } + } +} +// ==== +// EVMVersion: =byzantium +// ---- +// TypeError 7110: (93-104): The "extcodehash" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium"). +// TypeError 3950: (93-107): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_call_post_byzantium.sol.sol b/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_call_post_byzantium.sol.sol new file mode 100644 index 000000000..8368f81f2 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_call_post_byzantium.sol.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + uint returndatasize; + returndatasize; + assembly { + let x := returndatasize() + } + } +} +// ==== +// EVMVersion: >=byzantium \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_post_byzantium.sol b/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_post_byzantium.sol new file mode 100644 index 000000000..44a12aa06 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_post_byzantium.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + uint returndatasize; + returndatasize; + assembly { + returndatasize := 2 + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// ParserError 6272: (143-145): Cannot assign to builtin function "returndatasize". diff --git a/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_pre_byzantium.sol b/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_pre_byzantium.sol new file mode 100644 index 000000000..07bae8ac8 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_pre_byzantium.sol @@ -0,0 +1,6 @@ +contract C { function f() public pure { uint returndatasize; returndatasize; assembly { pop(returndatasize()) }}} +// ==== +// EVMVersion: =homestead +// ---- +// TypeError 4778: (92-106): The "returndatasize" instruction is only available for Byzantium-compatible VMs (you are currently compiling for "homestead"). +// TypeError 3950: (92-108): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_read_post_byzantium.sol.sol b/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_read_post_byzantium.sol.sol new file mode 100644 index 000000000..bd5ad50c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/returndatasize_as_variable_read_post_byzantium.sol.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + uint returndatasize; + returndatasize; + assembly { + let x := returndatasize + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// ParserError 7104: (137-151): Builtin function "returndatasize" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/global_function_by_opcode.sol b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/global_function_by_opcode.sol new file mode 100644 index 000000000..1af10c07c --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/global_function_by_opcode.sol @@ -0,0 +1,8 @@ +function mload() pure {} +contract C { + function g() public pure { + assembly { + } + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/local_function_by_opcode.sol b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/local_function_by_opcode.sol new file mode 100644 index 000000000..af433ea1e --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/local_function_by_opcode.sol @@ -0,0 +1,9 @@ +contract C { + function add(uint, uint) public pure returns (uint) { return 7; } + function g() public pure returns (uint x, uint y) { + x = add(1, 2); + assembly { + y := add(1, 2) + } + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/state_variable_by_opcode.sol b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/state_variable_by_opcode.sol new file mode 100644 index 000000000..2138f648f --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/state_variable_by_opcode.sol @@ -0,0 +1,8 @@ +contract C { + uint mload; + function g() public pure { + assembly { + } + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/variable_by_opcode.sol b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/variable_by_opcode.sol index a18abe90b..6c27750c8 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/variable_by_opcode.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/variable_by_opcode.sol @@ -9,6 +9,5 @@ contract C { } } // ---- -// Warning 8261: (109-119): Variable is shadowed in inline assembly by an instruction of the same name // Warning 2072: (52-62): Unused local variable. // Warning 2072: (109-119): Unused local variable.