From efc6dfb446251abcb3993de8bb66359d042be118 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Thu, 21 Feb 2013 22:01:10 +0000 Subject: [PATCH] AST dumping: dump template instantiations only once Fixes infinite loop in PR15220. Patch by Philip Craig. llvm-svn: 175805 --- clang/lib/AST/ASTDumper.cpp | 10 ++++++-- clang/test/Misc/ast-dump-decl.cpp | 39 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index cdc96b6e0161..740153029bae 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/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/clang/test/Misc/ast-dump-decl.cpp b/clang/test/Misc/ast-dump-decl.cpp index d8072b727aba..c8f7d2fe6ccf 100644 --- a/clang/test/Misc/ast-dump-decl.cpp +++ b/clang/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 void TestFunctionTemplate(T); + template 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 class TestClassTemplate { + template friend class TestClassTemplate; + }; + TestClassTemplate 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 TestClassScopeFunctionSpecialization { template void foo(U a) { }