[clang] [libclang] Visit function template instantiations (PR #67928)

Daan Vanoverloop via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 1 10:05:15 PDT 2023


https://github.com/Danacus updated https://github.com/llvm/llvm-project/pull/67928

>From a516d2c53451db78147a631b5c092dbfeba73e89 Mon Sep 17 00:00:00 2001
From: Daan Vanoverloop <daan at vanoverloop.xyz>
Date: Sun, 1 Oct 2023 18:48:26 +0200
Subject: [PATCH 1/4] [libclang] Add support for template arguments of
 CXXMethod cursors

---
 clang/include/clang-c/Index.h           | 13 +++++++------
 clang/tools/c-index-test/c-index-test.c |  1 +
 clang/tools/libclang/CXCursor.cpp       |  8 ++++----
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 1b91feabd584c50..eeb23ce41ef373c 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3126,9 +3126,9 @@ CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C);
 /**
  * Retrieve the kind of the I'th template argument of the CXCursor C.
  *
- * If the argument CXCursor does not represent a FunctionDecl, StructDecl, or
- * ClassTemplatePartialSpecialization, an invalid template argument kind is
- * returned.
+ * If the argument CXCursor does not represent a FunctionDecl, CXXMethod,
+ * StructDecl, or ClassTemplatePartialSpecialization, an invalid template
+ * argument kind is returned.
  *
  * For example, for the following declaration and specialization:
  *   template <typename T, int kInt, bool kBool>
@@ -3147,9 +3147,10 @@ clang_Cursor_getTemplateArgumentKind(CXCursor C, unsigned I);
  * Retrieve a CXType representing the type of a TemplateArgument of a
  *  function decl representing a template specialization.
  *
- * If the argument CXCursor does not represent a FunctionDecl, StructDecl,
- * ClassDecl or ClassTemplatePartialSpecialization whose I'th template argument
- * has a kind of CXTemplateArgKind_Integral, an invalid type is returned.
+ * If the argument CXCursor does not represent a FunctionDecl, CXXMethod,
+ * StructDecl, ClassDecl or ClassTemplatePartialSpecialization whose I'th
+ * template argument has a kind of CXTemplateArgKind_Integral, an invalid type
+ * is returned.
  *
  * For example, for the following declaration and specialization:
  *   template <typename T, int kInt, bool kBool>
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 9d66a22f3b43b55..238c9951269d159 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -1040,6 +1040,7 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
       clang_disposeString(Name);
 
       if (Cursor.kind == CXCursor_FunctionDecl
+          || Cursor.kind == CXCursor_CXXMethod
           || Cursor.kind == CXCursor_StructDecl
           || Cursor.kind == CXCursor_ClassDecl
           || Cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index fd03c48ba1a42aa..190e0063b78d740 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -1364,8 +1364,8 @@ CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i) {
 
 int clang_Cursor_getNumTemplateArguments(CXCursor C) {
   CXCursorKind kind = clang_getCursorKind(C);
-  if (kind != CXCursor_FunctionDecl && kind != CXCursor_StructDecl &&
-      kind != CXCursor_ClassDecl &&
+  if (kind != CXCursor_FunctionDecl && kind != CXCursor_CXXMethod &&
+      kind != CXCursor_StructDecl && kind != CXCursor_ClassDecl &&
       kind != CXCursor_ClassTemplatePartialSpecialization) {
     return -1;
   }
@@ -1411,8 +1411,8 @@ enum CXGetTemplateArgumentStatus {
 static int clang_Cursor_getTemplateArgument(CXCursor C, unsigned I,
                                             TemplateArgument *TA) {
   CXCursorKind kind = clang_getCursorKind(C);
-  if (kind != CXCursor_FunctionDecl && kind != CXCursor_StructDecl &&
-      kind != CXCursor_ClassDecl &&
+  if (kind != CXCursor_FunctionDecl && kind != CXCursor_CXXMethod &&
+      kind != CXCursor_StructDecl && kind != CXCursor_ClassDecl &&
       kind != CXCursor_ClassTemplatePartialSpecialization) {
     return -1;
   }

>From fa471bdf99b7d4e44f92c6e88af4f3d9876f6b95 Mon Sep 17 00:00:00 2001
From: Daan Vanoverloop <daan at vanoverloop.xyz>
Date: Sun, 1 Oct 2023 18:48:32 +0200
Subject: [PATCH 2/4] [libclang] Visit function template instantiations

---
 clang/test/Index/index-templates.cpp     | 17 +++++++++++------
 clang/test/Index/print-display-names.cpp |  3 +++
 clang/tools/libclang/CIndex.cpp          |  9 ++++++++-
 3 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/clang/test/Index/index-templates.cpp b/clang/test/Index/index-templates.cpp
index 430a156b189d9e3..4994ddcde8d9ebc 100644
--- a/clang/test/Index/index-templates.cpp
+++ b/clang/test/Index/index-templates.cpp
@@ -54,7 +54,7 @@ void template_exprs() {
   f<Unsigned, OneDimension, value>(value<Unsigned, OneDimension>());
   Z4().getAs<Unsigned>();
 }
-
+extern template float Z4::getAs<float>();
 template<typename T> void swap(T&, T&);
 template<typename T, typename U> void swap(Y<T, U>&, Y<T, U>&);
 void swap(Z4&, Z4&);
@@ -110,6 +110,8 @@ static const int FxnTmpl_Var = 7;
 template <>
 void foo<float, 9, FxnTmplEnum_B, FxnTmpl_Var + 7>(float Value);
 
+template void foo<char, 2, FxnTmplEnum_A, FxnTmpl_Var + 3>(char Value);
+
 template <class T>
 using alias = T;
 
@@ -166,6 +168,8 @@ using alias = T;
 // CHECK-LOAD: index-templates.cpp:47:16: ClassDecl=vector:47:16 (Definition) [Specialization of vector:14:7] [Template arg 0: kind: 1, type: int *] [Template arg 1: kind: 1, type: allocator<int *>] Extent=[47:1 - 47:28]
 // CHECK-LOAD: index-templates.cpp:49:8: StructDecl=Z4:49:8 (Definition) Extent=[49:1 - 51:2]
 // CHECK-LOAD: index-templates.cpp:50:26: FunctionTemplate=getAs:50:26 Extent=[50:3 - 50:33]
+// CHECK: index-templates.cpp:50:26: CXXMethod=template<> unsigned int getAs<unsigned int>():50:26 [Specialization of getAs:50:26] [Template arg 0: kind: 1, type: unsigned int] Extent=[50:24 - 50:33] [access=public]
+// CHECK: index-templates.cpp:50:26: CXXMethod=template<> float getAs<float>():50:26 [Specialization of getAs:50:26] [Template arg 0: kind: 1, type: float] Extent=[50:24 - 50:33] [access=public]
 // CHECK-LOAD: index-templates.cpp:50:21: TemplateTypeParameter=T:50:21 (Definition) Extent=[50:12 - 50:22]
 // CHECK-LOAD: index-templates.cpp:53:6: FunctionDecl=template_exprs:53:6 (Definition)
 // CHECK-LOAD: index-templates.cpp:54:3: CallExpr=f:4:6 Extent=[54:3 - 54:68]
@@ -177,7 +181,7 @@ using alias = T;
 // CHECK-LOAD: index-templates.cpp:55:8: MemberRefExpr=getAs:50:26 SingleRefName=[55:8 - 55:13] RefName=[55:8 - 55:13] Extent=[55:3 - 55:23]
 // CHECK-LOAD: index-templates.cpp:55:3: CallExpr=Z4:49:8 Extent=[55:3 - 55:7]
 // CHECK-LOAD: index-templates.cpp:55:14: TypeRef=Unsigned:42:18 Extent=[55:14 - 55:22]
-// CHECK-LOAD: index-templates.cpp:68:6: FunctionTemplate=unresolved_exprs:68:6 (Definition)
+// CHECK-LOAD: index-templates.cpp:68:6: FunctionTemplate=unresolved_exprs:68:6 (Definition) Extent=[67:1 - 73:2]
 // CHECK-LOAD: index-templates.cpp:69:3: OverloadedDeclRef=swap[60:6, 59:39, 58:27]
 // CHECK-LOAD: index-templates.cpp:71:6: OverloadedDeclRef=f[63:7, 64:9]
 // CHECK-LOAD: index-templates.cpp:72:3: OverloadedDeclRef=swap[58:27, 59:39]
@@ -192,11 +196,12 @@ using alias = T;
 // CHECK-LOAD: index-templates.cpp:100:31: TemplateTypeParameter=U:100:31 (Definition) Extent=[100:22 - 100:32]
 // CHECK-LOAD: index-templates.cpp:101:20: C++ base class specifier=Pair<int, int>:98:16 [access=public isVirtual=false] Extent=[101:20 - 101:34]
 // CHECK-LOAD: index-templates.cpp:101:36: C++ base class specifier=Pair<T, U>:76:8 [access=public isVirtual=false] Extent=[101:36 - 101:46]
+// CHECK-LOAD: index-templates.cpp:107:6: FunctionDecl=foo:107:6 (Definition) [Specialization of foo:107:6] [Template arg 0: kind: 1, type: char] [Template arg 1: kind: 4, intval: 2] [Template arg 2: kind: 4, intval: 0] [Template arg 3: kind: 4, intval: 10] Extent=[107:1 - 107:21]
 // CHECK-LOAD: index-templates.cpp:111:6: FunctionDecl=foo:111:6 [Specialization of foo:107:6] [Template arg 0: kind: 1, type: float] [Template arg 1: kind: 4, intval: 9] [Template arg 2: kind: 4, intval: 1] [Template arg 3: kind: 4, intval: 14] Extent=[110:1 - 111:64]
-// CHECK-LOAD: index-templates.cpp:114:1: TypeAliasTemplateDecl=alias:114:1 (Definition) Extent=[113:1 - 114:16]
-// CHECK-LOAD: index-templates.cpp:113:17: TemplateTypeParameter=T:113:17 (Definition) Extent=[113:11 - 113:18] [access=public]
-// CHECK-LOAD: index-templates.cpp:114:7: TypeAliasDecl=alias:114:7 (Definition) Extent=[114:1 - 114:16]
-// CHECK-LOAD: index-templates.cpp:114:15: TypeRef=T:113:17 Extent=[114:15 - 114:16]
+// CHECK-LOAD: index-templates.cpp:116:1: TypeAliasTemplateDecl=alias:116:1 (Definition) Extent=[115:1 - 116:16]
+// CHECK-LOAD: index-templates.cpp:115:17: TemplateTypeParameter=T:115:17 (Definition) Extent=[115:11 - 115:18] [access=public]
+// CHECK-LOAD: index-templates.cpp:116:7: TypeAliasDecl=alias:116:7 (Definition) Extent=[116:1 - 116:16]
+// CHECK-LOAD: index-templates.cpp:116:15: TypeRef=T:115:17 Extent=[116:15 - 116:16]
 
 // RUN: c-index-test -test-load-source-usrs all -fno-delayed-template-parsing %s | FileCheck -check-prefix=CHECK-USRS %s
 // CHECK-USRS: index-templates.cpp c:@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22S0_#v# Extent=[3:1 - 4:22]
diff --git a/clang/test/Index/print-display-names.cpp b/clang/test/Index/print-display-names.cpp
index 7623fa838085b7c..24915690d253e2c 100644
--- a/clang/test/Index/print-display-names.cpp
+++ b/clang/test/Index/print-display-names.cpp
@@ -11,12 +11,14 @@ template<typename T>
 void g(ClassTmpl<T, T>);
 
 template<> void g<int>(ClassTmpl<int, int>);
+extern template void g<char>(ClassTmpl<char, char>);
 
 // RUN: c-index-test -test-load-source all-display %s | FileCheck %s --check-prefix=DISPLAY_NAME
 // DISPLAY_NAME: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
 // DISPLAY_NAME: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
 // DISPLAY_NAME: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
 // DISPLAY_NAME: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
+// DISPLAY_NAME: print-display-names.cpp:11:6: FunctionDecl=g<>(ClassTmpl<char, char>):11:6 [Specialization of g:11:6] [Template arg 0: kind: 1, type: char] Extent=[11:1 - 11:24]
 // DISPLAY_NAME: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
 
 // RUN: env CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT=1 c-index-test -test-load-source all-pretty %s | FileCheck %s --check-prefix=PRETTY
@@ -27,5 +29,6 @@ template<> void g<int>(ClassTmpl<int, int>);
 // PRETTY: print-display-names.cpp:8:34: ParmDecl=ClassTmpl<float, Integer> p:8:34 (Definition) Extent=[8:8 - 8:35]
 // PRETTY: print-display-names.cpp:11:6: FunctionTemplate=template <typename T> void g(ClassTmpl<T, T>):11:6 Extent=[10:1 - 11:24]
 // PRETTY: print-display-names.cpp:11:23: ParmDecl=ClassTmpl<T, T>:11:23 (Definition) Extent=[11:8 - 11:23]
+// PRETTY: print-display-names.cpp:11:6: FunctionDecl=template<> void g<char>(ClassTmpl<char, char>):11:6 [Specialization of g:11:6] [Template arg 0: kind: 1, type: char] Extent=[11:1 - 11:24]
 // PRETTY: print-display-names.cpp:13:17: FunctionDecl=template<> void g<int>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6] [Template arg 0: kind: 1, type: int] Extent=[13:1 - 13:44]
 // PRETTY: print-display-names.cpp:13:43: ParmDecl=ClassTmpl<int, int>:13:43 (Definition) Extent=[13:24 - 13:43]
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index f0c8ecfcb6264fb..aeb685694e9d114 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -962,7 +962,14 @@ bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
     return true;
 
   auto *FD = D->getTemplatedDecl();
-  return VisitAttributes(FD) || VisitFunctionDecl(FD);
+  if (VisitAttributes(FD) || VisitFunctionDecl(FD))
+    return true;
+
+  for (auto *Child : D->specializations())
+    if (Visit(MakeCXCursor(Child, TU)))
+      return true; 
+  
+  return false;
 }
 
 bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {

>From a0fb919d9823139525649adb0e6668ac5d5e32cd Mon Sep 17 00:00:00 2001
From: Daan Vanoverloop <daan at vanoverloop.xyz>
Date: Sun, 1 Oct 2023 18:57:29 +0200
Subject: [PATCH 3/4] Fix formatting

---
 clang/tools/c-index-test/c-index-test.c | 10 +++++-----
 clang/tools/libclang/CIndex.cpp         |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 238c9951269d159..b41aaf00c68ee09 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -1039,11 +1039,11 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
              clang_getCString(Name), line, column);
       clang_disposeString(Name);
 
-      if (Cursor.kind == CXCursor_FunctionDecl
-          || Cursor.kind == CXCursor_CXXMethod
-          || Cursor.kind == CXCursor_StructDecl
-          || Cursor.kind == CXCursor_ClassDecl
-          || Cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
+      if (Cursor.kind == CXCursor_FunctionDecl ||
+          Cursor.kind == CXCursor_CXXMethod ||
+          Cursor.kind == CXCursor_StructDecl ||
+          Cursor.kind == CXCursor_ClassDecl ||
+          Cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
         /* Collect the template parameter kinds from the base template. */
         int NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor);
         int I;
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index aeb685694e9d114..c747cbbeefb4d2e 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -967,7 +967,7 @@ bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
 
   for (auto *Child : D->specializations())
     if (Visit(MakeCXCursor(Child, TU)))
-      return true; 
+      return true;
   
   return false;
 }

>From 00a996cd7ca39e4cec51e7036ea67911b8e0b7ce Mon Sep 17 00:00:00 2001
From: Daan Vanoverloop <daan at vanoverloop.xyz>
Date: Sun, 1 Oct 2023 19:04:53 +0200
Subject: [PATCH 4/4] Fix formatting

---
 clang/tools/c-index-test/c-index-test.c | 8 ++++----
 clang/tools/libclang/CIndex.cpp         | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index b41aaf00c68ee09..f370c2dfca22acb 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -1044,10 +1044,10 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
           Cursor.kind == CXCursor_StructDecl ||
           Cursor.kind == CXCursor_ClassDecl ||
           Cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
-        /* Collect the template parameter kinds from the base template. */
-        int NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor);
-        int I;
-        if (NumTemplateArgs < 0) {
+          /* Collect the template parameter kinds from the base template. */
+          int NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor);
+          int I;
+          if (NumTemplateArgs < 0) {
           printf(" [no template arg info]");
         }
         for (I = 0; I < NumTemplateArgs; I++) {
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index c747cbbeefb4d2e..7cb85ee6139c53b 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -968,7 +968,7 @@ bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
   for (auto *Child : D->specializations())
     if (Visit(MakeCXCursor(Child, TU)))
       return true;
-  
+
   return false;
 }
 



More information about the cfe-commits mailing list