diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-23 03:33:32 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-23 03:33:32 +0000 |
commit | 1af83c444e5a2f6f50a6e1c15e6ebc618ae18a5f (patch) | |
tree | 8a325a6f98d042574b75774b359263f77a7d32e8 /lib/Parse/ParseDecl.cpp | |
parent | ccc6f36e53274fccae024f30ac5adb6be6f815d3 (diff) |
Support for definitions of member enumerations of class templates outside the
class template's definition, and for explicit specializations of such enum
members.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153304 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 71 |
1 files changed, 48 insertions, 23 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 6f344f6691..24386d08ba 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2611,19 +2611,20 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, /// 'enum' identifier /// [GNU] 'enum' attributes[opt] identifier /// -/// [C++0x] enum-head '{' enumerator-list[opt] '}' -/// [C++0x] enum-head '{' enumerator-list ',' '}' +/// [C++11] enum-head '{' enumerator-list[opt] '}' +/// [C++11] enum-head '{' enumerator-list ',' '}' /// -/// enum-head: [C++0x] -/// enum-key attributes[opt] identifier[opt] enum-base[opt] -/// enum-key attributes[opt] nested-name-specifier identifier enum-base[opt] +/// enum-head: [C++11] +/// enum-key attribute-specifier-seq[opt] identifier[opt] enum-base[opt] +/// enum-key attribute-specifier-seq[opt] nested-name-specifier +/// identifier enum-base[opt] /// -/// enum-key: [C++0x] +/// enum-key: [C++11] /// 'enum' /// 'enum' 'class' /// 'enum' 'struct' /// -/// enum-base: [C++0x] +/// enum-base: [C++11] /// ':' type-specifier-seq /// /// [C++] elaborated-type-specifier: @@ -2648,7 +2649,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, IsScopedUsingClassTag = Tok.is(tok::kw_class); ScopedEnumKWLoc = ConsumeToken(); } - + + // C++11 [temp.explicit]p12: The usual access controls do not apply to names + // used to specify explicit instantiations. We extend this to also cover + // explicit specializations. + Sema::SuppressAccessChecksRAII SuppressAccess(Actions, + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation || + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization); + // If attributes exist after tag, parse them. ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); @@ -2711,6 +2719,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, IsScopedUsingClassTag = false; } + // Stop suppressing access control now we've parsed the enum name. + SuppressAccess.done(); + TypeResult BaseType; // Parse the fixed underlying type. @@ -2801,34 +2812,44 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, TUK = Sema::TUK_Declaration; else TUK = Sema::TUK_Reference; - - // enums cannot be templates, although they can be referenced from a - // template. + + MultiTemplateParamsArg TParams; if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && TUK != Sema::TUK_Reference) { - Diag(Tok, diag::err_enum_template); - - // Skip the rest of this declarator, up until the comma or semicolon. - SkipUntil(tok::comma, true); - return; + if (!getLangOpts().CPlusPlus0x || !SS.isSet()) { + // Skip the rest of this declarator, up until the comma or semicolon. + Diag(Tok, diag::err_enum_template); + SkipUntil(tok::comma, true); + return; + } + + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { + // Enumerations can't be explicitly instantiated. + DS.SetTypeSpecError(); + Diag(StartLoc, diag::err_explicit_instantiation_enum); + return; + } + + assert(TemplateInfo.TemplateParams && "no template parameters"); + TParams = MultiTemplateParamsArg(TemplateInfo.TemplateParams->data(), + TemplateInfo.TemplateParams->size()); } - + if (!Name && TUK != Sema::TUK_Definition) { Diag(Tok, diag::err_enumerator_unnamed_no_def); - + // Skip the rest of this declarator, up until the comma or semicolon. SkipUntil(tok::comma, true); return; } - + bool Owned = false; bool IsDependent = false; const char *PrevSpec = 0; unsigned DiagID; Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, attrs.getList(), - AS, DS.getModulePrivateSpecLoc(), - MultiTemplateParamsArg(Actions), + AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType); @@ -2870,10 +2891,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) { - if (TUK == Sema::TUK_Friend) + if (TUK == Sema::TUK_Friend) { Diag(Tok, diag::err_friend_decl_defines_type) << SourceRange(DS.getFriendSpecLoc()); - ParseEnumBody(StartLoc, TagDecl); + ConsumeBrace(); + SkipUntil(tok::r_brace); + } else { + ParseEnumBody(StartLoc, TagDecl); + } } if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, |