AST dumping: dump template instantiations only once

Fixes infinite loop in PR15220.

Patch by Philip Craig.

llvm-svn: 175805
This commit is contained in:
Dmitri Gribenko 2013-02-21 22:01:10 +00:00
parent 9b7f9c3e9e
commit efc6dfb446
2 changed files with 47 additions and 2 deletions

View File

@ -947,7 +947,10 @@ void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
case TSK_ImplicitInstantiation: case TSK_ImplicitInstantiation:
case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition: case TSK_ExplicitInstantiationDefinition:
if (D == D->getCanonicalDecl())
dumpDecl(*I); dumpDecl(*I);
else
dumpDeclRef(*I);
break; break;
case TSK_ExplicitSpecialization: case TSK_ExplicitSpecialization:
dumpDeclRef(*I); dumpDeclRef(*I);
@ -973,7 +976,10 @@ void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
switch (I->getTemplateSpecializationKind()) { switch (I->getTemplateSpecializationKind()) {
case TSK_Undeclared: case TSK_Undeclared:
case TSK_ImplicitInstantiation: case TSK_ImplicitInstantiation:
if (D == D->getCanonicalDecl())
dumpDecl(*I); dumpDecl(*I);
else
dumpDeclRef(*I);
break; break;
case TSK_ExplicitSpecialization: case TSK_ExplicitSpecialization:
case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDeclaration:

View File

@ -251,6 +251,45 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial
// CHECK-NEXT: FieldDecl{{.*}} j // 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> template <class T>
class TestClassScopeFunctionSpecialization { class TestClassScopeFunctionSpecialization {
template<class U> void foo(U a) { } template<class U> void foo(U a) { }