5
5
#ifndef CARBON_COMMON_ENUM_BASE_H_
6
6
#define CARBON_COMMON_ENUM_BASE_H_
7
7
8
+ #include < compare>
8
9
#include < type_traits>
9
10
10
11
#include " common/ostream.h"
@@ -53,7 +54,7 @@ namespace Carbon::Internal {
53
54
//
54
55
// In `my_kind.cpp`:
55
56
// ```
56
- // CARBON_DEFINE_ENUM_CLASS_NAMES(MyKind) = {
57
+ // CARBON_DEFINE_ENUM_CLASS_NAMES(MyKind) {
57
58
// #define CARBON_MY_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)
58
59
// #include ".../my_kind.def"
59
60
// };
@@ -122,22 +123,26 @@ class EnumBase : public Printable<DerivedT> {
122
123
// function.
123
124
//
124
125
// NOLINTNEXTLINE(google-explicit-constructor)
125
- constexpr operator RawEnumType () const { return value_; }
126
+ explicit ( false ) constexpr operator RawEnumType () const { return value_; }
126
127
127
128
// Conversion to bool is deleted to prevent direct use in an `if` condition
128
129
// instead of comparing with another value.
129
130
explicit operator bool () const = delete;
130
131
131
132
// Returns the name of this value.
132
- //
133
- // This method will be automatically defined using the static `names` string
134
- // table in the base class, which is in turn will be populated for each
135
- // derived type using the macro helpers in this file.
136
133
auto name () const -> llvm::StringRef { return Names[AsInt ()]; }
137
134
138
135
// Prints this value using its name.
139
136
auto Print (llvm::raw_ostream& out) const -> void { out << name (); }
140
137
138
+ // Don't support comparison of enums by default.
139
+ friend auto operator <(DerivedT lhs, DerivedT rhs) -> bool = delete ;
140
+ friend auto operator <=(DerivedT lhs, DerivedT rhs) -> bool = delete ;
141
+ friend auto operator >(DerivedT lhs, DerivedT rhs) -> bool = delete ;
142
+ friend auto operator >=(DerivedT lhs, DerivedT rhs) -> bool = delete ;
143
+ friend auto operator <=>(DerivedT lhs, DerivedT rhs)
144
+ -> std::partial_ordering = delete ;
145
+
141
146
protected:
142
147
// The default constructor is explicitly defaulted (and constexpr) as a
143
148
// protected constructor to allow derived classes to be constructed but not
@@ -165,42 +170,38 @@ class EnumBase : public Printable<DerivedT> {
165
170
}
166
171
167
172
private:
173
+ template <typename MaskDerivedT, typename MaskEnumT,
174
+ const llvm::StringLiteral MaskNames[]>
175
+ friend class EnumMaskBase ;
176
+
168
177
RawEnumType value_;
169
178
};
170
179
171
180
} // namespace Carbon::Internal
172
181
173
- // For use when multiple enums use the same list of names.
174
- #define CARBON_DEFINE_RAW_ENUM_CLASS_NO_NAMES (EnumClassName, UnderlyingType ) \
175
- namespace Internal { \
176
- enum class EnumClassName ##RawEnum : UnderlyingType; \
177
- } \
178
- enum class Internal ::EnumClassName##RawEnum : UnderlyingType
179
-
180
182
// Use this before defining a class that derives from `EnumBase` to begin the
181
183
// definition of the raw `enum class`. It should be followed by the body of that
182
184
// raw enum class.
183
185
#define CARBON_DEFINE_RAW_ENUM_CLASS (EnumClassName, UnderlyingType ) \
184
186
namespace Internal { \
185
- extern const llvm::StringLiteral EnumClassName##Names[]; \
187
+ struct EnumClassName ##Data { \
188
+ static const llvm::StringLiteral Names[]; \
189
+ enum class RawEnum : UnderlyingType; \
190
+ }; \
186
191
} \
187
- CARBON_DEFINE_RAW_ENUM_CLASS_NO_NAMES ( EnumClassName, UnderlyingType)
192
+ enum class Internal :: EnumClassName##Data::RawEnum : UnderlyingType
188
193
189
- // In CARBON_DEFINE_RAW_ENUM_CLASS block, use this to generate each enumerator.
194
+ // In the `CARBON_DEFINE_RAW_ENUM_CLASS` block, use this to generate each
195
+ // enumerator.
190
196
#define CARBON_RAW_ENUM_ENUMERATOR (Name ) Name,
191
197
192
198
// Use this to compute the `Internal::EnumBase` specialization for a Carbon enum
193
199
// class. It both computes the name of the raw enum and ensures all the
194
200
// namespaces are correct.
195
- #define CARBON_ENUM_BASE (EnumClassName ) \
196
- CARBON_ENUM_BASE_CRTP (EnumClassName, EnumClassName, EnumClassName)
197
- // This variant handles the case where the external name for the Carbon enum is
198
- // not the same as the name by which we refer to it from this context.
199
- #define CARBON_ENUM_BASE_CRTP (EnumClassName, LocalTypeNameForEnumClass, \
200
- EnumClassNameForNames) \
201
- ::Carbon::Internal::EnumBase<LocalTypeNameForEnumClass, \
202
- Internal::EnumClassName##RawEnum, \
203
- Internal::EnumClassNameForNames##Names>
201
+ #define CARBON_ENUM_BASE (EnumClassName ) \
202
+ ::Carbon::Internal::EnumBase<EnumClassName, \
203
+ Internal::EnumClassName##Data::RawEnum, \
204
+ Internal::EnumClassName##Data::Names>
204
205
205
206
// Use this within the Carbon enum class body to generate named constant
206
207
// declarations for each value.
@@ -212,24 +213,14 @@ class EnumBase : public Printable<DerivedT> {
212
213
constexpr EnumClassName EnumClassName::Name = \
213
214
EnumClassName::Make (RawEnumType::Name);
214
215
215
- // Alternatively, use this within the Carbon enum class body to declare and
216
- // define each named constant. Due to type completeness constraints, this will
217
- // only work if the enum-like class is templated.
218
- //
219
- // This requires the template to have a member named `Base` that names the
220
- // `EnumBase` base class.
221
- #define CARBON_INLINE_ENUM_CONSTANT_DEFINITION (Name ) \
222
- static constexpr const typename Base::EnumType& Name = \
223
- Base::Make (Base::RawEnumType::Name);
224
-
225
216
// Use this in the `.cpp` file for an enum class to start the definition of the
226
217
// constant names array for each enumerator. It is followed by the desired
227
218
// constant initializer.
228
219
//
229
220
// `clang-format` has a bug with spacing around `->` returns in macros. See
230
221
// https://bugs.llvm.org/show_bug.cgi?id=48320 for details.
231
222
#define CARBON_DEFINE_ENUM_CLASS_NAMES (EnumClassName ) \
232
- constexpr llvm::StringLiteral Internal::EnumClassName##Names[]
223
+ constexpr llvm::StringLiteral Internal::EnumClassName##Data:: Names[] =
233
224
234
225
// Use this within the names array initializer to generate a string for each
235
226
// name.
0 commit comments