Add libclang capabilities to retriete template arguments from specializations.

Includes Python bindings.

Reviewed in http://reviews.llvm.org/D5621
Patch by Rob Springer

llvm-svn: 219529
This commit is contained in:
Eli Bendersky 2014-10-10 20:01:05 +00:00
parent f42585fd96
commit c27a0c490c
8 changed files with 440 additions and 110 deletions

View File

@ -496,24 +496,28 @@ class TokenKind(object):
setattr(TokenKind, name, kind)
### Cursor Kinds ###
class CursorKind(object):
"""
A CursorKind describes the kind of entity that a cursor points to.
class BaseEnumeration(object):
"""
Common base class for named enumerations held in sync with Index.h values.
# The unique kind objects, indexed by id.
Subclasses must define their own _kinds and _name_map members, as:
_kinds = []
_name_map = None
These values hold the per-subclass instances and value-to-name mappings,
respectively.
"""
def __init__(self, value):
if value >= len(CursorKind._kinds):
CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1)
if CursorKind._kinds[value] is not None:
raise ValueError,'CursorKind already loaded'
if value >= len(self.__class__._kinds):
self.__class__._kinds += [None] * (value - len(self.__class__._kinds) + 1)
if self.__class__._kinds[value] is not None:
raise ValueError,'{0} value {1} already loaded'.format(
str(self.__class__), value)
self.value = value
CursorKind._kinds[value] = self
CursorKind._name_map = None
self.__class__._kinds[value] = self
self.__class__._name_map = None
def from_param(self):
return self.value
@ -523,16 +527,29 @@ class CursorKind(object):
"""Get the enumeration name of this cursor kind."""
if self._name_map is None:
self._name_map = {}
for key,value in CursorKind.__dict__.items():
if isinstance(value,CursorKind):
for key, value in self.__class__.__dict__.items():
if isinstance(value, self.__class__):
self._name_map[value] = key
return self._name_map[self]
@staticmethod
def from_id(id):
if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None:
raise ValueError,'Unknown cursor kind %d' % id
return CursorKind._kinds[id]
@classmethod
def from_id(cls, id):
if id >= len(cls._kinds) or cls._kinds[id] is None:
raise ValueError,'Unknown template argument kind %d' % id
return cls._kinds[id]
def __repr__(self):
return '%s.%s' % (self.__class__, self.name,)
class CursorKind(BaseEnumeration):
"""
A CursorKind describes the kind of entity that a cursor points to.
"""
# The required BaseEnumeration declarations.
_kinds = []
_name_map = None
@staticmethod
def get_all_kinds():
@ -578,11 +595,6 @@ class CursorKind(object):
def __repr__(self):
return 'CursorKind.%s' % (self.name,)
# FIXME: Is there a nicer way to expose this enumeration? We could potentially
# represent the nested structure, or even build a class hierarchy. The main
# things we want for sure are (a) simple external access to kinds, (b) a place
# to hang a description and name, (c) easy to keep in sync with Index.h.
###
# Declaration Kinds
@ -1101,6 +1113,24 @@ CursorKind.INCLUSION_DIRECTIVE = CursorKind(503)
# A module import declaration.
CursorKind.MODULE_IMPORT_DECL = CursorKind(600)
### Template Argument Kinds ###
class TemplateArgumentKind(BaseEnumeration):
"""
A TemplateArgumentKind describes the kind of entity that a template argument
represents.
"""
# The required BaseEnumeration declarations.
_kinds = []
_name_map = None
TemplateArgumentKind.NULL = TemplateArgumentKind(0)
TemplateArgumentKind.TYPE = TemplateArgumentKind(1)
TemplateArgumentKind.DECLARATION = TemplateArgumentKind(2)
TemplateArgumentKind.NULLPTR = TemplateArgumentKind(3)
TemplateArgumentKind.INTEGRAL = TemplateArgumentKind(4)
### Cursors ###
class Cursor(Structure):
@ -1378,6 +1408,27 @@ class Cursor(Structure):
for i in range(0, num_args):
yield conf.lib.clang_Cursor_getArgument(self, i)
def get_num_template_arguments(self):
"""Returns the number of template args associated with this cursor."""
return conf.lib.clang_Cursor_getNumTemplateArguments(self)
def get_template_argument_kind(self, num):
"""Returns the TemplateArgumentKind for the indicated template
argument."""
return conf.lib.clang_Cursor_getTemplateArgumentKind(self, num)
def get_template_argument_type(self, num):
"""Returns the CXType for the indicated template argument."""
return conf.lib.clang_Cursor_getTemplateArgumentType(self, num)
def get_template_argument_value(self, num):
"""Returns the value of the indicated arg as a signed 64b integer."""
return conf.lib.clang_Cursor_getTemplateArgumentValue(self, num)
def get_template_argument_unsigned_value(self, num):
"""Returns the value of the indicated arg as an unsigned 64b integer."""
return conf.lib.clang_Cursor_getTemplateArgumentUnsignedValue(self, num)
def get_children(self):
"""Return an iterator for accessing the children of this cursor."""
@ -1461,7 +1512,7 @@ class Cursor(Structure):
### C++ access specifiers ###
class AccessSpecifier(object):
class AccessSpecifier(BaseEnumeration):
"""
Describes the access of a C++ class member
"""
@ -1470,34 +1521,9 @@ class AccessSpecifier(object):
_kinds = []
_name_map = None
def __init__(self, value):
if value >= len(AccessSpecifier._kinds):
AccessSpecifier._kinds += [None] * (value - len(AccessSpecifier._kinds) + 1)
if AccessSpecifier._kinds[value] is not None:
raise ValueError,'AccessSpecifier already loaded'
self.value = value
AccessSpecifier._kinds[value] = self
AccessSpecifier._name_map = None
def from_param(self):
return self.value
@property
def name(self):
"""Get the enumeration name of this access specifier."""
if self._name_map is None:
self._name_map = {}
for key,value in AccessSpecifier.__dict__.items():
if isinstance(value,AccessSpecifier):
self._name_map[value] = key
return self._name_map[self]
@staticmethod
def from_id(id):
if id >= len(AccessSpecifier._kinds) or not AccessSpecifier._kinds[id]:
raise ValueError,'Unknown access specifier %d' % id
return AccessSpecifier._kinds[id]
def __repr__(self):
return 'AccessSpecifier.%s' % (self.name,)
@ -1509,7 +1535,7 @@ AccessSpecifier.NONE = AccessSpecifier(4)
### Type Kinds ###
class TypeKind(object):
class TypeKind(BaseEnumeration):
"""
Describes the kind of type.
"""
@ -1518,39 +1544,11 @@ class TypeKind(object):
_kinds = []
_name_map = None
def __init__(self, value):
if value >= len(TypeKind._kinds):
TypeKind._kinds += [None] * (value - len(TypeKind._kinds) + 1)
if TypeKind._kinds[value] is not None:
raise ValueError,'TypeKind already loaded'
self.value = value
TypeKind._kinds[value] = self
TypeKind._name_map = None
def from_param(self):
return self.value
@property
def name(self):
"""Get the enumeration name of this cursor kind."""
if self._name_map is None:
self._name_map = {}
for key,value in TypeKind.__dict__.items():
if isinstance(value,TypeKind):
self._name_map[value] = key
return self._name_map[self]
@property
def spelling(self):
"""Retrieve the spelling of this TypeKind."""
return conf.lib.clang_getTypeKindSpelling(self.value)
@staticmethod
def from_id(id):
if id >= len(TypeKind._kinds) or TypeKind._kinds[id] is None:
raise ValueError,'Unknown type kind %d' % id
return TypeKind._kinds[id]
def __repr__(self):
return 'TypeKind.%s' % (self.name,)
@ -1603,43 +1601,16 @@ TypeKind.VARIABLEARRAY = TypeKind(115)
TypeKind.DEPENDENTSIZEDARRAY = TypeKind(116)
TypeKind.MEMBERPOINTER = TypeKind(117)
class RefQualifierKind(object):
class RefQualifierKind(BaseEnumeration):
"""Describes a specific ref-qualifier of a type."""
# The unique kind objects, indexed by id.
_kinds = []
_name_map = None
def __init__(self, value):
if value >= len(RefQualifierKind._kinds):
num_kinds = value - len(RefQualifierKind._kinds) + 1
RefQualifierKind._kinds += [None] * num_kinds
if RefQualifierKind._kinds[value] is not None:
raise ValueError, 'RefQualifierKind already loaded'
self.value = value
RefQualifierKind._kinds[value] = self
RefQualifierKind._name_map = None
def from_param(self):
return self.value
@property
def name(self):
"""Get the enumeration name of this kind."""
if self._name_map is None:
self._name_map = {}
for key, value in RefQualifierKind.__dict__.items():
if isinstance(value, RefQualifierKind):
self._name_map[value] = key
return self._name_map[self]
@staticmethod
def from_id(id):
if (id >= len(RefQualifierKind._kinds) or
RefQualifierKind._kinds[id] is None):
raise ValueError, 'Unknown type kind %d' % id
return RefQualifierKind._kinds[id]
def __repr__(self):
return 'RefQualifierKind.%s' % (self.name,)
@ -3314,6 +3285,27 @@ functionList = [
Cursor,
Cursor.from_result),
("clang_Cursor_getNumTemplateArguments",
[Cursor],
c_int),
("clang_Cursor_getTemplateArgumentKind",
[Cursor, c_uint],
TemplateArgumentKind.from_id),
("clang_Cursor_getTemplateArgumentType",
[Cursor, c_uint],
Type,
Type.from_result),
("clang_Cursor_getTemplateArgumentValue",
[Cursor, c_uint],
c_longlong),
("clang_Cursor_getTemplateArgumentUnsignedValue",
[Cursor, c_uint],
c_ulonglong),
("clang_Cursor_isBitField",
[Cursor],
bool),

View File

@ -1,6 +1,8 @@
import ctypes
import gc
from clang.cindex import CursorKind
from clang.cindex import TemplateArgumentKind
from clang.cindex import TranslationUnit
from clang.cindex import TypeKind
from .util import get_cursor
@ -244,6 +246,48 @@ def test_get_arguments():
assert arguments[0].spelling == "i"
assert arguments[1].spelling == "j"
kTemplateArgTest = """\
template <int kInt, typename T, bool kBool>
void foo();
template<>
void foo<-7, float, true>();
"""
def test_get_num_template_arguments():
tu = get_tu(kTemplateArgTest, lang='cpp')
foos = get_cursors(tu, 'foo')
assert foos[1].get_num_template_arguments() == 3
def test_get_template_argument_kind():
tu = get_tu(kTemplateArgTest, lang='cpp')
foos = get_cursors(tu, 'foo')
assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL
assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE
assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL
def test_get_template_argument_type():
tu = get_tu(kTemplateArgTest, lang='cpp')
foos = get_cursors(tu, 'foo')
assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT
def test_get_template_argument_value():
tu = get_tu(kTemplateArgTest, lang='cpp')
foos = get_cursors(tu, 'foo')
assert foos[1].get_template_argument_value(0) == -7
assert foos[1].get_template_argument_value(2) == True
def test_get_template_argument_unsigned_value():
tu = get_tu(kTemplateArgTest, lang='cpp')
foos = get_cursors(tu, 'foo')
assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7
assert foos[1].get_template_argument_unsigned_value(2) == True
def test_referenced():
tu = get_tu('void foo(); void bar() { foo(); }')
foo = get_cursor(tu, 'foo')

View File

@ -2942,6 +2942,124 @@ CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C);
*/
CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i);
/**
* \brief Describes the kind of a template argument.
*
* See the definition of llvm::clang::TemplateArgument::ArgKind for full
* element descriptions.
*/
enum CXTemplateArgumentKind {
CXTemplateArgumentKind_Null,
CXTemplateArgumentKind_Type,
CXTemplateArgumentKind_Declaration,
CXTemplateArgumentKind_NullPtr,
CXTemplateArgumentKind_Integral,
CXTemplateArgumentKind_Template,
CXTemplateArgumentKind_TemplateExpansion,
CXTemplateArgumentKind_Expression,
CXTemplateArgumentKind_Pack,
/* Indicates an error case, preventing the kind from being deduced. */
CXTemplateArgumentKind_Invalid
};
/**
*\brief Returns the number of template args of a function decl representing a
* template specialization.
*
* If the argument cursor cannot be converted into a template function
* declaration, -1 is returned.
*
* For example, for the following declaration and specialization:
* template <typename T, int kInt, bool kBool>
* void foo() { ... }
*
* template <>
* void foo<float, -7, true>();
*
* The value 3 would be returned from this call.
*/
CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C);
/**
* \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
* template argument kind is returned.
*
* For example, for the following declaration and specialization:
* template <typename T, int kInt, bool kBool>
* void foo() { ... }
*
* template <>
* void foo<float, -7, true>();
*
* For I = 0, 1, and 2, Type, Integral, and Integral will be returned,
* respectively.
*/
CINDEX_LINKAGE enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(
CXCursor C, unsigned I);
/**
* \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
* 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>
* void foo() { ... }
*
* template <>
* void foo<float, -7, true>();
*
* If called with I = 0, "float", will be returned.
* Invalid types will be returned for I == 1 or 2.
*/
CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C,
unsigned I);
/**
* \brief 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 CXCursor that does not represent a
* FunctionDecl or whose I'th template argument is not an integral value.
*
* For example, for the following declaration and specialization:
* template <typename T, int kInt, bool kBool>
* void foo() { ... }
*
* template <>
* void foo<float, -7, true>();
*
* If called with I = 1 or 2, -7 or true will be returned, respectively.
* For I == 0, this function's behavior is undefined.
*/
CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C,
unsigned I);
/**
* \brief 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 CXCursor that does not represent a
* FunctionDecl or whose I'th template argument is not an integral value.
*
* For example, for the following declaration and specialization:
* template <typename T, int kInt, bool kBool>
* void foo() { ... }
*
* template <>
* void foo<float, 2147483649, true>();
*
* If called with I = 1 or 2, 2147483649 or true will be returned, respectively.
* For I == 0, this function's behavior is undefined.
*/
CINDEX_LINKAGE unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(
CXCursor C, unsigned I);
/**
* \brief Determine whether two CXTypes represent the same type.
*

View File

@ -100,6 +100,16 @@ template class Pair<int, int>;
template<typename T, typename U>
struct SuperPair : Pair<int, int>, Pair<T, U> { };
enum FxnTmplEnum {
FxnTmplEnum_A, FxnTmplEnum_B, FxnTmplEnum_C,
};
template <typename T, int I, FxnTmplEnum, int E>
void foo(T Value) {}
static const int FxnTmpl_Var = 7;
template <>
void foo<float, 9, FxnTmplEnum_B, FxnTmpl_Var + 7>(float Value);
// RUN: c-index-test -test-load-source all -fno-delayed-template-parsing %s | FileCheck -check-prefix=CHECK-LOAD %s
// CHECK-LOAD: index-templates.cpp:4:6: FunctionTemplate=f:4:6 Extent=[3:1 - 4:22]
// CHECK-LOAD: index-templates.cpp:3:19: TemplateTypeParameter=T:3:19 (Definition) Extent=[3:10 - 3:20]
@ -178,7 +188,7 @@ struct SuperPair : Pair<int, int>, Pair<T, U> { };
// 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: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]
// 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_# Extent=[3:1 - 4:22]

View File

@ -4,7 +4,7 @@ int main() { }
// RUN: c-index-test -write-pch %t.pch -fno-delayed-template-parsing -x c++-header %S/Inputs/preamble_macro_template.h
// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -fno-delayed-template-parsing -I %S/Inputs -include %t %s 2>&1 | tee %t.check.txt | FileCheck %s
// CHECK: preamble_macro_template.h:4:6: FunctionDecl=foo:4:6 (Definition) [Specialization of foo:4:6] Extent=[4:1 - 6:2]
// CHECK: preamble_macro_template.h:4:6: FunctionDecl=foo:4:6 (Definition) [Specialization of foo:4:6] [Template arg 0: kind: 1, type: int] Extent=[4:1 - 6:2]
// CHECK: preamble_macro_template.h:4:13: ParmDecl=p:4:13 (Definition) Extent=[4:10 - 4:14]
// CHECK: preamble_macro_template.h:4:16: CompoundStmt= Extent=[4:16 - 6:2]
// CHECK: preamble_macro_template.h:5:3: CStyleCastExpr= Extent=[5:3 - 5:27]

View File

@ -796,15 +796,42 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
printf(" [access=%s isVirtual=%s]", accessStr,
isVirtual ? "true" : "false");
}
SpecializationOf = clang_getSpecializedCursorTemplate(Cursor);
if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) {
CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf);
CXString Name = clang_getCursorSpelling(SpecializationOf);
clang_getSpellingLocation(Loc, 0, &line, &column, 0);
printf(" [Specialization of %s:%d:%d]",
printf(" [Specialization of %s:%d:%d]",
clang_getCString(Name), line, column);
clang_disposeString(Name);
if (Cursor.kind == CXCursor_FunctionDecl) {
/* Collect the template parameter kinds from the base template. */
unsigned NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor);
unsigned I;
for (I = 0; I < NumTemplateArgs; I++) {
enum CXTemplateArgumentKind TAK =
clang_Cursor_getTemplateArgumentKind(Cursor, I);
switch(TAK) {
case CXTemplateArgumentKind_Type:
{
CXType T = clang_Cursor_getTemplateArgumentType(Cursor, I);
CXString S = clang_getTypeSpelling(T);
printf(" [Template arg %d: kind: %d, type: %s]",
I, TAK, clang_getCString(S));
clang_disposeString(S);
}
break;
case CXTemplateArgumentKind_Integral:
printf(" [Template arg %d: kind: %d, intval: %lld]",
I, TAK, clang_Cursor_getTemplateArgumentValue(Cursor, I));
break;
default:
printf(" [Template arg %d: kind: %d]\n", I, TAK);
}
}
}
}
clang_getOverriddenCursors(Cursor, &overridden, &num_overridden);

View File

@ -1074,6 +1074,140 @@ CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i) {
return clang_getNullCursor();
}
int clang_Cursor_getNumTemplateArguments(CXCursor C) {
if (clang_getCursorKind(C) != CXCursor_FunctionDecl) {
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) {
return -1;
}
return SpecInfo->TemplateArguments->size();
}
enum CXGetTemplateArgumentStatus {
/** \brief The operation completed successfully */
CXGetTemplateArgumentStatus_Success = 0,
/** \brief The specified cursor did not represent a FunctionDecl. */
CXGetTemplateArgumentStatus_CursorNotFunctionDecl = -1,
/** \brief The specified cursor was not castable to a FunctionDecl. */
CXGetTemplateArgumentStatus_BadFunctionDeclCast = -2,
/** \brief A NULL FunctionTemplateSpecializationInfo was retrieved. */
CXGetTemplateArgumentStatus_NullTemplSpecInfo = -3,
/** \brief An invalid (OOB) argument index was specified */
CXGetTemplateArgumentStatus_InvalidIndex = -4
};
static int clang_Cursor_getTemplateArgument(
CXCursor C, unsigned I, TemplateArgument *TA) {
if (clang_getCursorKind(C) != CXCursor_FunctionDecl) {
return CXGetTemplateArgumentStatus_CursorNotFunctionDecl;
}
const FunctionDecl *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(
getCursorDecl(C));
if (!FD) {
return CXGetTemplateArgumentStatus_BadFunctionDeclCast;
}
const FunctionTemplateSpecializationInfo* SpecInfo =
FD->getTemplateSpecializationInfo();
if (!SpecInfo) {
return CXGetTemplateArgumentStatus_NullTemplSpecInfo;
}
if (I >= SpecInfo->TemplateArguments->size()) {
return CXGetTemplateArgumentStatus_InvalidIndex;
}
*TA = SpecInfo->TemplateArguments->get(I);
return 0;
}
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::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 clang_Cursor_getTemplateArgumentType(CXCursor C, unsigned I) {
TemplateArgument TA;
if (clang_Cursor_getTemplateArgument(C, I, &TA) !=
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));
}
long long clang_Cursor_getTemplateArgumentValue(CXCursor C, unsigned I) {
TemplateArgument TA;
if (clang_Cursor_getTemplateArgument(C, I, &TA) !=
CXGetTemplateArgumentStatus_Success) {
assert(0 && "Unable to retrieve TemplateArgument");
return 0;
}
if (TA.getKind() != TemplateArgument::Integral) {
assert(0 && "Passed template argument is not Integral");
return 0;
}
return TA.getAsIntegral().getSExtValue();
}
unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C,
unsigned I) {
TemplateArgument TA;
if (clang_Cursor_getTemplateArgument(C, I, &TA) !=
CXGetTemplateArgumentStatus_Success) {
assert(0 && "Unable to retrieve TemplateArgument");
return 0;
}
if (TA.getKind() != TemplateArgument::Integral) {
assert(0 && "Passed template argument is not Integral");
return 0;
}
return TA.getAsIntegral().getZExtValue();
}
} // end: extern "C"
//===----------------------------------------------------------------------===//

View File

@ -7,6 +7,11 @@ clang_CXXMethod_isPureVirtual
clang_CXXMethod_isStatic
clang_CXXMethod_isVirtual
clang_Cursor_getArgument
clang_Cursor_getNumTemplateArguments
clang_Cursor_getTemplateArgumentKind
clang_Cursor_getTemplateArgumentType
clang_Cursor_getTemplateArgumentValue
clang_Cursor_getTemplateArgumentUnsignedValue
clang_Cursor_getBriefCommentText
clang_Cursor_getCommentRange
clang_Cursor_getMangling