libclang: add clang_getTypeSpelling(CXType CT)

Adds a function clang_getTypeSpelling(CXType CT) that returns
a CXString containing the underlying type.

Patch by Ben Gertzfield.

llvm-svn: 175299
This commit is contained in:
Dmitri Gribenko 2013-02-15 21:15:49 +00:00
parent d4c1a2063c
commit 0035372bb7
10 changed files with 156 additions and 62 deletions

View File

@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 11
#define CINDEX_VERSION_MINOR 12
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@ -2694,6 +2694,14 @@ typedef struct {
*/
CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C);
/**
* \brief Pretty-print the underlying type using the rules of the
* language of the translation unit from which it came.
*
* If the type is invalid, an empty string is returned.
*/
CINDEX_LINKAGE CXString clang_getTypeSpelling(CXType CT);
/**
* \brief Retrieve the underlying type of a typedef declaration.
*

View File

@ -0,0 +1,44 @@
typedef int FooType;
int *p;
int *f(int *p, char *x, FooType z, int arr[5], void (*fn)(int)) {
fn(*p);
const FooType w = z;
return p + z + arr[3];
}
typedef double OtherType;
typedef int ArrayType[5];
int __attribute__((vector_size(16))) x;
typedef int __attribute__((vector_size(16))) int4_t;
// RUN: c-index-test -test-print-type %s | FileCheck %s
// CHECK: FunctionDecl=f:3:6 (Definition) [type=int *(int *, char *, FooType, int *, void (*)(int))] [typekind=FunctionProto] [canonicaltype=int *(int *, char *, int, int *, void (*)(int))] [canonicaltypekind=FunctionProto] [resulttype=int *] [resulttypekind=Pointer] [args= [int *] [Pointer] [char *] [Pointer] [FooType] [Typedef] [int *] [Pointer] [void (*)(int)] [Pointer]] [isPOD=0]
// CHECK: ParmDecl=p:3:13 (Definition) [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: ParmDecl=x:3:22 (Definition) [type=char *] [typekind=Pointer] [isPOD=1]
// CHECK: ParmDecl=z:3:33 (Definition) [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: TypeRef=FooType:1:13 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: ParmDecl=arr:3:40 (Definition) [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
// CHECK: ParmDecl=fn:3:55 (Definition) [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1]
// CHECK: ParmDecl=:3:62 (Definition) [type=int] [typekind=Int] [isPOD=1]
// CHECK: CompoundStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: CallExpr=fn:3:55 [type=void] [typekind=Void] [isPOD=0]
// CHECK: DeclRefExpr=fn:3:55 [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1]
// CHECK: UnaryOperator= [type=int] [typekind=Int] [isPOD=1]
// CHECK: DeclRefExpr=p:3:13 [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: DeclStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: VarDecl=w:5:17 (Definition) [type=const FooType] [typekind=Typedef] const [canonicaltype=const int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: TypeRef=FooType:1:13 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: DeclRefExpr=z:3:33 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: ReturnStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: BinaryOperator= [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: BinaryOperator= [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: DeclRefExpr=p:3:13 [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: DeclRefExpr=z:3:33 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: ArraySubscriptExpr= [type=int] [typekind=Int] [isPOD=1]
// CHECK: DeclRefExpr=arr:3:40 [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
// CHECK: TypedefDecl=OtherType:8:16 (Definition) [type=OtherType] [typekind=Typedef] [canonicaltype=double] [canonicaltypekind=Double] [isPOD=1]
// CHECK: TypedefDecl=ArrayType:9:13 (Definition) [type=ArrayType] [typekind=Typedef] [canonicaltype=int [5]] [canonicaltypekind=ConstantArray] [isPOD=1]
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
// CHECK: VarDecl=x:10:38 [type=__attribute__((__vector_size__(4 * sizeof(int)))) int] [typekind=Vector] [isPOD=1]
// CHECK: TypedefDecl=int4_t:11:46 (Definition) [type=int4_t] [typekind=Typedef] [canonicaltype=__attribute__((__vector_size__(4 * sizeof(int)))) int] [canonicaltypekind=Vector] [isPOD=1]

View File

@ -0,0 +1,56 @@
namespace outer {
template<typename T>
struct Foo {
T t;
};
namespace inner {
struct Bar {
Bar(outer::Foo<bool>* foo) { };
typedef int FooType;
int *p;
int *f(int *p, char *x, FooType z) {
const FooType w = z;
return p + z;
}
typedef double OtherType;
typedef int ArrayType[5];
};
}
}
// RUN: c-index-test -test-print-type %s | FileCheck %s
// CHECK: Namespace=outer:1:11 (Definition) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: ClassTemplate=Foo:4:8 (Definition) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: TemplateTypeParameter=T:3:19 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
// CHECK: FieldDecl=t:5:5 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
// CHECK: TypeRef=T:3:19 [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
// CHECK: Namespace=inner:8:11 (Definition) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: StructDecl=Bar:10:8 (Definition) [type=outer::inner::Bar] [typekind=Record] [isPOD=0]
// CHECK: CXXConstructor=Bar:11:3 (Definition) [type=void (outer::Foo<bool> *)] [typekind=FunctionProto] [canonicaltype=void (outer::Foo<bool> *)] [canonicaltypekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [args= [outer::Foo<bool> *] [Pointer]] [isPOD=0]
// CHECK: ParmDecl=foo:11:25 (Definition) [type=outer::Foo<bool> *] [typekind=Pointer] [canonicaltype=outer::Foo<bool> *] [canonicaltypekind=Pointer] [isPOD=1]
// CHECK: NamespaceRef=outer:1:11 [type=] [typekind=Invalid] [isPOD=0]
// CHECK: TemplateRef=Foo:4:8 [type=] [typekind=Invalid] [isPOD=0]
// CHECK: CompoundStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: TypedefDecl=FooType:13:15 (Definition) [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: FieldDecl=p:14:8 (Definition) [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: CXXMethod=f:15:8 (Definition) [type=int *(int *, char *, FooType)] [typekind=FunctionProto] [canonicaltype=int *(int *, char *, int)] [canonicaltypekind=FunctionProto] [resulttype=int *] [resulttypekind=Pointer] [args= [int *] [Pointer] [char *] [Pointer] [FooType] [Typedef]] [isPOD=0]
// CHECK: ParmDecl=p:15:15 (Definition) [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: ParmDecl=x:15:24 (Definition) [type=char *] [typekind=Pointer] [isPOD=1]
// CHECK: ParmDecl=z:15:35 (Definition) [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: TypeRef=FooType:13:15 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: CompoundStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: DeclStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: VarDecl=w:16:19 (Definition) [type=const FooType] [typekind=Typedef] const [canonicaltype=const int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: TypeRef=FooType:13:15 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: DeclRefExpr=z:15:35 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: ReturnStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: BinaryOperator= [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: DeclRefExpr=p:15:15 [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: DeclRefExpr=z:15:35 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: TypedefDecl=OtherType:19:18 (Definition) [type=OtherType] [typekind=Typedef] [canonicaltype=double] [canonicaltypekind=Double] [isPOD=1]
// CHECK: TypedefDecl=ArrayType:20:15 (Definition) [type=ArrayType] [typekind=Typedef] [canonicaltype=int [5]] [canonicaltypekind=ConstantArray] [isPOD=1]

View File

@ -0,0 +1,10 @@
@interface Foo
@property (readonly) id x;
-(int) mymethod;
-(const id) mymethod2:(id)x blah:(Class)y boo:(SEL)z;
@end
// RUN: c-index-test -test-print-type %s | FileCheck %s
// CHECK: ObjCPropertyDecl=x:2:25 [type=id] [typekind=ObjCId] [canonicaltype=id] [canonicaltypekind=ObjCObjectPointer] [isPOD=1]
// CHECK: ObjCInstanceMethodDecl=mymethod:3:8 [type=] [typekind=Invalid] [resulttype=int] [resulttypekind=Int] [isPOD=0]
// CHECK: ObjCInstanceMethodDecl=mymethod2:blah:boo::4:13 [type=] [typekind=Invalid] [resulttype=const id] [resulttypekind=ObjCId] [args= [id] [ObjCId] [Class] [ObjCClass] [SEL] [ObjCSel]] [isPOD=0]

View File

@ -1,28 +0,0 @@
typedef int FooType;
int *p;
int *f(int *p, char *x, FooType z) {
const FooType w = z;
return p + z;
}
typedef double OtherType;
typedef int ArrayType[5];
// RUN: c-index-test -test-print-typekind %s | FileCheck %s
// CHECK: TypedefDecl=FooType:1:13 (Definition) typekind=Typedef [canonical=Int] [isPOD=1]
// CHECK: VarDecl=p:2:6 typekind=Pointer [isPOD=1]
// CHECK: FunctionDecl=f:3:6 (Definition) typekind=FunctionProto [canonical=FunctionProto] [result=Pointer] [args= Pointer Pointer Typedef] [isPOD=0]
// CHECK: ParmDecl=p:3:13 (Definition) typekind=Pointer [isPOD=1]
// CHECK: ParmDecl=x:3:22 (Definition) typekind=Pointer [isPOD=1]
// CHECK: ParmDecl=z:3:33 (Definition) typekind=Typedef [canonical=Int] [isPOD=1]
// CHECK: TypeRef=FooType:1:13 typekind=Typedef [canonical=Int] [isPOD=1]
// CHECK: CompoundStmt= typekind=Invalid [isPOD=0]
// CHECK: DeclStmt= typekind=Invalid [isPOD=0]
// CHECK: VarDecl=w:4:17 (Definition) typekind=Typedef const [canonical=Int] [isPOD=1]
// CHECK: TypeRef=FooType:1:13 typekind=Typedef [canonical=Int] [isPOD=1]
// CHECK: DeclRefExpr=z:3:33 typekind=Typedef [canonical=Int] [isPOD=1]
// CHECK: ReturnStmt= typekind=Invalid [isPOD=0]
// CHECK: BinaryOperator= typekind=Pointer [isPOD=1]
// CHECK: DeclRefExpr=p:3:13 typekind=Pointer [isPOD=1]
// CHECK: DeclRefExpr=z:3:33 typekind=Typedef [canonical=Int] [isPOD=1]
// CHECK: TypedefDecl=OtherType:7:16 (Definition) typekind=Typedef [canonical=Double] [isPOD=1]
// CHECK: TypedefDecl=ArrayType:8:13 (Definition) typekind=Typedef [canonical=ConstantArray] [isPOD=1]

View File

@ -1,10 +0,0 @@
@interface Foo
@property (readonly) id x;
-(int) mymethod;
-(const id) mymethod2:(id)x blah:(Class)y boo:(SEL)z;
@end
// RUN: c-index-test -test-print-typekind %s | FileCheck %s
// CHECK: ObjCPropertyDecl=x:2:25 typekind=ObjCId [canonical=ObjCObjectPointer]
// CHECK: ObjCInstanceMethodDecl=mymethod:3:8 typekind=Invalid [result=Int]
// CHECK: ObjCInstanceMethodDecl=mymethod2:blah:boo::4:13 typekind=Invalid [result=ObjCId] [args= ObjCId ObjCClass ObjCSel]

View File

@ -1,6 +0,0 @@
int __attribute__((vector_size(16))) x;
typedef int __attribute__((vector_size(16))) int4_t;
// RUN: c-index-test -test-print-typekind %s | FileCheck %s
// CHECK: VarDecl=x:1:38 typekind=Vector [isPOD=1]
// CHECK: TypedefDecl=int4_t:2:46 (Definition) typekind=Typedef [canonical=Vector] [isPOD=1]

View File

@ -1083,36 +1083,42 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p,
/* Typekind testing. */
/******************************************************************************/
static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p,
CXClientData d) {
static void PrintTypeAndTypeKind(CXType T, const char *Format) {
CXString TypeSpelling, TypeKindSpelling;
TypeSpelling = clang_getTypeSpelling(T);
TypeKindSpelling = clang_getTypeKindSpelling(T.kind);
printf(Format,
clang_getCString(TypeSpelling),
clang_getCString(TypeKindSpelling));
clang_disposeString(TypeSpelling);
clang_disposeString(TypeKindSpelling);
}
static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
CXClientData d) {
if (!clang_isInvalid(clang_getCursorKind(cursor))) {
CXType T = clang_getCursorType(cursor);
CXString S = clang_getTypeKindSpelling(T.kind);
PrintCursor(cursor, NULL);
printf(" typekind=%s", clang_getCString(S));
PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]");
if (clang_isConstQualifiedType(T))
printf(" const");
if (clang_isVolatileQualifiedType(T))
printf(" volatile");
if (clang_isRestrictQualifiedType(T))
printf(" restrict");
clang_disposeString(S);
/* Print the canonical type if it is different. */
{
CXType CT = clang_getCanonicalType(T);
if (!clang_equalTypes(T, CT)) {
CXString CS = clang_getTypeKindSpelling(CT.kind);
printf(" [canonical=%s]", clang_getCString(CS));
clang_disposeString(CS);
PrintTypeAndTypeKind(CT, " [canonicaltype=%s] [canonicaltypekind=%s]");
}
}
/* Print the return type if it exists. */
{
CXType RT = clang_getCursorResultType(cursor);
if (RT.kind != CXType_Invalid) {
CXString RS = clang_getTypeKindSpelling(RT.kind);
printf(" [result=%s]", clang_getCString(RS));
clang_disposeString(RS);
PrintTypeAndTypeKind(RT, " [resulttype=%s] [resulttypekind=%s]");
}
}
/* Print the argument types if they exist. */
@ -1124,9 +1130,7 @@ static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p,
for (i = 0; i < numArgs; ++i) {
CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i));
if (T.kind != CXType_Invalid) {
CXString S = clang_getTypeKindSpelling(T.kind);
printf(" %s", clang_getCString(S));
clang_disposeString(S);
PrintTypeAndTypeKind(T, " [%s] [%s]");
}
}
printf("]");
@ -3543,7 +3547,7 @@ static void print_usage(void) {
" c-index-test -test-inclusion-stack-tu <AST file>\n");
fprintf(stderr,
" c-index-test -test-print-linkage-source {<args>}*\n"
" c-index-test -test-print-typekind {<args>}*\n"
" c-index-test -test-print-type {<args>}*\n"
" c-index-test -test-print-bitwidth {<args>}*\n"
" c-index-test -print-usr [<CursorKind> {<args>}]*\n"
" c-index-test -print-usr-file <file>\n"
@ -3625,9 +3629,9 @@ int cindextest_main(int argc, const char **argv) {
else if (argc > 2 && strcmp(argv[1], "-test-print-linkage-source") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all", PrintLinkage,
NULL);
else if (argc > 2 && strcmp(argv[1], "-test-print-typekind") == 0)
else if (argc > 2 && strcmp(argv[1], "-test-print-type") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all",
PrintTypeKind, 0);
PrintType, 0);
else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all",
PrintBitWidth, 0);

View File

@ -200,6 +200,21 @@ CXType clang_getCursorType(CXCursor C) {
return MakeCXType(QualType(), TU);
}
CXString clang_getTypeSpelling(CXType CT) {
QualType T = GetQualType(CT);
if (T.isNull())
return cxstring::createEmpty();
CXTranslationUnit TU = GetTU(CT);
SmallString<64> Str;
llvm::raw_svector_ostream OS(Str);
PrintingPolicy PP(cxtu::getASTUnit(TU)->getASTContext().getLangOpts());
T.print(OS, PP);
return cxstring::createDup(OS.str());
}
CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
using namespace cxcursor;
CXTranslationUnit TU = cxcursor::getCursorTU(C);

View File

@ -205,6 +205,7 @@ clang_getTranslationUnitCursor
clang_getTranslationUnitSpelling
clang_getTypeDeclaration
clang_getTypeKindSpelling
clang_getTypeSpelling
clang_getTypedefDeclUnderlyingType
clang_hashCursor
clang_indexLoc_getCXSourceLocation