[clang] [libclang] Add clang_Type_getDependentSizeExpr (PR #212648)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 30 06:20:27 PDT 2026
https://github.com/w-utter updated https://github.com/llvm/llvm-project/pull/212648
>From ded00301e58cb228a318e0c008bdcd33a4c836c7 Mon Sep 17 00:00:00 2001
From: will <104373134+w-utter at users.noreply.github.com>
Date: Wed, 29 Jul 2026 08:52:56 +1000
Subject: [PATCH 1/2] [libclang] Add clang_Type_getDependentSizeExpr
---
clang/include/clang-c/Index.h | 8 ++++++++
clang/tools/libclang/CXType.cpp | 26 ++++++++++++++++++++++++++
clang/tools/libclang/libclang.map | 1 +
3 files changed, 35 insertions(+)
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 8427236e0b444..3c2ae30d9bbb9 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3734,6 +3734,14 @@ CINDEX_LINKAGE CXType clang_Type_getModifiedType(CXType T);
*/
CINDEX_LINKAGE CXType clang_Type_getValueType(CXType CT);
+
+/**
+ * Gets the expression associated with this dependent sized array
+ *
+ * If a non-dependent type is passed in, an invalid cursor is returned.
+ */
+CINDEX_LINKAGE CXCursor clang_Type_getDependentSizeExpr(CXType CT);
+
/**
* Return the offset of the field represented by the Cursor.
*
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index 0063939dec423..52e813ea3c795 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -912,6 +912,32 @@ long long clang_getNumElements(CXType CT) {
return result;
}
+CXCursor clang_Type_getDependentSizeExpr(CXType CT) {
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (!TP)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ const Expr* E = nullptr;
+
+ switch (TP->getTypeClass()) {
+ case Type::DependentSizedArray:
+ E = cast<DependentSizedArrayType> (TP)->getSizeExpr();
+ break;
+ case Type::DependentSizedExtVector:
+ E = cast<DependentSizedExtVectorType> (TP)->getSizeExpr();
+ break;
+ default:
+ break;
+ }
+
+ if (!E)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ return cxcursor::MakeCXCursor(E, nullptr, GetTU(CT));
+}
+
CXType clang_getArrayElementType(CXType CT) {
QualType ET = QualType();
QualType T = GetQualType(CT);
diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map
index 57f281096929d..4864cb6da5929 100644
--- a/clang/tools/libclang/libclang.map
+++ b/clang/tools/libclang/libclang.map
@@ -461,6 +461,7 @@ LLVM_23 {
global:
clang_ModuleCache_prune;
clang_ModuleCache_pruneWithCallback;
+ clang_Type_getDependentSizeExpr;
};
# Example of how to add a new symbol version entry. If you do add a new symbol
>From 34d1bffc3e0253c474cc774ce327c8ded059b5a6 Mon Sep 17 00:00:00 2001
From: will <104373134+w-utter at users.noreply.github.com>
Date: Thu, 30 Jul 2026 23:20:03 +1000
Subject: [PATCH 2/2] [libclang] support getting template argument kind &
values from CXType
---
clang/include/clang-c/Index.h | 31 +++++++++++
clang/tools/libclang/CMakeLists.txt | 1 +
clang/tools/libclang/CXCursor.cpp | 52 +++---------------
clang/tools/libclang/CXTemplateArgument.h | 62 ++++++++++++++++++++++
clang/tools/libclang/CXType.cpp | 64 ++++++++++++++++-------
clang/tools/libclang/libclang.map | 5 ++
6 files changed, 150 insertions(+), 65 deletions(-)
create mode 100644 clang/tools/libclang/CXTemplateArgument.h
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 3c2ae30d9bbb9..6c53d1f7e5233 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3251,6 +3251,15 @@ CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C);
CINDEX_LINKAGE enum CXTemplateArgumentKind
clang_Cursor_getTemplateArgumentKind(CXCursor C, unsigned I);
+/**
+ * Retrieve the kind of the I'th template argument of the CXType CT.
+ *
+ * If the argument CXType does not represent a template specialization,
+ * an invalid template argument kind is returned.
+ */
+CINDEX_LINKAGE enum CXTemplateArgumentKind
+clang_Type_getTemplateArgumentKind(CXType CT, unsigned I);
+
/**
* Retrieve a CXType representing the type of a TemplateArgument of a
* function decl representing a template specialization.
@@ -3293,6 +3302,17 @@ CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C,
CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C,
unsigned I);
+/**
+ * Retrieve the value of an Integral TemplateArgument (of a function
+ * decl representing a template specialization) as a signed long long.
+ *
+ * It is undefined to call this function on a CXType that does not represent a
+ * FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization
+ * whose I'th template argument is not an integral value.
+ */
+CINDEX_LINKAGE long long clang_Type_getTemplateArgumentValue(CXType CT,
+ unsigned index);
+
/**
* Retrieve the value of an Integral TemplateArgument (of a function
* decl representing a template specialization) as an unsigned long long.
@@ -3314,6 +3334,17 @@ CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C,
CINDEX_LINKAGE unsigned long long
clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C, unsigned I);
+/**
+ * Retrieve the value of an Integral TemplateArgument (of a function
+ * decl representing a template specialization) as an unsigned long long.
+ *
+ * It is undefined to call this function on a CXType that does not represent a
+ * FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization
+ * whose I'th template argument is not an integral value.
+ */
+CINDEX_LINKAGE unsigned long long
+clang_Type_getTemplateArgumentUnsignedValue(CXType C, unsigned I);
+
/**
* Determine whether two CXTypes represent the same type.
*
diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt
index 38f577499dd22..a1e9ea43d2d8e 100644
--- a/clang/tools/libclang/CMakeLists.txt
+++ b/clang/tools/libclang/CMakeLists.txt
@@ -51,6 +51,7 @@ set(SOURCES
CXLoadedDiagnostic.h
CXSourceLocation.h
CXString.h
+ CXTemplateArgument.h
CXTranslationUnit.h
CXType.h
Index_Internal.h
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index fb0b3c1502574..6bf9fe24d2fb1 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -14,6 +14,7 @@
#include "CXCursor.h"
#include "CXString.h"
+#include "CXTemplateArgument.h"
#include "CXTranslationUnit.h"
#include "CXType.h"
#include "clang-c/Index.h"
@@ -1529,38 +1530,12 @@ static int clang_Cursor_getTemplateArgument(CXCursor C, unsigned I,
return CXGetTemplateArgumentStatus_BadDeclCast;
}
-enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C,
- unsigned I) {
+enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C, unsigned I) {
TemplateArgument TA;
if (clang_Cursor_getTemplateArgument(C, I, &TA)) {
return CXTemplateArgumentKind_Invalid;
}
-
- switch (TA.getKind()) {
- case TemplateArgument::Null:
- return CXTemplateArgumentKind_Null;
- case TemplateArgument::Type:
- return CXTemplateArgumentKind_Type;
- case TemplateArgument::Declaration:
- return CXTemplateArgumentKind_Declaration;
- case TemplateArgument::NullPtr:
- return CXTemplateArgumentKind_NullPtr;
- case TemplateArgument::Integral:
- return CXTemplateArgumentKind_Integral;
- case TemplateArgument::StructuralValue:
- // FIXME: Expose these values.
- return CXTemplateArgumentKind_Invalid;
- case TemplateArgument::Template:
- return CXTemplateArgumentKind_Template;
- case TemplateArgument::TemplateExpansion:
- return CXTemplateArgumentKind_TemplateExpansion;
- case TemplateArgument::Expression:
- return CXTemplateArgumentKind_Expression;
- case TemplateArgument::Pack:
- return CXTemplateArgumentKind_Pack;
- }
-
- return CXTemplateArgumentKind_Invalid;
+ return GetTemplateArgumentKind(TA);
}
CXType clang_Cursor_getTemplateArgumentType(CXCursor C, unsigned I) {
@@ -1569,12 +1544,7 @@ CXType clang_Cursor_getTemplateArgumentType(CXCursor C, unsigned I) {
CXGetTemplateArgumentStatus_Success) {
return cxtype::MakeCXType(QualType(), getCursorTU(C));
}
-
- if (TA.getKind() != TemplateArgument::Type) {
- return cxtype::MakeCXType(QualType(), getCursorTU(C));
- }
-
- return cxtype::MakeCXType(TA.getAsType(), getCursorTU(C));
+ return GetTemplateArgumentType(TA, getCursorTU(C));
}
long long clang_Cursor_getTemplateArgumentValue(CXCursor C, unsigned I) {
@@ -1585,12 +1555,7 @@ long long clang_Cursor_getTemplateArgumentValue(CXCursor C, unsigned I) {
return 0;
}
- if (TA.getKind() != TemplateArgument::Integral) {
- assert(0 && "Passed template argument is not Integral");
- return 0;
- }
-
- return TA.getAsIntegral().getSExtValue();
+ return GetTemplateArgumentValue(TA);
}
unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C,
@@ -1602,12 +1567,7 @@ unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C,
return 0;
}
- if (TA.getKind() != TemplateArgument::Integral) {
- assert(0 && "Passed template argument is not Integral");
- return 0;
- }
-
- return TA.getAsIntegral().getZExtValue();
+ return GetTemplateArgumentUnsignedValue(TA);
}
//===----------------------------------------------------------------------===//
diff --git a/clang/tools/libclang/CXTemplateArgument.h b/clang/tools/libclang/CXTemplateArgument.h
new file mode 100644
index 0000000000000..a5e2eab785dd4
--- /dev/null
+++ b/clang/tools/libclang/CXTemplateArgument.h
@@ -0,0 +1,62 @@
+#include "clang-c/Index.h"
+#include "clang/AST/TemplateBase.h"
+
+#include "CXCursor.h"
+#include "CXTranslationUnit.h"
+#include "CXType.h"
+
+using namespace clang;
+
+enum CXTemplateArgumentKind GetTemplateArgumentKind(TemplateArgument TA) {
+ switch (TA.getKind()) {
+ case TemplateArgument::Null:
+ return CXTemplateArgumentKind_Null;
+ case TemplateArgument::Type:
+ return CXTemplateArgumentKind_Type;
+ case TemplateArgument::Declaration:
+ return CXTemplateArgumentKind_Declaration;
+ case TemplateArgument::NullPtr:
+ return CXTemplateArgumentKind_NullPtr;
+ case TemplateArgument::Integral:
+ return CXTemplateArgumentKind_Integral;
+ case TemplateArgument::StructuralValue:
+ // FIXME: Expose these values.
+ return CXTemplateArgumentKind_Invalid;
+ case TemplateArgument::Template:
+ return CXTemplateArgumentKind_Template;
+ case TemplateArgument::TemplateExpansion:
+ return CXTemplateArgumentKind_TemplateExpansion;
+ case TemplateArgument::Expression:
+ return CXTemplateArgumentKind_Expression;
+ case TemplateArgument::Pack:
+ return CXTemplateArgumentKind_Pack;
+ }
+
+ return CXTemplateArgumentKind_Invalid;
+}
+
+CXType GetTemplateArgumentType(TemplateArgument TA, CXTranslationUnit TU) {
+ if (TA.getKind() != TemplateArgument::Type) {
+ return cxtype::MakeCXType(QualType(), TU);
+ }
+
+ return cxtype::MakeCXType(TA.getAsType(), TU);
+}
+
+long long GetTemplateArgumentValue(TemplateArgument TA) {
+ if (TA.getKind() != TemplateArgument::Integral) {
+ assert(0 && "Passed template argument is not Integral");
+ return 0;
+ }
+
+ return TA.getAsIntegral().getSExtValue();
+}
+
+unsigned long long GetTemplateArgumentUnsignedValue(TemplateArgument TA) {
+ if (TA.getKind() != TemplateArgument::Integral) {
+ assert(0 && "Passed template argument is not Integral");
+ return 0;
+ }
+
+ return TA.getAsIntegral().getZExtValue();
+}
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index 52e813ea3c795..dd49fe15564c9 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -14,7 +14,9 @@
#include "CIndexer.h"
#include "CXCursor.h"
#include "CXString.h"
+#include "CXTemplateArgument.h"
#include "CXTranslationUnit.h"
+#include "clang-c/Index.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -201,25 +203,26 @@ GetTemplateArguments(QualType Type) {
return std::nullopt;
}
-static std::optional<QualType>
-TemplateArgumentToQualType(const TemplateArgument &A) {
- if (A.getKind() == TemplateArgument::Type)
- return A.getAsType();
- return std::nullopt;
-}
+std::optional<TemplateArgument>
+FindTemplateArgumentAt(CXType CT, unsigned index) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return std::nullopt;
+
+ auto TA = GetTemplateArguments(T);
+ if (!TA)
+ return std::nullopt;
-static std::optional<QualType>
-FindTemplateArgumentTypeAt(ArrayRef<TemplateArgument> TA, unsigned index) {
unsigned current = 0;
- for (const auto &A : TA) {
+ for (const auto &A : *TA) {
if (A.getKind() == TemplateArgument::Pack) {
if (index < current + A.pack_size())
- return TemplateArgumentToQualType(A.getPackAsArray()[index - current]);
+ return A.getPackAsArray()[index - current];
current += A.pack_size();
continue;
}
if (current == index)
- return TemplateArgumentToQualType(A);
+ return A;
current++;
}
return std::nullopt;
@@ -1273,17 +1276,40 @@ int clang_Type_getNumTemplateArguments(CXType CT) {
return GetTemplateArgumentArraySize(*TA);
}
+enum CXTemplateArgumentKind clang_Type_getTemplateArgumentKind(CXType CT, unsigned index) {
+ const auto TA = FindTemplateArgumentAt(CT, index);
+
+ if (!TA) {
+ return CXTemplateArgumentKind_Invalid;
+ }
+ return GetTemplateArgumentKind(*TA);
+}
+
+long long clang_Type_getTemplateArgumentValue(CXType CT, unsigned index) {
+ const auto TA = FindTemplateArgumentAt(CT, index);
+
+ if (!TA) {
+ return 0;
+ }
+ return GetTemplateArgumentValue(*TA);
+}
+
+unsigned long long clang_Type_getTemplateArgumentUnsignedValue(CXType CT, unsigned index) {
+ const auto TA = FindTemplateArgumentAt(CT, index);
+
+ if (!TA) {
+ return 0;
+ }
+ return GetTemplateArgumentValue(*TA);
+}
+
CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) {
- QualType T = GetQualType(CT);
- if (T.isNull())
- return MakeCXType(QualType(), GetTU(CT));
+ const auto TA = FindTemplateArgumentAt(CT, index);
- auto TA = GetTemplateArguments(T);
- if (!TA)
+ if (!TA) {
return MakeCXType(QualType(), GetTU(CT));
-
- std::optional<QualType> QT = FindTemplateArgumentTypeAt(*TA, index);
- return MakeCXType(QT.value_or(QualType()), GetTU(CT));
+ }
+ return GetTemplateArgumentType(*TA, GetTU(CT));
}
CXType clang_Type_getObjCObjectBaseType(CXType CT) {
diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map
index 4864cb6da5929..7e51647d1f49c 100644
--- a/clang/tools/libclang/libclang.map
+++ b/clang/tools/libclang/libclang.map
@@ -462,8 +462,13 @@ LLVM_23 {
clang_ModuleCache_prune;
clang_ModuleCache_pruneWithCallback;
clang_Type_getDependentSizeExpr;
+ clang_Type_getTemplateArgumentValue;
+ clang_Type_getTemplateArgumentUnsignedValue;
+ clang_Type_getTemplateArgumentKind;
};
+
+
# Example of how to add a new symbol version entry. If you do add a new symbol
# version, please update the example to depend on the version you added.
# LLVM_X {
More information about the cfe-commits
mailing list