diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 95014fa18..488bd4cd1 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -208,7 +208,7 @@ vector, FunctionTypePointer>> const& ContractDefinition::getIn TypePointer EnumDeclaration::getType(ContractDefinition const*) const { - // LTODO + // LTODO: How to get the parent EnumDefinition and return its type here? return nullptr; } @@ -274,9 +274,7 @@ void EnumDefinition::checkValidityOfMembers() const TypePointer EnumDefinition::getType(ContractDefinition const*) const { - //LTODO: - return nullptr; - // return make_shared(make_shared(*this)); + return make_shared(make_shared(*this)); } TypePointer FunctionDefinition::getType(ContractDefinition const*) const diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 02493df25..65c35026c 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -177,7 +177,7 @@ class EnumDeclaration : public Declaration virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; - TypePointer getType(ContractDefinition const*) const; + TypePointer getType(ContractDefinition const* = nullptr) const; }; /** diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index fd25d7ce1..a26713a73 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -292,6 +292,7 @@ ASTPointer Parser::parseEnumDefinition() nodeFactory.markEndPosition(); expectToken(Token::RBrace); + expectToken(Token::Semicolon); return nodeFactory.createNode(name, members); } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 16514b148..6b6a70c29 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -662,6 +662,37 @@ u256 StructType::getStorageOffsetOfMember(string const& _name) const BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage offset of non-existing member requested.")); } +TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const +{ + return _operator == Token::Delete ? make_shared() : TypePointer(); +} + +bool EnumType::operator==(Type const& _other) const +{ + if (_other.getCategory() != getCategory()) + return false; + EnumType const& other = dynamic_cast(_other); + return other.m_enum == m_enum; +} + +string EnumType::toString() const +{ + return string("enum ") + m_enum.getName(); +} + +MemberList const& EnumType::getMembers() const +{ + // We need to lazy-initialize it because of recursive references. + if (!m_members) + { + map> members; + for (ASTPointer const& enumValue: m_enum.getMembers()) + members.insert(make_pair(enumValue->getName(), make_shared(m_enum))); + m_members.reset(new MemberList(members)); + } + return *m_members; +} + FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal): m_location(_isInternal ? Location::Internal : Location::External), m_isConstant(_function.isDeclaredConst()), diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 5a0e2c429..70703938d 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -76,10 +76,9 @@ class Type: private boost::noncopyable, public std::enable_shared_from_this m_members; }; +/** + * The type of an enum instance, there is one distinct type per enum definition. + */ +class EnumType: public Type +{ +public: + virtual Category getCategory() const override { return Category::Enum; } + explicit EnumType(EnumDefinition const& _enum): m_enum(_enum) {} + virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; + virtual bool operator==(Type const& _other) const override; + virtual unsigned getSizeOnStack() const override { return 1; /*@todo*/ } + virtual std::string toString() const override; + + virtual MemberList const& getMembers() const override; + +private: + EnumDefinition const& m_enum; + /// List of member types, will be lazy-initialized because of recursive references. + mutable std::unique_ptr m_members; +}; + /** * The type of a function, identified by its (return) parameter types. * @todo the return parameters should also have names, i.e. return parameters should be a struct diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index 035bfd789..291ec6051 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -717,6 +717,20 @@ BOOST_AUTO_TEST_CASE(enum_declaration) BOOST_CHECK_NO_THROW(parseTextExplainError(text)); } +BOOST_AUTO_TEST_CASE(empty_enum_declaration) +{ + char const* text = R"( + contract c { + enum foo { }; + function c () + { + a = 5; + } + uint256 a; + })"; + BOOST_CHECK_NO_THROW(parseTextExplainError(text)); +} + BOOST_AUTO_TEST_SUITE_END() }