From 4b0a566e708ba2f4d10d8b565d8514840822b5a3 Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 14 Feb 2015 03:06:50 +0100 Subject: [PATCH 1/2] Some changes to enums. --- libsolidity/AST.cpp | 13 ------------- libsolidity/AST.h | 4 ---- libsolidity/ExpressionCompiler.cpp | 13 ++++--------- libsolidity/NameAndTypeResolver.cpp | 8 ++++++-- libsolidity/NameAndTypeResolver.h | 1 + test/SolidityNameAndTypeResolution.cpp | 2 +- 6 files changed, 12 insertions(+), 29 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 683452027..0dbad433f 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -262,19 +262,6 @@ void StructDefinition::checkRecursion() const } } -void EnumDefinition::checkValidityOfMembers() const -{ - 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(members[i]->createTypeError("Duplicate member detected in Enum")); -} - TypePointer EnumDefinition::getType(ContractDefinition const*) const { return make_shared(make_shared(*this)); diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 4167537e5..51d8031a3 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -333,11 +333,7 @@ public: virtual TypePointer getType(ContractDefinition const*) const override; - /// Checks that the members do not include any duplicate names - void checkValidityOfMembers() const; - private: - std::vector> m_members; }; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 63324fe58..29ec3d577 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -498,12 +498,10 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) case Type::Category::TypeType: { TypeType const& type = dynamic_cast(*_memberAccess.getExpression().getType()); - ContractType const* contractType; - EnumType const* enumType; if (!type.getMembers().getMemberType(member)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString())); + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString())); - if ((contractType = dynamic_cast(type.getActualType().get()))) + if (auto contractType = dynamic_cast(type.getActualType().get())) { ContractDefinition const& contract = contractType->getContractDefinition(); for (ASTPointer const& function: contract.getDefinedFunctions()) @@ -513,12 +511,9 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) return; } } - else if ((enumType = dynamic_cast(type.getActualType().get()))) - { + else if (auto enumType = dynamic_cast(type.getActualType().get())) m_context << enumType->getMemberValue(_memberAccess.getMemberName()); - return; - } - + break; } case Type::Category::ByteArray: { diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 859d0097c..dbe5693a8 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -81,8 +81,6 @@ void NameAndTypeResolver::checkTypeRequirements(ContractDefinition& _contract) { for (ASTPointer const& structDef: _contract.getDefinedStructs()) structDef->checkValidityOfMembers(); - for (ASTPointer const& enumDef: _contract.getDefinedEnums()) - enumDef->checkValidityOfMembers(); _contract.checkTypeRequirements(); } @@ -236,6 +234,12 @@ void DeclarationRegistrationHelper::endVisit(EnumDefinition&) closeCurrentScope(); } +bool DeclarationRegistrationHelper::visit(EnumValue& _value) +{ + registerDeclaration(_value, false); + return true; +} + bool DeclarationRegistrationHelper::visit(FunctionDefinition& _function) { registerDeclaration(_function, true); diff --git a/libsolidity/NameAndTypeResolver.h b/libsolidity/NameAndTypeResolver.h index 4b1b8c0cd..d9ac98ce5 100644 --- a/libsolidity/NameAndTypeResolver.h +++ b/libsolidity/NameAndTypeResolver.h @@ -100,6 +100,7 @@ private: void endVisit(StructDefinition& _struct) override; bool visit(EnumDefinition& _enum) override; void endVisit(EnumDefinition& _enum) override; + bool visit(EnumValue& _value) override; bool visit(FunctionDefinition& _function) override; void endVisit(FunctionDefinition& _function) override; bool visit(ModifierDefinition& _modifier) override; diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index ec49a42d1..d6e4ed516 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -1080,7 +1080,7 @@ BOOST_AUTO_TEST_CASE(enum_duplicate_values) enum ActionChoices { GoLeft, GoRight, GoLeft, Sit } } )"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_SUITE_END() From ab9258d0a8c5651f2cbb3ad4571fff46a0018849 Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 14 Feb 2015 03:22:49 +0100 Subject: [PATCH 2/2] Forced cleanup for conversion to enum. --- libsolidity/ExpressionCompiler.cpp | 8 +++++++- test/SolidityEndToEndTest.cpp | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 29ec3d577..0f0e94f21 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -759,8 +759,11 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con } } } + else if (stackTypeCategory == Type::Category::Enum) + solAssert(targetTypeCategory == Type::Category::Integer || + targetTypeCategory == Type::Category::Enum, ""); else if (stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::Contract || - stackTypeCategory == Type::Category::IntegerConstant || stackTypeCategory == Type::Category::Enum) + stackTypeCategory == Type::Category::IntegerConstant) { if (targetTypeCategory == Type::Category::String && stackTypeCategory == Type::Category::Integer) { @@ -772,6 +775,9 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL; } + else if (targetTypeCategory == Type::Category::Enum) + // just clean + appendTypeConversion(_typeOnStack, *_typeOnStack.getRealType(), true); else { solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, ""); diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 2ef2b8038..0325c4c6a 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2519,6 +2519,21 @@ BOOST_AUTO_TEST_CASE(using_enums) BOOST_CHECK(callContractFunction("getChoice()") == encodeArgs(2)); } +BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) +{ + char const* sourceCode = R"( + contract c { + enum Truth { False, True } + function test() returns (uint) + { + return uint(Truth(uint8(0x701))); + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); +} + BOOST_AUTO_TEST_SUITE_END() }