aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2018-02-04 21:07:55 +0800
committerGitHub <noreply@github.com>2018-02-04 21:07:55 +0800
commit32300ea3fff05b6fb6080ebc32588e8e66ccc400 (patch)
tree55b376652e34079f48632a3ef61396f244ad5d43
parent07f8f96c94cd2a2602226dee2aa08597c1bd21d6 (diff)
parentaef95180392fcff5f339655754535a34c8564599 (diff)
downloaddexon-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.md1
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp33
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp67
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"(