From 01829d3afafdfd355cbe93537bc408aeeed964c6 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 31 Aug 2010 14:41:23 +0000 Subject: [PATCH] libclang indexing support for C++ constructors, destructors, and conversion functions. This introduces new cursor kinds for these three C++ entities, and reworks visitation of function declarations so that we get type-source information for the names. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112600 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 9 ++++- test/Index/load-classes.cpp | 22 +++++++++++ tools/libclang/CIndex.cpp | 78 +++++++++++++++++++++++++++++++++---- tools/libclang/CXCursor.cpp | 3 ++ 4 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 test/Index/load-classes.cpp diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 3f0dabf1c5..e3d10f3fcd 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -976,9 +976,14 @@ enum CXCursorKind { CXCursor_Namespace = 22, /** \brief A linkage specification, e.g. 'extern "C"'. */ CXCursor_LinkageSpec = 23, - + /** \brief A C++ constructor. */ + CXCursor_Constructor = 24, + /** \brief A C++ destructor. */ + CXCursor_Destructor = 25, + /** \brief A C++ conversion function. */ + CXCursor_ConversionFunction = 26, CXCursor_FirstDecl = CXCursor_UnexposedDecl, - CXCursor_LastDecl = CXCursor_LinkageSpec, + CXCursor_LastDecl = CXCursor_ConversionFunction, /* References */ CXCursor_FirstRef = 40, /* Decl references */ diff --git a/test/Index/load-classes.cpp b/test/Index/load-classes.cpp new file mode 100644 index 0000000000..478bf61a44 --- /dev/null +++ b/test/Index/load-classes.cpp @@ -0,0 +1,22 @@ +// Test is line- and column-sensitive; see below. + +struct X { + X(int value); + X(const X& x); + ~X(); + operator X*(); +}; + +// RUN: c-index-test -test-load-source all %s | FileCheck %s +// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 8:2] +// CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 Extent=[4:3 - 4:15] +// FIXME: missing TypeRef in the constructor name +// CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14] +// CHECK: load-classes.cpp:5:3: CXXConstructor=X:5:3 Extent=[5:3 - 5:16] +// FIXME: missing TypeRef in the constructor name +// CHECK: load-classes.cpp:5:14: ParmDecl=x:5:14 (Definition) Extent=[5:11 - 5:15] +// CHECK: load-classes.cpp:5:11: TypeRef=struct X:3:8 Extent=[5:11 - 5:12] +// CHECK: load-classes.cpp:6:3: CXXDestructor=~X:6:3 Extent=[6:3 - 6:7] +// FIXME: missing TypeRef in the destructor name +// CHECK: load-classes.cpp:7:3: CXXConversion=operator struct X *:7:3 Extent=[7:3 - 7:16] +// CHECK: load-classes.cpp:7:12: TypeRef=struct X:3:8 Extent=[7:12 - 7:13] diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 2361f421a4..fc665926f2 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -312,8 +312,11 @@ public: bool VisitLinkageSpecDecl(LinkageSpecDecl *D); bool VisitNamespaceDecl(NamespaceDecl *D); + // Name visitor + bool VisitDeclarationNameInfo(DeclarationNameInfo Name); + // Type visitors - // FIXME: QualifiedTypeLoc doesn't provide any location information + bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL); bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL); bool VisitTypedefTypeLoc(TypedefTypeLoc TL); bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL); @@ -327,7 +330,7 @@ public: bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL); bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL); bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL); - bool VisitFunctionTypeLoc(FunctionTypeLoc TL); + bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false); bool VisitArrayTypeLoc(ArrayTypeLoc TL); // FIXME: Implement for TemplateSpecializationTypeLoc // FIXME: Implement visitors here when the unimplemented TypeLocs get @@ -605,9 +608,34 @@ bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) { } bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { - if (VisitDeclaratorDecl(ND)) - return true; - + if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) { + // Visit the function declaration's syntactic components in the order + // written. This requires a bit of work. + TypeLoc TL = TSInfo->getTypeLoc(); + FunctionTypeLoc *FTL = dyn_cast(&TL); + + // If we have a function declared directly (without the use of a typedef), + // visit just the return type. Otherwise, just visit the function's type + // now. + if ((FTL && !isa(ND) && Visit(FTL->getResultLoc())) || + (!FTL && Visit(TL))) + return true; + + // FIXME: Visit the nested-name-specifier, if present. + + // Visit the declaration name. + if (VisitDeclarationNameInfo(ND->getNameInfo())) + return true; + + // FIXME: Visit explicitly-specified template arguments! + + // Visit the function parameters, if we have a function type. + if (FTL && VisitFunctionTypeLoc(*FTL, true)) + return true; + + // FIXME: Attributes? + } + if (ND->isThisDeclarationADefinition() && Visit(MakeCXCursor(ND->getBody(), StmtParent, TU))) return true; @@ -786,10 +814,39 @@ bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) { return VisitDeclContext(D); } +bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { + switch (Name.getName().getNameKind()) { + case clang::DeclarationName::Identifier: + case clang::DeclarationName::CXXLiteralOperatorName: + case clang::DeclarationName::CXXOperatorName: + case clang::DeclarationName::CXXUsingDirective: + return false; + + case clang::DeclarationName::CXXConstructorName: + case clang::DeclarationName::CXXDestructorName: + case clang::DeclarationName::CXXConversionFunctionName: + if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo()) + return Visit(TSInfo->getTypeLoc()); + return false; + + case clang::DeclarationName::ObjCZeroArgSelector: + case clang::DeclarationName::ObjCOneArgSelector: + case clang::DeclarationName::ObjCMultiArgSelector: + // FIXME: Per-identifier location info? + return false; + } + + return false; +} + bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) { return VisitDeclContext(D); } +bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { + return Visit(TL.getUnqualifiedLoc()); +} + bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { ASTContext &Context = TU->getASTContext(); @@ -905,8 +962,9 @@ bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { return Visit(TL.getPointeeLoc()); } -bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - if (Visit(TL.getResultLoc())) +bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL, + bool SkipResultType) { + if (!SkipResultType && Visit(TL.getResultLoc())) return true; for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I) @@ -1973,6 +2031,12 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("LinkageSpec"); case CXCursor_CXXBaseSpecifier: return createCXString("C++ base class specifier"); + case CXCursor_Constructor: + return createCXString("CXXConstructor"); + case CXCursor_Destructor: + return createCXString("CXXDestructor"); + case CXCursor_ConversionFunction: + return createCXString("CXXConversion"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 40f91a7383..029b3d237d 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -51,6 +51,9 @@ static CXCursorKind GetCursorKind(Decl *D) { return cast(D)->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl; case Decl::CXXMethod: return CXCursor_CXXMethod; + case Decl::CXXConstructor: return CXCursor_Constructor; + case Decl::CXXDestructor: return CXCursor_Destructor; + case Decl::CXXConversion: return CXCursor_ConversionFunction; case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl; case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl; case Decl::ParmVar: return CXCursor_ParmDecl; -- 2.40.0