AST dumping: dump template instantiations only once
authorDmitri Gribenko <gribozavr@gmail.com>
Thu, 21 Feb 2013 22:01:10 +0000 (22:01 +0000)
committerDmitri Gribenko <gribozavr@gmail.com>
Thu, 21 Feb 2013 22:01:10 +0000 (22:01 +0000)
Fixes infinite loop in PR15220.

Patch by Philip Craig.

llvm-svn: 175805

clang/lib/AST/ASTDumper.cpp
clang/test/Misc/ast-dump-decl.cpp

index cdc96b6..7401530 100644 (file)
@@ -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:
index d8072b7..c8f7d2f 100644 (file)
@@ -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) { }