Skip to content

Commit

Permalink
Emit error when declaring event with same name and arguments twice
Browse files Browse the repository at this point in the history
  • Loading branch information
federicobond committed Sep 29, 2017
1 parent ba7c5d2 commit 6d95447
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Bugfixes:
* Type Checker: Properly check array length and don't rely on an assertion in code generation.
* Type Checker: Properly support overwriting members inherited from ``address`` in a contract
(such as ``balance``, ``transfer``, etc.)
* Type Checker: Prevent duplicate event declarations.

### 0.4.17 (2017-09-21)

Expand Down
44 changes: 44 additions & 0 deletions libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
ASTNode::listAccept(_contract.baseContracts(), *this);

checkContractDuplicateFunctions(_contract);
checkContractDuplicateEvents(_contract);
checkContractIllegalOverrides(_contract);
checkContractAbstractFunctions(_contract);
checkContractAbstractConstructors(_contract);
Expand Down Expand Up @@ -218,6 +219,49 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
}
}

void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contract)
{
/// Checks that two events with the same name defined in this contract have different
/// argument types
map<string, vector<EventDefinition const*>> events;
for (EventDefinition const* event: _contract.events())
events[event->name()].push_back(event);

for (auto const& it: events)
{
vector<EventDefinition const*> const& overloads = it.second;
set<size_t> reported;
for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
{
SecondarySourceLocation ssl;

for (size_t j = i + 1; j < overloads.size(); ++j)
if (FunctionType(*overloads[i]).hasEqualArgumentTypes(FunctionType(*overloads[j])))
{
ssl.append("Other declaration is here:", overloads[j]->location());
reported.insert(j);
}

if (ssl.infos.size() > 0)
{
string msg = "Event with same name and arguments defined twice.";
size_t occurrences = ssl.infos.size();
if (occurrences > 32)
{
ssl.infos.resize(32);
msg += " Truncated from " + boost::lexical_cast<string>(occurrences) + " to the first 32 occurrences.";
}

m_errorReporter.declarationError(
overloads[i]->location(),
ssl,
msg
);
}
}
}
}

void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _contract)
{
// Mapping from name to function definition (exactly one per argument type equality class) and
Expand Down
1 change: 1 addition & 0 deletions libsolidity/analysis/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class TypeChecker: private ASTConstVisitor
/// Checks that two functions defined in this contract with the same name have different
/// arguments and that there is at most one constructor.
void checkContractDuplicateFunctions(ContractDefinition const& _contract);
void checkContractDuplicateEvents(ContractDefinition const& _contract);
void checkContractIllegalOverrides(ContractDefinition const& _contract);
/// Reports a type error with an appropiate message if overriden function signature differs.
/// Also stores the direct super function in the AST annotations.
Expand Down
55 changes: 55 additions & 0 deletions test/libsolidity/SolidityNameAndTypeResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,61 @@ BOOST_AUTO_TEST_CASE(events_with_same_name)
BOOST_CHECK(success(text));
}

BOOST_AUTO_TEST_CASE(events_with_same_name_unnamed_arguments)
{
char const* text = R"(
contract test {
event A(uint);
event A(uint, uint);
}
)";
CHECK_SUCCESS(text);
}

BOOST_AUTO_TEST_CASE(events_with_same_name_different_types)
{
char const* text = R"(
contract test {
event A(uint);
event A(bytes);
}
)";
CHECK_SUCCESS(text);
}

BOOST_AUTO_TEST_CASE(double_event_declaration)
{
char const* text = R"(
contract test {
event A(uint i);
event A(uint i);
}
)";
CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice.");
}

BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_anonymous)
{
char const* text = R"(
contract test {
event A(uint i);
event A(uint i) anonymous;
}
)";
CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice.");
}

BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_indexed)
{
char const* text = R"(
contract test {
event A(uint i);
event A(uint indexed i);
}
)";
CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice.");
}

BOOST_AUTO_TEST_CASE(event_call)
{
char const* text = R"(
Expand Down

0 comments on commit 6d95447

Please sign in to comment.