mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #13971 from ethereum/improve-error-reporting-for-wrong-constructor-arguments
Improve error messages for wrong constructor arguments
This commit is contained in:
commit
e147654f92
@ -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.
|
||||
|
@ -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(
|
||||
|
@ -365,7 +365,7 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
|
||||
toString(arguments->size()) +
|
||||
" arguments given but expected " +
|
||||
toString(parameterTypes.size()) +
|
||||
". Remove parentheses if you do not want to provide arguments here."
|
||||
(arguments->size() == 0 ? ". Remove parentheses if you do not want to provide arguments here." : "")
|
||||
);
|
||||
}
|
||||
for (size_t i = 0; i < std::min(arguments->size(), parameterTypes.size()); ++i)
|
||||
|
@ -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.
|
||||
|
@ -0,0 +1,30 @@
|
||||
contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
contract D is C() {}
|
||||
contract E is C() { constructor() {} }
|
||||
contract F is C() { constructor() C {} }
|
||||
contract G is C() { constructor() C() {} }
|
||||
|
||||
contract H is C {}
|
||||
contract I is C { constructor() {} }
|
||||
contract J is C { constructor() C {} }
|
||||
contract K is C { constructor() C() {} }
|
||||
// ----
|
||||
// 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 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 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.
|
||||
// TypeError 2973: (141-142): Wrong argument count for modifier invocation: 0 arguments given but expected 2.
|
||||
// TypeError 7927: (162-165): Wrong argument count for constructor call: 0 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here.
|
||||
// TypeError 2973: (182-185): Wrong argument count for modifier invocation: 0 arguments given but expected 2.
|
||||
// TypeError 2973: (280-281): Wrong argument count for modifier invocation: 0 arguments given but expected 2.
|
||||
// TypeError 2973: (319-322): Wrong argument count for modifier invocation: 0 arguments given but expected 2.
|
@ -0,0 +1,16 @@
|
||||
abstract contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
abstract contract D is C() {}
|
||||
abstract contract E is C() { constructor() {} }
|
||||
abstract contract F is C() { constructor() C {} }
|
||||
abstract contract G is C() { constructor() C() {} }
|
||||
// ----
|
||||
// DeclarationError 1563: (177-178): Modifier-style base constructor call without arguments.
|
||||
// TypeError 7927: (79-82): 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: (109-112): 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: (157-160): Wrong argument count for constructor call: 0 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here.
|
||||
// TypeError 2973: (177-178): Wrong argument count for modifier invocation: 0 arguments given but expected 2.
|
||||
// TypeError 7927: (207-210): Wrong argument count for constructor call: 0 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here.
|
||||
// TypeError 2973: (227-230): Wrong argument count for modifier invocation: 0 arguments given but expected 2.
|
@ -0,0 +1,6 @@
|
||||
abstract contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
abstract contract D is C {}
|
||||
abstract contract E is C { constructor() {} }
|
@ -0,0 +1,8 @@
|
||||
abstract contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
abstract contract D is C { constructor() C {} }
|
||||
// ----
|
||||
// DeclarationError 1563: (97-98): Modifier-style base constructor call without arguments.
|
||||
// TypeError 2973: (97-98): Wrong argument count for modifier invocation: 0 arguments given but expected 2.
|
@ -0,0 +1,7 @@
|
||||
abstract contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
abstract contract D is C { constructor() C() {} }
|
||||
// ----
|
||||
// TypeError 2973: (97-100): Wrong argument count for modifier invocation: 0 arguments given but expected 2.
|
@ -0,0 +1,13 @@
|
||||
contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
contract D is C(1, true, "a") { constructor() C(1, true, "a") {} }
|
||||
contract E is C(1) { constructor() C(1) {} }
|
||||
// ----
|
||||
// DeclarationError 3364: (93-108): Base constructor arguments given twice.
|
||||
// DeclarationError 3364: (149-153): Base constructor arguments given twice.
|
||||
// TypeError 7927: (61-76): Wrong argument count for constructor call: 3 arguments given but expected 2
|
||||
// TypeError 2973: (93-108): Wrong argument count for modifier invocation: 3 arguments given but expected 2.
|
||||
// TypeError 7927: (128-132): Wrong argument count for constructor call: 1 arguments given but expected 2
|
||||
// TypeError 2973: (149-153): Wrong argument count for modifier invocation: 1 arguments given but expected 2.
|
@ -0,0 +1,9 @@
|
||||
contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
contract D is C(1, true, "a") {}
|
||||
contract E is C(1) {}
|
||||
// ----
|
||||
// TypeError 7927: (61-76): Wrong argument count for constructor call: 3 arguments given but expected 2
|
||||
// TypeError 7927: (94-98): Wrong argument count for constructor call: 1 arguments given but expected 2
|
@ -0,0 +1,9 @@
|
||||
abstract contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
abstract contract D is C(1, true, "a") {}
|
||||
abstract contract E is C(1) {}
|
||||
// ----
|
||||
// TypeError 7927: (79-94): Wrong argument count for constructor call: 3 arguments given but expected 2
|
||||
// TypeError 7927: (121-125): Wrong argument count for constructor call: 1 arguments given but expected 2
|
@ -0,0 +1,11 @@
|
||||
contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
contract D is C() { constructor() C(1, true, "a") {} }
|
||||
contract E is C() { constructor() C(1) {} }
|
||||
// ----
|
||||
// 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 2973: (81-96): Wrong argument count for modifier invocation: 3 arguments given but expected 2.
|
||||
// TypeError 7927: (116-119): Wrong argument count for constructor call: 0 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here.
|
||||
// TypeError 2973: (136-140): Wrong argument count for modifier invocation: 1 arguments given but expected 2.
|
@ -0,0 +1,9 @@
|
||||
contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
contract D is C(1, true, "a") { constructor() {} }
|
||||
contract E is C(1) { constructor() {} }
|
||||
// ----
|
||||
// TypeError 7927: (61-76): Wrong argument count for constructor call: 3 arguments given but expected 2
|
||||
// TypeError 7927: (112-116): Wrong argument count for constructor call: 1 arguments given but expected 2
|
@ -0,0 +1,9 @@
|
||||
contract C {
|
||||
constructor(uint, bool) {}
|
||||
}
|
||||
|
||||
contract D is C { constructor() C(1, true, "a") {} }
|
||||
contract E is C { constructor() C(1) {} }
|
||||
// ----
|
||||
// TypeError 2973: (79-94): Wrong argument count for modifier invocation: 3 arguments given but expected 2.
|
||||
// TypeError 2973: (132-136): Wrong argument count for modifier invocation: 1 arguments given but expected 2.
|
@ -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".
|
||||
|
@ -6,5 +6,5 @@ contract Derived2 is Base {
|
||||
constructor() Base(2) { }
|
||||
}
|
||||
// ----
|
||||
// TypeError 7927: (67-74): Wrong argument count for constructor call: 1 arguments given but expected 2. Remove parentheses if you do not want to provide arguments here.
|
||||
// TypeError 7927: (67-74): Wrong argument count for constructor call: 1 arguments given but expected 2
|
||||
// TypeError 2973: (123-130): Wrong argument count for modifier invocation: 1 arguments given but expected 2.
|
||||
|
@ -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.
|
||||
|
@ -1,4 +1,4 @@
|
||||
contract A { constructor(uint a) { } }
|
||||
contract B is 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.
|
||||
|
@ -1,4 +1,4 @@
|
||||
interface I {}
|
||||
contract C is I(2) {}
|
||||
// ----
|
||||
// TypeError 7927: (29-33): Wrong argument count for constructor call: 1 arguments given but expected 0. Remove parentheses if you do not want to provide arguments here.
|
||||
// TypeError 7927: (29-33): Wrong argument count for constructor call: 1 arguments given but expected 0
|
||||
|
Loading…
Reference in New Issue
Block a user