Changes in ExpressionCompiler

This commit is contained in:
Leonardo Alt 2018-07-18 19:51:24 +02:00
parent 25fa1142bc
commit faa9c221d4
4 changed files with 50 additions and 54 deletions

View File

@ -5,7 +5,7 @@ How to update your code:
* Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``.
* Make your fallback functions ``external``.
* Explicitly state the storage location for local variables of struct and array types, e.g. change ``uint[] x = m_x`` to ``uint[] storage x = m_x``.
* Explicitly convert ``contract`` to ``address`` before using an ``address`` member. Example: if ``c`` is a variable of type ``contract``, change ``c.transfer(...)`` to ``address(c).transfer(...)``.
* Explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``.
Breaking Changes:
@ -47,7 +47,7 @@ Breaking Changes:
* Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``.
* Type Checker: Fallback function must be external. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode.
* Type Checker: ``Contract`` does not have access to ``address`` members anymore. An explicit conversion is now required before invoking an ``address`` member from a ``contract``.
* Type Checker: Address members are not included in contract types anymore. An explicit conversion is now required before invoking an ``address`` member from a contract.
* Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible.
* References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode.
* Syntax Checker: Named return values in function types are an error.

View File

@ -1957,8 +1957,9 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
for (auto const& addressMember: IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr))
if (addressMember.name == memberName)
{
Identifier const& var = dynamic_cast<Identifier const&>(_memberAccess.expression());
errorMsg += " Use \"address(" + var.name() + ")." + memberName + "\" to access this address member.";
Identifier const* var = dynamic_cast<Identifier const*>(&_memberAccess.expression());
string varName = var ? var->name() : "...";
errorMsg += " Use \"address(" + varName + ")." + memberName + "\" to access this address member.";
break;
}
m_errorReporter.fatalTypeError(

View File

@ -1214,63 +1214,52 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
switch (_memberAccess.expression().annotation().type->category())
{
case Type::Category::Contract:
case Type::Category::Integer:
{
bool alsoSearchInteger = false;
if (_memberAccess.expression().annotation().type->category() == Type::Category::Contract)
ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type);
if (type.isSuper())
{
ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type);
if (type.isSuper())
{
solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved.");
utils().pushCombinedFunctionEntryLabel(m_context.superFunction(
dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration),
type.contractDefinition()
));
}
solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved.");
utils().pushCombinedFunctionEntryLabel(m_context.superFunction(
dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration),
type.contractDefinition()
));
}
// ordinary contract type
else if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration)
{
u256 identifier;
if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration))
identifier = FunctionType(*variable).externalIdentifier();
else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration))
identifier = FunctionType(*function).externalIdentifier();
else
{
// ordinary contract type
if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration)
{
u256 identifier;
if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration))
identifier = FunctionType(*variable).externalIdentifier();
else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration))
identifier = FunctionType(*function).externalIdentifier();
else
solAssert(false, "Contract member is neither variable nor function.");
utils().convertType(type, IntegerType(160, IntegerType::Modifier::Address), true);
m_context << identifier;
}
else
// not found in contract, search in members inherited from address
alsoSearchInteger = true;
}
solAssert(false, "Contract member is neither variable nor function.");
utils().convertType(type, IntegerType(160, IntegerType::Modifier::Address), true);
m_context << identifier;
}
else
alsoSearchInteger = true;
if (alsoSearchInteger)
solAssert(false, "Invalid member access in contract");
break;
}
case Type::Category::Integer:
{
if (member == "balance")
{
if (member == "balance")
{
utils().convertType(
*_memberAccess.expression().annotation().type,
IntegerType(160, IntegerType::Modifier::Address),
true
);
m_context << Instruction::BALANCE;
}
else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall"}).count(member))
utils().convertType(
*_memberAccess.expression().annotation().type,
IntegerType(160, IntegerType::Modifier::Address),
true
);
else
solAssert(false, "Invalid member access to integer");
utils().convertType(
*_memberAccess.expression().annotation().type,
IntegerType(160, IntegerType::Modifier::Address),
true
);
m_context << Instruction::BALANCE;
}
else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall"}).count(member))
utils().convertType(
*_memberAccess.expression().annotation().type,
IntegerType(160, IntegerType::Modifier::Address),
true
);
else
solAssert(false, "Invalid member access to integer");
break;
}
case Type::Category::Function:

View File

@ -0,0 +1,6 @@
contract C {
function f() public returns (C) { return this; }
function g() public returns (uint) { return f().balance(); }
}
// ----
// TypeError: (114-125): Member "balance" not found or not visible after argument-dependent lookup in contract C. Use "address(...).balance" to access this address member.