mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #3360 from federicobond/nonfatal-reference-errors
Replace some fatal errors when resolving references with normal ones
This commit is contained in:
commit
32300ea3ff
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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"(
|
||||
|
Loading…
Reference in New Issue
Block a user