forked from OSchip/llvm-project
AST dumping: dump template instantiations only once
Fixes infinite loop in PR15220. Patch by Philip Craig. llvm-svn: 175805
This commit is contained in:
parent
9b7f9c3e9e
commit
efc6dfb446
|
@ -947,7 +947,10 @@ void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
|
|||
case TSK_ImplicitInstantiation:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
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:
|
||||
if (D == D->getCanonicalDecl())
|
||||
dumpDecl(*I);
|
||||
else
|
||||
dumpDeclRef(*I);
|
||||
break;
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
|
|
|
@ -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) { }
|
||||
|
|
Loading…
Reference in New Issue