diff options
author | John McCall <rjmccall@apple.com> | 2010-07-16 08:13:16 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-07-16 08:13:16 +0000 |
commit | c9068d7dd94d439cec66c421115d15303e481025 (patch) | |
tree | 8c9940175bcfc7c9ba1db3fbe19c759a3c4755e0 | |
parent | 34fa29485d6e0b22f1f32852f34e483db0f90b0d (diff) |
Treat template parameters as part of the declaration-specifiers for the
purpose of access control. Fixes PR7644.
I can't actually find anything directly justifying this, but it seems obvious.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108521 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Parser.h | 31 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 11 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | test/CXX/class.access/p6.cpp | 20 |
5 files changed, 69 insertions, 12 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index b8c294ada6..90a1cab5cf 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -654,12 +654,25 @@ private: 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(); } @@ -682,6 +695,12 @@ private: } private: + void steal(ParsingDeclRAIIObject &Other) { + State = Other.State; + Popped = Other.Popped; + Other.Popped = true; + } + void push() { State = Actions.PushParsingDeclaration(); Popped = false; @@ -700,8 +719,10 @@ private: 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); @@ -1414,7 +1435,8 @@ private: 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, @@ -1457,6 +1479,7 @@ private: DeclPtrTy ParseSingleDeclarationAfterTemplate( unsigned Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd, AccessSpecifier AS=AS_none); bool ParseTemplateParameters(unsigned Depth, diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 590ba6c6f8..1d81258367 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1218,7 +1218,8 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, /// '=' 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)) && @@ -1281,7 +1282,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // __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 @@ -1317,7 +1318,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, 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); @@ -1327,7 +1328,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::semi)) { ConsumeToken(); - Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); + DeclPtrTy TheDecl = + Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); + DS.complete(TheDecl); return; } diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index e1aaf91bd6..dfb1c86409 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -80,6 +80,10 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, // 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., // @@ -152,6 +156,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, ParsedTemplateInfo(&ParamLists, isSpecialization, LastParamListWasEmpty), + ParsingTemplateParams, DeclEnd, AS); } @@ -179,6 +184,7 @@ Parser::DeclPtrTy Parser::ParseSingleDeclarationAfterTemplate( unsigned Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd, AccessSpecifier AS) { assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && @@ -186,12 +192,13 @@ Parser::ParseSingleDeclarationAfterTemplate( 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); @@ -1057,8 +1064,12 @@ Parser::DeclPtrTy 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); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 538d56470f..29ecdbc680 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1562,7 +1562,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, << DS.getSourceRange(); } - return DeclPtrTy::make(Tag); + return DeclPtrTy::make(TagD); } /// We are trying to inject an anonymous member into the given scope; diff --git a/test/CXX/class.access/p6.cpp b/test/CXX/class.access/p6.cpp index 734a4d8c48..8795708474 100644 --- a/test/CXX/class.access/p6.cpp +++ b/test/CXX/class.access/p6.cpp @@ -119,3 +119,23 @@ namespace test4 { 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'}} + }; +} |