Always expose underlying type of enum

This commit is contained in:
Jonathan Müller 2017-04-06 11:51:31 +02:00
commit 251e9abf5f
4 changed files with 30 additions and 25 deletions

View file

@ -64,9 +64,9 @@ namespace cppast
{ {
public: public:
/// \effects Sets the name, underlying type and whether it is scoped. /// \effects Sets the name, underlying type and whether it is scoped.
/// \notes The underlying type may be `nullptr` if it is not explictly given. builder(std::string name, bool scoped, std::unique_ptr<cpp_type> type,
builder(std::string name, bool scoped, std::unique_ptr<cpp_type> type = nullptr) bool explicit_type)
: enum_(new cpp_enum(std::move(name), std::move(type), scoped)) : enum_(new cpp_enum(std::move(name), std::move(type), explicit_type, scoped))
{ {
} }
@ -105,11 +105,16 @@ namespace cppast
std::unique_ptr<cpp_enum> enum_; std::unique_ptr<cpp_enum> enum_;
}; };
/// \returns A [ts::optional_ref]() to the underlying [cppast::cpp_type]() of the enum. /// \returns A reference to the underlying [cppast::cpp_type]() of the enum.
/// \notes It only has an associated underlying type if it is not explictly given. const cpp_type& underlying_type() const noexcept
type_safe::optional_ref<const cpp_type> underlying_type() const noexcept
{ {
return type_safe::opt_cref(type_.get()); return *type_;
}
/// \returns Whether or not the underlying type is explictly given.
bool has_explicit_type() const noexcept
{
return type_given_;
} }
/// \returns Whether or not it is a scoped enumeration (i.e. an `enum class`). /// \returns Whether or not it is a scoped enumeration (i.e. an `enum class`).
@ -119,8 +124,11 @@ namespace cppast
} }
private: private:
cpp_enum(std::string name, std::unique_ptr<cpp_type> type, bool scoped) cpp_enum(std::string name, std::unique_ptr<cpp_type> type, bool type_given, bool scoped)
: cpp_entity(std::move(name)), type_(std::move(type)), scoped_(scoped) : cpp_entity(std::move(name)),
type_(std::move(type)),
scoped_(scoped),
type_given_(type_given)
{ {
} }
@ -131,7 +139,7 @@ namespace cppast
type_safe::optional<std::string> do_get_scope_name() const override; type_safe::optional<std::string> do_get_scope_name() const override;
std::unique_ptr<cpp_type> type_; std::unique_ptr<cpp_type> type_;
bool scoped_; bool scoped_, type_given_;
}; };
} // namespace cppast } // namespace cppast

View file

@ -205,10 +205,10 @@ namespace
if (e.is_scoped()) if (e.is_scoped())
output << whitespace << keyword("class"); output << whitespace << keyword("class");
output << whitespace << identifier(e.name()); output << whitespace << identifier(e.name());
if (e.underlying_type()) if (e.has_explicit_type())
{ {
output << newl << punctuation(":"); output << newl << punctuation(":");
detail::write_type(output, e.underlying_type().value(), ""); detail::write_type(output, e.underlying_type(), "");
} }
if (e.is_definition()) if (e.is_definition())

View file

@ -53,12 +53,11 @@ namespace
detail::skip_attribute(stream); detail::skip_attribute(stream);
auto& name = stream.get().value(); auto& name = stream.get().value();
std::unique_ptr<cpp_type> type; // parse type
if (detail::skip_if(stream, ":")) auto type = detail::parse_type(context, cur, clang_getEnumDeclIntegerType(cur));
// parse type, explictly given one auto type_given = detail::skip_if(stream, ":");
type = detail::parse_type(context, cur, clang_getEnumDeclIntegerType(cur));
return cpp_enum::builder(name.c_str(), scoped, std::move(type)); return cpp_enum::builder(name.c_str(), scoped, std::move(type), type_given);
} }
} }

View file

@ -54,7 +54,7 @@ enum c : int;
REQUIRE(e.is_definition()); REQUIRE(e.is_definition());
REQUIRE(!e.is_declaration()); REQUIRE(!e.is_declaration());
REQUIRE(!e.is_scoped()); REQUIRE(!e.is_scoped());
REQUIRE(!e.underlying_type()); REQUIRE(!e.has_explicit_type());
auto no_vals = 0u; auto no_vals = 0u;
for (auto& val : e) for (auto& val : e)
@ -96,9 +96,8 @@ enum c : int;
if (e.is_definition()) if (e.is_definition())
{ {
REQUIRE(e.underlying_type()); REQUIRE(e.has_explicit_type());
REQUIRE(equal_types(idx, e.underlying_type().value(), REQUIRE(equal_types(idx, e.underlying_type(), *cpp_builtin_type::build(cpp_int)));
*cpp_builtin_type::build(cpp_int)));
auto no_vals = 0u; auto no_vals = 0u;
for (auto& val : e) for (auto& val : e)
@ -125,7 +124,7 @@ enum c : int;
} }
else if (e.is_declaration()) else if (e.is_declaration())
{ {
REQUIRE(!e.underlying_type()); // no underlying type, implicit int REQUIRE(!e.has_explicit_type()); // no underlying type, implicit int
REQUIRE(count_children(e) == 0u); REQUIRE(count_children(e) == 0u);
auto definition = get_definition(idx, e); auto definition = get_definition(idx, e);
@ -141,9 +140,8 @@ enum c : int;
REQUIRE(e.is_declaration()); REQUIRE(e.is_declaration());
REQUIRE(!e.is_definition()); REQUIRE(!e.is_definition());
REQUIRE(!e.is_scoped()); REQUIRE(!e.is_scoped());
REQUIRE(e.underlying_type().has_value()); REQUIRE(e.has_explicit_type());
REQUIRE( REQUIRE(equal_types(idx, e.underlying_type(), *cpp_builtin_type::build(cpp_int)));
equal_types(idx, e.underlying_type().value(), *cpp_builtin_type::build(cpp_int)));
REQUIRE(count_children(e) == 0u); REQUIRE(count_children(e) == 0u);
auto definition = get_definition(idx, e); auto definition = get_definition(idx, e);