[cfe-commits] r101173 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/CXX/class.access/class.friend/p1.cpp

John McCall rjmccall at apple.com
Tue Apr 13 13:37:33 PDT 2010


Author: rjmccall
Date: Tue Apr 13 15:37:33 2010
New Revision: 101173

URL: http://llvm.org/viewvc/llvm-project?rev=101173&view=rev
Log:
Support befriending members of class template specializations.


Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/class.access/class.friend/p1.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=101173&r1=101172&r2=101173&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Apr 13 15:37:33 2010
@@ -2771,6 +2771,7 @@
                                           const CXXScopeSpec &SS,
                                           TemplateParameterList **ParamLists,
                                           unsigned NumParamLists,
+                                          bool IsFriend,
                                           bool &IsExplicitSpecialization);
 
   DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=101173&r1=101172&r2=101173&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Apr 13 15:37:33 2010
@@ -2393,6 +2393,7 @@
                                                   D.getCXXScopeSpec(),
                         (TemplateParameterList**)TemplateParamLists.get(),
                                                    TemplateParamLists.size(),
+                                                  /*never a friend*/ false,
                                                   isExplicitSpecialization)) {
     if (TemplateParams->size() > 0) {
       // There is no such thing as a variable template.
@@ -2943,6 +2944,7 @@
                                   D.getCXXScopeSpec(),
                            (TemplateParameterList**)TemplateParamLists.get(),
                                                   TemplateParamLists.size(),
+                                                  isFriend,
                                                   isExplicitSpecialization)) {
     if (TemplateParams->size() > 0) {
       // This is a function template
@@ -3041,10 +3043,8 @@
     if (FunctionTemplate) {
       FunctionTemplate->setObjectOfFriendDecl(false);
       FunctionTemplate->setAccess(AS_public);
-    } else {
-      NewFD->setObjectOfFriendDecl(false);
     }
-
+    NewFD->setObjectOfFriendDecl(false);
     NewFD->setAccess(AS_public);
   }
 
@@ -3198,10 +3198,6 @@
       NewFD->setInvalidDecl();
   }
 
-  // Make sure this is set before checking the function declaration.
-  // We'll override the visibility type later.
-  if (isFriend) NewFD->setObjectOfFriendDecl(false);
-    
   // Perform semantic checking on the function declaration.
   bool OverloadableAttrRequired = false; // FIXME: HACK!
   CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
@@ -4766,6 +4762,7 @@
           = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
                         (TemplateParameterList**)TemplateParameterLists.get(),
                                               TemplateParameterLists.size(),
+                                                    TUK == TUK_Friend,
                                                     isExplicitSpecialization)) {
       if (TemplateParams->size() > 0) {
         // This is a declaration or definition of a class template (which may

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=101173&r1=101172&r2=101173&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Apr 13 15:37:33 2010
@@ -1229,6 +1229,10 @@
 ///
 /// \param NumParamLists the number of template parameter lists in ParamLists.
 ///
+/// \param IsFriend Whether to apply the slightly different rules for
+/// matching template parameters to scope specifiers in friend
+/// declarations.
+///
 /// \param IsExplicitSpecialization will be set true if the entity being
 /// declared is an explicit specialization, false otherwise.
 ///
@@ -1243,6 +1247,7 @@
                                               const CXXScopeSpec &SS,
                                           TemplateParameterList **ParamLists,
                                               unsigned NumParamLists,
+                                              bool IsFriend,
                                               bool &IsExplicitSpecialization) {
   IsExplicitSpecialization = false;
   
@@ -1308,6 +1313,13 @@
     if (Idx >= NumParamLists) {
       // We have a template-id without a corresponding template parameter
       // list.
+
+      // ...which is fine if this is a friend declaration.
+      if (IsFriend) {
+        IsExplicitSpecialization = true;
+        break;
+      }
+
       if (DependentTemplateId) {
         // FIXME: the location information here isn't great.
         Diag(SS.getRange().getBegin(),
@@ -3538,6 +3550,7 @@
     = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS,
                         (TemplateParameterList**)TemplateParameterLists.get(),
                                               TemplateParameterLists.size(),
+                                              TUK == TUK_Friend,
                                               isExplicitSpecialization);
   if (TemplateParams && TemplateParams->size() > 0) {
     isPartialSpecialization = true;
@@ -4302,7 +4315,7 @@
 bool 
 Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
   assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
-         
+
   // Try to find the member we are instantiating.
   NamedDecl *Instantiation = 0;
   NamedDecl *InstantiatedFrom = 0;
@@ -4348,6 +4361,25 @@
     // this mismatch later.
     return false;
   }
+
+  // If this is a friend, just bail out here before we start turning
+  // things into explicit specializations.
+  if (Member->getFriendObjectKind() != Decl::FOK_None) {
+    // Preserve instantiation information.
+    if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) {
+      cast<CXXMethodDecl>(Member)->setInstantiationOfMemberFunction(
+                                      cast<CXXMethodDecl>(InstantiatedFrom),
+        cast<CXXMethodDecl>(Instantiation)->getTemplateSpecializationKind());
+    } else if (InstantiatedFrom && isa<CXXRecordDecl>(Member)) {
+      cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
+                                      cast<CXXRecordDecl>(InstantiatedFrom),
+        cast<CXXRecordDecl>(Instantiation)->getTemplateSpecializationKind());
+    }
+
+    Previous.clear();
+    Previous.addDecl(Instantiation);
+    return false;
+  }
   
   // Make sure that this is a specialization of a member.
   if (!InstantiatedFrom) {

Modified: cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p1.cpp?rev=101173&r1=101172&r2=101173&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/class.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/class.access/class.friend/p1.cpp Tue Apr 13 15:37:33 2010
@@ -222,3 +222,37 @@
     friend A &A::operator=(const A&);
   };
 }
+
+namespace test7 {
+  template <class T> struct X {
+    X();
+    ~X();
+    void foo();
+    void bar();
+  };
+
+  class A {
+    friend void X<int>::foo();
+    friend X<int>::X();
+    friend X<int>::X(const X&);
+
+  private:
+    A(); // expected-note 2 {{declared private here}}
+  };
+
+  template<> void X<int>::foo() {
+    A a;
+  }
+
+  template<> void X<int>::bar() {
+    A a; // expected-error {{calling a private constructor}}
+  }
+
+  template<> X<int>::X() {
+    A a;
+  }
+
+  template<> X<int>::~X() {
+    A a; // expected-error {{calling a private constructor}}
+  }
+}





More information about the cfe-commits mailing list