When instantiating a friend function template, don't forget to inherit default templa...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 10 May 2017 00:01:13 +0000 (00:01 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 10 May 2017 00:01:13 +0000 (00:01 +0000)
llvm-svn: 302603

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/SemaTemplate/default-arguments.cpp

index 226bd60..03df6fd 100644 (file)
@@ -1849,6 +1849,19 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
         }
       }
     }
+
+    // Check the template parameter list against the previous declaration. The
+    // goal here is to pick up default arguments added since the friend was
+    // declared; we know the template parameter lists match, since otherwise
+    // we would not have picked this template as the previous declaration.
+    if (TemplateParams && FunctionTemplate->getPreviousDecl()) {
+      SemaRef.CheckTemplateParameterList(
+          TemplateParams,
+          FunctionTemplate->getPreviousDecl()->getTemplateParameters(),
+          Function->isThisDeclarationADefinition()
+              ? Sema::TPC_FriendFunctionTemplateDefinition
+              : Sema::TPC_FriendFunctionTemplate);
+    }
   }
 
   if (Function->isLocalExternDecl() && !Function->getPreviousDecl())
index d3e249d..b5b042c 100644 (file)
@@ -207,3 +207,19 @@ Y<false> y2;
 
 } // end ns1
 } // end ns PR26134
+
+namespace friends {
+  namespace ns {
+    template<typename> struct A {
+      template<typename> friend void f();
+      template<typename> friend struct X;
+    };
+    template<typename = int> void f(); // expected-warning 0-1{{extension}}
+    template<typename = int> struct X;
+    A<int> a;
+  }
+  namespace ns {
+    void g() { f(); }
+    X<int> *p;
+  }
+}