From 05baa23e8a9e297584470200365a7d9a79f9c0ab Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 2 Dec 2019 21:39:53 +0100 Subject: [PATCH 1/3] Require unimplemented functions to be virtual. --- libsolidity/analysis/TypeChecker.cpp | 2 ++ test/libsolidity/SolidityEndToEndTest.cpp | 2 +- .../SolidityNameAndTypeResolution.cpp | 8 +++--- .../functions/functions_external_1.sol | 4 +-- .../functions/functions_external_2.sol | 4 +-- .../functions/functions_external_3.sol | 4 +-- .../abstract/unimplemented_functions.sol | 4 +-- .../unimplemented_functions_inherited.sol | 4 +-- .../storageReturn/unimplemented_internal.sol | 4 +-- ...ation_specifier_test_external_calldata.sol | 4 +-- ...ocation_specifier_test_internal_memory.sol | 4 +-- ...cation_specifier_test_internal_storage.sol | 4 +-- ..._location_specifier_test_public_memory.sol | 4 +-- ...t_internal_function_by_public_variable.sol | 4 +-- ...nt_private_function_by_public_variable.sol | 2 +- ...ent_public_function_by_public_variable.sol | 4 +-- .../inheritance/override/override.sol | 6 ++--- .../override/override_ambiguous.sol | 6 ++--- .../override/override_base_base.sol | 4 +-- .../override/override_interface.sol | 6 ++--- .../override/override_interface_multiple.sol | 6 ++--- .../override/override_missing_virtual.sol | 10 +++---- .../override/override_multiple.sol | 8 +++--- .../override/override_multiple2.sol | 4 +-- .../override/override_multiple_duplicated.sol | 10 +++---- .../override/override_multiple_missing.sol | 6 ++--- .../override/override_return_mismatch.sol | 4 +-- .../override/override_type_mismatch.sol | 8 +++--- .../override/state_variable_function.sol | 5 ++-- .../inheritance/override/virtual_private.sol | 2 +- .../unimplemented_without_virtual.sol | 5 ++++ ..._on_abstract_functions_no_parser_error.sol | 8 +++--- .../differentNumberOfComponentsFromReturn.sol | 26 +++++++++---------- .../disallowWildcardsFromReturn.sol | 10 +++---- .../029_create_abstract_contract.sol | 4 +-- ...lemented_abstract_function_as_abstract.sol | 5 ++-- .../268_function_overload_array_type.sol | 4 +-- ...6_no_unused_warning_abstract_arguments.sol | 2 +- ...members_that_look_like_address_members.sol | 2 +- .../natspec/docstring_empty_description.sol | 4 +-- .../natspec/docstring_empty_tag.sol | 2 +- .../syntaxTests/parsing/function_no_body.sol | 2 +- .../function_parameter_return_types_fail.sol | 16 ++++++------ .../interface_contract_function_default.sol | 4 +-- 44 files changed, 123 insertions(+), 118 deletions(-) create mode 100644 test/libsolidity/syntaxTests/inheritance/unimplemented_without_virtual.sol diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d32da45b4..960458f24 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -433,6 +433,8 @@ bool TypeChecker::visit(FunctionDefinition const& _function) m_errorReporter.typeError(_function.location(), "Constructor must be implemented if declared."); else if (isLibraryFunction) m_errorReporter.typeError(_function.location(), "Library functions must be implemented if declared."); + else if (!_function.virtualSemantics()) + m_errorReporter.typeError(_function.location(), "Functions without implementation must be marked virtual."); if (_function.isFallback()) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index ea72a946c..8275536a0 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -10464,7 +10464,7 @@ BOOST_AUTO_TEST_CASE(mutex) BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) { char const* sourceCode = R"YY( - abstract contract D { function g() public; } + abstract contract D { function g() public virtual; } contract C { D d = D(0x1212); function f() public returns (uint) { diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index f744d5b3c..d22d1880f 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(function_no_implementation) SourceUnit const* sourceUnit = nullptr; char const* text = R"( abstract contract test { - function functionName(bytes32 input) public returns (bytes32 out); + function functionName(bytes32 input) public virtual returns (bytes32 out); } )"; sourceUnit = parseAndAnalyse(text); @@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload) { SourceUnit const* sourceUnit = nullptr; char const* text = R"( - abstract contract base { function foo(bool) public; } + abstract contract base { function foo(bool) public virtual; } abstract contract derived is base { function foo(uint) public {} } )"; sourceUnit = parseAndAnalyse(text); @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) { SourceUnit const* sourceUnit = nullptr; char const* text = R"( - abstract contract base { function foo() public; } + abstract contract base { function foo() public virtual; } abstract contract foo is base { constructor() public {} } )"; sourceUnit = parseAndAnalyse(text); @@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) { char const* sourceCode = R"( abstract contract C { - function f(uint) public returns (string memory); + function f(uint) public virtual returns (string memory); function g() public { string memory x = this.f(2); // we can assign to x but it is not usable. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol b/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol index a0eccf3cf..4f1a64783 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_external_1.sol @@ -2,7 +2,7 @@ pragma experimental SMTChecker; abstract contract D { - function g(uint x) public; + function g(uint x) public virtual; } contract C @@ -17,4 +17,4 @@ contract C } } // ---- -// Warning: (249-263): Assertion violation happens here +// Warning: (257-271): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol b/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol index 60795ca7f..a0c59c0b7 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol @@ -2,7 +2,7 @@ pragma experimental SMTChecker; abstract contract D { - function g(uint x) public; + function g(uint x) public virtual; } contract C @@ -17,4 +17,4 @@ contract C } } // ---- -// Warning: (289-313): Assertion violation happens here +// Warning: (297-321): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/functions_external_3.sol b/test/libsolidity/smtCheckerTests/functions/functions_external_3.sol index 43745155d..0f4de76f6 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_external_3.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_external_3.sol @@ -2,7 +2,7 @@ pragma experimental SMTChecker; abstract contract D { - function g(uint x) public; + function g(uint x) public virtual; } contract C @@ -18,4 +18,4 @@ contract C } } // ---- -// Warning: (347-371): Assertion violation happens here +// Warning: (355-379): Assertion violation happens here diff --git a/test/libsolidity/syntaxTests/abstract/unimplemented_functions.sol b/test/libsolidity/syntaxTests/abstract/unimplemented_functions.sol index 6ec4c2c8e..efad376d8 100644 --- a/test/libsolidity/syntaxTests/abstract/unimplemented_functions.sol +++ b/test/libsolidity/syntaxTests/abstract/unimplemented_functions.sol @@ -1,5 +1,5 @@ contract A { - function a() public; + function a() public virtual; } // ---- -// TypeError: (0-39): Contract "A" should be marked as abstract. +// TypeError: (0-47): Contract "A" should be marked as abstract. diff --git a/test/libsolidity/syntaxTests/abstract/unimplemented_functions_inherited.sol b/test/libsolidity/syntaxTests/abstract/unimplemented_functions_inherited.sol index cb4640c3a..fc7f6c829 100644 --- a/test/libsolidity/syntaxTests/abstract/unimplemented_functions_inherited.sol +++ b/test/libsolidity/syntaxTests/abstract/unimplemented_functions_inherited.sol @@ -1,7 +1,7 @@ abstract contract A { - function a() public; + function a() public virtual; } contract B is A { } // ---- -// TypeError: (49-68): Contract "B" should be marked as abstract. +// TypeError: (57-76): Contract "B" should be marked as abstract. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_internal.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_internal.sol index 70cd3fcad..3c8986a6b 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_internal.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_internal.sol @@ -1,5 +1,5 @@ abstract contract C { - function f() internal returns(uint[] storage); - function g() internal returns(uint[] storage s); + function f() internal virtual returns(uint[] storage); + function g() internal virtual returns(uint[] storage s); } // ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_calldata.sol index cf5839d38..b75fc05c7 100644 --- a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_calldata.sol +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_calldata.sol @@ -1,4 +1,4 @@ -abstract contract test { - function f(bytes calldata) external; +contract test { + function f(bytes calldata) external {} } // ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_memory.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_memory.sol index 0f1b642cc..dde99d56c 100644 --- a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_memory.sol +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_memory.sol @@ -1,4 +1,4 @@ -abstract contract test { - function f(bytes memory) internal; +contract test { + function f(bytes memory) internal {} } // ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_storage.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_storage.sol index fdc07a452..706d22bce 100644 --- a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_storage.sol +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_storage.sol @@ -1,4 +1,4 @@ -abstract contract test { - function f(bytes storage) internal; +contract test { + function f(bytes storage) internal {} } // ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_memory.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_memory.sol index 3535d3d97..7cea3cb49 100644 --- a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_memory.sol +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_memory.sol @@ -1,4 +1,4 @@ -abstract contract test { - function f(bytes memory) public; +contract test { + function f(bytes memory) public {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol index 15b1288b8..ff07bae09 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol @@ -1,4 +1,4 @@ -abstract contract X { function test() internal returns (uint256); } +abstract contract X { function test() internal virtual returns (uint256); } contract Y is X { uint256 public test = 42; } @@ -6,4 +6,4 @@ contract T { constructor() public { new Y(); } } // ---- -// DeclarationError: (90-114): Identifier already declared. +// DeclarationError: (98-122): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol index 979f84f23..6d467e07c 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol @@ -1,4 +1,4 @@ -abstract contract X { function test() private returns (uint256); } +abstract contract X { function test() private returns (uint256) {} } contract Y is X { uint256 public test = 42; } diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol index f70f7608d..b68caffba 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol @@ -1,4 +1,4 @@ -abstract contract X { function test() public returns (uint256); } +abstract contract X { function test() public virtual returns (uint256); } contract Y is X { uint256 public test = 42; } @@ -6,4 +6,4 @@ contract T { constructor() public { new Y(); } } // ---- -// DeclarationError: (88-112): Identifier already declared. +// DeclarationError: (96-120): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/inheritance/override/override.sol b/test/libsolidity/syntaxTests/inheritance/override/override.sol index 66fef0da3..bf79c702d 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override.sol @@ -3,9 +3,9 @@ abstract contract A { function test() internal virtual returns (uint256); function test2() internal virtual returns (uint256); } -abstract contract X is A { +contract X is A { int public override testvar; - function test() internal override returns (uint256); - function test2() internal override(A) returns (uint256); + function test() internal override returns (uint256) {} + function test2() internal override(A) returns (uint256) {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_ambiguous.sol b/test/libsolidity/syntaxTests/inheritance/override/override_ambiguous.sol index d77aff87b..966c18f70 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_ambiguous.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_ambiguous.sol @@ -3,12 +3,12 @@ abstract contract A { function foo() internal virtual returns (uint256); } abstract contract B { - function foo() internal returns (uint256); + function foo() internal virtual returns (uint256); function test() internal virtual returns (uint256); } abstract contract X is A, B { int public override testvar; - function test() internal override returns (uint256); + function test() internal override returns (uint256) {} } // ---- -// TypeError: (218-333): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes. +// TypeError: (226-343): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes. diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_base_base.sol b/test/libsolidity/syntaxTests/inheritance/override/override_base_base.sol index 1df19f9ac..a3f5ed2c7 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_base_base.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_base_base.sol @@ -14,7 +14,7 @@ abstract contract D is C { function foo() internal override virtual returns (uint256); } -abstract contract X is D { - function foo() internal override returns (uint256); +contract X is D { + function foo() internal override returns (uint256) {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_interface.sol b/test/libsolidity/syntaxTests/inheritance/override/override_interface.sol index 06a846666..8b70bdbb6 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_interface.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_interface.sol @@ -2,8 +2,8 @@ interface A { function test() external returns (uint256); function test2() external returns (uint256); } -abstract contract X is A { - function test() external override returns (uint256); - function test2() external override(A) returns (uint256); +contract X is A { + function test() external override returns (uint256) {} + function test2() external override(A) returns (uint256) {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_interface_multiple.sol b/test/libsolidity/syntaxTests/inheritance/override/override_interface_multiple.sol index ad4f31fd5..9b82be89f 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_interface_multiple.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_interface_multiple.sol @@ -7,8 +7,8 @@ interface B { function test() external returns (uint256); function test2() external returns (uint256); } -abstract contract X is A, B { - function test() external override(A, B) returns (uint256); - function test2() external override(B, A) returns (uint256); +contract X is A, B { + function test() external override(A, B) returns (uint256) {} + function test2() external override(B, A) returns (uint256) {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_missing_virtual.sol b/test/libsolidity/syntaxTests/inheritance/override/override_missing_virtual.sol index 563947f88..bf4b15d46 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_missing_virtual.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_missing_virtual.sol @@ -1,11 +1,11 @@ abstract contract A { function test() external virtual returns (uint256); - function test2() external returns (uint256); + function test2() external returns (uint256) {} } abstract contract X is A { - function test() external returns (uint256); - function test2() external override(A) returns (uint256); + function test() external returns (uint256) {} + function test2() external override(A) returns (uint256) {} } // ---- -// TypeError: (151-194): Overriding function is missing 'override' specifier. -// TypeError: (76-120): Trying to override non-virtual function. Did you forget to add "virtual"? +// TypeError: (153-198): Overriding function is missing 'override' specifier. +// TypeError: (76-122): Trying to override non-virtual function. Did you forget to add "virtual"? diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_multiple.sol b/test/libsolidity/syntaxTests/inheritance/override/override_multiple.sol index 2923a5d66..d8daaf406 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_multiple.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_multiple.sol @@ -1,7 +1,7 @@ abstract contract A { int public testvar; function foo() internal virtual returns (uint256); - function test(uint8 _a) internal virtual returns (uint256); + function test(uint8 _a) internal virtual returns (uint256) {} } abstract contract B { function foo() internal virtual returns (uint256); @@ -13,9 +13,9 @@ abstract contract C { abstract contract D { function foo() internal virtual returns (uint256); } -abstract contract X is A, B, C, D { +contract X is A, B, C, D { int public override testvar; - function test() internal override returns (uint256); - function foo() internal override(A, B, C, D) returns (uint256); + function test() internal override returns (uint256) {} + function foo() internal override(A, B, C, D) returns (uint256) {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_multiple2.sol b/test/libsolidity/syntaxTests/inheritance/override/override_multiple2.sol index 46c7e1051..6cec3c2e7 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_multiple2.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_multiple2.sol @@ -1,7 +1,7 @@ abstract contract A { int public testvar; function foo() internal virtual returns (uint256); - function test(uint8 _a) internal returns (uint256); + function test(uint8 _a) internal virtual returns (uint256); } abstract contract B { function foo() internal virtual returns (uint256); @@ -10,6 +10,6 @@ abstract contract B { abstract contract C is A { } abstract contract D is A, B, C { - function foo() internal override(A, B) returns (uint256); + function foo() internal override(A, B) virtual returns (uint256); } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_multiple_duplicated.sol b/test/libsolidity/syntaxTests/inheritance/override/override_multiple_duplicated.sol index 947eb707b..a2c05bbd0 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_multiple_duplicated.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_multiple_duplicated.sol @@ -16,11 +16,11 @@ abstract contract D { } abstract contract X is A, B, C, D { int public override testvar; - function test() internal override(B, D, D) returns (uint256); - function foo() internal override(A, C, B, B, B, D ,D) returns (uint256); + function test() internal override(B, D, D) virtual returns (uint256); + function foo() internal override(A, C, B, B, B, D ,D) virtual returns (uint256); } // ---- // TypeError: (599-600): Duplicate contract "D" found in override list of "test". -// TypeError: (664-665): Duplicate contract "B" found in override list of "foo". -// TypeError: (667-668): Duplicate contract "B" found in override list of "foo". -// TypeError: (673-674): Duplicate contract "D" found in override list of "foo". +// TypeError: (672-673): Duplicate contract "B" found in override list of "foo". +// TypeError: (675-676): Duplicate contract "B" found in override list of "foo". +// TypeError: (681-682): Duplicate contract "D" found in override list of "foo". diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_multiple_missing.sol b/test/libsolidity/syntaxTests/inheritance/override/override_multiple_missing.sol index e989af6b0..e7b493dfd 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_multiple_missing.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_multiple_missing.sol @@ -16,9 +16,9 @@ abstract contract D { } abstract contract X is A, B, C, D { int public override testvar; - function test() internal override(B, D, C) returns (uint256); - function foo() internal override(A, C) returns (uint256); + function test() internal override(B, D, C) virtual returns (uint256); + function foo() internal override(A, C) virtual returns (uint256); } // ---- // TypeError: (584-601): Invalid contract specified in override list: C. -// TypeError: (646-660): Function needs to specify overridden contracts B and D. +// TypeError: (654-668): Function needs to specify overridden contracts B and D. diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_return_mismatch.sol b/test/libsolidity/syntaxTests/inheritance/override/override_return_mismatch.sol index 82cf5d5bc..e4aac5871 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_return_mismatch.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_return_mismatch.sol @@ -8,7 +8,7 @@ abstract contract B { } abstract contract X is A, B { int public override testvar; - function test() internal override returns (uint256); + function test() internal override virtual returns (uint256); } // ---- -// TypeError: (224-339): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes. +// TypeError: (224-347): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes. diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_type_mismatch.sol b/test/libsolidity/syntaxTests/inheritance/override/override_type_mismatch.sol index 7d448e829..ab9a4388b 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_type_mismatch.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_type_mismatch.sol @@ -18,9 +18,9 @@ abstract contract X is A, B, C, D { enum ENUM { F,G,H } int public override testvar; - function test() internal override returns (uint256); - function foo() internal override(MyStruct, ENUM, A, B, C, D) returns (uint256); + function test() internal override virtual returns (uint256); + function foo() internal override(MyStruct, ENUM, A, B, C, D) virtual returns (uint256); } // ---- -// TypeError: (645-653): Expected contract but got struct X.MyStruct. -// TypeError: (655-659): Expected contract but got enum X.ENUM. +// TypeError: (653-661): Expected contract but got struct X.MyStruct. +// TypeError: (663-667): Expected contract but got enum X.ENUM. diff --git a/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol index fb7f3fbdd..bb4b28be8 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol @@ -2,8 +2,7 @@ contract A { uint public x; } contract C is A { - function x() public returns (uint); + function x() public returns (uint) {} } // ---- -// DeclarationError: (50-85): Identifier already declared. -// TypeError: (50-85): Redeclaring an already implemented function as abstract +// DeclarationError: (50-87): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/inheritance/override/virtual_private.sol b/test/libsolidity/syntaxTests/inheritance/override/virtual_private.sol index 95690e7db..1d3b24478 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/virtual_private.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/virtual_private.sol @@ -2,7 +2,7 @@ abstract contract A { function test() private virtual returns (uint256); } abstract contract X is A { - function test() private override returns (uint256); + function test() private override returns (uint256) {} } // ---- // TypeError: (23-73): "virtual" and "private" cannot be used together. diff --git a/test/libsolidity/syntaxTests/inheritance/unimplemented_without_virtual.sol b/test/libsolidity/syntaxTests/inheritance/unimplemented_without_virtual.sol new file mode 100644 index 000000000..7635e0297 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/unimplemented_without_virtual.sol @@ -0,0 +1,5 @@ +abstract contract C { + function f() external; +} +// ---- +// TypeError: (23-45): Functions without implementation must be marked virtual. diff --git a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol index 534a4d1a8..a3ffd7c17 100644 --- a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol +++ b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol @@ -5,9 +5,9 @@ abstract contract C { modifier only_owner() { _; } - function foo() only_owner public; - function bar() public only_owner; + function foo() only_owner public virtual; + function bar() public only_owner virtual; } // ---- -// SyntaxError: (212-245): Functions without implementation cannot have modifiers. -// SyntaxError: (250-283): Functions without implementation cannot have modifiers. +// SyntaxError: (212-253): Functions without implementation cannot have modifiers. +// SyntaxError: (258-299): Functions without implementation cannot have modifiers. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponentsFromReturn.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponentsFromReturn.sol index 332ac6b14..dead52486 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponentsFromReturn.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/differentNumberOfComponentsFromReturn.sol @@ -1,4 +1,4 @@ -abstract contract C { +contract C { function f() public { uint a = two(); uint b = three(); @@ -13,17 +13,17 @@ abstract contract C { (uint a1, uint b1, uint c1, uint d1) = three(); (uint a2, uint b2, uint c2) = four(); } - function one() public pure returns (uint); - function two() public pure returns (uint, uint); - function three() public pure returns (uint, uint, uint); - function four() public pure returns (uint, uint, uint, uint); + function one() public pure returns (uint) {} + function two() public pure returns (uint, uint) {} + function three() public pure returns (uint, uint, uint) {} + function four() public pure returns (uint, uint, uint, uint) {} } // ---- -// TypeError: (56-70): Different number of components on the left hand side (1) than on the right hand side (2). -// TypeError: (80-96): Different number of components on the left hand side (1) than on the right hand side (3). -// TypeError: (106-121): Different number of components on the left hand side (1) than on the right hand side (4). -// TypeError: (163-207): Different number of components on the left hand side (4) than on the right hand side (1). -// TypeError: (217-252): Different number of components on the left hand side (3) than on the right hand side (1). -// TypeError: (262-288): Different number of components on the left hand side (2) than on the right hand side (1). -// TypeError: (330-376): Different number of components on the left hand side (4) than on the right hand side (3). -// TypeError: (386-422): Different number of components on the left hand side (3) than on the right hand side (4). +// TypeError: (47-61): Different number of components on the left hand side (1) than on the right hand side (2). +// TypeError: (71-87): Different number of components on the left hand side (1) than on the right hand side (3). +// TypeError: (97-112): Different number of components on the left hand side (1) than on the right hand side (4). +// TypeError: (154-198): Different number of components on the left hand side (4) than on the right hand side (1). +// TypeError: (208-243): Different number of components on the left hand side (3) than on the right hand side (1). +// TypeError: (253-279): Different number of components on the left hand side (2) than on the right hand side (1). +// TypeError: (321-367): Different number of components on the left hand side (4) than on the right hand side (3). +// TypeError: (377-413): Different number of components on the left hand side (3) than on the right hand side (4). diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcardsFromReturn.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcardsFromReturn.sol index 969b6883a..ee141495c 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcardsFromReturn.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/disallowWildcardsFromReturn.sol @@ -12,11 +12,11 @@ abstract contract C { (,uint m, uint n,) = five(); a;b;c;d;e;f;g;h;i;j;k;l;m;n; } - function one() public pure returns (uint); - function two() public pure returns (uint, uint); - function three() public pure returns (uint, uint, uint); - function four() public pure returns (uint, uint, uint, uint); - function five() public pure returns (uint, uint, uint, uint, uint); + function one() public pure returns (uint) {} + function two() public pure returns (uint, uint) {} + function three() public pure returns (uint, uint, uint) {} + function four() public pure returns (uint, uint, uint, uint) {} + function five() public pure returns (uint, uint, uint, uint, uint) {} } // ---- // TypeError: (62-81): Different number of components on the left hand side (2) than on the right hand side (3). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol index ba901a358..85c78bf30 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol @@ -1,7 +1,7 @@ -contract base { function foo() public; } +contract base { function foo() public virtual; } contract derived { base b; function foo() public { b = new base(); } } // ---- -// TypeError: (0-40): Contract "base" should be marked as abstract. +// TypeError: (0-48): Contract "base" should be marked as abstract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/030_redeclare_implemented_abstract_function_as_abstract.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/030_redeclare_implemented_abstract_function_as_abstract.sol index d18a9a0a8..a29c2f24c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/030_redeclare_implemented_abstract_function_as_abstract.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/030_redeclare_implemented_abstract_function_as_abstract.sol @@ -1,6 +1,5 @@ abstract contract base { function foo() public virtual; } contract derived is base { function foo() public virtual override {} } -contract wrong is derived { function foo() public; } +contract wrong is derived { function foo() public virtual override; } // ---- -// TypeError: (157-179): Overriding function is missing 'override' specifier. -// TypeError: (157-179): Redeclaring an already implemented function as abstract +// TypeError: (157-196): Redeclaring an already implemented function as abstract diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/268_function_overload_array_type.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/268_function_overload_array_type.sol index 659928277..6a713457e 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/268_function_overload_array_type.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/268_function_overload_array_type.sol @@ -1,5 +1,5 @@ abstract contract M { - function f(uint[] memory) public; - function f(int[] memory) public; + function f(uint[] memory) public virtual; + function f(int[] memory) public virtual; } // ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/446_no_unused_warning_abstract_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/446_no_unused_warning_abstract_arguments.sol index e6ae44ea7..636c9a360 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/446_no_unused_warning_abstract_arguments.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/446_no_unused_warning_abstract_arguments.sol @@ -1,4 +1,4 @@ abstract contract C { - function f(uint a) pure public returns (uint b); + function f(uint a) pure public virtual returns (uint b); } // ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/559_no_warning_for_using_members_that_look_like_address_members.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/559_no_warning_for_using_members_that_look_like_address_members.sol index a49a5e358..d4a47ec3c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/559_no_warning_for_using_members_that_look_like_address_members.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/559_no_warning_for_using_members_that_look_like_address_members.sol @@ -1,5 +1,5 @@ abstract contract C { - function transfer(uint) public; + function transfer(uint) public virtual; function f() public { this.transfer(10); } diff --git a/test/libsolidity/syntaxTests/natspec/docstring_empty_description.sol b/test/libsolidity/syntaxTests/natspec/docstring_empty_description.sol index da36f419f..cc8a31f3a 100644 --- a/test/libsolidity/syntaxTests/natspec/docstring_empty_description.sol +++ b/test/libsolidity/syntaxTests/natspec/docstring_empty_description.sol @@ -1,6 +1,6 @@ -abstract contract C { +contract C { /// @param id - function vote(uint id) public; + function vote(uint id) public {} } // ---- // DocstringParsingError: No description given for param id diff --git a/test/libsolidity/syntaxTests/natspec/docstring_empty_tag.sol b/test/libsolidity/syntaxTests/natspec/docstring_empty_tag.sol index e822e89b1..2e2584407 100644 --- a/test/libsolidity/syntaxTests/natspec/docstring_empty_tag.sol +++ b/test/libsolidity/syntaxTests/natspec/docstring_empty_tag.sol @@ -1,6 +1,6 @@ abstract contract C { /// @param - function vote(uint id) public; + function vote(uint id) public {} } // ---- // DocstringParsingError: End of tag @param not found diff --git a/test/libsolidity/syntaxTests/parsing/function_no_body.sol b/test/libsolidity/syntaxTests/parsing/function_no_body.sol index 1de881264..5851d2f61 100644 --- a/test/libsolidity/syntaxTests/parsing/function_no_body.sol +++ b/test/libsolidity/syntaxTests/parsing/function_no_body.sol @@ -1,4 +1,4 @@ abstract contract test { - function functionName(bytes32 input) public returns (bytes32 out); + function functionName(bytes32 input) public virtual returns (bytes32 out); } // ---- diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol index 692bcf5a0..c722ed814 100644 --- a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol +++ b/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol @@ -2,7 +2,7 @@ abstract contract Test { function uint256_to_uint256(uint256 x) internal pure returns (uint256) { return x; } function uint256_to_string(uint256 x) internal pure returns (string memory) { return x == 0 ? "a" : "b"; } - function uint256_to_string_storage(uint256) internal pure returns (string storage); + function uint256_to_string_storage(uint256) internal pure returns (string storage) {} function string_to_uint256(string memory x) internal pure returns (uint256) { return bytes(x).length; } function string_to_string(string memory x) internal pure returns (string memory) { return x; } @@ -33,10 +33,10 @@ abstract contract Test } } // ---- -// TypeError: (1227-1320): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (uint256) pure returns (uint256). -// TypeError: (1328-1434): Type function (uint256) pure returns (string storage pointer) is not implicitly convertible to expected type function (uint256) pure returns (string memory). -// TypeError: (1442-1540): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (string memory) pure returns (uint256). -// TypeError: (1548-1655): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (string memory) pure returns (string memory). -// TypeError: (1664-1775): Type function (uint256) pure returns (uint256) is not implicitly convertible to expected type function (uint256,uint256) pure returns (uint256). -// TypeError: (1783-1902): Type function (string memory) pure returns (string memory) is not implicitly convertible to expected type function (string memory,uint256) pure returns (string memory). -// TypeError: (1910-2034): Type function (string memory) pure returns (string memory) is not implicitly convertible to expected type function (string memory,string memory) pure returns (string memory). +// TypeError: (1229-1322): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (uint256) pure returns (uint256). +// TypeError: (1330-1436): Type function (uint256) pure returns (string storage pointer) is not implicitly convertible to expected type function (uint256) pure returns (string memory). +// TypeError: (1444-1542): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (string memory) pure returns (uint256). +// TypeError: (1550-1657): Type function (uint256) pure returns (string memory) is not implicitly convertible to expected type function (string memory) pure returns (string memory). +// TypeError: (1666-1777): Type function (uint256) pure returns (uint256) is not implicitly convertible to expected type function (uint256,uint256) pure returns (uint256). +// TypeError: (1785-1904): Type function (string memory) pure returns (string memory) is not implicitly convertible to expected type function (string memory,uint256) pure returns (string memory). +// TypeError: (1912-2036): Type function (string memory) pure returns (string memory) is not implicitly convertible to expected type function (string memory,string memory) pure returns (string memory). diff --git a/test/libsolidity/syntaxTests/visibility/interface/interface_contract_function_default.sol b/test/libsolidity/syntaxTests/visibility/interface/interface_contract_function_default.sol index 8c1aa0fda..c0adb47c8 100644 --- a/test/libsolidity/syntaxTests/visibility/interface/interface_contract_function_default.sol +++ b/test/libsolidity/syntaxTests/visibility/interface/interface_contract_function_default.sol @@ -4,9 +4,9 @@ interface I { function f(); } abstract contract C { - function g(); + function g() {} } // ---- // SyntaxError: (158-171): No visibility specified. Did you intend to add "external"? -// SyntaxError: (200-213): No visibility specified. Did you intend to add "public"? +// SyntaxError: (200-215): No visibility specified. Did you intend to add "public"? // TypeError: (158-171): Functions in interfaces must be declared external. From c33d233d881b1dc321e8fe50b04c179c9963e24d Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 3 Dec 2019 10:50:53 +0100 Subject: [PATCH 2/3] Update docs. --- docs/abi-spec.rst | 6 +++--- docs/contracts/abstract-contracts.rst | 2 +- docs/contracts/inheritance.rst | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index c9938cb79..b50017429 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -529,11 +529,11 @@ As an example, the code pragma experimental ABIEncoderV2; - abstract contract Test { + contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } - function f(S memory s, T memory t, uint a) public; - function g() public returns (S memory s, T memory t, uint a); + function f(S memory s, T memory t, uint a) public {} + function g() public returns (S memory s, T memory t, uint a) {} } would result in the JSON: diff --git a/docs/contracts/abstract-contracts.rst b/docs/contracts/abstract-contracts.rst index eab98154f..372c104cb 100644 --- a/docs/contracts/abstract-contracts.rst +++ b/docs/contracts/abstract-contracts.rst @@ -15,7 +15,7 @@ provided (no implementation body ``{ }`` was given).:: pragma solidity >=0.4.0 <0.7.0; abstract contract Feline { - function utterance() public returns (bytes32); + function utterance() public virtual returns (bytes32); } Such abstract contracts can not be instantiated directly. This is also true, if an abstract contract itself does implement diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index 81ad06f44..cd2e3f8fc 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -53,13 +53,13 @@ Details are given in the following example. // without body. If a contract does not implement all // functions it can only be used as an interface. abstract contract Config { - function lookup(uint id) public returns (address adr); + function lookup(uint id) public virtual returns (address adr); } abstract contract NameReg { - function register(bytes32 name) public; - function unregister() public; + function register(bytes32 name) public virtual; + function unregister() public virtual; } From c1505d3f44b7e6baba62de1c67ed569e976ff044 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 3 Dec 2019 10:53:11 +0100 Subject: [PATCH 3/3] Fix solc-js tests. --- test/externalTests/solc-js/DAO/Token.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/solc-js/DAO/Token.sol b/test/externalTests/solc-js/DAO/Token.sol index 10457774d..0e566830f 100644 --- a/test/externalTests/solc-js/DAO/Token.sol +++ b/test/externalTests/solc-js/DAO/Token.sol @@ -87,7 +87,7 @@ virtual returns (bool success); } abstract contract tokenRecipient { - function receiveApproval(address _from, uint256 _value, address _token, bytes memory _extraData) public; + function receiveApproval(address _from, uint256 _value, address _token, bytes memory _extraData) public virtual; } contract Token is TokenInterface {