summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2016-12-16 21:40:16 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2016-12-16 21:40:16 +0000
commit559be57f7aef4446004906e2c3796474fabf1664 (patch)
tree0e1eacc3ace7aa3645b51643ec0ea3abfe967c1e /tools
parent7fdb98e4e14616ecbea0439380888091d45174cf (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.c37
-rw-r--r--tools/libclang/CXType.cpp73
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,