[cfe-commits] r84267 - in /cfe/trunk: include/clang-c/Index.h include/clang/AST/DeclBase.h include/clang/Frontend/ASTUnit.h lib/Frontend/ASTUnit.cpp lib/Frontend/PCHReaderDecl.cpp lib/Frontend/PCHWriterDecl.cpp test/Index/c-index-pch.c tools/CIndex/CIndex.cpp tools/CIndex/CIndex.exports tools/c-index-test/c-index-test.c

Douglas Gregor dgregor at apple.com
Fri Oct 16 13:01:18 PDT 2009


Author: dgregor
Date: Fri Oct 16 15:01:17 2009
New Revision: 84267

URL: http://llvm.org/viewvc/llvm-project?rev=84267&view=rev
Log:
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.


Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/Frontend/ASTUnit.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
    cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
    cfe/trunk/test/Index/c-index-pch.c
    cfe/trunk/tools/CIndex/CIndex.cpp
    cfe/trunk/tools/CIndex/CIndex.exports
    cfe/trunk/tools/c-index-test/c-index-test.c

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Fri Oct 16 15:01:17 2009
@@ -117,6 +117,17 @@
 );
 void clang_disposeTranslationUnit(CXTranslationUnit);
 
+/**
+ * \brief Indicate to Clang that it should only enumerate "local" declarations
+ * when loading any new translation units.
+ *
+ * A "local" declaration is one that belongs in the translation unit itself and
+ * not in a precompiled header that was used by the translation unit.
+ *
+ * FIXME: Remove this hook.
+ */
+void clang_wantOnlyLocalDeclarations(CXIndex);
+  
 /*
    Usage: clang_loadTranslationUnit(). Will load the toplevel declarations
    within a translation unit, issuing a 'callback' for each one.

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Fri Oct 16 15:01:17 2009
@@ -166,6 +166,15 @@
   bool Used : 1;
 
 protected:
+  /// Access - Used by C++ decls for the access specifier.
+  // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
+  unsigned Access : 2;
+  friend class CXXClassMemberWrapper;
+  
+  // PCHLevel - the "level" of precompiled header/AST file from which this
+  // declaration was built.
+  unsigned PCHLevel : 2;
+  
   /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
   unsigned IdentifierNamespace : 16;
 
@@ -177,16 +186,13 @@
 #endif
 
 protected:
-  /// Access - Used by C++ decls for the access specifier.
-  // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
-  unsigned Access : 2;
-  friend class CXXClassMemberWrapper;
 
   Decl(Kind DK, DeclContext *DC, SourceLocation L)
     : NextDeclInContext(0), DeclCtx(DC),
       Loc(L), DeclKind(DK), InvalidDecl(0),
       HasAttrs(false), Implicit(false), Used(false),
-      IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
+      Access(AS_none), PCHLevel(0),
+      IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
     if (Decl::CollectingStats()) addDeclKind(DK);
   }
 
@@ -274,6 +280,26 @@
   bool isUsed() const { return Used; }
   void setUsed(bool U = true) { Used = U; }
 
+  /// \brief Retrieve the level of precompiled header from which this
+  /// declaration was generated.
+  ///
+  /// The PCH level of a declaration describes where the declaration originated
+  /// from. A PCH level of 0 indicates that the declaration was not from a 
+  /// precompiled header. A PCH level of 1 indicates that the declaration was
+  /// from a top-level precompiled header; 2 indicates that the declaration 
+  /// comes from a precompiled header on which the top-level precompiled header
+  /// depends, and so on. 
+  unsigned getPCHLevel() const { return PCHLevel; }
+
+  /// \brief The maximum PCH level that any declaration may have.
+  static const unsigned MaxPCHLevel = 3;
+  
+  /// \brief Set the PCH level of this declaration.
+  void setPCHLevel(unsigned Level) { 
+    assert(Level < MaxPCHLevel && "PCH level exceeds the maximum");
+    PCHLevel = Level;
+  }
+  
   unsigned getIdentifierNamespace() const {
     return IdentifierNamespace;
   }

Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Fri Oct 16 15:01:17 2009
@@ -40,6 +40,11 @@
   llvm::OwningPtr<ASTContext>       Ctx;
   bool                              tempFile;
   
+  // OnlyLocalDecls - when true, walking this AST should only visit declarations
+  // that come from the AST itself, not from included precompiled headers.
+  // FIXME: This is temporary; eventually, CIndex will always do this.
+  bool                              OnlyLocalDecls;
+  
   ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
   ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
   ASTUnit(Diagnostic &_Diag);
@@ -65,6 +70,8 @@
 
   void unlinkTemporaryFile() { tempFile = true; }
   
+  bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+  
   /// \brief Create a ASTUnit from a PCH file.
   ///
   /// \param Filename - The PCH file to load.
@@ -80,7 +87,8 @@
   static ASTUnit *LoadFromPCHFile(const std::string &Filename,
                                   Diagnostic &Diags,
                                   FileManager &FileMgr,
-                                  std::string *ErrMsg = 0);
+                                  std::string *ErrMsg = 0,
+                                  bool OnlyLocalDecls = false);
 };
 
 } // namespace clang

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Fri Oct 16 15:01:17 2009
@@ -94,9 +94,10 @@
 ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
                                   Diagnostic &Diags,
                                   FileManager &FileMgr,
-                                  std::string *ErrMsg) {
+                                  std::string *ErrMsg,
+                                  bool OnlyLocalDecls) {
   llvm::OwningPtr<ASTUnit> AST(new ASTUnit(Diags));
-
+  AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->HeaderInfo.reset(new HeaderSearch(FileMgr));
 
   // Gather Info for preprocessor construction later on.

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Fri Oct 16 15:01:17 2009
@@ -86,6 +86,7 @@
   D->setImplicit(Record[Idx++]);
   D->setUsed(Record[Idx++]);
   D->setAccess((AccessSpecifier)Record[Idx++]);
+  D->setPCHLevel(Record[Idx++] + 1);
 }
 
 void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {

Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Oct 16 15:01:17 2009
@@ -88,6 +88,7 @@
   Record.push_back(D->isImplicit());
   Record.push_back(D->isUsed());
   Record.push_back(D->getAccess());
+  Record.push_back(D->getPCHLevel());
 }
 
 void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
@@ -448,6 +449,7 @@
       !D->isImplicit() &&
       !D->isUsed() &&
       D->getAccess() == AS_none &&
+      D->getPCHLevel() == 0 &&
       D->getStorageClass() == 0 &&
       !D->hasCXXDirectInitializer() && // Can params have this ever?
       D->getObjCDeclQualifier() == 0)
@@ -523,6 +525,7 @@
   Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit
   Abv->Add(BitCodeAbbrevOp(0));                       // isUsed
   Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
+  Abv->Add(BitCodeAbbrevOp(0));                       // PCH level
 
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier

Modified: cfe/trunk/test/Index/c-index-pch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/c-index-pch.c?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/test/Index/c-index-pch.c (original)
+++ cfe/trunk/test/Index/c-index-pch.c Fri Oct 16 15:01:17 2009
@@ -1,7 +1,14 @@
 // RUN: clang-cc -emit-pch -x c -o %t.pch %S/c-index-pch.h &&
 // RUN: clang-cc -include-pch %t.pch -x c -emit-pch -o %t.ast %s &&
-// RUN: c-index-test %t.ast all | FileCheck -check-prefix=ALL %s
-// CHECK-ALL: FunctionDecl=foo
-// CHECK-ALL: VarDecl=bar
-// CHECK-ALL: FunctionDecl=wibble
+// RUN: c-index-test %t.ast all | FileCheck -check-prefix=ALL %s &&
+// RUN: c-index-test %t.ast local | FileCheck -check-prefix=LOCAL %s
+// ALL: FunctionDecl=foo
+// ALL: VarDecl=bar
+// ALL: FunctionDecl=wibble
+// ALL: FunctionDecl=wonka
+// LOCAL-NOT: FunctionDecl=foo
+// LOCAL-NOT: VarDecl=bar
+// LOCAL: FunctionDecl=wibble
+// LOCAL: FunctionDecl=wonka
 void wibble(int i);
+void wonka(float);

Modified: cfe/trunk/tools/CIndex/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.cpp?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Fri Oct 16 15:01:17 2009
@@ -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));
 }
 

Modified: cfe/trunk/tools/CIndex/CIndex.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.exports?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.exports (original)
+++ cfe/trunk/tools/CIndex/CIndex.exports Fri Oct 16 15:01:17 2009
@@ -28,3 +28,4 @@
 _clang_getCursorKindSpelling
 _clang_getDefinitionSpellingAndExtent
 _clang_getTranslationUnitSpelling
+_clang_wantOnlyLocalDeclarations

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=84267&r1=84266&r2=84267&view=diff

==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Fri Oct 16 15:01:17 2009
@@ -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;





More information about the cfe-commits mailing list