]> granicus.if.org Git - clang/commitdiff
[ASTPrinter] Print template parameter lists for out-of-line functions
authorAlex Lorenz <arphaman@gmail.com>
Tue, 18 Apr 2017 15:12:34 +0000 (15:12 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 18 Apr 2017 15:12:34 +0000 (15:12 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300560 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/DeclPrinter.cpp
test/Misc/ast-print-out-of-line-func.cpp

index 5d841a197f26dfec7a6ce24e6d97d77e77a63a2f..bc8a34c9365363102dda2b27f3de4ec2291a4211 100644 (file)
@@ -478,6 +478,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
 
   if (D->isFunctionTemplateSpecialization())
     Out << "template<> ";
+  else if (!D->getDescribedFunctionTemplate()) {
+    for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists();
+         I < NumTemplateParams; ++I)
+      printTemplateParameters(D->getTemplateParameterList(I));
+  }
 
   CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
   CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
@@ -1055,6 +1060,12 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
 
 void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
   prettyPrintPragmas(D->getTemplatedDecl());
+  // Print any leading template parameter lists.
+  if (const FunctionDecl *FD = D->getTemplatedDecl()) {
+    for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists();
+         I < NumTemplateParams; ++I)
+      printTemplateParameters(FD->getTemplateParameterList(I));
+  }
   VisitRedeclarableTemplateDecl(D);
 
   // Never print "instantiations" for deduction guides (they don't really
index 7c4f7ae7f813a290dd69b2e84ecc9bbd81db2c75..7d42f1f4037fe7184ebe2c56a8f699e16084c891 100644 (file)
@@ -52,3 +52,44 @@ void Wrapper::Inner::staticMember() { }
 // CHECK: void Wrapper::Inner::staticMember()
 
 }
+
+template<int x, typename T>
+class TemplateRecord {
+  void function();
+  template<typename U> void functionTemplate(T, U);
+};
+
+template<int x, typename T>
+void TemplateRecord<x, T>::function() { }
+// CHECK: template <int x, typename T> void TemplateRecord<x, T>::function()
+
+template<int x, typename T>
+template<typename U>
+void TemplateRecord<x, T>::functionTemplate(T, U) { }
+// CHECK: template <int x, typename T> template <typename U> void TemplateRecord<x, T>::functionTemplate(T, U)
+
+template<>
+class TemplateRecord<0, int> {
+  void function();
+  template<typename U> void functionTemplate(int, U);
+};
+
+void TemplateRecord<0, int>::function() { }
+// CHECK: void TemplateRecord<0, int>::function()
+
+template<typename U>
+void TemplateRecord<0, int>::functionTemplate(int, U) { }
+// CHECK: template <typename U> void TemplateRecord<0, int>::functionTemplate(int, U)
+
+template<typename T>
+struct OuterTemplateRecord {
+  template<typename U>
+  struct Inner {
+    void function();
+  };
+};
+
+template<typename T>
+template<typename U>
+void OuterTemplateRecord<T>::Inner<U>::function() { }
+// CHECK: template <typename T> template <typename U> void OuterTemplateRecord<T>::Inner<U>::function()