diff --git a/Changelog.md b/Changelog.md index 2a849b455..95095b102 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: + * ContractLevelChecker: Properly distinguish the case of missing base constructor arguments from having an unimplemented base function. * SMTChecker: Fix internal error when using the custom NatSpec annotation to abstract free functions. * TypeChecker: Also allow external library functions in ``using for``. * SMTChecker: Fix internal error caused by unhandled ``z3`` expressions that come from the solver when bitwise operators are used. diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 9ecf76f13..e7e7041a0 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include using namespace std; @@ -284,9 +286,6 @@ void ContractLevelChecker::checkAbstractDefinitions(ContractDefinition const& _c } // Set to not fully implemented if at least one flag is false. - // Note that `_contract.annotation().unimplementedDeclarations` has already been - // pre-filled by `checkBaseConstructorArguments`. - // for (auto const& proxy: proxies) if (proxy.unimplemented()) _contract.annotation().unimplementedDeclarations->push_back(proxy.declaration()); @@ -362,11 +361,27 @@ void ContractLevelChecker::checkBaseConstructorArguments(ContractDefinition cons // check that we get arguments for all base constructors that need it. // If not mark the contract as abstract (not fully implemented) - for (ContractDefinition const* contract: bases) - if (FunctionDefinition const* constructor = contract->constructor()) - if (contract != &_contract && !constructor->parameters().empty()) - if (!_contract.annotation().baseConstructorArguments.count(constructor)) - _contract.annotation().unimplementedDeclarations->push_back(constructor); + if (_contract.contractKind() == ContractKind::Contract && !_contract.abstract()) + for (ContractDefinition const* baseContract: bases) + if (FunctionDefinition const* baseConstructor = baseContract->constructor()) + if ( + baseContract != &_contract && + !baseConstructor->parameters().empty() && + _contract.annotation().baseConstructorArguments.count(baseConstructor) == 0 + ) + m_errorReporter.typeError( + 3415_error, + _contract.location(), + SecondarySourceLocation{}.append( + "Base constructor parameters:", + baseConstructor->parameterList().location() + ), + fmt::format( + "No arguments passed to the base constructor. " + "Specify the arguments or mark \"{}\" as abstract.", + *_contract.annotation().canonicalName + ) + ); } void ContractLevelChecker::annotateBaseConstructorArguments( diff --git a/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol b/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol index 491c688cc..144b3141a 100644 --- a/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol +++ b/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol @@ -12,4 +12,4 @@ contract Parent { contract Child is Parent { } // ---- -// TypeError 3656: (226-254): Contract "Child" should be marked as abstract. +// TypeError 3415: (226-254): No arguments passed to the base constructor. Specify the arguments or mark "Child" as abstract. diff --git a/test/libsolidity/syntaxTests/constructor/base_constructor_missing_arguments.sol b/test/libsolidity/syntaxTests/constructor/base_constructor_missing_arguments.sol index 2432d7e73..5a005c160 100644 --- a/test/libsolidity/syntaxTests/constructor/base_constructor_missing_arguments.sol +++ b/test/libsolidity/syntaxTests/constructor/base_constructor_missing_arguments.sol @@ -12,14 +12,14 @@ contract I is C { constructor() {} } contract J is C { constructor() C {} } contract K is C { constructor() C() {} } // ---- -// TypeError 3656: (47-67): Contract "D" should be marked as abstract. -// TypeError 3656: (68-106): Contract "E" should be marked as abstract. +// TypeError 3415: (47-67): No arguments passed to the base constructor. Specify the arguments or mark "D" as abstract. +// TypeError 3415: (68-106): No arguments passed to the base constructor. Specify the arguments or mark "E" as abstract. // DeclarationError 1563: (141-142): Modifier-style base constructor call without arguments. -// TypeError 3656: (107-147): Contract "F" should be marked as abstract. -// TypeError 3656: (192-210): Contract "H" should be marked as abstract. -// TypeError 3656: (211-247): Contract "I" should be marked as abstract. +// TypeError 3415: (107-147): No arguments passed to the base constructor. Specify the arguments or mark "F" as abstract. +// TypeError 3415: (192-210): No arguments passed to the base constructor. Specify the arguments or mark "H" as abstract. +// TypeError 3415: (211-247): No arguments passed to the base constructor. Specify the arguments or mark "I" as abstract. // DeclarationError 1563: (280-281): Modifier-style base constructor call without arguments. -// TypeError 3656: (248-286): Contract "J" should be marked as abstract. +// TypeError 3415: (248-286): No arguments passed to the base constructor. Specify the arguments or mark "J" as abstract. // TypeError 7927: (61-64): Wrong argument count for constructor call: 0 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here. // TypeError 7927: (82-85): Wrong argument count for constructor call: 0 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here. // TypeError 7927: (121-124): Wrong argument count for constructor call: 0 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here. diff --git a/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol b/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol index 0175e22f7..5992dfa4c 100644 --- a/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol +++ b/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol @@ -9,5 +9,5 @@ contract B is A { } } // ---- -// TypeError 3656: (124-303): Contract "B" should be marked as abstract. +// TypeError 3415: (124-303): No arguments passed to the base constructor. Specify the arguments or mark "B" as abstract. // TypeError 9640: (252-256): Explicit type conversion not allowed from "string memory" to "contract A". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol index 0e123ae23..83119653b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol @@ -1,4 +1,4 @@ contract A { constructor(uint a) { } } contract B is A { } // ---- -// TypeError 3656: (39-58): Contract "B" should be marked as abstract. +// TypeError 3415: (39-58): No arguments passed to the base constructor. Specify the arguments or mark "B" as abstract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol index 181364fed..bdca8fdd3 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol @@ -1,4 +1,4 @@ contract A { constructor(uint a) { } } contract B is A { constructor(bytes4 a, bytes28 b) { } } // ---- -// TypeError 3656: (39-58): Contract "B" should be marked as abstract. +// TypeError 3415: (39-95): No arguments passed to the base constructor. Specify the arguments or mark "B" as abstract.