aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r--lib/Parse/ParseDecl.cpp60
1 files changed, 36 insertions, 24 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index dbf35b14cf..7cb6474678 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2773,12 +2773,16 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
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);
+ // 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. Note that
+ // we don't suppress if this turns out to be an elaborated type
+ // specifier.
+ bool shouldDelayDiagsInTag =
+ (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
+ TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
+ SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
// If attributes exist after tag, parse them.
ParsedAttributes attrs(AttrFactory);
@@ -2842,8 +2846,10 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
IsScopedUsingClassTag = false;
}
- // Stop suppressing access control now we've parsed the enum name.
- SuppressAccess.done();
+ // Okay, end the suppression area. We'll decide whether to emit the
+ // diagnostics in a second.
+ if (shouldDelayDiagsInTag)
+ diagsFromTag.done();
TypeResult BaseType;
@@ -2925,16 +2931,29 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// enum foo {..}; void bar() { enum foo x; } <- use of old foo.
//
Sema::TagUseKind TUK;
- if (DS.isFriendSpecified())
- TUK = Sema::TUK_Friend;
- else if (!AllowDeclaration)
+ if (!AllowDeclaration) {
TUK = Sema::TUK_Reference;
- else if (Tok.is(tok::l_brace))
- TUK = Sema::TUK_Definition;
- else if (Tok.is(tok::semi) && DSC != DSC_type_specifier)
- TUK = Sema::TUK_Declaration;
- else
+ } else if (Tok.is(tok::l_brace)) {
+ if (DS.isFriendSpecified()) {
+ Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)
+ << SourceRange(DS.getFriendSpecLoc());
+ ConsumeBrace();
+ SkipUntil(tok::r_brace);
+ TUK = Sema::TUK_Friend;
+ } else {
+ TUK = Sema::TUK_Definition;
+ }
+ } else if (Tok.is(tok::semi) && DSC != DSC_type_specifier) {
+ TUK = (DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration);
+ } else {
TUK = Sema::TUK_Reference;
+ }
+
+ // If this is an elaborated type specifier, and we delayed
+ // diagnostics before, just merge them into the current pool.
+ if (TUK == Sema::TUK_Reference && shouldDelayDiagsInTag) {
+ diagsFromTag.redelay();
+ }
MultiTemplateParamsArg TParams;
if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
@@ -3014,14 +3033,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) {
- if (TUK == Sema::TUK_Friend) {
- Diag(Tok, diag::err_friend_decl_defines_type)
- << SourceRange(DS.getFriendSpecLoc());
- ConsumeBrace();
- SkipUntil(tok::r_brace);
- } else {
- ParseEnumBody(StartLoc, TagDecl);
- }
+ ParseEnumBody(StartLoc, TagDecl);
}
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,