[libclang] Separate the underlying indexing functionality of libclang and introduce...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 12 Feb 2016 23:10:59 +0000 (23:10 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 12 Feb 2016 23:10:59 +0000 (23:10 +0000)
It is a general goodness for libclang itself to mostly be a wrapper of functionality provided by the libraries.

llvm-svn: 260760

16 files changed:
clang/include/clang/Index/IndexDataConsumer.h [new file with mode: 0644]
clang/include/clang/Index/IndexSymbol.h [new file with mode: 0644]
clang/include/clang/Index/IndexingAction.h [new file with mode: 0644]
clang/lib/Index/CMakeLists.txt
clang/lib/Index/IndexBody.cpp [new file with mode: 0644]
clang/lib/Index/IndexDecl.cpp [moved from clang/tools/libclang/IndexDecl.cpp with 50% similarity]
clang/lib/Index/IndexSymbol.cpp [new file with mode: 0644]
clang/lib/Index/IndexTypeSourceInfo.cpp [moved from clang/tools/libclang/IndexTypeSourceInfo.cpp with 52% similarity]
clang/lib/Index/IndexingAction.cpp [new file with mode: 0644]
clang/lib/Index/IndexingContext.cpp [new file with mode: 0644]
clang/lib/Index/IndexingContext.h [new file with mode: 0644]
clang/tools/libclang/CMakeLists.txt
clang/tools/libclang/CXIndexDataConsumer.cpp [moved from clang/tools/libclang/IndexingContext.cpp with 70% similarity]
clang/tools/libclang/CXIndexDataConsumer.h [moved from clang/tools/libclang/IndexingContext.h with 91% similarity]
clang/tools/libclang/IndexBody.cpp [deleted file]
clang/tools/libclang/Indexing.cpp

diff --git a/clang/include/clang/Index/IndexDataConsumer.h b/clang/include/clang/Index/IndexDataConsumer.h
new file mode 100644 (file)
index 0000000..cb00345
--- /dev/null
@@ -0,0 +1,61 @@
+//===--- IndexDataConsumer.h - Abstract index data consumer ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_INDEXDATACONSUMER_H
+#define LLVM_CLANG_INDEX_INDEXDATACONSUMER_H
+
+#include "clang/Index/IndexSymbol.h"
+
+namespace clang {
+  class DeclContext;
+  class Expr;
+  class FileID;
+  class IdentifierInfo;
+  class ImportDecl;
+  class MacroInfo;
+
+namespace index {
+
+class IndexDataConsumer {
+public:
+  struct ASTNodeInfo {
+    const Expr *OrigE;
+    const Decl *OrigD;
+    const Decl *Parent;
+    const DeclContext *ContainerDC;
+  };
+
+  virtual ~IndexDataConsumer() {}
+
+  /// \returns true to continue indexing, or false to abort.
+  virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
+                                   ArrayRef<SymbolRelation> Relations,
+                                   FileID FID, unsigned Offset,
+                                   ASTNodeInfo ASTNode);
+
+  /// \returns true to continue indexing, or false to abort.
+  virtual bool handleMacroOccurence(const IdentifierInfo *Name,
+                                    const MacroInfo *MI, SymbolRoleSet Roles,
+                                    FileID FID, unsigned Offset);
+
+  /// \returns true to continue indexing, or false to abort.
+  virtual bool handleModuleOccurence(const ImportDecl *ImportD,
+                                     SymbolRoleSet Roles,
+                                     FileID FID, unsigned Offset);
+
+  virtual void finish() {}
+
+private:
+  virtual void _anchor();
+};
+
+} // namespace index
+} // namespace clang
+
+#endif
diff --git a/clang/include/clang/Index/IndexSymbol.h b/clang/include/clang/Index/IndexSymbol.h
new file mode 100644 (file)
index 0000000..0849241
--- /dev/null
@@ -0,0 +1,112 @@
+//===--- IndexSymbol.h - Types and functions for indexing symbols ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_INDEXSYMBOL_H
+#define LLVM_CLANG_INDEX_INDEXSYMBOL_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+  class Decl;
+
+namespace index {
+
+enum class SymbolKind : uint8_t {
+  Unknown,
+
+  Module,
+  Macro,
+
+  Enum,
+  Struct,
+  Union,
+  Typedef,
+
+  Function,
+  Variable,
+  Field,
+  EnumConstant,
+
+  ObjCClass,
+  ObjCProtocol,
+  ObjCCategory,
+
+  ObjCInstanceMethod,
+  ObjCClassMethod,
+  ObjCProperty,
+  ObjCIvar,
+
+  CXXClass,
+  CXXNamespace,
+  CXXNamespaceAlias,
+  CXXStaticVariable,
+  CXXStaticMethod,
+  CXXInstanceMethod,
+  CXXConstructor,
+  CXXDestructor,
+  CXXConversionFunction,
+  CXXTypeAlias,
+  CXXInterface,
+};
+
+enum class SymbolLanguage {
+  C,
+  ObjC,
+  CXX,
+};
+
+enum class SymbolCXXTemplateKind {
+  NonTemplate,
+  Template,
+  TemplatePartialSpecialization,
+  TemplateSpecialization,
+};
+
+/// Set of roles that are attributed to symbol occurrences.
+enum class SymbolRole : uint16_t {
+  Declaration = 1 << 0,
+  Definition  = 1 << 1,
+  Reference   = 1 << 2,
+  Read        = 1 << 3,
+  Write       = 1 << 4,
+  Call        = 1 << 5,
+  Dynamic     = 1 << 6,
+  AddressOf   = 1 << 7,
+  Implicit    = 1 << 8,
+
+  // Relation roles.
+  RelationChildOf     = 1 << 9,
+  RelationBaseOf      = 1 << 10,
+  RelationOverrideOf  = 1 << 11,
+  RelationReceivedBy  = 1 << 12,
+};
+static const unsigned SymbolRoleBitNum = 13;
+typedef unsigned SymbolRoleSet;
+
+/// Represents a relation to another symbol for a symbol occurrence.
+struct SymbolRelation {
+  SymbolRoleSet Roles;
+  const Decl *RelatedSymbol;
+
+  SymbolRelation(SymbolRoleSet Roles, const Decl *Sym)
+    : Roles(Roles), RelatedSymbol(Sym) {}
+};
+
+struct SymbolInfo {
+  SymbolKind Kind;
+  SymbolCXXTemplateKind TemplateKind;
+  SymbolLanguage Lang;
+};
+
+SymbolInfo getSymbolInfo(const Decl *D);
+
+} // namespace index
+} // namespace clang
+
+#endif
diff --git a/clang/include/clang/Index/IndexingAction.h b/clang/include/clang/Index/IndexingAction.h
new file mode 100644 (file)
index 0000000..dfc363a
--- /dev/null
@@ -0,0 +1,47 @@
+//===--- IndexingAction.h - Frontend index action -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_INDEXINGACTION_H
+#define LLVM_CLANG_INDEX_INDEXINGACTION_H
+
+#include "clang/Basic/LLVM.h"
+#include <memory>
+
+namespace clang {
+  class ASTUnit;
+  class FrontendAction;
+
+namespace index {
+  class IndexDataConsumer;
+
+struct IndexingOptions {
+  enum class SystemSymbolFilterKind {
+    None,
+    DeclarationsOnly,
+    All,
+  };
+
+  SystemSymbolFilterKind SystemSymbolFilter
+    = SystemSymbolFilterKind::DeclarationsOnly;
+  bool IndexFunctionLocals = false;
+};
+
+std::unique_ptr<FrontendAction>
+createIndexingAction(std::unique_ptr<FrontendAction> WrappedAction,
+                     std::shared_ptr<IndexDataConsumer> DataConsumer,
+                     IndexingOptions Opts);
+
+void indexASTUnit(ASTUnit &Unit,
+                  std::shared_ptr<IndexDataConsumer> DataConsumer,
+                  IndexingOptions Opts);
+
+} // namespace index
+} // namespace clang
+
+#endif
index 3869c32..cb2b931 100644 (file)
@@ -5,14 +5,22 @@ set(LLVM_LINK_COMPONENTS
 add_clang_library(clangIndex
   CommentToXML.cpp
   USRGeneration.cpp
+  IndexBody.cpp
+  IndexDecl.cpp
+  IndexingAction.cpp
+  IndexingContext.cpp
+  IndexSymbol.cpp
+  IndexTypeSourceInfo.cpp
 
   ADDITIONAL_HEADERS
+  IndexingContext.h
   SimpleFormatContext.h
 
   LINK_LIBS
   clangAST
   clangBasic
   clangFormat
+  clangFrontend
   clangRewrite
   clangToolingCore
   )
diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp
new file mode 100644 (file)
index 0000000..56fba28
--- /dev/null
@@ -0,0 +1,347 @@
+//===- IndexBody.cpp - Indexing statements --------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IndexingContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+using namespace clang;
+using namespace clang::index;
+
+namespace {
+
+class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
+  IndexingContext &IndexCtx;
+  const NamedDecl *Parent;
+  const DeclContext *ParentDC;
+  SmallVector<Stmt*, 16> StmtStack;
+
+  typedef RecursiveASTVisitor<BodyIndexer> base;
+public:
+  BodyIndexer(IndexingContext &indexCtx,
+              const NamedDecl *Parent, const DeclContext *DC)
+    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
+  
+  bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+  bool TraverseStmt(Stmt *S) {
+    StmtStack.push_back(S);
+    bool ret = base::TraverseStmt(S);
+    StmtStack.pop_back();
+    return ret;
+  }
+
+  bool TraverseTypeLoc(TypeLoc TL) {
+    IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
+    return true;
+  }
+
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
+    return true;
+  }
+
+  SymbolRoleSet getRolesForRef(const Expr *E,
+                               SmallVectorImpl<SymbolRelation> &Relations) {
+    SymbolRoleSet Roles{};
+    assert(!StmtStack.empty() && E == StmtStack.back());
+    if (StmtStack.size() == 1)
+      return Roles;
+    auto It = StmtStack.end()-2;
+    while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
+      if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
+        if (ICE->getCastKind() == CK_LValueToRValue)
+          Roles |= (unsigned)(unsigned)SymbolRole::Read;
+      }
+      if (It == StmtStack.begin())
+        break;
+      --It;
+    }
+    const Stmt *Parent = *It;
+
+    if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
+      if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
+        Roles |= (unsigned)SymbolRole::Write;
+
+    } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
+      if (UO->isIncrementDecrementOp()) {
+        Roles |= (unsigned)SymbolRole::Read;
+        Roles |= (unsigned)SymbolRole::Write;
+      } else if (UO->getOpcode() == UO_AddrOf) {
+        Roles |= (unsigned)SymbolRole::AddressOf;
+      }
+
+    } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
+      if (CA->getLHS()->IgnoreParenCasts() == E) {
+        Roles |= (unsigned)SymbolRole::Read;
+        Roles |= (unsigned)SymbolRole::Write;
+      }
+
+    } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
+      if (CE->getCallee()->IgnoreParenCasts() == E) {
+        Roles |= (unsigned)SymbolRole::Call;
+        if (auto *ME = dyn_cast<MemberExpr>(E)) {
+          if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
+            if (CXXMD->isVirtual() && !ME->hasQualifier()) {
+              Roles |= (unsigned)SymbolRole::Dynamic;
+              auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
+              if (!BaseTy.isNull())
+                if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
+                  Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
+                                         CXXRD);
+            }
+        }
+      } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
+        if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
+          OverloadedOperatorKind Op = CXXOp->getOperator();
+          if (Op == OO_Equal) {
+            Roles |= (unsigned)SymbolRole::Write;
+          } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
+                     Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
+                     Op == OO_PlusPlus || Op == OO_MinusMinus) {
+            Roles |= (unsigned)SymbolRole::Read;
+            Roles |= (unsigned)SymbolRole::Write;
+          } else if (Op == OO_Amp) {
+            Roles |= (unsigned)SymbolRole::AddressOf;
+          }
+        }
+      }
+    }
+
+    return Roles;
+  }
+
+  bool VisitDeclRefExpr(DeclRefExpr *E) {
+    SmallVector<SymbolRelation, 4> Relations;
+    SymbolRoleSet Roles = getRolesForRef(E, Relations);
+    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
+                                    Parent, ParentDC, Roles, Relations, E);
+  }
+
+  bool VisitMemberExpr(MemberExpr *E) {
+    SourceLocation Loc = E->getMemberLoc();
+    if (Loc.isInvalid())
+      Loc = E->getLocStart();
+    SmallVector<SymbolRelation, 4> Relations;
+    SymbolRoleSet Roles = getRolesForRef(E, Relations);
+    return IndexCtx.handleReference(E->getMemberDecl(), Loc,
+                                    Parent, ParentDC, Roles, Relations, E);
+  }
+
+  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+    for (DesignatedInitExpr::reverse_designators_iterator
+           D = E->designators_rbegin(), DEnd = E->designators_rend();
+           D != DEnd; ++D) {
+      if (D->isFieldDesignator())
+        return IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
+                                        Parent, ParentDC, SymbolRoleSet(),
+                                        {}, E);
+    }
+    return true;
+  }
+
+  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+    SmallVector<SymbolRelation, 4> Relations;
+    SymbolRoleSet Roles = getRolesForRef(E, Relations);
+    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
+                                    Parent, ParentDC, Roles, Relations, E);
+  }
+
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+    auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
+      if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
+        return false;
+      if (auto *RecE = dyn_cast<ObjCMessageExpr>(
+              MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
+        if (RecE->getMethodFamily() == OMF_alloc)
+          return false;
+      }
+      return true;
+    };
+
+    if (ObjCMethodDecl *MD = E->getMethodDecl()) {
+      SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
+      if (E->isImplicit())
+        Roles |= (unsigned)SymbolRole::Implicit;
+
+      SmallVector<SymbolRelation, 2> Relations;
+      if (isDynamic(E)) {
+        Roles |= (unsigned)SymbolRole::Dynamic;
+        if (auto *RecD = E->getReceiverInterface())
+          Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
+      }
+
+      return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
+                                      Parent, ParentDC, Roles, Relations, E);
+    }
+    return true;
+  }
+
+  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+    if (E->isExplicitProperty())
+      return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
+                                      Parent, ParentDC, SymbolRoleSet(), {}, E);
+
+    // No need to do a handleReference for the objc method, because there will
+    // be a message expr as part of PseudoObjectExpr.
+    return true;
+  }
+
+  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+    return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
+                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
+  }
+
+  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+    return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
+                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
+  }
+
+  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
+    if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
+      SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
+      Roles |= (unsigned)SymbolRole::Implicit;
+      return IndexCtx.handleReference(MD, E->getLocStart(),
+                                      Parent, ParentDC, Roles, {}, E);
+    }
+    return true;
+  }
+  
+  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
+    if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
+      SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
+      Roles |= (unsigned)SymbolRole::Implicit;
+      return IndexCtx.handleReference(MD, E->getLocStart(),
+                                      Parent, ParentDC, Roles, {}, E);
+    }
+    return true;
+  }
+
+  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
+    if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
+      SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
+      Roles |= (unsigned)SymbolRole::Implicit;
+      return IndexCtx.handleReference(MD, E->getLocStart(),
+                                      Parent, ParentDC, Roles, {}, E);
+    }
+    return true;
+  }
+
+  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+    return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
+                                    Parent, ParentDC, (unsigned)SymbolRole::Call, {}, E);
+  }
+
+  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
+                                   DataRecursionQueue *Q = nullptr) {
+    if (E->getOperatorLoc().isInvalid())
+      return true; // implicit.
+    return base::TraverseCXXOperatorCallExpr(E);
+  }
+
+  bool VisitDeclStmt(DeclStmt *S) {
+    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
+      IndexCtx.indexDeclGroupRef(S->getDeclGroup());
+      return true;
+    }
+
+    DeclGroupRef DG = S->getDeclGroup();
+    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
+      const Decl *D = *I;
+      if (!D)
+        continue;
+      if (!IndexCtx.isFunctionLocalDecl(D))
+        IndexCtx.indexTopLevelDecl(D);
+    }
+
+    return true;
+  }
+
+  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
+    if (C->capturesThis() || C->capturesVLAType())
+      return true;
+
+    if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
+      return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
+                                      Parent, ParentDC, SymbolRoleSet());
+
+    // FIXME: Lambda init-captures.
+    return true;
+  }
+
+  // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
+  // the things that we visit. Make sure to only visit the semantic form.
+  // Also visit things that are in the syntactic form but not the semantic one,
+  // for example the indices in DesignatedInitExprs.
+  bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
+
+    class SyntacticFormIndexer :
+              public RecursiveASTVisitor<SyntacticFormIndexer> {
+      IndexingContext &IndexCtx;
+      const NamedDecl *Parent;
+      const DeclContext *ParentDC;
+
+    public:
+      SyntacticFormIndexer(IndexingContext &indexCtx,
+                            const NamedDecl *Parent, const DeclContext *DC)
+        : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
+
+      bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+      bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+        for (DesignatedInitExpr::reverse_designators_iterator
+               D = E->designators_rbegin(), DEnd = E->designators_rend();
+               D != DEnd; ++D) {
+          if (D->isFieldDesignator())
+            return IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
+                                            Parent, ParentDC, SymbolRoleSet(),
+                                            {}, E);
+        }
+        return true;
+      }
+    };
+
+    auto visitForm = [&](InitListExpr *Form) {
+      for (Stmt *SubStmt : Form->children()) {
+        if (!TraverseStmt(SubStmt))
+          return false;
+      }
+      return true;
+    };
+
+    InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
+    InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
+
+    if (SemaForm) {
+      // Visit things present in syntactic form but not the semantic form.
+      if (SyntaxForm) {
+        SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
+      }
+      return visitForm(SemaForm);
+    }
+
+    // No semantic, try the syntactic.
+    if (SyntaxForm) {
+      return visitForm(SyntaxForm);
+    }
+
+    return true;
+  }
+};
+
+} // anonymous namespace
+
+void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
+                                const DeclContext *DC) {
+  if (!S)
+    return;
+
+  if (!DC)
+    DC = Parent->getLexicalDeclContext();
+  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
+}
similarity index 50%
rename from clang/tools/libclang/IndexDecl.cpp
rename to clang/lib/Index/IndexDecl.cpp
index aa97129..76f68e5 100644 (file)
@@ -1,4 +1,4 @@
-//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
+//===- IndexDecl.cpp - Indexing declarations ------------------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -8,10 +8,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "IndexingContext.h"
+#include "clang/Index/IndexDataConsumer.h"
 #include "clang/AST/DeclVisitor.h"
 
 using namespace clang;
-using namespace cxindex;
+using namespace index;
 
 namespace {
 
@@ -22,6 +23,13 @@ public:
   explicit IndexingDeclVisitor(IndexingContext &indexCtx)
     : IndexCtx(indexCtx) { }
 
+  bool Handled = true;
+
+  bool VisitDecl(const Decl *D) {
+    Handled = false;
+    return true;
+  }
+
   /// \brief Returns true if the given method has been defined explicitly by the
   /// user.
   static bool hasUserDefined(const ObjCMethodDecl *D,
@@ -35,25 +43,35 @@ public:
                         const NamedDecl *Parent = nullptr) {
     if (!Parent) Parent = D;
 
-    if (!IndexCtx.shouldIndexFunctionLocalSymbols()) {
-      IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
-      IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
-    } else {
+    IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
+    IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
+    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
+      // Only index parameters in definitions, parameters in declarations are
+      // not useful.
       if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
-        IndexCtx.handleVar(Parm);
+        auto *DC = Parm->getDeclContext();
+        if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
+          if (FD->isThisDeclarationADefinition())
+            IndexCtx.handleDecl(Parm);
+        } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
+          if (MD->isThisDeclarationADefinition())
+            IndexCtx.handleDecl(Parm);
+        } else {
+          IndexCtx.handleDecl(Parm);
+        }
       } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-        for (auto PI : FD->params()) {
-          IndexCtx.handleVar(PI);
+        if (FD->isThisDeclarationADefinition()) {
+          for (auto PI : FD->params()) {
+            IndexCtx.handleDecl(PI);
+          }
         }
       }
     }
   }
 
-  void handleObjCMethod(const ObjCMethodDecl *D) {
-    IndexCtx.handleObjCMethod(D);
-    if (D->isImplicit())
-      return;
-
+  bool handleObjCMethod(const ObjCMethodDecl *D) {
+    if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic))
+      return false;
     IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
     for (const auto *I : D->params())
       handleDeclarator(I, D);
@@ -64,10 +82,26 @@ public:
         IndexCtx.indexBody(Body, D, D);
       }
     }
+    return true;
   }
 
   bool VisitFunctionDecl(const FunctionDecl *D) {
-    IndexCtx.handleFunction(D);
+    if (D->isDeleted())
+      return true;
+
+    SymbolRoleSet Roles{};
+    SmallVector<SymbolRelation, 4> Relations;
+    if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
+      if (CXXMD->isVirtual())
+        Roles |= (unsigned)SymbolRole::Dynamic;
+      for (auto I = CXXMD->begin_overridden_methods(),
+           E = CXXMD->end_overridden_methods(); I != E; ++I) {
+        Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
+      }
+    }
+
+    if (!IndexCtx.handleDecl(D, Roles, Relations))
+      return false;
     handleDeclarator(D);
 
     if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
@@ -76,7 +110,8 @@ public:
         if (Init->isWritten()) {
           IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
           if (const FieldDecl *Member = Init->getAnyMember())
-            IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D);
+            IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
+                                     (unsigned)SymbolRole::Write);
           IndexCtx.indexBody(Init->getInit(), D, D);
         }
       }
@@ -92,14 +127,16 @@ public:
   }
 
   bool VisitVarDecl(const VarDecl *D) {
-    IndexCtx.handleVar(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
     handleDeclarator(D);
     IndexCtx.indexBody(D->getInit(), D);
     return true;
   }
 
   bool VisitFieldDecl(const FieldDecl *D) {
-    IndexCtx.handleField(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
     handleDeclarator(D);
     if (D->isBitField())
       IndexCtx.indexBody(D->getBitWidth(), D);
@@ -108,44 +145,77 @@ public:
     return true;
   }
 
+  bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
+    if (D->getSynthesize()) {
+      // For synthesized ivars, use the location of the ObjC implementation,
+      // not the location of the property.
+      // Otherwise the header file containing the @interface will have different
+      // indexing contents based on whether the @implementation was present or
+      // not in the translation unit.
+      return IndexCtx.handleDecl(D,
+                                 cast<Decl>(D->getDeclContext())->getLocation(),
+                                 (unsigned)SymbolRole::Implicit);
+    }
+    if (!IndexCtx.handleDecl(D))
+      return false;
+    handleDeclarator(D);
+    return true;
+  }
+
   bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
     handleDeclarator(D);
     return true;
   }
 
   bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
-    IndexCtx.handleEnumerator(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
     IndexCtx.indexBody(D->getInitExpr(), D);
     return true;
   }
 
   bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
-    IndexCtx.handleTypedefName(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
     return true;
   }
 
   bool VisitTagDecl(const TagDecl *D) {
     // Non-free standing tags are handled in indexTypeSourceInfo.
-    if (D->isFreeStanding())
-      IndexCtx.indexTagDecl(D);
+    if (D->isFreeStanding()) {
+      if (D->isThisDeclarationADefinition()) {
+        IndexCtx.indexTagDecl(D);
+      } else {
+        auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
+        return IndexCtx.handleReference(D, D->getLocation(), Parent,
+                                        D->getLexicalDeclContext(),
+                                        SymbolRoleSet());
+      }
+    }
     return true;
   }
 
   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
-    IndexCtx.handleObjCInterface(D);
-
     if (D->isThisDeclarationADefinition()) {
+      if (!IndexCtx.handleDecl(D))
+        return false;
       IndexCtx.indexDeclContext(D);
+    } else {
+      return IndexCtx.handleReference(D, D->getLocation(), nullptr, nullptr,
+                                      SymbolRoleSet());
     }
     return true;
   }
 
   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
-    IndexCtx.handleObjCProtocol(D);
-
     if (D->isThisDeclarationADefinition()) {
+      if (!IndexCtx.handleDecl(D))
+        return false;
       IndexCtx.indexDeclContext(D);
+    } else {
+      return IndexCtx.handleReference(D, D->getLocation(), nullptr, nullptr,
+                                      SymbolRoleSet());
     }
     return true;
   }
@@ -156,9 +226,10 @@ public:
       return true;
 
     if (Class->isImplicitInterfaceDecl())
-      IndexCtx.handleObjCInterface(Class);
+      IndexCtx.handleDecl(Class);
 
-    IndexCtx.handleObjCImplementation(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
 
     // Index the ivars first to make sure the synthesized ivars are indexed
     // before indexing the methods that can reference them.
@@ -173,7 +244,8 @@ public:
   }
 
   bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
-    IndexCtx.handleObjCCategory(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
     IndexCtx.indexDeclContext(D);
     return true;
   }
@@ -183,7 +255,8 @@ public:
     if (!Cat)
       return true;
 
-    IndexCtx.handleObjCCategoryImpl(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
     IndexCtx.indexDeclContext(D);
     return true;
   }
@@ -205,14 +278,19 @@ public:
     if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
         handleObjCMethod(MD);
-    IndexCtx.handleObjCProperty(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
     return true;
   }
 
   bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
     ObjCPropertyDecl *PD = D->getPropertyDecl();
-    IndexCtx.handleSynthesizedObjCProperty(D);
+    if (!IndexCtx.handleReference(PD, D->getLocation(),
+                             /*Parent=*/cast<NamedDecl>(D->getDeclContext()),
+                             D->getDeclContext(), SymbolRoleSet(), {},
+                             /*RefE=*/nullptr, D))
+      return false;
 
     if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
       return true;
@@ -221,121 +299,131 @@ public:
     if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
       if (!IvarD->getSynthesize())
         IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
-                                 D->getDeclContext());
+                                 D->getDeclContext(), SymbolRoleSet());
     }
 
+    auto *ImplD = cast<ObjCImplDecl>(D->getDeclContext());
     if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
       if (MD->isPropertyAccessor() &&
-          !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
-        IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
-                                             D->getLexicalDeclContext());
+          !hasUserDefined(MD, ImplD))
+        IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD);
     }
     if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
       if (MD->isPropertyAccessor() &&
-          !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
-        IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
-                                             D->getLexicalDeclContext());
+          !hasUserDefined(MD, ImplD))
+        IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD);
     }
     return true;
   }
 
   bool VisitNamespaceDecl(const NamespaceDecl *D) {
-    IndexCtx.handleNamespace(D);
+    if (!IndexCtx.handleDecl(D))
+      return false;
     IndexCtx.indexDeclContext(D);
     return true;
   }
 
   bool VisitUsingDecl(const UsingDecl *D) {
-    // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
-    // we should do better.
+    const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+    const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
 
-    IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
+    IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
+                                         D->getLexicalDeclContext());
     for (const auto *I : D->shadows())
-      IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), D,
-                               D->getLexicalDeclContext());
+      IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
+                               D->getLexicalDeclContext(), SymbolRoleSet());
     return true;
   }
 
   bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
-    // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
-    // we should do better.
-
-    IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
-    IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
-                             D->getLocation(), D, D->getLexicalDeclContext());
-    return true;
-  }
-
-  bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
-    IndexCtx.handleClassTemplate(D);
-    if (D->isThisDeclarationADefinition())
-      IndexCtx.indexDeclContext(D->getTemplatedDecl());
-    return true;
+    const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+    const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
+
+    IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
+                                         D->getLexicalDeclContext());
+    return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
+                                    D->getLocation(), Parent,
+                                    D->getLexicalDeclContext(),
+                                    SymbolRoleSet());
   }
 
   bool VisitClassTemplateSpecializationDecl(const
                                            ClassTemplateSpecializationDecl *D) {
     // FIXME: Notify subsequent callbacks if info comes from implicit
     // instantiation.
-    if (D->isThisDeclarationADefinition() &&
-        (IndexCtx.shouldIndexImplicitTemplateInsts() ||
-         !IndexCtx.isTemplateImplicitInstantiation(D)))
+    if (D->isThisDeclarationADefinition())
       IndexCtx.indexTagDecl(D);
     return true;
   }
 
-  bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
-    IndexCtx.handleFunctionTemplate(D);
-    FunctionDecl *FD = D->getTemplatedDecl();
-    handleDeclarator(FD, D);
-    if (FD->isThisDeclarationADefinition()) {
-      const Stmt *Body = FD->getBody();
-      if (Body) {
-        IndexCtx.indexBody(Body, D, FD);
-      }
-    }
-    return true;
+  bool VisitTemplateDecl(const TemplateDecl *D) {
+    // FIXME: Template parameters.
+    return Visit(D->getTemplatedDecl());
   }
 
-  bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
-    IndexCtx.handleTypeAliasTemplate(D);
-    IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D);
+  bool VisitFriendDecl(const FriendDecl *D) {
+    if (auto ND = D->getFriendDecl()) {
+      // FIXME: Ignore a class template in a dependent context, these are not
+      // linked properly with their redeclarations, ending up with duplicate
+      // USRs.
+      // See comment "Friend templates are visible in fairly strange ways." in
+      // SemaTemplate.cpp which precedes code that prevents the friend template
+      // from becoming visible from the enclosing context.
+      if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
+        return true;
+      return Visit(ND);
+    }
+    if (auto Ty = D->getFriendType()) {
+      IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
+    }
     return true;
   }
 
   bool VisitImportDecl(const ImportDecl *D) {
-    IndexCtx.importedModule(D);
-    return true;
+    return IndexCtx.importedModule(D);
   }
 };
 
 } // anonymous namespace
 
-void IndexingContext::indexDecl(const Decl *D) {
+bool IndexingContext::indexDecl(const Decl *D) {
   if (D->isImplicit() && shouldIgnoreIfImplicit(D))
-    return;
+    return true;
 
-  bool Handled = IndexingDeclVisitor(*this).Visit(D);
-  if (!Handled && isa<DeclContext>(D))
-    indexDeclContext(cast<DeclContext>(D));
+  if (isTemplateImplicitInstantiation(D))
+    return true;
+
+  IndexingDeclVisitor Visitor(*this);
+  bool ShouldContinue = Visitor.Visit(D);
+  if (!ShouldContinue)
+    return false;
+
+  if (!Visitor.Handled && isa<DeclContext>(D))
+    return indexDeclContext(cast<DeclContext>(D));
+
+  return true;
 }
 
-void IndexingContext::indexDeclContext(const DeclContext *DC) {
+bool IndexingContext::indexDeclContext(const DeclContext *DC) {
   for (const auto *I : DC->decls())
-    indexDecl(I);
+    if (!indexDecl(I))
+      return false;
+  return true;
 }
 
-void IndexingContext::indexTopLevelDecl(const Decl *D) {
-  if (isNotFromSourceFile(D->getLocation()))
-    return;
+bool IndexingContext::indexTopLevelDecl(const Decl *D) {
+  if (D->getLocation().isInvalid())
+    return true;
 
   if (isa<ObjCMethodDecl>(D))
-    return; // Wait for the objc container.
+    return true; // Wait for the objc container.
 
-  indexDecl(D);
+  return indexDecl(D);
 }
 
-void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
+bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
-    indexTopLevelDecl(*I);
+    if (!indexTopLevelDecl(*I))
+      return false;
+  return true;
 }
diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp
new file mode 100644 (file)
index 0000000..c7c3c8c
--- /dev/null
@@ -0,0 +1,187 @@
+//===--- IndexSymbol.cpp - Types and functions for indexing symbols -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/IndexSymbol.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+
+using namespace clang;
+using namespace clang::index;
+
+SymbolInfo index::getSymbolInfo(const Decl *D) {
+  assert(D);
+  SymbolInfo Info;
+  Info.Kind = SymbolKind::Unknown;
+  Info.TemplateKind = SymbolCXXTemplateKind::NonTemplate;
+  Info.Lang = SymbolLanguage::C;
+
+  if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
+    switch (TD->getTagKind()) {
+    case TTK_Struct:
+      Info.Kind = SymbolKind::Struct; break;
+    case TTK_Union:
+      Info.Kind = SymbolKind::Union; break;
+    case TTK_Class:
+      Info.Kind = SymbolKind::CXXClass;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    case TTK_Interface:
+      Info.Kind = SymbolKind::CXXInterface;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    case TTK_Enum:
+      Info.Kind = SymbolKind::Enum; break;
+    }
+
+    if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
+      if (!CXXRec->isCLike())
+        Info.Lang = SymbolLanguage::CXX;
+
+    if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
+      Info.TemplateKind = SymbolCXXTemplateKind::TemplatePartialSpecialization;
+    } else if (isa<ClassTemplateSpecializationDecl>(D)) {
+      Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization;
+    }
+
+  } else {
+    switch (D->getKind()) {
+    case Decl::Typedef:
+      Info.Kind = SymbolKind::Typedef; break;
+    case Decl::Function:
+      Info.Kind = SymbolKind::Function;
+      break;
+    case Decl::ParmVar:
+      Info.Kind = SymbolKind::Variable;
+      break;
+    case Decl::Var:
+      Info.Kind = SymbolKind::Variable;
+      if (isa<CXXRecordDecl>(D->getDeclContext())) {
+        Info.Kind = SymbolKind::CXXStaticVariable;
+        Info.Lang = SymbolLanguage::CXX;
+      }
+      break;
+    case Decl::Field:
+      Info.Kind = SymbolKind::Field;
+      if (const CXXRecordDecl *
+            CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
+        if (!CXXRec->isCLike())
+          Info.Lang = SymbolLanguage::CXX;
+      }
+      break;
+    case Decl::EnumConstant:
+      Info.Kind = SymbolKind::EnumConstant; break;
+    case Decl::ObjCInterface:
+    case Decl::ObjCImplementation:
+      Info.Kind = SymbolKind::ObjCClass;
+      Info.Lang = SymbolLanguage::ObjC;
+      break;
+    case Decl::ObjCProtocol:
+      Info.Kind = SymbolKind::ObjCProtocol;
+      Info.Lang = SymbolLanguage::ObjC;
+      break;
+    case Decl::ObjCCategory:
+    case Decl::ObjCCategoryImpl:
+      Info.Kind = SymbolKind::ObjCCategory;
+      Info.Lang = SymbolLanguage::ObjC;
+      break;
+    case Decl::ObjCMethod:
+      if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
+        Info.Kind = SymbolKind::ObjCInstanceMethod;
+      else
+        Info.Kind = SymbolKind::ObjCClassMethod;
+      Info.Lang = SymbolLanguage::ObjC;
+      break;
+    case Decl::ObjCProperty:
+      Info.Kind = SymbolKind::ObjCProperty;
+      Info.Lang = SymbolLanguage::ObjC;
+      break;
+    case Decl::ObjCIvar:
+      Info.Kind = SymbolKind::ObjCIvar;
+      Info.Lang = SymbolLanguage::ObjC;
+      break;
+    case Decl::Namespace:
+      Info.Kind = SymbolKind::CXXNamespace;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    case Decl::NamespaceAlias:
+      Info.Kind = SymbolKind::CXXNamespaceAlias;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    case Decl::CXXConstructor:
+      Info.Kind = SymbolKind::CXXConstructor;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    case Decl::CXXDestructor:
+      Info.Kind = SymbolKind::CXXDestructor;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    case Decl::CXXConversion:
+      Info.Kind = SymbolKind::CXXConversionFunction;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    case Decl::CXXMethod: {
+      const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
+      if (MD->isStatic())
+        Info.Kind = SymbolKind::CXXStaticMethod;
+      else
+        Info.Kind = SymbolKind::CXXInstanceMethod;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    }
+    case Decl::ClassTemplate:
+      Info.Kind = SymbolKind::CXXClass;
+      Info.TemplateKind = SymbolCXXTemplateKind::Template;
+      break;
+    case Decl::FunctionTemplate:
+      Info.Kind = SymbolKind::Function;
+      Info.TemplateKind = SymbolCXXTemplateKind::Template;
+      if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
+                           cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
+        if (isa<CXXConstructorDecl>(MD))
+          Info.Kind = SymbolKind::CXXConstructor;
+        else if (isa<CXXDestructorDecl>(MD))
+          Info.Kind = SymbolKind::CXXDestructor;
+        else if (isa<CXXConversionDecl>(MD))
+          Info.Kind = SymbolKind::CXXConversionFunction;
+        else {
+          if (MD->isStatic())
+            Info.Kind = SymbolKind::CXXStaticMethod;
+          else
+            Info.Kind = SymbolKind::CXXInstanceMethod;
+        }
+      }
+      break;
+    case Decl::TypeAliasTemplate:
+      Info.Kind = SymbolKind::CXXTypeAlias;
+      Info.TemplateKind = SymbolCXXTemplateKind::Template;
+      break;
+    case Decl::TypeAlias:
+      Info.Kind = SymbolKind::CXXTypeAlias;
+      Info.Lang = SymbolLanguage::CXX;
+      break;
+    default:
+      break;
+    }
+  }
+
+  if (Info.Kind == SymbolKind::Unknown)
+    return Info;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->getTemplatedKind() ==
+          FunctionDecl::TK_FunctionTemplateSpecialization)
+      Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization;
+  }
+
+  if (Info.TemplateKind != SymbolCXXTemplateKind::NonTemplate)
+    Info.Lang = SymbolLanguage::CXX;
+
+  return Info;
+}
similarity index 52%
rename from clang/tools/libclang/IndexTypeSourceInfo.cpp
rename to clang/lib/Index/IndexTypeSourceInfo.cpp
index 9666052..619a9a4 100644 (file)
@@ -1,4 +1,4 @@
-//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
+//===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -11,7 +11,7 @@
 #include "clang/AST/RecursiveASTVisitor.h"
 
 using namespace clang;
-using namespace cxindex;
+using namespace index;
 
 namespace {
 
@@ -19,20 +19,58 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
   IndexingContext &IndexCtx;
   const NamedDecl *Parent;
   const DeclContext *ParentDC;
+  bool IsBase;
+  SmallVector<SymbolRelation, 3> Relations;
+
+  typedef RecursiveASTVisitor<TypeIndexer> base;
 
 public:
   TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
-              const DeclContext *DC)
-    : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { }
+              const DeclContext *DC, bool isBase)
+    : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
+    if (IsBase) {
+      assert(Parent);
+      Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
+    }
+  }
   
   bool shouldWalkTypesOfTypeLocs() const { return false; }
 
   bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
-    IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
-                             Parent, ParentDC);
+    return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
+                                    Parent, ParentDC, SymbolRoleSet(),
+                                    Relations);
+  }
+
+#define TRY_TO(CALL_EXPR)                                                      \
+  do {                                                                         \
+    if (!CALL_EXPR)                                                            \
+      return false;                                                            \
+  } while (0)
+
+  bool traverseParamVarHelper(ParmVarDecl *D) {
+    TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+    if (D->getTypeSourceInfo())
+      TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
     return true;
   }
 
+  bool TraverseParmVarDecl(ParmVarDecl *D) {
+    // Avoid visiting default arguments from the definition that were already
+    // visited in the declaration.
+    // FIXME: A free function definition can have default arguments.
+    // Avoiding double visitaiton of default arguments should be handled by the
+    // visitor probably with a bit in the AST to indicate if the attached
+    // default argument was 'inherited' or written in source.
+    if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
+      if (FD->isThisDeclarationADefinition()) {
+        return traverseParamVarHelper(D);
+      }
+    }
+
+    return base::TraverseParmVarDecl(D);
+  }
+
   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
     return true;
@@ -48,24 +86,20 @@ public:
       return true;
     }
 
-    if (D->getLocation() == TL.getNameLoc())
-      IndexCtx.handleTagDecl(D);
-    else
-      IndexCtx.handleReference(D, TL.getNameLoc(),
-                               Parent, ParentDC);
-    return true;
+    return IndexCtx.handleReference(D, TL.getNameLoc(),
+                                    Parent, ParentDC, SymbolRoleSet(),
+                                    Relations);
   }
 
   bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
-    IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
-                             Parent, ParentDC);
-    return true;
+    return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
+                                    Parent, ParentDC, SymbolRoleSet());
   }
 
   bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
     for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
       IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
-                               Parent, ParentDC);
+                               Parent, ParentDC, SymbolRoleSet());
     }
     return true;
   }
@@ -75,11 +109,11 @@ public:
       if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
         if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
           IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
-                                   Parent, ParentDC);
+                                   Parent, ParentDC, SymbolRoleSet(), Relations);
       } else {
         if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
           IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
-                                   Parent, ParentDC);
+                                   Parent, ParentDC, SymbolRoleSet(), Relations);
       }
     }
     return true;
@@ -95,22 +129,24 @@ public:
 
 void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
                                           const NamedDecl *Parent,
-                                          const DeclContext *DC) {
+                                          const DeclContext *DC,
+                                          bool isBase) {
   if (!TInfo || TInfo->getTypeLoc().isNull())
     return;
   
-  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC);
+  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase);
 }
 
 void IndexingContext::indexTypeLoc(TypeLoc TL,
                                    const NamedDecl *Parent,
-                                   const DeclContext *DC) {
+                                   const DeclContext *DC,
+                                   bool isBase) {
   if (TL.isNull())
     return;
 
   if (!DC)
     DC = Parent->getLexicalDeclContext();
-  TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL);
+  TypeIndexer(*this, Parent, DC, isBase).TraverseTypeLoc(TL);
 }
 
 void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
@@ -134,11 +170,11 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
 
   case NestedNameSpecifier::Namespace:
     handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
-                    Loc, Parent, DC);
+                    Loc, Parent, DC, SymbolRoleSet());
     break;
   case NestedNameSpecifier::NamespaceAlias:
     handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
-                    Loc, Parent, DC);
+                    Loc, Parent, DC, SymbolRoleSet());
     break;
 
   case NestedNameSpecifier::TypeSpec:
@@ -149,8 +185,18 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
 }
 
 void IndexingContext::indexTagDecl(const TagDecl *D) {
-  if (handleTagDecl(D)) {
-    if (D->isThisDeclarationADefinition())
+  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
+    return;
+
+  if (handleDecl(D)) {
+    if (D->isThisDeclarationADefinition()) {
+      indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
+      if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
+        for (const auto &I : CXXRD->bases()) {
+          indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
+        }
+      }
       indexDeclContext(D);
+    }
   }
 }
diff --git a/clang/lib/Index/IndexingAction.cpp b/clang/lib/Index/IndexingAction.cpp
new file mode 100644 (file)
index 0000000..3f7ef43
--- /dev/null
@@ -0,0 +1,140 @@
+//===- IndexingAction.cpp - Frontend index action -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/IndexingAction.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "IndexingContext.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+using namespace clang::index;
+
+void IndexDataConsumer::_anchor() {}
+
+bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
+                                            ArrayRef<SymbolRelation> Relations,
+                                            FileID FID, unsigned Offset,
+                                            ASTNodeInfo ASTNode) {
+  return true;
+}
+
+bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
+                                             const MacroInfo *MI, SymbolRoleSet Roles,
+                                             FileID FID, unsigned Offset) {
+  return true;
+}
+
+bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
+                                              SymbolRoleSet Roles,
+                                              FileID FID, unsigned Offset) {
+  return true;
+}
+
+namespace {
+
+class IndexASTConsumer : public ASTConsumer {
+  IndexingContext &IndexCtx;
+
+public:
+  IndexASTConsumer(IndexingContext &IndexCtx)
+    : IndexCtx(IndexCtx) {}
+
+protected:
+  void Initialize(ASTContext &Context) override {
+    IndexCtx.setASTContext(Context);
+  }
+
+  bool HandleTopLevelDecl(DeclGroupRef DG) override {
+    return IndexCtx.indexDeclGroupRef(DG);
+  }
+
+  void HandleInterestingDecl(DeclGroupRef DG) override {
+    // Ignore deserialized decls.
+  }
+
+  void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
+    IndexCtx.indexDeclGroupRef(DG);
+  }
+
+  void HandleTranslationUnit(ASTContext &Ctx) override {
+  }
+};
+
+class IndexAction : public WrapperFrontendAction {
+  IndexingOptions IndexOpts;
+  std::shared_ptr<IndexDataConsumer> DataConsumer;
+  std::unique_ptr<IndexingContext> IndexCtx;
+
+public:
+  IndexAction(std::unique_ptr<FrontendAction> WrappedAction,
+              std::shared_ptr<IndexDataConsumer> DataConsumer,
+              IndexingOptions Opts)
+    : WrapperFrontendAction(std::move(WrappedAction)),
+      IndexOpts(Opts),
+      DataConsumer(std::move(DataConsumer)) {}
+
+protected:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+  void EndSourceFileAction() override;
+};
+
+} // anonymous namespace
+
+void IndexAction::EndSourceFileAction() {
+  // Invoke wrapped action's method.
+  WrapperFrontendAction::EndSourceFileAction();
+
+  bool IndexActionFailed = !IndexCtx;
+  if (!IndexActionFailed)
+    DataConsumer->finish();
+}
+
+std::unique_ptr<ASTConsumer>
+IndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+  auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+  if (!OtherConsumer)
+    return nullptr;
+
+  IndexCtx.reset(new IndexingContext(IndexOpts, *DataConsumer));
+
+  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+  Consumers.push_back(std::move(OtherConsumer));
+  Consumers.push_back(llvm::make_unique<IndexASTConsumer>(*IndexCtx));
+  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
+}
+
+std::unique_ptr<FrontendAction>
+index::createIndexingAction(std::unique_ptr<FrontendAction> WrappedAction,
+                            std::shared_ptr<IndexDataConsumer> DataConsumer,
+                            IndexingOptions Opts) {
+  return llvm::make_unique<IndexAction>(std::move(WrappedAction),
+                                        std::move(DataConsumer),
+                                        Opts);
+}
+
+
+static bool topLevelDeclVisitor(void *context, const Decl *D) {
+  IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
+  return IndexCtx.indexTopLevelDecl(D);
+}
+
+static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
+  Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
+}
+
+void index::indexASTUnit(ASTUnit &Unit,
+                         std::shared_ptr<IndexDataConsumer> DataConsumer,
+                         IndexingOptions Opts) {
+  IndexingContext IndexCtx(Opts, *DataConsumer);
+  IndexCtx.setASTContext(Unit.getASTContext());
+  indexTranslationUnit(Unit, IndexCtx);
+}
diff --git a/clang/lib/Index/IndexingContext.cpp b/clang/lib/Index/IndexingContext.cpp
new file mode 100644 (file)
index 0000000..91fbbfb
--- /dev/null
@@ -0,0 +1,325 @@
+//===- IndexingContext.cpp - Indexing context data ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IndexingContext.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceManager.h"
+
+using namespace clang;
+using namespace index;
+
+bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
+  return IndexOpts.IndexFunctionLocals;
+}
+
+bool IndexingContext::handleDecl(const Decl *D,
+                                 SymbolRoleSet Roles,
+                                 ArrayRef<SymbolRelation> Relations) {
+  return handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false,
+                              cast<Decl>(D->getDeclContext()), Roles, Relations,
+                              nullptr, nullptr, D->getDeclContext());
+}
+
+bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
+                                 SymbolRoleSet Roles,
+                                 ArrayRef<SymbolRelation> Relations,
+                                 const DeclContext *DC) {
+  if (!DC)
+    DC = D->getDeclContext();
+  return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
+                              Roles, Relations,
+                              nullptr, nullptr, DC);
+}
+
+bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
+                                      const NamedDecl *Parent,
+                                      const DeclContext *DC,
+                                      SymbolRoleSet Roles,
+                                      ArrayRef<SymbolRelation> Relations,
+                                      const Expr *RefE,
+                                      const Decl *RefD) {
+  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
+    return true;
+
+  if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
+    return true;
+    
+  return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
+                              RefE, RefD, DC);
+}
+
+bool IndexingContext::importedModule(const ImportDecl *ImportD) {
+  SourceLocation Loc = ImportD->getLocation();
+  SourceManager &SM = Ctx->getSourceManager();
+  Loc = SM.getFileLoc(Loc);
+  if (Loc.isInvalid())
+    return true;
+
+  FileID FID;
+  unsigned Offset;
+  std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
+  if (FID.isInvalid())
+    return true;
+
+  bool Invalid = false;
+  const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
+  if (Invalid || !SEntry.isFile())
+    return true;
+
+  if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
+    switch (IndexOpts.SystemSymbolFilter) {
+    case IndexingOptions::SystemSymbolFilterKind::None:
+    case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
+      return true;
+    case IndexingOptions::SystemSymbolFilterKind::All:
+      break;
+    }
+  }
+
+  SymbolRoleSet Roles{};
+  if (ImportD->isImplicit())
+    Roles |= (unsigned)SymbolRole::Implicit;
+
+  return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
+}
+
+bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
+  assert(D);
+
+  if (isa<TemplateTemplateParmDecl>(D))
+    return true;
+
+  if (!D->getParentFunctionOrMethod())
+    return false;
+
+  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+    switch (ND->getFormalLinkage()) {
+    case NoLinkage:
+    case VisibleNoLinkage:
+    case InternalLinkage:
+      return true;
+    case UniqueExternalLinkage:
+      llvm_unreachable("Not a sema linkage");
+    case ExternalLinkage:
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
+  TemplateSpecializationKind TKind = TSK_Undeclared;
+  if (const ClassTemplateSpecializationDecl *
+      SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+    TKind = SD->getSpecializationKind();
+  }
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    TKind = FD->getTemplateSpecializationKind();
+  }
+  switch (TKind) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      return false;
+    case TSK_ImplicitInstantiation:
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+      return true;
+  }
+}
+
+bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
+  if (isa<ObjCInterfaceDecl>(D))
+    return false;
+  if (isa<ObjCCategoryDecl>(D))
+    return false;
+  if (isa<ObjCIvarDecl>(D))
+    return false;
+  if (isa<ObjCMethodDecl>(D))
+    return false;
+  if (isa<ImportDecl>(D))
+    return false;
+  return true;
+}
+
+static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
+  if (const ClassTemplateSpecializationDecl *
+      SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+    return SD->getTemplateInstantiationPattern();
+  }
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    return FD->getTemplateInstantiationPattern();
+  }
+  return nullptr;
+}
+
+static bool isDeclADefinition(const Decl *D, ASTContext &Ctx) {
+  if (auto VD = dyn_cast<VarDecl>(D))
+    return VD->isThisDeclarationADefinition(Ctx);
+
+  if (auto FD = dyn_cast<FunctionDecl>(D))
+    return FD->isThisDeclarationADefinition();
+
+  if (auto TD = dyn_cast<TagDecl>(D))
+    return TD->isThisDeclarationADefinition();
+
+  if (auto MD = dyn_cast<ObjCMethodDecl>(D))
+    return MD->isThisDeclarationADefinition();
+
+  if (isa<TypedefNameDecl>(D) ||
+      isa<EnumConstantDecl>(D) ||
+      isa<FieldDecl>(D) ||
+      isa<MSPropertyDecl>(D) ||
+      isa<ObjCImplDecl>(D) ||
+      isa<ObjCPropertyImplDecl>(D))
+    return true;
+
+  return false;
+}
+
+static const Decl *adjustParent(const Decl *Parent) {
+  if (!Parent)
+    return nullptr;
+  for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
+    if (isa<TranslationUnitDecl>(Parent))
+      return nullptr;
+    if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
+      continue;
+    if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
+      if (NS->isAnonymousNamespace())
+        continue;
+    } else if (auto EnumD = dyn_cast<EnumDecl>(Parent)) {
+      // Move enumerators under anonymous enum to the enclosing parent.
+      if (EnumD->getDeclName().isEmpty())
+        continue;
+    } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
+      if (RD->isAnonymousStructOrUnion())
+        continue;
+    } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
+      if (FD->getDeclName().isEmpty())
+        continue;
+    }
+    return Parent;
+  }
+}
+
+static const Decl *getCanonicalDecl(const Decl *D) {
+  D = D->getCanonicalDecl();
+  if (auto TD = dyn_cast<TemplateDecl>(D)) {
+    D = TD->getTemplatedDecl();
+    assert(D->isCanonicalDecl());
+  }
+
+  return D;
+}
+
+bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
+                                           bool IsRef, const Decl *Parent,
+                                           SymbolRoleSet Roles,
+                                           ArrayRef<SymbolRelation> Relations,
+                                           const Expr *OrigE,
+                                           const Decl *OrigD,
+                                           const DeclContext *ContainerDC) {
+  if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
+    return true;
+  if (!isa<NamedDecl>(D) ||
+      (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
+       !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
+    return true;
+
+  SourceManager &SM = Ctx->getSourceManager();
+  Loc = SM.getFileLoc(Loc);
+  if (Loc.isInvalid())
+    return true;
+
+  FileID FID;
+  unsigned Offset;
+  std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
+  if (FID.isInvalid())
+    return true;
+
+  bool Invalid = false;
+  const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
+  if (Invalid || !SEntry.isFile())
+    return true;
+
+  if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
+    switch (IndexOpts.SystemSymbolFilter) {
+    case IndexingOptions::SystemSymbolFilterKind::None:
+      return true;
+    case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
+      if (IsRef)
+        return true;
+      break;
+    case IndexingOptions::SystemSymbolFilterKind::All:
+      break;
+    }
+  }
+
+  if (isTemplateImplicitInstantiation(D)) {
+    if (!IsRef)
+      return true;
+    D = adjustTemplateImplicitInstantiation(D);
+    if (!D)
+      return true;
+    assert(!isTemplateImplicitInstantiation(D));
+  }
+
+  if (!OrigD)
+    OrigD = D;
+
+  if (IsRef)
+    Roles |= (unsigned)SymbolRole::Reference;
+  else if (isDeclADefinition(D, *Ctx))
+    Roles |= (unsigned)SymbolRole::Definition;
+  else
+    Roles |= (unsigned)SymbolRole::Declaration;
+
+  D = getCanonicalDecl(D);
+  if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) {
+    // operator new declarations will link to the implicit one as canonical.
+    return true;
+  }
+  Parent = adjustParent(Parent);
+  if (Parent)
+    Parent = getCanonicalDecl(Parent);
+  assert(!Parent || !Parent->isImplicit() ||
+         isa<ObjCInterfaceDecl>(Parent) || isa<ObjCMethodDecl>(Parent));
+
+  SmallVector<SymbolRelation, 6> FinalRelations;
+  FinalRelations.reserve(Relations.size()+1);
+
+  auto addRelation = [&](SymbolRelation Rel) {
+    auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
+                [&](SymbolRelation Elem)->bool {
+                  return Elem.RelatedSymbol == Rel.RelatedSymbol;
+                });
+    if (It != FinalRelations.end()) {
+      It->Roles |= Rel.Roles;
+    } else {
+      FinalRelations.push_back(Rel);
+    }
+    Roles |= Rel.Roles;
+  };
+
+  if (!IsRef && Parent && !cast<DeclContext>(Parent)->isFunctionOrMethod()) {
+    addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent});
+  }
+  for (auto &Rel : Relations) {
+    addRelation(SymbolRelation(Rel.Roles,
+                               Rel.RelatedSymbol->getCanonicalDecl()));
+  }
+
+  IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
+  return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
+                                          Node);
+}
diff --git a/clang/lib/Index/IndexingContext.h b/clang/lib/Index/IndexingContext.h
new file mode 100644 (file)
index 0000000..7746505
--- /dev/null
@@ -0,0 +1,121 @@
+//===- IndexingContext.h - Indexing context data ----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H
+#define LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Index/IndexSymbol.h"
+#include "clang/Index/IndexingAction.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace clang {
+  class ASTContext;
+  class Decl;
+  class DeclGroupRef;
+  class ImportDecl;
+  class TagDecl;
+  class TypeSourceInfo;
+  class NamedDecl;
+  class ObjCMethodDecl;
+  class DeclContext;
+  class NestedNameSpecifierLoc;
+  class Stmt;
+  class Expr;
+  class TypeLoc;
+  class SourceLocation;
+
+namespace index {
+  class IndexDataConsumer;
+
+class IndexingContext {
+  IndexingOptions IndexOpts;
+  IndexDataConsumer &DataConsumer;
+  ASTContext *Ctx = nullptr;
+
+public:
+  IndexingContext(IndexingOptions IndexOpts, IndexDataConsumer &DataConsumer)
+    : IndexOpts(IndexOpts), DataConsumer(DataConsumer) {}
+
+  const IndexingOptions &getIndexOpts() const { return IndexOpts; }
+  IndexDataConsumer &getDataConsumer() { return DataConsumer; }
+
+  void setASTContext(ASTContext &ctx) { Ctx = &ctx; }
+
+  bool shouldSuppressRefs() const {
+    return false;
+  }
+
+  bool shouldIndexFunctionLocalSymbols() const;
+
+  bool shouldIndexImplicitTemplateInsts() const {
+    return false;
+  }
+
+  static bool isFunctionLocalDecl(const Decl *D);
+  static bool isTemplateImplicitInstantiation(const Decl *D);
+
+  bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(),
+                  ArrayRef<SymbolRelation> Relations = {});
+
+  bool handleDecl(const Decl *D, SourceLocation Loc,
+                  SymbolRoleSet Roles = SymbolRoleSet(),
+                  ArrayRef<SymbolRelation> Relations = {},
+                  const DeclContext *DC = nullptr);
+
+  bool handleReference(const NamedDecl *D, SourceLocation Loc,
+                       const NamedDecl *Parent,
+                       const DeclContext *DC,
+                       SymbolRoleSet Roles,
+                       ArrayRef<SymbolRelation> Relations = {},
+                       const Expr *RefE = nullptr,
+                       const Decl *RefD = nullptr);
+
+  bool importedModule(const ImportDecl *ImportD);
+
+  bool indexDecl(const Decl *D);
+
+  void indexTagDecl(const TagDecl *D);
+
+  void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
+                           const DeclContext *DC = nullptr,
+                           bool isBase = false);
+
+  void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
+                    const DeclContext *DC = nullptr,
+                    bool isBase = false);
+
+  void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+                                   const NamedDecl *Parent,
+                                   const DeclContext *DC = nullptr);
+
+  bool indexDeclContext(const DeclContext *DC);
+
+  void indexBody(const Stmt *S, const NamedDecl *Parent,
+                 const DeclContext *DC = nullptr);
+
+  bool indexTopLevelDecl(const Decl *D);
+  bool indexDeclGroupRef(DeclGroupRef DG);
+
+private:
+  bool shouldIgnoreIfImplicit(const Decl *D);
+
+  bool handleDeclOccurrence(const Decl *D, SourceLocation Loc,
+                            bool IsRef, const Decl *Parent,
+                            SymbolRoleSet Roles,
+                            ArrayRef<SymbolRelation> Relations,
+                            const Expr *RefE,
+                            const Decl *RefD,
+                            const DeclContext *ContainerDC);
+};
+
+} // end namespace index
+} // end namespace clang
+
+#endif
index d7eaca1..d893b5e 100644 (file)
@@ -11,17 +11,14 @@ set(SOURCES
   CIndexer.cpp
   CXComment.cpp
   CXCursor.cpp
+  CXIndexDataConsumer.cpp
   CXCompilationDatabase.cpp
   CXLoadedDiagnostic.cpp
   CXSourceLocation.cpp
   CXStoredDiagnostic.cpp
   CXString.cpp
   CXType.cpp
-  IndexBody.cpp
-  IndexDecl.cpp
-  IndexTypeSourceInfo.cpp
   Indexing.cpp
-  IndexingContext.cpp
 
   ADDITIONAL_HEADERS
   CIndexDiagnostic.h
similarity index 70%
rename from clang/tools/libclang/IndexingContext.cpp
rename to clang/tools/libclang/CXIndexDataConsumer.cpp
index 7f65412..f6f8e30 100644 (file)
@@ -1,4 +1,4 @@
-//===- IndexingContext.cpp - Higher level API functions -------------------===//
+//===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 //
 //===----------------------------------------------------------------------===//
 
-#include "IndexingContext.h"
+#include "CXIndexDataConsumer.h"
 #include "CIndexDiagnostic.h"
 #include "CXTranslationUnit.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
 #include "clang/Frontend/ASTUnit.h"
 
 using namespace clang;
+using namespace clang::index;
 using namespace cxindex;
 using namespace cxcursor;
 
-IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo(
+namespace {
+class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
+  CXIndexDataConsumer &DataConsumer;
+  SourceLocation DeclLoc;
+  const DeclContext *LexicalDC;
+
+public:
+  IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc,
+                      const DeclContext *lexicalDC)
+    : DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { }
+
+  bool VisitFunctionDecl(const FunctionDecl *D) {
+    DataConsumer.handleFunction(D);
+    return true;
+  }
+
+  bool VisitVarDecl(const VarDecl *D) {
+    DataConsumer.handleVar(D);
+    return true;
+  }
+
+  bool VisitFieldDecl(const FieldDecl *D) {
+    DataConsumer.handleField(D);
+    return true;
+  }
+
+  bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
+    return true;
+  }
+
+  bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
+    DataConsumer.handleEnumerator(D);
+    return true;
+  }
+
+  bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
+    DataConsumer.handleTypedefName(D);
+    return true;
+  }
+
+  bool VisitTagDecl(const TagDecl *D) {
+    DataConsumer.handleTagDecl(D);
+    return true;
+  }
+
+  bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
+    DataConsumer.handleObjCInterface(D);
+    return true;
+  }
+
+  bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
+    DataConsumer.handleObjCProtocol(D);
+    return true;
+  }
+
+  bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
+    DataConsumer.handleObjCImplementation(D);
+    return true;
+  }
+
+  bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
+    DataConsumer.handleObjCCategory(D);
+    return true;
+  }
+
+  bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
+    DataConsumer.handleObjCCategoryImpl(D);
+    return true;
+  }
+
+  bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
+    if (D->getDeclContext() != LexicalDC)
+      DataConsumer.handleSynthesizedObjCMethod(D, DeclLoc, LexicalDC);
+    else
+      DataConsumer.handleObjCMethod(D);
+    return true;
+  }
+
+  bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
+    DataConsumer.handleObjCProperty(D);
+    return true;
+  }
+
+  bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
+    DataConsumer.handleSynthesizedObjCProperty(D);
+    return true;
+  }
+
+  bool VisitNamespaceDecl(const NamespaceDecl *D) {
+    DataConsumer.handleNamespace(D);
+    return true;
+  }
+
+  bool VisitUsingDecl(const UsingDecl *D) {
+    return true;
+  }
+
+  bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
+    return true;
+  }
+
+  bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
+    DataConsumer.handleClassTemplate(D);
+    return true;
+  }
+
+  bool VisitClassTemplateSpecializationDecl(const
+                                           ClassTemplateSpecializationDecl *D) {
+    DataConsumer.handleTagDecl(D);
+    return true;
+  }
+
+  bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
+    DataConsumer.handleFunctionTemplate(D);
+    return true;
+  }
+
+  bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
+    DataConsumer.handleTypeAliasTemplate(D);
+    return true;
+  }
+
+  bool VisitImportDecl(const ImportDecl *D) {
+    DataConsumer.importedModule(D);
+    return true;
+  }
+};
+}
+
+bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D,
+                                              SymbolRoleSet Roles,
+                                             ArrayRef<SymbolRelation> Relations,
+                                              FileID FID, unsigned Offset,
+                                              ASTNodeInfo ASTNode) {
+  SourceLocation Loc = getASTContext().getSourceManager()
+      .getLocForStartOfFile(FID).getLocWithOffset(Offset);
+
+  if (Roles & (unsigned)SymbolRole::Reference) {
+    const NamedDecl *ND = dyn_cast<NamedDecl>(D);
+    if (!ND)
+      return true;
+
+    if (auto *ObjCID = dyn_cast_or_null<ObjCInterfaceDecl>(ASTNode.OrigD)) {
+      if (!ObjCID->isThisDeclarationADefinition() &&
+          ObjCID->getLocation() == Loc) {
+        // The libclang API treats this as ObjCClassRef declaration.
+        IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID);
+        return true;
+      }
+    }
+
+    CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct;
+    if (Roles & (unsigned)SymbolRole::Implicit) {
+      Kind = CXIdxEntityRef_Implicit;
+    }
+
+    CXCursor Cursor;
+    if (ASTNode.OrigE) {
+      Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE,
+                                      cast<Decl>(ASTNode.ContainerDC),
+                                      getCXTU());
+    } else {
+      const NamedDecl *CursorD = dyn_cast_or_null<NamedDecl>(ASTNode.OrigD);
+      if (!CursorD)
+        CursorD = ND;
+      Cursor = getRefCursor(CursorD, Loc);
+    }
+    handleReference(ND, Loc, Cursor,
+                    dyn_cast_or_null<NamedDecl>(ASTNode.Parent),
+                    ASTNode.ContainerDC, ASTNode.OrigE, Kind);
+
+  } else {
+    const DeclContext *DC = nullptr;
+    for (const auto &SymRel : Relations) {
+      if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf)
+        DC = dyn_cast<DeclContext>(SymRel.RelatedSymbol);
+    }
+    IndexingDeclVisitor(*this, Loc, DC).Visit(ASTNode.OrigD);
+  }
+
+  return !shouldAbort();
+}
+
+bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
+                                                SymbolRoleSet Roles,
+                                                FileID FID,
+                                                unsigned Offset) {
+  IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
+  return !shouldAbort();
+}
+
+void CXIndexDataConsumer::finish() {
+  indexDiagnostics();
+}
+
+
+CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo(
                                     const ObjCProtocolList &ProtList,
-                                    IndexingContext &IdxCtx,
+                                    CXIndexDataConsumer &IdxCtx,
                                     ScratchAlloc &SA) {
   ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
   for (ObjCInterfaceDecl::protocol_iterator
@@ -61,7 +259,7 @@ IBOutletCollectionInfo::IBOutletCollectionInfo(
     IBCollInfo.objcClass = nullptr;
 }
 
-AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx)
+AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx)
   : SA(IdxCtx), ref_cnt(0) {
 
   if (!D->hasAttrs())
@@ -114,14 +312,14 @@ AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx)
 }
 
 IntrusiveRefCntPtr<AttrListInfo>
-AttrListInfo::create(const Decl *D, IndexingContext &IdxCtx) {
+AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) {
   ScratchAlloc SA(IdxCtx);
   AttrListInfo *attrs = SA.allocate<AttrListInfo>();
   return new (attrs) AttrListInfo(D, IdxCtx);
 }
 
-IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
-                                   IndexingContext &IdxCtx,
+CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
+                                   CXIndexDataConsumer &IdxCtx,
                                    ScratchAlloc &SA) {
   for (const auto &Base : D->bases()) {
     BaseEntities.push_back(EntityInfo());
@@ -155,7 +353,7 @@ IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
     CXBases.push_back(&BaseInfos[i]);
 }
 
-SourceLocation IndexingContext::CXXBasesListInfo::getBaseLoc(
+SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
                                            const CXXBaseSpecifier &Base) const {
   SourceLocation Loc = Base.getSourceRange().getBegin();
   TypeLoc TL;
@@ -193,16 +391,16 @@ const char *ScratchAlloc::copyCStr(StringRef Str) {
   return buf;
 }
 
-void IndexingContext::setASTContext(ASTContext &ctx) {
+void CXIndexDataConsumer::setASTContext(ASTContext &ctx) {
   Ctx = &ctx;
   cxtu::getASTUnit(CXTU)->setASTContext(&ctx);
 }
 
-void IndexingContext::setPreprocessor(Preprocessor &PP) {
+void CXIndexDataConsumer::setPreprocessor(Preprocessor &PP) {
   cxtu::getASTUnit(CXTU)->setPreprocessor(&PP);
 }
 
-bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
+bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) {
   assert(D);
 
   if (!D->getParentFunctionOrMethod())
@@ -224,13 +422,13 @@ bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
   return true;
 }
 
-bool IndexingContext::shouldAbort() {
+bool CXIndexDataConsumer::shouldAbort() {
   if (!CB.abortQuery)
     return false;
   return CB.abortQuery(ClientData, nullptr);
 }
 
-void IndexingContext::enteredMainFile(const FileEntry *File) {
+void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) {
   if (File && CB.enteredMainFile) {
     CXIdxClientFile idxFile =
       CB.enteredMainFile(ClientData,
@@ -240,7 +438,7 @@ void IndexingContext::enteredMainFile(const FileEntry *File) {
   }
 }
 
-void IndexingContext::ppIncludedFile(SourceLocation hashLoc,
+void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc,
                                      StringRef filename,
                                      const FileEntry *File,
                                      bool isImport, bool isAngled,
@@ -258,7 +456,7 @@ void IndexingContext::ppIncludedFile(SourceLocation hashLoc,
   FileMap[File] = idxFile;
 }
 
-void IndexingContext::importedModule(const ImportDecl *ImportD) {
+void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
   if (!CB.importedASTFile)
     return;
 
@@ -277,7 +475,7 @@ void IndexingContext::importedModule(const ImportDecl *ImportD) {
   (void)astFile;
 }
 
-void IndexingContext::importedPCH(const FileEntry *File) {
+void CXIndexDataConsumer::importedPCH(const FileEntry *File) {
   if (!CB.importedASTFile)
     return;
 
@@ -292,21 +490,29 @@ void IndexingContext::importedPCH(const FileEntry *File) {
   (void)astFile;
 }
 
-void IndexingContext::startedTranslationUnit() {
+void CXIndexDataConsumer::startedTranslationUnit() {
   CXIdxClientContainer idxCont = nullptr;
   if (CB.startedTranslationUnit)
     idxCont = CB.startedTranslationUnit(ClientData, nullptr);
   addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
 }
 
-void IndexingContext::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
+void CXIndexDataConsumer::indexDiagnostics() {
+  if (!hasDiagnosticCallback())
+    return;
+
+  CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU());
+  handleDiagnosticSet(DiagSet);
+}
+
+void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
   if (!CB.diagnostic)
     return;
 
   CB.diagnostic(ClientData, CXDiagSet, nullptr);
 }
 
-bool IndexingContext::handleDecl(const NamedDecl *D,
+bool CXIndexDataConsumer::handleDecl(const NamedDecl *D,
                                  SourceLocation Loc, CXCursor Cursor,
                                  DeclInfo &DInfo,
                                  const DeclContext *LexicalDC,
@@ -365,14 +571,14 @@ bool IndexingContext::handleDecl(const NamedDecl *D,
   return true;
 }
 
-bool IndexingContext::handleObjCContainer(const ObjCContainerDecl *D,
+bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D,
                                           SourceLocation Loc, CXCursor Cursor,
                                           ObjCContainerDeclInfo &ContDInfo) {
   ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
   return handleDecl(D, Loc, Cursor, ContDInfo);
 }
 
-bool IndexingContext::handleFunction(const FunctionDecl *D) {
+bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) {
   bool isDef = D->isThisDeclarationADefinition();
   bool isContainer = isDef;
   bool isSkipped = false;
@@ -388,31 +594,31 @@ bool IndexingContext::handleFunction(const FunctionDecl *D) {
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleVar(const VarDecl *D) {
+bool CXIndexDataConsumer::handleVar(const VarDecl *D) {
   DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
                  /*isContainer=*/false);
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleField(const FieldDecl *D) {
+bool CXIndexDataConsumer::handleField(const FieldDecl *D) {
   DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
                  /*isContainer=*/false);
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleMSProperty(const MSPropertyDecl *D) {
+bool CXIndexDataConsumer::handleMSProperty(const MSPropertyDecl *D) {
   DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
                  /*isContainer=*/false);
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
+bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) {
   DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
                  /*isContainer=*/false);
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleTagDecl(const TagDecl *D) {
+bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) {
   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D))
     return handleCXXRecordDecl(CXXRD, D);
 
@@ -421,13 +627,13 @@ bool IndexingContext::handleTagDecl(const TagDecl *D) {
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleTypedefName(const TypedefNameDecl *D) {
+bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) {
   DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true,
                  /*isContainer=*/false);
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
+bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) {
   // For @class forward declarations, suppress them the same way as references.
   if (!D->isThisDeclarationADefinition()) {
     if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
@@ -475,7 +681,7 @@ bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
   return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo);
 }
 
-bool IndexingContext::handleObjCImplementation(
+bool CXIndexDataConsumer::handleObjCImplementation(
                                               const ObjCImplementationDecl *D) {
   ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
                       /*isRedeclaration=*/true,
@@ -483,7 +689,7 @@ bool IndexingContext::handleObjCImplementation(
   return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
 }
 
-bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
+bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) {
   if (!D->isThisDeclarationADefinition()) {
     if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
       return false; // already occurred.
@@ -512,7 +718,7 @@ bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
   return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo);
 }
 
-bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
+bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) {
   ScratchAlloc SA(*this);
 
   ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
@@ -544,7 +750,7 @@ bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
   return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
 }
 
-bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
+bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
   ScratchAlloc SA(*this);
 
   const ObjCCategoryDecl *CatD = D->getCategoryDecl();
@@ -573,7 +779,7 @@ bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
   return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
 }
 
-bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
+bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D) {
   bool isDef = D->isThisDeclarationADefinition();
   bool isContainer = isDef;
   bool isSkipped = false;
@@ -589,7 +795,7 @@ bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleSynthesizedObjCProperty(
+bool CXIndexDataConsumer::handleSynthesizedObjCProperty(
                                                 const ObjCPropertyImplDecl *D) {
   ObjCPropertyDecl *PD = D->getPropertyDecl();
   auto *DC = D->getDeclContext();
@@ -597,7 +803,7 @@ bool IndexingContext::handleSynthesizedObjCProperty(
                          dyn_cast<NamedDecl>(DC), DC);
 }
 
-bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
+bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
                                                   SourceLocation Loc,
                                                  const DeclContext *LexicalDC) {
   DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true,
@@ -605,7 +811,7 @@ bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
   return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC, LexicalDC);
 }
 
-bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
+bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) {
   ScratchAlloc SA(*this);
 
   ObjCPropertyDeclInfo DInfo;
@@ -630,31 +836,31 @@ bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleNamespace(const NamespaceDecl *D) {
+bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
   DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
                  /*isDefinition=*/true,
                  /*isContainer=*/true);
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleClassTemplate(const ClassTemplateDecl *D) {
+bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) {
   return handleCXXRecordDecl(D->getTemplatedDecl(), D);
 }
 
-bool IndexingContext::handleFunctionTemplate(const FunctionTemplateDecl *D) {
+bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) {
   DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
                  /*isDefinition=*/D->isThisDeclarationADefinition(),
                  /*isContainer=*/D->isThisDeclarationADefinition());
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
+bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
   DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
                  /*isDefinition=*/true, /*isContainer=*/false);
   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
 }
 
-bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
+bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
                                       const NamedDecl *Parent,
                                       const DeclContext *DC,
                                       const Expr *E,
@@ -667,7 +873,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
   return handleReference(D, Loc, Cursor, Parent, DC, E, Kind);
 }
 
-bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
+bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
                                       CXCursor Cursor,
                                       const NamedDecl *Parent,
                                       const DeclContext *DC,
@@ -713,7 +919,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
   return true;
 }
 
-bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const {
+bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const {
   if (Loc.isInvalid())
     return true;
   SourceManager &SM = Ctx->getSourceManager();
@@ -722,7 +928,7 @@ bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const {
   return SM.getFileEntryForID(FID) == nullptr;
 }
 
-void IndexingContext::addContainerInMap(const DeclContext *DC,
+void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC,
                                         CXIdxClientContainer container) {
   if (!DC)
     return;
@@ -741,7 +947,7 @@ void IndexingContext::addContainerInMap(const DeclContext *DC,
     ContainerMap.erase(I);
 }
 
-CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const {
+CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const {
   if (!D)
     return nullptr;
   EntityMapTy::const_iterator I = EntityMap.find(D);
@@ -750,13 +956,13 @@ CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const {
   return I->second;
 }
 
-void IndexingContext::setClientEntity(const Decl *D, CXIdxClientEntity client) {
+void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) {
   if (!D)
     return;
   EntityMap[D] = client;
 }
 
-bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD,
+bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD,
                                           const NamedDecl *OrigD) {
   if (RD->isThisDeclarationADefinition()) {
     ScratchAlloc SA(*this);
@@ -789,7 +995,7 @@ bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD,
   return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo);
 }
 
-bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D,
+bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D,
                                                  SourceLocation Loc) {
   if (!D || Loc.isInvalid())
     return true;
@@ -811,7 +1017,7 @@ bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D,
   return !res.second; // already in map
 }
 
-const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
+const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const {
   assert(D);
   D = cast<NamedDecl>(D->getCanonicalDecl());
 
@@ -834,7 +1040,7 @@ const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
 }
 
 const DeclContext *
-IndexingContext::getEntityContainer(const Decl *D) const {
+CXIndexDataConsumer::getEntityContainer(const Decl *D) const {
   const DeclContext *DC = dyn_cast<DeclContext>(D);
   if (DC)
     return DC;
@@ -850,7 +1056,7 @@ IndexingContext::getEntityContainer(const Decl *D) const {
 }
 
 CXIdxClientContainer
-IndexingContext::getClientContainerForDC(const DeclContext *DC) const {
+CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const {
   if (!DC)
     return nullptr;
 
@@ -861,7 +1067,7 @@ IndexingContext::getClientContainerForDC(const DeclContext *DC) const {
   return I->second;
 }
 
-CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) {
+CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) {
   if (!File)
     return nullptr;
 
@@ -872,17 +1078,17 @@ CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) {
   return nullptr;
 }
 
-CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const {
+CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const {
   CXIdxLoc idxLoc =  { {nullptr, nullptr}, 0 };
   if (Loc.isInvalid())
     return idxLoc;
 
-  idxLoc.ptr_data[0] = const_cast<IndexingContext *>(this);
+  idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this);
   idxLoc.int_data = Loc.getRawEncoding();
   return idxLoc;
 }
 
-void IndexingContext::translateLoc(SourceLocation Loc,
+void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
                                    CXIdxClientFile *indexFile, CXFile *file,
                                    unsigned *line, unsigned *column,
                                    unsigned *offset) {
@@ -912,7 +1118,12 @@ void IndexingContext::translateLoc(SourceLocation Loc,
     *offset = FileOffset;
 }
 
-void IndexingContext::getEntityInfo(const NamedDecl *D,
+static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K);
+static CXIdxEntityCXXTemplateKind
+getEntityKindFromSymbolCXXTemplateKind(SymbolCXXTemplateKind K);
+static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
+
+void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
                                     EntityInfo &EntityInfo,
                                     ScratchAlloc &SA) {
   if (!D)
@@ -922,9 +1133,12 @@ void IndexingContext::getEntityInfo(const NamedDecl *D,
   EntityInfo.cursor = getCursor(D);
   EntityInfo.Dcl = D;
   EntityInfo.IndexCtx = this;
-  EntityInfo.kind = CXIdxEntity_Unexposed;
-  EntityInfo.templateKind = CXIdxEntity_NonTemplate;
-  EntityInfo.lang = CXIdxEntityLang_C;
+
+  SymbolInfo SymInfo = getSymbolInfo(D);
+  EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind);
+  EntityInfo.templateKind =
+    getEntityKindFromSymbolCXXTemplateKind(SymInfo.TemplateKind);
+  EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang);
 
   if (D->hasAttrs()) {
     EntityInfo.AttrList = AttrListInfo::create(D, *this);
@@ -932,167 +1146,9 @@ void IndexingContext::getEntityInfo(const NamedDecl *D,
     EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs();
   }
 
-  if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
-    switch (TD->getTagKind()) {
-    case TTK_Struct:
-      EntityInfo.kind = CXIdxEntity_Struct; break;
-    case TTK_Union:
-      EntityInfo.kind = CXIdxEntity_Union; break;
-    case TTK_Class:
-      EntityInfo.kind = CXIdxEntity_CXXClass;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    case TTK_Interface:
-      EntityInfo.kind = CXIdxEntity_CXXInterface;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    case TTK_Enum:
-      EntityInfo.kind = CXIdxEntity_Enum; break;
-    }
-
-    if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
-      if (!CXXRec->isCLike())
-        EntityInfo.lang = CXIdxEntityLang_CXX;
-
-    if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
-      EntityInfo.templateKind = CXIdxEntity_TemplatePartialSpecialization;
-    } else if (isa<ClassTemplateSpecializationDecl>(D)) {
-      EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization;
-    }
-
-  } else {
-    switch (D->getKind()) {
-    case Decl::Typedef:
-      EntityInfo.kind = CXIdxEntity_Typedef; break;
-    case Decl::Function:
-      EntityInfo.kind = CXIdxEntity_Function;
-      break;
-    case Decl::ParmVar:
-      EntityInfo.kind = CXIdxEntity_Variable;
-      break;
-    case Decl::Var:
-      EntityInfo.kind = CXIdxEntity_Variable;
-      if (isa<CXXRecordDecl>(D->getDeclContext())) {
-        EntityInfo.kind = CXIdxEntity_CXXStaticVariable;
-        EntityInfo.lang = CXIdxEntityLang_CXX;
-      }
-      break;
-    case Decl::Field:
-      EntityInfo.kind = CXIdxEntity_Field;
-      if (const CXXRecordDecl *
-            CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
-        // FIXME: isPOD check is not sufficient, a POD can contain methods,
-        // we want a isCStructLike check.
-        if (!CXXRec->isPOD())
-          EntityInfo.lang = CXIdxEntityLang_CXX;
-      }
-      break;
-    case Decl::EnumConstant:
-      EntityInfo.kind = CXIdxEntity_EnumConstant; break;
-    case Decl::ObjCInterface:
-      EntityInfo.kind = CXIdxEntity_ObjCClass;
-      EntityInfo.lang = CXIdxEntityLang_ObjC;
-      break;
-    case Decl::ObjCProtocol:
-      EntityInfo.kind = CXIdxEntity_ObjCProtocol;
-      EntityInfo.lang = CXIdxEntityLang_ObjC;
-      break;
-    case Decl::ObjCCategory:
-      EntityInfo.kind = CXIdxEntity_ObjCCategory;
-      EntityInfo.lang = CXIdxEntityLang_ObjC;
-      break;
-    case Decl::ObjCMethod:
-      if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
-        EntityInfo.kind = CXIdxEntity_ObjCInstanceMethod;
-      else
-        EntityInfo.kind = CXIdxEntity_ObjCClassMethod;
-      EntityInfo.lang = CXIdxEntityLang_ObjC;
-      break;
-    case Decl::ObjCProperty:
-      EntityInfo.kind = CXIdxEntity_ObjCProperty;
-      EntityInfo.lang = CXIdxEntityLang_ObjC;
-      break;
-    case Decl::ObjCIvar:
-      EntityInfo.kind = CXIdxEntity_ObjCIvar;
-      EntityInfo.lang = CXIdxEntityLang_ObjC;
-      break;
-    case Decl::Namespace:
-      EntityInfo.kind = CXIdxEntity_CXXNamespace;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    case Decl::NamespaceAlias:
-      EntityInfo.kind = CXIdxEntity_CXXNamespaceAlias;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    case Decl::CXXConstructor:
-      EntityInfo.kind = CXIdxEntity_CXXConstructor;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    case Decl::CXXDestructor:
-      EntityInfo.kind = CXIdxEntity_CXXDestructor;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    case Decl::CXXConversion:
-      EntityInfo.kind = CXIdxEntity_CXXConversionFunction;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    case Decl::CXXMethod: {
-      const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
-      if (MD->isStatic())
-        EntityInfo.kind = CXIdxEntity_CXXStaticMethod;
-      else
-        EntityInfo.kind = CXIdxEntity_CXXInstanceMethod;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    }
-    case Decl::ClassTemplate:
-      EntityInfo.kind = CXIdxEntity_CXXClass;
-      EntityInfo.templateKind = CXIdxEntity_Template;
-      break;
-    case Decl::FunctionTemplate:
-      EntityInfo.kind = CXIdxEntity_Function;
-      EntityInfo.templateKind = CXIdxEntity_Template;
-      if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
-                           cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
-        if (isa<CXXConstructorDecl>(MD))
-          EntityInfo.kind = CXIdxEntity_CXXConstructor;
-        else if (isa<CXXDestructorDecl>(MD))
-          EntityInfo.kind = CXIdxEntity_CXXDestructor;
-        else if (isa<CXXConversionDecl>(MD))
-          EntityInfo.kind = CXIdxEntity_CXXConversionFunction;
-        else {
-          if (MD->isStatic())
-            EntityInfo.kind = CXIdxEntity_CXXStaticMethod;
-          else
-            EntityInfo.kind = CXIdxEntity_CXXInstanceMethod;
-        }
-      }
-      break;
-    case Decl::TypeAliasTemplate:
-      EntityInfo.kind = CXIdxEntity_CXXTypeAlias;
-      EntityInfo.templateKind = CXIdxEntity_Template;
-      break;
-    case Decl::TypeAlias:
-      EntityInfo.kind = CXIdxEntity_CXXTypeAlias;
-      EntityInfo.lang = CXIdxEntityLang_CXX;
-      break;
-    default:
-      break;
-    }
-  }
-
   if (EntityInfo.kind == CXIdxEntity_Unexposed)
     return;
 
-  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    if (FD->getTemplatedKind() ==
-          FunctionDecl::TK_FunctionTemplateSpecialization)
-      EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization;
-  }
-
-  if (EntityInfo.templateKind != CXIdxEntity_NonTemplate)
-    EntityInfo.lang = CXIdxEntityLang_CXX;
-
   if (IdentifierInfo *II = D->getIdentifier()) {
     EntityInfo.name = SA.toCStr(II->getName());
 
@@ -1119,14 +1175,14 @@ void IndexingContext::getEntityInfo(const NamedDecl *D,
   }
 }
 
-void IndexingContext::getContainerInfo(const DeclContext *DC,
+void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC,
                                        ContainerInfo &ContInfo) {
   ContInfo.cursor = getCursor(cast<Decl>(DC));
   ContInfo.DC = DC;
   ContInfo.IndexCtx = this;
 }
 
-CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
+CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
   if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
     return MakeCursorTypeRef(TD, Loc, CXTU);
   if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
@@ -1147,7 +1203,7 @@ CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
   return clang_getNullCursor();
 }
 
-bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
+bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) {
   if (isa<ObjCInterfaceDecl>(D))
     return false;
   if (isa<ObjCCategoryDecl>(D))
@@ -1161,7 +1217,7 @@ bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
   return true;
 }
 
-bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
+bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) {
   if (const ClassTemplateSpecializationDecl *
         SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
     return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
@@ -1171,3 +1227,60 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
   }
   return false;
 }
+
+static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K) {
+  switch (K) {
+  case SymbolKind::Unknown:
+  case SymbolKind::Module:
+  case SymbolKind::Macro:
+    return CXIdxEntity_Unexposed;
+
+  case SymbolKind::Enum: return CXIdxEntity_Enum;
+  case SymbolKind::Struct: return CXIdxEntity_Struct;
+  case SymbolKind::Union: return CXIdxEntity_Union;
+  case SymbolKind::Typedef: return CXIdxEntity_Typedef;
+  case SymbolKind::Function: return CXIdxEntity_Function;
+  case SymbolKind::Variable: return CXIdxEntity_Variable;
+  case SymbolKind::Field: return CXIdxEntity_Field;
+  case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant;
+  case SymbolKind::ObjCClass: return CXIdxEntity_ObjCClass;
+  case SymbolKind::ObjCProtocol: return CXIdxEntity_ObjCProtocol;
+  case SymbolKind::ObjCCategory: return CXIdxEntity_ObjCCategory;
+  case SymbolKind::ObjCInstanceMethod: return CXIdxEntity_ObjCInstanceMethod;
+  case SymbolKind::ObjCClassMethod: return CXIdxEntity_ObjCClassMethod;
+  case SymbolKind::ObjCProperty: return CXIdxEntity_ObjCProperty;
+  case SymbolKind::ObjCIvar: return CXIdxEntity_ObjCIvar;
+  case SymbolKind::CXXClass: return CXIdxEntity_CXXClass;
+  case SymbolKind::CXXNamespace: return CXIdxEntity_CXXNamespace;
+  case SymbolKind::CXXNamespaceAlias: return CXIdxEntity_CXXNamespaceAlias;
+  case SymbolKind::CXXStaticVariable: return CXIdxEntity_CXXStaticVariable;
+  case SymbolKind::CXXStaticMethod: return CXIdxEntity_CXXStaticMethod;
+  case SymbolKind::CXXInstanceMethod: return CXIdxEntity_CXXInstanceMethod;
+  case SymbolKind::CXXConstructor: return CXIdxEntity_CXXConstructor;
+  case SymbolKind::CXXDestructor: return CXIdxEntity_CXXDestructor;
+  case SymbolKind::CXXConversionFunction:
+    return CXIdxEntity_CXXConversionFunction;
+  case SymbolKind::CXXTypeAlias: return CXIdxEntity_CXXTypeAlias;
+  case SymbolKind::CXXInterface: return CXIdxEntity_CXXInterface;
+  }
+}
+
+static CXIdxEntityCXXTemplateKind
+getEntityKindFromSymbolCXXTemplateKind(SymbolCXXTemplateKind K) {
+  switch (K) {
+  case SymbolCXXTemplateKind::NonTemplate: return CXIdxEntity_NonTemplate;
+  case SymbolCXXTemplateKind::Template: return CXIdxEntity_Template;
+  case SymbolCXXTemplateKind::TemplatePartialSpecialization:
+    return CXIdxEntity_TemplatePartialSpecialization;
+  case SymbolCXXTemplateKind::TemplateSpecialization:
+    return CXIdxEntity_TemplateSpecialization;
+  }
+}
+
+static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
+  switch (L) {
+  case SymbolLanguage::C: return CXIdxEntityLang_C;
+  case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
+  case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
+  }
+}
similarity index 91%
rename from clang/tools/libclang/IndexingContext.h
rename to clang/tools/libclang/CXIndexDataConsumer.h
index d1d62c9..308fa79 100644 (file)
@@ -1,4 +1,4 @@
-//===- IndexingContext.h - Higher level API functions -----------*- C++ -*-===//
+//===- CXIndexDataConsumer.h - Index data consumer for libclang--*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,11 +7,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H
-#define LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
 
 #include "CXCursor.h"
 #include "Index_Internal.h"
+#include "clang/Index/IndexDataConsumer.h"
 #include "clang/AST/DeclGroup.h"
 #include "clang/AST/DeclObjC.h"
 #include "llvm/ADT/DenseSet.h"
@@ -27,14 +28,14 @@ namespace clang {
   class ClassTemplateSpecializationDecl;
 
 namespace cxindex {
-  class IndexingContext;
+  class CXIndexDataConsumer;
   class AttrListInfo;
 
 class ScratchAlloc {
-  IndexingContext &IdxCtx;
+  CXIndexDataConsumer &IdxCtx;
 
 public:
-  explicit ScratchAlloc(IndexingContext &indexCtx);
+  explicit ScratchAlloc(CXIndexDataConsumer &indexCtx);
   ScratchAlloc(const ScratchAlloc &SA);
 
   ~ScratchAlloc();
@@ -48,7 +49,7 @@ public:
 
 struct EntityInfo : public CXIdxEntityInfo {
   const NamedDecl *Dcl;
-  IndexingContext *IndexCtx;
+  CXIndexDataConsumer *IndexCtx;
   IntrusiveRefCntPtr<AttrListInfo> AttrList;
 
   EntityInfo() {
@@ -60,7 +61,7 @@ struct EntityInfo : public CXIdxEntityInfo {
 
 struct ContainerInfo : public CXIdxContainerInfo {
   const DeclContext *DC;
-  IndexingContext *IndexCtx;
+  CXIndexDataConsumer *IndexCtx;
 };
   
 struct DeclInfo : public CXIdxDeclInfo {
@@ -248,10 +249,10 @@ class AttrListInfo {
   AttrListInfo(const AttrListInfo &) = delete;
   void operator=(const AttrListInfo &) = delete;
 public:
-  AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
+  AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx);
 
   static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
-                                                 IndexingContext &IdxCtx);
+                                                 CXIndexDataConsumer &IdxCtx);
 
   const CXIdxAttrInfo *const *getAttrs() const {
     if (CXAttrs.empty())
@@ -273,7 +274,7 @@ public:
   }
 };
 
-class IndexingContext {
+class CXIndexDataConsumer : public index::IndexDataConsumer {
   ASTContext *Ctx;
   CXClientData ClientData;
   IndexerCallbacks &CB;
@@ -308,7 +309,7 @@ class IndexingContext {
     }
 
     ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
-                         IndexingContext &IdxCtx,
+                         CXIndexDataConsumer &IdxCtx,
                          ScratchAlloc &SA);
   };
 
@@ -323,7 +324,7 @@ class IndexingContext {
     unsigned getNumBases() const { return (unsigned)CXBases.size(); }
 
     CXXBasesListInfo(const CXXRecordDecl *D,
-                     IndexingContext &IdxCtx, ScratchAlloc &SA);
+                     CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA);
 
   private:
     SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
@@ -332,13 +333,14 @@ class IndexingContext {
   friend class AttrListInfo;
 
 public:
-  IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
+  CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks,
                   unsigned indexOptions, CXTranslationUnit cxTU)
     : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
       IndexOptions(indexOptions), CXTU(cxTU),
       StrScratch(), StrAdapterCount(0) { }
 
   ASTContext &getASTContext() const { return *Ctx; }
+  CXTranslationUnit getCXTU() const { return CXTU; }
 
   void setASTContext(ASTContext &ctx);
   void setPreprocessor(Preprocessor &PP);
@@ -391,6 +393,8 @@ public:
   void indexBody(const Stmt *S, const NamedDecl *Parent,
                  const DeclContext *DC = nullptr);
 
+  void indexDiagnostics();
+
   void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
 
   bool handleFunction(const FunctionDecl *FD);
@@ -458,6 +462,17 @@ public:
   static bool isTemplateImplicitInstantiation(const Decl *D);
 
 private:
+  bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+                           ArrayRef<index::SymbolRelation> Relations,
+                           FileID FID, unsigned Offset,
+                           ASTNodeInfo ASTNode) override;
+
+  bool handleModuleOccurence(const ImportDecl *ImportD,
+                             index::SymbolRoleSet Roles,
+                             FileID FID, unsigned Offset) override;
+
+  void finish() override;
+
   bool handleDecl(const NamedDecl *D,
                   SourceLocation Loc, CXCursor Cursor,
                   DeclInfo &DInfo,
@@ -495,7 +510,7 @@ private:
   static bool shouldIgnoreIfImplicit(const Decl *D);
 };
 
-inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
+inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) {
   ++IdxCtx.StrAdapterCount;
 }
 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
diff --git a/clang/tools/libclang/IndexBody.cpp b/clang/tools/libclang/IndexBody.cpp
deleted file mode 100644 (file)
index 58dc117..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IndexingContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-
-using namespace clang;
-using namespace cxindex;
-
-namespace {
-
-class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
-  IndexingContext &IndexCtx;
-  const NamedDecl *Parent;
-  const DeclContext *ParentDC;
-
-  typedef RecursiveASTVisitor<BodyIndexer> base;
-public:
-  BodyIndexer(IndexingContext &indexCtx,
-              const NamedDecl *Parent, const DeclContext *DC)
-    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
-  
-  bool shouldWalkTypesOfTypeLocs() const { return false; }
-
-  bool TraverseTypeLoc(TypeLoc TL) {
-    IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
-    return true;
-  }
-
-  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
-    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
-    return true;
-  }
-
-  bool VisitDeclRefExpr(DeclRefExpr *E) {
-    IndexCtx.handleReference(E->getDecl(), E->getLocation(),
-                             Parent, ParentDC, E);
-    return true;
-  }
-
-  bool VisitMemberExpr(MemberExpr *E) {
-    IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(),
-                             Parent, ParentDC, E);
-    return true;
-  }
-
-  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
-    IndexCtx.handleReference(E->getDecl(), E->getLocation(),
-                             Parent, ParentDC, E);
-    return true;
-  }
-
-  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
-    if (ObjCMethodDecl *MD = E->getMethodDecl())
-      IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
-                               Parent, ParentDC, E,
-                               E->isImplicit() ? CXIdxEntityRef_Implicit
-                                               : CXIdxEntityRef_Direct);
-    return true;
-  }
-
-  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
-    if (E->isExplicitProperty())
-      IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
-                               Parent, ParentDC, E);
-
-    // No need to do a handleReference for the objc method, because there will
-    // be a message expr as part of PseudoObjectExpr.
-    return true;
-  }
-
-  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
-    IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent,
-                             ParentDC, E, CXIdxEntityRef_Direct);
-    return true;
-  }
-
-  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
-    IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
-                             Parent, ParentDC, E, CXIdxEntityRef_Direct);
-    return true;
-  }
-
-  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
-    if (ObjCMethodDecl *MD = E->getBoxingMethod())
-      IndexCtx.handleReference(MD, E->getLocStart(),
-                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
-    return true;
-  }
-  
-  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
-    if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod())
-      IndexCtx.handleReference(MD, E->getLocStart(),
-                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
-    return true;
-  }
-
-  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
-    if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod())
-      IndexCtx.handleReference(MD, E->getLocStart(),
-                               Parent, ParentDC, E, CXIdxEntityRef_Implicit);
-    return true;
-  }
-
-  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
-    IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
-                             Parent, ParentDC, E);
-    return true;
-  }
-
-  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
-                                   DataRecursionQueue *Q = nullptr) {
-    if (E->getOperatorLoc().isInvalid())
-      return true; // implicit.
-    return base::TraverseCXXOperatorCallExpr(E, Q);
-  }
-
-  bool VisitDeclStmt(DeclStmt *S) {
-    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
-      IndexCtx.indexDeclGroupRef(S->getDeclGroup());
-      return true;
-    }
-
-    DeclGroupRef DG = S->getDeclGroup();
-    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
-      const Decl *D = *I;
-      if (!D)
-        continue;
-      if (!IndexCtx.isFunctionLocalDecl(D))
-        IndexCtx.indexTopLevelDecl(D);
-    }
-
-    return true;
-  }
-
-  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
-    if (C->capturesThis() || C->capturesVLAType())
-      return true;
-
-    if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
-      IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), Parent,
-                               ParentDC);
-
-    // FIXME: Lambda init-captures.
-    return true;
-  }
-
-  // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
-  // the things that we visit. Make sure to only visit the semantic form.
-  // Also visit things that are in the syntactic form but not the semantic one,
-  // for example the indices in DesignatedInitExprs.
-  bool TraverseInitListExpr(InitListExpr *S) {
-
-    class SyntacticFormIndexer :
-              public RecursiveASTVisitor<SyntacticFormIndexer> {
-      IndexingContext &IndexCtx;
-      const NamedDecl *Parent;
-      const DeclContext *ParentDC;
-
-    public:
-      SyntacticFormIndexer(IndexingContext &indexCtx,
-                            const NamedDecl *Parent, const DeclContext *DC)
-        : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
-
-      bool shouldWalkTypesOfTypeLocs() const { return false; }
-
-      bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
-        for (DesignatedInitExpr::reverse_designators_iterator
-               D = E->designators_rbegin(), DEnd = E->designators_rend();
-               D != DEnd; ++D) {
-          if (D->isFieldDesignator())
-            IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
-                                     Parent, ParentDC, E);
-        }
-        return true;
-      }
-    };
-
-    auto visitForm = [&](InitListExpr *Form) {
-      for (Stmt *SubStmt : Form->children()) {
-        if (!TraverseStmt(SubStmt))
-          return false;
-      }
-      return true;
-    };
-
-    InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
-    InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
-
-    if (SemaForm) {
-      // Visit things present in syntactic form but not the semantic form.
-      if (SyntaxForm) {
-        SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
-      }
-      return visitForm(SemaForm);
-    }
-
-    // No semantic, try the syntactic.
-    if (SyntaxForm) {
-      return visitForm(SyntaxForm);
-    }
-
-    return true;
-  }
-
-};
-
-} // anonymous namespace
-
-void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
-                                const DeclContext *DC) {
-  if (!S)
-    return;
-
-  if (!DC)
-    DC = Parent->getLexicalDeclContext();
-  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
-}
index 01f1b95..d901b53 100644 (file)
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "IndexingContext.h"
+#include "CXIndexDataConsumer.h"
 #include "CIndexDiagnostic.h"
 #include "CIndexer.h"
 #include "CLog.h"
 #include "CXString.h"
 #include "CXTranslationUnit.h"
 #include "clang/AST/ASTConsumer.h"
-#include "clang/AST/DeclVisitor.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Frontend/FrontendAction.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Index/IndexingAction.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/PPCallbacks.h"
 #include "clang/Lex/PPConditionalDirectiveRecord.h"
 #include <cstdio>
 
 using namespace clang;
+using namespace clang::index;
 using namespace cxtu;
 using namespace cxindex;
 
-static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx);
-
 namespace {
 
 //===----------------------------------------------------------------------===//
@@ -224,12 +223,12 @@ private:
 
 class IndexPPCallbacks : public PPCallbacks {
   Preprocessor &PP;
-  IndexingContext &IndexCtx;
+  CXIndexDataConsumer &DataConsumer;
   bool IsMainFileEntered;
 
 public:
-  IndexPPCallbacks(Preprocessor &PP, IndexingContext &indexCtx)
-    : PP(PP), IndexCtx(indexCtx), IsMainFileEntered(false) { }
+  IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer)
+    : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { }
 
   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
                  SrcMgr::CharacteristicKind FileType, FileID PrevFID) override {
@@ -241,7 +240,7 @@ public:
 
     if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) {
       IsMainFileEntered = true;
-      IndexCtx.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
+      DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
     }
   }
 
@@ -252,7 +251,7 @@ public:
                           const Module *Imported) override {
     bool isImport = (IncludeTok.is(tok::identifier) &&
             IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
-    IndexCtx.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
+    DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
                             Imported);
   }
 
@@ -279,18 +278,18 @@ public:
 //===----------------------------------------------------------------------===//
 
 class IndexingConsumer : public ASTConsumer {
-  IndexingContext &IndexCtx;
+  CXIndexDataConsumer &DataConsumer;
   TUSkipBodyControl *SKCtrl;
 
 public:
-  IndexingConsumer(IndexingContext &indexCtx, TUSkipBodyControl *skCtrl)
-    : IndexCtx(indexCtx), SKCtrl(skCtrl) { }
+  IndexingConsumer(CXIndexDataConsumer &dataConsumer, TUSkipBodyControl *skCtrl)
+    : DataConsumer(dataConsumer), SKCtrl(skCtrl) { }
 
   // ASTConsumer Implementation
 
   void Initialize(ASTContext &Context) override {
-    IndexCtx.setASTContext(Context);
-    IndexCtx.startedTranslationUnit();
+    DataConsumer.setASTContext(Context);
+    DataConsumer.startedTranslationUnit();
   }
 
   void HandleTranslationUnit(ASTContext &Ctx) override {
@@ -299,34 +298,7 @@ public:
   }
 
   bool HandleTopLevelDecl(DeclGroupRef DG) override {
-    IndexCtx.indexDeclGroupRef(DG);
-    return !IndexCtx.shouldAbort();
-  }
-
-  /// \brief Handle the specified top-level declaration that occurred inside
-  /// and ObjC container.
-  void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
-    IndexCtx.indexDeclGroupRef(DG);
-  }
-
-  /// \brief This is called by the AST reader when deserializing things.
-  /// The default implementation forwards to HandleTopLevelDecl but we don't
-  /// care about them when indexing, so have an empty definition.
-  void HandleInterestingDecl(DeclGroupRef D) override {}
-
-  void HandleTagDeclDefinition(TagDecl *D) override {
-    if (!IndexCtx.shouldIndexImplicitTemplateInsts())
-      return;
-
-    if (IndexCtx.isTemplateImplicitInstantiation(D))
-      IndexCtx.indexDecl(D);
-  }
-
-  void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override {
-    if (!IndexCtx.shouldIndexImplicitTemplateInsts())
-      return;
-
-    IndexCtx.indexDecl(D);
+    return !DataConsumer.shouldAbort();
   }
 
   bool shouldSkipFunctionBody(Decl *D) override {
@@ -335,7 +307,7 @@ public:
       return true;
     }
 
-    const SourceManager &SM = IndexCtx.getASTContext().getSourceManager();
+    const SourceManager &SM = DataConsumer.getASTContext().getSourceManager();
     SourceLocation Loc = D->getLocation();
     if (Loc.isMacroID())
       return false;
@@ -376,34 +348,29 @@ public:
 //===----------------------------------------------------------------------===//
 
 class IndexingFrontendAction : public ASTFrontendAction {
-  IndexingContext IndexCtx;
-  CXTranslationUnit CXTU;
+  std::shared_ptr<CXIndexDataConsumer> DataConsumer;
 
   SessionSkipBodyData *SKData;
   std::unique_ptr<TUSkipBodyControl> SKCtrl;
 
 public:
-  IndexingFrontendAction(CXClientData clientData,
-                         IndexerCallbacks &indexCallbacks,
-                         unsigned indexOptions,
-                         CXTranslationUnit cxTU,
+  IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer,
                          SessionSkipBodyData *skData)
-    : IndexCtx(clientData, indexCallbacks, indexOptions, cxTU),
-      CXTU(cxTU), SKData(skData) { }
+    : DataConsumer(dataConsumer), SKData(skData) { }
 
   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                  StringRef InFile) override {
     PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
 
     if (!PPOpts.ImplicitPCHInclude.empty()) {
-      IndexCtx.importedPCH(
+      DataConsumer->importedPCH(
                         CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude));
     }
 
-    IndexCtx.setASTContext(CI.getASTContext());
+    DataConsumer->setASTContext(CI.getASTContext());
     Preprocessor &PP = CI.getPreprocessor();
-    PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, IndexCtx));
-    IndexCtx.setPreprocessor(PP);
+    PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, *DataConsumer));
+    DataConsumer->setPreprocessor(PP);
 
     if (SKData) {
       auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager());
@@ -411,15 +378,11 @@ public:
       SKCtrl = llvm::make_unique<TUSkipBodyControl>(*SKData, *PPRec, PP);
     }
 
-    return llvm::make_unique<IndexingConsumer>(IndexCtx, SKCtrl.get());
-  }
-
-  void EndSourceFileAction() override {
-    indexDiagnostics(CXTU, IndexCtx);
+    return llvm::make_unique<IndexingConsumer>(*DataConsumer, SKCtrl.get());
   }
 
   TranslationUnitKind getTranslationUnitKind() override {
-    if (IndexCtx.shouldIndexImplicitTemplateInsts())
+    if (DataConsumer->shouldIndexImplicitTemplateInsts())
       return TU_Complete;
     else
       return TU_Prefix;
@@ -431,6 +394,13 @@ public:
 // clang_indexSourceFileUnit Implementation
 //===----------------------------------------------------------------------===//
 
+static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) {
+  IndexingOptions IdxOpts;
+  if (index_options & CXIndexOpt_IndexFunctionLocalSymbols)
+    IdxOpts.IndexFunctionLocals = true;
+  return IdxOpts;
+}
+
 struct IndexSessionData {
   CXIndex CIdx;
   std::unique_ptr<SessionSkipBodyData> SkipBodyData;
@@ -566,13 +536,17 @@ static CXErrorCode clang_indexSourceFile_Impl(
   if (SkipBodies)
     CInvok->getFrontendOpts().SkipFunctionBodies = true;
 
-  std::unique_ptr<IndexingFrontendAction> IndexAction;
-  IndexAction.reset(new IndexingFrontendAction(client_data, CB,
-                                               index_options, CXTU->getTU(),
-                        SkipBodies ? IdxSession->SkipBodyData.get() : nullptr));
+  auto DataConsumer =
+    std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options,
+                                          CXTU->getTU());
+  auto InterAction = llvm::make_unique<IndexingFrontendAction>(DataConsumer,
+                         SkipBodies ? IdxSession->SkipBodyData.get() : nullptr);
+  std::unique_ptr<FrontendAction> IndexAction;
+  IndexAction = createIndexingAction(std::move(InterAction), DataConsumer,
+                                getIndexingOptionsFromCXOptions(index_options));
 
   // Recover resources if we crash before exiting this method.
-  llvm::CrashRecoveryContextCleanupRegistrar<IndexingFrontendAction>
+  llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction>
     IndexActionCleanup(IndexAction.get());
 
   bool Persistent = requestedToGetTU;
@@ -632,7 +606,7 @@ static CXErrorCode clang_indexSourceFile_Impl(
 // clang_indexTranslationUnit Implementation
 //===----------------------------------------------------------------------===//
 
-static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
+static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) {
   Preprocessor &PP = Unit.getPreprocessor();
   if (!PP.getPreprocessingRecord())
     return;
@@ -655,24 +629,6 @@ static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
   }
 }
 
-static bool topLevelDeclVisitor(void *context, const Decl *D) {
-  IndexingContext &IdxCtx = *static_cast<IndexingContext*>(context);
-  IdxCtx.indexTopLevelDecl(D);
-  return !IdxCtx.shouldAbort();
-}
-
-static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) {
-  Unit.visitLocalTopLevelDecls(&IdxCtx, topLevelDeclVisitor);
-}
-
-static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) {
-  if (!IdxCtx.hasDiagnosticCallback())
-    return;
-
-  CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(TU);
-  IdxCtx.handleDiagnosticSet(DiagSet);
-}
-
 static CXErrorCode clang_indexTranslationUnit_Impl(
     CXIndexAction idxAction, CXClientData client_data,
     IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
@@ -696,19 +652,8 @@ static CXErrorCode clang_indexTranslationUnit_Impl(
                                   ? index_callbacks_size : sizeof(CB);
   memcpy(&CB, client_index_callbacks, ClientCBSize);
 
-  std::unique_ptr<IndexingContext> IndexCtx;
-  IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU));
-
-  // Recover resources if we crash before exiting this method.
-  llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext>
-    IndexCtxCleanup(IndexCtx.get());
-
-  std::unique_ptr<IndexingConsumer> IndexConsumer;
-  IndexConsumer.reset(new IndexingConsumer(*IndexCtx, nullptr));
-
-  // Recover resources if we crash before exiting this method.
-  llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer>
-    IndexConsumerCleanup(IndexConsumer.get());
+  auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB,
+                                                            index_options, TU);
 
   ASTUnit *Unit = cxtu::getASTUnit(TU);
   if (!Unit)
@@ -717,20 +662,21 @@ static CXErrorCode clang_indexTranslationUnit_Impl(
   ASTUnit::ConcurrencyCheck Check(*Unit);
 
   if (const FileEntry *PCHFile = Unit->getPCHFile())
-    IndexCtx->importedPCH(PCHFile);
+    DataConsumer->importedPCH(PCHFile);
 
   FileManager &FileMgr = Unit->getFileManager();
 
   if (Unit->getOriginalSourceFileName().empty())
-    IndexCtx->enteredMainFile(nullptr);
+    DataConsumer->enteredMainFile(nullptr);
   else
-    IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
+    DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
 
-  IndexConsumer->Initialize(Unit->getASTContext());
+  DataConsumer->setASTContext(Unit->getASTContext());
+  DataConsumer->startedTranslationUnit();
 
-  indexPreprocessingRecord(*Unit, *IndexCtx);
-  indexTranslationUnit(*Unit, *IndexCtx);
-  indexDiagnostics(TU, *IndexCtx);
+  indexPreprocessingRecord(*Unit, *DataConsumer);
+  indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options));
+  DataConsumer->indexDiagnostics();
 
   return CXError_Success;
 }
@@ -1015,9 +961,9 @@ void clang_indexLoc_getFileLocation(CXIdxLoc location,
   if (!location.ptr_data[0] || Loc.isInvalid())
     return;
 
-  IndexingContext &IndexCtx =
-      *static_cast<IndexingContext*>(location.ptr_data[0]);
-  IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset);
+  CXIndexDataConsumer &DataConsumer =
+      *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
+  DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset);
 }
 
 CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
@@ -1025,9 +971,9 @@ CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
   if (!location.ptr_data[0] || Loc.isInvalid())
     return clang_getNullLocation();
 
-  IndexingContext &IndexCtx =
-      *static_cast<IndexingContext*>(location.ptr_data[0]);
-  return cxloc::translateSourceLocation(IndexCtx.getASTContext(), Loc);
+  CXIndexDataConsumer &DataConsumer =
+      *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
+  return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
 }
 
 } // end: extern "C"