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))``. * Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``.
* Make your fallback functions ``external``. * 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 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: 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: 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: 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: 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. * 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. * 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. * 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)) for (auto const& addressMember: IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr))
if (addressMember.name == memberName) if (addressMember.name == memberName)
{ {
Identifier const& var = dynamic_cast<Identifier const&>(_memberAccess.expression()); Identifier const* var = dynamic_cast<Identifier const*>(&_memberAccess.expression());
errorMsg += " Use \"address(" + var.name() + ")." + memberName + "\" to access this address member."; string varName = var ? var->name() : "...";
errorMsg += " Use \"address(" + varName + ")." + memberName + "\" to access this address member.";
break; break;
} }
m_errorReporter.fatalTypeError( m_errorReporter.fatalTypeError(

View File

@ -1214,63 +1214,52 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
switch (_memberAccess.expression().annotation().type->category()) switch (_memberAccess.expression().annotation().type->category())
{ {
case Type::Category::Contract: case Type::Category::Contract:
case Type::Category::Integer:
{ {
bool alsoSearchInteger = false; ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type);
if (_memberAccess.expression().annotation().type->category() == Type::Category::Contract) if (type.isSuper())
{ {
ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type); solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved.");
if (type.isSuper()) utils().pushCombinedFunctionEntryLabel(m_context.superFunction(
{ dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration),
solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved."); type.contractDefinition()
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 else
{ solAssert(false, "Contract member is neither variable nor function.");
// ordinary contract type utils().convertType(type, IntegerType(160, IntegerType::Modifier::Address), true);
if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration) m_context << identifier;
{
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;
}
} }
else else
alsoSearchInteger = true; solAssert(false, "Invalid member access in contract");
break;
if (alsoSearchInteger) }
case Type::Category::Integer:
{
if (member == "balance")
{ {
if (member == "balance") utils().convertType(
{ *_memberAccess.expression().annotation().type,
utils().convertType( IntegerType(160, IntegerType::Modifier::Address),
*_memberAccess.expression().annotation().type, true
IntegerType(160, IntegerType::Modifier::Address), );
true m_context << Instruction::BALANCE;
);
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");
} }
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; break;
} }
case Type::Category::Function: 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.