From 1fbaeb196b5ddeb9b2b19ae66a16c89ad93746c4 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 31 Aug 2010 19:02:00 +0000 Subject: [PATCH] Add a libclang cursor kind, visitation support and USR support for C++ class templates. llvm-svn: 112627 --- clang/include/clang-c/Index.h | 5 +++- clang/test/Index/index-templates.cpp | 14 ++++++++++++ clang/tools/libclang/CIndex.cpp | 12 ++++++++++ clang/tools/libclang/CIndexUSRs.cpp | 34 +++++++++++++++++++++++----- clang/tools/libclang/CXCursor.cpp | 2 ++ 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index cc00f1835bac..7131853d524d 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -990,8 +990,11 @@ enum CXCursorKind { CXCursor_TemplateTemplateParameter = 29, /** \brief A C++ function template. */ CXCursor_FunctionTemplate = 30, + /** \brief A C++ class template. */ + CXCursor_ClassTemplate = 31, + CXCursor_FirstDecl = CXCursor_UnexposedDecl, - CXCursor_LastDecl = CXCursor_FunctionTemplate, + CXCursor_LastDecl = CXCursor_ClassTemplate, /* References */ CXCursor_FirstRef = 40, /* Decl references */ diff --git a/clang/test/Index/index-templates.cpp b/clang/test/Index/index-templates.cpp index 90e0c352bc09..777c66e1a5db 100644 --- a/clang/test/Index/index-templates.cpp +++ b/clang/test/Index/index-templates.cpp @@ -3,6 +3,12 @@ template class X> void f(X x); +template class allocator; + +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] @@ -13,6 +19,11 @@ void f(X x); // FIXME: Need the template declaration here. // FIXME: Need the template type parameter here // CHECK-LOAD: index-templates.cpp:4:13: DeclRefExpr=Value:3:24 Extent=[4:13 - 4:18] +// CHECK-LOAD: index-templates.cpp:6:28: ClassTemplate=allocator:6:28 Extent=[6:1 - 6:37] +// CHECK-LOAD: index-templates.cpp:6:19: TemplateTypeParameter=T:6:19 (Definition) Extent=[6:19 - 6:20] +// 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] // 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] @@ -20,3 +31,6 @@ void f(X x); // CHECK-USRS: index-templates.cpp c:index-templates.cpp@82 Extent=[3:22 - 3:29] // CHECK-USRS: index-templates.cpp c:index-templates.cpp@91 Extent=[3:31 - 3:67] // CHECK-USRS: index-templates.cpp c:index-templates.cpp@136@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22t0.0#@x Extent=[4:8 - 4:21] +// 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] diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 6629f5c0acf0..919962cfdeb5 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -297,6 +297,7 @@ public: bool VisitFieldDecl(FieldDecl *D); bool VisitVarDecl(VarDecl *); bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D); + bool VisitClassTemplateDecl(ClassTemplateDecl *D); bool VisitObjCMethodDecl(ObjCMethodDecl *ND); bool VisitObjCContainerDecl(ObjCContainerDecl *D); bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND); @@ -683,6 +684,15 @@ bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { return VisitFunctionDecl(D->getTemplatedDecl()); } +bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) { + // FIXME: Visit the "outer" template parameter lists on the TagDecl + // before visiting these template parameters. + if (VisitTemplateParameters(D->getTemplateParameters())) + return true; + + return VisitCXXRecordDecl(D->getTemplatedDecl()); +} + bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) { if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo()) if (Visit(TSInfo->getTypeLoc())) @@ -2132,6 +2142,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("TemplateTemplateParameter"); case CXCursor_FunctionTemplate: return createCXString("FunctionTemplate"); + case CXCursor_ClassTemplate: + return createCXString("ClassTemplate"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/clang/tools/libclang/CIndexUSRs.cpp b/clang/tools/libclang/CIndexUSRs.cpp index 6dfe9df4dd77..b397f1e0d42f 100644 --- a/clang/tools/libclang/CIndexUSRs.cpp +++ b/clang/tools/libclang/CIndexUSRs.cpp @@ -66,6 +66,7 @@ public: void VisitNamedDecl(NamedDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); + void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitObjCClassDecl(ObjCClassDecl *CD); void VisitObjCContainerDecl(ObjCContainerDecl *CD); void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P); @@ -252,6 +253,11 @@ void USRGenerator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { VisitFunctionDecl(D->getTemplatedDecl()); } +void USRGenerator::VisitClassTemplateDecl(ClassTemplateDecl *D) { + VisitTagDecl(D->getTemplatedDecl()); +} + + void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) { Decl *container = cast(D->getDeclContext()); @@ -360,13 +366,29 @@ void USRGenerator::VisitTagDecl(TagDecl *D) { D = D->getCanonicalDecl(); VisitDeclContext(D->getDeclContext()); - switch (D->getTagKind()) { - case TTK_Struct: Out << "@S"; break; - case TTK_Class: Out << "@C"; break; - case TTK_Union: Out << "@U"; break; - case TTK_Enum: Out << "@E"; break; + bool IsTemplate = false; + if (CXXRecordDecl *CXXRecord = dyn_cast(D)) + if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { + IsTemplate = 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"); + } + VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); + } + + if (!IsTemplate) { + switch (D->getTagKind()) { + case TTK_Struct: Out << "@S"; break; + case TTK_Class: Out << "@C"; break; + case TTK_Union: Out << "@U"; break; + case TTK_Enum: Out << "@E"; break; + } } - + Out << '@'; Out.flush(); assert(Buf.size() > 0); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 86cf83d75e59..283c38815740 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -64,6 +64,8 @@ static CXCursorKind GetCursorKind(Decl *D) { case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter; case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter; case Decl::FunctionTemplate: return CXCursor_FunctionTemplate; + case Decl::ClassTemplate: return CXCursor_ClassTemplate; + default: if (TagDecl *TD = dyn_cast(D)) { switch (TD->getTagKind()) {