diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 7996fd71137b..a426b8af93dd 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -30,6 +30,7 @@ #include +#include #include using namespace solidity; @@ -116,19 +117,22 @@ void ContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinition const& ); } - for (auto const* ancestorContract: _contract.annotation().linearizedBaseContracts | ranges::views::reverse) + for (auto const& baseContractSpecifier: _contract.baseContracts()) { - if (*ancestorContract == _contract) - continue; - if (ancestorContract->storageLayoutSpecifier()) + auto const* baseContract = dynamic_cast( + baseContractSpecifier->name().annotation().referencedDeclaration + ); + + solAssert(baseContract); + if (baseContract->storageLayoutSpecifier()) m_errorReporter.typeError( 8894_error, - _contract.location(), + baseContractSpecifier->location(), SecondarySourceLocation().append( - "Storage layout was already specified here.", - ancestorContract->storageLayoutSpecifier()->location() + "Custom storage layout defined here:", + baseContract->storageLayoutSpecifier()->location() ), - "Storage layout can only be specified in the most derived contract." + "Cannot inherit from a contract with a custom storage layout." ); } } diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err index a5ad279544f2..6d5d1dc46c36 100644 --- a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err @@ -1,20 +1,9 @@ -Error: Storage layout can only be specified in the most derived contract. - --> :5:1: +Error: Cannot inherit from a contract with a custom storage layout. + --> :5:15: | 5 | contract B is A {} - | ^^^^^^^^^^^^^^^^^^ -Note: Storage layout was already specified here. - --> :4:12: - | -4 | contract A layout at 0x1234 {} - | ^^^^^^^^^^^^^^^^ - -Error: Storage layout can only be specified in the most derived contract. - --> :6:1: - | -6 | contract C layout at 0x1234 is B {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Note: Storage layout was already specified here. + | ^ +Note: Custom storage layout defined here: --> :4:12: | 4 | contract A layout at 0x1234 {} diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol index d525d92066a0..3d60cc38d51a 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol @@ -4,5 +4,4 @@ contract B is A {} contract C is B layout at 0xABCD {} // ---- -// TypeError 8894: (32-50): Storage layout can only be specified in the most derived contract. -// TypeError 8894: (52-87): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (46-47): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol new file mode 100644 index 000000000000..3b1cf05ce321 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol @@ -0,0 +1,13 @@ +==== Source: C ==== +import "M" as M; +import "N" as N; + +contract C is M.A, N.A layout at 0xABCD {} +==== Source: M ==== +contract A layout at 0x1234 {} + +==== Source: N ==== +contract A {} + +// ---- +// TypeError 8894: (C:49-52): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol new file mode 100644 index 000000000000..8b41095fb51d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol @@ -0,0 +1,16 @@ +contract A layout at 1 {} +contract B is A layout at 2 {} + +contract C1 is B {} +contract C2 is A, B {} +contract C3 is B {} + +contract D1 is C1 {} +contract D2 is C2 {} +contract D3 is C3 {} +// ---- +// TypeError 8894: (40-41): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (73-74): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (93-94): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (96-97): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (116-117): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol index 77b1ed617c08..69df5d7752c3 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol @@ -3,6 +3,4 @@ contract B is A {} contract C is B {} contract D is C {} // ---- -// TypeError 8894: (27-45): Storage layout can only be specified in the most derived contract. -// TypeError 8894: (46-64): Storage layout can only be specified in the most derived contract. -// TypeError 8894: (65-83): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (41-42): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol index 0c42f3550a44..d2ac0e931d0d 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol @@ -3,4 +3,4 @@ contract B is A {} contract C is B layout at 42 {} contract D is C {} // ---- -// TypeError 8894: (65-83): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (79-80): Cannot inherit from a contract with a custom storage layout.