diff --git a/mfbt/TypedEnum.h b/mfbt/TypedEnum.h index 2baae5ea8b2..6f595cb4c5f 100644 --- a/mfbt/TypedEnum.h +++ b/mfbt/TypedEnum.h @@ -92,16 +92,33 @@ * mandatory. As with MOZ_ENUM_TYPE(), it will do nothing on compilers that do * not support it. * - * Note that the workaround implemented here is not compatible with enums - * nested inside a class. + * MOZ_{BEGIN,END}_ENUM_CLASS doesn't work for defining enum classes nested + * inside classes. To define an enum class nested inside another class, use + * MOZ_{BEGIN,END}_NESTED_ENUM_CLASS, and place a MOZ_FINISH_NESTED_ENUM_CLASS + * in namespace scope to handle bits that can only be implemented with + * namespace-scoped code. For example: + * + * class FooBar { + * + * MOZ_BEGIN_NESTED_ENUM_CLASS(Enum, int32_t) + * A, + * B = 6 + * MOZ_END_NESTED_ENUM_CLASS(Enum) + * + * }; + * + * MOZ_FINISH_NESTED_ENUM_CLASS(FooBar::Enum) */ #if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) /* * All compilers that support strong enums also support an explicit * underlying type, so no extra check is needed. */ -# define MOZ_BEGIN_ENUM_CLASS(Name, type) enum class Name : type { -# define MOZ_END_ENUM_CLASS(Name) }; +# define MOZ_BEGIN_NESTED_ENUM_CLASS(Name, type) \ + enum class Name : type { +# define MOZ_END_NESTED_ENUM_CLASS(Name) \ + }; +# define MOZ_FINISH_NESTED_ENUM_CLASS(Name) /* nothing */ #else /** * We need Name to both name a type, and scope the provided enumerator @@ -137,14 +154,14 @@ * { * return Enum::A; * } - */ -# define MOZ_BEGIN_ENUM_CLASS(Name, type) \ + */\ +# define MOZ_BEGIN_NESTED_ENUM_CLASS(Name, type) \ class Name \ { \ public: \ enum Enum MOZ_ENUM_TYPE(type) \ { -# define MOZ_END_ENUM_CLASS(Name) \ +# define MOZ_END_NESTED_ENUM_CLASS(Name) \ }; \ Name() {} \ Name(Enum aEnum) : mEnum(aEnum) {} \ @@ -152,7 +169,8 @@ operator Enum() const { return mEnum; } \ private: \ Enum mEnum; \ - }; \ + }; +# define MOZ_FINISH_NESTED_ENUM_CLASS(Name) \ inline int operator+(const int&, const Name::Enum&) MOZ_DELETE; \ inline int operator+(const Name::Enum&, const int&) MOZ_DELETE; \ inline int operator-(const int&, const Name::Enum&) MOZ_DELETE; \ @@ -208,6 +226,10 @@ inline int& operator<<=(int&, const Name::Enum&) MOZ_DELETE; \ inline int& operator>>=(int&, const Name::Enum&) MOZ_DELETE; #endif +# define MOZ_BEGIN_ENUM_CLASS(Name, type) MOZ_BEGIN_NESTED_ENUM_CLASS(Name, type) +# define MOZ_END_ENUM_CLASS(Name) \ + MOZ_END_NESTED_ENUM_CLASS(Name) \ + MOZ_FINISH_NESTED_ENUM_CLASS(Name) #endif /* __cplusplus */