]> granicus.if.org Git - clang/commitdiff
libclang indexing support for C++ constructors, destructors, and
authorDouglas Gregor <dgregor@apple.com>
Tue, 31 Aug 2010 14:41:23 +0000 (14:41 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 31 Aug 2010 14:41:23 +0000 (14:41 +0000)
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
test/Index/load-classes.cpp [new file with mode: 0644]
tools/libclang/CIndex.cpp
tools/libclang/CXCursor.cpp

index 3f0dabf1c5db72f8112bc27c573f67bc220c6800..e3d10f3fcd6e56233b0018f911298518c53a0759 100644 (file)
@@ -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 (file)
index 0000000..478bf61
--- /dev/null
@@ -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]
index 2361f421a4b92a4514d697c919b97f5e35e15817..fc665926f2895582c62ce8ac4e5ead5f7e98915c 100644 (file)
@@ -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<FunctionTypeLoc>(&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<CXXConversionDecl>(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");
index 40f91a7383909294c45bdbc282b2c32d3d4f6cbe..029b3d237dcc7d508b819ecf6b0b1492a4585499 100644 (file)
@@ -51,6 +51,9 @@ static CXCursorKind GetCursorKind(Decl *D) {
       return cast<ObjCMethodDecl>(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;