]> granicus.if.org Git - clang/commitdiff
Treat template parameters as part of the declaration-specifiers for the
authorJohn McCall <rjmccall@apple.com>
Fri, 16 Jul 2010 08:13:16 +0000 (08:13 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 16 Jul 2010 08:13:16 +0000 (08:13 +0000)
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

include/clang/Parse/Parser.h
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseTemplate.cpp
lib/Sema/SemaDecl.cpp
test/CXX/class.access/p6.cpp

index b8c294ada6914c595aff0469b2a9b40e7e41607c..90a1cab5cf12705e95cdd41a4dad5a8a20bc05ae 100644 (file)
@@ -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,
index 590ba6c6f8bcd62b1d3203b8527c21cbcc16ee85..1d812583672540bf156dc443941b14d70d33fe60 100644 (file)
@@ -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;
   }
 
index e1aaf91bd65895f59cfe818da80ad4d9f233d368..dfb1c864096276459ed6c0bcb079b6393f008ab5 100644 (file)
@@ -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);
 }
index 538d56470fdabdc5ba338f7887e9764208c866e0..29ecdbc680a240f94a2051f8ec1cab7884062692 100644 (file)
@@ -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;
index 734a4d8c486922b7679c9e27737ec6faaa07df88..87957084747a60d36c5806fcc38a624b138eacfc 100644 (file)
@@ -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'}}
+  };
+}