[cfe-commits] r83911 - in /cfe/trunk: lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp

Douglas Gregor dgregor at apple.com
Mon Oct 12 15:27:17 PDT 2009


Author: dgregor
Date: Mon Oct 12 17:27:17 2009
New Revision: 83911

URL: http://llvm.org/viewvc/llvm-project?rev=83911&view=rev
Log:
Permit explicit specialization of member functions of class templates
that are declarations (rather than definitions). Also, be sure to set
the access specifiers properly when instantiating the declarations of
member function templates.

Added:
    cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp
Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=83911&r1=83910&r2=83911&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Oct 12 17:27:17 2009
@@ -2810,7 +2810,7 @@
     // function templates or member functions of class templates, per
     // C++ [temp.expl.spec]p2.
     if (!IsFunctionDefinition && !isFriend &&
-        NewFD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
+        !isFunctionTemplateSpecialization && !isExplicitSpecialization) {
       Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
         << D.getCXXScopeSpec().getRange();
       NewFD->setInvalidDecl();
@@ -2979,9 +2979,17 @@
         return NewFD->setInvalidDecl();
 
       if (FunctionTemplateDecl *OldTemplateDecl
-            = dyn_cast<FunctionTemplateDecl>(OldDecl))
+                                    = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
         NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
-      else {
+        FunctionTemplateDecl *NewTemplateDecl
+          = NewFD->getDescribedFunctionTemplate();
+        assert(NewTemplateDecl && "Template/non-template mismatch");
+        if (CXXMethodDecl *Method 
+              = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
+          Method->setAccess(OldTemplateDecl->getAccess());
+          NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
+        }
+      } else {
         if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
           NewFD->setAccess(OldDecl->getAccess());
         NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=83911&r1=83910&r2=83911&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Oct 12 17:27:17 2009
@@ -431,7 +431,9 @@
 
   // Link the instantiated function template declaration to the function
   // template from which it was instantiated.
-  FunctionTemplateDecl *InstTemplate = InstMethod->getDescribedFunctionTemplate();
+  FunctionTemplateDecl *InstTemplate 
+    = InstMethod->getDescribedFunctionTemplate();
+  InstTemplate->setAccess(D->getAccess());
   assert(InstTemplate && "VisitCXXMethodDecl didn't create a template!");
   InstTemplate->setInstantiatedFromMemberTemplate(D);
   Owner->addDecl(InstTemplate);

Added: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp?rev=83911&view=auto

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp Mon Oct 12 17:27:17 2009
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only %s
+template<class T> struct A { 
+  void f(T);
+  template<class X1> void g1(T, X1); 
+  template<class X2> void g2(T, X2); 
+  void h(T) { }
+};
+
+// specialization 
+template<> void A<int>::f(int);
+
+// out of class member template definition 
+template<class T> template<class X1> void A<T>::g1(T, X1) { }
+
+// member template specialization 
+template<> template<class X1> void A<int>::g1(int, X1);
+
+// member template specialization 
+template<> template<>
+  void A<int>::g1(int, char);	// X1 deduced as char 
+
+template<> template<>
+  void A<int>::g2<char>(int, char); // X2 specified as char 
+                                    // member specialization even if defined in class definition
+
+template<> void A<int>::h(int) { }





More information about the cfe-commits mailing list