Parse friend template ids as types instead of ending up in
ActOnClassTemplateSpecialization and being very confused.
Fixes PR6514 (for non-templated-scope friends).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101198 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index c6df571..60aee6a 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -780,9 +780,6 @@
   Action::DeclResult TagOrTempResult = true; // invalid
   Action::TypeResult TypeResult = true; // invalid
 
-  // FIXME: When TUK == TUK_Reference and we have a template-id, we need
-  // to turn that template-id into a type.
-
   bool Owned = false;
   if (TemplateId) {
     // Explicit specialization, class template partial specialization,
@@ -806,7 +803,14 @@
                                              TemplateArgsPtr,
                                              TemplateId->RAngleLoc,
                                              AttrList);
-    } else if (TUK == Action::TUK_Reference) {
+
+    // Friend template-ids are treated as references unless
+    // they have template headers, in which case they're ill-formed
+    // (FIXME: "template <class T> friend class A<T>::B<int>;").
+    // We diagnose this error in ActOnClassTemplateSpecialization.
+    } else if (TUK == Action::TUK_Reference ||
+               (TUK == Action::TUK_Friend &&
+                TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
       TypeResult
         = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
                                       TemplateId->TemplateNameLoc,
diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp
index 41cf363..7604a23 100644
--- a/test/CXX/temp/temp.decls/temp.friend/p1.cpp
+++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp
@@ -276,3 +276,20 @@
     return Foo<long>(t, true);
   }
 }
+
+// PR6514
+namespace test13 {
+  template <int N, template <int> class Temp>
+  class Role : public Temp<N> {
+    friend class Temp<N>;
+    int x;
+  };
+
+  template <int N> class Foo {
+    void foo(Role<N, test13::Foo> &role) {
+      (void) role.x;
+    }
+  };
+
+  template class Foo<0>;
+}