llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (fscheidl)

<details>
<summary>Changes</summary>

### Bug fixes to existing APIs:

**clang_Cursor_getNumTemplateArguments**:
- Add `CXCursor_CXXMethod` to accepted cursor kinds, queries on method 
specializations would incorrectly return -1 before
- Expand parameter packs into a flat count
Previously for the following this would incorrectly report 2 (T + the pack) 
instead of 3
```
template&lt;typename T, typename... Ts&gt; struct Foo {};
Foo&lt;int, float, double&gt; x;
```

**clang_Cursor_getTemplateArgument** (static helper used by all 
getTemplateArgument* APIs):
- Add `CXCursor_CXXMethod` to accepted cursor kinds (would also fail before)
- Allow indexing into parameter packs, so that index 2 for the specialization 
above returns `double` instead of
failing with out of bounds

### New APIs:
- **clang_Cursor_getNumTemplateParameters**: get the parameter count on a 
class/function template
- **clang_Cursor_getTemplateParameter**: get the I-th template parameter as a 
cursor
- **clang_Cursor_isTemplateParameterPack**: check if a template parameter is a 
parameter pack
Currently the only way of checking whether a cursor represents a parameter pack 
seems to be to inspect the spelling.
- **clang_Cursor_getTemplateArgumentIntegralType**: get the type of a non-type 
template parameter argument.
The existing `clang_Cursor_getTemplateArgumentValue` and 
`clang_Cursor_getTemplateArgumentUnsignedValue` return the value but provide no 
easy way to query the type of the non-type template parameter, making it hard 
to determine which of the two to use (possible to infer based on the return 
value of each one, but it's quite cumbersome)

---

Patch is 22.46 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/183504.diff


8 Files Affected:

- (modified) clang/bindings/python/clang/cindex.py (+26) 
- (modified) clang/bindings/python/tests/cindex/test_cursor.py (+135) 
- (modified) clang/docs/ReleaseNotes.rst (+6) 
- (modified) clang/include/clang-c/Index.h (+56-2) 
- (added) clang/test/Index/template-parameters.cpp (+14) 
- (modified) clang/tools/c-index-test/c-index-test.c (+5-4) 
- (modified) clang/tools/libclang/CXCursor.cpp (+107-28) 
- (modified) clang/tools/libclang/libclang.map (+8) 


``````````diff
diff --git a/clang/bindings/python/clang/cindex.py 
b/clang/bindings/python/clang/cindex.py
index 1896a0a9c1c34..9207fd0727063 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -2272,6 +2272,28 @@ def get_template_argument_unsigned_value(self, num: int) 
-> int:
         """Returns the value of the indicated arg as an unsigned 64b 
integer."""
         return conf.lib.clang_Cursor_getTemplateArgumentUnsignedValue(self, 
num)  # type: ignore [no-any-return]
 
+    @cursor_null_guard
+    def get_template_argument_integral_type(self, num: int) -> Type:
+        """Returns the type of an integral template argument at the given 
index."""
+        return Type.from_result(
+            conf.lib.clang_Cursor_getTemplateArgumentIntegralType(self, num), 
self
+        )
+
+    @cursor_null_guard
+    def get_num_template_parameters(self) -> int:
+        """Returns the number of template parameters, or -1 if not a 
template."""
+        return conf.lib.clang_Cursor_getNumTemplateParameters(self)  # type: 
ignore [no-any-return]
+
+    @cursor_null_guard
+    def get_template_parameter(self, num: int) -> Cursor:
+        """Returns the template parameter at the given index."""
+        return conf.lib.clang_Cursor_getTemplateParameter(self, num)  # type: 
ignore [no-any-return]
+
+    @cursor_null_guard
+    def is_template_parameter_pack(self) -> bool:
+        """Returns True if the cursor is a template parameter pack."""
+        return bool(conf.lib.clang_Cursor_isTemplateParameterPack(self))
+
     @cursor_null_guard
     def get_children(self) -> Iterator[Cursor]:
         """Return an iterator for accessing the children of this cursor."""
@@ -4427,6 +4449,10 @@ def set_property(self, property, value):
     ("clang_Cursor_getTemplateArgumentType", [Cursor, c_uint], Type),
     ("clang_Cursor_getTemplateArgumentValue", [Cursor, c_uint], c_longlong),
     ("clang_Cursor_getTemplateArgumentUnsignedValue", [Cursor, c_uint], 
c_ulonglong),
+    ("clang_Cursor_getTemplateArgumentIntegralType", [Cursor, c_uint], Type),
+    ("clang_Cursor_getNumTemplateParameters", [Cursor], c_int),
+    ("clang_Cursor_getTemplateParameter", [Cursor, c_uint], Cursor),
+    ("clang_Cursor_isTemplateParameterPack", [Cursor], c_uint),
     ("clang_getCursorBinaryOperatorKind", [Cursor], c_int),
     ("clang_Cursor_getBriefCommentText", [Cursor], _CXString),
     ("clang_Cursor_getRawCommentText", [Cursor], _CXString),
diff --git a/clang/bindings/python/tests/cindex/test_cursor.py 
b/clang/bindings/python/tests/cindex/test_cursor.py
index 76680e576b307..4adfc244f2582 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -916,6 +916,141 @@ def test_get_template_argument_unsigned_value(self):
         self.assertEqual(foos[1].get_template_argument_unsigned_value(0), 
2**32 - 7)
         self.assertEqual(foos[1].get_template_argument_unsigned_value(2), True)
 
+    def test_get_template_argument_integral_type(self):
+        tu = get_tu(TEMPLATE_ARG_TEST, lang="cpp")
+        foos = get_cursors(tu, "foo")
+
+        self.assertEqual(
+            foos[1].get_template_argument_integral_type(0).kind, TypeKind.INT
+        )
+        self.assertEqual(
+            foos[1].get_template_argument_integral_type(1).kind,
+            TypeKind.INVALID,
+        )
+        self.assertEqual(
+            foos[1].get_template_argument_integral_type(2).kind, TypeKind.BOOL
+        )
+
+    def test_get_template_argument_integral_type_pack(self):
+        source = """
+            template<int... Ns> struct Foo {};
+            template class Foo<1, 2, 3>;
+        """
+        tu = get_tu(source, lang="cpp")
+        foo = get_cursor(tu, "Foo")
+        # Find the specialization.
+        spec = None
+        for c in tu.cursor.walk_preorder():
+            if c.kind == CursorKind.STRUCT_DECL and c.spelling == "Foo":
+                if c.get_num_template_arguments() >= 0:
+                    spec = c
+                    break
+        self.assertIsNotNone(spec)
+        self.assertEqual(spec.get_num_template_arguments(), 3)
+        self.assertEqual(
+            spec.get_template_argument_integral_type(0).kind, TypeKind.INT
+        )
+        self.assertEqual(
+            spec.get_template_argument_integral_type(1).kind, TypeKind.INT
+        )
+        self.assertEqual(
+            spec.get_template_argument_integral_type(2).kind, TypeKind.INT
+        )
+
+    def test_get_num_template_parameters(self):
+        source = "template<typename T, int N> void foo(); template<typename... 
Ts> void bar(); void baz();"
+        tu = get_tu(source, lang="cpp")
+        foo = get_cursor(tu, "foo")
+        bar = get_cursor(tu, "bar")
+        baz = get_cursor(tu, "baz")
+        self.assertIsNotNone(foo)
+        self.assertIsNotNone(bar)
+        self.assertIsNotNone(baz)
+
+        self.assertEqual(foo.get_num_template_parameters(), 2)
+        self.assertEqual(bar.get_num_template_parameters(), 1)
+        self.assertEqual(baz.get_num_template_parameters(), -1)
+
+    def test_get_template_parameter(self):
+        source = "template<typename T, int N> void foo();"
+        tu = get_tu(source, lang="cpp")
+        foo = get_cursor(tu, "foo")
+        self.assertIsNotNone(foo)
+
+        t_param = foo.get_template_parameter(0)
+        n_param = foo.get_template_parameter(1)
+        self.assertEqual(t_param.kind, CursorKind.TEMPLATE_TYPE_PARAMETER)
+        self.assertEqual(t_param.spelling, "T")
+        self.assertEqual(n_param.kind, CursorKind.TEMPLATE_NON_TYPE_PARAMETER)
+        self.assertEqual(n_param.spelling, "N")
+        oob = conf.lib.clang_Cursor_getTemplateParameter(foo, 5)
+        self.assertTrue(oob.is_null())
+
+    def test_is_template_parameter_pack(self):
+        # Type parameter pack
+        source = "template<typename T, typename... Ts> void foo();"
+        tu = get_tu(source, lang="cpp")
+        foo = get_cursor(tu, "foo")
+        self.assertIsNotNone(foo)
+        
self.assertFalse(foo.get_template_parameter(0).is_template_parameter_pack())
+        
self.assertTrue(foo.get_template_parameter(1).is_template_parameter_pack())
+
+        # Non-type parameter pack
+        source = "template<int... Ns> void bar();"
+        tu = get_tu(source, lang="cpp")
+        bar = get_cursor(tu, "bar")
+        self.assertIsNotNone(bar)
+        
self.assertTrue(bar.get_template_parameter(0).is_template_parameter_pack())
+
+        # Template template parameter pack
+        source = "template<template<typename> class... Ts> void baz();"
+        tu = get_tu(source, lang="cpp")
+        baz = get_cursor(tu, "baz")
+        self.assertIsNotNone(baz)
+        
self.assertTrue(baz.get_template_parameter(0).is_template_parameter_pack())
+
+    def test_get_template_argument_variadic(self):
+        source = """
+            template<typename T, typename... Ts> struct Foo {};
+            Foo<int, float, double> x;
+            Foo<int> y;
+        """
+        tu = get_tu(source, lang="cpp")
+
+        x = get_cursor(tu, "x")
+        self.assertIsNotNone(x)
+        x_type = x.type.get_declaration()
+        self.assertEqual(x_type.get_num_template_arguments(), 3)
+        self.assertEqual(x_type.get_template_argument_type(0).kind, 
TypeKind.INT)
+        self.assertEqual(x_type.get_template_argument_type(1).kind, 
TypeKind.FLOAT)
+        self.assertEqual(x_type.get_template_argument_type(2).kind, 
TypeKind.DOUBLE)
+        self.assertEqual(x_type.get_template_argument_type(3).kind, 
TypeKind.INVALID)
+
+        # Empty pack: only T=int, pack contributes 0.
+        y = get_cursor(tu, "y")
+        self.assertIsNotNone(y)
+        y_type = y.type.get_declaration()
+        self.assertEqual(y_type.get_num_template_arguments(), 1)
+
+    def test_get_num_template_arguments_method(self):
+        source = """
+            struct S {
+                template<typename U> void method(U) {}
+            };
+            void use() { S().method(42); }
+        """
+        tu = get_tu(source, lang="cpp")
+        # Find a call to S::method<int> and get the referenced specialization.
+        method_spec = None
+        for c in tu.cursor.walk_preorder():
+            if c.kind == CursorKind.CALL_EXPR and c.spelling == "method":
+                method_spec = c.referenced
+                break
+        self.assertIsNotNone(method_spec)
+        self.assertEqual(method_spec.kind, CursorKind.CXX_METHOD)
+        self.assertEqual(method_spec.get_num_template_arguments(), 1)
+        self.assertEqual(method_spec.get_template_argument_type(0).kind, 
TypeKind.INT)
+
     def test_referenced(self):
         tu = get_tu("void foo(); void bar() { foo(); }")
         foo = get_cursor(tu, "foo")
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cb1010aee1edd..e6286ab41fde8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -430,6 +430,10 @@ libclang
 - Visit constraints of `auto` type to properly visit concept usages (#GH166580)
 - Visit switch initializer statements 
(https://bugs.kde.org/show_bug.cgi?id=415537#c2)
 - Fix crash in clang_getBinaryOperatorKindSpelling and 
clang_getUnaryOperatorKindSpelling
+- Added ``clang_Cursor_getNumTemplateParameters``, 
``clang_Cursor_getTemplateParameter``,
+  ``clang_Cursor_isTemplateParameterPack``, and 
``clang_Cursor_getTemplateArgumentIntegralType``.
+- Fixed ``clang_Cursor_getNumTemplateArguments`` and related APIs to work with
+  ``CXCursor_CXXMethod`` cursors and to correctly allow indexing into 
parameter pack arguments.
 
 Code Completion
 ---------------
@@ -468,6 +472,8 @@ Python Binding Changes
   ``CodeCompletionResults.results`` should be changed to directly use
   ``CodeCompletionResults``: it nows supports ``__len__`` and ``__getitem__``,
   so it can be used the same as ``CodeCompletionResults.results``.
+- Added ``Cursor.get_num_template_parameters``, 
``Cursor.get_template_parameter``,
+  ``Cursor.is_template_parameter_pack``, and 
``Cursor.get_template_argument_integral_type``.
 
 OpenMP Support
 --------------
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 203634c80d82a..8d04932f57fcf 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3267,7 +3267,29 @@ CINDEX_LINKAGE CXType 
clang_Cursor_getTemplateArgumentType(CXCursor C,
                                                            unsigned I);
 
 /**
- * Retrieve the value of an Integral TemplateArgument (of a function
+ * Retrieve the type of an Integral TemplateArgument at a given index.
+ *
+ * For example, for:
+ *   template <typename T, int N>
+ *   void foo() {}
+ *
+ *   template <>
+ *   void foo<float, 42>();
+ *
+ * If called with I = 1, the type "int" will be returned (the type of the
+ * integral argument 42). An invalid type is returned if the argument at
+ * index I is not integral, or if the index is out of range.
+ *
+ * \param C a cursor representing a template specialization.
+ * \param I the zero-based index of the template argument.
+ *
+ * \returns the type of the integral template argument, or an invalid type.
+ */
+CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentIntegralType(CXCursor C,
+                                                                   unsigned I);
+
+/**
+ * Retrieve the value of an Integral TemplateArgument (of a function or class
  *  decl representing a template specialization) as a signed long long.
  *
  * It is undefined to call this function on a CXCursor that does not represent 
a
@@ -3288,7 +3310,7 @@ CINDEX_LINKAGE long long 
clang_Cursor_getTemplateArgumentValue(CXCursor C,
                                                                unsigned I);
 
 /**
- * Retrieve the value of an Integral TemplateArgument (of a function
+ * Retrieve the value of an Integral TemplateArgument (of a function or class
  *  decl representing a template specialization) as an unsigned long long.
  *
  * It is undefined to call this function on a CXCursor that does not represent 
a
@@ -3308,6 +3330,38 @@ CINDEX_LINKAGE long long 
clang_Cursor_getTemplateArgumentValue(CXCursor C,
 CINDEX_LINKAGE unsigned long long
 clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C, unsigned I);
 
+/**
+ * Retrieve the number of template parameters on a template declaration.
+ *
+ * \param C a cursor representing a class template or function template.
+ *
+ * \returns the number of template parameters, or -1 if the cursor does not
+ * represent a template.
+ */
+CINDEX_LINKAGE int clang_Cursor_getNumTemplateParameters(CXCursor C);
+
+/**
+ * Retrieve a template parameter at the given index.
+ *
+ * \param C a cursor representing a class template or function template.
+ * \param I the zero-based index of the template parameter.
+ *
+ * \returns a cursor for the template parameter, or a null cursor if the
+ * index is out of range or the cursor is not a template.
+ */
+CINDEX_LINKAGE CXCursor clang_Cursor_getTemplateParameter(CXCursor C,
+                                                          unsigned I);
+
+/**
+ * Determine whether a template parameter is a parameter pack.
+ *
+ * \param C a cursor representing a template type parameter, non-type
+ * template parameter, or template template parameter.
+ *
+ * \returns non-zero if the template parameter is a parameter pack.
+ */
+CINDEX_LINKAGE unsigned clang_Cursor_isTemplateParameterPack(CXCursor C);
+
 /**
  * Determine whether two CXTypes represent the same type.
  *
diff --git a/clang/test/Index/template-parameters.cpp 
b/clang/test/Index/template-parameters.cpp
new file mode 100644
index 0000000000000..b78e850de59e2
--- /dev/null
+++ b/clang/test/Index/template-parameters.cpp
@@ -0,0 +1,14 @@
+// Test template argument pack expansion.
+// RUN: c-index-test -test-load-source all -fno-delayed-template-parsing %s | 
FileCheck %s
+
+template<typename T, typename... Ts>
+struct Variadic {};
+
+template class Variadic<int, float, double>;
+template class Variadic<int>;
+
+// Pack with 3 args: should report 3 (not 2).
+// CHECK: StructDecl=Variadic:7:16 (Definition) [Specialization of 
Variadic:5:8] [Template arg 0: kind: 1, type: int] [Template arg 1: kind: 1, 
type: float] [Template arg 2: kind: 1, type: double]
+
+// Empty pack: should report 1 (just T, pack contributes 0).
+// CHECK: StructDecl=Variadic:8:16 (Definition) [Specialization of 
Variadic:5:8] [Template arg 0: kind: 1, type: int]
diff --git a/clang/tools/c-index-test/c-index-test.c 
b/clang/tools/c-index-test/c-index-test.c
index cb3245756a394..e6e78c8d5ab37 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -1054,10 +1054,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_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/CXCursor.cpp 
b/clang/tools/libclang/CXCursor.cpp
index 17f485e5c78a5..1f39fdc66a5cf 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -1438,29 +1438,40 @@ 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;
   }
 
-  if (const auto *FD =
-          llvm::dyn_cast_if_present<clang::FunctionDecl>(getCursorDecl(C))) {
+  const TemplateArgumentList *TAL = nullptr;
+
+  if (const auto *FD = dyn_cast_if_present<FunctionDecl>(getCursorDecl(C))) {
     const FunctionTemplateSpecializationInfo *SpecInfo =
         FD->getTemplateSpecializationInfo();
     if (!SpecInfo) {
       return -1;
     }
-    return SpecInfo->TemplateArguments->size();
+    TAL = SpecInfo->TemplateArguments;
   }
 
-  if (const auto *SD =
-          llvm::dyn_cast_if_present<clang::ClassTemplateSpecializationDecl>(
-              getCursorDecl(C))) {
-    return SD->getTemplateArgs().size();
+  if (!TAL) {
+    if (const auto *SD = dyn_cast_if_present<ClassTemplateSpecializationDecl>(
+            getCursorDecl(C))) {
+      TAL = &SD->getTemplateArgs();
+    }
   }
 
-  return -1;
+  if (!TAL)
+    return -1;
+
+  unsigned ArgCount = TAL->size();
+  for (unsigned i = 0; i < TAL->size(); i++) {
+    const TemplateArgument &Arg = TAL->get(i);
+    if (Arg.getKind() == TemplateArgument::Pack)
+      ArgCount += Arg.pack_size() - 1;
+  }
+  return ArgCount;
 }
 
 enum CXGetTemplateArgumentStatus {
@@ -1485,14 +1496,15 @@ 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;
   }
 
-  if (const auto *FD =
-          llvm::dyn_cast_if_present<clang::FunctionDecl>(getCursorDecl(C))) {
+  const TemplateArgumentList *TAL = nullptr;
+
+  if (const auto *FD = dyn_cast_if_present<FunctionDecl>(getCursorDecl(C))) {
 
     const FunctionTemplateSpecializationInfo *SpecInfo =
         FD->getTemplateSpecializationInfo();
@@ -1500,26 +1512,38 @@ static int clang_Cursor_getTemplateArgument(CXCursor C, 
unsigned I,
       return CXGetTemplateArgumentStatus_NullTemplSpecInfo;
     }
 
-    if (I >= SpecInfo->TemplateArguments->size()) {
-      return CXGetTemplateArgumentStatus_InvalidIndex;
-    }
-
-    *TA = SpecInfo->TemplateArguments->get(I);
-    return 0;
+    TAL = SpecInfo->TemplateArguments;
   }
 
-  if (const auto *SD =
-          llvm::dyn_cast_if_present<clang::ClassTemplateSpecializationDecl>(
-              getCursorDecl(C))) {
-    if (I >= SD->getTemplateArgs().size()) {
-      return CXGetTemplateArgumentStatus_InvalidIndex;
+  if (!TAL) {
+    if (const auto *SD = dyn_cast_if_present<ClassTemplateSpecializationDecl>(
+            getCursorDecl(C))) {
+      TAL = &SD->getTemplateArgs();
     }
+  }
 
-    *TA = SD->getTemplateArgs()[I];
-    return 0;
+  if (!TAL)
+    return CXGetTemplateArgumentStatus_BadDeclCast;
+
+  unsigned current = 0;
+  for (unsigned i = 0; i < TAL->size(); i++) {
+    const auto &TACand = TAL->get(i);
+    if (TACand.getKind() == TemplateArgument::Pack) {
+      if (I < current + TACand.pack_size()) {
+        *TA = TACand.pack_elements()[I - current];
+        return 0;
+      }
+      current += TACand.pack_size();
+      continue;
+    }
+    if (current == I) {
+      *TA = TACand;
+      return 0;
+    }
+    current++;
   }
 
-  return CXGetTemplateArgumentStatus_BadDeclCast;
+  return CXGetTemplateArgumentStatus_InvalidIndex;
 }
 
 enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C,
@@ -1603,6 +1627,61 @@ unsigned long long 
clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C,
   return TA.getAsIntegral().getZExtValue();
 }
 
+CXType clang_Cursor_getTemplateArgumentIntegralType(CXCursor C, unsigned I) {
+  TemplateArgument TA;
+  if (clang_Cursor_getTemplateArgument(C, I, &TA))
+    return cxtype::MakeCXType(QualType(), getCursorTU(C));
+
+  if (TA.getKind() != TemplateArgument::Integral)
+    return cxtype::MakeCXType(QualType(), getCursorTU(C));
+
+  return cxtype::MakeCXType(TA.getIntegralT...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/183504
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to