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
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 2361f42..fc66592 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -312,8 +312,11 @@
   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 @@
   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::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 @@
   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 @@
   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 @@
     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");