From: Alex Lorenz Date: Tue, 18 Apr 2017 15:12:34 +0000 (+0000) Subject: [ASTPrinter] Print template parameter lists for out-of-line functions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=76c33eb3db0ce968fd7b11e25571c34adf4a4fb7;p=clang [ASTPrinter] Print template parameter lists for out-of-line functions git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300560 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 5d841a197f..bc8a34c936 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -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(D); CXXConversionDecl *ConversionDecl = dyn_cast(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 diff --git a/test/Misc/ast-print-out-of-line-func.cpp b/test/Misc/ast-print-out-of-line-func.cpp index 7c4f7ae7f8..7d42f1f403 100644 --- a/test/Misc/ast-print-out-of-line-func.cpp +++ b/test/Misc/ast-print-out-of-line-func.cpp @@ -52,3 +52,44 @@ void Wrapper::Inner::staticMember() { } // CHECK: void Wrapper::Inner::staticMember() } + +template +class TemplateRecord { + void function(); + template void functionTemplate(T, U); +}; + +template +void TemplateRecord::function() { } +// CHECK: template void TemplateRecord::function() + +template +template +void TemplateRecord::functionTemplate(T, U) { } +// CHECK: template template void TemplateRecord::functionTemplate(T, U) + +template<> +class TemplateRecord<0, int> { + void function(); + template void functionTemplate(int, U); +}; + +void TemplateRecord<0, int>::function() { } +// CHECK: void TemplateRecord<0, int>::function() + +template +void TemplateRecord<0, int>::functionTemplate(int, U) { } +// CHECK: template void TemplateRecord<0, int>::functionTemplate(int, U) + +template +struct OuterTemplateRecord { + template + struct Inner { + void function(); + }; +}; + +template +template +void OuterTemplateRecord::Inner::function() { } +// CHECK: template template void OuterTemplateRecord::Inner::function()