From: Argyrios Kyrtzidis Date: Fri, 16 Dec 2016 21:40:16 +0000 (+0000) Subject: [libclang] Restore the CXXRecordDecl path for clang_Type_getNumTemplateArguments... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=559be57f7aef4446004906e2c3796474fabf1664;p=clang [libclang] Restore the CXXRecordDecl path for clang_Type_getNumTemplateArguments and clang_Type_getTemplateArgumentAsType Patch by Emilio Cobos Álvarez! See https://reviews.llvm.org/D26907 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289995 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Index/keep-going.cpp b/test/Index/keep-going.cpp index a25d1c4b04..82987c6cf1 100644 --- a/test/Index/keep-going.cpp +++ b/test/Index/keep-going.cpp @@ -19,10 +19,10 @@ class C : public A { }; // 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] [templateargs/1= [type=int] [typekind=Int]] [canonicaltype=A] [canonicaltypekind=Record] [canonicaltemplateargs/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] [templateargs/1= [type=float] [typekind=Float]] [canonicaltype=A] [canonicaltypekind=Record] [canonicaltemplateargs/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 diff --git a/test/Index/print-type.cpp b/test/Index/print-type.cpp index b17d5189c5..784733f421 100644 --- a/test/Index/print-type.cpp +++ b/test/Index/print-type.cpp @@ -61,6 +61,15 @@ using TypeAlias = outer::Qux; struct TypeAliasUser { TypeAlias foo; }; +template +struct Specialization {}; + +template<> +struct Specialization; + +Specialization& > templRefParam; +auto autoTemplRefParam = templRefParam; + // RUN: c-index-test -test-print-type %s -std=c++14 | FileCheck %s // CHECK: Namespace=outer:1:11 (Definition) [type=] [typekind=Invalid] [isPOD=0] // CHECK: ClassTemplate=Foo:4:8 (Definition) [type=] [typekind=Invalid] [isPOD=0] @@ -100,11 +109,11 @@ struct TypeAliasUser { TypeAlias foo; }; // 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] [templateargs/3= [type=int] [typekind=Int]] [canonicaltype=outer::Baz] [canonicaltypekind=Record] [canonicaltemplateargs/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] [templateargs/3= [type=int] [typekind=Int] [type=char *] [typekind=Pointer] [type=Foo] [typekind=Unexposed]] [canonicaltype=outer::Qux >] [canonicaltypekind=Record] [canonicaltemplateargs/3= [type=int] [typekind=Int] [type=char *] [typekind=Pointer] [type=outer::Foo] [typekind=Record]] [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 +164,14 @@ struct TypeAliasUser { TypeAlias foo; }; // 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] [templateargs/1= [type=int] [typekind=Int]] [canonicaltype=outer::Qux] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=int] [typekind=Int]] [isPOD=1] // CHECK: TemplateRef=TypeAlias:60:1 [type=] [typekind=Invalid] [isPOD=0] +// CHECK: ClassTemplate=Specialization:65:8 (Definition) [type=] [typekind=Invalid] [isPOD=0] +// CHECK: TemplateTypeParameter=T:64:19 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: StructDecl=Specialization:68:8 [Specialization of Specialization:65:8] [type=Specialization] [typekind=Record] [templateargs/1= [type=int] [typekind=Int]] [isPOD=0] +// CHECK: VarDecl=templRefParam:70:40 (Definition) [type=Specialization &>] [typekind=Unexposed] [templateargs/1= [type=Specialization &] [typekind=LValueReference]] [canonicaltype=Specialization &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization &] [typekind=LValueReference]] [isPOD=1] +// CHECK: TemplateRef=Specialization:65:8 [type=] [typekind=Invalid] [isPOD=0] +// CHECK: CallExpr=Specialization:65:8 [type=Specialization &>] [typekind=Unexposed] [templateargs/1= [type=Specialization &] [typekind=LValueReference]] [canonicaltype=Specialization &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization &] [typekind=LValueReference]] [isPOD=1] +// CHECK: VarDecl=autoTemplRefParam:71:6 (Definition) [type=Specialization &>] [typekind=Auto] [templateargs/1= [type=Specialization &] [typekind=LValueReference]] [canonicaltype=Specialization &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization &] [typekind=LValueReference]] [isPOD=1] +// CHECK: UnexposedExpr=templRefParam:70:40 [type=const Specialization &>] [typekind=Unexposed] const [templateargs/1= [type=Specialization &] [typekind=LValueReference]] [canonicaltype=const Specialization &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization &] [typekind=LValueReference]] [isPOD=1] +// CHECK: DeclRefExpr=templRefParam:70:40 [type=Specialization &>] [typekind=Unexposed] [templateargs/1= [type=Specialization &] [typekind=LValueReference]] [canonicaltype=Specialization &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization &] [typekind=LValueReference]] [isPOD=1] diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index de87351059..dfb4b27bce 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1316,6 +1316,25 @@ static enum CXVisitorResult FieldVisitor(CXCursor C, return CXVisit_Continue; } +static void PrintTypeTemplateArgs(CXType T, const char *Format) { + int NumTArgs = clang_Type_getNumTemplateArguments(T); + if (NumTArgs != -1 && NumTArgs != 0) { + int i; + CXType TArg; + printf(Format, NumTArgs); + for (i = 0; i < NumTArgs; ++i) { + TArg = clang_Type_getTemplateArgumentAsType(T, i); + if (TArg.kind != CXType_Invalid) { + PrintTypeAndTypeKind(TArg, " [type=%s] [typekind=%s]"); + } + } + /* Ensure that the returned type is invalid when indexing off-by-one. */ + TArg = clang_Type_getTemplateArgumentAsType(T, i); + assert(TArg.kind == CXType_Invalid); + printf("]"); + } +} + static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, CXClientData d) { if (!clang_isInvalid(clang_getCursorKind(cursor))) { @@ -1333,11 +1352,14 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, printf(" lvalue-ref-qualifier"); if (RQ == CXRefQualifier_RValue) printf(" rvalue-ref-qualifier"); + /* Print the template argument types if they exist. */ + PrintTypeTemplateArgs(T, " [templateargs/%d="); /* Print the canonical type if it is different. */ { 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. */ @@ -1362,21 +1384,6 @@ 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)); /* Print the pointee type. */ diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index a07bbe0857..22269984c1 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -920,33 +920,76 @@ CXString clang_getDeclObjCTypeEncoding(CXCursor C) { return cxstring::createDup(encoding); } +static Optional> +GetTemplateArguments(QualType Type) { + assert(!Type.isNull()); + if (const auto *Specialization = Type->getAs()) + return Specialization->template_arguments(); + + if (const auto *RecordDecl = Type->getAsCXXRecordDecl()) { + const auto *TemplateDecl = + dyn_cast(RecordDecl); + if (TemplateDecl) + return TemplateDecl->getTemplateArgs().asArray(); + } + + return None; +} + +static unsigned GetTemplateArgumentArraySize(ArrayRef TA) { + unsigned size = TA.size(); + for (const auto &Arg : TA) + if (Arg.getKind() == TemplateArgument::Pack) + size += Arg.pack_size() - 1; + return size; +} + int clang_Type_getNumTemplateArguments(CXType CT) { QualType T = GetQualType(CT); if (T.isNull()) return -1; - const TemplateSpecializationType *Specialization = - T->getAs(); - if (!Specialization) + + auto TA = GetTemplateArguments(T); + if (!TA) return -1; - return Specialization->template_arguments().size(); + + return GetTemplateArgumentArraySize(TA.getValue()); } -CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned i) { +static Optional TemplateArgumentToQualType(const TemplateArgument &A) { + if (A.getKind() == TemplateArgument::Type) + return A.getAsType(); + return None; +} + +static Optional +FindTemplateArgumentTypeAt(ArrayRef TA, unsigned index) { + unsigned current = 0; + for (const auto &A : TA) { + if (A.getKind() == TemplateArgument::Pack) { + if (index < current + A.pack_size()) + return TemplateArgumentToQualType(A.getPackAsArray()[index - current]); + current += A.pack_size(); + continue; + } + if (current == index) + return TemplateArgumentToQualType(A); + current++; + } + return None; +} + +CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) { QualType T = GetQualType(CT); 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(); - if (TA.size() <= i) + auto TA = GetTemplateArguments(T); + if (!TA) return MakeCXType(QualType(), GetTU(CT)); - const TemplateArgument &A = TA[i]; - if (A.getKind() != TemplateArgument::Type) - return MakeCXType(QualType(), GetTU(CT)); - return MakeCXType(A.getAsType(), GetTU(CT)); + + Optional QT = FindTemplateArgumentTypeAt(TA.getValue(), index); + return MakeCXType(QT.getValueOr(QualType()), GetTU(CT)); } unsigned clang_Type_visitFields(CXType PT,