diff --git a/Changelog.md b/Changelog.md index 61a6c693e..c87a53807 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Breaking Changes: * Commandline interface: Remove obsolete ``--formal`` option. * Commandline interface: Require ``-`` if standard input is used as source. * General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code. + * General: Disallow declaring empty structs. * General: Disallow ``sha3`` and ``suicide`` aliases. * General: Introduce ``emit`` as a keyword instead of parsing it as identifier. * General: New keywords: ``calldata`` diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 396058f44..f234dcaff 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -276,14 +276,8 @@ bool SyntaxChecker::visit(VariableDeclaration const& _declaration) bool SyntaxChecker::visit(StructDefinition const& _struct) { - bool const v050 = m_sourceUnit->annotation().experimentalFeatures.count(ExperimentalFeature::V050); - if (_struct.members().empty()) - { - if (v050) - m_errorReporter.syntaxError(_struct.location(), "Defining empty structs is disallowed."); - else - m_errorReporter.warning(_struct.location(), "Defining empty structs is deprecated."); - } + m_errorReporter.syntaxError(_struct.location(), "Defining empty structs is disallowed."); + return true; } diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index b3ebb7a5b..b588ca1b3 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -659,26 +659,6 @@ BOOST_AUTO_TEST_CASE(struct_function) ) } -BOOST_AUTO_TEST_CASE(empty_struct) -{ - string sourceCode = R"( - contract C { - struct S { } - function f(uint a, S s, uint b) public pure returns (uint x, uint y) { - assembly { x := a y := b } - } - function g() public returns (uint, uint) { - return this.f(7, S(), 8); - } - } - )"; - NEW_ENCODER( - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("f(uint256,(),uint256)", 7, 8), encodeArgs(7, 8)); - ABI_CHECK(callContractFunction("g()"), encodeArgs(7, 8)); - ) -} - BOOST_AUTO_TEST_CASE(mediocre_struct) { string sourceCode = R"( diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 5f15b28fa..227eadb5c 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -447,28 +447,6 @@ BOOST_AUTO_TEST_CASE(structs) ) } -BOOST_AUTO_TEST_CASE(empty_struct) -{ - string sourceCode = R"( - contract C { - struct S { } - S s; - event e(uint16, S, uint16); - function f() returns (uint, S, uint) { - e(7, s, 8); - return (7, s, 8); - } - } - )"; - - NEW_ENCODER( - compileAndRun(sourceCode, 0, "C"); - bytes encoded = encodeArgs(7, 8); - BOOST_CHECK(callContractFunction("f()") == encoded); - REQUIRE_LOG_DATA(encoded); - ) -} - BOOST_AUTO_TEST_CASE(structs2) { string sourceCode = R"( diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 236d83ef6..c80aa8ba1 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1271,7 +1271,6 @@ BOOST_AUTO_TEST_CASE(deleteStruct) contract test { struct topStruct { nestedStruct nstr; - emptyStruct empty; uint topValue; mapping (uint => uint) topMapping; } @@ -1281,8 +1280,6 @@ BOOST_AUTO_TEST_CASE(deleteStruct) uint nestedValue; mapping (uint => bool) nestedMapping; } - struct emptyStruct{ - } function test(){ toDelete = 5; str.topValue = 1; diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index e1516f845..bca66d01c 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -203,10 +203,10 @@ BOOST_AUTO_TEST_CASE(external_structs) pragma experimental ABIEncoderV2; contract Test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - struct Empty {} + struct Simple { uint i; } struct Nested { X[2][] a; uint y; } - struct X { bytes32 x; Test t; Empty[] e; } - function f(ActionChoices, uint, Empty) external {} + struct X { bytes32 x; Test t; Simple[] s; } + function f(ActionChoices, uint, Simple) external {} function g(Test, Nested) external {} function h(function(Nested) external returns (uint)[]) external {} function i(Nested[]) external {} @@ -218,10 +218,10 @@ BOOST_AUTO_TEST_CASE(external_structs) { auto functions = contract->definedFunctions(); BOOST_REQUIRE(!functions.empty()); - BOOST_CHECK_EQUAL("f(uint8,uint256,())", functions[0]->externalSignature()); - BOOST_CHECK_EQUAL("g(address,((bytes32,address,()[])[2][],uint256))", functions[1]->externalSignature()); + BOOST_CHECK_EQUAL("f(uint8,uint256,(uint256))", functions[0]->externalSignature()); + BOOST_CHECK_EQUAL("g(address,((bytes32,address,(uint256)[])[2][],uint256))", functions[1]->externalSignature()); BOOST_CHECK_EQUAL("h(function[])", functions[2]->externalSignature()); - BOOST_CHECK_EQUAL("i(((bytes32,address,()[])[2][],uint256)[])", functions[3]->externalSignature()); + BOOST_CHECK_EQUAL("i(((bytes32,address,(uint256)[])[2][],uint256)[])", functions[3]->externalSignature()); } } @@ -231,10 +231,10 @@ BOOST_AUTO_TEST_CASE(external_structs_in_libraries) pragma experimental ABIEncoderV2; library Test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - struct Empty {} + struct Simple { uint i; } struct Nested { X[2][] a; uint y; } - struct X { bytes32 x; Test t; Empty[] e; } - function f(ActionChoices, uint, Empty) external {} + struct X { bytes32 x; Test t; Simple[] s; } + function f(ActionChoices, uint, Simple) external {} function g(Test, Nested) external {} function h(function(Nested) external returns (uint)[]) external {} function i(Nested[]) external {} @@ -246,7 +246,7 @@ BOOST_AUTO_TEST_CASE(external_structs_in_libraries) { auto functions = contract->definedFunctions(); BOOST_REQUIRE(!functions.empty()); - BOOST_CHECK_EQUAL("f(Test.ActionChoices,uint256,Test.Empty)", functions[0]->externalSignature()); + BOOST_CHECK_EQUAL("f(Test.ActionChoices,uint256,Test.Simple)", functions[0]->externalSignature()); BOOST_CHECK_EQUAL("g(Test,Test.Nested)", functions[1]->externalSignature()); BOOST_CHECK_EQUAL("h(function[])", functions[2]->externalSignature()); BOOST_CHECK_EQUAL("i(Test.Nested[])", functions[3]->externalSignature()); diff --git a/test/libsolidity/syntaxTests/empty_struct.sol b/test/libsolidity/syntaxTests/empty_struct.sol index 12655309f..0a52fb729 100644 --- a/test/libsolidity/syntaxTests/empty_struct.sol +++ b/test/libsolidity/syntaxTests/empty_struct.sol @@ -2,4 +2,4 @@ contract test { struct A {} } // ---- -// Warning: (17-28): Defining empty structs is deprecated. +// SyntaxError: (17-28): Defining empty structs is disallowed. diff --git a/test/libsolidity/syntaxTests/empty_struct_050.sol b/test/libsolidity/syntaxTests/empty_struct_050.sol deleted file mode 100644 index 886f1f838..000000000 --- a/test/libsolidity/syntaxTests/empty_struct_050.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - struct A {} -} -// ---- -// SyntaxError: (47-58): Defining empty structs is disallowed. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/039_functions_with_identical_structs_in_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/039_functions_with_identical_structs_in_interface.sol index df4f5879c..0be0bb2b3 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/039_functions_with_identical_structs_in_interface.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/039_functions_with_identical_structs_in_interface.sol @@ -1,13 +1,11 @@ pragma experimental ABIEncoderV2; contract C { - struct S1 { } - struct S2 { } + struct S1 { int i; } + struct S2 { int i; } function f(S1) pure {} function f(S2) pure {} } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// Warning: (52-65): Defining empty structs is deprecated. -// Warning: (70-83): Defining empty structs is deprecated. -// TypeError: (115-137): Function overload clash during conversion to external types for arguments. +// TypeError: (129-151): Function overload clash during conversion to external types for arguments. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol index 2afef06c5..c74d52d3c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/419_interface_structs.sol @@ -1,7 +1,9 @@ interface I { struct A { + // This is currently expected to break, but it *may* change in the future. + int dummy; } } // ---- -// Warning: (18-34): Defining empty structs is deprecated. -// TypeError: (18-34): Structs cannot be defined in interfaces. +// TypeError: (18-136): Structs cannot be defined in interfaces. +// TypeError: (120-129): Variables cannot be declared in interfaces. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol index d10c17187..e46a90503 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol @@ -1,7 +1,7 @@ contract C { struct S { uint x; } S s; - struct T { } + struct T { uint y; } T t; enum A { X, Y } function f() public pure { @@ -9,9 +9,8 @@ contract C { } } // ---- -// Warning: (51-63): Defining empty structs is deprecated. -// TypeError: (168-169): This type cannot be encoded. -// TypeError: (171-172): This type cannot be encoded. +// TypeError: (176-177): This type cannot be encoded. // TypeError: (179-180): This type cannot be encoded. -// TypeError: (182-186): This type cannot be encoded. -// TypeError: (188-194): This type cannot be encoded. +// TypeError: (187-188): This type cannot be encoded. +// TypeError: (190-194): This type cannot be encoded. +// TypeError: (196-202): This type cannot be encoded.