From: Dmitri Gribenko Date: Thu, 27 Feb 2014 16:05:05 +0000 (+0000) Subject: libclang: New functions clang_Type_getNumTemplateArguments, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0b945e0ef27cdab8d67023396c5cd3f7466f1aaf;p=clang libclang: New functions clang_Type_getNumTemplateArguments, clang_Type_getTemplateArgument Note that these functions don't handle variadic templates -- see tests. Patch by Matthieu Nottale and Philippe Daouadi. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202406 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 02abfcab30..b77ddcb6c0 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -3080,6 +3080,24 @@ enum CXRefQualifierKind { CXRefQualifier_RValue }; +/** + * \brief Returns the number of template arguments for given class template + * specialization, or -1 if type \c T is not a class template specialization. + * + * Variadic argument packs count as only one argument, and can not be inspected + * further. + */ +CINDEX_LINKAGE int clang_Type_getNumTemplateArguments(CXType T); + +/** + * \brief Returns the type template argument of a template class specialization + * at given index. + * + * This function only returns template type arguments and does not handle + * template template arguments or variadic packs. + */ +CINDEX_LINKAGE CXType clang_Type_getTemplateArgumentAsType(CXType T, unsigned i); + /** * \brief Retrieve the ref-qualifier kind of a function or method. * diff --git a/test/Index/print-type.cpp b/test/Index/print-type.cpp index e1b25f2a1a..ef372a2fb7 100644 --- a/test/Index/print-type.cpp +++ b/test/Index/print-type.cpp @@ -5,10 +5,16 @@ struct Foo { T t; }; +template class W> +struct Baz { }; + +template +struct Qux { }; + namespace inner { struct Bar { - Bar(outer::Foo* foo) { }; + Bar(outer::Foo* foo) { } typedef int FooType; int *p; @@ -18,6 +24,8 @@ struct Bar { } typedef double OtherType; typedef int ArrayType[5]; + Baz baz; + Qux> qux; }; } @@ -39,43 +47,74 @@ struct Blob { }; int Blob::*member_pointer; -// RUN: c-index-test -test-print-type %s | FileCheck %s +// RUN: c-index-test -test-print-type %s -std=c++11 | 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 *){{.*}}] [typekind=FunctionProto] [canonicaltype=void (outer::Foo *){{.*}}] [canonicaltypekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [args= [outer::Foo *] [Pointer]] [isPOD=0] -// CHECK: ParmDecl=foo:11:25 (Definition) [type=outer::Foo *] [typekind=Pointer] [canonicaltype=outer::Foo *] [canonicaltypekind=Pointer] [isPOD=1] +// CHECK: ClassTemplate=Baz:9:8 (Definition) [type=] [typekind=Invalid] [isPOD=0] +// CHECK: TemplateTypeParameter=T:8:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: NonTypeTemplateParameter=U:8:32 (Definition) [type=unsigned int] [typekind=UInt] [isPOD=1] +// CHECK: TemplateTemplateParameter=W:8:60 (Definition) [type=] [typekind=Invalid] [isPOD=0] +// CHECK: Namespace=inner:14:11 (Definition) [type=] [typekind=Invalid] [isPOD=0] +// CHECK: StructDecl=Bar:16:8 (Definition) [type=outer::inner::Bar] [typekind=Record] [isPOD=0] +// CHECK: CXXConstructor=Bar:17:3 (Definition) [type=void (outer::Foo *){{.*}}] [typekind=FunctionProto] [canonicaltype=void (outer::Foo *){{.*}}] [canonicaltypekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [args= [outer::Foo *] [Pointer]] [isPOD=0] +// CHECK: ParmDecl=foo:17:25 (Definition) [type=outer::Foo *] [typekind=Pointer] [canonicaltype=outer::Foo *] [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: TypedefDecl=FooType:19:15 (Definition) [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1] +// CHECK: FieldDecl=p:20:8 (Definition) [type=int *] [typekind=Pointer] [isPOD=1] +// CHECK: CXXMethod=f:21: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:21:15 (Definition) [type=int *] [typekind=Pointer] [isPOD=1] +// CHECK: ParmDecl=x:21:24 (Definition) [type=char *] [typekind=Pointer] [isPOD=1] +// CHECK: ParmDecl=z:21:35 (Definition) [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1] +// CHECK: TypeRef=FooType:19: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: VarDecl=w:22:19 (Definition) [type=const FooType] [typekind=Typedef] const [canonicaltype=const int] [canonicaltypekind=Int] [isPOD=1] +// CHECK: TypeRef=FooType:19:15 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1] +// CHECK: UnexposedExpr=z:21:35 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1] +// CHECK: DeclRefExpr=z:21: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] -// CHECK: FunctionTemplate=tbar:27:3 [type=T (int)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0] -// CHECK: TemplateTypeParameter=T:26:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] -// CHECK: FunctionTemplate=tbar:30:3 [type=T (int *)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int *)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0] -// CHECK: ParmDecl=:30:11 (Definition) [type=int [5]] [typekind=ConstantArray] [isPOD=1] -// CHECK: FunctionTemplate=tbar:33:3 [type=T (int *)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int *)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0] -// CHECK: ParmDecl=:33:11 (Definition) [type=int [size]] [typekind=DependentSizedArray] [isPOD=0] -// CHECK: ParmDecl=incomplete_array:35:21 (Definition) [type=int []] [typekind=IncompleteArray] [isPOD=1] -// CHECK: VarDecl=variable_array:35:47 (Definition) [type=int [i]] [typekind=VariableArray] [isPOD=1] -// CHECK: VarDecl=member_pointer:40:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [isPOD=1] +// CHECK: UnexposedExpr=p:21:15 [type=int *] [typekind=Pointer] [isPOD=1] +// CHECK: DeclRefExpr=p:21:15 [type=int *] [typekind=Pointer] [isPOD=1] +// CHECK: UnexposedExpr=z:21:35 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1] +// CHECK: DeclRefExpr=z:21:35 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1] +// CHECK: TypedefDecl=OtherType:25:18 (Definition) [type=OtherType] [typekind=Typedef] [canonicaltype=double] [canonicaltypekind=Double] [isPOD=1] +// CHECK: TypedefDecl=ArrayType:26:15 (Definition) [type=ArrayType] [typekind=Typedef] [canonicaltype=int [5]] [canonicaltypekind=ConstantArray] [isPOD=1] +// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1] +// CHECK: FieldDecl=baz:27:20 (Definition) [type=Baz] [typekind=Unexposed] [canonicaltype=outer::Baz] [canonicaltypekind=Record] [templateargs/3= [type=int] [typekind=Int]] [isPOD=1] +// CHECK: TemplateRef=Baz:9:8 [type=] [typekind=Invalid] [isPOD=0] +// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1] +// CHECK: TemplateRef=Foo:4:8 [type=] [typekind=Invalid] [isPOD=0] +// CHECK: FieldDecl=qux:28:29 (Definition) [type=Qux >] [typekind=Unexposed] [canonicaltype=outer::Qux >] [canonicaltypekind=Record] [templateargs/1=] [isPOD=1] +// CHECK: TemplateRef=Qux:12:8 [type=] [typekind=Invalid] [isPOD=0] +// CHECK: TemplateRef=Foo:4:8 [type=] [typekind=Invalid] [isPOD=0] +// CHECK: FunctionTemplate=tbar:35:3 [type=T (int)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0] +// CHECK: TemplateTypeParameter=T:34:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: TypeRef=T:34:20 [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: ParmDecl=:35:11 (Definition) [type=int] [typekind=Int] [isPOD=1] +// CHECK: FunctionTemplate=tbar:38:3 [type=T (int *)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int *)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0] +// CHECK: TemplateTypeParameter=T:37:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: TypeRef=T:37:20 [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: ParmDecl=:38:11 (Definition) [type=int [5]] [typekind=ConstantArray] [isPOD=1] +// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1] +// CHECK: FunctionTemplate=tbar:41:3 [type=T (int *)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int *)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0] +// CHECK: TemplateTypeParameter=T:40:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: NonTypeTemplateParameter=size:40:27 (Definition) [type=int] [typekind=Int] [isPOD=1] +// CHECK: TypeRef=T:40:20 [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: ParmDecl=:41:11 (Definition) [type=int [size]] [typekind=DependentSizedArray] [isPOD=0] +// CHECK: DeclRefExpr=size:40:27 [type=int] [typekind=Int] [isPOD=1] +// CHECK: FunctionDecl=foo:43:6 (Definition) [type=void (int, int *)] [typekind=FunctionProto] [canonicaltype=void (int, int *)] [canonicaltypekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [args= [int] [Int] [int []] [IncompleteArray]] [isPOD=0] +// CHECK: ParmDecl=i:43:14 (Definition) [type=int] [typekind=Int] [isPOD=1] +// CHECK: ParmDecl=incomplete_array:43:21 (Definition) [type=int []] [typekind=IncompleteArray] [isPOD=1] +// CHECK: CompoundStmt= [type=] [typekind=Invalid] [isPOD=0] +// CHECK: DeclStmt= [type=] [typekind=Invalid] [isPOD=0] +// CHECK: VarDecl=variable_array:43:47 (Definition) [type=int [i]] [typekind=VariableArray] [isPOD=1] +// CHECK: DeclRefExpr=i:43:14 [type=int] [typekind=Int] [isPOD=1] +// CHECK: StructDecl=Blob:45:8 (Definition) [type=Blob] [typekind=Record] [isPOD=1] +// CHECK: FieldDecl=i:46:7 (Definition) [type=int] [typekind=Int] [isPOD=1] +// CHECK: VarDecl=member_pointer:48:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [isPOD=1] diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 3a47ae4bad..defc916819 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1263,11 +1263,11 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, } /* Print the argument types if they exist. */ { - int numArgs = clang_Cursor_getNumArguments(cursor); - if (numArgs != -1 && numArgs != 0) { + int NumArgs = clang_Cursor_getNumArguments(cursor); + if (NumArgs != -1 && NumArgs != 0) { int i; printf(" [args="); - for (i = 0; i < numArgs; ++i) { + for (i = 0; i < NumArgs; ++i) { CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i)); if (T.kind != CXType_Invalid) { PrintTypeAndTypeKind(T, " [%s] [%s]"); @@ -1276,6 +1276,21 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, printf("]"); } } + /* Print the template argument types if they exist. */ + { + int NumTArgs = clang_Type_getNumTemplateArguments(T); + if (NumTArgs != -1 && NumTArgs != 0) { + int i; + printf(" [templateargs/%d=", NumTArgs); + for (i = 0; i < NumTArgs; ++i) { + CXType TArg = clang_Type_getTemplateArgumentAsType(T, i); + if (TArg.kind != CXType_Invalid) { + PrintTypeAndTypeKind(TArg, " [type=%s] [typekind=%s]"); + } + } + printf("]"); + } + } /* Print if this is a non-POD type. */ printf(" [isPOD=%d]", clang_isPODType(T)); diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index d31168c1e7..545b56deda 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -871,4 +871,38 @@ CXString clang_getDeclObjCTypeEncoding(CXCursor C) { return cxstring::createDup(encoding); } +int clang_Type_getNumTemplateArguments(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) + return -1; + const CXXRecordDecl *RecordDecl = T->getAsCXXRecordDecl(); + if (!RecordDecl) + return -1; + const ClassTemplateSpecializationDecl *TemplateDecl = + dyn_cast(RecordDecl); + if (!TemplateDecl) + return -1; + return TemplateDecl->getTemplateArgs().size(); +} + +CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned i) { + QualType T = GetQualType(CT); + if (T.isNull()) + return MakeCXType(QualType(), GetTU(CT)); + const CXXRecordDecl *RecordDecl = T->getAsCXXRecordDecl(); + if (!RecordDecl) + return MakeCXType(QualType(), GetTU(CT)); + const ClassTemplateSpecializationDecl *TemplateDecl = + dyn_cast(RecordDecl); + if (!TemplateDecl) + return MakeCXType(QualType(), GetTU(CT)); + const TemplateArgumentList &TA = TemplateDecl->getTemplateArgs(); + if (TA.size() <= i) + return MakeCXType(QualType(), GetTU(CT)); + const TemplateArgument &A = TA.get(i); + if (A.getKind() != TemplateArgument::Type) + return MakeCXType(QualType(), GetTU(CT)); + return MakeCXType(A.getAsType(), GetTU(CT)); +} + } // end: extern "C" diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 5fbd9a2468..dfee253ba1 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -64,6 +64,8 @@ clang_Type_getAlignOf clang_Type_getClassType clang_Type_getSizeOf clang_Type_getOffsetOf +clang_Type_getNumTemplateArguments +clang_Type_getTemplateArgumentAsType clang_Type_getCXXRefQualifier clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText