Merge pull request #3752 from ethereum/fixStateVariableParsing

Fix state variable parsing
This commit is contained in:
chriseth 2018-04-11 22:25:36 +02:00 committed by GitHub
commit ee5d0ef79b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 373 additions and 475 deletions

View File

@ -14,6 +14,7 @@ Features:
* Optimizer: Optimize across ``mload`` if ``msize()`` is not used.
* Static Analyzer: Error on duplicated super constructor calls as experimental 0.5.0 feature.
* Syntax Checker: Issue warning for empty structs (or error as experimental 0.5.0 feature).
* Syntax Checker: Warn about modifiers on functions without implementation (this will turn into an error with version 0.5.0).
* Syntax Tests: Add source locations to syntax test expectations.
* General: Introduce new constructor syntax using the ``constructor`` keyword as experimental 0.5.0 feature.
* Inheritance: Error when using empty parentheses for base class constructors that require arguments as experimental 0.5.0 feature.
@ -30,6 +31,7 @@ Bugfixes:
* Commandline interface: Support ``--evm-version constantinople`` properly.
* DocString Parser: Fix error message for empty descriptions.
* Gas Estimator: Correctly ignore costs of fallback function for other functions.
* Parser: Fix parsing of getters for function type variables.
* Standard JSON: Support ``constantinople`` as ``evmVersion`` properly.
* Type Checker: Fix detection of recursive structs.
* Type Checker: Fix asymmetry bug when comparing with literal numbers.

View File

@ -232,6 +232,13 @@ bool SyntaxChecker::visit(FunctionDefinition const& _function)
"Use \"constructor(...) { ... }\" instead."
);
}
if (!_function.isImplemented() && !_function.modifiers().empty())
{
if (v050)
m_errorReporter.syntaxError(_function.location(), "Functions without implementation cannot have modifiers.");
else
m_errorReporter.warning( _function.location(), "Modifiers of functions without implementation are ignored." );
}
return true;
}

View File

@ -365,12 +365,13 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(
Token::Value token = m_scanner->currentToken();
if (_allowModifiers && token == Token::Identifier)
{
// This can either be a modifier (function declaration) or the name of the
// variable (function type name plus variable).
if (
// If the name is empty (and this is not a constructor),
// then this can either be a modifier (fallback function declaration)
// or the name of the state variable (function type name plus variable).
if ((result.name->empty() && !result.isConstructor) && (
m_scanner->peekNextToken() == Token::Semicolon ||
m_scanner->peekNextToken() == Token::Assign
)
))
// Variable declaration, break here.
break;
else
@ -380,6 +381,14 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(
{
if (result.visibility != Declaration::Visibility::Default)
{
// There is the special case of a public state variable of function type.
// Detect this and return early.
if (
(result.visibility == Declaration::Visibility::External || result.visibility == Declaration::Visibility::Internal) &&
result.modifiers.empty() &&
(result.name->empty() && !result.isConstructor)
)
break;
parserError(string(
"Visibility already specified as \"" +
Declaration::visibilityToString(result.visibility) +
@ -429,6 +438,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(A
FunctionHeaderParserResult header = parseFunctionHeader(false, true, _contractName);
if (
header.isConstructor ||
!header.modifiers.empty() ||
!header.name->empty() ||
m_scanner->currentToken() == Token::Semicolon ||
@ -794,6 +804,7 @@ ASTPointer<FunctionTypeName> Parser::parseFunctionType()
RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this);
FunctionHeaderParserResult header = parseFunctionHeader(true, false);
solAssert(!header.isConstructor, "Tried to parse type as constructor.");
return nodeFactory.createNode<FunctionTypeName>(
header.parameters,
header.returnParameters,

View File

@ -975,139 +975,6 @@ BOOST_AUTO_TEST_CASE(super_excludes_current_contract)
CHECK_ERROR(text, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in contract super B");
}
BOOST_AUTO_TEST_CASE(function_modifier_invocation)
{
char const* text = R"(
contract B {
function f() mod1(2, true) mod2("0123456") pure public { }
modifier mod1(uint a, bool b) { if (b) _; }
modifier mod2(bytes7 a) { while (a == "1234567") _; }
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(invalid_function_modifier_type)
{
char const* text = R"(
contract B {
function f() mod1(true) public { }
modifier mod1(uint a) { if (a > 0) _; }
}
)";
CHECK_ERROR(text, TypeError, "Invalid type for argument in modifier invocation. Invalid implicit conversion from bool to uint256 requested.");
}
BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters)
{
char const* text = R"(
contract B {
function f(uint8 a) mod1(a, true) mod2(r) public returns (bytes7 r) { }
modifier mod1(uint a, bool b) { if (b) _; }
modifier mod2(bytes7 a) { while (a == "1234567") _; }
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables)
{
char const* text = R"(
contract B {
function f() mod(x) pure public { uint x = 7; }
modifier mod(uint a) { if (a > 0) _; }
}
)";
CHECK_SUCCESS_NO_WARNINGS(text);
}
BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables050)
{
char const* text = R"(
pragma experimental "v0.5.0";
contract B {
function f() mod(x) pure public { uint x = 7; }
modifier mod(uint a) { if (a > 0) _; }
}
)";
CHECK_ERROR(text, DeclarationError, "Undeclared identifier.");
}
BOOST_AUTO_TEST_CASE(function_modifier_double_invocation)
{
char const* text = R"(
contract B {
function f(uint x) mod(x) mod(2) public { }
modifier mod(uint a) { if (a > 0) _; }
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(base_constructor_double_invocation)
{
char const* text = R"(
contract C { function C(uint a) public {} }
contract B is C {
function B() C(2) C(2) public {}
}
)";
CHECK_ERROR(text, DeclarationError, "Base constructor already provided");
}
BOOST_AUTO_TEST_CASE(legal_modifier_override)
{
char const* text = R"(
contract A { modifier mod(uint a) { _; } }
contract B is A { modifier mod(uint a) { _; } }
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(illegal_modifier_override)
{
char const* text = R"(
contract A { modifier mod(uint a) { _; } }
contract B is A { modifier mod(uint8 a) { _; } }
)";
CHECK_ERROR(text, TypeError, "Override changes modifier signature.");
}
BOOST_AUTO_TEST_CASE(modifier_overrides_function)
{
char const* text = R"(
contract A { modifier mod(uint a) { _; } }
contract B is A { function mod(uint a) public { } }
)";
CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, string>>{
{Error::Type::DeclarationError, "Identifier already declared"},
{Error::Type::TypeError, "Override changes modifier to function"}
}));
}
BOOST_AUTO_TEST_CASE(function_overrides_modifier)
{
char const* text = R"(
contract A { function mod(uint a) public { } }
contract B is A { modifier mod(uint a) { _; } }
)";
CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, string>>{
{Error::Type::DeclarationError, "Identifier already declared"},
{Error::Type::TypeError, "Override changes function to modifier"}
}));
}
BOOST_AUTO_TEST_CASE(modifier_returns_value)
{
char const* text = R"(
contract A {
function f(uint a) mod(2) public returns (uint r) { }
modifier mod(uint a) { _; return 7; }
}
)";
CHECK_ERROR(text, TypeError, "Return arguments not allowed.");
}
BOOST_AUTO_TEST_CASE(state_variable_accessors)
{
char const* text = R"(
@ -4176,21 +4043,6 @@ BOOST_AUTO_TEST_CASE(conditional_with_all_types)
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count)
{
// This caused a segfault in an earlier version
char const* text = R"(
contract C {
function C(){}
}
contract D is C {
function D() C(5){}
}
)";
CHECK_ERROR(text, TypeError, "Wrong argument count for modifier invocation: 1 arguments given but expected 0.");
}
BOOST_AUTO_TEST_CASE(index_access_for_bytes)
{
char const* text = R"(
@ -5055,16 +4907,6 @@ BOOST_AUTO_TEST_CASE(no_warn_about_callcode_as_function)
CHECK_SUCCESS_NO_WARNINGS(text);
}
BOOST_AUTO_TEST_CASE(modifier_without_underscore)
{
char const* text = R"(
contract test {
modifier m() {}
}
)";
CHECK_ERROR(text, SyntaxError, "Modifier body does not contain '_'.");
}
BOOST_AUTO_TEST_CASE(payable_in_library)
{
char const* text = R"(
@ -5264,319 +5106,6 @@ BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype)
CHECK_ERROR(text, TypeError, "Member \"b\" not found or not visible after argument-dependent lookup in bytes memory");
}
BOOST_AUTO_TEST_CASE(function_type)
{
char const* text = R"(
contract C {
function f() public {
function(uint) returns (uint) x;
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_type_parameter)
{
char const* text = R"(
contract C {
function f(function(uint) external returns (uint) g) public returns (function(uint) external returns (uint)) {
return g;
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_type_returned)
{
char const* text = R"(
contract C {
function f() public returns (function(uint) external returns (uint) g) {
return g;
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(private_function_type)
{
char const* text = R"(
contract C {
function f() public {
function(uint) private returns (uint) x;
}
}
)";
CHECK_ERROR(text, TypeError, "Invalid visibility, can only be \"external\" or \"internal\".");
}
BOOST_AUTO_TEST_CASE(public_function_type)
{
char const* text = R"(
contract C {
function f() public {
function(uint) public returns (uint) x;
}
}
)";
CHECK_ERROR(text, TypeError, "Invalid visibility, can only be \"external\" or \"internal\".");
}
BOOST_AUTO_TEST_CASE(payable_internal_function_type)
{
char const* text = R"(
contract C {
function (uint) internal payable returns (uint) x;
}
)";
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, (std::vector<std::string>{"Only external function types can be payable."}));
}
BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type)
{
char const* text = R"(
contract C {
function (uint) external returns (uint) x;
function f() public {
x.value(2)();
}
}
)";
CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup in function (uint256) external returns (uint256) - did you forget the \"payable\" modifier?");
}
BOOST_AUTO_TEST_CASE(external_function_type_returning_internal)
{
char const* text = R"(
contract C {
function() external returns (function () internal) x;
}
)";
CHECK_ERROR(text, TypeError, "Internal type cannot be used for external function type.");
}
BOOST_AUTO_TEST_CASE(external_function_type_taking_internal)
{
char const* text = R"(
contract C {
function(function () internal) external x;
}
)";
CHECK_ERROR(text, TypeError, "Internal type cannot be used for external function type.");
}
BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type)
{
char const* text = R"(
contract C {
function (uint) external payable returns (uint) x;
function f() public {
x.value(2)(1);
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter)
{
// It should not be possible to give internal functions
// as parameters to external functions.
char const* text = R"(
contract C {
function f(function(uint) internal returns (uint) x) public {
}
}
)";
CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions.");
}
BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function)
{
// It should not be possible to return internal functions from external functions.
char const* text = R"(
contract C {
function f() public returns (function(uint) internal returns (uint) x) {
}
}
)";
CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions.");
}
BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal)
{
char const* text = R"(
library L {
function f(function(uint) internal returns (uint) x) internal {
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external)
{
char const* text = R"(
library L {
function f(function(uint) internal returns (uint) x) public {
}
}
)";
CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions.");
}
BOOST_AUTO_TEST_CASE(function_type_arrays)
{
char const* text = R"(
contract C {
function(uint) external returns (uint)[] public x;
function(uint) internal returns (uint)[10] y;
function f() public {
function(uint) returns (uint)[10] memory a;
function(uint) returns (uint)[10] storage b = y;
function(uint) external returns (uint)[] memory c;
c = new function(uint) external returns (uint)[](200);
a; b;
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(delete_function_type)
{
char const* text = R"(
contract C {
function(uint) external returns (uint) x;
function(uint) internal returns (uint) y;
function f() public {
delete x;
var a = y;
delete a;
delete y;
var c = f;
delete c;
function(uint) internal returns (uint) g;
delete g;
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(delete_function_type_invalid)
{
char const* text = R"(
contract C {
function f() public {
delete f;
}
}
)";
CHECK_ERROR(text, TypeError, "Expression has to be an lvalue.");
}
BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid)
{
char const* text = R"(
contract C {
function f() public {
delete this.f;
}
}
)";
CHECK_ERROR(text, TypeError, "Expression has to be an lvalue.");
}
BOOST_AUTO_TEST_CASE(external_function_to_function_type_calldata_parameter)
{
// This is a test that checks that the type of the `bytes` parameter is
// correctly changed from its own type `bytes calldata` to `bytes memory`
// when converting to a function type.
char const* text = R"(
contract C {
function f(function(bytes memory) external g) public { }
function callback(bytes) external {}
function g() public {
f(this.callback);
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(external_function_type_to_address)
{
char const* text = R"(
contract C {
function f() public returns (address) {
return address(this.f);
}
}
)";
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(internal_function_type_to_address)
{
char const* text = R"(
contract C {
function f() public returns (address) {
return address(f);
}
}
)";
CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed");
}
BOOST_AUTO_TEST_CASE(external_function_type_to_uint)
{
char const* text = R"(
contract C {
function f() public returns (uint) {
return uint(this.f);
}
}
)";
CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed");
}
BOOST_AUTO_TEST_CASE(warn_function_type_parameters_with_names)
{
char const* text = R"(
contract C {
function(uint a) f;
}
)";
CHECK_WARNING(text, "Naming function type parameters is deprecated.");
}
BOOST_AUTO_TEST_CASE(warn_function_type_return_parameters_with_names)
{
char const* text = R"(
contract C {
function(uint) returns (bool ret) f;
}
)";
CHECK_WARNING(text, "Naming function type return parameters is deprecated.");
}
BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue)
{
char const* text = R"(

View File

@ -0,0 +1,8 @@
contract C {
function (uint) external returns (uint) x;
function f() public {
x.value(2)();
}
}
// ----
// TypeError: (94-101): Member "value" not found or not visible after argument-dependent lookup in function (uint256) external returns (uint256) - did you forget the "payable" modifier?

View File

@ -0,0 +1,6 @@
contract C {
function (uint) external payable returns (uint) x;
function f() public {
x.value(2)(1);
}
}

View File

@ -0,0 +1,7 @@
contract C {
function f() public {
delete this.f;
}
}
// ----
// TypeError: (54-60): Expression has to be an lvalue.

View File

@ -0,0 +1,17 @@
contract C {
function(uint) external returns (uint) x;
function(uint) internal returns (uint) y;
function f() public {
delete x;
var a = y;
delete a;
delete y;
var c = f;
delete c;
function(uint) internal returns (uint) g;
delete g;
}
}
// ----
// Warning: (157-162): Use of the "var" keyword is deprecated.
// Warning: (212-217): Use of the "var" keyword is deprecated.

View File

@ -0,0 +1,7 @@
contract C {
function f() public {
delete f;
}
}
// ----
// TypeError: (54-55): Expression has to be an lvalue.

View File

@ -0,0 +1,10 @@
// This is a test that checks that the type of the `bytes` parameter is
// correctly changed from its own type `bytes calldata` to `bytes memory`
// when converting to a function type.
contract C {
function f(function(bytes memory) pure external /*g*/) pure public { }
function callback(bytes) pure external {}
function g() view public {
f(this.callback);
}
}

View File

@ -0,0 +1,11 @@
contract C {
function (uint) external public x;
function g(uint) public {
x = this.g;
}
function f() public view returns (function(uint) external) {
return this.x();
}
}
// ----

View File

@ -0,0 +1,5 @@
contract C {
function() external returns (function () internal) x;
}
// ----
// TypeError: (46-67): Internal type cannot be used for external function type.

View File

@ -0,0 +1,5 @@
contract C {
function(function () internal) external x;
}
// ----
// TypeError: (26-47): Internal type cannot be used for external function type.

View File

@ -0,0 +1,5 @@
contract C {
function f() public view returns (address) {
return address(this.f);
}
}

View File

@ -0,0 +1,7 @@
contract C {
function f() public returns (uint) {
return uint(this.f);
}
}
// ----
// TypeError: (69-81): Explicit type conversion not allowed from "function () external returns (uint256)" to "uint256".

View File

@ -0,0 +1,6 @@
contract C {
function f() pure public {
function(uint) returns (uint) x;
x;
}
}

View File

@ -0,0 +1,11 @@
contract C {
function(uint) external returns (uint)[] public x;
function(uint) internal returns (uint)[10] y;
function f() view public {
function(uint) returns (uint)[10] memory a;
function(uint) returns (uint)[10] storage b = y;
function(uint) external returns (uint)[] memory c;
c = new function(uint) external returns (uint)[](200);
a; b;
}
}

View File

@ -0,0 +1,7 @@
contract C {
// Fool parser into parsing a constructor as a function type.
constructor() x;
}
// ----
// Warning: (83-99): Modifiers of functions without implementation are ignored.
// DeclarationError: (97-98): Undeclared identifier.

View File

@ -0,0 +1,8 @@
contract C {
// Fool parser into parsing a constructor as a function type.
function f() {
constructor() x;
}
}
// ----
// ParserError: (118-118): Expected token Semicolon got 'Identifier'

View File

@ -0,0 +1,5 @@
contract C {
function(bytes memory) internal public a;
}
// ----
// TypeError: (17-57): Internal or recursive type is not allowed for public state variables.

View File

@ -0,0 +1,7 @@
contract C {
uint x;
function f(function(uint) external returns (uint) g) public returns (function(uint) external returns (uint)) {
x = 2;
return g;
}
}

View File

@ -0,0 +1,5 @@
contract C {
function f() public pure returns (function(uint) pure external returns (uint) g) {
return g;
}
}

View File

@ -0,0 +1,6 @@
contract test {
function fa(bytes memory) public { }
function(bytes memory) external internal a = fa;
}
// ----
// TypeError: (106-108): Type function (bytes memory) is not implicitly convertible to expected type function (bytes memory) external.

View File

@ -0,0 +1,7 @@
contract C {
// This is an error, you should explicitly use
// `external public` to fix it - `internal public` does not exist.
function(bytes memory) public a;
}
// ----
// TypeError: (139-170): Invalid visibility, can only be "external" or "internal".

View File

@ -0,0 +1,9 @@
contract C {
function(bytes memory) a1;
function(bytes memory) internal b1;
function(bytes memory) internal internal b2;
function(bytes memory) external c1;
function(bytes memory) external internal c2;
function(bytes memory) external public c3;
}
// ----

View File

@ -0,0 +1,8 @@
// It should not be possible to give internal functions
// as parameters to external functions.
contract C {
function f(function(uint) internal returns (uint) x) public {
}
}
// ----
// TypeError: (124-164): Internal or recursive type is not allowed for public or external functions.

View File

@ -0,0 +1,6 @@
library L {
function f(function(uint) internal returns (uint) x) public {
}
}
// ----
// TypeError: (27-67): Internal or recursive type is not allowed for public or external functions.

View File

@ -0,0 +1,4 @@
library L {
function f(function(uint) internal returns (uint) /*x*/) pure internal {
}
}

View File

@ -0,0 +1,7 @@
// It should not be possible to return internal functions from external functions.
contract C {
function f() public returns (function(uint) internal returns (uint) x) {
}
}
// ----
// TypeError: (129-169): Internal or recursive type is not allowed for public or external functions.

View File

@ -0,0 +1,7 @@
contract C {
function f() public returns (address) {
return address(f);
}
}
// ----
// TypeError: (72-82): Explicit type conversion not allowed from "function () returns (address)" to "address".

View File

@ -0,0 +1,5 @@
contract C {
function (uint) internal payable returns (uint) x;
}
// ----
// TypeError: (17-66): Only external function types can be payable.

View File

@ -0,0 +1,9 @@
contract C {
function (uint) internal payable returns (uint) x;
function g() public {
x = g;
}
}
// ----
// TypeError: (17-66): Only external function types can be payable.

View File

@ -0,0 +1,7 @@
contract C {
function f() public {
function(uint) private returns (uint) x;
}
}
// ----
// TypeError: (47-86): Invalid visibility, can only be "external" or "internal".

View File

@ -0,0 +1,7 @@
contract C {
function f() public {
function(uint) public returns (uint) x;
}
}
// ----
// TypeError: (47-85): Invalid visibility, can only be "external" or "internal".

View File

@ -0,0 +1,23 @@
contract test {
function fa(uint) {}
function fb(uint) internal {}
function fc(uint) internal {}
function fd(uint) external {}
function fe(uint) external {}
function ff(uint) internal {}
function fg(uint) internal pure {}
function fh(uint) pure internal {}
function(uint) a = fa;
function(uint) internal b = fb; // (explicit internal applies to the function type)
function(uint) internal internal c = fc;
function(uint) external d = this.fd;
function(uint) external internal e = this.fe;
function(uint) internal public f = ff;
function(uint) internal pure public g = fg;
function(uint) pure internal public h = fh;
}
// ----
// TypeError: (545-582): Internal or recursive type is not allowed for public state variables.
// TypeError: (588-630): Internal or recursive type is not allowed for public state variables.
// TypeError: (636-678): Internal or recursive type is not allowed for public state variables.

View File

@ -0,0 +1,5 @@
contract C {
function(uint a) f;
}
// ----
// Warning: (26-32): Naming function type parameters is deprecated.

View File

@ -0,0 +1,5 @@
contract C {
function(uint) returns (bool ret) f;
}
// ----
// Warning: (41-49): Naming function type return parameters is deprecated.

View File

@ -0,0 +1,7 @@
contract C { constructor(uint a) public {} }
contract B is C {
constructor() C(2) C(2) public {}
}
// ----
// Warning: (81-85): Base constructor arguments given twice.
// DeclarationError: (86-90): Base constructor already provided.

View File

@ -0,0 +1,9 @@
// This caused a segfault in an earlier version
contract C {
constructor() public {}
}
contract D is C {
constructor() C(5) public {}
}
// ----
// TypeError: (127-131): Wrong argument count for modifier invocation: 1 arguments given but expected 0.

View File

@ -0,0 +1,4 @@
contract B {
function f(uint x) mod(x) mod(2) public pure { }
modifier mod(uint a) { if (a > 0) _; }
}

View File

@ -0,0 +1,5 @@
contract B {
function f() mod1(2, true) mod2("0123456") pure public { }
modifier mod1(uint a, bool b) { if (b) _; }
modifier mod2(bytes7 a) { while (a == "1234567") _; }
}

View File

@ -0,0 +1,4 @@
contract B {
function f() mod(x) pure public { uint x = 7; }
modifier mod(uint a) { if (a > 0) _; }
}

View File

@ -0,0 +1,7 @@
pragma experimental "v0.5.0";
contract B {
function f() mod(x) pure public { uint x = 7; }
modifier mod(uint a) { if (a > 0) _; }
}
// ----
// DeclarationError: (64-65): Undeclared identifier.

View File

@ -0,0 +1,5 @@
contract B {
function f(uint8 a) mod1(a, true) mod2(r) pure public returns (bytes7 r) { }
modifier mod1(uint a, bool b) { if (b) _; }
modifier mod2(bytes7 a) { while (a == "1234567") _; }
}

View File

@ -0,0 +1,5 @@
contract A { function mod(uint a) public { } }
contract B is A { modifier mod(uint a) { _; } }
// ----
// DeclarationError: (65-92): Identifier already declared.
// TypeError: (65-92): Override changes function to modifier.

View File

@ -0,0 +1,4 @@
contract A { modifier mod(uint a) { _; } }
contract B is A { modifier mod(uint8 a) { _; } }
// ----
// TypeError: (61-89): Override changes modifier signature.

View File

@ -0,0 +1,6 @@
contract B {
function f() mod1(true) public { }
modifier mod1(uint a) { if (a > 0) _; }
}
// ----
// TypeError: (35-39): Invalid type for argument in modifier invocation. Invalid implicit conversion from bool to uint256 requested.

View File

@ -0,0 +1,2 @@
contract A { modifier mod(uint a) { _; } }
contract B is A { modifier mod(uint a) { _; } }

View File

@ -0,0 +1,5 @@
contract A { modifier mod(uint a) { _; } }
contract B is A { function mod(uint a) public { } }
// ----
// DeclarationError: (61-92): Identifier already declared.
// TypeError: (13-40): Override changes modifier to function.

View File

@ -0,0 +1,6 @@
contract A {
function f(uint a) mod(2) public returns (uint r) { }
modifier mod(uint a) { _; return 7; }
}
// ----
// TypeError: (101-109): Return arguments not allowed.

View File

@ -0,0 +1,5 @@
contract test {
modifier m() {}
}
// ----
// SyntaxError: (33-35): Modifier body does not contain '_'.

View File

@ -0,0 +1,10 @@
pragma experimental "v0.5.0";
contract C
{
modifier only_owner() { _; }
function foo() only_owner public;
function bar() public only_owner;
}
// ----
// SyntaxError: (80-113): Functions without implementation cannot have modifiers.
// SyntaxError: (118-151): Functions without implementation cannot have modifiers.

View File

@ -0,0 +1,13 @@
// Previous versions of Solidity turned this
// into a parser error (they wrongly recognized
// these functions as state variables of
// function type).
contract C
{
modifier only_owner() { _; }
function foo() only_owner public;
function bar() public only_owner;
}
// ----
// Warning: (203-236): Modifiers of functions without implementation are ignored.
// Warning: (241-274): Modifiers of functions without implementation are ignored.