aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/ASTDumper.cpp10
-rw-r--r--test/Misc/ast-dump-decl.cpp39
2 files changed, 47 insertions, 2 deletions
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index cdc96b6e01..740153029b 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -947,7 +947,10 @@ void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
case TSK_ImplicitInstantiation:
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
- dumpDecl(*I);
+ if (D == D->getCanonicalDecl())
+ dumpDecl(*I);
+ else
+ dumpDeclRef(*I);
break;
case TSK_ExplicitSpecialization:
dumpDeclRef(*I);
@@ -973,7 +976,10 @@ void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
switch (I->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
- dumpDecl(*I);
+ if (D == D->getCanonicalDecl())
+ dumpDecl(*I);
+ else
+ dumpDeclRef(*I);
break;
case TSK_ExplicitSpecialization:
case TSK_ExplicitInstantiationDeclaration:
diff --git a/test/Misc/ast-dump-decl.cpp b/test/Misc/ast-dump-decl.cpp
index d8072b727a..c8f7d2fe6c 100644
--- a/test/Misc/ast-dump-decl.cpp
+++ b/test/Misc/ast-dump-decl.cpp
@@ -251,6 +251,45 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial
// CHECK-NEXT: FieldDecl{{.*}} j
+// PR15220 dump instantiation only once
+namespace testCanonicalTemplate {
+ class A {};
+
+ template<typename T> void TestFunctionTemplate(T);
+ template<typename T> void TestFunctionTemplate(T);
+ void bar(A a) { TestFunctionTemplate(a); }
+ // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
+ // CHECK-NEXT: ParmVarDecl{{.*}} 'T'
+ // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A
+ // CHECK-NEXT: TemplateArgument
+ // CHECK-NEXT: ParmVarDecl
+ // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
+ // CHECK-NEXT: ParmVarDecl{{.*}} 'T'
+ // CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate'
+ // CHECK-NEXT-NOT: TemplateArgument
+
+ template<typename T1> class TestClassTemplate {
+ template<typename T2> friend class TestClassTemplate;
+ };
+ TestClassTemplate<A> a;
+ // CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+ // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+ // CHECK-NEXT: FriendDecl
+ // CHECK-NEXT: ClassTemplateDecl{{.*}} TestClassTemplate
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+ // CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
+ // CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
+ // CHECK-NEXT: TemplateArgument{{.*}}A
+ // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+}
+
template <class T>
class TestClassScopeFunctionSpecialization {
template<class U> void foo(U a) { }