diff --git a/Changelog.md b/Changelog.md index 62536e8bf..3fa7c9dec 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: + * Yul: Properly detect name clashes with functions before their declaration. Build System: diff --git a/libyul/AsmScopeFiller.cpp b/libyul/AsmScopeFiller.cpp index ee797d6a8..e9461473b 100644 --- a/libyul/AsmScopeFiller.cpp +++ b/libyul/AsmScopeFiller.cpp @@ -150,9 +150,16 @@ bool ScopeFiller::operator()(Block const& _block) scope(&_block).superScope = m_currentScope; m_currentScope = &scope(&_block); + // First visit all functions to make them create + // an entry in the scope according to their visibility. for (auto const& s: _block.statements) - if (!boost::apply_visitor(*this, s)) - success = false; + if (s.type() == typeid(FunctionDefinition)) + if (!boost::apply_visitor(*this, s)) + success = false; + for (auto const& s: _block.statements) + if (s.type() != typeid(FunctionDefinition)) + if (!boost::apply_visitor(*this, s)) + success = false; m_currentScope = m_currentScope->superScope; return success; diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 03e74befb..e4af58d39 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -428,7 +428,31 @@ BOOST_AUTO_TEST_CASE(opcode_for_function_args) BOOST_AUTO_TEST_CASE(name_clashes) { - CHECK_PARSE_ERROR("{ let g := 2 function g() { } }", DeclarationError, "Function name g already taken in this scope"); + CHECK_PARSE_ERROR("{ let g := 2 function g() { } }", DeclarationError, "Variable name g already taken in this scope"); +} + +BOOST_AUTO_TEST_CASE(name_clashes_function_subscope) +{ + CHECK_PARSE_ERROR("{ function g() { function g() {} } }", DeclarationError, "Function name g already taken in this scope"); +} + +BOOST_AUTO_TEST_CASE(name_clashes_function_subscope_reverse) +{ + CHECK_PARSE_ERROR("{ { function g() {} } function g() { } }", DeclarationError, "Function name g already taken in this scope"); +} + +BOOST_AUTO_TEST_CASE(name_clashes_function_variable_subscope) +{ + CHECK_PARSE_ERROR("{ function g() { let g := 0 } }", DeclarationError, "Variable name g already taken in this scope"); +} + +BOOST_AUTO_TEST_CASE(name_clashes_function_variable_subscope_reverse) +{ + CHECK_PARSE_ERROR("{ { let g := 0 } function g() { } }", DeclarationError, "Variable name g already taken in this scope"); +} +BOOST_AUTO_TEST_CASE(functions_in_parallel_scopes) +{ + BOOST_CHECK(successParse("{ { function g() {} } { function g() {} } }")); } BOOST_AUTO_TEST_CASE(variable_access_cross_functions)