Merge pull request #3875 from ethereum/constructorSelfRef

Stricter check for "this" in constructor.
This commit is contained in:
chriseth 2018-04-13 18:39:31 +02:00 committed by GitHub
commit 95c49b367e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 4 deletions

View File

@ -206,10 +206,32 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
);
}
if (m_constructor && m_currentContract)
if (ContractType const* type = dynamic_cast<ContractType const*>(_memberAccess.expression().annotation().type.get()))
if (type->contractDefinition() == *m_currentContract)
m_errorReporter.warning(_memberAccess.location(), "\"this\" used in constructor.");
if (m_constructor)
{
auto const* expr = &_memberAccess.expression();
while(expr)
{
if (auto id = dynamic_cast<Identifier const*>(expr))
{
if (id->name() == "this")
m_errorReporter.warning(
id->location(),
"\"this\" used in constructor. "
"Note that external functions of a contract "
"cannot be called while it is being constructed.");
break;
}
else if (auto tuple = dynamic_cast<TupleExpression const*>(expr))
{
if (tuple->components().size() == 1)
expr = tuple->components().front().get();
else
break;
}
else
break;
}
}
return true;
}

View File

@ -0,0 +1,12 @@
contract C {
function f() public pure {}
constructor() public {
C c = this;
c.f(); // this does not warn now, but should warn in the future
this.f();
(this).f();
}
}
// ----
// Warning: (172-176): "this" used in constructor. Note that external functions of a contract cannot be called while it is being constructed.
// Warning: (191-195): "this" used in constructor. Note that external functions of a contract cannot be called while it is being constructed.

View File

@ -0,0 +1,28 @@
contract A {
function a() public pure {
}
}
contract B {
constructor(address) public {
}
function b(address) public returns (A) {
return new A();
}
}
contract C {
B m_b;
C m_c;
constructor(C other_c) public {
m_c = other_c;
m_b = new B(this);
m_b.b(this).a();
g(this).f();
other_c.f();
m_c.f();
}
function f() public pure {
}
function g(C) public view returns (C) {
return m_c;
}
}

View File

@ -0,0 +1,10 @@
contract A {
function x() pure internal {}
}
contract B is A {
constructor() public {
// used to trigger warning about using ``this`` in constructor
super.x();
}
}