How to represent: enum class X : int;? Possibly add opt<Type> underlying_type
Opened this issue · 4 comments
Need to be able to represent:
enum class X : int;
Currently not representable by IPR
Enum should have opt underlying_type
Enums are an odd case compared to class types. An enum declaration with an underlying type is really a complete type, where as there a forward declaration of a class references an incomplete type. So, the issue here is whether a Typedecl
as currently defined is sufficient to represent both a forward declaration of num and a forward declaration of a class. The answer is "no" post C++11. It is a design point as to which of the various choices should be picked.
One of the ideas we had during recent discussion about this issue was to introduce a meta type, tentative name, [Complete type: enum, alignment: x, size: sizeof(int)] that will be used in this case instead of lexicon::enum_type() both in a Typedecl when there is no initializer (i.e. enum body) and as a type of ipr::Enum itself.
enum class X : int;
enum class X : int { a, b };
Will be represented as:
type#1 Complete[type: enum, size: sizeof(int), alignment: alignas(int)]
decl#1 Typedecl[name:X, type:type#1, init: <absent>]
type#2 Enum[type:type#1 enumerators... ]
decl#2 Typedecl[name:X, type:type#1, init: type#2]
We talked a bit more about this representation. Latest thinking:
- Change complete to be just a pair
[Complete type: enum, layout: int]
, as opposed carrying size/align fields. If we want to represent an exported opaque structure (for which only size and alignment is visible), we can introduce a new type[OpaqueLayout align: <expr> size: <expr>
to be used for the layout field ofComplete
metatype.
This addresses a use case:
enum class X;
using undy = std::underlying_type_t<X>;
Now std::underlying_type_t can grab the type from the layout field.
- Currently ipr uses a Kind field in the enum type to represent a distinction between scoped and unscoped enumerations. Since under the model we are discussing in this thread, we would like to retain a property that only one declaration is a definition (adds initializer), we need to represent scoped/unscoped without relying on an initializer.
enum class X;
enum X; // error: scoped enum cannot be redeclared as an unscoped one
The suggestion is to introduce a new metatype scoped_enum_type to the lexicon that will be the type of scoped enumerations and the enum_type will be used for unscoped ones.
There are two issues in this report:
- How to represent the underlying type of an enumeration in a declaration that explicitly specifies it?
- How to represent the enumerators of an enumeration that are defined in a declaration separate from a prior declaration that specified the base type?
All of these issues stem from timeline: when IPR was originally designed, the notion of separately specifying the underlying type of an enumeration was not yet a thing. This points to the perilous task of predicting the future.
Aspect (1) bears some similarity with base class types of a class declaration.
Aspect (2) bears some similarity with the notion of prolongation, i.e. definition of members (providing initializer for a member) of a scope outside the definition of that scope.