Error on duplicated super constructor calls

This commit is contained in:
Federico Bond 2017-12-11 18:00:15 -03:00 committed by Daniel Kirchner
parent fe61435c27
commit 4e037281ac
7 changed files with 55 additions and 9 deletions

View File

@ -28,6 +28,7 @@ Bugfixes:
* Type System: Make external library functions accessible.
* Type System: Prevent encoding of weird types.
* Static Analyzer: Fix non-deterministic order of unused variable warnings.
* Static Analyzer: Error on duplicated super constructor calls.
### 0.4.21 (2018-03-07)

View File

@ -1034,9 +1034,12 @@ the base constructors. This can be done in two ways::
constructor(uint _x) public { x = _x; }
}
contract Derived is Base(7) {
constructor(uint _y) Base(_y * _y) public {
}
contract Derived1 is Base(7) {
constructor(uint _y) public {}
}
contract Derived2 is Base {
constructor(uint _y) Base(_y * _y) public {}
}
One way is directly in the inheritance list (``is Base(7)``). The other is in
@ -1046,8 +1049,9 @@ do it is more convenient if the constructor argument is a
constant and defines the behaviour of the contract or
describes it. The second way has to be used if the
constructor arguments of the base depend on those of the
derived contract. If, as in this silly example, both places
are used, the modifier-style argument takes precedence.
derived contract. Arguments have to be given either in the
inheritance list or in modifier-style in the derived constuctor.
Specifying arguments in both places is an error.
.. index:: ! inheritance;multiple, ! linearization, ! C3 linearization

View File

@ -90,6 +90,38 @@ void StaticAnalyzer::endVisit(FunctionDefinition const&)
m_localVarUseCount.clear();
}
bool modifierOverridesInheritanceSpecifier(
ContractDefinition const* _contract,
ModifierInvocation const& _modifier,
InheritanceSpecifier const& _specifier
)
{
auto parent = _specifier.name().annotation().referencedDeclaration;
return _contract == parent && (!_specifier.arguments().empty() || _modifier.arguments().empty());
}
bool StaticAnalyzer::visit(ModifierInvocation const& _modifier)
{
if (!m_constructor)
return true;
if (auto contract = dynamic_cast<ContractDefinition const*>(_modifier.name()->annotation().referencedDeclaration))
for (auto const& specifier: m_currentContract->baseContracts())
if (modifierOverridesInheritanceSpecifier(contract, _modifier, *specifier))
{
SecondarySourceLocation ssl;
ssl.append("Overriden constructor call is here:", specifier->location());
m_errorReporter.declarationError(
_modifier.location(),
ssl,
"Duplicated super constructor call."
);
}
return true;
}
bool StaticAnalyzer::visit(Identifier const& _identifier)
{
if (m_currentFunction)

View File

@ -57,6 +57,7 @@ private:
virtual bool visit(FunctionDefinition const& _function) override;
virtual void endVisit(FunctionDefinition const& _function) override;
virtual bool visit(ModifierInvocation const& _modifier) override;
virtual bool visit(ExpressionStatement const& _statement) override;
virtual bool visit(VariableDeclaration const& _variable) override;

View File

@ -5191,7 +5191,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base)
}
uint public m_i;
}
contract Derived is Base(2) {
contract Derived is Base {
function Derived(uint i) Base(i)
{}
}
@ -5211,10 +5211,10 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base)
}
uint public m_i;
}
contract Base1 is Base(3) {
contract Base1 is Base {
function Base1(uint k) Base(k*k) {}
}
contract Derived is Base(3), Base1(2) {
contract Derived is Base, Base1 {
function Derived(uint i) Base(i) Base1(i)
{}
}
@ -5235,7 +5235,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap)
uint public m_i;
}
contract Base1 is Base(3) {}
contract Derived is Base(2), Base1 {
contract Derived is Base, Base1 {
function Derived(uint i) Base(i) {}
}
contract Final is Derived(4) {

View File

@ -0,0 +1,4 @@
contract A { constructor(uint) public { } }
contract B is A(2) { constructor() A(3) public { } }
// ----
// DeclarationError: Duplicated super constructor call.

View File

@ -0,0 +1,4 @@
contract A { constructor() public { } }
contract B is A { constructor() A() public { } }
// ----
// DeclarationError: Duplicated super constructor call.