Allow duplicated constructor calls, if no arguments; support for multiple inheritance; backwards compatibility.

# tmp
This commit is contained in:
Daniel Kirchner 2018-04-04 12:28:22 +02:00
parent 4e037281ac
commit b8fdb666e2
10 changed files with 70 additions and 27 deletions

View File

@ -9,6 +9,7 @@ Features:
* Optimizer: Remove useless ``SWAP1`` instruction preceding a commutative instruction (such as ``ADD``, ``MUL``, etc).
* Optimizer: Replace comparison operators (``LT``, ``GT``, etc) with opposites if preceded by ``SWAP1``, e.g. ``SWAP1 LT`` is replaced with ``GT``.
* Optimizer: Optimize across ``mload`` if ``msize()`` is not used.
* Static Analyzer: Error on duplicated super constructor calls as experimental 0.5.0 feature.
* Syntax Checker: Issue warning for empty structs (or error as experimental 0.5.0 feature).
* General: Introduce new constructor syntax using the ``constructor`` keyword as experimental 0.5.0 feature.
* Inheritance: Error when using empty parenthesis for base class constructors that require arguments as experimental 0.5.0 feature.
@ -28,7 +29,6 @@ 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

@ -90,33 +90,43 @@ 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());
bool const v050 = m_currentContract->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
m_errorReporter.declarationError(
_modifier.location(),
ssl,
"Duplicated super constructor call."
);
if (auto contract = dynamic_cast<ContractDefinition const*>(_modifier.name()->annotation().referencedDeclaration))
for (auto const& base: m_currentContract->annotation().linearizedBaseContracts)
for (auto const& specifier: base->baseContracts())
{
Declaration const* parent = specifier->name().annotation().referencedDeclaration;
if (contract == parent && !specifier->arguments().empty())
{
if (v050)
{
SecondarySourceLocation ssl;
ssl.append("Second constructor call is here:", specifier->location());
m_errorReporter.declarationError(
_modifier.location(),
ssl,
"Duplicated super constructor call."
);
}
else
{
SecondarySourceLocation ssl;
ssl.append("Overridden constructor call is here:", specifier->location());
m_errorReporter.warning(
_modifier.location(),
"Duplicated super constructor calls are deprecated.",
ssl
);
}
}
}
return true;

View File

@ -0,0 +1,3 @@
contract A { constructor() public { } }
contract B1 is A { constructor() A() public { } }
contract B2 is A { constructor() A public { } }

View File

@ -0,0 +1,9 @@
contract Base {
constructor(uint) public { }
}
contract Base1 is Base(3) {}
contract Derived is Base, Base1 {
constructor(uint i) Base(i) public {}
}
// ----
// Warning: Duplicated super constructor calls are deprecated.

View File

@ -0,0 +1,5 @@
contract A { constructor(uint) public { } }
contract B is A(2) { constructor() public { } }
contract C is B { constructor() A(3) public { } }
// ----
// Warning: Duplicated super constructor calls are deprecated.

View File

@ -0,0 +1,7 @@
pragma experimental "v0.5.0";
contract A { constructor(uint) public { } }
contract B is A(2) { constructor() public { } }
contract C is B { constructor() A(3) public { } }
// ----
// DeclarationError: Duplicated super constructor call.

View File

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

View File

@ -0,0 +1,6 @@
pragma experimental "v0.5.0";
contract A { constructor(uint) public { } }
contract B is A(2) { constructor() A(3) public { } }
// ----
// DeclarationError: Duplicated super constructor call.

View File

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

View File

@ -0,0 +1,7 @@
contract C { constructor(uint) public {} }
contract A is C(2) {}
contract B is C(2) {}
contract D is A, B { constructor() C(3) public {} }
// ----
// Warning: Duplicated super constructor calls are deprecated.
// Warning: Duplicated super constructor calls are deprecated.