From 5c164fb42c67aa541d00675245b8bedda49b8e1e Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 13 Feb 2015 13:32:18 +0100 Subject: [PATCH] Enum Value member access should now work properly - Also detection of duplicate enum values and tests for them have been added --- libsolidity/AST.cpp | 14 +++++++------ libsolidity/ExpressionCompiler.cpp | 27 ++++++++++++++++++-------- test/SolidityNameAndTypeResolution.cpp | 17 ++++++++++++++++ 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 7653952f4..65dc57e5e 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -263,13 +263,15 @@ void StructDefinition::checkRecursion() const void EnumDefinition::checkValidityOfMembers() const { -#if 0 // LTODO: Make this work for the Declarations - vector> members = getMembers(); - sort(begin(members), end(members)); - for (size_t i = 0; i < members.size(); ++i) - if (members[i] == members[i + 1]) + vector> members(getMembers()); + auto compareDecls = [](ASTPointer a, ASTPointer b) + { + return a->getName() < b->getName(); + }; + sort(begin(members), end(members), compareDecls); + for (size_t i = 0; i < members.size() - 1; ++i) + if (members[i]->getName() == members[i + 1]->getName()) BOOST_THROW_EXCEPTION(createTypeError("Duplicate member detected in Enum")); -#endif } TypePointer EnumDefinition::getType(ContractDefinition const*) const diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index dd41b485a..4e72aca54 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -494,20 +494,31 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) EnumType const& type = dynamic_cast(*_memberAccess.getExpression().getType()); EnumDefinition const& enumDef = type.getEnumDefinition(); m_context << enumDef.getMemberValue(_memberAccess.getMemberName()); + break; } case Type::Category::TypeType: { TypeType const& type = dynamic_cast(*_memberAccess.getExpression().getType()); + ContractType const* contractType; + EnumType const* enumType; if (type.getMembers().getMemberType(member)) { - ContractDefinition const& contract = dynamic_cast(*type.getActualType()) - .getContractDefinition(); - for (ASTPointer const& function: contract.getDefinedFunctions()) - if (function->getName() == member) - { - m_context << m_context.getFunctionEntryLabel(*function).pushTag(); - return; - } + if ((contractType = dynamic_cast(type.getActualType().get()))) + { + ContractDefinition const& contract = contractType->getContractDefinition(); + for (ASTPointer const& function: contract.getDefinedFunctions()) + if (function->getName() == member) + { + m_context << m_context.getFunctionEntryLabel(*function).pushTag(); + return; + } + } + else if ((enumType = dynamic_cast(type.getActualType().get()))) + { + EnumDefinition const &enumDef = enumType->getEnumDefinition(); + m_context << enumDef.getMemberValue(_memberAccess.getMemberName()); + return; + } } BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString())); } diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 9399280b0..e7482d661 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -1056,6 +1056,23 @@ BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(enum_duplicate_values) +{ + char const* text = R"( + contract test { + enum ActionChoices { GoLeft, GoRight, GoLeft, Sit }; + function test() + { + a = 1; + b = 2; + } + uint256 a; + uint64 b; + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() }