[cfe-commits] r73741 - in /cfe/trunk: include/clang/Frontend/PCHReader.h lib/Frontend/PCHReader.cpp

Argiris Kirtzidis akyrtzi at gmail.com
Thu Jun 18 17:03:24 PDT 2009


Author: akirtzidis
Date: Thu Jun 18 19:03:23 2009
New Revision: 73741

URL: http://llvm.org/viewvc/llvm-project?rev=73741&view=rev
Log:
Make changes to PCHReader to allow reading a PCH file without having a pre-initialized Preprocessor.

-Introduce 'PCHReaderListener' which is an abstract interface for getting various information from the PCHReader.
-If PCHReader is constructed without a Preprocessor, it can still load the file and invoke the callbacks of PCHReaderListener.
-If PCHReader is constructed with an initialized Preprocessor, PCHValidator is used as a PCHReaderListener to validate the contents of the PCH file against the given Preprocessor.

Modified:
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/lib/Frontend/PCHReader.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Jun 18 19:03:23 2009
@@ -53,6 +53,82 @@
 class Preprocessor;
 class Sema;
 class SwitchCase;
+class PCHReader;
+class HeaderFileInfo;
+
+/// \brief Abstract interface for callback invocations by the PCHReader.
+///
+/// While reading a PCH file, the PCHReader will call the methods of the
+/// listener to pass on specific information. Some of the listener methods can
+/// return true to indicate to the PCHReader that the information (and
+/// consequently the PCH file) is invalid.
+class PCHReaderListener {
+public:
+  virtual ~PCHReaderListener();
+  
+  /// \brief Receives the language options.
+  ///
+  /// \returns true to indicate the options are invalid or false otherwise.
+  virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+    return false;
+  }
+  
+  /// \brief Receives the target triple.
+  ///
+  /// \returns true to indicate the target triple is invalid or false otherwise.
+  virtual bool ReadTargetTriple(const std::string &Triple) {
+    return false;
+  }
+  
+  /// \brief Receives the contents of the predefines buffer.
+  ///
+  /// \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.
+  ///
+  /// \param SuggestedPredefines If necessary, additional definitions are added
+  /// here.
+  ///
+  /// \returns true to indicate the predefines are invalid or false otherwise.
+  virtual bool ReadPredefinesBuffer(const char *PCHPredef, 
+                                    unsigned PCHPredefLen,
+                                    FileID PCHBufferID,
+                                    std::string &SuggestedPredefines) {
+    return false;
+  }
+  
+  /// \brief Receives a HeaderFileInfo entry.
+  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {}
+  
+  /// \brief Receives __COUNTER__ value.
+  virtual void ReadCounter(unsigned Value) {}
+};
+
+/// \brief PCHReaderListener implementation to validate the information of
+/// the PCH file against an initialized Preprocessor.
+class PCHValidator : public PCHReaderListener {
+  Preprocessor &PP;
+  PCHReader &Reader;
+  
+  unsigned NumHeaderInfos;
+  
+public:
+  PCHValidator(Preprocessor &PP, PCHReader &Reader)
+    : PP(PP), Reader(Reader), NumHeaderInfos(0) {}
+  
+  virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
+  virtual bool ReadTargetTriple(const std::string &Triple);
+  virtual bool ReadPredefinesBuffer(const char *PCHPredef, 
+                                    unsigned PCHPredefLen,
+                                    FileID PCHBufferID,
+                                    std::string &SuggestedPredefines);
+  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI);
+  virtual void ReadCounter(unsigned Value);
+};
 
 /// \brief Reads a precompiled head containing the contents of a
 /// translation unit.
@@ -75,12 +151,19 @@
   enum PCHReadResult { Success, Failure, IgnorePCH };
 
 private:
+  /// \ brief The receiver of some callbacks invoked by PCHReader.
+  llvm::OwningPtr<PCHReaderListener> Listener;
+  
+  SourceManager &SourceMgr;
+  FileManager &FileMgr;
+  Diagnostic &Diags;
+  
   /// \brief The semantic analysis object that will be processing the
   /// PCH file and the translation unit that uses it.
   Sema *SemaObj;
 
   /// \brief The preprocessor that will be loading the source file.
-  Preprocessor &PP;
+  Preprocessor *PP;
 
   /// \brief The AST context into which we'll read the PCH file.
   ASTContext *Context;
@@ -328,12 +411,33 @@
 public:
   typedef llvm::SmallVector<uint64_t, 64> RecordData;
 
-  explicit PCHReader(Preprocessor &PP, ASTContext *Context);
+  /// \brief Load the PCH file and validate its contents against the given
+  /// Preprocessor.
+  PCHReader(Preprocessor &PP, ASTContext *Context);
+  
+  /// \brief Load the PCH file without using any pre-initialized Preprocessor.
+  ///
+  /// The necessary information to initialize a Preprocessor later can be
+  /// obtained by setting a PCHReaderListener.
+  PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, Diagnostic &Diags);
   ~PCHReader();
 
   /// \brief Load the precompiled header designated by the given file
   /// name.
   PCHReadResult ReadPCH(const std::string &FileName);
+  
+  /// \brief Set the PCH callbacks listener.
+  void setListener(PCHReaderListener *listener) {
+    Listener.reset(listener);
+  }
+  
+  /// \brief Set the Preprocessor to use.
+  void setPreprocessor(Preprocessor &pp) {
+    PP = &pp;
+  }
+  
+  /// \brief Sets and initializes the given Context.
+  void InitializeContext(ASTContext &Context);
 
   /// \brief Retrieve the name of the original source file name 
   const std::string &getOriginalSourceFile() { return OriginalFileName; }

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Jun 18 19:03:23 2009
@@ -36,11 +36,321 @@
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
+// PCH reader validator implementation
+//===----------------------------------------------------------------------===//
+
+PCHReaderListener::~PCHReaderListener() {}
+
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
+  const LangOptions &PPLangOpts = PP.getLangOptions();
+#define PARSE_LANGOPT_BENIGN(Option)
+#define PARSE_LANGOPT_IMPORTANT(Option, DiagID)                    \
+  if (PPLangOpts.Option != LangOpts.Option) {                      \
+    Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option;   \
+    return true;                                                   \
+  }
+
+  PARSE_LANGOPT_BENIGN(Trigraphs);
+  PARSE_LANGOPT_BENIGN(BCPLComment);
+  PARSE_LANGOPT_BENIGN(DollarIdents);
+  PARSE_LANGOPT_BENIGN(AsmPreprocessor);
+  PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
+  PARSE_LANGOPT_BENIGN(ImplicitInt);
+  PARSE_LANGOPT_BENIGN(Digraphs);
+  PARSE_LANGOPT_BENIGN(HexFloats);
+  PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
+  PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
+  PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
+  PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
+  PARSE_LANGOPT_BENIGN(CXXOperatorName);
+  PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
+  PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
+  PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
+  PARSE_LANGOPT_BENIGN(PascalStrings);
+  PARSE_LANGOPT_BENIGN(WritableStrings);
+  PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, 
+                          diag::warn_pch_lax_vector_conversions);
+  PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
+  PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
+  PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
+  PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
+  PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics, 
+                          diag::warn_pch_thread_safe_statics);
+  PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
+  PARSE_LANGOPT_BENIGN(EmitAllDecls);
+  PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
+  PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
+  PARSE_LANGOPT_IMPORTANT(HeinousExtensions, 
+                          diag::warn_pch_heinous_extensions);
+  // FIXME: Most of the options below are benign if the macro wasn't
+  // used. Unfortunately, this means that a PCH compiled without
+  // optimization can't be used with optimization turned on, even
+  // though the only thing that changes is whether __OPTIMIZE__ was
+  // defined... but if __OPTIMIZE__ never showed up in the header, it
+  // doesn't matter. We could consider making this some special kind
+  // of check.
+  PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
+  PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
+  PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
+  PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
+  PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
+  PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
+  PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
+  PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+  if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
+    Reader.Diag(diag::warn_pch_gc_mode) 
+      << LangOpts.getGCMode() << PPLangOpts.getGCMode();
+    return true;
+  }
+  PARSE_LANGOPT_BENIGN(getVisibilityMode());
+  PARSE_LANGOPT_BENIGN(InstantiationDepth);
+#undef PARSE_LANGOPT_IRRELEVANT
+#undef PARSE_LANGOPT_BENIGN
+
+  return false;
+}
+
+bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
+  if (Triple != PP.getTargetInfo().getTargetTriple()) {
+    Reader.Diag(diag::warn_pch_target_triple)
+      << Triple << PP.getTargetInfo().getTargetTriple();
+    return true;
+  }
+  return false;
+}
+
+/// \brief Split the given string into a vector of lines, eliminating
+/// any empty lines in the process.
+///
+/// \param Str the string to split.
+/// \param Len the length of Str.
+/// \param KeepEmptyLines true if empty lines should be included
+/// \returns a vector of lines, with the line endings removed
+static std::vector<std::string> splitLines(const char *Str, unsigned Len,
+                                           bool KeepEmptyLines = false) {
+  std::vector<std::string> Lines;
+  for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
+    unsigned LineEnd = LineStart;
+    while (LineEnd < Len && Str[LineEnd] != '\n')
+      ++LineEnd;
+    if (LineStart != LineEnd || KeepEmptyLines)
+      Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
+    LineStart = LineEnd;
+  }
+  return Lines;
+}
+
+/// \brief Determine whether the string Haystack starts with the
+/// substring Needle.
+static bool startsWith(const std::string &Haystack, const char *Needle) {
+  for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
+    if (I == N)
+      return false;
+    if (Haystack[I] != Needle[I])
+      return false;
+  }
+
+  return true;
+}
+
+/// \brief Determine whether the string Haystack starts with the
+/// substring Needle.
+static inline bool startsWith(const std::string &Haystack,
+                              const std::string &Needle) {
+  return startsWith(Haystack, Needle.c_str());
+}
+
+bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, 
+                                        unsigned PCHPredefLen,
+                                        FileID PCHBufferID,
+                                        std::string &SuggestedPredefines) {
+  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;
+
+  SourceManager &SourceMgr = PP.getSourceManager();
+  
+  // The predefines buffers are different. Determine what the
+  // differences are, and whether they require us to reject the PCH
+  // file.
+  std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
+  std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
+
+  // Sort both sets of predefined buffer lines, since 
+  std::sort(CmdLineLines.begin(), CmdLineLines.end());
+  std::sort(PCHLines.begin(), PCHLines.end());
+
+  // Determine which predefines that where used to build the PCH file
+  // are missing from the command line.
+  std::vector<std::string> MissingPredefines;
+  std::set_difference(PCHLines.begin(), PCHLines.end(),
+                      CmdLineLines.begin(), CmdLineLines.end(),
+                      std::back_inserter(MissingPredefines));
+
+  bool MissingDefines = false;
+  bool ConflictingDefines = false;
+  for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
+    const std::string &Missing = MissingPredefines[I];
+    if (!startsWith(Missing, "#define ") != 0) {
+      Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+      return true;
+    }
+    
+    // This is a macro definition. Determine the name of the macro
+    // we're defining.
+    std::string::size_type StartOfMacroName = strlen("#define ");
+    std::string::size_type EndOfMacroName 
+      = Missing.find_first_of("( \n\r", StartOfMacroName);
+    assert(EndOfMacroName != std::string::npos &&
+           "Couldn't find the end of the macro name");
+    std::string MacroName = Missing.substr(StartOfMacroName,
+                                           EndOfMacroName - StartOfMacroName);
+
+    // Determine whether this macro was given a different definition
+    // on the command line.
+    std::string MacroDefStart = "#define " + MacroName;
+    std::string::size_type MacroDefLen = MacroDefStart.size();
+    std::vector<std::string>::iterator ConflictPos
+      = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
+                         MacroDefStart);
+    for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
+      if (!startsWith(*ConflictPos, MacroDefStart)) {
+        // Different macro; we're done.
+        ConflictPos = CmdLineLines.end();
+        break; 
+      }
+      
+      assert(ConflictPos->size() > MacroDefLen && 
+             "Invalid #define in predefines buffer?");
+      if ((*ConflictPos)[MacroDefLen] != ' ' && 
+          (*ConflictPos)[MacroDefLen] != '(')
+        continue; // Longer macro name; keep trying.
+      
+      // We found a conflicting macro definition.
+      break;
+    }
+    
+    if (ConflictPos != CmdLineLines.end()) {
+      Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
+          << MacroName;
+
+      // Show the definition of this macro within the PCH file.
+      const char *MissingDef = strstr(PCHPredef, Missing.c_str());
+      unsigned Offset = MissingDef - PCHPredef;
+      SourceLocation PCHMissingLoc
+        = SourceMgr.getLocForStartOfFile(PCHBufferID)
+            .getFileLocWithOffset(Offset);
+      Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
+        << MacroName;
+
+      ConflictingDefines = true;
+      continue;
+    }
+    
+    // If the macro doesn't conflict, then we'll just pick up the
+    // macro definition from the PCH file. Warn the user that they
+    // made a mistake.
+    if (ConflictingDefines)
+      continue; // Don't complain if there are already conflicting defs
+    
+    if (!MissingDefines) {
+      Reader.Diag(diag::warn_cmdline_missing_macro_defs);
+      MissingDefines = true;
+    }
+
+    // Show the definition of this macro within the PCH file.
+    const char *MissingDef = strstr(PCHPredef, Missing.c_str());
+    unsigned Offset = MissingDef - PCHPredef;
+    SourceLocation PCHMissingLoc
+      = SourceMgr.getLocForStartOfFile(PCHBufferID)
+      .getFileLocWithOffset(Offset);
+    Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
+  }
+  
+  if (ConflictingDefines)
+    return true;
+  
+  // Determine what predefines were introduced based on command-line
+  // parameters that were not present when building the PCH
+  // file. Extra #defines are okay, so long as the identifiers being
+  // defined were not used within the precompiled header.
+  std::vector<std::string> ExtraPredefines;
+  std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
+                      PCHLines.begin(), PCHLines.end(),
+                      std::back_inserter(ExtraPredefines));  
+  for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
+    const std::string &Extra = ExtraPredefines[I];
+    if (!startsWith(Extra, "#define ") != 0) {
+      Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+      return true;
+    }
+
+    // This is an extra macro definition. Determine the name of the
+    // macro we're defining.
+    std::string::size_type StartOfMacroName = strlen("#define ");
+    std::string::size_type EndOfMacroName 
+      = Extra.find_first_of("( \n\r", StartOfMacroName);
+    assert(EndOfMacroName != std::string::npos &&
+           "Couldn't find the end of the macro name");
+    std::string MacroName = Extra.substr(StartOfMacroName,
+                                         EndOfMacroName - StartOfMacroName);
+
+    // Check whether this name was used somewhere in the PCH file. If
+    // so, defining it as a macro could change behavior, so we reject
+    // the PCH file.
+    if (IdentifierInfo *II = Reader.get(MacroName.c_str(),
+                                 MacroName.c_str() + MacroName.size())) {
+      Reader.Diag(diag::warn_macro_name_used_in_pch)
+        << II;
+      return true;
+    }
+
+    // Add this definition to the suggested predefines buffer.
+    SuggestedPredefines += Extra;
+    SuggestedPredefines += '\n';
+  }
+
+  // If we get here, it's because the predefines buffer had compatible
+  // contents. Accept the PCH file.
+  return false;
+}
+
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+}
+
+void PCHValidator::ReadCounter(unsigned Value) {
+  PP.setCounterValue(Value);
+}
+
+
+
+//===----------------------------------------------------------------------===//
 // PCH reader implementation
 //===----------------------------------------------------------------------===//
 
 PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context) 
-  : SemaObj(0), PP(PP), Context(Context), Consumer(0),
+  : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
+    FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
+    SemaObj(0), PP(&PP), Context(Context), Consumer(0),
+    IdentifierTableData(0), IdentifierLookupTable(0),
+    IdentifierOffsets(0),
+    MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
+    TotalSelectorsInMethodPool(0), SelectorOffsets(0),
+    TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0), 
+    NumSLocEntriesRead(0), NumStatementsRead(0), 
+    NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
+    NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
+
+PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
+                     Diagnostic &Diags) 
+  : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
+    SemaObj(0), PP(PP), Context(Context), Consumer(0),
     IdentifierTableData(0), IdentifierLookupTable(0),
     IdentifierOffsets(0),
     MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
@@ -296,69 +606,27 @@
         // Queue this declaration so that it will be added to the
         // translation unit scope and identifier's declaration chain
         // once a Sema object is known.
-        Reader.PreloadedDecls.push_back(D);
-      }
-
-      DataLen -= 4;
-    }
-    return II;
-  }
-};
-  
-} // end anonymous namespace  
-
-/// \brief The on-disk hash table used to contain information about
-/// all of the identifiers in the program.
-typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait> 
-  PCHIdentifierLookupTable;
-
-// FIXME: use the diagnostics machinery
-bool PCHReader::Error(const char *Msg) {
-  Diagnostic &Diags = PP.getDiagnostics();
-  unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
-  Diag(DiagID);
-  return true;
-}
-
-/// \brief Split the given string into a vector of lines, eliminating
-/// any empty lines in the process.
-///
-/// \param Str the string to split.
-/// \param Len the length of Str.
-/// \param KeepEmptyLines true if empty lines should be included
-/// \returns a vector of lines, with the line endings removed
-std::vector<std::string> splitLines(const char *Str, unsigned Len,
-                                    bool KeepEmptyLines = false) {
-  std::vector<std::string> Lines;
-  for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
-    unsigned LineEnd = LineStart;
-    while (LineEnd < Len && Str[LineEnd] != '\n')
-      ++LineEnd;
-    if (LineStart != LineEnd || KeepEmptyLines)
-      Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
-    LineStart = LineEnd;
-  }
-  return Lines;
-}
+        Reader.PreloadedDecls.push_back(D);
+      }
 
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static bool startsWith(const std::string &Haystack, const char *Needle) {
-  for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
-    if (I == N)
-      return false;
-    if (Haystack[I] != Needle[I])
-      return false;
+      DataLen -= 4;
+    }
+    return II;
   }
+};
+  
+} // end anonymous namespace  
 
-  return true;
-}
+/// \brief The on-disk hash table used to contain information about
+/// all of the identifiers in the program.
+typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait> 
+  PCHIdentifierLookupTable;
 
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static inline bool startsWith(const std::string &Haystack,
-                              const std::string &Needle) {
-  return startsWith(Haystack, Needle.c_str());
+// FIXME: use the diagnostics machinery
+bool PCHReader::Error(const char *Msg) {
+  unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
+  Diag(DiagID);
+  return true;
 }
 
 /// \brief Check the contents of the predefines buffer against the
@@ -381,158 +649,9 @@
 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;
-
-  SourceManager &SourceMgr = PP.getSourceManager();
-  
-  // The predefines buffers are different. Determine what the
-  // differences are, and whether they require us to reject the PCH
-  // file.
-  std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
-  std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
-
-  // Sort both sets of predefined buffer lines, since 
-  std::sort(CmdLineLines.begin(), CmdLineLines.end());
-  std::sort(PCHLines.begin(), PCHLines.end());
-
-  // Determine which predefines that where used to build the PCH file
-  // are missing from the command line.
-  std::vector<std::string> MissingPredefines;
-  std::set_difference(PCHLines.begin(), PCHLines.end(),
-                      CmdLineLines.begin(), CmdLineLines.end(),
-                      std::back_inserter(MissingPredefines));
-
-  bool MissingDefines = false;
-  bool ConflictingDefines = false;
-  for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
-    const std::string &Missing = MissingPredefines[I];
-    if (!startsWith(Missing, "#define ") != 0) {
-      Diag(diag::warn_pch_compiler_options_mismatch);
-      return true;
-    }
-    
-    // This is a macro definition. Determine the name of the macro
-    // we're defining.
-    std::string::size_type StartOfMacroName = strlen("#define ");
-    std::string::size_type EndOfMacroName 
-      = Missing.find_first_of("( \n\r", StartOfMacroName);
-    assert(EndOfMacroName != std::string::npos &&
-           "Couldn't find the end of the macro name");
-    std::string MacroName = Missing.substr(StartOfMacroName,
-                                           EndOfMacroName - StartOfMacroName);
-
-    // Determine whether this macro was given a different definition
-    // on the command line.
-    std::string MacroDefStart = "#define " + MacroName;
-    std::string::size_type MacroDefLen = MacroDefStart.size();
-    std::vector<std::string>::iterator ConflictPos
-      = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
-                         MacroDefStart);
-    for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
-      if (!startsWith(*ConflictPos, MacroDefStart)) {
-        // Different macro; we're done.
-        ConflictPos = CmdLineLines.end();
-        break; 
-      }
-      
-      assert(ConflictPos->size() > MacroDefLen && 
-             "Invalid #define in predefines buffer?");
-      if ((*ConflictPos)[MacroDefLen] != ' ' && 
-          (*ConflictPos)[MacroDefLen] != '(')
-        continue; // Longer macro name; keep trying.
-      
-      // We found a conflicting macro definition.
-      break;
-    }
-    
-    if (ConflictPos != CmdLineLines.end()) {
-      Diag(diag::warn_cmdline_conflicting_macro_def)
-          << MacroName;
-
-      // Show the definition of this macro within the PCH file.
-      const char *MissingDef = strstr(PCHPredef, Missing.c_str());
-      unsigned Offset = MissingDef - PCHPredef;
-      SourceLocation PCHMissingLoc
-        = SourceMgr.getLocForStartOfFile(PCHBufferID)
-            .getFileLocWithOffset(Offset);
-      Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
-        << MacroName;
-
-      ConflictingDefines = true;
-      continue;
-    }
-    
-    // If the macro doesn't conflict, then we'll just pick up the
-    // macro definition from the PCH file. Warn the user that they
-    // made a mistake.
-    if (ConflictingDefines)
-      continue; // Don't complain if there are already conflicting defs
-    
-    if (!MissingDefines) {
-      Diag(diag::warn_cmdline_missing_macro_defs);
-      MissingDefines = true;
-    }
-
-    // Show the definition of this macro within the PCH file.
-    const char *MissingDef = strstr(PCHPredef, Missing.c_str());
-    unsigned Offset = MissingDef - PCHPredef;
-    SourceLocation PCHMissingLoc
-      = SourceMgr.getLocForStartOfFile(PCHBufferID)
-      .getFileLocWithOffset(Offset);
-    Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
-  }
-  
-  if (ConflictingDefines)
-    return true;
-  
-  // Determine what predefines were introduced based on command-line
-  // parameters that were not present when building the PCH
-  // file. Extra #defines are okay, so long as the identifiers being
-  // defined were not used within the precompiled header.
-  std::vector<std::string> ExtraPredefines;
-  std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
-                      PCHLines.begin(), PCHLines.end(),
-                      std::back_inserter(ExtraPredefines));  
-  for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
-    const std::string &Extra = ExtraPredefines[I];
-    if (!startsWith(Extra, "#define ") != 0) {
-      Diag(diag::warn_pch_compiler_options_mismatch);
-      return true;
-    }
-
-    // This is an extra macro definition. Determine the name of the
-    // macro we're defining.
-    std::string::size_type StartOfMacroName = strlen("#define ");
-    std::string::size_type EndOfMacroName 
-      = Extra.find_first_of("( \n\r", StartOfMacroName);
-    assert(EndOfMacroName != std::string::npos &&
-           "Couldn't find the end of the macro name");
-    std::string MacroName = Extra.substr(StartOfMacroName,
-                                         EndOfMacroName - StartOfMacroName);
-
-    // Check whether this name was used somewhere in the PCH file. If
-    // so, defining it as a macro could change behavior, so we reject
-    // the PCH file.
-    if (IdentifierInfo *II = get(MacroName.c_str(),
-                                 MacroName.c_str() + MacroName.size())) {
-      Diag(diag::warn_macro_name_used_in_pch)
-        << II;
-      return true;
-    }
-
-    // Add this definition to the suggested predefines buffer.
-    SuggestedPredefines += Extra;
-    SuggestedPredefines += '\n';
-  }
-
-  // If we get here, it's because the predefines buffer had compatible
-  // contents. Accept the PCH file.
+  if (Listener)
+    return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
+                                          SuggestedPredefines);
   return false;
 }
 
@@ -714,9 +833,7 @@
     return Failure;
   }
 
-  SourceManager &SourceMgr = PP.getSourceManager();
   RecordData Record;
-  unsigned NumHeaderInfos = 0;
   while (true) {
     unsigned Code = SLocEntryCursor.ReadCode();
     if (Code == llvm::bitc::END_BLOCK) {
@@ -761,7 +878,8 @@
       HFI.DirInfo = Record[1];
       HFI.NumIncludes = Record[2];
       HFI.ControllingMacroID = Record[3];
-      PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+      if (Listener)
+        Listener->ReadHeaderFileInfo(HFI);
       break;
     }
 
@@ -794,7 +912,6 @@
     return Failure;
   }
 
-  SourceManager &SourceMgr = PP.getSourceManager();
   RecordData Record;
   const char *BlobStart;
   unsigned BlobLen;
@@ -804,8 +921,7 @@
     return Failure;
 
   case pch::SM_SLOC_FILE_ENTRY: {
-    const FileEntry *File = PP.getFileManager().getFile(BlobStart,
-                                                        BlobStart + BlobLen);
+    const FileEntry *File = FileMgr.getFile(BlobStart, BlobStart + BlobLen);
     if (File == 0) {
       std::string ErrorStr = "could not find file '";
       ErrorStr.append(BlobStart, BlobLen);
@@ -886,6 +1002,8 @@
 }
 
 void PCHReader::ReadMacroRecord(uint64_t Offset) {
+  assert(PP && "Forgot to set Preprocessor ?");
+  
   // Keep track of where we are in the stream, then jump back there
   // after reading this macro.
   SavedStreamPosition SavedPosition(Stream);
@@ -937,7 +1055,7 @@
       SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
       bool isUsed = Record[2];
       
-      MacroInfo *MI = PP.AllocateMacroInfo(Loc);
+      MacroInfo *MI = PP->AllocateMacroInfo(Loc);
       MI->setIsUsed(isUsed);
       
       if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
@@ -954,11 +1072,11 @@
         if (isC99VarArgs) MI->setIsC99Varargs();
         if (isGNUVarArgs) MI->setIsGNUVarargs();
         MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
-                            PP.getPreprocessorAllocator());
+                            PP->getPreprocessorAllocator());
       }
 
       // Finally, install the macro.
-      PP.setMacroInfo(II, MI);
+      PP->setMacroInfo(II, MI);
 
       // Remember that we saw this macro last so that we add the tokens that
       // form its body to it.
@@ -1099,11 +1217,10 @@
         return IgnorePCH;
       }
 
-      std::string TargetTriple(BlobStart, BlobLen);
-      if (TargetTriple != PP.getTargetInfo().getTargetTriple()) {
-        Diag(diag::warn_pch_target_triple)
-          << TargetTriple << PP.getTargetInfo().getTargetTriple();
-        return IgnorePCH;
+      if (Listener) {
+        std::string TargetTriple(BlobStart, BlobLen);
+        if (Listener->ReadTargetTriple(TargetTriple))
+          return IgnorePCH;
       }
       break;
     }
@@ -1116,7 +1233,8 @@
                         (const unsigned char *)IdentifierTableData + Record[0],
                         (const unsigned char *)IdentifierTableData, 
                         PCHIdentifierLookupTrait(*this));
-        PP.getIdentifierTable().setExternalIdentifierLookup(this);
+        if (PP)
+          PP->getIdentifierTable().setExternalIdentifierLookup(this);
       }
       break;
 
@@ -1127,7 +1245,8 @@
       }
       IdentifierOffsets = (const uint32_t *)BlobStart;
       IdentifiersLoaded.resize(Record[0]);
-      PP.getHeaderSearchInfo().SetExternalLookup(this);
+      if (PP)
+        PP->getHeaderSearchInfo().SetExternalLookup(this);
       break;
 
     case pch::EXTERNAL_DEFINITIONS:
@@ -1183,14 +1302,14 @@
       break;
 
     case pch::PP_COUNTER_VALUE:
-      if (!Record.empty())
-        PP.setCounterValue(Record[0]);
+      if (!Record.empty() && Listener)
+        Listener->ReadCounter(Record[0]);
       break;
 
     case pch::SOURCE_LOCATION_OFFSETS:
       SLocOffsets = (const uint32_t *)BlobStart;
       TotalNumSLocEntries = Record[0];
-      PP.getSourceManager().PreallocateSLocEntries(this, 
+      SourceMgr.PreallocateSLocEntries(this, 
                                                    TotalNumSLocEntries, 
                                                    Record[1]);
       break;
@@ -1204,7 +1323,7 @@
       break;
 
     case pch::STAT_CACHE:
-      PP.getFileManager().setStatCache(
+      FileMgr.setStatCache(
                   new PCHStatCache((const unsigned char *)BlobStart + Record[0],
                                    (const unsigned char *)BlobStart,
                                    NumStatHits, NumStatMisses));
@@ -1294,10 +1413,10 @@
 
         // Clear out any preallocated source location entries, so that
         // the source manager does not try to resolve them later.
-        PP.getSourceManager().ClearPreallocatedSLocEntries();
+        SourceMgr.ClearPreallocatedSLocEntries();
 
         // Remove the stat cache.
-        PP.getFileManager().setStatCache(0);
+        FileMgr.setStatCache(0);
 
         return IgnorePCH;
       }
@@ -1310,71 +1429,82 @@
       break;
     }
   }  
-
-  // Load the translation unit declaration
-  if (Context)
-    ReadDeclRecord(DeclOffsets[0], 0);
   
   // Check the predefines buffer.
   if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen, 
                             PCHPredefinesBufferID))
     return IgnorePCH;
   
-  // Initialization of builtins and library builtins occurs before the
-  // PCH file is read, so there may be some identifiers that were
-  // loaded into the IdentifierTable before we intercepted the
-  // creation of identifiers. Iterate through the list of known
-  // identifiers and determine whether we have to establish
-  // preprocessor definitions or top-level identifier declaration
-  // chains for those identifiers.
-  //
-  // We copy the IdentifierInfo pointers to a small vector first,
-  // since de-serializing declarations or macro definitions can add
-  // new entries into the identifier table, invalidating the
-  // iterators.
-  llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
-  for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
-                              IdEnd = PP.getIdentifierTable().end();
-       Id != IdEnd; ++Id)
-    Identifiers.push_back(Id->second);
-  PCHIdentifierLookupTable *IdTable 
-    = (PCHIdentifierLookupTable *)IdentifierLookupTable;
-  for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
-    IdentifierInfo *II = Identifiers[I];
-    // Look in the on-disk hash table for an entry for
-    PCHIdentifierLookupTrait Info(*this, II);
-    std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
-    PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
-    if (Pos == IdTable->end())
-      continue;
-
-    // Dereferencing the iterator has the effect of populating the
-    // IdentifierInfo node with the various declarations it needs.
-    (void)*Pos;
+  if (PP) {
+    // Initialization of builtins and library builtins occurs before the
+    // PCH file is read, so there may be some identifiers that were
+    // loaded into the IdentifierTable before we intercepted the
+    // creation of identifiers. Iterate through the list of known
+    // identifiers and determine whether we have to establish
+    // preprocessor definitions or top-level identifier declaration
+    // chains for those identifiers.
+    //
+    // We copy the IdentifierInfo pointers to a small vector first,
+    // since de-serializing declarations or macro definitions can add
+    // new entries into the identifier table, invalidating the
+    // iterators.
+    llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
+    for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
+                                IdEnd = PP->getIdentifierTable().end();
+         Id != IdEnd; ++Id)
+      Identifiers.push_back(Id->second);
+    PCHIdentifierLookupTable *IdTable 
+      = (PCHIdentifierLookupTable *)IdentifierLookupTable;
+    for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
+      IdentifierInfo *II = Identifiers[I];
+      // Look in the on-disk hash table for an entry for
+      PCHIdentifierLookupTrait Info(*this, II);
+      std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
+      PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
+      if (Pos == IdTable->end())
+        continue;
+  
+      // Dereferencing the iterator has the effect of populating the
+      // IdentifierInfo node with the various declarations it needs.
+      (void)*Pos;
+    }
   }
 
-  // Load the special types.
-  if (Context) {
-    Context->setBuiltinVaListType(
-      GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
-    if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
-      Context->setObjCIdType(GetType(Id));
-    if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
-      Context->setObjCSelType(GetType(Sel));
-    if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
-      Context->setObjCProtoType(GetType(Proto));
-    if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
-      Context->setObjCClassType(GetType(Class));
-    if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
-      Context->setCFConstantStringType(GetType(String));
-    if (unsigned FastEnum 
-          = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
-      Context->setObjCFastEnumerationStateType(GetType(FastEnum));
-  }
+  if (Context)
+    InitializeContext(*Context);
 
   return Success;
 }
 
+void PCHReader::InitializeContext(ASTContext &Ctx) {
+  Context = &Ctx;
+  assert(Context && "Passed null context!");
+
+  assert(PP && "Forgot to set Preprocessor ?");
+  PP->getIdentifierTable().setExternalIdentifierLookup(this);
+  PP->getHeaderSearchInfo().SetExternalLookup(this);
+  
+  // Load the translation unit declaration
+  ReadDeclRecord(DeclOffsets[0], 0);
+
+  // Load the special types.
+  Context->setBuiltinVaListType(
+    GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
+  if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
+    Context->setObjCIdType(GetType(Id));
+  if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
+    Context->setObjCSelType(GetType(Sel));
+  if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
+    Context->setObjCProtoType(GetType(Proto));
+  if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
+    Context->setObjCClassType(GetType(Class));
+  if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
+    Context->setCFConstantStringType(GetType(String));
+  if (unsigned FastEnum 
+        = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
+    Context->setObjCFastEnumerationStateType(GetType(FastEnum));
+}
+
 /// \brief Retrieve the name of the original source file name
 /// directly from the PCH file, without actually loading the PCH
 /// file.
@@ -1472,73 +1602,60 @@
 /// \returns true if the PCH file is unacceptable, false otherwise.
 bool PCHReader::ParseLanguageOptions(
                              const llvm::SmallVectorImpl<uint64_t> &Record) {
-  const LangOptions &LangOpts = PP.getLangOptions();
-#define PARSE_LANGOPT_BENIGN(Option) ++Idx
-#define PARSE_LANGOPT_IMPORTANT(Option, DiagID)                 \
-  if (Record[Idx] != LangOpts.Option) {                         \
-    Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option;   \
-    return true;                                                \
-  }                                                             \
-  ++Idx
+  if (Listener) {
+    LangOptions LangOpts;
+    
+  #define PARSE_LANGOPT(Option)                  \
+      LangOpts.Option = Record[Idx];             \
+      ++Idx
+    
+    unsigned Idx = 0;
+    PARSE_LANGOPT(Trigraphs);
+    PARSE_LANGOPT(BCPLComment);
+    PARSE_LANGOPT(DollarIdents);
+    PARSE_LANGOPT(AsmPreprocessor);
+    PARSE_LANGOPT(GNUMode);
+    PARSE_LANGOPT(ImplicitInt);
+    PARSE_LANGOPT(Digraphs);
+    PARSE_LANGOPT(HexFloats);
+    PARSE_LANGOPT(C99);
+    PARSE_LANGOPT(Microsoft);
+    PARSE_LANGOPT(CPlusPlus);
+    PARSE_LANGOPT(CPlusPlus0x);
+    PARSE_LANGOPT(CXXOperatorNames);
+    PARSE_LANGOPT(ObjC1);
+    PARSE_LANGOPT(ObjC2);
+    PARSE_LANGOPT(ObjCNonFragileABI);
+    PARSE_LANGOPT(PascalStrings);
+    PARSE_LANGOPT(WritableStrings);
+    PARSE_LANGOPT(LaxVectorConversions);
+    PARSE_LANGOPT(Exceptions);
+    PARSE_LANGOPT(NeXTRuntime);
+    PARSE_LANGOPT(Freestanding);
+    PARSE_LANGOPT(NoBuiltin);
+    PARSE_LANGOPT(ThreadsafeStatics);
+    PARSE_LANGOPT(Blocks);
+    PARSE_LANGOPT(EmitAllDecls);
+    PARSE_LANGOPT(MathErrno);
+    PARSE_LANGOPT(OverflowChecking);
+    PARSE_LANGOPT(HeinousExtensions);
+    PARSE_LANGOPT(Optimize);
+    PARSE_LANGOPT(OptimizeSize);
+    PARSE_LANGOPT(Static);
+    PARSE_LANGOPT(PICLevel);
+    PARSE_LANGOPT(GNUInline);
+    PARSE_LANGOPT(NoInline);
+    PARSE_LANGOPT(AccessControl);
+    PARSE_LANGOPT(CharIsSigned);
+    LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
+    ++Idx;
+    LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
+    ++Idx;
+    PARSE_LANGOPT(InstantiationDepth);
+  #undef PARSE_LANGOPT
 
-  unsigned Idx = 0;
-  PARSE_LANGOPT_BENIGN(Trigraphs);
-  PARSE_LANGOPT_BENIGN(BCPLComment);
-  PARSE_LANGOPT_BENIGN(DollarIdents);
-  PARSE_LANGOPT_BENIGN(AsmPreprocessor);
-  PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
-  PARSE_LANGOPT_BENIGN(ImplicitInt);
-  PARSE_LANGOPT_BENIGN(Digraphs);
-  PARSE_LANGOPT_BENIGN(HexFloats);
-  PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
-  PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
-  PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
-  PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
-  PARSE_LANGOPT_BENIGN(CXXOperatorName);
-  PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
-  PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
-  PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
-  PARSE_LANGOPT_BENIGN(PascalStrings);
-  PARSE_LANGOPT_BENIGN(WritableStrings);
-  PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, 
-                          diag::warn_pch_lax_vector_conversions);
-  PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
-  PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
-  PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
-  PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
-  PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics, 
-                          diag::warn_pch_thread_safe_statics);
-  PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
-  PARSE_LANGOPT_BENIGN(EmitAllDecls);
-  PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
-  PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
-  PARSE_LANGOPT_IMPORTANT(HeinousExtensions, 
-                          diag::warn_pch_heinous_extensions);
-  // FIXME: Most of the options below are benign if the macro wasn't
-  // used. Unfortunately, this means that a PCH compiled without
-  // optimization can't be used with optimization turned on, even
-  // though the only thing that changes is whether __OPTIMIZE__ was
-  // defined... but if __OPTIMIZE__ never showed up in the header, it
-  // doesn't matter. We could consider making this some special kind
-  // of check.
-  PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
-  PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
-  PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
-  PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
-  PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
-  PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
-  PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
-  PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
-  if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
-    Diag(diag::warn_pch_gc_mode) 
-      << (unsigned)Record[Idx] << LangOpts.getGCMode();
-    return true;
+    return Listener->ReadLanguageOptions(LangOpts);
   }
-  ++Idx;
-  PARSE_LANGOPT_BENIGN(getVisibilityMode());
-  PARSE_LANGOPT_BENIGN(InstantiationDepth);
-#undef PARSE_LANGOPT_IRRELEVANT
-#undef PARSE_LANGOPT_BENIGN
 
   return false;
 }
@@ -2065,6 +2182,7 @@
     return 0;
   }
   
+  assert(PP && "Forgot to set Preprocessor ?");
   if (!IdentifiersLoaded[ID - 1]) {
     uint32_t Offset = IdentifierOffsets[ID - 1];
     const char *Str = IdentifierTableData + Offset;
@@ -2076,7 +2194,7 @@
     unsigned StrLen = (((unsigned) StrLenPtr[0])
                        | (((unsigned) StrLenPtr[1]) << 8)) - 1;
     IdentifiersLoaded[ID - 1] 
-      = &PP.getIdentifierTable().get(Str, Str + StrLen);
+      = &PP->getIdentifierTable().get(Str, Str + StrLen);
   }
   
   return IdentifiersLoaded[ID - 1];
@@ -2179,15 +2297,14 @@
 }
 
 DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
-  return PP.getDiagnostics().Report(FullSourceLoc(Loc,
-                                                  PP.getSourceManager()),
-                                    DiagID);
+  return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
 }
 
 /// \brief Retrieve the identifier table associated with the
 /// preprocessor.
 IdentifierTable &PCHReader::getIdentifierTable() {
-  return PP.getIdentifierTable();
+  assert(PP && "Forgot to set Preprocessor ?");
+  return PP->getIdentifierTable();
 }
 
 /// \brief Record that the given ID maps to the given switch-case





More information about the cfe-commits mailing list