]> granicus.if.org Git - clang/commitdiff
When declaring a friend class template, we may end up finding an
authorDouglas Gregor <dgregor@apple.com>
Fri, 9 Oct 2009 21:11:42 +0000 (21:11 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 9 Oct 2009 21:11:42 +0000 (21:11 +0000)
injected-class-name (e.g., when we're referring to other
specializations of the current class template). Make sure that we see
the template rather than the injected-class-name. Fixes PR4768.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83672 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplate.cpp
test/SemaTemplate/friend-template.cpp

index 219d73146ea39f75e1d3ba4b6cea25c361fb76a9..3ee257a94eb5d8ec20d7ce46ec8880986639fc19 100644 (file)
@@ -616,6 +616,22 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
   // whether this is a valid redeclaration.
   ClassTemplateDecl *PrevClassTemplate
     = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+
+  // We may have found the injected-class-name of a class template,
+  // class template partial specialization, or class template specialization. 
+  // In these cases, grab the template that is being defined or specialized.
+  if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) && 
+      cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
+    PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
+    PrevClassTemplate 
+      = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
+    if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
+      PrevClassTemplate
+        = cast<ClassTemplateSpecializationDecl>(PrevDecl)
+            ->getSpecializedTemplate();
+    }
+  }
+
   if (PrevClassTemplate) {
     // Ensure that the template parameter lists are compatible.
     if (!TemplateParameterListsAreEqual(TemplateParams,
index df27c920b7bc4dbe8ba5cc3e5c546d10f7ddbd32..9a483aeb5b1e8ba9b2fc6147ad7bbe8fe0fb2106 100644 (file)
@@ -28,3 +28,19 @@ namespace N {
   template<typename T> void f0(T) { }
   template<typename T> void f1(T) { } // expected-error{{redefinition}}
 }
+
+// PR4768
+template<typename T>
+struct X0 {
+  template<typename U> friend struct X0;
+};
+
+template<typename T>
+struct X0<T*> {
+  template<typename U> friend struct X0;
+};
+
+template<>
+struct X0<int> {
+  template<typename U> friend struct X0;
+};