Merge pull request #1474 from ethereum/event-lookup-base-name

Event lookup with base name
This commit is contained in:
chriseth 2017-01-03 14:11:41 +01:00 committed by GitHub
commit c8ba7f5278
4 changed files with 61 additions and 9 deletions

View File

@ -1,5 +1,8 @@
### 0.4.8 (unreleased)
BugFixes:
* Type checker, code generator: enable access to events of base contracts' names.
### 0.4.7 (2016-12-15)
Features:

View File

@ -217,6 +217,9 @@ vector<Declaration const*> const& ContractDefinition::inheritableMembers() const
for (EnumDefinition const* e: definedEnums())
addInheritableMember(e);
for (EventDefinition const* e: events())
addInheritableMember(e);
}
return *m_inheritableMembers;
}

View File

@ -908,19 +908,43 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
solAssert(_memberAccess.annotation().type, "_memberAccess has no type");
if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type.get()))
{
if (funType->location() != FunctionType::Location::Internal)
{
_memberAccess.expression().accept(*this);
m_context << funType->externalIdentifier();
}
else
switch (funType->location())
{
case FunctionType::Location::Internal:
// We do not visit the expression here on purpose, because in the case of an
// internal library function call, this would push the library address forcing
// us to link against it although we actually do not need it.
auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration);
solAssert(!!function, "Function not found in member access");
utils().pushCombinedFunctionEntryLabel(*function);
if (auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration))
utils().pushCombinedFunctionEntryLabel(*function);
else
solAssert(false, "Function not found in member access");
break;
case FunctionType::Location::Event:
if (!dynamic_cast<EventDefinition const*>(_memberAccess.annotation().referencedDeclaration))
solAssert(false, "event not found");
// no-op, because the parent node will do the job
break;
case FunctionType::Location::External:
case FunctionType::Location::Creation:
case FunctionType::Location::DelegateCall:
case FunctionType::Location::CallCode:
case FunctionType::Location::Send:
case FunctionType::Location::Bare:
case FunctionType::Location::BareCallCode:
case FunctionType::Location::BareDelegateCall:
_memberAccess.expression().accept(*this);
m_context << funType->externalIdentifier();
break;
case FunctionType::Location::Log0:
case FunctionType::Location::Log1:
case FunctionType::Location::Log2:
case FunctionType::Location::Log3:
case FunctionType::Location::Log4:
case FunctionType::Location::ECRecover:
case FunctionType::Location::SHA256:
case FunctionType::Location::RIPEMD160:
default:
solAssert(false, "unsupported member function");
}
}
else if (dynamic_cast<TypeType const*>(_memberAccess.annotation().type.get()))

View File

@ -2770,6 +2770,28 @@ BOOST_AUTO_TEST_CASE(event_no_arguments)
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()")));
}
BOOST_AUTO_TEST_CASE(event_access_through_base_name)
{
char const* sourceCode = R"(
contract A {
event x();
}
contract B is A {
function f() returns (uint) {
A.x();
return 1;
}
}
)";
compileAndRun(sourceCode);
callContractFunction("f()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data.empty());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("x()")));
}
BOOST_AUTO_TEST_CASE(event_anonymous)
{
char const* sourceCode = R"(