def ext_cxx11_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a C++11 extension">,
InGroup<CXX11>;
-def ext_c_enum_fixed_underlying_type : Extension<
+def ext_ms_c_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a Microsoft extension">,
InGroup<MicrosoftFixedEnum>;
+def ext_clang_c_enum_fixed_underlying_type : Extension<
+ "enumeration types with a fixed underlying type are a Clang extension">,
+ InGroup<DiagGroup<"fixed-enum-extension">>;
def warn_cxx98_compat_enum_fixed_underlying_type : Warning<
"enumeration types with a fixed underlying type are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
FEATURE(objc_arc_fields, true)
FEATURE(objc_arc_weak, LangOpts.ObjCWeak)
FEATURE(objc_default_synthesize_properties, LangOpts.ObjC2)
-FEATURE(objc_fixed_enum, LangOpts.ObjC2)
+FEATURE(objc_fixed_enum, true)
FEATURE(objc_instancetype, LangOpts.ObjC2)
FEATURE(objc_kindof, LangOpts.ObjC2)
FEATURE(objc_modules, LangOpts.ObjC2 &&LangOpts.Modules)
EXTENSION(cxx_reference_qualified_functions, LangOpts.CPlusPlus)
EXTENSION(cxx_rvalue_references, LangOpts.CPlusPlus)
EXTENSION(cxx_variadic_templates, LangOpts.CPlusPlus)
+EXTENSION(cxx_fixed_enum, true)
// C++14 features supported by other languages as extensions.
EXTENSION(cxx_binary_literals, true)
EXTENSION(cxx_init_captures, LangOpts.CPlusPlus11)
// Enum definitions should not be parsed in a trailing-return-type.
bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing;
- bool AllowFixedUnderlyingType = AllowDeclaration &&
- (getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt ||
- getLangOpts().ObjC2);
-
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
// "enum foo : bar;" is not a potential typo for "enum foo::bar;"
// if a fixed underlying type is allowed.
- ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType);
+ ColonProtectionRAIIObject X(*this, AllowDeclaration);
CXXScopeSpec Spec;
if (ParseOptionalCXXScopeSpecifier(Spec, nullptr,
// Must have either 'enum name' or 'enum {...}'.
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
- !(AllowFixedUnderlyingType && Tok.is(tok::colon))) {
+ !(AllowDeclaration && Tok.is(tok::colon))) {
Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
// Skip the rest of this declarator, up until the comma or semicolon.
// Parse the fixed underlying type.
bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope;
- if (AllowFixedUnderlyingType && Tok.is(tok::colon)) {
+ if (AllowDeclaration && Tok.is(tok::colon)) {
bool PossibleBitfield = false;
if (CanBeBitfield) {
// If we're in class scope, this can either be an enum declaration with
SourceRange Range;
BaseType = ParseTypeName(&Range);
- if (getLangOpts().CPlusPlus11) {
- Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type);
- } else if (!getLangOpts().ObjC2) {
- if (getLangOpts().CPlusPlus)
- Diag(StartLoc, diag::ext_cxx11_enum_fixed_underlying_type) << Range;
+ if (!getLangOpts().ObjC2) {
+ if (getLangOpts().CPlusPlus11)
+ Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type);
+ else if (getLangOpts().CPlusPlus)
+ Diag(StartLoc, diag::ext_cxx11_enum_fixed_underlying_type);
+ else if (getLangOpts().MicrosoftExt)
+ Diag(StartLoc, diag::ext_ms_c_enum_fixed_underlying_type);
else
- Diag(StartLoc, diag::ext_c_enum_fixed_underlying_type) << Range;
+ Diag(StartLoc, diag::ext_clang_c_enum_fixed_underlying_type);
}
}
}
--- /dev/null
+// RUN: %clang_cc1 -Weverything -xc++ -std=c++11 -DCXX11 -verify %s
+// RUN: %clang_cc1 -Weverything -xc++ -std=c++03 -DCXX03 -verify %s
+// RUN: %clang_cc1 -Weverything -xobjective-c -DOBJC -verify %s
+// RUN: %clang_cc1 -Weverything -std=c11 -xc -DC11 -verify %s
+// RUN: %clang_cc1 -Weverything -std=c11 -xc -fms-extensions -DMS -verify %s
+
+enum X : int {e};
+#if defined(CXX11)
+// expected-warning@-2{{enumeration types with a fixed underlying type are incompatible with C++98}}
+#elif defined(CXX03)
+// expected-warning@-4{{enumeration types with a fixed underlying type are a C++11 extension}}
+#elif defined(OBJC)
+// expected-no-diagnostics
+#elif defined(C11)
+// expected-warning@-8{{enumeration types with a fixed underlying type are a Clang extension}}
+#elif defined(MS)
+// expected-warning@-10{{enumeration types with a fixed underlying type are a Microsoft extension}}
+#endif
// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -xc %s
#if !__has_feature(objc_fixed_enum)
# error Enumerations with a fixed underlying type are not supported
#endif
+#if !__has_extension(cxx_fixed_enum)
+# error Enumerations with a fixed underlying type are not supported
+#endif
+
typedef long Integer;
typedef enum : Integer { Enumerator1, Enumerator2 } Enumeration;