[cfe-commits] r68838 - in /cfe/trunk: include/clang/Basic/DiagnosticFrontendKinds.td include/clang/Frontend/PCHReader.h include/clang/Lex/Preprocessor.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp lib/Lex/Preprocessor.cpp lib/Sema/SemaDecl.cpp tools/clang-cc/clang-cc.cpp

Douglas Gregor dgregor at apple.com
Fri Apr 10 16:10:46 PDT 2009


Author: dgregor
Date: Fri Apr 10 18:10:45 2009
New Revision: 68838

URL: http://llvm.org/viewvc/llvm-project?rev=68838&view=rev
Log:
Compare the predefines buffer in the PCH file with the predefines
buffer generated for the current translation unit. If they are
different, complain and then ignore the PCH file. This effectively
checks for all compilation options that somehow would affect
preprocessor state (-D, -U, -include, the dreaded -imacros, etc.).

When we do accept the PCH file, throw away the contents of the
predefines buffer rather than parsing them, since all of the results
of that parsing are already stored in the PCH file. This eliminates
the ugliness with the redefinition of __builtin_va_list, among other
things.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Lex/Preprocessor.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/tools/clang-cc/clang-cc.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=68838&r1=68837&r2=68838&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Fri Apr 10 18:10:45 2009
@@ -110,4 +110,9 @@
     "the PCH file was built with %select{no||hybrid}0 garbage collection but "
     "the current translation unit will compiled with %select{no||hybrid}1 "
     "garbage collection">;
+def warn_pch_preprocessor : Warning<
+    "the PCH file was built with different preprocessor definitions than the "
+    "current translation unit">;
+def note_predef_in_pch : Note<
+    "preprocessor definitions in PCH file">;
 }

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Fri Apr 10 18:10:45 2009
@@ -51,6 +51,10 @@
 /// required when traversing the AST. Only those AST nodes that are
 /// actually required will be de-serialized.
 class PCHReader : public ExternalASTSource {
+public:
+  enum PCHReadResult { Success, Failure, IgnorePCH };
+
+private:
   /// \brief The preprocessor that will be loading the source file.
   Preprocessor &PP;
 
@@ -103,10 +107,11 @@
   /// DeclContext.
   DeclContextOffsetsMap DeclContextOffsets;
 
-  enum PCHReadResult { Success, Failure, IgnorePCH };
-
   PCHReadResult ReadPCHBlock();
-  bool ReadSourceManagerBlock();
+  bool CheckPredefinesBuffer(const char *PCHPredef, 
+                             unsigned PCHPredefLen,
+                             FileID PCHBufferID);
+  PCHReadResult ReadSourceManagerBlock();
   bool ReadPreprocessorBlock();
 
   bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
@@ -125,7 +130,7 @@
 
   ~PCHReader();
 
-  bool ReadPCH(const std::string &FileName);
+  PCHReadResult ReadPCH(const std::string &FileName);
 
   /// \brief Resolve a type ID into a type, potentially building a new
   /// type.
@@ -176,6 +181,9 @@
   /// \brief Report a diagnostic.
   DiagnosticBuilder Diag(unsigned DiagID);
 
+  /// \brief Report a diagnostic.
+  DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+
   const IdentifierInfo *GetIdentifierInfo(const RecordData &Record, 
                                           unsigned &Idx);
   DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx);

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=68838&r1=68837&r2=68838&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Fri Apr 10 18:10:45 2009
@@ -788,7 +788,6 @@
 public:
   virtual ~PreprocessorFactory();
   virtual Preprocessor* CreatePreprocessor() = 0;  
-  virtual bool FinishInitialization(Preprocessor *PP, bool usesPCH);
 };
   
 }  // end namespace clang

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Apr 10 18:10:45 2009
@@ -116,27 +116,109 @@
   return true;
 }
 
+/// \brief Check the contents of the predefines buffer against the
+/// contents of the predefines buffer used to build the PCH file.
+///
+/// The contents of the two predefines buffers should be the same. If
+/// not, then some command-line option changed the preprocessor state
+/// and we must reject the PCH file.
+///
+/// \param PCHPredef The start of the predefines buffer in the PCH
+/// file.
+///
+/// \param PCHPredefLen The length of the predefines buffer in the PCH
+/// file.
+///
+/// \param PCHBufferID The FileID for the PCH predefines buffer.
+///
+/// \returns true if there was a mismatch (in which case the PCH file
+/// should be ignored), or false otherwise.
+bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef, 
+                                      unsigned PCHPredefLen,
+                                      FileID PCHBufferID) {
+  const char *Predef = PP.getPredefines().c_str();
+  unsigned PredefLen = PP.getPredefines().size();
+
+  // If the two predefines buffers compare equal, we're done!.
+  if (PredefLen == PCHPredefLen && 
+      strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
+    return false;
+  
+  // The predefines buffers are different. Produce a reasonable
+  // diagnostic showing where they are different.
+
+  // The source locations (potentially in the two different predefines
+  // buffers)
+  SourceLocation Loc1, Loc2;
+  SourceManager &SourceMgr = PP.getSourceManager();
+
+  // Create a source buffer for our predefines string, so
+  // that we can build a diagnostic that points into that
+  // source buffer.
+  FileID BufferID;
+  if (Predef && Predef[0]) {
+    llvm::MemoryBuffer *Buffer
+      = llvm::MemoryBuffer::getMemBuffer(Predef, Predef + PredefLen,
+                                         "<built-in>");
+    BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
+  }
+
+  unsigned MinLen = std::min(PredefLen, PCHPredefLen);
+  std::pair<const char *, const char *> Locations
+    = std::mismatch(Predef, Predef + MinLen, PCHPredef); 
+ 
+  if (Locations.first != Predef + MinLen) {
+    // We found the location in the two buffers where there is a
+    // difference. Form source locations to point there (in both
+    // buffers).
+    unsigned Offset = Locations.first - Predef;
+    Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
+             .getFileLocWithOffset(Offset);
+    Loc2 = SourceMgr.getLocForStartOfFile(PCHBufferID)
+             .getFileLocWithOffset(Offset);
+  } else if (PredefLen > PCHPredefLen) {
+    Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
+             .getFileLocWithOffset(MinLen);
+  } else {
+    Loc1 = SourceMgr.getLocForStartOfFile(PCHBufferID)
+             .getFileLocWithOffset(MinLen);
+  }
+  
+  Diag(Loc1, diag::warn_pch_preprocessor);
+  if (Loc2.isValid())
+    Diag(Loc2, diag::note_predef_in_pch);
+  Diag(diag::note_ignoring_pch) << FileName;
+  return true;
+}
+
 /// \brief Read the source manager block
-bool PCHReader::ReadSourceManagerBlock() {
+PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
   using namespace SrcMgr;
-  if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID))
-    return Error("Malformed source manager block record");
+  if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
+    Error("Malformed source manager block record");
+    return Failure;
+  }
 
   SourceManager &SourceMgr = Context.getSourceManager();
   RecordData Record;
   while (true) {
     unsigned Code = Stream.ReadCode();
     if (Code == llvm::bitc::END_BLOCK) {
-      if (Stream.ReadBlockEnd())
-        return Error("Error at end of Source Manager block");
-      return false;
+      if (Stream.ReadBlockEnd()) {
+        Error("Error at end of Source Manager block");
+        return Failure;
+      }
+
+      return Success;
     }
     
     if (Code == llvm::bitc::ENTER_SUBBLOCK) {
       // No known subblocks, always skip them.
       Stream.ReadSubBlockID();
-      if (Stream.SkipBlock())
-        return Error("Malformed block record");
+      if (Stream.SkipBlock()) {
+        Error("Malformed block record");
+        return Failure;
+      }
       continue;
     }
     
@@ -172,9 +254,15 @@
       Record.clear();
       unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
       assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
-      SourceMgr.createFileIDForMemBuffer(
-          llvm::MemoryBuffer::getMemBuffer(BlobStart, BlobStart + BlobLen - 1,
-                                           Name));
+      llvm::MemoryBuffer *Buffer
+        = llvm::MemoryBuffer::getMemBuffer(BlobStart, 
+                                           BlobStart + BlobLen - 1,
+                                           Name);
+      FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
+
+      if (strcmp(Name, "<built-in>") == 0
+          && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID))
+        return IgnorePCH;
       break;
     }
 
@@ -329,9 +417,16 @@
         break;
 
       case pch::SOURCE_MANAGER_BLOCK_ID:
-        if (ReadSourceManagerBlock()) {
+        switch (ReadSourceManagerBlock()) {
+        case Success:
+          break;
+
+        case Failure:
           Error("Malformed source manager block");
           return Failure;
+
+        case IgnorePCH:
+          return IgnorePCH;
         }
         break;
           
@@ -400,15 +495,17 @@
 
 PCHReader::~PCHReader() { }
 
-bool PCHReader::ReadPCH(const std::string &FileName) {
+PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
   // Set the PCH file name.
   this->FileName = FileName;
 
   // Open the PCH file.
   std::string ErrStr;
   Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
-  if (!Buffer)
-    return Error(ErrStr.c_str());
+  if (!Buffer) {
+    Error(ErrStr.c_str());
+    return IgnorePCH;
+  }
 
   // Initialize the stream
   Stream.init((const unsigned char *)Buffer->getBufferStart(), 
@@ -418,24 +515,30 @@
   if (Stream.Read(8) != 'C' ||
       Stream.Read(8) != 'P' ||
       Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'H')
-    return Error("Not a PCH file");
+      Stream.Read(8) != 'H') {
+    Error("Not a PCH file");
+    return IgnorePCH;
+  }
 
   // We expect a number of well-defined blocks, though we don't necessarily
   // need to understand them all.
   while (!Stream.AtEndOfStream()) {
     unsigned Code = Stream.ReadCode();
     
-    if (Code != llvm::bitc::ENTER_SUBBLOCK)
-      return Error("Invalid record at top-level");
+    if (Code != llvm::bitc::ENTER_SUBBLOCK) {
+      Error("Invalid record at top-level");
+      return Failure;
+    }
 
     unsigned BlockID = Stream.ReadSubBlockID();
     
     // We only know the PCH subblock ID.
     switch (BlockID) {
     case llvm::bitc::BLOCKINFO_BLOCK_ID:
-      if (Stream.ReadBlockInfoBlock())
-        return Error("Malformed BlockInfoBlock");
+      if (Stream.ReadBlockInfoBlock()) {
+        Error("Malformed BlockInfoBlock");
+        return Failure;
+      }
       break;
     case pch::PCH_BLOCK_ID:
       switch (ReadPCHBlock()) {
@@ -443,18 +546,20 @@
         break;
 
       case Failure:
-        return true;
+        return Failure;
 
       case IgnorePCH:
         // FIXME: We could consider reading through to the end of this
         // PCH block, skipping subblocks, to see if there are other
         // PCH blocks elsewhere.
-        return false;
+        return IgnorePCH;
       }
       break;
     default:
-      if (Stream.SkipBlock())
-        return Error("Malformed block record");
+      if (Stream.SkipBlock()) {
+        Error("Malformed block record");
+        return Failure;
+      }
       break;
     }
   }  
@@ -462,13 +567,7 @@
   // Load the translation unit declaration
   ReadDeclRecord(DeclOffsets[0], 0);
 
-  // If everything looks like it will be ok, then the PCH file load succeeded.
-  // Since the PCH file contains everything that is in the preprocessor's
-  // predefines buffer (and we validated that they are the same) clear out the
-  // predefines buffer so that it doesn't get processed again.
-  PP.setPredefines("");
-  
-  return false;
+  return Success;
 }
 
 /// \brief Parse the record that corresponds to a LangOptions data
@@ -875,7 +974,11 @@
 }
 
 DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
-  return PP.getDiagnostics().Report(FullSourceLoc(SourceLocation(),
+  return Diag(SourceLocation(), DiagID);
+}
+
+DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
+  return PP.getDiagnostics().Report(FullSourceLoc(Loc,
                                                   Context.getSourceManager()),
                                     DiagID);
 }

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Fri Apr 10 18:10:45 2009
@@ -872,7 +872,7 @@
   }
 
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
-    pch::TypeID ID;
+    pch::TypeID ID = 0;
     switch (BT->getKind()) {
     case BuiltinType::Void:       ID = pch::PREDEF_TYPE_VOID_ID;       break;
     case BuiltinType::Bool:       ID = pch::PREDEF_TYPE_BOOL_ID;       break;

Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=68838&r1=68837&r2=68838&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Fri Apr 10 18:10:45 2009
@@ -45,10 +45,6 @@
 
 PreprocessorFactory::~PreprocessorFactory() {}
 
-bool PreprocessorFactory::FinishInitialization(Preprocessor *PP, bool UsesPCH) {
-  return false;
-}
-
 Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
                            TargetInfo &target, SourceManager &SM, 
                            HeaderSearch &Headers,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=68838&r1=68837&r2=68838&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Apr 10 18:10:45 2009
@@ -524,22 +524,6 @@
       return false;
   }
 
-  // __builtin_va_list gets redeclared in the built-in definitions
-  // buffer when using PCH. Don't complain about such redefinitions.
-  //
-  // FIXME: The problem here is that the __builtin_va_list declaration
-  // comes in as target-specific text in the predefines buffer, both
-  // in the generation of the PCH file and in the source file. Thus,
-  // we end up with two typedefs for the same type, which is an error
-  // in C. Our hackish solution is to allow redundant typedefs *to the
-  // same type* if the types are defined in the predefined buffer. We
-  // would like to eliminate this ugliness, perhaps by making
-  // __builtin_va_list a real, Sema-supplied declaration rather than
-  // putting its text into the predefines buffer.
-  if (Context.getExternalSource() && 
-      strcmp(SourceMgr.getBufferName(New->getLocation()), "<built-in>") == 0)
-    return false;
-
   Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
   Diag(Old->getLocation(), diag::note_previous_definition);
   return true;

Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=68838&r1=68837&r2=68838&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Fri Apr 10 18:10:45 2009
@@ -1437,50 +1437,46 @@
   TI.getTargetDefines(LangOpts, Buf);
 }
 
-/// InitializePreprocessor - Initialize the preprocessor getting it and the
-/// environment ready to process a single file. This returns true on error.
-///
-static bool InitializePreprocessor(Preprocessor &PP,
-                                   bool InitializeSourceMgr, 
-                                   const std::string &InFile, bool UsesPCH) {
-  FileManager &FileMgr = PP.getFileManager();
-  
+static bool InitializeSourceManager(Preprocessor &PP,
+                                    const std::string &InFile) {
   // Figure out where to get and map in the main file.
   SourceManager &SourceMgr = PP.getSourceManager();
+  FileManager &FileMgr = PP.getFileManager();
+  
+  if (InFile != "-") {
+    const FileEntry *File = FileMgr.getFile(InFile);
+    if (File) SourceMgr.createMainFileID(File, SourceLocation());
+    if (SourceMgr.getMainFileID().isInvalid()) {
+      PP.getDiagnostics().Report(FullSourceLoc(), diag::err_fe_error_reading) 
+        << InFile.c_str();
+      return true;
+    }
+  } else {
+    llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
 
-  if (InitializeSourceMgr) {
-    if (InFile != "-") {
-      const FileEntry *File = FileMgr.getFile(InFile);
-      if (File) SourceMgr.createMainFileID(File, SourceLocation());
-      if (SourceMgr.getMainFileID().isInvalid()) {
-        PP.getDiagnostics().Report(FullSourceLoc(), diag::err_fe_error_reading) 
-          << InFile.c_str();
-        return true;
-      }
-    } else {
-      llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
-
-      // If stdin was empty, SB is null.  Cons up an empty memory
-      // buffer now.
-      if (!SB) {
-        const char *EmptyStr = "";
-        SB = llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<stdin>");
-      }
+    // If stdin was empty, SB is null.  Cons up an empty memory
+    // buffer now.
+    if (!SB) {
+      const char *EmptyStr = "";
+      SB = llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<stdin>");
+    }
 
-      SourceMgr.createMainFileIDForMemBuffer(SB);
-      if (SourceMgr.getMainFileID().isInvalid()) {
-        PP.getDiagnostics().Report(FullSourceLoc(), 
-                                   diag::err_fe_error_reading_stdin);
-        return true;
-      }
+    SourceMgr.createMainFileIDForMemBuffer(SB);
+    if (SourceMgr.getMainFileID().isInvalid()) {
+      PP.getDiagnostics().Report(FullSourceLoc(), 
+                                 diag::err_fe_error_reading_stdin);
+      return true;
     }
   }
 
-  // If the file is using PCH, then the PCH will include all the predefines, no
-  // need to install them now.
-  if (UsesPCH)
-    return false;
-  
+  return false;
+}
+
+/// InitializePreprocessor - Initialize the preprocessor getting it and the
+/// environment ready to process a single file. This returns true on error.
+///
+static bool InitializePreprocessor(Preprocessor &PP,
+                                   const std::string &InFile) {
   std::vector<char> PredefineBuffer;
   
   // Install things like __POWERPC__, __GNUC__, etc into the macro table.
@@ -1721,7 +1717,6 @@
   TargetInfo        &Target;
   SourceManager     &SourceMgr;
   HeaderSearch      &HeaderInfo;
-  bool              InitializeSourceMgr;
   
 public:
   DriverPreprocessorFactory(const std::string &infile,
@@ -1729,7 +1724,7 @@
                             TargetInfo &target, SourceManager &SM,
                             HeaderSearch &Headers)  
   : InFile(infile), Diags(diags), LangInfo(opts), Target(target),
-    SourceMgr(SM), HeaderInfo(Headers), InitializeSourceMgr(true) {}
+    SourceMgr(SM), HeaderInfo(Headers) {}
   
   
   virtual ~DriverPreprocessorFactory() {}
@@ -1766,26 +1761,21 @@
       PTHMgr->setPreprocessor(PP.get());
       PP->setPTHManager(PTHMgr.take());
     }
-    
-    return PP.take();
-  }
 
-  virtual bool FinishInitialization(Preprocessor *PP, bool UsesPCH) {
-    if (InitializePreprocessor(*PP, InitializeSourceMgr, InFile, UsesPCH))
-      return true;
+    if (InitializePreprocessor(*PP, InFile))
+      return 0;
     
     /// FIXME: PP can only handle one callback
     if (ProgAction != PrintPreprocessedInput) {
       std::string ErrStr;
-      bool DFG = CreateDependencyFileGen(PP, ErrStr);
+      bool DFG = CreateDependencyFileGen(PP.get(), ErrStr);
       if (!DFG && !ErrStr.empty()) {
         fprintf(stderr, "%s", ErrStr.c_str());
-        return true;
+        return 0;
       }
     }
 
-    InitializeSourceMgr = false;
-    return false;
+    return PP.take();
   }
 };
 }
@@ -2089,19 +2079,37 @@
     if (!ImplicitIncludePCH.empty()) {
       // The user has asked us to include a precompiled header. Load
       // the precompiled header into the AST context.
-      llvm::OwningPtr<PCHReader> 
-        Reader(new clang::PCHReader(PP, *ContextOwner.get()));
-      if (Reader->ReadPCH(ImplicitIncludePCH))
+      llvm::OwningPtr<PCHReader> Reader(new PCHReader(PP, *ContextOwner.get()));
+      switch (Reader->ReadPCH(ImplicitIncludePCH)) {
+      case PCHReader::Success: {
+        // Attach the PCH reader to the AST context as an external AST
+        // source, so that declarations will be deserialized from the
+        // PCH file as needed.
+        llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
+        ContextOwner->setExternalSource(Source);
+
+        // Clear out the predefines buffer, because all of the
+        // predefines are already in the PCH file.
+        PP.setPredefines("");
+        break;
+      }
+
+      case PCHReader::Failure:
+        // Unrecoverable failure: don't even try to process the input
+        // file.
         return;
 
-      llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
-      ContextOwner->setExternalSource(Source);
+      case PCHReader::IgnorePCH:
+        // No suitable PCH file could be found. Just ignore the
+        // -include-pch option entirely.
+        break;
+      }
 
       // Finish preprocessor initialization. We do this now (rather
       // than earlier) because this initialization creates new source
       // location entries in the source manager, which must come after
       // the source location entries for the PCH file.
-      if (PPF.FinishInitialization(&PP, true /*uses PCH*/))
+      if (InitializeSourceManager(PP, InFile))
         return;
     }
 
@@ -2311,8 +2319,8 @@
     if (!PP)
       continue;
 
-    if (ImplicitIncludePCH.empty()
-        && PPFactory.FinishInitialization(PP.get(), false))
+    if (ImplicitIncludePCH.empty() && 
+        InitializeSourceManager(*PP.get(), InFile))
       continue;
 
     // Create the HTMLDiagnosticsClient if we are using one.  Otherwise,





More information about the cfe-commits mailing list