diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2016-12-16 21:40:16 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2016-12-16 21:40:16 +0000 |
commit | 559be57f7aef4446004906e2c3796474fabf1664 (patch) | |
tree | 0e1eacc3ace7aa3645b51643ec0ea3abfe967c1e /tools | |
parent | 7fdb98e4e14616ecbea0439380888091d45174cf (diff) |
[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
Diffstat (limited to 'tools')
-rw-r--r-- | tools/c-index-test/c-index-test.c | 37 | ||||
-rw-r--r-- | tools/libclang/CXType.cpp | 73 |
2 files changed, 80 insertions, 30 deletions
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<ArrayRef<TemplateArgument>> +GetTemplateArguments(QualType Type) { + assert(!Type.isNull()); + if (const auto *Specialization = Type->getAs<TemplateSpecializationType>()) + return Specialization->template_arguments(); + + if (const auto *RecordDecl = Type->getAsCXXRecordDecl()) { + const auto *TemplateDecl = + dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl); + if (TemplateDecl) + return TemplateDecl->getTemplateArgs().asArray(); + } + + return None; +} + +static unsigned GetTemplateArgumentArraySize(ArrayRef<TemplateArgument> 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<TemplateSpecializationType>(); - 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<QualType> TemplateArgumentToQualType(const TemplateArgument &A) { + if (A.getKind() == TemplateArgument::Type) + return A.getAsType(); + return None; +} + +static Optional<QualType> +FindTemplateArgumentTypeAt(ArrayRef<TemplateArgument> 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<TemplateSpecializationType>(); - 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<QualType> QT = FindTemplateArgumentTypeAt(TA.getValue(), index); + return MakeCXType(QT.getValueOr(QualType()), GetTU(CT)); } unsigned clang_Type_visitFields(CXType PT, |