aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r--lib/Parse/ParseDeclCXX.cpp22
1 files changed, 22 insertions, 0 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 53fc3405bb..ffef288e71 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -613,6 +613,20 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ConsumeCodeCompletionToken();
}
+ // C++03 [temp.explicit] 14.7.2/8:
+ // The usual access checking rules do not apply to names used to specify
+ // explicit instantiations.
+ //
+ // As an extension we do not perform access checking on the names used to
+ // specify explicit specializations either. This is important to allow
+ // specializing traits classes for private types.
+ bool SuppressingAccessChecks = false;
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
+ TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) {
+ Actions.ActOnStartSuppressingAccessChecks();
+ SuppressingAccessChecks = true;
+ }
+
AttributeList *AttrList = 0;
// If attributes exist after tag, parse them.
if (Tok.is(tok::kw___attribute))
@@ -732,10 +746,18 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
DS.SetTypeSpecError();
SkipUntil(tok::semi, false, true);
TemplateId->Destroy();
+ if (SuppressingAccessChecks)
+ Actions.ActOnStopSuppressingAccessChecks();
+
return;
}
}
+ // As soon as we're finished parsing the class's template-id, turn access
+ // checking back on.
+ if (SuppressingAccessChecks)
+ Actions.ActOnStopSuppressingAccessChecks();
+
// There are four options here. If we have 'struct foo;', then this
// is either a forward declaration or a friend declaration, which
// have to be treated differently. If we have 'struct foo {...' or