mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #3752 from ethereum/fixStateVariableParsing
Fix state variable parsing
This commit is contained in:
commit
ee5d0ef79b
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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"(
|
||||
|
@ -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?
|
@ -0,0 +1,6 @@
|
||||
contract C {
|
||||
function (uint) external payable returns (uint) x;
|
||||
function f() public {
|
||||
x.value(2)(1);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
function f() public {
|
||||
delete this.f;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (54-60): Expression has to be an lvalue.
|
@ -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.
|
@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
function f() public {
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (54-55): Expression has to be an lvalue.
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function() external returns (function () internal) x;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (46-67): Internal type cannot be used for external function type.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function(function () internal) external x;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (26-47): Internal type cannot be used for external function type.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function f() public view returns (address) {
|
||||
return address(this.f);
|
||||
}
|
||||
}
|
@ -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".
|
@ -0,0 +1,6 @@
|
||||
contract C {
|
||||
function f() pure public {
|
||||
function(uint) returns (uint) x;
|
||||
x;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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.
|
@ -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'
|
@ -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.
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function f() public pure returns (function(uint) pure external returns (uint) g) {
|
||||
return g;
|
||||
}
|
||||
}
|
@ -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.
|
@ -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".
|
@ -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;
|
||||
}
|
||||
// ----
|
@ -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.
|
@ -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.
|
@ -0,0 +1,4 @@
|
||||
library L {
|
||||
function f(function(uint) internal returns (uint) /*x*/) pure internal {
|
||||
}
|
||||
}
|
@ -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.
|
@ -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".
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function (uint) internal payable returns (uint) x;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (17-66): Only external function types can be payable.
|
@ -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.
|
@ -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".
|
@ -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".
|
@ -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.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function(uint a) f;
|
||||
}
|
||||
// ----
|
||||
// Warning: (26-32): Naming function type parameters is deprecated.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function(uint) returns (bool ret) f;
|
||||
}
|
||||
// ----
|
||||
// Warning: (41-49): Naming function type return parameters is deprecated.
|
@ -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.
|
@ -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.
|
@ -0,0 +1,4 @@
|
||||
contract B {
|
||||
function f(uint x) mod(x) mod(2) public pure { }
|
||||
modifier mod(uint a) { if (a > 0) _; }
|
||||
}
|
@ -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") _; }
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
contract B {
|
||||
function f() mod(x) pure public { uint x = 7; }
|
||||
modifier mod(uint a) { if (a > 0) _; }
|
||||
}
|
@ -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.
|
@ -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") _; }
|
||||
}
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -0,0 +1,2 @@
|
||||
contract A { modifier mod(uint a) { _; } }
|
||||
contract B is A { modifier mod(uint a) { _; } }
|
@ -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.
|
@ -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.
|
@ -0,0 +1,5 @@
|
||||
contract test {
|
||||
modifier m() {}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError: (33-35): Modifier body does not contain '_'.
|
@ -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.
|
@ -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.
|
Loading…
Reference in New Issue
Block a user