From 74dbe640021d96a8dbb85c592471c04449ade81c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 31 Aug 2010 19:31:58 +0000 Subject: [PATCH] Add libclang support for class template partial specializations, including a cursor kind, visitation, and USRs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112629 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 4 +++- test/Index/index-templates.cpp | 8 ++++++++ tools/libclang/CIndex.cpp | 20 ++++++++++++++++++++ tools/libclang/CIndexUSRs.cpp | 28 ++++++++++++++++++++-------- tools/libclang/CXCursor.cpp | 2 ++ 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 7131853d52..04d9bbcedf 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -992,9 +992,11 @@ enum CXCursorKind { CXCursor_FunctionTemplate = 30, /** \brief A C++ class template. */ CXCursor_ClassTemplate = 31, + /** \brief A C++ class template partial specialization. */ + CXCursor_ClassTemplatePartialSpecialization = 32, CXCursor_FirstDecl = CXCursor_UnexposedDecl, - CXCursor_LastDecl = CXCursor_ClassTemplate, + CXCursor_LastDecl = CXCursor_ClassTemplatePartialSpecialization, /* References */ CXCursor_FirstRef = 40, /* Decl references */ diff --git a/test/Index/index-templates.cpp b/test/Index/index-templates.cpp index 777c66e1a5..fb22f884d3 100644 --- a/test/Index/index-templates.cpp +++ b/test/Index/index-templates.cpp @@ -9,6 +9,9 @@ template > class vector { }; +template +class vector { }; + // RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-LOAD %s // CHECK-LOAD: index-templates.cpp:4:6: FunctionTemplate=f:4:6 Extent=[3:1 - 4:22] // CHECK-LOAD: index-templates.cpp:3:19: TemplateTypeParameter=T:3:19 (Definition) Extent=[3:19 - 3:20] @@ -24,6 +27,9 @@ class vector { // CHECK-LOAD: index-templates.cpp:9:7: ClassTemplate=vector:9:7 (Definition) Extent=[8:1 - 10:2] // CHECK-LOAD: index-templates.cpp:8:19: TemplateTypeParameter=T:8:19 (Definition) Extent=[8:19 - 8:20] // CHECK-LOAD: index-templates.cpp:8:31: TemplateTypeParameter=Alloc:8:31 (Definition) Extent=[8:31 - 8:36] +// CHECK-LOAD: index-templates.cpp:13:7: ClassTemplatePartialSpecialization=vector:13:7 (Definition) Extent=[12:1 - 13:21] +// CHECK-LOAD: index-templates.cpp:12:19: TemplateTypeParameter=T:12:19 (Definition) Extent=[12:19 - 12:20] +// FIXME: Need the template type parameter here // RUN: c-index-test -test-load-source-usrs all %s | FileCheck -check-prefix=CHECK-USRS %s // CHECK-USRS: index-templates.cpp c:@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22t0.0# Extent=[3:1 - 4:22] @@ -34,3 +40,5 @@ class vector { // CHECK-USRS: index-templates.cpp c:@CT>1#T@allocator Extent=[6:1 - 6:37] // CHECK-USRS: index-templates.cpp c:index-templates.cpp@171 Extent=[6:19 - 6:20] // CHECK-USRS: index-templates.cpp c:@CT>2#T#T@vector Extent=[8:1 - 10:2] +// CHECK-USRS: index-templates.cpp c:index-templates.cpp@264@CP>1#T@vector Extent=[12:1 - 13:21] +// CHECK-USRS: index-templates.cpp c:index-templates.cpp@282 Extent=[12:19 - 12:20] diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 919962cfde..ae53c16be0 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -290,6 +290,8 @@ public: bool VisitTranslationUnitDecl(TranslationUnitDecl *D); bool VisitTypedefDecl(TypedefDecl *D); bool VisitTagDecl(TagDecl *D); + bool VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D); bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); bool VisitEnumConstantDecl(EnumConstantDecl *D); bool VisitDeclaratorDecl(DeclaratorDecl *DD); @@ -600,6 +602,22 @@ bool CursorVisitor::VisitTagDecl(TagDecl *D) { return VisitDeclContext(D); } +bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D) { + // FIXME: Visit the "outer" template parameter lists on the TagDecl + // before visiting these template parameters. + if (VisitTemplateParameters(D->getTemplateParameters())) + return true; + + // Visit the partial specialization arguments. + const TemplateArgumentLoc *TemplateArgs = D->getTemplateArgsAsWritten(); + for (unsigned I = 0, N = D->getNumTemplateArgsAsWritten(); I != N; ++I) + if (VisitTemplateArgumentLoc(TemplateArgs[I])) + return true; + + return VisitCXXRecordDecl(D); +} + bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { // FIXME: Visit default argument return false; @@ -2144,6 +2162,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("FunctionTemplate"); case CXCursor_ClassTemplate: return createCXString("ClassTemplate"); + case CXCursor_ClassTemplatePartialSpecialization: + return createCXString("ClassTemplatePartialSpecialization"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index b397f1e0d4..6705076c9f 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -366,21 +366,33 @@ void USRGenerator::VisitTagDecl(TagDecl *D) { D = D->getCanonicalDecl(); VisitDeclContext(D->getDeclContext()); - bool IsTemplate = false; - if (CXXRecordDecl *CXXRecord = dyn_cast(D)) + bool AlreadyStarted = false; + if (CXXRecordDecl *CXXRecord = dyn_cast(D)) { if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { - IsTemplate = true; + AlreadyStarted = true; switch (D->getTagKind()) { - case TTK_Struct: Out << "@ST"; break; - case TTK_Class: Out << "@CT"; break; - case TTK_Union: Out << "@UT"; break; - case TTK_Enum: llvm_unreachable("enum template"); + case TTK_Struct: Out << "@ST"; break; + case TTK_Class: Out << "@CT"; break; + case TTK_Union: Out << "@UT"; break; + case TTK_Enum: llvm_unreachable("enum template"); break; } VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); + } else if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast(CXXRecord)) { + AlreadyStarted = true; + + switch (D->getTagKind()) { + case TTK_Struct: Out << "@SP"; break; + case TTK_Class: Out << "@CP"; break; + case TTK_Union: Out << "@UP"; break; + case TTK_Enum: llvm_unreachable("enum partial specialization"); break; + } + VisitTemplateParameterList(PartialSpec->getTemplateParameters()); } + } - if (!IsTemplate) { + if (!AlreadyStarted) { switch (D->getTagKind()) { case TTK_Struct: Out << "@S"; break; case TTK_Class: Out << "@C"; break; diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 283c388157..691ccd5f32 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -65,6 +65,8 @@ static CXCursorKind GetCursorKind(Decl *D) { case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter; case Decl::FunctionTemplate: return CXCursor_FunctionTemplate; case Decl::ClassTemplate: return CXCursor_ClassTemplate; + case Decl::ClassTemplatePartialSpecialization: + return CXCursor_ClassTemplatePartialSpecialization; default: if (TagDecl *TD = dyn_cast(D)) { -- 2.50.1