[cfe-commits] r109823 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Frontend/ lib/Basic/ lib/Frontend/ test/PCH/ test/PCH/Inputs/

Sebastian Redl sebastian.redl at getdesigned.at
Thu Jul 29 17:29:30 PDT 2010


Author: cornedbee
Date: Thu Jul 29 19:29:29 2010
New Revision: 109823

URL: http://llvm.org/viewvc/llvm-project?rev=109823&view=rev
Log:
Make macro weirdness in chained PCH work. This required changing the way PCHReader and PCHWriter are initialized to correctly pick up all initializer. On the upside, this means that there is far less repetition in the dependent PCH now.

Added:
    cfe/trunk/test/PCH/Inputs/chain-macro-override1.h
    cfe/trunk/test/PCH/Inputs/chain-macro-override2.h
    cfe/trunk/test/PCH/chain-macro-override.c
Modified:
    cfe/trunk/include/clang/AST/ASTConsumer.h
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Frontend/ASTConsumers.h
    cfe/trunk/include/clang/Frontend/CompilerInstance.h
    cfe/trunk/include/clang/Frontend/PCHDeserializationListener.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/lib/Basic/IdentifierTable.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Frontend/FrontendAction.cpp
    cfe/trunk/lib/Frontend/FrontendActions.cpp
    cfe/trunk/lib/Frontend/GeneratePCH.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp

Modified: cfe/trunk/include/clang/AST/ASTConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTConsumer.h?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTConsumer.h (original)
+++ cfe/trunk/include/clang/AST/ASTConsumer.h Thu Jul 29 19:29:29 2010
@@ -18,9 +18,10 @@
   class ASTContext;
   class CXXRecordDecl;
   class DeclGroupRef;
-  class TagDecl;
   class HandleTagDeclDefinition;
+  class PCHDeserializationListener; // layering violation because void* is ugly
   class SemaConsumer; // layering violation required for safe SemaConsumer
+  class TagDecl;
   class VarDecl;
 
 /// ASTConsumer - This is an abstract interface that should be implemented by
@@ -80,6 +81,12 @@
   /// it was actually used.
   virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
 
+  /// \brief If the consumer is interested in entities being deserialized from
+  /// PCH, it should return a pointer to a PCHDeserializationListener here.
+  ///
+  /// The return type is void* because PCHDS lives in Frontend.
+  virtual PCHDeserializationListener *GetPCHDeserializationListener() { return 0; }
+
   /// PrintStats - If desired, print any statistics.
   virtual void PrintStats() {}
 

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Thu Jul 29 19:29:29 2010
@@ -59,7 +59,9 @@
   bool IsPoisoned             : 1; // True if identifier is poisoned.
   bool IsCPPOperatorKeyword   : 1; // True if ident is a C++ operator keyword.
   bool NeedsHandleIdentifier  : 1; // See "RecomputeNeedsHandleIdentifier".
-  // 9 bits left in 32-bit word.
+  bool IsFromPCH              : 1; // True if identfier first appeared in a PCH
+                                   // and wasn't modified since.
+  // 8 bits left in 32-bit word.
   void *FETokenInfo;               // Managed by the language front-end.
   llvm::StringMapEntry<IdentifierInfo*> *Entry;
 
@@ -125,6 +127,7 @@
       NeedsHandleIdentifier = 1;
     else
       RecomputeNeedsHandleIdentifier();
+    IsFromPCH = false;
   }
 
   /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API
@@ -186,6 +189,7 @@
       NeedsHandleIdentifier = 1;
     else
       RecomputeNeedsHandleIdentifier();
+    IsFromPCH = false;
   }
 
   /// isPoisoned - Return true if this token has been poisoned.
@@ -213,6 +217,12 @@
   /// know that HandleIdentifier will not affect the token.
   bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
 
+  /// isFromPCH - Return true if the identifier in its current state was loaded
+  /// from a PCH file.
+  bool isFromPCH() const { return IsFromPCH; }
+
+  void setIsFromPCH(bool FromPCH = true) { IsFromPCH = FromPCH; }
+
 private:
   /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does
   /// several special (but rare) things to identifiers of various sorts.  For
@@ -321,35 +331,33 @@
     return get(llvm::StringRef(Name, NameLen));
   }
 
-  /// \brief Creates a new IdentifierInfo from the given string.
+  /// \brief Gets an IdentifierInfo for the given name without consulting
+  ///        external sources.
   ///
-  /// This is a lower-level version of get() that requires that this
-  /// identifier not be known previously and that does not consult an
-  /// external source for identifiers. In particular, external
-  /// identifier sources can use this routine to build IdentifierInfo
-  /// nodes and then introduce additional information about those
-  /// identifiers.
-  IdentifierInfo &CreateIdentifierInfo(const char *NameStart,
-                                       const char *NameEnd) {
+  /// This is a version of get() meant for external sources that want to
+  /// introduce or modify an identifier. If they called get(), they would
+  /// likely end up in a recursion.
+  IdentifierInfo &getOwn(const char *NameStart, const char *NameEnd) {
     llvm::StringMapEntry<IdentifierInfo*> &Entry =
       HashTable.GetOrCreateValue(NameStart, NameEnd);
 
     IdentifierInfo *II = Entry.getValue();
-    assert(!II && "IdentifierInfo already exists");
+    if (!II) {
 
-    // Lookups failed, make a new IdentifierInfo.
-    void *Mem = getAllocator().Allocate<IdentifierInfo>();
-    II = new (Mem) IdentifierInfo();
-    Entry.setValue(II);
-
-    // Make sure getName() knows how to find the IdentifierInfo
-    // contents.
-    II->Entry = &Entry;
+      // Lookups failed, make a new IdentifierInfo.
+      void *Mem = getAllocator().Allocate<IdentifierInfo>();
+      II = new (Mem) IdentifierInfo();
+      Entry.setValue(II);
+
+      // Make sure getName() knows how to find the IdentifierInfo
+      // contents.
+      II->Entry = &Entry;
+    }
 
     return *II;
   }
-  IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) {
-    return CreateIdentifierInfo(Name.begin(), Name.end());
+  IdentifierInfo &getOwn(llvm::StringRef Name) {
+    return getOwn(Name.begin(), Name.end());
   }
 
   typedef HashTableTy::const_iterator iterator;

Modified: cfe/trunk/include/clang/Frontend/ASTConsumers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTConsumers.h?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTConsumers.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTConsumers.h Thu Jul 29 19:29:29 2010
@@ -29,7 +29,6 @@
 class Diagnostic;
 class FileManager;
 class LangOptions;
-class PCHReader;
 class Preprocessor;
 class TargetOptions;
 
@@ -63,7 +62,7 @@
 // times.
 ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
                                 llvm::raw_ostream *OS,
-                                PCHReader *Chain,
+                                bool Chaining,
                                 const char *isysroot = 0);
 
 // Inheritance viewer: for C++ code, creates a graph of the inheritance

Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original)
+++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Thu Jul 29 19:29:29 2010
@@ -97,9 +97,6 @@
   /// The list of active output files.
   std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
 
-  /// The PCH reader. Not owned; the ASTContext owns this.
-  PCHReader *Reader;
-
   void operator=(const CompilerInstance &);  // DO NOT IMPLEMENT
   CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT
 public:
@@ -503,7 +500,8 @@
   /// Create an external AST source to read a PCH file and attach it to the AST
   /// context.
   void createPCHExternalASTSource(llvm::StringRef Path,
-                                  bool DisablePCHValidation);
+                                  bool DisablePCHValidation,
+                                  void *DeserializationListener);
 
   /// Create an external AST source to read a PCH file.
   ///
@@ -511,10 +509,8 @@
   static ExternalASTSource *
   createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot,
                              bool DisablePCHValidation,
-                             Preprocessor &PP, ASTContext &Context);
-
-  /// Get the PCH reader, if any.
-  PCHReader *getPCHReader() { return Reader; }
+                             Preprocessor &PP, ASTContext &Context,
+                             void *DeserializationListener);
 
   /// Create a code completion consumer using the invocation; note that this
   /// will cause the source manager to truncate the input source file at the

Modified: cfe/trunk/include/clang/Frontend/PCHDeserializationListener.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHDeserializationListener.h?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHDeserializationListener.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHDeserializationListener.h Thu Jul 29 19:29:29 2010
@@ -20,6 +20,7 @@
 namespace clang {
 
 class Decl;
+class PCHReader;
 class QualType;
 
 class PCHDeserializationListener {
@@ -27,6 +28,9 @@
   virtual ~PCHDeserializationListener() {}
 
 public:
+  /// \brief Tell the listener about the reader.
+  virtual void SetReader(PCHReader *Reader) = 0;
+
   /// \brief An identifier was deserialized from the PCH.
   virtual void IdentifierRead(pch::IdentID ID, IdentifierInfo *II) = 0;
   /// \brief A type was deserialized from the PCH. The ID here has the qualifier

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Jul 29 19:29:29 2010
@@ -645,9 +645,8 @@
     Listener.reset(listener);
   }
 
-  void setDeserializationListener(PCHDeserializationListener *Listener) {
-    DeserializationListener = Listener;
-  }
+  /// \brief Set the PCH deserialization listener.
+  void setDeserializationListener(PCHDeserializationListener *Listener);
 
   /// \brief Set the Preprocessor to use.
   void setPreprocessor(Preprocessor &pp);
@@ -911,6 +910,12 @@
 
   /// \brief Retrieve the macro definition with the given ID.
   MacroDefinition *getMacroDefinition(pch::IdentID ID);
+
+  /// \brief Erase the macro that's bound to the given IdentifierInfo.
+  void EraseMacro(IdentifierInfo *II);
+
+  /// \brief Check if the given macro identifier is built-in.
+  bool isBuiltinMacro(IdentifierInfo *II);
       
   /// \brief Retrieve the AST context that this PCH reader
   /// supplements.

Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Thu Jul 29 19:29:29 2010
@@ -268,7 +268,7 @@
 public:
   /// \brief Create a new precompiled header writer that outputs to
   /// the given bitstream.
-  PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain);
+  PCHWriter(llvm::BitstreamWriter &Stream);
 
   /// \brief Write a precompiled header for the given semantic analysis.
   ///
@@ -421,6 +421,7 @@
   bool hasChain() const { return Chain; }
 
   // PCHDeserializationListener implementation
+  void SetReader(PCHReader *Reader);
   void IdentifierRead(pch::IdentID ID, IdentifierInfo *II);
   void TypeRead(pch::TypeID ID, QualType T);
   void DeclRead(pch::DeclID ID, const Decl *D);

Modified: cfe/trunk/lib/Basic/IdentifierTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/IdentifierTable.cpp?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)
+++ cfe/trunk/lib/Basic/IdentifierTable.cpp Thu Jul 29 19:29:29 2010
@@ -34,6 +34,7 @@
   IsPoisoned = false;
   IsCPPOperatorKeyword = false;
   NeedsHandleIdentifier = false;
+  IsFromPCH = false;
   FETokenInfo = 0;
   Entry = 0;
 }

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Thu Jul 29 19:29:29 2010
@@ -37,7 +37,7 @@
 using namespace clang;
 
 CompilerInstance::CompilerInstance()
-  : Invocation(new CompilerInvocation()), Reader(0) {
+  : Invocation(new CompilerInvocation()) {
 }
 
 CompilerInstance::~CompilerInstance() {
@@ -251,13 +251,13 @@
 // ExternalASTSource
 
 void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
-                                                  bool DisablePCHValidation) {
+                                                  bool DisablePCHValidation,
+                                                 void *DeserializationListener){
   llvm::OwningPtr<ExternalASTSource> Source;
   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
                                           DisablePCHValidation,
-                                          getPreprocessor(), getASTContext()));
-  // Remember the PCHReader, but in a non-owning way.
-  Reader = static_cast<PCHReader*>(Source.get());
+                                          getPreprocessor(), getASTContext(),
+                                          DeserializationListener));
   getASTContext().setExternalSource(Source);
 }
 
@@ -266,12 +266,15 @@
                                              const std::string &Sysroot,
                                              bool DisablePCHValidation,
                                              Preprocessor &PP,
-                                             ASTContext &Context) {
+                                             ASTContext &Context,
+                                             void *DeserializationListener) {
   llvm::OwningPtr<PCHReader> Reader;
   Reader.reset(new PCHReader(PP, &Context,
                              Sysroot.empty() ? 0 : Sysroot.c_str(),
                              DisablePCHValidation));
 
+  Reader->setDeserializationListener(
+            static_cast<PCHDeserializationListener *>(DeserializationListener));
   switch (Reader->ReadPCH(Path)) {
   case PCHReader::Success:
     // Set the predefines buffer as suggested by the PCH reader. Typically, the

Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendAction.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendAction.cpp Thu Jul 29 19:29:29 2010
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Frontend/FrontendAction.h"
+#include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
@@ -112,19 +113,21 @@
   if (!usesPreprocessorOnly()) {
     CI.createASTContext();
 
-    /// Use PCH? If so, we want the PCHReader active before the consumer
-    /// is created, because the consumer might be interested in the reader
-    /// (e.g. the PCH writer for chaining).
+    llvm::OwningPtr<ASTConsumer> Consumer(CreateASTConsumer(CI, Filename));
+
+    /// Use PCH?
     if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
       assert(hasPCHSupport() && "This action does not have PCH support!");
       CI.createPCHExternalASTSource(
                                 CI.getPreprocessorOpts().ImplicitPCHInclude,
-                                CI.getPreprocessorOpts().DisablePCHValidation);
+                                CI.getPreprocessorOpts().DisablePCHValidation,
+                                CI.getInvocation().getFrontendOpts().ChainedPCH?
+                                 Consumer->GetPCHDeserializationListener() : 0);
       if (!CI.getASTContext().getExternalSource())
         goto failure;
     }
 
-    CI.setASTConsumer(CreateASTConsumer(CI, Filename));
+    CI.setASTConsumer(Consumer.take());
     if (!CI.hasASTConsumer())
       goto failure;
   }

Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Thu Jul 29 19:29:29 2010
@@ -81,11 +81,11 @@
   if (!OS)
     return 0;
 
-  PCHReader *Chain = CI.getInvocation().getFrontendOpts().ChainedPCH ?
-                               CI.getPCHReader() : 0;
+  bool Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
+                  !CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
   const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
                              Sysroot.c_str() : 0;
-  return CreatePCHGenerator(CI.getPreprocessor(), OS, Chain, isysroot);
+  return CreatePCHGenerator(CI.getPreprocessor(), OS, Chaining, isysroot);
 }
 
 ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,

Modified: cfe/trunk/lib/Frontend/GeneratePCH.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/GeneratePCH.cpp?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/GeneratePCH.cpp (original)
+++ cfe/trunk/lib/Frontend/GeneratePCH.cpp Thu Jul 29 19:29:29 2010
@@ -37,19 +37,20 @@
     PCHWriter Writer;
 
   public:
-    PCHGenerator(const Preprocessor &PP, PCHReader *Chain,
+    PCHGenerator(const Preprocessor &PP, bool Chaining,
                  const char *isysroot, llvm::raw_ostream *Out);
     virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
     virtual void HandleTranslationUnit(ASTContext &Ctx);
+    virtual PCHDeserializationListener *GetPCHDeserializationListener();
   };
 }
 
 PCHGenerator::PCHGenerator(const Preprocessor &PP,
-                           PCHReader *Chain,
+                           bool Chaining,
                            const char *isysroot,
                            llvm::raw_ostream *OS)
-  : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0),
-    Stream(Buffer), Writer(Stream, Chain) {
+  : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0),
+    StatCalls(0), Stream(Buffer), Writer(Stream) {
 
   // Install a stat() listener to keep track of all of the stat()
   // calls.
@@ -57,7 +58,7 @@
   // If we have a chain, we want new stat calls only, so install the memorizer
   // *after* the already installed PCHReader's stat cache.
   PP.getFileManager().addStatCache(StatCalls,
-    /*AtBeginning=*/!Chain);
+    /*AtBeginning=*/!Chaining);
 }
 
 void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
@@ -78,9 +79,13 @@
   Buffer.clear();
 }
 
+PCHDeserializationListener *PCHGenerator::GetPCHDeserializationListener() {
+  return &Writer;
+}
+
 ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP,
                                        llvm::raw_ostream *OS,
-                                       PCHReader *Chain,
+                                       bool Chaining,
                                        const char *isysroot) {
-  return new PCHGenerator(PP, Chain, isysroot, OS);
+  return new PCHGenerator(PP, Chaining, isysroot, OS);
 }

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Jul 29 19:29:29 2010
@@ -460,6 +460,13 @@
     NumPreallocatedPreprocessingEntities(0)
 {}
 
+void
+PCHReader::setDeserializationListener(PCHDeserializationListener *Listener) {
+  DeserializationListener = Listener;
+  if (DeserializationListener)
+    DeserializationListener->SetReader(this);
+}
+
 
 namespace {
 class PCHMethodPoolLookupTrait {
@@ -637,9 +644,9 @@
       // and associate it with the persistent ID.
       IdentifierInfo *II = KnownII;
       if (!II)
-        II = &Reader.getIdentifierTable().CreateIdentifierInfo(
-                                                 k.first, k.first + k.second);
+        II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second);
       Reader.SetIdentifierInfo(ID, II);
+      II->setIsFromPCH();
       return II;
     }
 
@@ -662,8 +669,7 @@
     // the new IdentifierInfo.
     IdentifierInfo *II = KnownII;
     if (!II)
-      II = &Reader.getIdentifierTable().CreateIdentifierInfo(
-                                                 k.first, k.first + k.second);
+      II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second);
     Reader.SetIdentifierInfo(ID, II);
 
     // Set or check the various bits in the IdentifierInfo structure.
@@ -683,6 +689,9 @@
       uint32_t Offset = ReadUnalignedLE32(d);
       Reader.ReadMacroRecord(Stream, Offset);
       DataLen -= 4;
+    } else if (II->hasMacroDefinition() && !Reader.isBuiltinMacro(II)) {
+      // A previous part of the chain added a macro, but this part #undefed it.
+      Reader.EraseMacro(II);
     }
 
     // Read all of the declarations visible at global scope with this
@@ -695,6 +704,7 @@
       Reader.SetGloballyVisibleDecls(II, DeclIDs);
     }
 
+    II->setIsFromPCH();
     return II;
   }
 };
@@ -1379,6 +1389,15 @@
   return MacroDefinitionsLoaded[ID];
 }
 
+void PCHReader::EraseMacro(IdentifierInfo *II) {
+  PP->setMacroInfo(II, 0);
+}
+
+bool PCHReader::isBuiltinMacro(IdentifierInfo *II) {
+  assert(II->hasMacroDefinition() && "Identifier is not a macro");
+  return PP->getMacroInfo(II)->isBuiltinMacro();
+}
+
 /// \brief If we are loading a relocatable PCH file, and the filename is
 /// not an absolute path, add the system root to the beginning of the file
 /// name.
@@ -1797,8 +1816,6 @@
          Id != IdEnd; ++Id)
       Identifiers.push_back(Id->second);
     // We need to search the tables in all files.
-    // FIXME: What happens if this stuff changes between files, e.g. the
-    // dependent PCH undefs a macro from the core file?
     for (unsigned J = 0, M = Chain.size(); J != M; ++J) {
       PCHIdentifierLookupTable *IdTable
         = (PCHIdentifierLookupTable *)Chain[J]->IdentifierLookupTable;

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=109823&r1=109822&r2=109823&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Thu Jul 29 19:29:29 2010
@@ -1810,7 +1810,8 @@
       for (IdentifierResolver::iterator D = IdentifierResolver::begin(II),
                                      DEnd = IdentifierResolver::end();
            D != DEnd; ++D)
-        DataLen += sizeof(pch::DeclID);
+        if (!Writer.hasChain() || (*D)->getPCHLevel() == 0)
+          DataLen += sizeof(pch::DeclID);
     }
     clang::io::Emit16(Out, DataLen);
     // We emit the key length after the data length so that every
@@ -1898,9 +1899,7 @@
            ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
          ID != IDEnd; ++ID) {
       assert(ID->first && "NULL identifier in identifier table");
-      // FIXME: Right now, we only write identifiers that are new to this file.
-      // We need to write older identifiers that changed too, though.
-      if (ID->second >= FirstIdentID)
+      if (!Chain || !ID->first->isFromPCH())
         Generator.insert(ID->first, ID->second);
     }
 
@@ -2142,17 +2141,11 @@
   SelectorOffsets[ID - 1] = Offset;
 }
 
-PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain)
-  : Stream(Stream), Chain(Chain), FirstDeclID(1),
+PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
+  : Stream(Stream), Chain(0), FirstDeclID(1),
     FirstTypeID(pch::NUM_PREDEF_TYPE_IDS), FirstIdentID(1),
     CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
     NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) {
-  if (Chain) {
-    Chain->setDeserializationListener(this);
-    FirstDeclID += Chain->getTotalNumDecls();
-    FirstTypeID += Chain->getTotalNumTypes();
-    FirstIdentID += Chain->getTotalNumIdentifiers();
-  }
   NextDeclID = FirstDeclID;
   NextTypeID = FirstTypeID;
   NextIdentID = FirstIdentID;
@@ -2335,6 +2328,13 @@
                               const char *isysroot) {
   using namespace llvm;
 
+  FirstDeclID += Chain->getTotalNumDecls();
+  FirstTypeID += Chain->getTotalNumTypes();
+  FirstIdentID += Chain->getTotalNumIdentifiers();
+  NextDeclID = FirstDeclID;
+  NextTypeID = FirstTypeID;
+  NextIdentID = FirstIdentID;
+
   ASTContext &Context = SemaRef.Context;
   Preprocessor &PP = SemaRef.PP;
 
@@ -2352,9 +2352,6 @@
   // We don't start with the translation unit, but with its decls that
   // don't come from the other PCH.
   const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
-  // The TU was loaded before we managed to register ourselves as a listener.
-  // Thus we need to add it manually.
-  DeclIDs[TU] = 1;
   llvm::SmallVector<pch::DeclID, 64> NewGlobalDecls;
   for (DeclContext::decl_iterator I = TU->noload_decls_begin(),
                                   E = TU->noload_decls_end();
@@ -2868,6 +2865,15 @@
   AddSourceRange(Base.getSourceRange(), Record);
 }
 
+void PCHWriter::SetReader(PCHReader *Reader) {
+  assert(Reader && "Cannot remove chain");
+  assert(FirstDeclID == NextDeclID &&
+         FirstTypeID == NextTypeID &&
+         FirstIdentID == NextIdentID &&
+         "Setting chain after writing has started.");
+  Chain = Reader;
+}
+
 void PCHWriter::IdentifierRead(pch::IdentID ID, IdentifierInfo *II) {
   IdentifierIDs[II] = ID;
 }

Added: cfe/trunk/test/PCH/Inputs/chain-macro-override1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/Inputs/chain-macro-override1.h?rev=109823&view=auto
==============================================================================
--- cfe/trunk/test/PCH/Inputs/chain-macro-override1.h (added)
+++ cfe/trunk/test/PCH/Inputs/chain-macro-override1.h Thu Jul 29 19:29:29 2010
@@ -0,0 +1,4 @@
+void f() __attribute__((unavailable));
+void g();
+#define g() f()
+#define h() f()

Added: cfe/trunk/test/PCH/Inputs/chain-macro-override2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/Inputs/chain-macro-override2.h?rev=109823&view=auto
==============================================================================
--- cfe/trunk/test/PCH/Inputs/chain-macro-override2.h (added)
+++ cfe/trunk/test/PCH/Inputs/chain-macro-override2.h Thu Jul 29 19:29:29 2010
@@ -0,0 +1,4 @@
+#define f() g()
+#undef g
+#undef h
+#define h() g()

Added: cfe/trunk/test/PCH/chain-macro-override.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/chain-macro-override.c?rev=109823&view=auto
==============================================================================
--- cfe/trunk/test/PCH/chain-macro-override.c (added)
+++ cfe/trunk/test/PCH/chain-macro-override.c Thu Jul 29 19:29:29 2010
@@ -0,0 +1,13 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/Inputs/chain-macro-override1.h -include %S/Inputs/chain-macro-override2.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-macro-override1.h
+// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-macro-override2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -include-pch %t2 -fsyntax-only -verify %s
+
+void foo() {
+  f();
+  g();
+  h();
+}





More information about the cfe-commits mailing list