Eliminate cursor kinds used to express definitions. Instead, provide
CIndex functions that (1) map from a reference or declaration to the
corresponding definition, if available, and (2) determine whether a
given declaration cursor is also a definition. This eliminates a lot
of duplication in the cursor kinds, and maps more closely to the Clang
ASTs.

This is another API + ABI breaker with no deprecation. Yay, progress.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93893 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 355b80d..e6b4baf 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -365,13 +365,11 @@
 }
 
 void CDeclVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
-  if (ND->getBody()) {
-    Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDefn
-         : CXCursor_ObjCClassMethodDefn, ND);
+  Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl
+       : CXCursor_ObjCClassMethodDecl, ND);
+
+  if (ND->getBody())
     VisitDeclContext(dyn_cast<DeclContext>(ND));
-  } else
-    Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl
-         : CXCursor_ObjCClassMethodDecl, ND);
 }
 
 void CDeclVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *ND) {
@@ -772,7 +770,6 @@
   case CXCursor_UnionDecl: return "UnionDecl";
   case CXCursor_ClassDecl: return "ClassDecl";
   case CXCursor_FieldDecl: return "FieldDecl";
-  case CXCursor_FunctionDefn: return "FunctionDefn";
   case CXCursor_VarDecl: return "VarDecl";
   case CXCursor_ParmDecl: return "ParmDecl";
   case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl";
@@ -783,10 +780,8 @@
   case CXCursor_ObjCIvarRef: return "ObjCIvarRef";
   case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
   case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
-  case CXCursor_ObjCInstanceMethodDefn: return "ObjCInstanceMethodDefn";
-  case CXCursor_ObjCCategoryDefn: return "ObjCCategoryDefn";
-  case CXCursor_ObjCClassMethodDefn: return "ObjCClassMethodDefn";
-  case CXCursor_ObjCClassDefn: return "ObjCClassDefn";
+  case CXCursor_ObjCImplementationDecl: return "ObjCImplementationDecl";
+  case CXCursor_ObjCCategoryImplDecl: return "ObjCCategoryImplDecl";
   case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
   case CXCursor_ObjCProtocolRef: return "ObjCProtocolRef";
   case CXCursor_ObjCClassRef: return "ObjCClassRef";
@@ -878,16 +873,12 @@
   return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
 }
 
-unsigned clang_isDefinition(enum CXCursorKind K) {
-  return K >= CXCursor_FirstDefn && K <= CXCursor_LastDefn;
-}
-
 CXCursorKind clang_getCursorKind(CXCursor C) {
   return C.kind;
 }
 
 CXDecl clang_getCursorDecl(CXCursor C) {
-  if (clang_isDeclaration(C.kind) || clang_isDefinition(C.kind))
+  if (clang_isDeclaration(C.kind))
     return getCursorDecl(C);
 
   if (clang_isReference(C.kind)) {
@@ -1008,7 +999,7 @@
 }
 
 CXCursor clang_getCursorReferenced(CXCursor C) {
-  if (clang_isDeclaration(C.kind) || clang_isDefinition(C.kind))
+  if (clang_isDeclaration(C.kind))
     return C;
   
   if (!clang_isReference(C.kind))
@@ -1046,6 +1037,238 @@
   return clang_getNullCursor();
 }
 
+CXCursor clang_getCursorDefinition(CXCursor C) {
+  bool WasReference = false;
+  if (clang_isReference(C.kind)) {
+    C = clang_getCursorReferenced(C);
+    WasReference = true;
+  }
+
+  if (!clang_isDeclaration(C.kind))
+    return clang_getNullCursor();
+
+  Decl *D = getCursorDecl(C);
+  if (!D)
+    return clang_getNullCursor();
+  
+  switch (D->getKind()) {
+  // Declaration kinds that don't really separate the notions of
+  // declaration and definition.
+  case Decl::Namespace:
+  case Decl::Typedef:
+  case Decl::TemplateTypeParm:
+  case Decl::EnumConstant:
+  case Decl::Field:
+  case Decl::ObjCIvar:
+  case Decl::ObjCAtDefsField:
+  case Decl::ImplicitParam:
+  case Decl::ParmVar:
+  case Decl::NonTypeTemplateParm:
+  case Decl::TemplateTemplateParm:
+  case Decl::ObjCCategoryImpl:
+  case Decl::ObjCImplementation:
+  case Decl::LinkageSpec:
+  case Decl::ObjCPropertyImpl:
+  case Decl::FileScopeAsm:
+  case Decl::StaticAssert:
+  case Decl::Block:
+    return C;
+
+  // Declaration kinds that don't make any sense here, but are
+  // nonetheless harmless.
+  case Decl::TranslationUnit:
+  case Decl::Template:
+  case Decl::ObjCContainer:
+    break;
+
+  // Declaration kinds for which the definition is not resolvable.
+  case Decl::UnresolvedUsingTypename:
+  case Decl::UnresolvedUsingValue:
+    break;
+
+  case Decl::UsingDirective:
+    return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace());
+
+  case Decl::NamespaceAlias:
+    return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace());
+
+  case Decl::Enum:
+  case Decl::Record:
+  case Decl::CXXRecord:
+  case Decl::ClassTemplateSpecialization:
+  case Decl::ClassTemplatePartialSpecialization:
+    if (TagDecl *Def = cast<TagDecl>(D)->getDefinition(D->getASTContext()))
+      return MakeCXCursor(Def);
+    return clang_getNullCursor();
+
+  case Decl::Function:
+  case Decl::CXXMethod:
+  case Decl::CXXConstructor:
+  case Decl::CXXDestructor:
+  case Decl::CXXConversion: {
+    const FunctionDecl *Def = 0;
+    if (cast<FunctionDecl>(D)->getBody(Def))
+      return MakeCXCursor(const_cast<FunctionDecl *>(Def));
+    return clang_getNullCursor();
+  }
+
+  case Decl::Var: {
+    VarDecl *Var = cast<VarDecl>(D);
+
+    // Variables with initializers have definitions.
+    const VarDecl *Def = 0;
+    if (Var->getDefinition(Def))
+      return MakeCXCursor(const_cast<VarDecl *>(Def));
+
+    // extern and private_extern variables are not definitions.
+    if (Var->hasExternalStorage())
+      return clang_getNullCursor();
+
+    // In-line static data members do not have definitions.
+    if (Var->isStaticDataMember() && !Var->isOutOfLine())
+      return clang_getNullCursor();
+
+    // All other variables are themselves definitions.
+    return C;
+  }
+   
+  case Decl::FunctionTemplate: {
+    const FunctionDecl *Def = 0;
+    if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
+      return MakeCXCursor(Def->getDescribedFunctionTemplate());
+    return clang_getNullCursor();
+  }
+   
+  case Decl::ClassTemplate: {
+    if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
+                                          ->getDefinition(D->getASTContext()))
+      return MakeCXCursor(
+                         cast<CXXRecordDecl>(Def)->getDescribedClassTemplate());
+    return clang_getNullCursor();
+  }
+
+  case Decl::Using: {
+    UsingDecl *Using = cast<UsingDecl>(D);
+    CXCursor Def = clang_getNullCursor();
+    for (UsingDecl::shadow_iterator S = Using->shadow_begin(), 
+                                 SEnd = Using->shadow_end(); 
+         S != SEnd; ++S) {
+      if (Def != clang_getNullCursor()) {
+        // FIXME: We have no way to return multiple results.
+        return clang_getNullCursor();
+      }
+
+      Def = clang_getCursorDefinition(MakeCXCursor((*S)->getTargetDecl()));
+    }
+
+    return Def;
+  }
+
+  case Decl::UsingShadow:
+    return clang_getCursorDefinition(
+                       MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl()));
+
+  case Decl::ObjCMethod: {
+    ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
+    if (Method->isThisDeclarationADefinition())
+      return C;
+
+    // Dig out the method definition in the associated
+    // @implementation, if we have it.
+    // FIXME: The ASTs should make finding the definition easier.
+    if (ObjCInterfaceDecl *Class
+                       = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
+      if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
+        if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(),
+                                                  Method->isInstanceMethod()))
+          if (Def->isThisDeclarationADefinition())
+            return MakeCXCursor(Def);
+
+    return clang_getNullCursor();
+  }
+
+  case Decl::ObjCCategory:
+    if (ObjCCategoryImplDecl *Impl
+                               = cast<ObjCCategoryDecl>(D)->getImplementation())
+      return MakeCXCursor(Impl);
+    return clang_getNullCursor();
+
+  case Decl::ObjCProtocol:
+    if (!cast<ObjCProtocolDecl>(D)->isForwardDecl())
+      return C;
+    return clang_getNullCursor();
+
+  case Decl::ObjCInterface:
+    // There are two notions of a "definition" for an Objective-C
+    // class: the interface and its implementation. When we resolved a
+    // reference to an Objective-C class, produce the @interface as
+    // the definition; when we were provided with the interface,
+    // produce the @implementation as the definition.
+    if (WasReference) {
+      if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl())
+        return C;
+    } else if (ObjCImplementationDecl *Impl
+                              = cast<ObjCInterfaceDecl>(D)->getImplementation())
+      return MakeCXCursor(Impl);
+    return clang_getNullCursor();
+  
+  case Decl::ObjCProperty:
+    // FIXME: We don't really know where to find the
+    // ObjCPropertyImplDecls that implement this property.
+    return clang_getNullCursor();
+
+  case Decl::ObjCCompatibleAlias:
+    if (ObjCInterfaceDecl *Class
+          = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
+      if (!Class->isForwardDecl())
+        return MakeCXCursor(Class);
+    
+    return clang_getNullCursor();
+
+  case Decl::ObjCForwardProtocol: {
+    ObjCForwardProtocolDecl *Forward = cast<ObjCForwardProtocolDecl>(D);
+    if (Forward->protocol_size() == 1)
+      return clang_getCursorDefinition(
+                                     MakeCXCursor(*Forward->protocol_begin()));
+
+    // FIXME: Cannot return multiple definitions.
+    return clang_getNullCursor();
+  }
+
+  case Decl::ObjCClass: {
+    ObjCClassDecl *Class = cast<ObjCClassDecl>(D);
+    if (Class->size() == 1) {
+      ObjCInterfaceDecl *IFace = Class->begin()->getInterface();
+      if (!IFace->isForwardDecl())
+        return MakeCXCursor(IFace);
+      return clang_getNullCursor();
+    }
+
+    // FIXME: Cannot return multiple definitions.
+    return clang_getNullCursor();
+  }
+
+  case Decl::Friend:
+    if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
+      return clang_getCursorDefinition(MakeCXCursor(Friend));
+    return clang_getNullCursor();
+
+  case Decl::FriendTemplate:
+    if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
+      return clang_getCursorDefinition(MakeCXCursor(Friend));
+    return clang_getNullCursor();
+  }
+
+  return clang_getNullCursor();
+}
+
+unsigned clang_isCursorDefinition(CXCursor C) {
+  if (!clang_isDeclaration(C.kind))
+    return 0;
+
+  return clang_getCursorDefinition(C) == C;
+}
+
 void clang_getDefinitionSpellingAndExtent(CXCursor C,
                                           const char **startBuf,
                                           const char **endBuf,