Index: test/Index/keep-going.cpp =================================================================== --- test/Index/keep-going.cpp +++ test/Index/keep-going.cpp @@ -19,10 +19,10 @@ // CHECK: FieldDecl=a:4:13 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] // CHECK: TypeRef=T:3:16 [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] // CHECK: ClassDecl=B:6:7 (Definition) [type=B] [typekind=Record] [isPOD=0] -// CHECK: C++ base class specifier=A:4:7 [access=public isVirtual=false] [type=A] [typekind=Unexposed] [canonicaltype=A] [canonicaltypekind=Record] [templateargs/1= [type=int] [typekind=Int]] [isPOD=0] [nbFields=1] +// CHECK: C++ base class specifier=A:4:7 [access=public isVirtual=false] [type=A] [typekind=Unexposed] [canonicaltype=A] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=int] [typekind=Int]] [templateargs/1= [type=int] [typekind=Int]] [isPOD=0] [nbFields=1] // CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0] // CHECK: ClassDecl=C:10:7 (Definition) [type=C] [typekind=Record] [isPOD=0] -// CHECK: C++ base class specifier=A:4:7 [access=public isVirtual=false] [type=A] [typekind=Unexposed] [canonicaltype=A] [canonicaltypekind=Record] [templateargs/1= [type=float] [typekind=Float]] [isPOD=0] [nbFields=1] +// CHECK: C++ base class specifier=A:4:7 [access=public isVirtual=false] [type=A] [typekind=Unexposed] [canonicaltype=A] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=float] [typekind=Float]] [templateargs/1= [type=float] [typekind=Float]] [isPOD=0] [nbFields=1] // CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0] // CHECK-DIAG: keep-going.cpp:1:10: error: 'missing1.h' file not found Index: test/Index/print-type.cpp =================================================================== --- test/Index/print-type.cpp +++ test/Index/print-type.cpp @@ -100,11 +100,11 @@ // 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: FieldDecl=baz:27:20 (Definition) [type=Baz] [typekind=Unexposed] [canonicaltype=outer::Baz] [canonicaltypekind=Record] [canonicaltemplateargs/3= [type=int] [typekind=Int]] [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/3= [type=int] [typekind=Int] [type=char *] [typekind=Pointer] [type=Foo] [typekind=Unexposed]] [isPOD=1] +// CHECK: FieldDecl=qux:28:29 (Definition) [type=Qux >] [typekind=Unexposed] [canonicaltype=outer::Qux >] [canonicaltypekind=Record] [canonicaltemplateargs/1=] [templateargs/3= [type=int] [typekind=Int] [type=char *] [typekind=Pointer] [type=Foo] [typekind=Unexposed]] [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] @@ -155,5 +155,5 @@ // CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1] // CHECK: TypeAliasTemplateDecl=TypeAlias:60:1 (Definition) [type=] [typekind=Invalid] [isPOD=0] // CHECK: TemplateTypeParameter=T:59:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] -// CHECK: FieldDecl=foo:62:39 (Definition) [type=TypeAlias] [typekind=Unexposed] [canonicaltype=outer::Qux] [canonicaltypekind=Record] [templateargs/1= [type=int] [typekind=Int]] [isPOD=1] +// CHECK: FieldDecl=foo:62:39 (Definition) [type=TypeAlias] [typekind=Unexposed] [canonicaltype=outer::Qux] [canonicaltypekind=Record] [canonicaltemplateargs/1=] [templateargs/1= [type=int] [typekind=Int]] [isPOD=1] // CHECK: TemplateRef=TypeAlias:60:1 [type=] [typekind=Invalid] [isPOD=0] Index: tools/c-index-test/c-index-test.c =================================================================== --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -1316,6 +1316,21 @@ return CXVisit_Continue; } +static void PrintTypeTemplateArgs(CXType T, const char *Format) { + int NumTArgs = clang_Type_getNumTemplateArguments(T); + if (NumTArgs != -1 && NumTArgs != 0) { + int i; + printf(Format, 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("]"); + } +} + static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, CXClientData d) { if (!clang_isInvalid(clang_getCursorKind(cursor))) { @@ -1338,6 +1353,7 @@ CXType CT = clang_getCanonicalType(T); if (!clang_equalTypes(T, CT)) { PrintTypeAndTypeKind(CT, " [canonicaltype=%s] [canonicaltypekind=%s]"); + PrintTypeTemplateArgs(CT, " [canonicaltemplateargs/%d="); } } /* Print the return type if it exists. */ @@ -1363,20 +1379,8 @@ } } /* 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("]"); - } - } + PrintTypeTemplateArgs(T, " [templateargs/%d="); + /* Print if this is a non-POD type. */ printf(" [isPOD=%d]", clang_isPODType(T)); /* Print the pointee type. */ Index: tools/libclang/CXType.cpp =================================================================== --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -924,11 +924,20 @@ QualType T = GetQualType(CT); if (T.isNull()) return -1; - const TemplateSpecializationType *Specialization = - T->getAs(); - if (!Specialization) - return -1; - return Specialization->template_arguments().size(); + + if (const TemplateSpecializationType *Specialization = + T->getAs()) { + return Specialization->template_arguments().size(); + } + + if (const CXXRecordDecl *RecordDecl = T->getAsCXXRecordDecl()) { + const ClassTemplateSpecializationDecl *TemplateDecl = + dyn_cast(RecordDecl); + if (TemplateDecl) + return TemplateDecl->getTemplateArgs().size(); + } + + return -1; } CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned i) { @@ -936,11 +945,17 @@ if (T.isNull()) return MakeCXType(QualType(), GetTU(CT)); - const TemplateSpecializationType *Specialization = - T->getAs(); - if (!Specialization) - return MakeCXType(QualType(), GetTU(CT)); - auto TA = Specialization->template_arguments(); + ArrayRef TA; + if (const TemplateSpecializationType *Specialization = + T->getAs()) { + TA = Specialization->template_arguments(); + } else if (const CXXRecordDecl *RecordDecl = T->getAsCXXRecordDecl()) { + const ClassTemplateSpecializationDecl *TemplateDecl = + dyn_cast(RecordDecl); + if (TemplateDecl) + TA = TemplateDecl->getTemplateArgs().asArray(); + } + if (TA.size() <= i) return MakeCXType(QualType(), GetTU(CT)); const TemplateArgument &A = TA[i];