Fix missing base constructor arguments being treated as an unimplemented function

This commit is contained in:
Kamil Śliwak 2023-02-13 20:18:08 +01:00
parent bc3cbfa18d
commit 73183d3df9
7 changed files with 34 additions and 18 deletions

View File

@ -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.

View File

@ -28,6 +28,8 @@
#include <libsolutil/FunctionSelector.h>
#include <liblangutil/ErrorReporter.h>
#include <fmt/format.h>
#include <range/v3/view/reverse.hpp>
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(

View File

@ -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.

View File

@ -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.

View File

@ -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".

View File

@ -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.

View File

@ -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.