diff options
author | Alex Beregszaszi <alex@rtfs.hu> | 2018-02-04 21:07:55 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-04 21:07:55 +0800 |
commit | 32300ea3fff05b6fb6080ebc32588e8e66ccc400 (patch) | |
tree | 55b376652e34079f48632a3ef61396f244ad5d43 | |
parent | 07f8f96c94cd2a2602226dee2aa08597c1bd21d6 (diff) | |
parent | aef95180392fcff5f339655754535a34c8564599 (diff) | |
download | dexon-solidity-32300ea3fff05b6fb6080ebc32588e8e66ccc400.tar dexon-solidity-32300ea3fff05b6fb6080ebc32588e8e66ccc400.tar.gz dexon-solidity-32300ea3fff05b6fb6080ebc32588e8e66ccc400.tar.bz2 dexon-solidity-32300ea3fff05b6fb6080ebc32588e8e66ccc400.tar.lz dexon-solidity-32300ea3fff05b6fb6080ebc32588e8e66ccc400.tar.xz dexon-solidity-32300ea3fff05b6fb6080ebc32588e8e66ccc400.tar.zst dexon-solidity-32300ea3fff05b6fb6080ebc32588e8e66ccc400.zip |
Merge pull request #3360 from federicobond/nonfatal-reference-errors
Replace some fatal errors when resolving references with normal ones
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 33 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 67 |
3 files changed, 87 insertions, 14 deletions
diff --git a/Changelog.md b/Changelog.md index 3a1a23dc..34fbf682 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Features: * Code Generator: Prevent non-view functions in libraries from being called directly. * Commandline interface: Support strict mode of assembly with the ``--strict--assembly`` switch. + * Compiler now continues resolving references after the first error. * Limit the number of warnings raised for creating abstract contracts. * Inline Assembly: Issue warning for using jump labels (already existed for jump instructions). * Inline Assembly: Support some restricted tokens (return, byte, address) as identifiers in Julia mode. diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 540ffaf5..30b06615 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -47,7 +47,7 @@ bool ReferencesResolver::visit(Identifier const& _identifier) { auto declarations = m_resolver.nameFromCurrentScope(_identifier.name()); if (declarations.empty()) - fatalDeclarationError(_identifier.location(), "Undeclared identifier."); + declarationError(_identifier.location(), "Undeclared identifier."); else if (declarations.size() == 1) _identifier.annotation().referencedDeclaration = declarations.front(); else @@ -90,7 +90,10 @@ void ReferencesResolver::endVisit(UserDefinedTypeName const& _typeName) { Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath()); if (!declaration) - fatalDeclarationError(_typeName.location(), "Identifier not found or not unique."); + { + declarationError(_typeName.location(), "Identifier not found or not unique."); + return; + } _typeName.annotation().referencedDeclaration = declaration; @@ -101,7 +104,7 @@ void ReferencesResolver::endVisit(UserDefinedTypeName const& _typeName) else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration)) _typeName.annotation().type = make_shared<ContractType>(*contract); else - fatalTypeError(_typeName.location(), "Name has to refer to a struct, enum or contract."); + typeError(_typeName.location(), "Name has to refer to a struct, enum or contract."); } void ReferencesResolver::endVisit(FunctionTypeName const& _typeName) @@ -112,17 +115,25 @@ void ReferencesResolver::endVisit(FunctionTypeName const& _typeName) case VariableDeclaration::Visibility::External: break; default: - fatalTypeError(_typeName.location(), "Invalid visibility, can only be \"external\" or \"internal\"."); + typeError(_typeName.location(), "Invalid visibility, can only be \"external\" or \"internal\"."); + return; } if (_typeName.isPayable() && _typeName.visibility() != VariableDeclaration::Visibility::External) - fatalTypeError(_typeName.location(), "Only external function types can be payable."); + { + typeError(_typeName.location(), "Only external function types can be payable."); + return; + } + if (_typeName.visibility() == VariableDeclaration::Visibility::External) for (auto const& t: _typeName.parameterTypes() + _typeName.returnParameterTypes()) { solAssert(t->annotation().type, "Type not set for parameter."); if (!t->annotation().type->canBeUsedExternally(false)) - fatalTypeError(t->location(), "Internal type cannot be used for external function type."); + { + typeError(t->location(), "Internal type cannot be used for external function type."); + return; + } } _typeName.annotation().type = make_shared<FunctionType>(_typeName); @@ -322,17 +333,13 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) type = ref->copyForLocation(typeLoc, isPointer); } else if (varLoc != Location::Default && !ref) - fatalTypeError(_variable.location(), "Storage location can only be given for array or struct types."); - - if (!type) - fatalTypeError(_variable.location(), "Invalid type name."); + typeError(_variable.location(), "Storage location can only be given for array or struct types."); + _variable.annotation().type = type; } else if (!_variable.canHaveAutoType()) - fatalTypeError(_variable.location(), "Explicit type needed."); + typeError(_variable.location(), "Explicit type needed."); // otherwise we have a "var"-declaration whose type is resolved by the first assignment - - _variable.annotation().type = type; } void ReferencesResolver::typeError(SourceLocation const& _location, string const& _description) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 513b5e2c..e8405281 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -122,6 +122,20 @@ BOOST_AUTO_TEST_CASE(undeclared_name) CHECK_ERROR(text, DeclarationError, "Undeclared identifier."); } +BOOST_AUTO_TEST_CASE(undeclared_name_is_not_fatal) +{ + char const* text = R"( + contract test { + uint256 variable; + function f(uint256 arg) public { + f(notfound); + f(notfound); + } + } + )"; + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, "Undeclared identifier."); +} + BOOST_AUTO_TEST_CASE(reference_to_later_declaration) { char const* text = R"( @@ -4050,7 +4064,7 @@ BOOST_AUTO_TEST_CASE(varM_disqualified_as_keyword) } } )"; - CHECK_ERROR(text, DeclarationError, "Identifier not found or not unique."); + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, "Identifier not found or not unique."); } BOOST_AUTO_TEST_CASE(modifier_is_not_a_valid_typename) @@ -4067,6 +4081,21 @@ BOOST_AUTO_TEST_CASE(modifier_is_not_a_valid_typename) CHECK_ERROR(text, TypeError, "Name has to refer to a struct, enum or contract."); } +BOOST_AUTO_TEST_CASE(modifier_is_not_a_valid_typename_is_not_fatal) +{ + char const* text = R"( + contract test { + modifier mod() { _; } + + function f() public { + mod g; + g = f; + } + } + )"; + CHECK_ERROR_ALLOW_MULTI(text, TypeError, "Name has to refer to a struct, enum or contract."); +} + BOOST_AUTO_TEST_CASE(function_is_not_a_valid_typename) { char const* text = R"( @@ -5132,6 +5161,20 @@ BOOST_AUTO_TEST_CASE(payable_internal_function_type) CHECK_ERROR(text, TypeError, "Only external function types can be payable."); } +BOOST_AUTO_TEST_CASE(payable_internal_function_type_is_not_fatal) +{ + char const* text = R"( + contract C { + function (uint) internal payable returns (uint) x; + + function g() { + x = g; + } + } + )"; + CHECK_ERROR_ALLOW_MULTI(text, TypeError, "Only external function types can be payable."); +} + BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) { char const* text = R"( @@ -6656,6 +6699,28 @@ BOOST_AUTO_TEST_CASE(warn_unspecified_storage) CHECK_ERROR(text, TypeError, "Storage location must be specified as either \"memory\" or \"storage\"."); } +BOOST_AUTO_TEST_CASE(storage_location_non_array_or_struct_disallowed) +{ + char const* text = R"( + contract C { + function f(uint storage a) public { } + } + )"; + CHECK_ERROR(text, TypeError, "Storage location can only be given for array or struct types."); +} + +BOOST_AUTO_TEST_CASE(storage_location_non_array_or_struct_disallowed_is_not_fatal) +{ + char const* text = R"( + contract C { + function f(uint storage a) public { + a = f; + } + } + )"; + CHECK_ERROR_ALLOW_MULTI(text, TypeError, "Storage location can only be given for array or struct types."); +} + BOOST_AUTO_TEST_CASE(implicit_conversion_disallowed) { char const* text = R"( |