Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -88,9 +88,12 @@ def ext_cxx11_enum_fixed_underlying_type : Extension< "enumeration types with a fixed underlying type are a C++11 extension">, InGroup; -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; +def ext_clang_c_enum_fixed_underlying_type : Extension< + "enumeration types with a fixed underlying type are a Clang extension">, + InGroup>; def warn_cxx98_compat_enum_fixed_underlying_type : Warning< "enumeration types with a fixed underlying type are incompatible with C++98">, InGroup, DefaultIgnore; Index: include/clang/Basic/Features.def =================================================================== --- include/clang/Basic/Features.def +++ include/clang/Basic/Features.def @@ -89,7 +89,7 @@ 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) @@ -232,6 +232,7 @@ 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) Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -4153,15 +4153,11 @@ // 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, @@ -4183,7 +4179,7 @@ // 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. @@ -4216,7 +4212,7 @@ // 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 @@ -4276,13 +4272,15 @@ 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); } } } Index: test/Sema/fixed-enum.c =================================================================== --- test/Sema/fixed-enum.c +++ test/Sema/fixed-enum.c @@ -0,0 +1,18 @@ +// 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 Index: test/SemaObjC/enum-fixed-type.m =================================================================== --- test/SemaObjC/enum-fixed-type.m +++ test/SemaObjC/enum-fixed-type.m @@ -1,9 +1,14 @@ // 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;