Keep track of whether declararions were loaded from a precompiled
header or not via a new "PCHLevel" field in Decl. We currently use
this information to help CIndex filter out declarations that came from
a precompiled header (rather than from an AST file). Further down the
road, it can be used to help implement multi-level precompiled
headers.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84267 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 23bbb0c..133a269 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -88,14 +88,24 @@
   CXTranslationUnitIterator Callback;
   CXClientData CData;
   
+  // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
+  // to the visitor. Declarations with a PCH level greater than this value will
+  // be suppressed.
+  unsigned MaxPCHLevel;
+  
   void Call(enum CXCursorKind CK, NamedDecl *ND) {
+    // Filter any declarations that have a PCH level greater than what we allow.
+    if (ND->getPCHLevel() > MaxPCHLevel)
+      return;
+    
     CXCursor C = { CK, ND, 0 };
     Callback(TUnit, C, CData);
   }
 public:
   TUVisitor(CXTranslationUnit CTU, 
-            CXTranslationUnitIterator cback, CXClientData D) : 
-    TUnit(CTU), Callback(cback), CData(D) {}
+            CXTranslationUnitIterator cback, CXClientData D,
+            unsigned MaxPCHLevel) : 
+    TUnit(CTU), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}
   
   void VisitTranslationUnitDecl(TranslationUnitDecl *D) {
     VisitDeclContext(dyn_cast<DeclContext>(D));
@@ -154,16 +164,27 @@
   CXDeclIterator Callback;
   CXClientData CData;
   
+  // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
+  // to the visitor. Declarations with a PCH level greater than this value will
+  // be suppressed.
+  unsigned MaxPCHLevel;
+  
   void Call(enum CXCursorKind CK, NamedDecl *ND) {
     // Disable the callback when the context is equal to the visiting decl.
     if (CDecl == ND && !clang_isReference(CK))
       return;
+    
+    // Filter any declarations that have a PCH level greater than what we allow.
+    if (ND->getPCHLevel() > MaxPCHLevel)
+      return;
+    
     CXCursor C = { CK, ND, 0 };
     Callback(CDecl, C, CData);
   }
 public:
-  CDeclVisitor(CXDecl C, CXDeclIterator cback, CXClientData D) : 
-    CDecl(C), Callback(cback), CData(D) {}
+  CDeclVisitor(CXDecl C, CXDeclIterator cback, CXClientData D, 
+               unsigned MaxPCHLevel) : 
+    CDecl(C), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}
     
   void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
     // Issue callbacks for the containing class.
@@ -242,6 +263,20 @@
   }
 };
 
+class CIndexer : public Indexer {
+public:  
+  explicit CIndexer(Program &prog) : Indexer(prog), OnlyLocalDecls(false) { }
+
+  /// \brief Whether we only want to see "local" declarations (that did not
+  /// come from a previous precompiled header). If false, we want to see all
+  /// declarations.
+  bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+  void setOnlyLocalDecls(bool Local = true) { OnlyLocalDecls = Local; }
+  
+private:
+  bool OnlyLocalDecls;
+};
+  
 }
 
 extern "C" {
@@ -267,13 +302,13 @@
   
   clangPath = ClangPath.c_str();
   
-  return new Indexer(*new Program());
+  return new CIndexer(*new Program());
 }
 
 void clang_disposeIndex(CXIndex CIdx)
 {
   assert(CIdx && "Passed null CXIndex");
-  delete static_cast<Indexer *>(CIdx);
+  delete static_cast<CIndexer *>(CIdx);
 }
 
 // FIXME: need to pass back error info.
@@ -281,12 +316,13 @@
   CXIndex CIdx, const char *ast_filename) 
 {
   assert(CIdx && "Passed null CXIndex");
-  Indexer *CXXIdx = static_cast<Indexer *>(CIdx);
+  CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
   std::string astName(ast_filename);
   std::string ErrMsg;
   
   return ASTUnit::LoadFromPCHFile(astName, CXXIdx->getDiagnostics(),
-                                  CXXIdx->getFileManager(), &ErrMsg);
+                                  CXXIdx->getFileManager(), &ErrMsg,
+                                  CXXIdx->getOnlyLocalDecls());
 }
 
 CXTranslationUnit clang_createTranslationUnitFromSourceFile(
@@ -338,6 +374,10 @@
   delete static_cast<ASTUnit *>(CTUnit);
 }
 
+void clang_wantOnlyLocalDeclarations(CXIndex CIdx) {
+  static_cast<CIndexer *>(CIdx)->setOnlyLocalDecls(true);
+}
+  
 const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)
 {
   assert(CTUnit && "Passed null CXTranslationUnit");
@@ -353,7 +393,8 @@
   ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
   ASTContext &Ctx = CXXUnit->getASTContext();
   
-  TUVisitor DVisit(CTUnit, callback, CData);
+  TUVisitor DVisit(CTUnit, callback, CData, 
+                   CXXUnit->getOnlyLocalDecls()? 1 : Decl::MaxPCHLevel);
   DVisit.Visit(Ctx.getTranslationUnitDecl());
 }
 
@@ -363,7 +404,8 @@
 {
   assert(Dcl && "Passed null CXDecl");
   
-  CDeclVisitor DVisit(Dcl, callback, CData);
+  CDeclVisitor DVisit(Dcl, callback, CData,
+                      static_cast<Decl *>(Dcl)->getPCHLevel());
   DVisit.Visit(static_cast<Decl *>(Dcl));
 }
 
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index ea647b4..cbffbed 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -28,3 +28,4 @@
 _clang_getCursorKindSpelling
 _clang_getDefinitionSpellingAndExtent
 _clang_getTranslationUnitSpelling
+_clang_wantOnlyLocalDeclarations
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 716c15d..bfc8e62 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -86,10 +86,16 @@
   }
   {
   CXIndex Idx = clang_createIndex();
+  if (!strcmp(argv[2], "local"))
+    clang_wantOnlyLocalDeclarations(Idx);
   CXTranslationUnit TU = clang_createTranslationUnit(Idx, argv[1]);
+  if (!TU) {
+    fprintf(stderr, "Unable to load translation unit!\n");
+    return 1;
+  }
   enum CXCursorKind K = CXCursor_NotImplemented;
 
-  if (!strcmp(argv[2], "all")) {
+  if (!strcmp(argv[2], "all") || !strcmp(argv[2], "local")) {
     clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0);
     clang_disposeTranslationUnit(TU);
     return 1;