Action &Actions;
Action::ParsingDeclStackState State;
bool Popped;
-
+
public:
ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
push();
}
+ ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *Other)
+ : Actions(P.Actions) {
+ if (Other) steal(*Other);
+ else push();
+ }
+
+ /// Creates a RAII object which steals the state from a different
+ /// object instead of pushing.
+ ParsingDeclRAIIObject(ParsingDeclRAIIObject &Other)
+ : Actions(Other.Actions) {
+ steal(Other);
+ }
+
~ParsingDeclRAIIObject() {
abort();
}
}
private:
+ void steal(ParsingDeclRAIIObject &Other) {
+ State = Other.State;
+ Popped = Other.Popped;
+ Other.Popped = true;
+ }
+
void push() {
State = Actions.PushParsingDeclaration();
Popped = false;
ParsingDeclRAIIObject ParsingRAII;
public:
- ParsingDeclSpec(Parser &P) : ParsingRAII(P) {
- }
+ ParsingDeclSpec(Parser &P) : ParsingRAII(P) {}
+ ParsingDeclSpec(ParsingDeclRAIIObject &RAII) : ParsingRAII(RAII) {}
+ ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
+ : ParsingRAII(P, RAII) {}
void complete(DeclPtrTy D) {
ParsingRAII.complete(D);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
DeclPtrTy TagDecl);
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
- const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ParsingDeclRAIIObject *DiagsFromTParams = 0);
void ParseConstructorInitializer(DeclPtrTy ConstructorDecl);
MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl);
void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
DeclPtrTy ParseSingleDeclarationAfterTemplate(
unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromParams,
SourceLocation &DeclEnd,
AccessSpecifier AS=AS_none);
bool ParseTemplateParameters(unsigned Depth,
/// '=' constant-expression
///
void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
- const ParsedTemplateInfo &TemplateInfo) {
+ const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject *TemplateDiags) {
// Access declarations.
if (!TemplateInfo.Kind &&
(Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
ConsumeToken();
- return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
+ return ParseCXXClassMemberDeclaration(AS, TemplateInfo, TemplateDiags);
}
// Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
SourceLocation DSStart = Tok.getLocation();
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
- ParsingDeclSpec DS(*this);
+ ParsingDeclSpec DS(*this, TemplateDiags);
DS.AddAttributes(AttrList.AttrList);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
if (Tok.is(tok::semi)) {
ConsumeToken();
- Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ DeclPtrTy TheDecl =
+ Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ DS.complete(TheDecl);
return;
}
// Enter template-parameter scope.
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+ // Tell the action that names should be checked in the context of
+ // the declaration to come.
+ ParsingDeclRAIIObject ParsingTemplateParams(*this);
+
// Parse multiple levels of template headers within this template
// parameter scope, e.g.,
//
ParsedTemplateInfo(&ParamLists,
isSpecialization,
LastParamListWasEmpty),
+ ParsingTemplateParams,
DeclEnd, AS);
}
Parser::ParseSingleDeclarationAfterTemplate(
unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromTParams,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
if (Context == Declarator::MemberContext) {
// We are parsing a member template.
- ParseCXXClassMemberDeclaration(AS, TemplateInfo);
+ ParseCXXClassMemberDeclaration(AS, TemplateInfo, &DiagsFromTParams);
return DeclPtrTy::make((void*)0);
}
- // Parse the declaration specifiers.
- ParsingDeclSpec DS(*this);
+ // Parse the declaration specifiers, stealing the accumulated
+ // diagnostics from the template parameters.
+ ParsingDeclSpec DS(DiagsFromTParams);
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
DS.AddAttributes(ParseCXX0XAttributes().AttrList);
Parser::ParseExplicitInstantiation(SourceLocation ExternLoc,
SourceLocation TemplateLoc,
SourceLocation &DeclEnd) {
+ // This isn't really required here.
+ ParsingDeclRAIIObject ParsingTemplateParams(*this);
+
return ParseSingleDeclarationAfterTemplate(Declarator::FileContext,
ParsedTemplateInfo(ExternLoc,
TemplateLoc),
+ ParsingTemplateParams,
DeclEnd, AS_none);
}
<< DS.getSourceRange();
}
- return DeclPtrTy::make(Tag);
+ return DeclPtrTy::make(TagD);
}
/// We are trying to inject an anonymous member into the given scope;
foo(a, 0);
}
}
+
+// PR7644
+namespace test5 {
+ class A {
+ enum Enum { E0, E1, E2 }; // expected-note 4 {{declared private here}}
+ template <Enum> void foo();
+ template <Enum> class bar;
+ };
+
+ template <A::Enum en> void A::foo() {}
+ template <A::Enum en> class A::bar {};
+
+ template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}}
+ template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}}
+
+ class B {
+ template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}}
+ template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}}
+ };
+}