@@ -4443,14 +4443,20 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
44434443 TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
44444444 SuppressAccessChecks diagsFromTag (*this , shouldDelayDiagsInTag);
44454445
4446- // Enum definitions should not be parsed in a trailing-return-type.
4447- bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing;
4446+ // Determine whether this declaration is permitted to have an enum-base.
4447+ AllowDefiningTypeSpec AllowEnumSpecifier =
4448+ isDefiningTypeSpecifierContext (DSC);
4449+ bool CanBeOpaqueEnumDeclaration =
4450+ DS.isEmpty () && isOpaqueEnumDeclarationContext (DSC);
4451+ bool CanHaveEnumBase = (getLangOpts ().CPlusPlus11 || getLangOpts ().ObjC ||
4452+ getLangOpts ().MicrosoftExt ) &&
4453+ (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes ||
4454+ CanBeOpaqueEnumDeclaration);
44484455
44494456 CXXScopeSpec &SS = DS.getTypeSpecScope ();
44504457 if (getLangOpts ().CPlusPlus ) {
4451- // "enum foo : bar;" is not a potential typo for "enum foo::bar;"
4452- // if a fixed underlying type is allowed.
4453- ColonProtectionRAIIObject X (*this , AllowDeclaration);
4458+ // "enum foo : bar;" is not a potential typo for "enum foo::bar;".
4459+ ColonProtectionRAIIObject X (*this );
44544460
44554461 CXXScopeSpec Spec;
44564462 if (ParseOptionalCXXScopeSpecifier (Spec, /* ObjectType=*/ nullptr ,
@@ -4471,9 +4477,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
44714477 SS = Spec;
44724478 }
44734479
4474- // Must have either 'enum name' or 'enum {...}'.
4480+ // Must have either 'enum name' or 'enum {...}' or (rarely) 'enum : T { ... }' .
44754481 if (Tok.isNot (tok::identifier) && Tok.isNot (tok::l_brace) &&
4476- !(AllowDeclaration && Tok.is (tok::colon) )) {
4482+ Tok.isNot (tok::colon)) {
44774483 Diag (Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
44784484
44794485 // Skip the rest of this declarator, up until the comma or semicolon.
@@ -4503,78 +4509,61 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
45034509 diagsFromTag.done ();
45044510
45054511 TypeResult BaseType;
4512+ SourceRange BaseRange;
45064513
4507- // Parse the fixed underlying type.
45084514 bool CanBeBitfield = getCurScope ()->getFlags () & Scope::ClassScope;
4509- if (AllowDeclaration && Tok.is (tok::colon)) {
4510- bool PossibleBitfield = false ;
4511- if (CanBeBitfield) {
4512- // If we're in class scope, this can either be an enum declaration with
4513- // an underlying type, or a declaration of a bitfield member. We try to
4514- // use a simple disambiguation scheme first to catch the common cases
4515- // (integer literal, sizeof); if it's still ambiguous, we then consider
4516- // anything that's a simple-type-specifier followed by '(' as an
4517- // expression. This suffices because function types are not valid
4518- // underlying types anyway.
4519- EnterExpressionEvaluationContext Unevaluated (
4520- Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
4521- TPResult TPR = isExpressionOrTypeSpecifierSimple (NextToken ().getKind ());
4522- // If the next token starts an expression, we know we're parsing a
4523- // bit-field. This is the common case.
4524- if (TPR == TPResult::True)
4525- PossibleBitfield = true ;
4526- // If the next token starts a type-specifier-seq, it may be either a
4527- // a fixed underlying type or the start of a function-style cast in C++;
4528- // lookahead one more token to see if it's obvious that we have a
4529- // fixed underlying type.
4530- else if (TPR == TPResult::False &&
4531- GetLookAheadToken (2 ).getKind () == tok::semi) {
4532- // Consume the ':'.
4533- ConsumeToken ();
4534- } else {
4535- // We have the start of a type-specifier-seq, so we have to perform
4536- // tentative parsing to determine whether we have an expression or a
4537- // type.
4538- TentativeParsingAction TPA (*this );
4539-
4540- // Consume the ':'.
4541- ConsumeToken ();
45424515
4543- // If we see a type specifier followed by an open-brace, we have an
4544- // ambiguity between an underlying type and a C++11 braced
4545- // function-style cast. Resolve this by always treating it as an
4546- // underlying type.
4547- // FIXME: The standard is not entirely clear on how to disambiguate in
4548- // this case.
4549- if ((getLangOpts ().CPlusPlus &&
4550- isCXXDeclarationSpecifier (TPResult::True) != TPResult::True) ||
4551- (!getLangOpts ().CPlusPlus && !isDeclarationSpecifier (true ))) {
4552- // We'll parse this as a bitfield later.
4553- PossibleBitfield = true ;
4554- TPA.Revert ();
4555- } else {
4556- // We have a type-specifier-seq.
4557- TPA.Commit ();
4558- }
4559- }
4560- } else {
4561- // Consume the ':'.
4562- ConsumeToken ();
4563- }
4564-
4565- if (!PossibleBitfield) {
4566- SourceRange Range;
4567- BaseType = ParseTypeName (&Range);
4516+ // Parse the fixed underlying type.
4517+ if (Tok.is (tok::colon)) {
4518+ // This might be an enum-base or part of some unrelated enclosing context.
4519+ //
4520+ // 'enum E : base' is permitted in two circumstances:
4521+ //
4522+ // 1) As a defining-type-specifier, when followed by '{'.
4523+ // 2) As the sole constituent of a complete declaration -- when DS is empty
4524+ // and the next token is ';'.
4525+ //
4526+ // The restriction to defining-type-specifiers is important to allow parsing
4527+ // a ? new enum E : int{}
4528+ // _Generic(a, enum E : int{})
4529+ // properly.
4530+ //
4531+ // One additional consideration applies:
4532+ //
4533+ // C++ [dcl.enum]p1:
4534+ // A ':' following "enum nested-name-specifier[opt] identifier" within
4535+ // the decl-specifier-seq of a member-declaration is parsed as part of
4536+ // an enum-base.
4537+ //
4538+ // Other lamguage modes supporting enumerations with fixed underlying types
4539+ // do not have clear rules on this, so we disambiguate to determine whether
4540+ // the tokens form a bit-field width or an enum-base.
4541+
4542+ if (CanBeBitfield && !isEnumBase (CanBeOpaqueEnumDeclaration)) {
4543+ // Outside C++11, do not interpret the tokens as an enum-base if they do
4544+ // not make sense as one. In C++11, it's an error if this happens.
4545+ if (getLangOpts ().CPlusPlus11 && !getLangOpts ().ObjC &&
4546+ !getLangOpts ().MicrosoftExt )
4547+ Diag (Tok.getLocation (), diag::err_anonymous_enum_bitfield);
4548+ } else if (CanHaveEnumBase || !ColonIsSacred) {
4549+ SourceLocation ColonLoc = ConsumeToken ();
4550+
4551+ BaseType = ParseTypeName (&BaseRange);
4552+ BaseRange.setBegin (ColonLoc);
45684553
45694554 if (!getLangOpts ().ObjC ) {
45704555 if (getLangOpts ().CPlusPlus11 )
4571- Diag (StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type);
4556+ Diag (ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type)
4557+ << BaseRange;
45724558 else if (getLangOpts ().CPlusPlus )
4573- Diag (StartLoc, diag::ext_cxx11_enum_fixed_underlying_type);
4559+ Diag (ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type)
4560+ << BaseRange;
45744561 else if (getLangOpts ().MicrosoftExt )
4575- Diag (StartLoc, diag::ext_ms_c_enum_fixed_underlying_type);
4562+ Diag (ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type)
4563+ << BaseRange;
45764564 else
4577- Diag (StartLoc, diag::ext_clang_c_enum_fixed_underlying_type);
4565+ Diag (ColonLoc, diag::ext_clang_c_enum_fixed_underlying_type)
4566+ << BaseRange;
45784567 }
45794568 }
45804569 }
@@ -4590,9 +4579,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
45904579 // enum foo {..}; void bar() { enum foo x; } <- use of old foo.
45914580 //
45924581 Sema::TagUseKind TUK;
4593- if (!AllowDeclaration) {
4582+ if (AllowEnumSpecifier == AllowDefiningTypeSpec::No)
45944583 TUK = Sema::TUK_Reference;
4595- } else if (Tok.is (tok::l_brace)) {
4584+ else if (Tok.is (tok::l_brace)) {
45964585 if (DS.isFriendSpecified ()) {
45974586 Diag (Tok.getLocation (), diag::err_friend_decl_defines_type)
45984587 << SourceRange (DS.getFriendSpecLoc ());
@@ -4623,6 +4612,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
46234612 diagsFromTag.redelay ();
46244613 }
46254614
4615+ // A C++11 enum-base can only appear as part of an enum definition or an
4616+ // opaque-enum-declaration. MSVC and ObjC permit an enum-base anywhere.
4617+ if (BaseType.isUsable () && TUK != Sema::TUK_Definition &&
4618+ !getLangOpts ().ObjC && !getLangOpts ().MicrosoftExt &&
4619+ !(CanBeOpaqueEnumDeclaration && Tok.is (tok::semi))) {
4620+ Diag (BaseRange.getBegin (), diag::ext_enum_base_in_type_specifier)
4621+ << (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes) << BaseRange;
4622+ }
4623+
46264624 MultiTemplateParamsArg TParams;
46274625 if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
46284626 TUK != Sema::TUK_Reference) {
0 commit comments