[cfe-dev] Patch libclang: clang_Cursor_getTemplate* for struct/classes template specialization
Benoit Maurin
maurinbe at gmail.com
Sat Aug 8 16:59:21 PDT 2015
Hi,
In the current state of things, clang_Cursor_getNumTemplateArguments and co
only works for functions.
It would be nice for it to also work for struct/class template
specializations.
A patch doing just that is attached.
It is rather short and there are also tests included (for python lib)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150809/470b6d76/attachment.html>
-------------- next part --------------
Index: bindings/python/tests/cindex/test_cursor.py
===================================================================
--- bindings/python/tests/cindex/test_cursor.py (revision 244406)
+++ bindings/python/tests/cindex/test_cursor.py (working copy)
@@ -252,6 +252,15 @@
template<>
void foo<-7, float, true>();
+
+ template <int kInt, typename T, bool kBool>
+ struct bar{
+ int a=kInt;
+ T b;
+ bool c=kBool;
+ };
+
+ bar<-7, float, true> X;
"""
def test_get_num_template_arguments():
@@ -288,6 +297,40 @@
assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7
assert foos[1].get_template_argument_unsigned_value(2) == True
+def test_get_num_template_arguments_struct():
+ tu = get_tu(kTemplateArgTest, lang='cpp')
+ bar = get_cursor(tu, 'X').type.get_declaration()
+
+ assert bar.get_num_template_arguments() == 3
+
+def test_get_template_argument_kind_struct():
+ tu = get_tu(kTemplateArgTest, lang='cpp')
+ bar = get_cursor(tu, 'X').type.get_declaration()
+
+ assert bar.get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL
+ assert bar.get_template_argument_kind(1) == TemplateArgumentKind.TYPE
+ assert bar.get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL
+
+def test_get_template_argument_type_struct():
+ tu = get_tu(kTemplateArgTest, lang='cpp')
+ bar = get_cursor(tu, 'X').type.get_declaration()
+
+ assert bar.get_template_argument_type(1).kind == TypeKind.FLOAT
+
+def test_get_template_argument_value_struct():
+ tu = get_tu(kTemplateArgTest, lang='cpp')
+ bar = get_cursor(tu, 'X').type.get_declaration()
+
+ assert bar.get_template_argument_value(0) == -7
+ assert bar.get_template_argument_value(2) == True
+
+def test_get_template_argument_unsigned_value_struct():
+ tu = get_tu(kTemplateArgTest, lang='cpp')
+ bar = get_cursor(tu, 'X').type.get_declaration()
+
+ assert bar.get_template_argument_unsigned_value(0) == 2 ** 32 - 7
+ assert bar.get_template_argument_unsigned_value(2) == True
+
def test_referenced():
tu = get_tu('void foo(); void bar() { foo(); }')
foo = get_cursor(tu, 'foo')
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h (revision 244406)
+++ include/clang-c/Index.h (working copy)
@@ -3005,7 +3005,7 @@
/**
* \brief Retrieve the kind of the I'th template argument of the CXCursor C.
*
- * If the argument CXCursor does not represent a FunctionDecl, an invalid
+ * If the argument CXCursor does not represent a FunctionDecl or a Struct/Class Decl, an invalid
* template argument kind is returned.
*
* For example, for the following declaration and specialization:
@@ -3025,7 +3025,7 @@
* \brief 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 whose I'th
+ * If the argument CXCursor does not represent a FunctionDecl Struct/Class Decl whose I'th
* template argument has a kind of CXTemplateArgKind_Integral, an invalid type
* is returned.
*
Index: tools/libclang/CXCursor.cpp
===================================================================
--- tools/libclang/CXCursor.cpp (revision 244406)
+++ tools/libclang/CXCursor.cpp (working copy)
@@ -1092,23 +1092,35 @@
}
int clang_Cursor_getNumTemplateArguments(CXCursor C) {
- if (clang_getCursorKind(C) != CXCursor_FunctionDecl) {
- return -1;
- }
+ if (clang_getCursorKind(C) == CXCursor_FunctionDecl) {
- const FunctionDecl *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(
- getCursorDecl(C));
- if (!FD) {
- return -1;
- }
+ const FunctionDecl *FD =
+ llvm::dyn_cast_or_null<clang::FunctionDecl>(getCursorDecl(C));
+ if (!FD) {
+ return -1;
+ }
- const FunctionTemplateSpecializationInfo* SpecInfo =
- FD->getTemplateSpecializationInfo();
- if (!SpecInfo) {
+ const FunctionTemplateSpecializationInfo *SpecInfo =
+ FD->getTemplateSpecializationInfo();
+ if (!SpecInfo) {
+ return -1;
+ }
+
+ return SpecInfo->TemplateArguments->size();
+ } else if (clang_getCursorKind(C) == CXCursor_StructDecl ||
+ clang_getCursorKind(C) == CXCursor_ClassDecl) {
+
+ const ClassTemplateSpecializationDecl *Decl =
+ llvm::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(
+ getCursorDecl(C));
+ if (!Decl) {
+ return -1;
+ }
+
+ return Decl->getTemplateArgs().size();
+ } else {
return -1;
}
-
- return SpecInfo->TemplateArguments->size();
}
enum CXGetTemplateArgumentStatus {
@@ -1116,10 +1128,10 @@
CXGetTemplateArgumentStatus_Success = 0,
/** \brief The specified cursor did not represent a FunctionDecl. */
- CXGetTemplateArgumentStatus_CursorNotFunctionDecl = -1,
+ CXGetTemplateArgumentStatus_CursorNotSupportedDecl = -1,
/** \brief The specified cursor was not castable to a FunctionDecl. */
- CXGetTemplateArgumentStatus_BadFunctionDeclCast = -2,
+ CXGetTemplateArgumentStatus_BadDeclCast = -2,
/** \brief A NULL FunctionTemplateSpecializationInfo was retrieved. */
CXGetTemplateArgumentStatus_NullTemplSpecInfo = -3,
@@ -1130,28 +1142,43 @@
static int clang_Cursor_getTemplateArgument(
CXCursor C, unsigned I, TemplateArgument *TA) {
- if (clang_getCursorKind(C) != CXCursor_FunctionDecl) {
- return CXGetTemplateArgumentStatus_CursorNotFunctionDecl;
- }
+ if (clang_getCursorKind(C) == CXCursor_FunctionDecl) {
- const FunctionDecl *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(
- getCursorDecl(C));
- if (!FD) {
- return CXGetTemplateArgumentStatus_BadFunctionDeclCast;
- }
+ const FunctionDecl *FD =
+ llvm::dyn_cast_or_null<clang::FunctionDecl>(getCursorDecl(C));
+ if (!FD) {
+ return CXGetTemplateArgumentStatus_BadDeclCast;
+ }
- const FunctionTemplateSpecializationInfo* SpecInfo =
- FD->getTemplateSpecializationInfo();
- if (!SpecInfo) {
- return CXGetTemplateArgumentStatus_NullTemplSpecInfo;
- }
+ const FunctionTemplateSpecializationInfo *SpecInfo =
+ FD->getTemplateSpecializationInfo();
+ if (!SpecInfo) {
+ return CXGetTemplateArgumentStatus_NullTemplSpecInfo;
+ }
- if (I >= SpecInfo->TemplateArguments->size()) {
- return CXGetTemplateArgumentStatus_InvalidIndex;
+ if (I >= SpecInfo->TemplateArguments->size()) {
+ return CXGetTemplateArgumentStatus_InvalidIndex;
+ }
+
+ *TA = SpecInfo->TemplateArguments->get(I);
+ return 0;
+ } else if (clang_getCursorKind(C) == CXCursor_StructDecl ||
+ clang_getCursorKind(C) == CXCursor_ClassDecl) {
+
+ const ClassTemplateSpecializationDecl *Decl =
+ llvm::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(
+ getCursorDecl(C));
+ if (!Decl) {
+ return CXGetTemplateArgumentStatus_NullTemplSpecInfo;
+ }
+
+ if (I >= Decl->getTemplateArgs().size())
+ return CXGetTemplateArgumentStatus_InvalidIndex;
+ *TA = Decl->getTemplateArgs().get(I);
+ return 0;
+ } else {
+ return CXGetTemplateArgumentStatus_CursorNotSupportedDecl;
}
-
- *TA = SpecInfo->TemplateArguments->get(I);
- return 0;
}
enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C,
More information about the cfe-dev
mailing list