diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 428647f..019d25c 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -12,7 +12,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/PCHWriter.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/DeclVisitor.h"
@@ -26,7 +25,8 @@
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/FrontendOptions.h"
-#include "clang/Frontend/PCHReader.h"
+#include "clang/Serialization/PCHReader.h"
+#include "clang/Serialization/PCHWriter.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/TargetOptions.h"
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index a3fd17f..fa20aff 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -20,12 +20,6 @@
   InitHeaderSearch.cpp
   InitPreprocessor.cpp
   LangStandards.cpp
-  PCHReader.cpp
-  PCHReaderDecl.cpp
-  PCHReaderStmt.cpp
-  PCHWriter.cpp
-  PCHWriterDecl.cpp
-  PCHWriterStmt.cpp
   PrintPreprocessedOutput.cpp
   StmtXML.cpp
   TextDiagnosticBuffer.cpp
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 8e1dbcb..aaa6780 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -21,11 +21,11 @@
 #include "clang/Lex/PTHManager.h"
 #include "clang/Frontend/ChainedDiagnosticClient.h"
 #include "clang/Frontend/FrontendAction.h"
-#include "clang/Frontend/PCHReader.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/VerifyDiagnosticsClient.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Serialization/PCHReader.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "llvm/LLVMContext.h"
 #include "llvm/Support/MemoryBuffer.h"
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 82cd75d..68b384f 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -18,7 +18,7 @@
 #include "clang/Driver/Option.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Frontend/LangStandard.h"
-#include "clang/Frontend/PCHReader.h"
+#include "clang/Serialization/PCHReader.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 0a03ab4..8599efb 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -17,8 +17,8 @@
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/PCHWriter.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Serialization/PCHWriter.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp
deleted file mode 100644
index 33f5ef5..0000000
--- a/lib/Frontend/GeneratePCH.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-//===--- GeneratePCH.cpp - AST Consumer for PCH Generation ------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file defines the CreatePCHGenerate function, which creates an
-//  ASTConsume that generates a PCH file.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/ASTConsumers.h"
-#include "clang/Frontend/PCHWriter.h"
-#include "clang/Sema/SemaConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Basic/FileManager.h"
-#include "llvm/Bitcode/BitstreamWriter.h"
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-
-using namespace clang;
-
-PCHGenerator::PCHGenerator(const Preprocessor &PP,
-                           bool Chaining,
-                           const char *isysroot,
-                           llvm::raw_ostream *OS)
-  : 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.
-  StatCalls = new MemorizeStatCalls;
-  // 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=*/!Chaining);
-}
-
-void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
-  if (PP.getDiagnostics().hasErrorOccurred())
-    return;
-
-  // Emit the PCH file
-  assert(SemaPtr && "No Sema?");
-  Writer.WritePCH(*SemaPtr, StatCalls, isysroot);
-
-  // Write the generated bitstream to "Out".
-  Out->write((char *)&Buffer.front(), Buffer.size());
-
-  // Make sure it hits disk now.
-  Out->flush();
-
-  // Free up some memory, in case the process is kept alive.
-  Buffer.clear();
-}
-
-PCHDeserializationListener *PCHGenerator::GetPCHDeserializationListener() {
-  return &Writer;
-}
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
deleted file mode 100644
index 9491770..0000000
--- a/lib/Frontend/PCHReader.cpp
+++ /dev/null
@@ -1,3857 +0,0 @@
-//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file defines the PCHReader class, which reads a precompiled header.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/PCHReader.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/PCHDeserializationListener.h"
-#include "clang/Frontend/Utils.h"
-#include "clang/Sema/Sema.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/TypeLocVisitor.h"
-#include "clang/Lex/MacroInfo.h"
-#include "clang/Lex/PreprocessingRecord.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Basic/OnDiskHashTable.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/SourceManagerInternals.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Version.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Bitcode/BitstreamReader.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/System/Path.h"
-#include <algorithm>
-#include <iterator>
-#include <cstdio>
-#include <sys/stat.h>
-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_IMPORTANT(GNUKeywords, diag::warn_pch_gnu_keywords);
-  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_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2);
-  PARSE_LANGOPT_IMPORTANT(NoConstantCFStrings, 
-                          diag::warn_pch_no_constant_cfstrings);
-  PARSE_LANGOPT_BENIGN(PascalStrings);
-  PARSE_LANGOPT_BENIGN(WritableStrings);
-  PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
-                          diag::warn_pch_lax_vector_conversions);
-  PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec);
-  PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
-  PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_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(POSIXThreads, diag::warn_pch_posix_threads);
-  PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
-  PARSE_LANGOPT_BENIGN(EmitAllDecls);
-  PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
-  PARSE_LANGOPT_BENIGN(getSignedOverflowBehavior());
-  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);
-  PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
-  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_IMPORTANT(getStackProtectorMode(),
-                          diag::warn_pch_stack_protector);
-  PARSE_LANGOPT_BENIGN(InstantiationDepth);
-  PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl);
-  PARSE_LANGOPT_BENIGN(CatchUndefined);
-  PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors);
-  PARSE_LANGOPT_BENIGN(SpellChecking);
-#undef PARSE_LANGOPT_IMPORTANT
-#undef PARSE_LANGOPT_BENIGN
-
-  return false;
-}
-
-bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) {
-  if (Triple == PP.getTargetInfo().getTriple().str())
-    return false;
-
-  Reader.Diag(diag::warn_pch_target_triple)
-    << Triple << PP.getTargetInfo().getTriple().str();
-  return true;
-}
-
-struct EmptyStringRef {
-  bool operator ()(llvm::StringRef r) const { return r.empty(); }
-};
-struct EmptyBlock {
-  bool operator ()(const PCHPredefinesBlock &r) const { return r.Data.empty(); }
-};
-
-static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L,
-                                PCHPredefinesBlocks R) {
-  // First, sum up the lengths.
-  unsigned LL = 0, RL = 0;
-  for (unsigned I = 0, N = L.size(); I != N; ++I) {
-    LL += L[I].size();
-  }
-  for (unsigned I = 0, N = R.size(); I != N; ++I) {
-    RL += R[I].Data.size();
-  }
-  if (LL != RL)
-    return false;
-  if (LL == 0 && RL == 0)
-    return true;
-
-  // Kick out empty parts, they confuse the algorithm below.
-  L.erase(std::remove_if(L.begin(), L.end(), EmptyStringRef()), L.end());
-  R.erase(std::remove_if(R.begin(), R.end(), EmptyBlock()), R.end());
-
-  // Do it the hard way. At this point, both vectors must be non-empty.
-  llvm::StringRef LR = L[0], RR = R[0].Data;
-  unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size();
-  (void) RN;
-  for (;;) {
-    // Compare the current pieces.
-    if (LR.size() == RR.size()) {
-      // If they're the same length, it's pretty easy.
-      if (LR != RR)
-        return false;
-      // Both pieces are done, advance.
-      ++LI;
-      ++RI;
-      // If either string is done, they're both done, since they're the same
-      // length.
-      if (LI == LN) {
-        assert(RI == RN && "Strings not the same length after all?");
-        return true;
-      }
-      LR = L[LI];
-      RR = R[RI].Data;
-    } else if (LR.size() < RR.size()) {
-      // Right piece is longer.
-      if (!RR.startswith(LR))
-        return false;
-      ++LI;
-      assert(LI != LN && "Strings not the same length after all?");
-      RR = RR.substr(LR.size());
-      LR = L[LI];
-    } else {
-      // Left piece is longer.
-      if (!LR.startswith(RR))
-        return false;
-      ++RI;
-      assert(RI != RN && "Strings not the same length after all?");
-      LR = LR.substr(RR.size());
-      RR = R[RI].Data;
-    }
-  }
-}
-
-static std::pair<FileID, llvm::StringRef::size_type>
-FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) {
-  std::pair<FileID, llvm::StringRef::size_type> Res;
-  for (unsigned I = 0, N = Buffers.size(); I != N; ++I) {
-    Res.second = Buffers[I].Data.find(MacroDef);
-    if (Res.second != llvm::StringRef::npos) {
-      Res.first = Buffers[I].BufferID;
-      break;
-    }
-  }
-  return Res;
-}
-
-bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
-                                        llvm::StringRef OriginalFileName,
-                                        std::string &SuggestedPredefines) {
-  // We are in the context of an implicit include, so the predefines buffer will
-  // have a #include entry for the PCH file itself (as normalized by the
-  // preprocessor initialization). Find it and skip over it in the checking
-  // below.
-  llvm::SmallString<256> PCHInclude;
-  PCHInclude += "#include \"";
-  PCHInclude += NormalizeDashIncludePath(OriginalFileName);
-  PCHInclude += "\"\n";
-  std::pair<llvm::StringRef,llvm::StringRef> Split =
-    llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
-  llvm::StringRef Left =  Split.first, Right = Split.second;
-  if (Left == PP.getPredefines()) {
-    Error("Missing PCH include entry!");
-    return true;
-  }
-
-  // If the concatenation of all the PCH buffers is equal to the adjusted
-  // command line, we're done.
-  // We build a SmallVector of the command line here, because we'll eventually
-  // need to support an arbitrary amount of pieces anyway (when we have chained
-  // PCH reading).
-  llvm::SmallVector<llvm::StringRef, 2> CommandLine;
-  CommandLine.push_back(Left);
-  CommandLine.push_back(Right);
-  if (EqualConcatenations(CommandLine, Buffers))
-    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.
-  llvm::SmallVector<llvm::StringRef, 8> PCHLines;
-  for (unsigned I = 0, N = Buffers.size(); I != N; ++I)
-    Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
-
-  llvm::SmallVector<llvm::StringRef, 8> CmdLineLines;
-  Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
-  Right.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
-
-  // Sort both sets of predefined buffer lines, since we allow some extra
-  // definitions and they may appear at any point in the output.
-  std::sort(CmdLineLines.begin(), CmdLineLines.end());
-  std::sort(PCHLines.begin(), PCHLines.end());
-
-  // Determine which predefines that were used to build the PCH file are missing
-  // from the command line.
-  std::vector<llvm::StringRef> 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) {
-    llvm::StringRef Missing = MissingPredefines[I];
-    if (!Missing.startswith("#define ")) {
-      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");
-    llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName);
-
-    // Determine whether this macro was given a different definition on the
-    // command line.
-    std::string MacroDefStart = "#define " + MacroName.str();
-    std::string::size_type MacroDefLen = MacroDefStart.size();
-    llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos
-      = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
-                         MacroDefStart);
-    for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
-      if (!ConflictPos->startswith(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.
-      std::pair<FileID, llvm::StringRef::size_type> MacroLoc =
-          FindMacro(Buffers, Missing);
-      assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!");
-      SourceLocation PCHMissingLoc =
-          SourceMgr.getLocForStartOfFile(MacroLoc.first)
-            .getFileLocWithOffset(MacroLoc.second);
-      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.
-    std::pair<FileID, llvm::StringRef::size_type> MacroLoc =
-        FindMacro(Buffers, Missing);
-    assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!");
-    SourceLocation PCHMissingLoc =
-        SourceMgr.getLocForStartOfFile(MacroLoc.first)
-          .getFileLocWithOffset(MacroLoc.second);
-    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<llvm::StringRef> 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) {
-    llvm::StringRef &Extra = ExtraPredefines[I];
-    if (!Extra.startswith("#define ")) {
-      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");
-    llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName);
-
-    // 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)) {
-      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,
-                                      unsigned ID) {
-  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);
-  ++NumHeaderInfos;
-}
-
-void PCHValidator::ReadCounter(unsigned Value) {
-  PP.setCounterValue(Value);
-}
-
-//===----------------------------------------------------------------------===//
-// PCH reader implementation
-//===----------------------------------------------------------------------===//
-
-PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
-                     const char *isysroot, bool DisableValidation)
-  : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
-    SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
-    Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
-    Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation),
-    NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0),
-    TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0),
-    NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0),
-    NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0),
-    TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0),
-    TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0),
-    TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) {
-  RelocatablePCH = false;
-}
-
-PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
-                     Diagnostic &Diags, const char *isysroot,
-                     bool DisableValidation)
-  : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
-    Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0),
-    isysroot(isysroot), DisableValidation(DisableValidation), NumStatHits(0),
-    NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0),
-    NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
-    TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
-    NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0),
-    NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
-    NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
-    NumCurrentElementsDeserializing(0) {
-  RelocatablePCH = false;
-}
-
-PCHReader::~PCHReader() {
-  for (unsigned i = 0, e = Chain.size(); i != e; ++i)
-    delete Chain[e - i - 1];
-}
-
-PCHReader::PerFileData::PerFileData()
-  : StatCache(0), LocalNumSLocEntries(0), LocalNumTypes(0), TypeOffsets(0),
-    LocalNumDecls(0), DeclOffsets(0), LocalNumIdentifiers(0),
-    IdentifierOffsets(0), IdentifierTableData(0), IdentifierLookupTable(0),
-    LocalNumMacroDefinitions(0), MacroDefinitionOffsets(0),
-    NumPreallocatedPreprocessingEntities(0), SelectorLookupTable(0),
-    SelectorLookupTableData(0), SelectorOffsets(0), LocalNumSelectors(0)
-{}
-
-void
-PCHReader::setDeserializationListener(PCHDeserializationListener *Listener) {
-  DeserializationListener = Listener;
-  if (DeserializationListener)
-    DeserializationListener->SetReader(this);
-}
-
-
-namespace {
-class PCHSelectorLookupTrait {
-  PCHReader &Reader;
-
-public:
-  struct data_type {
-    pch::SelectorID ID;
-    ObjCMethodList Instance, Factory;
-  };
-
-  typedef Selector external_key_type;
-  typedef external_key_type internal_key_type;
-
-  explicit PCHSelectorLookupTrait(PCHReader &Reader) : Reader(Reader) { }
-
-  static bool EqualKey(const internal_key_type& a,
-                       const internal_key_type& b) {
-    return a == b;
-  }
-
-  static unsigned ComputeHash(Selector Sel) {
-    unsigned N = Sel.getNumArgs();
-    if (N == 0)
-      ++N;
-    unsigned R = 5381;
-    for (unsigned I = 0; I != N; ++I)
-      if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
-        R = llvm::HashString(II->getName(), R);
-    return R;
-  }
-
-  // This hopefully will just get inlined and removed by the optimizer.
-  static const internal_key_type&
-  GetInternalKey(const external_key_type& x) { return x; }
-
-  static std::pair<unsigned, unsigned>
-  ReadKeyDataLength(const unsigned char*& d) {
-    using namespace clang::io;
-    unsigned KeyLen = ReadUnalignedLE16(d);
-    unsigned DataLen = ReadUnalignedLE16(d);
-    return std::make_pair(KeyLen, DataLen);
-  }
-
-  internal_key_type ReadKey(const unsigned char* d, unsigned) {
-    using namespace clang::io;
-    SelectorTable &SelTable = Reader.getContext()->Selectors;
-    unsigned N = ReadUnalignedLE16(d);
-    IdentifierInfo *FirstII
-      = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
-    if (N == 0)
-      return SelTable.getNullarySelector(FirstII);
-    else if (N == 1)
-      return SelTable.getUnarySelector(FirstII);
-
-    llvm::SmallVector<IdentifierInfo *, 16> Args;
-    Args.push_back(FirstII);
-    for (unsigned I = 1; I != N; ++I)
-      Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
-
-    return SelTable.getSelector(N, Args.data());
-  }
-
-  data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
-    using namespace clang::io;
-
-    data_type Result;
-
-    Result.ID = ReadUnalignedLE32(d);
-    unsigned NumInstanceMethods = ReadUnalignedLE16(d);
-    unsigned NumFactoryMethods = ReadUnalignedLE16(d);
-
-    // Load instance methods
-    ObjCMethodList *Prev = 0;
-    for (unsigned I = 0; I != NumInstanceMethods; ++I) {
-      ObjCMethodDecl *Method
-        = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
-      if (!Result.Instance.Method) {
-        // This is the first method, which is the easy case.
-        Result.Instance.Method = Method;
-        Prev = &Result.Instance;
-        continue;
-      }
-
-      ObjCMethodList *Mem =
-        Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>();
-      Prev->Next = new (Mem) ObjCMethodList(Method, 0);
-      Prev = Prev->Next;
-    }
-
-    // Load factory methods
-    Prev = 0;
-    for (unsigned I = 0; I != NumFactoryMethods; ++I) {
-      ObjCMethodDecl *Method
-        = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
-      if (!Result.Factory.Method) {
-        // This is the first method, which is the easy case.
-        Result.Factory.Method = Method;
-        Prev = &Result.Factory;
-        continue;
-      }
-
-      ObjCMethodList *Mem =
-        Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>();
-      Prev->Next = new (Mem) ObjCMethodList(Method, 0);
-      Prev = Prev->Next;
-    }
-
-    return Result;
-  }
-};
-
-} // end anonymous namespace
-
-/// \brief The on-disk hash table used for the global method pool.
-typedef OnDiskChainedHashTable<PCHSelectorLookupTrait>
-  PCHSelectorLookupTable;
-
-namespace {
-class PCHIdentifierLookupTrait {
-  PCHReader &Reader;
-  llvm::BitstreamCursor &Stream;
-
-  // If we know the IdentifierInfo in advance, it is here and we will
-  // not build a new one. Used when deserializing information about an
-  // identifier that was constructed before the PCH file was read.
-  IdentifierInfo *KnownII;
-
-public:
-  typedef IdentifierInfo * data_type;
-
-  typedef const std::pair<const char*, unsigned> external_key_type;
-
-  typedef external_key_type internal_key_type;
-
-  PCHIdentifierLookupTrait(PCHReader &Reader, llvm::BitstreamCursor &Stream,
-                           IdentifierInfo *II = 0)
-    : Reader(Reader), Stream(Stream), KnownII(II) { }
-
-  static bool EqualKey(const internal_key_type& a,
-                       const internal_key_type& b) {
-    return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
-                                  : false;
-  }
-
-  static unsigned ComputeHash(const internal_key_type& a) {
-    return llvm::HashString(llvm::StringRef(a.first, a.second));
-  }
-
-  // This hopefully will just get inlined and removed by the optimizer.
-  static const internal_key_type&
-  GetInternalKey(const external_key_type& x) { return x; }
-
-  static std::pair<unsigned, unsigned>
-  ReadKeyDataLength(const unsigned char*& d) {
-    using namespace clang::io;
-    unsigned DataLen = ReadUnalignedLE16(d);
-    unsigned KeyLen = ReadUnalignedLE16(d);
-    return std::make_pair(KeyLen, DataLen);
-  }
-
-  static std::pair<const char*, unsigned>
-  ReadKey(const unsigned char* d, unsigned n) {
-    assert(n >= 2 && d[n-1] == '\0');
-    return std::make_pair((const char*) d, n-1);
-  }
-
-  IdentifierInfo *ReadData(const internal_key_type& k,
-                           const unsigned char* d,
-                           unsigned DataLen) {
-    using namespace clang::io;
-    pch::IdentID ID = ReadUnalignedLE32(d);
-    bool IsInteresting = ID & 0x01;
-
-    // Wipe out the "is interesting" bit.
-    ID = ID >> 1;
-
-    if (!IsInteresting) {
-      // For uninteresting identifiers, just build the IdentifierInfo
-      // and associate it with the persistent ID.
-      IdentifierInfo *II = KnownII;
-      if (!II)
-        II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second);
-      Reader.SetIdentifierInfo(ID, II);
-      II->setIsFromPCH();
-      return II;
-    }
-
-    unsigned Bits = ReadUnalignedLE16(d);
-    bool CPlusPlusOperatorKeyword = Bits & 0x01;
-    Bits >>= 1;
-    bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
-    Bits >>= 1;
-    bool Poisoned = Bits & 0x01;
-    Bits >>= 1;
-    bool ExtensionToken = Bits & 0x01;
-    Bits >>= 1;
-    bool hasMacroDefinition = Bits & 0x01;
-    Bits >>= 1;
-    unsigned ObjCOrBuiltinID = Bits & 0x3FF;
-    Bits >>= 10;
-
-    assert(Bits == 0 && "Extra bits in the identifier?");
-    DataLen -= 6;
-
-    // Build the IdentifierInfo itself and link the identifier ID with
-    // the new IdentifierInfo.
-    IdentifierInfo *II = KnownII;
-    if (!II)
-      II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second);
-    Reader.SetIdentifierInfo(ID, II);
-
-    // Set or check the various bits in the IdentifierInfo structure.
-    // Token IDs are read-only.
-    if (HasRevertedTokenIDToIdentifier)
-      II->RevertTokenIDToIdentifier();
-    II->setObjCOrBuiltinID(ObjCOrBuiltinID);
-    assert(II->isExtensionToken() == ExtensionToken &&
-           "Incorrect extension token flag");
-    (void)ExtensionToken;
-    II->setIsPoisoned(Poisoned);
-    assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
-           "Incorrect C++ operator keyword flag");
-    (void)CPlusPlusOperatorKeyword;
-
-    // If this identifier is a macro, deserialize the macro
-    // definition.
-    if (hasMacroDefinition) {
-      uint32_t Offset = ReadUnalignedLE32(d);
-      Reader.ReadMacroRecord(Stream, Offset);
-      DataLen -= 4;
-    }
-
-    // Read all of the declarations visible at global scope with this
-    // name.
-    if (Reader.getContext() == 0) return II;
-    if (DataLen > 0) {
-      llvm::SmallVector<uint32_t, 4> DeclIDs;
-      for (; DataLen > 0; DataLen -= 4)
-        DeclIDs.push_back(ReadUnalignedLE32(d));
-      Reader.SetGloballyVisibleDecls(II, DeclIDs);
-    }
-
-    II->setIsFromPCH();
-    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;
-
-void PCHReader::Error(const char *Msg) {
-  Diag(diag::err_fe_pch_malformed) << Msg;
-}
-
-/// \brief Check the contents of the concatenation of all predefines buffers in
-/// the PCH chain against the contents of the predefines buffer of the current
-/// compiler invocation.
-///
-/// The contents should be the same. If not, then some command-line option
-/// changed the preprocessor state and we must probably reject the PCH file.
-///
-/// \returns true if there was a mismatch (in which case the PCH file
-/// should be ignored), or false otherwise.
-bool PCHReader::CheckPredefinesBuffers() {
-  if (Listener)
-    return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
-                                          ActualOriginalFileName,
-                                          SuggestedPredefines);
-  return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Source Manager Deserialization
-//===----------------------------------------------------------------------===//
-
-/// \brief Read the line table in the source manager block.
-/// \returns true if ther was an error.
-bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
-  unsigned Idx = 0;
-  LineTableInfo &LineTable = SourceMgr.getLineTable();
-
-  // Parse the file names
-  std::map<int, int> FileIDs;
-  for (int I = 0, N = Record[Idx++]; I != N; ++I) {
-    // Extract the file name
-    unsigned FilenameLen = Record[Idx++];
-    std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
-    Idx += FilenameLen;
-    MaybeAddSystemRootToFilename(Filename);
-    FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
-                                                  Filename.size());
-  }
-
-  // Parse the line entries
-  std::vector<LineEntry> Entries;
-  while (Idx < Record.size()) {
-    int FID = Record[Idx++];
-
-    // Extract the line entries
-    unsigned NumEntries = Record[Idx++];
-    assert(NumEntries && "Numentries is 00000");
-    Entries.clear();
-    Entries.reserve(NumEntries);
-    for (unsigned I = 0; I != NumEntries; ++I) {
-      unsigned FileOffset = Record[Idx++];
-      unsigned LineNo = Record[Idx++];
-      int FilenameID = FileIDs[Record[Idx++]];
-      SrcMgr::CharacteristicKind FileKind
-        = (SrcMgr::CharacteristicKind)Record[Idx++];
-      unsigned IncludeOffset = Record[Idx++];
-      Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
-                                       FileKind, IncludeOffset));
-    }
-    LineTable.AddEntry(FID, Entries);
-  }
-
-  return false;
-}
-
-namespace {
-
-class PCHStatData {
-public:
-  const bool hasStat;
-  const ino_t ino;
-  const dev_t dev;
-  const mode_t mode;
-  const time_t mtime;
-  const off_t size;
-
-  PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
-  : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
-
-  PCHStatData()
-    : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
-};
-
-class PCHStatLookupTrait {
- public:
-  typedef const char *external_key_type;
-  typedef const char *internal_key_type;
-
-  typedef PCHStatData data_type;
-
-  static unsigned ComputeHash(const char *path) {
-    return llvm::HashString(path);
-  }
-
-  static internal_key_type GetInternalKey(const char *path) { return path; }
-
-  static bool EqualKey(internal_key_type a, internal_key_type b) {
-    return strcmp(a, b) == 0;
-  }
-
-  static std::pair<unsigned, unsigned>
-  ReadKeyDataLength(const unsigned char*& d) {
-    unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
-    unsigned DataLen = (unsigned) *d++;
-    return std::make_pair(KeyLen + 1, DataLen);
-  }
-
-  static internal_key_type ReadKey(const unsigned char *d, unsigned) {
-    return (const char *)d;
-  }
-
-  static data_type ReadData(const internal_key_type, const unsigned char *d,
-                            unsigned /*DataLen*/) {
-    using namespace clang::io;
-
-    if (*d++ == 1)
-      return data_type();
-
-    ino_t ino = (ino_t) ReadUnalignedLE32(d);
-    dev_t dev = (dev_t) ReadUnalignedLE32(d);
-    mode_t mode = (mode_t) ReadUnalignedLE16(d);
-    time_t mtime = (time_t) ReadUnalignedLE64(d);
-    off_t size = (off_t) ReadUnalignedLE64(d);
-    return data_type(ino, dev, mode, mtime, size);
-  }
-};
-
-/// \brief stat() cache for precompiled headers.
-///
-/// This cache is very similar to the stat cache used by pretokenized
-/// headers.
-class PCHStatCache : public StatSysCallCache {
-  typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
-  CacheTy *Cache;
-
-  unsigned &NumStatHits, &NumStatMisses;
-public:
-  PCHStatCache(const unsigned char *Buckets,
-               const unsigned char *Base,
-               unsigned &NumStatHits,
-               unsigned &NumStatMisses)
-    : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
-    Cache = CacheTy::Create(Buckets, Base);
-  }
-
-  ~PCHStatCache() { delete Cache; }
-
-  int stat(const char *path, struct stat *buf) {
-    // Do the lookup for the file's data in the PCH file.
-    CacheTy::iterator I = Cache->find(path);
-
-    // If we don't get a hit in the PCH file just forward to 'stat'.
-    if (I == Cache->end()) {
-      ++NumStatMisses;
-      return StatSysCallCache::stat(path, buf);
-    }
-
-    ++NumStatHits;
-    PCHStatData Data = *I;
-
-    if (!Data.hasStat)
-      return 1;
-
-    buf->st_ino = Data.ino;
-    buf->st_dev = Data.dev;
-    buf->st_mtime = Data.mtime;
-    buf->st_mode = Data.mode;
-    buf->st_size = Data.size;
-    return 0;
-  }
-};
-} // end anonymous namespace
-
-
-/// \brief Read a source manager block
-PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock(PerFileData &F) {
-  using namespace SrcMgr;
-
-  llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;
-
-  // Set the source-location entry cursor to the current position in
-  // the stream. This cursor will be used to read the contents of the
-  // source manager block initially, and then lazily read
-  // source-location entries as needed.
-  SLocEntryCursor = F.Stream;
-
-  // The stream itself is going to skip over the source manager block.
-  if (F.Stream.SkipBlock()) {
-    Error("malformed block record in PCH file");
-    return Failure;
-  }
-
-  // Enter the source manager block.
-  if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
-    Error("malformed source manager block record in PCH file");
-    return Failure;
-  }
-
-  RecordData Record;
-  while (true) {
-    unsigned Code = SLocEntryCursor.ReadCode();
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (SLocEntryCursor.ReadBlockEnd()) {
-        Error("error at end of Source Manager block in PCH file");
-        return Failure;
-      }
-      return Success;
-    }
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      // No known subblocks, always skip them.
-      SLocEntryCursor.ReadSubBlockID();
-      if (SLocEntryCursor.SkipBlock()) {
-        Error("malformed block record in PCH file");
-        return Failure;
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      SLocEntryCursor.ReadAbbrevRecord();
-      continue;
-    }
-
-    // Read a record.
-    const char *BlobStart;
-    unsigned BlobLen;
-    Record.clear();
-    switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
-    default:  // Default behavior: ignore.
-      break;
-
-    case pch::SM_LINE_TABLE:
-      if (ParseLineTable(Record))
-        return Failure;
-      break;
-
-    case pch::SM_SLOC_FILE_ENTRY:
-    case pch::SM_SLOC_BUFFER_ENTRY:
-    case pch::SM_SLOC_INSTANTIATION_ENTRY:
-      // Once we hit one of the source location entries, we're done.
-      return Success;
-    }
-  }
-}
-
-/// \brief Get a cursor that's correctly positioned for reading the source
-/// location entry with the given ID.
-llvm::BitstreamCursor &PCHReader::SLocCursorForID(unsigned ID) {
-  assert(ID != 0 && ID <= TotalNumSLocEntries &&
-         "SLocCursorForID should only be called for real IDs.");
-
-  ID -= 1;
-  PerFileData *F = 0;
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    F = Chain[N - I - 1];
-    if (ID < F->LocalNumSLocEntries)
-      break;
-    ID -= F->LocalNumSLocEntries;
-  }
-  assert(F && F->LocalNumSLocEntries > ID && "Chain corrupted");
-
-  F->SLocEntryCursor.JumpToBit(F->SLocOffsets[ID]);
-  return F->SLocEntryCursor;
-}
-
-/// \brief Read in the source location entry with the given ID.
-PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
-  if (ID == 0)
-    return Success;
-
-  if (ID > TotalNumSLocEntries) {
-    Error("source location entry ID out-of-range for PCH file");
-    return Failure;
-  }
-
-  llvm::BitstreamCursor &SLocEntryCursor = SLocCursorForID(ID);
-
-  ++NumSLocEntriesRead;
-  unsigned Code = SLocEntryCursor.ReadCode();
-  if (Code == llvm::bitc::END_BLOCK ||
-      Code == llvm::bitc::ENTER_SUBBLOCK ||
-      Code == llvm::bitc::DEFINE_ABBREV) {
-    Error("incorrectly-formatted source location entry in PCH file");
-    return Failure;
-  }
-
-  RecordData Record;
-  const char *BlobStart;
-  unsigned BlobLen;
-  switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
-  default:
-    Error("incorrectly-formatted source location entry in PCH file");
-    return Failure;
-
-  case pch::SM_SLOC_FILE_ENTRY: {
-    std::string Filename(BlobStart, BlobStart + BlobLen);
-    MaybeAddSystemRootToFilename(Filename);
-    const FileEntry *File = FileMgr.getFile(Filename);
-    if (File == 0) {
-      std::string ErrorStr = "could not find file '";
-      ErrorStr += Filename;
-      ErrorStr += "' referenced by PCH file";
-      Error(ErrorStr.c_str());
-      return Failure;
-    }
-
-    if (Record.size() < 10) {
-      Error("source location entry is incorrect");
-      return Failure;
-    }
-
-    if (!DisableValidation &&
-        ((off_t)Record[4] != File->getSize()
-#if !defined(LLVM_ON_WIN32)
-        // In our regression testing, the Windows file system seems to
-        // have inconsistent modification times that sometimes
-        // erroneously trigger this error-handling path.
-         || (time_t)Record[5] != File->getModificationTime()
-#endif
-        )) {
-      Diag(diag::err_fe_pch_file_modified)
-        << Filename;
-      return Failure;
-    }
-
-    FileID FID = SourceMgr.createFileID(File,
-                                SourceLocation::getFromRawEncoding(Record[1]),
-                                       (SrcMgr::CharacteristicKind)Record[2],
-                                        ID, Record[0]);
-    if (Record[3])
-      const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
-        .setHasLineDirectives();
-
-    // Reconstruct header-search information for this file.
-    HeaderFileInfo HFI;
-    HFI.isImport = Record[6];
-    HFI.DirInfo = Record[7];
-    HFI.NumIncludes = Record[8];
-    HFI.ControllingMacroID = Record[9];
-    if (Listener)
-      Listener->ReadHeaderFileInfo(HFI, File->getUID());
-    break;
-  }
-
-  case pch::SM_SLOC_BUFFER_ENTRY: {
-    const char *Name = BlobStart;
-    unsigned Offset = Record[0];
-    unsigned Code = SLocEntryCursor.ReadCode();
-    Record.clear();
-    unsigned RecCode
-      = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
-
-    if (RecCode != pch::SM_SLOC_BUFFER_BLOB) {
-      Error("PCH record has invalid code");
-      return Failure;
-    }
-
-    llvm::MemoryBuffer *Buffer
-    = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(BlobStart, BlobLen - 1),
-                                       Name);
-    FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
-
-    if (strcmp(Name, "<built-in>") == 0) {
-      PCHPredefinesBlock Block = {
-        BufferID,
-        llvm::StringRef(BlobStart, BlobLen - 1)
-      };
-      PCHPredefinesBuffers.push_back(Block);
-    }
-
-    break;
-  }
-
-  case pch::SM_SLOC_INSTANTIATION_ENTRY: {
-    SourceLocation SpellingLoc
-      = SourceLocation::getFromRawEncoding(Record[1]);
-    SourceMgr.createInstantiationLoc(SpellingLoc,
-                              SourceLocation::getFromRawEncoding(Record[2]),
-                              SourceLocation::getFromRawEncoding(Record[3]),
-                                     Record[4],
-                                     ID,
-                                     Record[0]);
-    break;
-  }
-  }
-
-  return Success;
-}
-
-/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
-/// specified cursor.  Read the abbreviations that are at the top of the block
-/// and then leave the cursor pointing into the block.
-bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
-                                 unsigned BlockID) {
-  if (Cursor.EnterSubBlock(BlockID)) {
-    Error("malformed block record in PCH file");
-    return Failure;
-  }
-
-  while (true) {
-    unsigned Code = Cursor.ReadCode();
-
-    // We expect all abbrevs to be at the start of the block.
-    if (Code != llvm::bitc::DEFINE_ABBREV)
-      return false;
-    Cursor.ReadAbbrevRecord();
-  }
-}
-
-void PCHReader::ReadMacroRecord(llvm::BitstreamCursor &Stream, 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);
-
-  Stream.JumpToBit(Offset);
-  RecordData Record;
-  llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
-  MacroInfo *Macro = 0;
-
-  while (true) {
-    unsigned Code = Stream.ReadCode();
-    switch (Code) {
-    case llvm::bitc::END_BLOCK:
-      return;
-
-    case llvm::bitc::ENTER_SUBBLOCK:
-      // No known subblocks, always skip them.
-      Stream.ReadSubBlockID();
-      if (Stream.SkipBlock()) {
-        Error("malformed block record in PCH file");
-        return;
-      }
-      continue;
-
-    case llvm::bitc::DEFINE_ABBREV:
-      Stream.ReadAbbrevRecord();
-      continue;
-    default: break;
-    }
-
-    // Read a record.
-    Record.clear();
-    pch::PreprocessorRecordTypes RecType =
-      (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
-    switch (RecType) {
-    case pch::PP_MACRO_OBJECT_LIKE:
-    case pch::PP_MACRO_FUNCTION_LIKE: {
-      // If we already have a macro, that means that we've hit the end
-      // of the definition of the macro we were looking for. We're
-      // done.
-      if (Macro)
-        return;
-
-      IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
-      if (II == 0) {
-        Error("macro must have a name in PCH file");
-        return;
-      }
-      SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
-      bool isUsed = Record[2];
-
-      MacroInfo *MI = PP->AllocateMacroInfo(Loc);
-      MI->setIsUsed(isUsed);
-      MI->setIsFromPCH();
-
-      unsigned NextIndex = 3;
-      if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
-        // Decode function-like macro info.
-        bool isC99VarArgs = Record[3];
-        bool isGNUVarArgs = Record[4];
-        MacroArgs.clear();
-        unsigned NumArgs = Record[5];
-        NextIndex = 6 + NumArgs;
-        for (unsigned i = 0; i != NumArgs; ++i)
-          MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
-
-        // Install function-like macro info.
-        MI->setIsFunctionLike();
-        if (isC99VarArgs) MI->setIsC99Varargs();
-        if (isGNUVarArgs) MI->setIsGNUVarargs();
-        MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
-                            PP->getPreprocessorAllocator());
-      }
-
-      // Finally, install the macro.
-      PP->setMacroInfo(II, MI);
-
-      // Remember that we saw this macro last so that we add the tokens that
-      // form its body to it.
-      Macro = MI;
-      
-      if (NextIndex + 1 == Record.size() && PP->getPreprocessingRecord()) {
-        // We have a macro definition. Load it now.
-        PP->getPreprocessingRecord()->RegisterMacroDefinition(Macro,
-                                        getMacroDefinition(Record[NextIndex]));
-      }
-      
-      ++NumMacrosRead;
-      break;
-    }
-
-    case pch::PP_TOKEN: {
-      // If we see a TOKEN before a PP_MACRO_*, then the file is
-      // erroneous, just pretend we didn't see this.
-      if (Macro == 0) break;
-
-      Token Tok;
-      Tok.startToken();
-      Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
-      Tok.setLength(Record[1]);
-      if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
-        Tok.setIdentifierInfo(II);
-      Tok.setKind((tok::TokenKind)Record[3]);
-      Tok.setFlag((Token::TokenFlags)Record[4]);
-      Macro->AddTokenToBody(Tok);
-      break;
-    }
-        
-    case pch::PP_MACRO_INSTANTIATION: {
-      // If we already have a macro, that means that we've hit the end
-      // of the definition of the macro we were looking for. We're
-      // done.
-      if (Macro)
-        return;
-      
-      if (!PP->getPreprocessingRecord()) {
-        Error("missing preprocessing record in PCH file");
-        return;
-      }
-        
-      PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
-      if (PPRec.getPreprocessedEntity(Record[0]))
-        return;
-
-      MacroInstantiation *MI
-        = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]),
-                               SourceRange(
-                                 SourceLocation::getFromRawEncoding(Record[1]),
-                                 SourceLocation::getFromRawEncoding(Record[2])),
-                                         getMacroDefinition(Record[4]));
-      PPRec.SetPreallocatedEntity(Record[0], MI);
-      return;
-    }
-
-    case pch::PP_MACRO_DEFINITION: {
-      // If we already have a macro, that means that we've hit the end
-      // of the definition of the macro we were looking for. We're
-      // done.
-      if (Macro)
-        return;
-      
-      if (!PP->getPreprocessingRecord()) {
-        Error("missing preprocessing record in PCH file");
-        return;
-      }
-      
-      PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
-      if (PPRec.getPreprocessedEntity(Record[0]))
-        return;
-        
-      if (Record[1] >= MacroDefinitionsLoaded.size()) {
-        Error("out-of-bounds macro definition record");
-        return;
-      }
-
-      MacroDefinition *MD
-        = new (PPRec) MacroDefinition(DecodeIdentifierInfo(Record[4]),
-                                SourceLocation::getFromRawEncoding(Record[5]),
-                              SourceRange(
-                                SourceLocation::getFromRawEncoding(Record[2]),
-                                SourceLocation::getFromRawEncoding(Record[3])));
-      PPRec.SetPreallocatedEntity(Record[0], MD);
-      MacroDefinitionsLoaded[Record[1]] = MD;
-      return;
-    }
-  }
-  }
-}
-
-void PCHReader::ReadDefinedMacros() {
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    llvm::BitstreamCursor &MacroCursor = Chain[N - I - 1]->MacroCursor;
-
-    // If there was no preprocessor block, skip this file.
-    if (!MacroCursor.getBitStreamReader())
-      continue;
-
-    llvm::BitstreamCursor Cursor = MacroCursor;
-    if (Cursor.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID)) {
-      Error("malformed preprocessor block record in PCH file");
-      return;
-    }
-
-    RecordData Record;
-    while (true) {
-      unsigned Code = Cursor.ReadCode();
-      if (Code == llvm::bitc::END_BLOCK) {
-        if (Cursor.ReadBlockEnd()) {
-          Error("error at end of preprocessor block in PCH file");
-          return;
-        }
-        break;
-      }
-
-      if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-        // No known subblocks, always skip them.
-        Cursor.ReadSubBlockID();
-        if (Cursor.SkipBlock()) {
-          Error("malformed block record in PCH file");
-          return;
-        }
-        continue;
-      }
-
-      if (Code == llvm::bitc::DEFINE_ABBREV) {
-        Cursor.ReadAbbrevRecord();
-        continue;
-      }
-
-      // Read a record.
-      const char *BlobStart;
-      unsigned BlobLen;
-      Record.clear();
-      switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
-      default:  // Default behavior: ignore.
-        break;
-
-      case pch::PP_MACRO_OBJECT_LIKE:
-      case pch::PP_MACRO_FUNCTION_LIKE:
-        DecodeIdentifierInfo(Record[0]);
-        break;
-
-      case pch::PP_TOKEN:
-        // Ignore tokens.
-        break;
-        
-      case pch::PP_MACRO_INSTANTIATION:
-      case pch::PP_MACRO_DEFINITION:
-        // Read the macro record.
-        ReadMacroRecord(Chain[N - I - 1]->Stream, Cursor.GetCurrentBitNo());
-        break;
-      }
-    }
-  }
-}
-
-MacroDefinition *PCHReader::getMacroDefinition(pch::IdentID ID) {
-  if (ID == 0 || ID >= MacroDefinitionsLoaded.size())
-    return 0;
-
-  if (!MacroDefinitionsLoaded[ID]) {
-    unsigned Index = ID;
-    for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-      PerFileData &F = *Chain[N - I - 1];
-      if (Index < F.LocalNumMacroDefinitions) {
-        ReadMacroRecord(F.Stream, F.MacroDefinitionOffsets[Index]);
-        break;
-      }
-      Index -= F.LocalNumMacroDefinitions;
-    }
-    assert(MacroDefinitionsLoaded[ID] && "Broken chain");
-  }
-
-  return MacroDefinitionsLoaded[ID];
-}
-
-/// \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.
-void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
-  // If this is not a relocatable PCH file, there's nothing to do.
-  if (!RelocatablePCH)
-    return;
-
-  if (Filename.empty() || llvm::sys::Path(Filename).isAbsolute())
-    return;
-
-  if (isysroot == 0) {
-    // If no system root was given, default to '/'
-    Filename.insert(Filename.begin(), '/');
-    return;
-  }
-
-  unsigned Length = strlen(isysroot);
-  if (isysroot[Length - 1] != '/')
-    Filename.insert(Filename.begin(), '/');
-
-  Filename.insert(Filename.begin(), isysroot, isysroot + Length);
-}
-
-PCHReader::PCHReadResult
-PCHReader::ReadPCHBlock(PerFileData &F) {
-  llvm::BitstreamCursor &Stream = F.Stream;
-
-  if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
-    Error("malformed block record in PCH file");
-    return Failure;
-  }
-
-  // Read all of the records and blocks for the PCH file.
-  RecordData Record;
-  bool First = true;
-  while (!Stream.AtEndOfStream()) {
-    unsigned Code = Stream.ReadCode();
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (Stream.ReadBlockEnd()) {
-        Error("error at end of module block in PCH file");
-        return Failure;
-      }
-
-      return Success;
-    }
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      switch (Stream.ReadSubBlockID()) {
-      case pch::DECLTYPES_BLOCK_ID:
-        // We lazily load the decls block, but we want to set up the
-        // DeclsCursor cursor to point into it.  Clone our current bitcode
-        // cursor to it, enter the block and read the abbrevs in that block.
-        // With the main cursor, we just skip over it.
-        F.DeclsCursor = Stream;
-        if (Stream.SkipBlock() ||  // Skip with the main cursor.
-            // Read the abbrevs.
-            ReadBlockAbbrevs(F.DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
-          Error("malformed block record in PCH file");
-          return Failure;
-        }
-        break;
-
-      case pch::PREPROCESSOR_BLOCK_ID:
-        F.MacroCursor = Stream;
-        if (PP)
-          PP->setExternalSource(this);
-
-        if (Stream.SkipBlock()) {
-          Error("malformed block record in PCH file");
-          return Failure;
-        }
-        break;
-
-      case pch::SOURCE_MANAGER_BLOCK_ID:
-        switch (ReadSourceManagerBlock(F)) {
-        case Success:
-          break;
-
-        case Failure:
-          Error("malformed source manager block in PCH file");
-          return Failure;
-
-        case IgnorePCH:
-          return IgnorePCH;
-        }
-        break;
-      }
-      First = false;
-      continue;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      Stream.ReadAbbrevRecord();
-      continue;
-    }
-
-    // Read and process a record.
-    Record.clear();
-    const char *BlobStart = 0;
-    unsigned BlobLen = 0;
-    switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
-                                                   &BlobStart, &BlobLen)) {
-    default:  // Default behavior: ignore.
-      break;
-
-    case pch::METADATA: {
-      if (Record[0] != pch::VERSION_MAJOR && !DisableValidation) {
-        Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
-                                           : diag::warn_pch_version_too_new);
-        return IgnorePCH;
-      }
-
-      RelocatablePCH = Record[4];
-      if (Listener) {
-        std::string TargetTriple(BlobStart, BlobLen);
-        if (Listener->ReadTargetTriple(TargetTriple))
-          return IgnorePCH;
-      }
-      break;
-    }
-
-    case pch::CHAINED_METADATA: {
-      if (!First) {
-        Error("CHAINED_METADATA is not first record in block");
-        return Failure;
-      }
-      if (Record[0] != pch::VERSION_MAJOR && !DisableValidation) {
-        Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
-                                           : diag::warn_pch_version_too_new);
-        return IgnorePCH;
-      }
-
-      // Load the chained file.
-      switch(ReadPCHCore(llvm::StringRef(BlobStart, BlobLen))) {
-      case Failure: return Failure;
-        // If we have to ignore the dependency, we'll have to ignore this too.
-      case IgnorePCH: return IgnorePCH;
-      case Success: break;
-      }
-      break;
-    }
-
-    case pch::TYPE_OFFSET:
-      if (F.LocalNumTypes != 0) {
-        Error("duplicate TYPE_OFFSET record in PCH file");
-        return Failure;
-      }
-      F.TypeOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumTypes = Record[0];
-      break;
-
-    case pch::DECL_OFFSET:
-      if (F.LocalNumDecls != 0) {
-        Error("duplicate DECL_OFFSET record in PCH file");
-        return Failure;
-      }
-      F.DeclOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumDecls = Record[0];
-      break;
-
-    case pch::TU_UPDATE_LEXICAL: {
-      DeclContextInfo Info = {
-        /* No visible information */ 0, 0,
-        reinterpret_cast<const pch::DeclID *>(BlobStart),
-        BlobLen / sizeof(pch::DeclID)
-      };
-      DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info);
-      break;
-    }
-
-    case pch::REDECLS_UPDATE_LATEST: {
-      assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs");
-      for (unsigned i = 0, e = Record.size(); i < e; i += 2) {
-        pch::DeclID First = Record[i], Latest = Record[i+1];
-        assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() ||
-                Latest > FirstLatestDeclIDs[First]) &&
-               "The new latest is supposed to come after the previous latest");
-        FirstLatestDeclIDs[First] = Latest;
-      }
-      break;
-    }
-
-    case pch::LANGUAGE_OPTIONS:
-      if (ParseLanguageOptions(Record) && !DisableValidation)
-        return IgnorePCH;
-      break;
-
-    case pch::IDENTIFIER_TABLE:
-      F.IdentifierTableData = BlobStart;
-      if (Record[0]) {
-        F.IdentifierLookupTable
-          = PCHIdentifierLookupTable::Create(
-                       (const unsigned char *)F.IdentifierTableData + Record[0],
-                       (const unsigned char *)F.IdentifierTableData,
-                       PCHIdentifierLookupTrait(*this, F.Stream));
-        if (PP)
-          PP->getIdentifierTable().setExternalIdentifierLookup(this);
-      }
-      break;
-
-    case pch::IDENTIFIER_OFFSET:
-      if (F.LocalNumIdentifiers != 0) {
-        Error("duplicate IDENTIFIER_OFFSET record in PCH file");
-        return Failure;
-      }
-      F.IdentifierOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumIdentifiers = Record[0];
-      break;
-
-    case pch::EXTERNAL_DEFINITIONS:
-      // Optimization for the first block.
-      if (ExternalDefinitions.empty())
-        ExternalDefinitions.swap(Record);
-      else
-        ExternalDefinitions.insert(ExternalDefinitions.end(),
-                                   Record.begin(), Record.end());
-      break;
-
-    case pch::SPECIAL_TYPES:
-      // Optimization for the first block
-      if (SpecialTypes.empty())
-        SpecialTypes.swap(Record);
-      else
-        SpecialTypes.insert(SpecialTypes.end(), Record.begin(), Record.end());
-      break;
-
-    case pch::STATISTICS:
-      TotalNumStatements += Record[0];
-      TotalNumMacros += Record[1];
-      TotalLexicalDeclContexts += Record[2];
-      TotalVisibleDeclContexts += Record[3];
-      break;
-
-    case pch::TENTATIVE_DEFINITIONS:
-      // Optimization for the first block.
-      if (TentativeDefinitions.empty())
-        TentativeDefinitions.swap(Record);
-      else
-        TentativeDefinitions.insert(TentativeDefinitions.end(),
-                                    Record.begin(), Record.end());
-      break;
-
-    case pch::UNUSED_FILESCOPED_DECLS:
-      // Optimization for the first block.
-      if (UnusedFileScopedDecls.empty())
-        UnusedFileScopedDecls.swap(Record);
-      else
-        UnusedFileScopedDecls.insert(UnusedFileScopedDecls.end(),
-                                     Record.begin(), Record.end());
-      break;
-
-    case pch::WEAK_UNDECLARED_IDENTIFIERS:
-      // Later blocks overwrite earlier ones.
-      WeakUndeclaredIdentifiers.swap(Record);
-      break;
-
-    case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
-      // Optimization for the first block.
-      if (LocallyScopedExternalDecls.empty())
-        LocallyScopedExternalDecls.swap(Record);
-      else
-        LocallyScopedExternalDecls.insert(LocallyScopedExternalDecls.end(),
-                                          Record.begin(), Record.end());
-      break;
-
-    case pch::SELECTOR_OFFSETS:
-      F.SelectorOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumSelectors = Record[0];
-      break;
-
-    case pch::METHOD_POOL:
-      F.SelectorLookupTableData = (const unsigned char *)BlobStart;
-      if (Record[0])
-        F.SelectorLookupTable
-          = PCHSelectorLookupTable::Create(
-                        F.SelectorLookupTableData + Record[0],
-                        F.SelectorLookupTableData,
-                        PCHSelectorLookupTrait(*this));
-      TotalNumMethodPoolEntries += Record[1];
-      break;
-
-    case pch::REFERENCED_SELECTOR_POOL: {
-      ReferencedSelectorsData.insert(ReferencedSelectorsData.end(),
-          Record.begin(), Record.end());
-      break;
-    }
-
-    case pch::PP_COUNTER_VALUE:
-      if (!Record.empty() && Listener)
-        Listener->ReadCounter(Record[0]);
-      break;
-
-    case pch::SOURCE_LOCATION_OFFSETS:
-      F.SLocOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumSLocEntries = Record[0];
-      // We cannot delay this until all PCHs are loaded, because then source
-      // location preloads would also have to be delayed.
-      TotalNumSLocEntries += F.LocalNumSLocEntries;
-      SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]);
-      break;
-
-    case pch::SOURCE_LOCATION_PRELOADS:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I) {
-        PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
-        if (Result != Success)
-          return Result;
-      }
-      break;
-
-    case pch::STAT_CACHE: {
-      PCHStatCache *MyStatCache =
-        new PCHStatCache((const unsigned char *)BlobStart + Record[0],
-                         (const unsigned char *)BlobStart,
-                         NumStatHits, NumStatMisses);
-      FileMgr.addStatCache(MyStatCache);
-      F.StatCache = MyStatCache;
-      break;
-    }
-
-    case pch::EXT_VECTOR_DECLS:
-      // Optimization for the first block.
-      if (ExtVectorDecls.empty())
-        ExtVectorDecls.swap(Record);
-      else
-        ExtVectorDecls.insert(ExtVectorDecls.end(),
-                              Record.begin(), Record.end());
-      break;
-
-    case pch::VTABLE_USES:
-      // Later tables overwrite earlier ones.
-      VTableUses.swap(Record);
-      break;
-
-    case pch::DYNAMIC_CLASSES:
-      // Optimization for the first block.
-      if (DynamicClasses.empty())
-        DynamicClasses.swap(Record);
-      else
-        DynamicClasses.insert(DynamicClasses.end(),
-                              Record.begin(), Record.end());
-      break;
-
-    case pch::PENDING_IMPLICIT_INSTANTIATIONS:
-      // Optimization for the first block.
-      if (PendingImplicitInstantiations.empty())
-        PendingImplicitInstantiations.swap(Record);
-      else
-        PendingImplicitInstantiations.insert(
-             PendingImplicitInstantiations.end(), Record.begin(), Record.end());
-      break;
-
-    case pch::SEMA_DECL_REFS:
-      // Later tables overwrite earlier ones.
-      SemaDeclRefs.swap(Record);
-      break;
-
-    case pch::ORIGINAL_FILE_NAME:
-      // The primary PCH will be the last to get here, so it will be the one
-      // that's used.
-      ActualOriginalFileName.assign(BlobStart, BlobLen);
-      OriginalFileName = ActualOriginalFileName;
-      MaybeAddSystemRootToFilename(OriginalFileName);
-      break;
-
-    case pch::VERSION_CONTROL_BRANCH_REVISION: {
-      const std::string &CurBranch = getClangFullRepositoryVersion();
-      llvm::StringRef PCHBranch(BlobStart, BlobLen);
-      if (llvm::StringRef(CurBranch) != PCHBranch && !DisableValidation) {
-        Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
-        return IgnorePCH;
-      }
-      break;
-    }
-
-    case pch::MACRO_DEFINITION_OFFSETS:
-      F.MacroDefinitionOffsets = (const uint32_t *)BlobStart;
-      F.NumPreallocatedPreprocessingEntities = Record[0];
-      F.LocalNumMacroDefinitions = Record[1];
-      break;
-
-    case pch::DECL_REPLACEMENTS: {
-      if (Record.size() % 2 != 0) {
-        Error("invalid DECL_REPLACEMENTS block in PCH file");
-        return Failure;
-      }
-      for (unsigned I = 0, N = Record.size(); I != N; I += 2)
-        ReplacedDecls[static_cast<pch::DeclID>(Record[I])] =
-            std::make_pair(&F, Record[I+1]);
-      break;
-    }
-    }
-    First = false;
-  }
-  Error("premature end of bitstream in PCH file");
-  return Failure;
-}
-
-PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
-  switch(ReadPCHCore(FileName)) {
-  case Failure: return Failure;
-  case IgnorePCH: return IgnorePCH;
-  case Success: break;
-  }
-
-  // Here comes stuff that we only do once the entire chain is loaded.
-
-  // Allocate space for loaded identifiers, decls and types.
-  unsigned TotalNumIdentifiers = 0, TotalNumTypes = 0, TotalNumDecls = 0,
-           TotalNumPreallocatedPreprocessingEntities = 0, TotalNumMacroDefs = 0,
-           TotalNumSelectors = 0;
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    TotalNumIdentifiers += Chain[I]->LocalNumIdentifiers;
-    TotalNumTypes += Chain[I]->LocalNumTypes;
-    TotalNumDecls += Chain[I]->LocalNumDecls;
-    TotalNumPreallocatedPreprocessingEntities +=
-        Chain[I]->NumPreallocatedPreprocessingEntities;
-    TotalNumMacroDefs += Chain[I]->LocalNumMacroDefinitions;
-    TotalNumSelectors += Chain[I]->LocalNumSelectors;
-  }
-  IdentifiersLoaded.resize(TotalNumIdentifiers);
-  TypesLoaded.resize(TotalNumTypes);
-  DeclsLoaded.resize(TotalNumDecls);
-  MacroDefinitionsLoaded.resize(TotalNumMacroDefs);
-  if (PP) {
-    if (TotalNumIdentifiers > 0)
-      PP->getHeaderSearchInfo().SetExternalLookup(this);
-    if (TotalNumPreallocatedPreprocessingEntities > 0) {
-      if (!PP->getPreprocessingRecord())
-        PP->createPreprocessingRecord();
-      PP->getPreprocessingRecord()->SetExternalSource(*this,
-                                     TotalNumPreallocatedPreprocessingEntities);
-    }
-  }
-  SelectorsLoaded.resize(TotalNumSelectors);
-
-  // Check the predefines buffers.
-  if (!DisableValidation && CheckPredefinesBuffers())
-    return IgnorePCH;
-
-  if (PP) {
-    // Initialization of keywords and pragmas 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);
-    // We need to search the tables in all files.
-    for (unsigned J = 0, M = Chain.size(); J != M; ++J) {
-      PCHIdentifierLookupTable *IdTable
-        = (PCHIdentifierLookupTable *)Chain[J]->IdentifierLookupTable;
-      // Not all PCH files necessarily have identifier tables, only the useful
-      // ones.
-      if (!IdTable)
-        continue;
-      for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
-        IdentifierInfo *II = Identifiers[I];
-        // Look in the on-disk hash tables for an entry for this identifier
-        PCHIdentifierLookupTrait Info(*this, Chain[J]->Stream, II);
-        std::pair<const char*,unsigned> Key(II->getNameStart(),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 (Context)
-    InitializeContext(*Context);
-
-  return Success;
-}
-
-PCHReader::PCHReadResult PCHReader::ReadPCHCore(llvm::StringRef FileName) {
-  Chain.push_back(new PerFileData());
-  PerFileData &F = *Chain.back();
-
-  // Set the PCH file name.
-  F.FileName = FileName;
-
-  // Open the PCH file.
-  //
-  // FIXME: This shouldn't be here, we should just take a raw_ostream.
-  std::string ErrStr;
-  F.Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
-  if (!F.Buffer) {
-    Error(ErrStr.c_str());
-    return IgnorePCH;
-  }
-
-  // Initialize the stream
-  F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(),
-                    (const unsigned char *)F.Buffer->getBufferEnd());
-  llvm::BitstreamCursor &Stream = F.Stream;
-  Stream.init(F.StreamFile);
-  F.SizeInBits = F.Buffer->getBufferSize() * 8;
-
-  // Sniff for the signature.
-  if (Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'P' ||
-      Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'H') {
-    Diag(diag::err_not_a_pch_file) << FileName;
-    return Failure;
-  }
-
-  while (!Stream.AtEndOfStream()) {
-    unsigned Code = Stream.ReadCode();
-
-    if (Code != llvm::bitc::ENTER_SUBBLOCK) {
-      Error("invalid record at top-level of PCH file");
-      return Failure;
-    }
-
-    unsigned BlockID = Stream.ReadSubBlockID();
-
-    // We only know the PCH subblock ID.
-    switch (BlockID) {
-    case llvm::bitc::BLOCKINFO_BLOCK_ID:
-      if (Stream.ReadBlockInfoBlock()) {
-        Error("malformed BlockInfoBlock in PCH file");
-        return Failure;
-      }
-      break;
-    case pch::PCH_BLOCK_ID:
-      switch (ReadPCHBlock(F)) {
-      case Success:
-        break;
-
-      case Failure:
-        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.
-
-        // Clear out any preallocated source location entries, so that
-        // the source manager does not try to resolve them later.
-        SourceMgr.ClearPreallocatedSLocEntries();
-
-        // Remove the stat cache.
-        if (F.StatCache)
-          FileMgr.removeStatCache((PCHStatCache*)F.StatCache);
-
-        return IgnorePCH;
-      }
-      break;
-    default:
-      if (Stream.SkipBlock()) {
-        Error("malformed block record in PCH file");
-        return Failure;
-      }
-      break;
-    }
-  }
-
-  return Success;
-}
-
-void PCHReader::setPreprocessor(Preprocessor &pp) {
-  PP = &pp;
-
-  unsigned TotalNum = 0;
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I)
-    TotalNum += Chain[I]->NumPreallocatedPreprocessingEntities;
-  if (TotalNum) {
-    if (!PP->getPreprocessingRecord())
-      PP->createPreprocessingRecord();
-    PP->getPreprocessingRecord()->SetExternalSource(*this, TotalNum);
-  }
-}
-
-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);
-  PP->setExternalSource(this);
-
-  // Load the translation unit declaration
-  GetTranslationUnitDecl();
-
-  // 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));
-  if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) {
-    QualType FileType = GetType(File);
-    if (FileType.isNull()) {
-      Error("FILE type is NULL");
-      return;
-    }
-    if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
-      Context->setFILEDecl(Typedef->getDecl());
-    else {
-      const TagType *Tag = FileType->getAs<TagType>();
-      if (!Tag) {
-        Error("Invalid FILE type in PCH file");
-        return;
-      }
-      Context->setFILEDecl(Tag->getDecl());
-    }
-  }
-  if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) {
-    QualType Jmp_bufType = GetType(Jmp_buf);
-    if (Jmp_bufType.isNull()) {
-      Error("jmp_bug type is NULL");
-      return;
-    }
-    if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
-      Context->setjmp_bufDecl(Typedef->getDecl());
-    else {
-      const TagType *Tag = Jmp_bufType->getAs<TagType>();
-      if (!Tag) {
-        Error("Invalid jmp_bug type in PCH file");
-        return;
-      }
-      Context->setjmp_bufDecl(Tag->getDecl());
-    }
-  }
-  if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) {
-    QualType Sigjmp_bufType = GetType(Sigjmp_buf);
-    if (Sigjmp_bufType.isNull()) {
-      Error("sigjmp_buf type is NULL");
-      return;
-    }
-    if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
-      Context->setsigjmp_bufDecl(Typedef->getDecl());
-    else {
-      const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
-      assert(Tag && "Invalid sigjmp_buf type in PCH file");
-      Context->setsigjmp_bufDecl(Tag->getDecl());
-    }
-  }
-  if (unsigned ObjCIdRedef
-        = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION])
-    Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef);
-  if (unsigned ObjCClassRedef
-      = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
-    Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
-  if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
-    Context->setBlockDescriptorType(GetType(String));
-  if (unsigned String
-      = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
-    Context->setBlockDescriptorExtendedType(GetType(String));
-  if (unsigned ObjCSelRedef
-      = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION])
-    Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef);
-  if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_NS_CONSTANT_STRING])
-    Context->setNSConstantStringType(GetType(String));
-
-  if (SpecialTypes[pch::SPECIAL_TYPE_INT128_INSTALLED])
-    Context->setInt128Installed();
-}
-
-/// \brief Retrieve the name of the original source file name
-/// directly from the PCH file, without actually loading the PCH
-/// file.
-std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
-                                             Diagnostic &Diags) {
-  // Open the PCH file.
-  std::string ErrStr;
-  llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
-  Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr));
-  if (!Buffer) {
-    Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr;
-    return std::string();
-  }
-
-  // Initialize the stream
-  llvm::BitstreamReader StreamFile;
-  llvm::BitstreamCursor Stream;
-  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
-                  (const unsigned char *)Buffer->getBufferEnd());
-  Stream.init(StreamFile);
-
-  // Sniff for the signature.
-  if (Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'P' ||
-      Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'H') {
-    Diags.Report(diag::err_fe_not_a_pch_file) << PCHFileName;
-    return std::string();
-  }
-
-  RecordData Record;
-  while (!Stream.AtEndOfStream()) {
-    unsigned Code = Stream.ReadCode();
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      unsigned BlockID = Stream.ReadSubBlockID();
-
-      // We only know the PCH subblock ID.
-      switch (BlockID) {
-      case pch::PCH_BLOCK_ID:
-        if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
-          Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName;
-          return std::string();
-        }
-        break;
-
-      default:
-        if (Stream.SkipBlock()) {
-          Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName;
-          return std::string();
-        }
-        break;
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (Stream.ReadBlockEnd()) {
-        Diags.Report(diag::err_fe_pch_error_at_end_block) << PCHFileName;
-        return std::string();
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      Stream.ReadAbbrevRecord();
-      continue;
-    }
-
-    Record.clear();
-    const char *BlobStart = 0;
-    unsigned BlobLen = 0;
-    if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
-          == pch::ORIGINAL_FILE_NAME)
-      return std::string(BlobStart, BlobLen);
-  }
-
-  return std::string();
-}
-
-/// \brief Parse the record that corresponds to a LangOptions data
-/// structure.
-///
-/// This routine compares the language options used to generate the
-/// PCH file against the language options set for the current
-/// compilation. For each option, we classify differences between the
-/// two compiler states as either "benign" or "important". Benign
-/// differences don't matter, and we accept them without complaint
-/// (and without modifying the language options). Differences between
-/// the states for important options cause the PCH file to be
-/// unusable, so we emit a warning and return true to indicate that
-/// there was an error.
-///
-/// \returns true if the PCH file is unacceptable, false otherwise.
-bool PCHReader::ParseLanguageOptions(
-                             const llvm::SmallVectorImpl<uint64_t> &Record) {
-  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(GNUKeywords);
-    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(ObjCNonFragileABI2);
-    PARSE_LANGOPT(NoConstantCFStrings);
-    PARSE_LANGOPT(PascalStrings);
-    PARSE_LANGOPT(WritableStrings);
-    PARSE_LANGOPT(LaxVectorConversions);
-    PARSE_LANGOPT(AltiVec);
-    PARSE_LANGOPT(Exceptions);
-    PARSE_LANGOPT(SjLjExceptions);
-    PARSE_LANGOPT(NeXTRuntime);
-    PARSE_LANGOPT(Freestanding);
-    PARSE_LANGOPT(NoBuiltin);
-    PARSE_LANGOPT(ThreadsafeStatics);
-    PARSE_LANGOPT(POSIXThreads);
-    PARSE_LANGOPT(Blocks);
-    PARSE_LANGOPT(EmitAllDecls);
-    PARSE_LANGOPT(MathErrno);
-    LangOpts.setSignedOverflowBehavior((LangOptions::SignedOverflowBehaviorTy)
-                                       Record[Idx++]);
-    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);
-    PARSE_LANGOPT(ShortWChar);
-    LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]);
-    LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx++]);
-    LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
-                                   Record[Idx++]);
-    PARSE_LANGOPT(InstantiationDepth);
-    PARSE_LANGOPT(OpenCL);
-    PARSE_LANGOPT(CatchUndefined);
-    // FIXME: Missing ElideConstructors?!
-  #undef PARSE_LANGOPT
-
-    return Listener->ReadLanguageOptions(LangOpts);
-  }
-
-  return false;
-}
-
-void PCHReader::ReadPreprocessedEntities() {
-  ReadDefinedMacros();
-}
-
-/// \brief Get the correct cursor and offset for loading a type.
-PCHReader::RecordLocation PCHReader::TypeCursorForIndex(unsigned Index) {
-  PerFileData *F = 0;
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    F = Chain[N - I - 1];
-    if (Index < F->LocalNumTypes)
-      break;
-    Index -= F->LocalNumTypes;
-  }
-  assert(F && F->LocalNumTypes > Index && "Broken chain");
-  return RecordLocation(&F->DeclsCursor, F->TypeOffsets[Index]);
-}
-
-/// \brief Read and return the type with the given index..
-///
-/// The index is the type ID, shifted and minus the number of predefs. This
-/// routine actually reads the record corresponding to the type at the given
-/// location. It is a helper routine for GetType, which deals with reading type
-/// IDs.
-QualType PCHReader::ReadTypeRecord(unsigned Index) {
-  RecordLocation Loc = TypeCursorForIndex(Index);
-  llvm::BitstreamCursor &DeclsCursor = *Loc.first;
-
-  // Keep track of where we are in the stream, then jump back there
-  // after reading this type.
-  SavedStreamPosition SavedPosition(DeclsCursor);
-
-  ReadingKindTracker ReadingKind(Read_Type, *this);
-
-  // Note that we are loading a type record.
-  Deserializing AType(this);
-
-  DeclsCursor.JumpToBit(Loc.second);
-  RecordData Record;
-  unsigned Code = DeclsCursor.ReadCode();
-  switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
-  case pch::TYPE_EXT_QUAL: {
-    if (Record.size() != 2) {
-      Error("Incorrect encoding of extended qualifier type");
-      return QualType();
-    }
-    QualType Base = GetType(Record[0]);
-    Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]);
-    return Context->getQualifiedType(Base, Quals);
-  }
-
-  case pch::TYPE_COMPLEX: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of complex type");
-      return QualType();
-    }
-    QualType ElemType = GetType(Record[0]);
-    return Context->getComplexType(ElemType);
-  }
-
-  case pch::TYPE_POINTER: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of pointer type");
-      return QualType();
-    }
-    QualType PointeeType = GetType(Record[0]);
-    return Context->getPointerType(PointeeType);
-  }
-
-  case pch::TYPE_BLOCK_POINTER: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of block pointer type");
-      return QualType();
-    }
-    QualType PointeeType = GetType(Record[0]);
-    return Context->getBlockPointerType(PointeeType);
-  }
-
-  case pch::TYPE_LVALUE_REFERENCE: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of lvalue reference type");
-      return QualType();
-    }
-    QualType PointeeType = GetType(Record[0]);
-    return Context->getLValueReferenceType(PointeeType);
-  }
-
-  case pch::TYPE_RVALUE_REFERENCE: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of rvalue reference type");
-      return QualType();
-    }
-    QualType PointeeType = GetType(Record[0]);
-    return Context->getRValueReferenceType(PointeeType);
-  }
-
-  case pch::TYPE_MEMBER_POINTER: {
-    if (Record.size() != 2) {
-      Error("Incorrect encoding of member pointer type");
-      return QualType();
-    }
-    QualType PointeeType = GetType(Record[0]);
-    QualType ClassType = GetType(Record[1]);
-    return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
-  }
-
-  case pch::TYPE_CONSTANT_ARRAY: {
-    QualType ElementType = GetType(Record[0]);
-    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
-    unsigned IndexTypeQuals = Record[2];
-    unsigned Idx = 3;
-    llvm::APInt Size = ReadAPInt(Record, Idx);
-    return Context->getConstantArrayType(ElementType, Size,
-                                         ASM, IndexTypeQuals);
-  }
-
-  case pch::TYPE_INCOMPLETE_ARRAY: {
-    QualType ElementType = GetType(Record[0]);
-    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
-    unsigned IndexTypeQuals = Record[2];
-    return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
-  }
-
-  case pch::TYPE_VARIABLE_ARRAY: {
-    QualType ElementType = GetType(Record[0]);
-    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
-    unsigned IndexTypeQuals = Record[2];
-    SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]);
-    SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]);
-    return Context->getVariableArrayType(ElementType, ReadExpr(DeclsCursor),
-                                         ASM, IndexTypeQuals,
-                                         SourceRange(LBLoc, RBLoc));
-  }
-
-  case pch::TYPE_VECTOR: {
-    if (Record.size() != 3) {
-      Error("incorrect encoding of vector type in PCH file");
-      return QualType();
-    }
-
-    QualType ElementType = GetType(Record[0]);
-    unsigned NumElements = Record[1];
-    unsigned AltiVecSpec = Record[2];
-    return Context->getVectorType(ElementType, NumElements,
-                                  (VectorType::AltiVecSpecific)AltiVecSpec);
-  }
-
-  case pch::TYPE_EXT_VECTOR: {
-    if (Record.size() != 3) {
-      Error("incorrect encoding of extended vector type in PCH file");
-      return QualType();
-    }
-
-    QualType ElementType = GetType(Record[0]);
-    unsigned NumElements = Record[1];
-    return Context->getExtVectorType(ElementType, NumElements);
-  }
-
-  case pch::TYPE_FUNCTION_NO_PROTO: {
-    if (Record.size() != 4) {
-      Error("incorrect encoding of no-proto function type");
-      return QualType();
-    }
-    QualType ResultType = GetType(Record[0]);
-    FunctionType::ExtInfo Info(Record[1], Record[2], (CallingConv)Record[3]);
-    return Context->getFunctionNoProtoType(ResultType, Info);
-  }
-
-  case pch::TYPE_FUNCTION_PROTO: {
-    QualType ResultType = GetType(Record[0]);
-    bool NoReturn = Record[1];
-    unsigned RegParm = Record[2];
-    CallingConv CallConv = (CallingConv)Record[3];
-    unsigned Idx = 4;
-    unsigned NumParams = Record[Idx++];
-    llvm::SmallVector<QualType, 16> ParamTypes;
-    for (unsigned I = 0; I != NumParams; ++I)
-      ParamTypes.push_back(GetType(Record[Idx++]));
-    bool isVariadic = Record[Idx++];
-    unsigned Quals = Record[Idx++];
-    bool hasExceptionSpec = Record[Idx++];
-    bool hasAnyExceptionSpec = Record[Idx++];
-    unsigned NumExceptions = Record[Idx++];
-    llvm::SmallVector<QualType, 2> Exceptions;
-    for (unsigned I = 0; I != NumExceptions; ++I)
-      Exceptions.push_back(GetType(Record[Idx++]));
-    return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
-                                    isVariadic, Quals, hasExceptionSpec,
-                                    hasAnyExceptionSpec, NumExceptions,
-                                    Exceptions.data(),
-                                    FunctionType::ExtInfo(NoReturn, RegParm,
-                                                          CallConv));
-  }
-
-  case pch::TYPE_UNRESOLVED_USING:
-    return Context->getTypeDeclType(
-             cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0])));
-
-  case pch::TYPE_TYPEDEF: {
-    if (Record.size() != 2) {
-      Error("incorrect encoding of typedef type");
-      return QualType();
-    }
-    TypedefDecl *Decl = cast<TypedefDecl>(GetDecl(Record[0]));
-    QualType Canonical = GetType(Record[1]);
-    return Context->getTypedefType(Decl, Canonical);
-  }
-
-  case pch::TYPE_TYPEOF_EXPR:
-    return Context->getTypeOfExprType(ReadExpr(DeclsCursor));
-
-  case pch::TYPE_TYPEOF: {
-    if (Record.size() != 1) {
-      Error("incorrect encoding of typeof(type) in PCH file");
-      return QualType();
-    }
-    QualType UnderlyingType = GetType(Record[0]);
-    return Context->getTypeOfType(UnderlyingType);
-  }
-
-  case pch::TYPE_DECLTYPE:
-    return Context->getDecltypeType(ReadExpr(DeclsCursor));
-
-  case pch::TYPE_RECORD: {
-    if (Record.size() != 2) {
-      Error("incorrect encoding of record type");
-      return QualType();
-    }
-    bool IsDependent = Record[0];
-    QualType T = Context->getRecordType(cast<RecordDecl>(GetDecl(Record[1])));
-    T->Dependent = IsDependent;
-    return T;
-  }
-
-  case pch::TYPE_ENUM: {
-    if (Record.size() != 2) {
-      Error("incorrect encoding of enum type");
-      return QualType();
-    }
-    bool IsDependent = Record[0];
-    QualType T = Context->getEnumType(cast<EnumDecl>(GetDecl(Record[1])));
-    T->Dependent = IsDependent;
-    return T;
-  }
-
-  case pch::TYPE_ELABORATED: {
-    unsigned Idx = 0;
-    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
-    QualType NamedType = GetType(Record[Idx++]);
-    return Context->getElaboratedType(Keyword, NNS, NamedType);
-  }
-
-  case pch::TYPE_OBJC_INTERFACE: {
-    unsigned Idx = 0;
-    ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
-    return Context->getObjCInterfaceType(ItfD);
-  }
-
-  case pch::TYPE_OBJC_OBJECT: {
-    unsigned Idx = 0;
-    QualType Base = GetType(Record[Idx++]);
-    unsigned NumProtos = Record[Idx++];
-    llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
-    for (unsigned I = 0; I != NumProtos; ++I)
-      Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
-    return Context->getObjCObjectType(Base, Protos.data(), NumProtos);    
-  }
-
-  case pch::TYPE_OBJC_OBJECT_POINTER: {
-    unsigned Idx = 0;
-    QualType Pointee = GetType(Record[Idx++]);
-    return Context->getObjCObjectPointerType(Pointee);
-  }
-
-  case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
-    unsigned Idx = 0;
-    QualType Parm = GetType(Record[Idx++]);
-    QualType Replacement = GetType(Record[Idx++]);
-    return
-      Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
-                                            Replacement);
-  }
-
-  case pch::TYPE_INJECTED_CLASS_NAME: {
-    CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0]));
-    QualType TST = GetType(Record[1]); // probably derivable
-    // FIXME: ASTContext::getInjectedClassNameType is not currently suitable
-    // for PCH reading, too much interdependencies.
-    return
-      QualType(new (*Context, TypeAlignment) InjectedClassNameType(D, TST), 0);
-  }
-  
-  case pch::TYPE_TEMPLATE_TYPE_PARM: {
-    unsigned Idx = 0;
-    unsigned Depth = Record[Idx++];
-    unsigned Index = Record[Idx++];
-    bool Pack = Record[Idx++];
-    IdentifierInfo *Name = GetIdentifierInfo(Record, Idx);
-    return Context->getTemplateTypeParmType(Depth, Index, Pack, Name);
-  }
-  
-  case pch::TYPE_DEPENDENT_NAME: {
-    unsigned Idx = 0;
-    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
-    const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx);
-    QualType Canon = GetType(Record[Idx++]);
-    return Context->getDependentNameType(Keyword, NNS, Name, Canon);
-  }
-  
-  case pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {
-    unsigned Idx = 0;
-    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
-    const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx);
-    unsigned NumArgs = Record[Idx++];
-    llvm::SmallVector<TemplateArgument, 8> Args;
-    Args.reserve(NumArgs);
-    while (NumArgs--)
-      Args.push_back(ReadTemplateArgument(DeclsCursor, Record, Idx));
-    return Context->getDependentTemplateSpecializationType(Keyword, NNS, Name,
-                                                      Args.size(), Args.data());
-  }
-  
-  case pch::TYPE_DEPENDENT_SIZED_ARRAY: {
-    unsigned Idx = 0;
-
-    // ArrayType
-    QualType ElementType = GetType(Record[Idx++]);
-    ArrayType::ArraySizeModifier ASM
-      = (ArrayType::ArraySizeModifier)Record[Idx++];
-    unsigned IndexTypeQuals = Record[Idx++];
-
-    // DependentSizedArrayType
-    Expr *NumElts = ReadExpr(DeclsCursor);
-    SourceRange Brackets = ReadSourceRange(Record, Idx);
-
-    return Context->getDependentSizedArrayType(ElementType, NumElts, ASM,
-                                               IndexTypeQuals, Brackets);
-  }
-
-  case pch::TYPE_TEMPLATE_SPECIALIZATION: {
-    unsigned Idx = 0;
-    bool IsDependent = Record[Idx++];
-    TemplateName Name = ReadTemplateName(Record, Idx);
-    llvm::SmallVector<TemplateArgument, 8> Args;
-    ReadTemplateArgumentList(Args, DeclsCursor, Record, Idx);
-    QualType Canon = GetType(Record[Idx++]);
-    QualType T;
-    if (Canon.isNull())
-      T = Context->getCanonicalTemplateSpecializationType(Name, Args.data(),
-                                                          Args.size());
-    else
-      T = Context->getTemplateSpecializationType(Name, Args.data(),
-                                                 Args.size(), Canon);
-    T->Dependent = IsDependent;
-    return T;
-  }
-  }
-  // Suppress a GCC warning
-  return QualType();
-}
-
-namespace {
-
-class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
-  PCHReader &Reader;
-  llvm::BitstreamCursor &DeclsCursor;
-  const PCHReader::RecordData &Record;
-  unsigned &Idx;
-
-public:
-  TypeLocReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor,
-                const PCHReader::RecordData &Record, unsigned &Idx)
-    : Reader(Reader), DeclsCursor(Cursor), Record(Record), Idx(Idx) { }
-
-  // We want compile-time assurance that we've enumerated all of
-  // these, so unfortunately we have to declare them first, then
-  // define them out-of-line.
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
-  void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
-#include "clang/AST/TypeLocNodes.def"
-
-  void VisitFunctionTypeLoc(FunctionTypeLoc);
-  void VisitArrayTypeLoc(ArrayTypeLoc);
-};
-
-}
-
-void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
-  // nothing to do
-}
-void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
-  TL.setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  if (TL.needsExtraLocalData()) {
-    TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
-    TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
-    TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));
-    TL.setModeAttr(Record[Idx++]);
-  }
-}
-void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
-  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
-  TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
-  TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
-  TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
-  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
-  TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  if (Record[Idx++])
-    TL.setSizeExpr(Reader.ReadExpr(DeclsCursor));
-  else
-    TL.setSizeExpr(0);
-}
-void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocReader::VisitDependentSizedArrayTypeLoc(
-                                            DependentSizedArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
-                                        DependentSizedExtVectorTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
-  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
-    TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
-  }
-}
-void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
-  VisitFunctionTypeLoc(TL);
-}
-void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
-  VisitFunctionTypeLoc(TL);
-}
-void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
-  TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
-  TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-}
-void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
-                                            SubstTemplateTypeParmTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitTemplateSpecializationTypeLoc(
-                                           TemplateSpecializationTypeLoc TL) {
-  TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
-    TL.setArgLocInfo(i,
-        Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(),
-                                          DeclsCursor, Record, Idx));
-}
-void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
-  TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-}
-void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
-  TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
-       DependentTemplateSpecializationTypeLoc TL) {
-  TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
-    TL.setArgLocInfo(I,
-        Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(),
-                                          DeclsCursor, Record, Idx));
-}
-void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
-  TL.setHasBaseTypeAsWritten(Record[Idx++]);
-  TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
-    TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
-  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-TypeSourceInfo *PCHReader::GetTypeSourceInfo(llvm::BitstreamCursor &DeclsCursor,
-                                             const RecordData &Record,
-                                             unsigned &Idx) {
-  QualType InfoTy = GetType(Record[Idx++]);
-  if (InfoTy.isNull())
-    return 0;
-
-  TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy);
-  TypeLocReader TLR(*this, DeclsCursor, Record, Idx);
-  for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
-    TLR.Visit(TL);
-  return TInfo;
-}
-
-QualType PCHReader::GetType(pch::TypeID ID) {
-  unsigned FastQuals = ID & Qualifiers::FastMask;
-  unsigned Index = ID >> Qualifiers::FastWidth;
-
-  if (Index < pch::NUM_PREDEF_TYPE_IDS) {
-    QualType T;
-    switch ((pch::PredefinedTypeIDs)Index) {
-    case pch::PREDEF_TYPE_NULL_ID: return QualType();
-    case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
-    case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
-
-    case pch::PREDEF_TYPE_CHAR_U_ID:
-    case pch::PREDEF_TYPE_CHAR_S_ID:
-      // FIXME: Check that the signedness of CharTy is correct!
-      T = Context->CharTy;
-      break;
-
-    case pch::PREDEF_TYPE_UCHAR_ID:      T = Context->UnsignedCharTy;     break;
-    case pch::PREDEF_TYPE_USHORT_ID:     T = Context->UnsignedShortTy;    break;
-    case pch::PREDEF_TYPE_UINT_ID:       T = Context->UnsignedIntTy;      break;
-    case pch::PREDEF_TYPE_ULONG_ID:      T = Context->UnsignedLongTy;     break;
-    case pch::PREDEF_TYPE_ULONGLONG_ID:  T = Context->UnsignedLongLongTy; break;
-    case pch::PREDEF_TYPE_UINT128_ID:    T = Context->UnsignedInt128Ty;   break;
-    case pch::PREDEF_TYPE_SCHAR_ID:      T = Context->SignedCharTy;       break;
-    case pch::PREDEF_TYPE_WCHAR_ID:      T = Context->WCharTy;            break;
-    case pch::PREDEF_TYPE_SHORT_ID:      T = Context->ShortTy;            break;
-    case pch::PREDEF_TYPE_INT_ID:        T = Context->IntTy;              break;
-    case pch::PREDEF_TYPE_LONG_ID:       T = Context->LongTy;             break;
-    case pch::PREDEF_TYPE_LONGLONG_ID:   T = Context->LongLongTy;         break;
-    case pch::PREDEF_TYPE_INT128_ID:     T = Context->Int128Ty;           break;
-    case pch::PREDEF_TYPE_FLOAT_ID:      T = Context->FloatTy;            break;
-    case pch::PREDEF_TYPE_DOUBLE_ID:     T = Context->DoubleTy;           break;
-    case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy;       break;
-    case pch::PREDEF_TYPE_OVERLOAD_ID:   T = Context->OverloadTy;         break;
-    case pch::PREDEF_TYPE_DEPENDENT_ID:  T = Context->DependentTy;        break;
-    case pch::PREDEF_TYPE_NULLPTR_ID:    T = Context->NullPtrTy;          break;
-    case pch::PREDEF_TYPE_CHAR16_ID:     T = Context->Char16Ty;           break;
-    case pch::PREDEF_TYPE_CHAR32_ID:     T = Context->Char32Ty;           break;
-    case pch::PREDEF_TYPE_OBJC_ID:       T = Context->ObjCBuiltinIdTy;    break;
-    case pch::PREDEF_TYPE_OBJC_CLASS:    T = Context->ObjCBuiltinClassTy; break;
-    case pch::PREDEF_TYPE_OBJC_SEL:      T = Context->ObjCBuiltinSelTy;   break;
-    }
-
-    assert(!T.isNull() && "Unknown predefined type");
-    return T.withFastQualifiers(FastQuals);
-  }
-
-  Index -= pch::NUM_PREDEF_TYPE_IDS;
-  assert(Index < TypesLoaded.size() && "Type index out-of-range");
-  if (TypesLoaded[Index].isNull()) {
-    TypesLoaded[Index] = ReadTypeRecord(Index);
-    TypesLoaded[Index]->setFromPCH();
-    if (DeserializationListener)
-      DeserializationListener->TypeRead(ID >> Qualifiers::FastWidth,
-                                        TypesLoaded[Index]);
-  }
-
-  return TypesLoaded[Index].withFastQualifiers(FastQuals);
-}
-
-TemplateArgumentLocInfo
-PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
-                                      llvm::BitstreamCursor &DeclsCursor,
-                                      const RecordData &Record,
-                                      unsigned &Index) {
-  switch (Kind) {
-  case TemplateArgument::Expression:
-    return ReadExpr(DeclsCursor);
-  case TemplateArgument::Type:
-    return GetTypeSourceInfo(DeclsCursor, Record, Index);
-  case TemplateArgument::Template: {
-    SourceRange QualifierRange = ReadSourceRange(Record, Index);
-    SourceLocation TemplateNameLoc = ReadSourceLocation(Record, Index);
-    return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc);
-  }
-  case TemplateArgument::Null:
-  case TemplateArgument::Integral:
-  case TemplateArgument::Declaration:
-  case TemplateArgument::Pack:
-    return TemplateArgumentLocInfo();
-  }
-  llvm_unreachable("unexpected template argument loc");
-  return TemplateArgumentLocInfo();
-}
-
-TemplateArgumentLoc
-PCHReader::ReadTemplateArgumentLoc(llvm::BitstreamCursor &DeclsCursor,
-                                   const RecordData &Record, unsigned &Index) {
-  TemplateArgument Arg = ReadTemplateArgument(DeclsCursor, Record, Index);
-
-  if (Arg.getKind() == TemplateArgument::Expression) {
-    if (Record[Index++]) // bool InfoHasSameExpr.
-      return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr()));
-  }
-  return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(Arg.getKind(),
-                                                             DeclsCursor,
-                                                             Record, Index));
-}
-
-Decl *PCHReader::GetExternalDecl(uint32_t ID) {
-  return GetDecl(ID);
-}
-
-TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() {
-  if (!DeclsLoaded[0]) {
-    ReadDeclRecord(0, 0);
-    if (DeserializationListener)
-      DeserializationListener->DeclRead(1, DeclsLoaded[0]);
-  }
-
-  return cast<TranslationUnitDecl>(DeclsLoaded[0]);
-}
-
-Decl *PCHReader::GetDecl(pch::DeclID ID) {
-  if (ID == 0)
-    return 0;
-
-  if (ID > DeclsLoaded.size()) {
-    Error("declaration ID out-of-range for PCH file");
-    return 0;
-  }
-
-  unsigned Index = ID - 1;
-  if (!DeclsLoaded[Index]) {
-    ReadDeclRecord(Index, ID);
-    if (DeserializationListener)
-      DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
-  }
-
-  return DeclsLoaded[Index];
-}
-
-/// \brief Resolve the offset of a statement into a statement.
-///
-/// This operation will read a new statement from the external
-/// source each time it is called, and is meant to be used via a
-/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
-Stmt *PCHReader::GetExternalDeclStmt(uint64_t Offset) {
-  // Offset here is a global offset across the entire chain.
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    PerFileData &F = *Chain[N - I - 1];
-    if (Offset < F.SizeInBits) {
-      // Since we know that this statement is part of a decl, make sure to use
-      // the decl cursor to read it.
-      F.DeclsCursor.JumpToBit(Offset);
-      return ReadStmtFromStream(F.DeclsCursor);
-    }
-    Offset -= F.SizeInBits;
-  }
-  llvm_unreachable("Broken chain");
-}
-
-bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC,
-                                         llvm::SmallVectorImpl<Decl*> &Decls) {
-  assert(DC->hasExternalLexicalStorage() &&
-         "DeclContext has no lexical decls in storage");
-
-  // There might be lexical decls in multiple parts of the chain, for the TU
-  // at least.
-  DeclContextInfos &Infos = DeclContextOffsets[DC];
-  for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end();
-       I != E; ++I) {
-    // IDs can be 0 if this context doesn't contain declarations.
-    if (!I->LexicalDecls)
-      continue;
-
-    // Load all of the declaration IDs
-    for (const pch::DeclID *ID = I->LexicalDecls,
-                           *IDE = ID + I->NumLexicalDecls;
-         ID != IDE; ++ID)
-      Decls.push_back(GetDecl(*ID));
-  }
-
-  ++NumLexicalDeclContextsRead;
-  return false;
-}
-
-DeclContext::lookup_result
-PCHReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
-                                          DeclarationName Name) {
-  assert(DC->hasExternalVisibleStorage() &&
-         "DeclContext has no visible decls in storage");
-
-  llvm::SmallVector<VisibleDeclaration, 64> Decls;
-  // There might be lexical decls in multiple parts of the chain, for the TU
-  // and namespaces.
-  DeclContextInfos &Infos = DeclContextOffsets[DC];
-  for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end();
-       I != E; ++I) {
-    uint64_t Offset = I->OffsetToVisibleDecls;
-    if (Offset == 0)
-      continue;
-
-    llvm::BitstreamCursor &DeclsCursor = *I->Stream;
-
-    // Keep track of where we are in the stream, then jump back there
-    // after reading this context.
-    SavedStreamPosition SavedPosition(DeclsCursor);
-
-    // Load the record containing all of the declarations visible in
-    // this context.
-    DeclsCursor.JumpToBit(Offset);
-    RecordData Record;
-    unsigned Code = DeclsCursor.ReadCode();
-    unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
-    if (RecCode != pch::DECL_CONTEXT_VISIBLE) {
-      Error("Expected visible block");
-      return DeclContext::lookup_result(DeclContext::lookup_iterator(),
-                                        DeclContext::lookup_iterator());
-    }
-
-    if (Record.empty())
-      continue;
-
-    unsigned Idx = 0;
-    while (Idx < Record.size()) {
-      Decls.push_back(VisibleDeclaration());
-      Decls.back().Name = ReadDeclarationName(Record, Idx);
-
-      unsigned Size = Record[Idx++];
-      llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
-      LoadedDecls.reserve(Size);
-      for (unsigned J = 0; J < Size; ++J)
-        LoadedDecls.push_back(Record[Idx++]);
-    }
-  }
-
-  ++NumVisibleDeclContextsRead;
-
-  SetExternalVisibleDecls(DC, Decls);
-  return const_cast<DeclContext*>(DC)->lookup(Name);
-}
-
-void PCHReader::PassInterestingDeclsToConsumer() {
-  assert(Consumer);
-  while (!InterestingDecls.empty()) {
-    DeclGroupRef DG(InterestingDecls.front());
-    InterestingDecls.pop_front();
-    Consumer->HandleInterestingDecl(DG);
-  }
-}
-
-void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
-  this->Consumer = Consumer;
-
-  if (!Consumer)
-    return;
-
-  for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
-    // Force deserialization of this decl, which will cause it to be queued for
-    // passing to the consumer.
-    GetDecl(ExternalDefinitions[I]);
-  }
-
-  PassInterestingDeclsToConsumer();
-}
-
-void PCHReader::PrintStats() {
-  std::fprintf(stderr, "*** PCH Statistics:\n");
-
-  unsigned NumTypesLoaded
-    = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
-                                      QualType());
-  unsigned NumDeclsLoaded
-    = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
-                                      (Decl *)0);
-  unsigned NumIdentifiersLoaded
-    = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
-                                            IdentifiersLoaded.end(),
-                                            (IdentifierInfo *)0);
-  unsigned NumSelectorsLoaded
-    = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
-                                          SelectorsLoaded.end(),
-                                          Selector());
-
-  std::fprintf(stderr, "  %u stat cache hits\n", NumStatHits);
-  std::fprintf(stderr, "  %u stat cache misses\n", NumStatMisses);
-  if (TotalNumSLocEntries)
-    std::fprintf(stderr, "  %u/%u source location entries read (%f%%)\n",
-                 NumSLocEntriesRead, TotalNumSLocEntries,
-                 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
-  if (!TypesLoaded.empty())
-    std::fprintf(stderr, "  %u/%u types read (%f%%)\n",
-                 NumTypesLoaded, (unsigned)TypesLoaded.size(),
-                 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
-  if (!DeclsLoaded.empty())
-    std::fprintf(stderr, "  %u/%u declarations read (%f%%)\n",
-                 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
-                 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
-  if (!IdentifiersLoaded.empty())
-    std::fprintf(stderr, "  %u/%u identifiers read (%f%%)\n",
-                 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
-                 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
-  if (!SelectorsLoaded.empty())
-    std::fprintf(stderr, "  %u/%u selectors read (%f%%)\n",
-                 NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(),
-                 ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 100));
-  if (TotalNumStatements)
-    std::fprintf(stderr, "  %u/%u statements read (%f%%)\n",
-                 NumStatementsRead, TotalNumStatements,
-                 ((float)NumStatementsRead/TotalNumStatements * 100));
-  if (TotalNumMacros)
-    std::fprintf(stderr, "  %u/%u macros read (%f%%)\n",
-                 NumMacrosRead, TotalNumMacros,
-                 ((float)NumMacrosRead/TotalNumMacros * 100));
-  if (TotalLexicalDeclContexts)
-    std::fprintf(stderr, "  %u/%u lexical declcontexts read (%f%%)\n",
-                 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
-                 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
-                  * 100));
-  if (TotalVisibleDeclContexts)
-    std::fprintf(stderr, "  %u/%u visible declcontexts read (%f%%)\n",
-                 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
-                 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
-                  * 100));
-  if (TotalNumMethodPoolEntries) {
-    std::fprintf(stderr, "  %u/%u method pool entries read (%f%%)\n",
-                 NumMethodPoolEntriesRead, TotalNumMethodPoolEntries,
-                 ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries
-                  * 100));
-    std::fprintf(stderr, "  %u method pool misses\n", NumMethodPoolMisses);
-  }
-  std::fprintf(stderr, "\n");
-}
-
-void PCHReader::InitializeSema(Sema &S) {
-  SemaObj = &S;
-  S.ExternalSource = this;
-
-  // Makes sure any declarations that were deserialized "too early"
-  // still get added to the identifier's declaration chains.
-  if (SemaObj->TUScope) {
-    for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
-      SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
-      SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
-    }
-  }
-  PreloadedDecls.clear();
-
-  // If there were any tentative definitions, deserialize them and add
-  // them to Sema's list of tentative definitions.
-  for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
-    VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
-    SemaObj->TentativeDefinitions.push_back(Var);
-  }
-
-  // If there were any unused file scoped decls, deserialize them and add to
-  // Sema's list of unused file scoped decls.
-  for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) {
-    DeclaratorDecl *D = cast<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I]));
-    SemaObj->UnusedFileScopedDecls.push_back(D);
-  }
-
-  // If there were any weak undeclared identifiers, deserialize them and add to
-  // Sema's list of weak undeclared identifiers.
-  if (!WeakUndeclaredIdentifiers.empty()) {
-    unsigned Idx = 0;
-    for (unsigned I = 0, N = WeakUndeclaredIdentifiers[Idx++]; I != N; ++I) {
-      IdentifierInfo *WeakId = GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx);
-      IdentifierInfo *AliasId=GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx);
-      SourceLocation Loc = ReadSourceLocation(WeakUndeclaredIdentifiers, Idx);
-      bool Used = WeakUndeclaredIdentifiers[Idx++];
-      Sema::WeakInfo WI(AliasId, Loc);
-      WI.setUsed(Used);
-      SemaObj->WeakUndeclaredIdentifiers.insert(std::make_pair(WeakId, WI));
-    }
-  }
-
-  // If there were any locally-scoped external declarations,
-  // deserialize them and add them to Sema's table of locally-scoped
-  // external declarations.
-  for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
-    NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
-    SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
-  }
-
-  // If there were any ext_vector type declarations, deserialize them
-  // and add them to Sema's vector of such declarations.
-  for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
-    SemaObj->ExtVectorDecls.push_back(
-                               cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
-
-  // FIXME: Do VTable uses and dynamic classes deserialize too much ?
-  // Can we cut them down before writing them ?
-
-  // If there were any VTable uses, deserialize the information and add it
-  // to Sema's vector and map of VTable uses.
-  if (!VTableUses.empty()) {
-    unsigned Idx = 0;
-    for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) {
-      CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
-      SourceLocation Loc = ReadSourceLocation(VTableUses, Idx);
-      bool DefinitionRequired = VTableUses[Idx++];
-      SemaObj->VTableUses.push_back(std::make_pair(Class, Loc));
-      SemaObj->VTablesUsed[Class] = DefinitionRequired;
-    }
-  }
-
-  // If there were any dynamic classes declarations, deserialize them
-  // and add them to Sema's vector of such declarations.
-  for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I)
-    SemaObj->DynamicClasses.push_back(
-                               cast<CXXRecordDecl>(GetDecl(DynamicClasses[I])));
-
-  // If there were any pending implicit instantiations, deserialize them
-  // and add them to Sema's queue of such instantiations.
-  assert(PendingImplicitInstantiations.size() % 2 == 0 &&
-         "Expected pairs of entries");
-  for (unsigned Idx = 0, N = PendingImplicitInstantiations.size(); Idx < N;) {
-    ValueDecl *D=cast<ValueDecl>(GetDecl(PendingImplicitInstantiations[Idx++]));
-    SourceLocation Loc = ReadSourceLocation(PendingImplicitInstantiations, Idx);
-    SemaObj->PendingImplicitInstantiations.push_back(std::make_pair(D, Loc));
-  }
-
-  // Load the offsets of the declarations that Sema references.
-  // They will be lazily deserialized when needed.
-  if (!SemaDeclRefs.empty()) {
-    assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!");
-    SemaObj->StdNamespace = SemaDeclRefs[0];
-    SemaObj->StdBadAlloc = SemaDeclRefs[1];
-  }
-
-  // If there are @selector references added them to its pool. This is for
-  // implementation of -Wselector.
-  if (!ReferencedSelectorsData.empty()) {
-    unsigned int DataSize = ReferencedSelectorsData.size()-1;
-    unsigned I = 0;
-    while (I < DataSize) {
-      Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]);
-      SourceLocation SelLoc = 
-        SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]);
-      SemaObj->ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
-    }
-  }
-}
-
-IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
-  // Try to find this name within our on-disk hash tables. We start with the
-  // most recent one, since that one contains the most up-to-date info.
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    PCHIdentifierLookupTable *IdTable
-        = (PCHIdentifierLookupTable *)Chain[I]->IdentifierLookupTable;
-    if (!IdTable)
-      continue;
-    std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
-    PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
-    if (Pos == IdTable->end())
-      continue;
-
-    // Dereferencing the iterator has the effect of building the
-    // IdentifierInfo node and populating it with the various
-    // declarations it needs.
-    return *Pos;
-  }
-  return 0;
-}
-
-std::pair<ObjCMethodList, ObjCMethodList>
-PCHReader::ReadMethodPool(Selector Sel) {
-  // Find this selector in a hash table. We want to find the most recent entry.
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    PerFileData &F = *Chain[I];
-    if (!F.SelectorLookupTable)
-      continue;
-
-    PCHSelectorLookupTable *PoolTable
-      = (PCHSelectorLookupTable*)F.SelectorLookupTable;
-    PCHSelectorLookupTable::iterator Pos = PoolTable->find(Sel);
-    if (Pos != PoolTable->end()) {
-      ++NumSelectorsRead;
-      // FIXME: Not quite happy with the statistics here. We probably should
-      // disable this tracking when called via LoadSelector.
-      // Also, should entries without methods count as misses?
-      ++NumMethodPoolEntriesRead;
-      PCHSelectorLookupTrait::data_type Data = *Pos;
-      if (DeserializationListener)
-        DeserializationListener->SelectorRead(Data.ID, Sel);
-      return std::make_pair(Data.Instance, Data.Factory);
-    }
-  }
-
-  ++NumMethodPoolMisses;
-  return std::pair<ObjCMethodList, ObjCMethodList>();
-}
-
-void PCHReader::LoadSelector(Selector Sel) {
-  // It would be complicated to avoid reading the methods anyway. So don't.
-  ReadMethodPool(Sel);
-}
-
-void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
-  assert(ID && "Non-zero identifier ID required");
-  assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
-  IdentifiersLoaded[ID - 1] = II;
-  if (DeserializationListener)
-    DeserializationListener->IdentifierRead(ID, II);
-}
-
-/// \brief Set the globally-visible declarations associated with the given
-/// identifier.
-///
-/// If the PCH reader is currently in a state where the given declaration IDs
-/// cannot safely be resolved, they are queued until it is safe to resolve
-/// them.
-///
-/// \param II an IdentifierInfo that refers to one or more globally-visible
-/// declarations.
-///
-/// \param DeclIDs the set of declaration IDs with the name @p II that are
-/// visible at global scope.
-///
-/// \param Nonrecursive should be true to indicate that the caller knows that
-/// this call is non-recursive, and therefore the globally-visible declarations
-/// will not be placed onto the pending queue.
-void
-PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
-                              const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
-                                   bool Nonrecursive) {
-  if (NumCurrentElementsDeserializing && !Nonrecursive) {
-    PendingIdentifierInfos.push_back(PendingIdentifierInfo());
-    PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
-    PII.II = II;
-    for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I)
-      PII.DeclIDs.push_back(DeclIDs[I]);
-    return;
-  }
-
-  for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
-    NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
-    if (SemaObj) {
-      if (SemaObj->TUScope) {
-        // Introduce this declaration into the translation-unit scope
-        // and add it to the declaration chain for this identifier, so
-        // that (unqualified) name lookup will find it.
-        SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
-        SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
-      }
-    } else {
-      // 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.
-      PreloadedDecls.push_back(D);
-    }
-  }
-}
-
-IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
-  if (ID == 0)
-    return 0;
-
-  if (IdentifiersLoaded.empty()) {
-    Error("no identifier table in PCH file");
-    return 0;
-  }
-
-  assert(PP && "Forgot to set Preprocessor ?");
-  ID -= 1;
-  if (!IdentifiersLoaded[ID]) {
-    unsigned Index = ID;
-    const char *Str = 0;
-    for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-      PerFileData *F = Chain[N - I - 1];
-      if (Index < F->LocalNumIdentifiers) {
-         uint32_t Offset = F->IdentifierOffsets[Index];
-         Str = F->IdentifierTableData + Offset;
-         break;
-      }
-      Index -= F->LocalNumIdentifiers;
-    }
-    assert(Str && "Broken Chain");
-
-    // All of the strings in the PCH file are preceded by a 16-bit
-    // length. Extract that 16-bit length to avoid having to execute
-    // strlen().
-    // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
-    //  unsigned integers.  This is important to avoid integer overflow when
-    //  we cast them to 'unsigned'.
-    const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
-    unsigned StrLen = (((unsigned) StrLenPtr[0])
-                       | (((unsigned) StrLenPtr[1]) << 8)) - 1;
-    IdentifiersLoaded[ID]
-      = &PP->getIdentifierTable().get(Str, StrLen);
-    if (DeserializationListener)
-      DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]);
-  }
-
-  return IdentifiersLoaded[ID];
-}
-
-void PCHReader::ReadSLocEntry(unsigned ID) {
-  ReadSLocEntryRecord(ID);
-}
-
-Selector PCHReader::DecodeSelector(unsigned ID) {
-  if (ID == 0)
-    return Selector();
-
-  if (ID > SelectorsLoaded.size()) {
-    Error("selector ID out of range in PCH file");
-    return Selector();
-  }
-
-  if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) {
-    // Load this selector from the selector table.
-    unsigned Idx = ID - 1;
-    for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-      PerFileData &F = *Chain[N - I - 1];
-      if (Idx < F.LocalNumSelectors) {
-        PCHSelectorLookupTrait Trait(*this);
-        SelectorsLoaded[ID - 1] =
-           Trait.ReadKey(F.SelectorLookupTableData + F.SelectorOffsets[Idx], 0);
-        if (DeserializationListener)
-          DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]);
-        break;
-      }
-      Idx -= F.LocalNumSelectors;
-    }
-  }
-
-  return SelectorsLoaded[ID - 1];
-}
-
-Selector PCHReader::GetExternalSelector(uint32_t ID) { 
-  return DecodeSelector(ID);
-}
-
-uint32_t PCHReader::GetNumExternalSelectors() {
-  // ID 0 (the null selector) is considered an external selector.
-  return getTotalNumSelectors() + 1;
-}
-
-DeclarationName
-PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
-  DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
-  switch (Kind) {
-  case DeclarationName::Identifier:
-    return DeclarationName(GetIdentifierInfo(Record, Idx));
-
-  case DeclarationName::ObjCZeroArgSelector:
-  case DeclarationName::ObjCOneArgSelector:
-  case DeclarationName::ObjCMultiArgSelector:
-    return DeclarationName(GetSelector(Record, Idx));
-
-  case DeclarationName::CXXConstructorName:
-    return Context->DeclarationNames.getCXXConstructorName(
-                          Context->getCanonicalType(GetType(Record[Idx++])));
-
-  case DeclarationName::CXXDestructorName:
-    return Context->DeclarationNames.getCXXDestructorName(
-                          Context->getCanonicalType(GetType(Record[Idx++])));
-
-  case DeclarationName::CXXConversionFunctionName:
-    return Context->DeclarationNames.getCXXConversionFunctionName(
-                          Context->getCanonicalType(GetType(Record[Idx++])));
-
-  case DeclarationName::CXXOperatorName:
-    return Context->DeclarationNames.getCXXOperatorName(
-                                       (OverloadedOperatorKind)Record[Idx++]);
-
-  case DeclarationName::CXXLiteralOperatorName:
-    return Context->DeclarationNames.getCXXLiteralOperatorName(
-                                       GetIdentifierInfo(Record, Idx));
-
-  case DeclarationName::CXXUsingDirective:
-    return DeclarationName::getUsingDirectiveName();
-  }
-
-  // Required to silence GCC warning
-  return DeclarationName();
-}
-
-TemplateName
-PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
-  TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; 
-  switch (Kind) {
-  case TemplateName::Template:
-    return TemplateName(cast_or_null<TemplateDecl>(GetDecl(Record[Idx++])));
-
-  case TemplateName::OverloadedTemplate: {
-    unsigned size = Record[Idx++];
-    UnresolvedSet<8> Decls;
-    while (size--)
-      Decls.addDecl(cast<NamedDecl>(GetDecl(Record[Idx++])));
-
-    return Context->getOverloadedTemplateName(Decls.begin(), Decls.end());
-  }
-    
-  case TemplateName::QualifiedTemplate: {
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
-    bool hasTemplKeyword = Record[Idx++];
-    TemplateDecl *Template = cast<TemplateDecl>(GetDecl(Record[Idx++]));
-    return Context->getQualifiedTemplateName(NNS, hasTemplKeyword, Template);
-  }
-    
-  case TemplateName::DependentTemplate: {
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
-    if (Record[Idx++])  // isIdentifier
-      return Context->getDependentTemplateName(NNS,
-                                               GetIdentifierInfo(Record, Idx));
-    return Context->getDependentTemplateName(NNS,
-                                         (OverloadedOperatorKind)Record[Idx++]);
-  }
-  }
-  
-  assert(0 && "Unhandled template name kind!");
-  return TemplateName();
-}
-
-TemplateArgument
-PCHReader::ReadTemplateArgument(llvm::BitstreamCursor &DeclsCursor,
-                                const RecordData &Record, unsigned &Idx) {
-  switch ((TemplateArgument::ArgKind)Record[Idx++]) {
-  case TemplateArgument::Null:
-    return TemplateArgument();
-  case TemplateArgument::Type:
-    return TemplateArgument(GetType(Record[Idx++]));
-  case TemplateArgument::Declaration:
-    return TemplateArgument(GetDecl(Record[Idx++]));
-  case TemplateArgument::Integral: {
-    llvm::APSInt Value = ReadAPSInt(Record, Idx);
-    QualType T = GetType(Record[Idx++]);
-    return TemplateArgument(Value, T);
-  }
-  case TemplateArgument::Template:
-    return TemplateArgument(ReadTemplateName(Record, Idx));
-  case TemplateArgument::Expression:
-    return TemplateArgument(ReadExpr(DeclsCursor));
-  case TemplateArgument::Pack: {
-    unsigned NumArgs = Record[Idx++];
-    llvm::SmallVector<TemplateArgument, 8> Args;
-    Args.reserve(NumArgs);
-    while (NumArgs--)
-      Args.push_back(ReadTemplateArgument(DeclsCursor, Record, Idx));
-    TemplateArgument TemplArg;
-    TemplArg.setArgumentPack(Args.data(), Args.size(), /*CopyArgs=*/true);
-    return TemplArg;
-  }
-  }
-  
-  assert(0 && "Unhandled template argument kind!");
-  return TemplateArgument();
-}
-
-TemplateParameterList *
-PCHReader::ReadTemplateParameterList(const RecordData &Record, unsigned &Idx) {
-  SourceLocation TemplateLoc = ReadSourceLocation(Record, Idx);
-  SourceLocation LAngleLoc = ReadSourceLocation(Record, Idx);
-  SourceLocation RAngleLoc = ReadSourceLocation(Record, Idx);
-
-  unsigned NumParams = Record[Idx++];
-  llvm::SmallVector<NamedDecl *, 16> Params;
-  Params.reserve(NumParams);
-  while (NumParams--)
-    Params.push_back(cast<NamedDecl>(GetDecl(Record[Idx++])));
-    
-  TemplateParameterList* TemplateParams = 
-    TemplateParameterList::Create(*Context, TemplateLoc, LAngleLoc,
-                                  Params.data(), Params.size(), RAngleLoc);
-  return TemplateParams;
-}
-
-void
-PCHReader::
-ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs,
-                         llvm::BitstreamCursor &DeclsCursor,
-                         const RecordData &Record, unsigned &Idx) {
-  unsigned NumTemplateArgs = Record[Idx++];
-  TemplArgs.reserve(NumTemplateArgs);
-  while (NumTemplateArgs--)
-    TemplArgs.push_back(ReadTemplateArgument(DeclsCursor, Record, Idx));
-}
-
-/// \brief Read a UnresolvedSet structure.
-void PCHReader::ReadUnresolvedSet(UnresolvedSetImpl &Set,
-                                  const RecordData &Record, unsigned &Idx) {
-  unsigned NumDecls = Record[Idx++];
-  while (NumDecls--) {
-    NamedDecl *D = cast<NamedDecl>(GetDecl(Record[Idx++]));
-    AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
-    Set.addDecl(D, AS);
-  }
-}
-
-CXXBaseSpecifier
-PCHReader::ReadCXXBaseSpecifier(llvm::BitstreamCursor &DeclsCursor,
-                                const RecordData &Record, unsigned &Idx) {
-  bool isVirtual = static_cast<bool>(Record[Idx++]);
-  bool isBaseOfClass = static_cast<bool>(Record[Idx++]);
-  AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);
-  TypeSourceInfo *TInfo = GetTypeSourceInfo(DeclsCursor, Record, Idx);
-  SourceRange Range = ReadSourceRange(Record, Idx);
-  return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, TInfo);
-}
-
-std::pair<CXXBaseOrMemberInitializer **, unsigned>
-PCHReader::ReadCXXBaseOrMemberInitializers(llvm::BitstreamCursor &Cursor,
-                                           const RecordData &Record,
-                                           unsigned &Idx) {
-  CXXBaseOrMemberInitializer **BaseOrMemberInitializers = 0;
-  unsigned NumInitializers = Record[Idx++];
-  if (NumInitializers) {
-    ASTContext &C = *getContext();
-
-    BaseOrMemberInitializers
-        = new (C) CXXBaseOrMemberInitializer*[NumInitializers];
-    for (unsigned i=0; i != NumInitializers; ++i) {
-      TypeSourceInfo *BaseClassInfo = 0;
-      bool IsBaseVirtual = false;
-      FieldDecl *Member = 0;
-  
-      bool IsBaseInitializer = Record[Idx++];
-      if (IsBaseInitializer) {
-        BaseClassInfo = GetTypeSourceInfo(Cursor, Record, Idx);
-        IsBaseVirtual = Record[Idx++];
-      } else {
-        Member = cast<FieldDecl>(GetDecl(Record[Idx++]));
-      }
-      SourceLocation MemberLoc = ReadSourceLocation(Record, Idx);
-      Expr *Init = ReadExpr(Cursor);
-      FieldDecl *AnonUnionMember
-          = cast_or_null<FieldDecl>(GetDecl(Record[Idx++]));
-      SourceLocation LParenLoc = ReadSourceLocation(Record, Idx);
-      SourceLocation RParenLoc = ReadSourceLocation(Record, Idx);
-      bool IsWritten = Record[Idx++];
-      unsigned SourceOrderOrNumArrayIndices;
-      llvm::SmallVector<VarDecl *, 8> Indices;
-      if (IsWritten) {
-        SourceOrderOrNumArrayIndices = Record[Idx++];
-      } else {
-        SourceOrderOrNumArrayIndices = Record[Idx++];
-        Indices.reserve(SourceOrderOrNumArrayIndices);
-        for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
-          Indices.push_back(cast<VarDecl>(GetDecl(Record[Idx++])));
-      }
-      
-      CXXBaseOrMemberInitializer *BOMInit;
-      if (IsBaseInitializer) {
-        BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo,
-                                                     IsBaseVirtual, LParenLoc,
-                                                     Init, RParenLoc);
-      } else if (IsWritten) {
-        BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc,
-                                                     LParenLoc, Init, RParenLoc);
-      } else {
-        BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc,
-                                                     LParenLoc, Init, RParenLoc,
-                                                     Indices.data(),
-                                                     Indices.size());
-      }
-
-      BOMInit->setAnonUnionMember(AnonUnionMember);
-      BaseOrMemberInitializers[i] = BOMInit;
-    }
-  }
-
-  return std::make_pair(BaseOrMemberInitializers, NumInitializers);
-}
-
-NestedNameSpecifier *
-PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
-  unsigned N = Record[Idx++];
-  NestedNameSpecifier *NNS = 0, *Prev = 0;
-  for (unsigned I = 0; I != N; ++I) {
-    NestedNameSpecifier::SpecifierKind Kind
-      = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
-    switch (Kind) {
-    case NestedNameSpecifier::Identifier: {
-      IdentifierInfo *II = GetIdentifierInfo(Record, Idx);
-      NNS = NestedNameSpecifier::Create(*Context, Prev, II);
-      break;
-    }
-
-    case NestedNameSpecifier::Namespace: {
-      NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++]));
-      NNS = NestedNameSpecifier::Create(*Context, Prev, NS);
-      break;
-    }
-
-    case NestedNameSpecifier::TypeSpec:
-    case NestedNameSpecifier::TypeSpecWithTemplate: {
-      Type *T = GetType(Record[Idx++]).getTypePtr();
-      bool Template = Record[Idx++];
-      NNS = NestedNameSpecifier::Create(*Context, Prev, Template, T);
-      break;
-    }
-
-    case NestedNameSpecifier::Global: {
-      NNS = NestedNameSpecifier::GlobalSpecifier(*Context);
-      // No associated value, and there can't be a prefix.
-      break;
-    }
-    }
-    Prev = NNS;
-  }
-  return NNS;
-}
-
-SourceRange
-PCHReader::ReadSourceRange(const RecordData &Record, unsigned &Idx) {
-  SourceLocation beg = SourceLocation::getFromRawEncoding(Record[Idx++]);
-  SourceLocation end = SourceLocation::getFromRawEncoding(Record[Idx++]);
-  return SourceRange(beg, end);
-}
-
-/// \brief Read an integral value
-llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
-  unsigned BitWidth = Record[Idx++];
-  unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
-  llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
-  Idx += NumWords;
-  return Result;
-}
-
-/// \brief Read a signed integral value
-llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
-  bool isUnsigned = Record[Idx++];
-  return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
-}
-
-/// \brief Read a floating-point value
-llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
-  return llvm::APFloat(ReadAPInt(Record, Idx));
-}
-
-// \brief Read a string
-std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
-  unsigned Len = Record[Idx++];
-  std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
-  Idx += Len;
-  return Result;
-}
-
-CXXTemporary *PCHReader::ReadCXXTemporary(const RecordData &Record,
-                                          unsigned &Idx) {
-  CXXDestructorDecl *Decl = cast<CXXDestructorDecl>(GetDecl(Record[Idx++]));
-  return CXXTemporary::Create(*Context, Decl);
-}
-
-DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
-  return Diag(SourceLocation(), DiagID);
-}
-
-DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
-  return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
-}
-
-/// \brief Retrieve the identifier table associated with the
-/// preprocessor.
-IdentifierTable &PCHReader::getIdentifierTable() {
-  assert(PP && "Forgot to set Preprocessor ?");
-  return PP->getIdentifierTable();
-}
-
-/// \brief Record that the given ID maps to the given switch-case
-/// statement.
-void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
-  assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
-  SwitchCaseStmts[ID] = SC;
-}
-
-/// \brief Retrieve the switch-case statement with the given ID.
-SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
-  assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
-  return SwitchCaseStmts[ID];
-}
-
-/// \brief Record that the given label statement has been
-/// deserialized and has the given ID.
-void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
-  assert(LabelStmts.find(ID) == LabelStmts.end() &&
-         "Deserialized label twice");
-  LabelStmts[ID] = S;
-
-  // If we've already seen any goto statements that point to this
-  // label, resolve them now.
-  typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
-  std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
-  for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
-    Goto->second->setLabel(S);
-  UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
-
-  // If we've already seen any address-label statements that point to
-  // this label, resolve them now.
-  typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
-  std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
-    = UnresolvedAddrLabelExprs.equal_range(ID);
-  for (AddrLabelIter AddrLabel = AddrLabels.first;
-       AddrLabel != AddrLabels.second; ++AddrLabel)
-    AddrLabel->second->setLabel(S);
-  UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
-}
-
-/// \brief Set the label of the given statement to the label
-/// identified by ID.
-///
-/// Depending on the order in which the label and other statements
-/// referencing that label occur, this operation may complete
-/// immediately (updating the statement) or it may queue the
-/// statement to be back-patched later.
-void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
-  std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
-  if (Label != LabelStmts.end()) {
-    // We've already seen this label, so set the label of the goto and
-    // we're done.
-    S->setLabel(Label->second);
-  } else {
-    // We haven't seen this label yet, so add this goto to the set of
-    // unresolved goto statements.
-    UnresolvedGotoStmts.insert(std::make_pair(ID, S));
-  }
-}
-
-/// \brief Set the label of the given expression to the label
-/// identified by ID.
-///
-/// Depending on the order in which the label and other statements
-/// referencing that label occur, this operation may complete
-/// immediately (updating the statement) or it may queue the
-/// statement to be back-patched later.
-void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
-  std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
-  if (Label != LabelStmts.end()) {
-    // We've already seen this label, so set the label of the
-    // label-address expression and we're done.
-    S->setLabel(Label->second);
-  } else {
-    // We haven't seen this label yet, so add this label-address
-    // expression to the set of unresolved label-address expressions.
-    UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
-  }
-}
-
-void PCHReader::FinishedDeserializing() {
-  assert(NumCurrentElementsDeserializing &&
-         "FinishedDeserializing not paired with StartedDeserializing");
-  if (NumCurrentElementsDeserializing == 1) {
-    // If any identifiers with corresponding top-level declarations have
-    // been loaded, load those declarations now.
-    while (!PendingIdentifierInfos.empty()) {
-      SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
-                              PendingIdentifierInfos.front().DeclIDs, true);
-      PendingIdentifierInfos.pop_front();
-    }
-
-    // We are not in recursive loading, so it's safe to pass the "interesting"
-    // decls to the consumer.
-    if (Consumer)
-      PassInterestingDeclsToConsumer();
-  }
-  --NumCurrentElementsDeserializing;
-}
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
deleted file mode 100644
index aa5ce7a..0000000
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ /dev/null
@@ -1,1600 +0,0 @@
-//===--- PCHReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the PCHReader::ReadDeclRecord method, which is the
-// entrypoint for loading a decl.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/PCHReader.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
-using namespace clang;
-
-
-//===----------------------------------------------------------------------===//
-// Declaration deserialization
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-  class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> {
-    PCHReader &Reader;
-    llvm::BitstreamCursor &Cursor;
-    const pch::DeclID ThisDeclID;
-    const PCHReader::RecordData &Record;
-    unsigned &Idx;
-    pch::TypeID TypeIDForTypeDecl;
-
-    uint64_t GetCurrentCursorOffset();
-
-  public:
-    PCHDeclReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor,
-                  pch::DeclID thisDeclID, const PCHReader::RecordData &Record,
-                  unsigned &Idx)
-      : Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), Record(Record),
-        Idx(Idx), TypeIDForTypeDecl(0) { }
-
-    void Visit(Decl *D);
-
-    void VisitDecl(Decl *D);
-    void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
-    void VisitNamedDecl(NamedDecl *ND);
-    void VisitNamespaceDecl(NamespaceDecl *D);
-    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
-    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
-    void VisitTypeDecl(TypeDecl *TD);
-    void VisitTypedefDecl(TypedefDecl *TD);
-    void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
-    void VisitTagDecl(TagDecl *TD);
-    void VisitEnumDecl(EnumDecl *ED);
-    void VisitRecordDecl(RecordDecl *RD);
-    void VisitCXXRecordDecl(CXXRecordDecl *D);
-    void VisitClassTemplateSpecializationDecl(
-                                            ClassTemplateSpecializationDecl *D);
-    void VisitClassTemplatePartialSpecializationDecl(
-                                     ClassTemplatePartialSpecializationDecl *D);
-    void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
-    void VisitValueDecl(ValueDecl *VD);
-    void VisitEnumConstantDecl(EnumConstantDecl *ECD);
-    void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
-    void VisitDeclaratorDecl(DeclaratorDecl *DD);
-    void VisitFunctionDecl(FunctionDecl *FD);
-    void VisitCXXMethodDecl(CXXMethodDecl *D);
-    void VisitCXXConstructorDecl(CXXConstructorDecl *D);
-    void VisitCXXDestructorDecl(CXXDestructorDecl *D);
-    void VisitCXXConversionDecl(CXXConversionDecl *D);
-    void VisitFieldDecl(FieldDecl *FD);
-    void VisitVarDecl(VarDecl *VD);
-    void VisitImplicitParamDecl(ImplicitParamDecl *PD);
-    void VisitParmVarDecl(ParmVarDecl *PD);
-    void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
-    void VisitTemplateDecl(TemplateDecl *D);
-    void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
-    void VisitClassTemplateDecl(ClassTemplateDecl *D);
-    void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
-    void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
-    void VisitUsingDecl(UsingDecl *D);
-    void VisitUsingShadowDecl(UsingShadowDecl *D);
-    void VisitLinkageSpecDecl(LinkageSpecDecl *D);
-    void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
-    void VisitAccessSpecDecl(AccessSpecDecl *D);
-    void VisitFriendDecl(FriendDecl *D);
-    void VisitFriendTemplateDecl(FriendTemplateDecl *D);
-    void VisitStaticAssertDecl(StaticAssertDecl *D);
-    void VisitBlockDecl(BlockDecl *BD);
-
-    std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
-    template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
-
-    // FIXME: Reorder according to DeclNodes.td?
-    void VisitObjCMethodDecl(ObjCMethodDecl *D);
-    void VisitObjCContainerDecl(ObjCContainerDecl *D);
-    void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
-    void VisitObjCIvarDecl(ObjCIvarDecl *D);
-    void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
-    void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
-    void VisitObjCClassDecl(ObjCClassDecl *D);
-    void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
-    void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
-    void VisitObjCImplDecl(ObjCImplDecl *D);
-    void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
-    void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
-    void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
-    void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
-    void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
-  };
-}
-
-uint64_t PCHDeclReader::GetCurrentCursorOffset() {
-  uint64_t Off = 0;
-  for (unsigned I = 0, N = Reader.Chain.size(); I != N; ++I) {
-    PCHReader::PerFileData &F = *Reader.Chain[N - I - 1];
-    if (&Cursor == &F.DeclsCursor) {
-      Off += F.DeclsCursor.GetCurrentBitNo();
-      break;
-    }
-    Off += F.SizeInBits;
-  }
-  return Off;
-}
-
-void PCHDeclReader::Visit(Decl *D) {
-  DeclVisitor<PCHDeclReader, void>::Visit(D);
-
-  if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
-    // if we have a fully initialized TypeDecl, we can safely read its type now.
-    TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtr());
-  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    // FunctionDecl's body was written last after all other Stmts/Exprs.
-    if (Record[Idx++])
-      FD->setLazyBody(GetCurrentCursorOffset());
-  }
-}
-
-void PCHDeclReader::VisitDecl(Decl *D) {
-  D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
-  D->setLexicalDeclContext(
-                     cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
-  D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  D->setInvalidDecl(Record[Idx++]);
-  if (Record[Idx++])
-    D->initAttrs(Reader.ReadAttributes(Cursor));
-  D->setImplicit(Record[Idx++]);
-  D->setUsed(Record[Idx++]);
-  D->setAccess((AccessSpecifier)Record[Idx++]);
-  D->setPCHLevel(Record[Idx++] + 1);
-}
-
-void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
-  VisitDecl(TU);
-  TU->setAnonymousNamespace(
-                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
-  VisitDecl(ND);
-  ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
-}
-
-void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
-  VisitNamedDecl(TD);
-  // Delay type reading until after we have fully initialized the decl.
-  TypeIDForTypeDecl = Record[Idx++];
-}
-
-void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
-  VisitTypeDecl(TD);
-  TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
-}
-
-void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
-  VisitTypeDecl(TD);
-  TD->IdentifierNamespace = Record[Idx++];
-  VisitRedeclarable(TD);
-  TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
-  TD->setDefinition(Record[Idx++]);
-  TD->setEmbeddedInDeclarator(Record[Idx++]);
-  TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  // FIXME: maybe read optional qualifier and its range.
-  TD->setTypedefForAnonDecl(
-                    cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
-  VisitTagDecl(ED);
-  ED->setIntegerType(Reader.GetType(Record[Idx++]));
-  ED->setPromotionType(Reader.GetType(Record[Idx++]));
-  ED->setNumPositiveBits(Record[Idx++]);
-  ED->setNumNegativeBits(Record[Idx++]);
-  ED->setInstantiationOfMemberEnum(
-                         cast_or_null<EnumDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) {
-  VisitTagDecl(RD);
-  RD->setHasFlexibleArrayMember(Record[Idx++]);
-  RD->setAnonymousStructOrUnion(Record[Idx++]);
-  RD->setHasObjectMember(Record[Idx++]);
-}
-
-void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
-  VisitNamedDecl(VD);
-  VD->setType(Reader.GetType(Record[Idx++]));
-}
-
-void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
-  VisitValueDecl(ECD);
-  if (Record[Idx++])
-    ECD->setInitExpr(Reader.ReadExpr(Cursor));
-  ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
-}
-
-void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
-  VisitValueDecl(DD);
-  TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
-  if (TInfo)
-    DD->setTypeSourceInfo(TInfo);
-  // FIXME: read optional qualifier and its range.
-}
-
-void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
-  VisitDeclaratorDecl(FD);
-  // FIXME: read DeclarationNameLoc.
-
-  FD->IdentifierNamespace = Record[Idx++];
-  switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
-  default: assert(false && "Unhandled TemplatedKind!");
-    break;
-  case FunctionDecl::TK_NonTemplate:
-    break;
-  case FunctionDecl::TK_FunctionTemplate:
-    FD->setDescribedFunctionTemplate(
-                     cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++])));
-    break;
-  case FunctionDecl::TK_MemberSpecialization: {
-    FunctionDecl *InstFD = cast<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
-    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
-    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
-    FD->setInstantiationOfMemberFunction(InstFD, TSK);
-    FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
-    break;
-  }
-  case FunctionDecl::TK_FunctionTemplateSpecialization: {
-    FunctionTemplateDecl *Template
-      = cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]));
-    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
-    
-    // Template arguments.
-    llvm::SmallVector<TemplateArgument, 8> TemplArgs;
-    Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
-    
-    // Template args as written.
-    llvm::SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
-    SourceLocation LAngleLoc, RAngleLoc;
-    if (Record[Idx++]) {  // TemplateArgumentsAsWritten != 0
-      unsigned NumTemplateArgLocs = Record[Idx++];
-      TemplArgLocs.reserve(NumTemplateArgLocs);
-      for (unsigned i=0; i != NumTemplateArgLocs; ++i)
-        TemplArgLocs.push_back(
-            Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx));
-  
-      LAngleLoc = Reader.ReadSourceLocation(Record, Idx);
-      RAngleLoc = Reader.ReadSourceLocation(Record, Idx);
-    }
-    
-    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
-
-    if (FD->isCanonicalDecl()) // if canonical add to template's set.
-      FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(),
-                                            TemplArgs.data(), TSK,
-                                            TemplArgLocs.size(),
-                                            TemplArgLocs.data(),
-                                            LAngleLoc, RAngleLoc, POI);
-    break;
-  }
-  case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
-    // Templates.
-    UnresolvedSet<8> TemplDecls;
-    unsigned NumTemplates = Record[Idx++];
-    while (NumTemplates--)
-      TemplDecls.addDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
-    
-    // Templates args.
-    TemplateArgumentListInfo TemplArgs;
-    unsigned NumArgs = Record[Idx++];
-    while (NumArgs--)
-      TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(Cursor,Record, Idx));
-    TemplArgs.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx));
-    TemplArgs.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx));
-    
-    FD->setDependentTemplateSpecialization(*Reader.getContext(),
-                                           TemplDecls, TemplArgs);
-    break;
-  }
-  }
-
-  // FunctionDecl's body is handled last at PCHReaderDecl::Visit,
-  // after everything else is read.
-
-  VisitRedeclarable(FD);
-  FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
-  FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]);
-  FD->setInlineSpecified(Record[Idx++]);
-  FD->setVirtualAsWritten(Record[Idx++]);
-  FD->setPure(Record[Idx++]);
-  FD->setHasInheritedPrototype(Record[Idx++]);
-  FD->setHasWrittenPrototype(Record[Idx++]);
-  FD->setDeleted(Record[Idx++]);
-  FD->setTrivial(Record[Idx++]);
-  FD->setCopyAssignment(Record[Idx++]);
-  FD->setHasImplicitReturnZero(Record[Idx++]);
-  FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
-
-  // Read in the parameters.
-  unsigned NumParams = Record[Idx++];
-  llvm::SmallVector<ParmVarDecl *, 16> Params;
-  Params.reserve(NumParams);
-  for (unsigned I = 0; I != NumParams; ++I)
-    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
-  FD->setParams(Params.data(), NumParams);
-}
-
-void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
-  VisitNamedDecl(MD);
-  if (Record[Idx++]) {
-    // In practice, this won't be executed (since method definitions
-    // don't occur in header files).
-    MD->setBody(Reader.ReadStmt(Cursor));
-    MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
-    MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
-  }
-  MD->setInstanceMethod(Record[Idx++]);
-  MD->setVariadic(Record[Idx++]);
-  MD->setSynthesized(Record[Idx++]);
-  MD->setDefined(Record[Idx++]);
-  MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
-  MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
-  MD->setNumSelectorArgs(unsigned(Record[Idx++]));
-  MD->setResultType(Reader.GetType(Record[Idx++]));
-  MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
-  MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  unsigned NumParams = Record[Idx++];
-  llvm::SmallVector<ParmVarDecl *, 16> Params;
-  Params.reserve(NumParams);
-  for (unsigned I = 0; I != NumParams; ++I)
-    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
-  MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams,
-                      NumParams);
-}
-
-void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
-  VisitNamedDecl(CD);
-  SourceLocation A = SourceLocation::getFromRawEncoding(Record[Idx++]);
-  SourceLocation B = SourceLocation::getFromRawEncoding(Record[Idx++]);
-  CD->setAtEndRange(SourceRange(A, B));
-}
-
-void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
-  VisitObjCContainerDecl(ID);
-  ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
-  ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
-                       (Reader.GetDecl(Record[Idx++])));
-  unsigned NumProtocols = Record[Idx++];
-  llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols;
-  Protocols.reserve(NumProtocols);
-  for (unsigned I = 0; I != NumProtocols; ++I)
-    Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
-  ProtoLocs.reserve(NumProtocols);
-  for (unsigned I = 0; I != NumProtocols; ++I)
-    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
-                      *Reader.getContext());
-  unsigned NumIvars = Record[Idx++];
-  llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
-  IVars.reserve(NumIvars);
-  for (unsigned I = 0; I != NumIvars; ++I)
-    IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
-  ID->setCategoryList(
-               cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
-  ID->setForwardDecl(Record[Idx++]);
-  ID->setImplicitInterfaceDecl(Record[Idx++]);
-  ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
-  VisitFieldDecl(IVD);
-  IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
-  bool synth = Record[Idx++];
-  IVD->setSynthesize(synth);
-}
-
-void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
-  VisitObjCContainerDecl(PD);
-  PD->setForwardDecl(Record[Idx++]);
-  PD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  unsigned NumProtoRefs = Record[Idx++];
-  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
-  ProtoRefs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
-  ProtoLocs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
-                      *Reader.getContext());
-}
-
-void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
-  VisitFieldDecl(FD);
-}
-
-void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
-  VisitDecl(CD);
-  unsigned NumClassRefs = Record[Idx++];
-  llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs;
-  ClassRefs.reserve(NumClassRefs);
-  for (unsigned I = 0; I != NumClassRefs; ++I)
-    ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
-  llvm::SmallVector<SourceLocation, 16> SLocs;
-  SLocs.reserve(NumClassRefs);
-  for (unsigned I = 0; I != NumClassRefs; ++I)
-    SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(),
-                   NumClassRefs);
-}
-
-void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
-  VisitDecl(FPD);
-  unsigned NumProtoRefs = Record[Idx++];
-  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
-  ProtoRefs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
-  ProtoLocs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
-                       *Reader.getContext());
-}
-
-void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
-  VisitObjCContainerDecl(CD);
-  CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
-  unsigned NumProtoRefs = Record[Idx++];
-  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
-  ProtoRefs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
-  ProtoLocs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
-                      *Reader.getContext());
-  CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
-  CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
-  VisitNamedDecl(CAD);
-  CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
-  VisitNamedDecl(D);
-  D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  D->setType(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
-  // FIXME: stable encoding
-  D->setPropertyAttributes(
-                      (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
-  D->setPropertyAttributesAsWritten(
-                      (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
-  // FIXME: stable encoding
-  D->setPropertyImplementation(
-                            (ObjCPropertyDecl::PropertyControl)Record[Idx++]);
-  D->setGetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector());
-  D->setSetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector());
-  D->setGetterMethodDecl(
-                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setSetterMethodDecl(
-                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setPropertyIvarDecl(
-                   cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
-  VisitObjCContainerDecl(D);
-  D->setClassInterface(
-              cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
-  VisitObjCImplDecl(D);
-  D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx));
-}
-
-void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
-  VisitObjCImplDecl(D);
-  D->setSuperClass(
-              cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
-  llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
-      = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx);
-}
-
-
-void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
-  VisitDecl(D);
-  D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  D->setPropertyDecl(
-               cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setPropertyIvarDecl(
-                   cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setGetterCXXConstructor(Reader.ReadExpr(Cursor));
-  D->setSetterCXXAssignment(Reader.ReadExpr(Cursor));
-}
-
-void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
-  VisitDeclaratorDecl(FD);
-  FD->setMutable(Record[Idx++]);
-  if (Record[Idx++])
-    FD->setBitWidth(Reader.ReadExpr(Cursor));
-  if (!FD->getDeclName()) {
-    FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]));
-    if (Tmpl)
-      Reader.getContext()->setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
-  }
-}
-
-void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
-  VisitDeclaratorDecl(VD);
-  VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
-  VD->setStorageClassAsWritten((VarDecl::StorageClass)Record[Idx++]);
-  VD->setThreadSpecified(Record[Idx++]);
-  VD->setCXXDirectInitializer(Record[Idx++]);
-  VD->setExceptionVariable(Record[Idx++]);
-  VD->setNRVOVariable(Record[Idx++]);
-  VisitRedeclarable(VD);
-  if (Record[Idx++])
-    VD->setInit(Reader.ReadExpr(Cursor));
-
-  if (Record[Idx++]) { // HasMemberSpecializationInfo.
-    VarDecl *Tmpl = cast<VarDecl>(Reader.GetDecl(Record[Idx++]));
-    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
-    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
-    Reader.getContext()->setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
-  }
-}
-
-void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
-  VisitVarDecl(PD);
-}
-
-void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
-  VisitVarDecl(PD);
-  PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
-  PD->setHasInheritedDefaultArg(Record[Idx++]);
-  if (Record[Idx++]) // hasUninstantiatedDefaultArg.
-    PD->setUninstantiatedDefaultArg(Reader.ReadExpr(Cursor));
-}
-
-void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
-  VisitDecl(AD);
-  AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(Cursor)));
-}
-
-void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {
-  VisitDecl(BD);
-  BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(Cursor)));
-  BD->setSignatureAsWritten(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
-  unsigned NumParams = Record[Idx++];
-  llvm::SmallVector<ParmVarDecl *, 16> Params;
-  Params.reserve(NumParams);
-  for (unsigned I = 0; I != NumParams; ++I)
-    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
-  BD->setParams(Params.data(), NumParams);
-}
-
-void PCHDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  VisitDecl(D);
-  D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]);
-  D->setHasBraces(Record[Idx++]);
-}
-
-void PCHDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
-  VisitNamedDecl(D);
-  D->setLBracLoc(Reader.ReadSourceLocation(Record, Idx));
-  D->setRBracLoc(Reader.ReadSourceLocation(Record, Idx));
-  D->setNextNamespace(
-                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
-
-  bool IsOriginal = Record[Idx++];
-  D->OrigOrAnonNamespace.setInt(IsOriginal);
-  D->OrigOrAnonNamespace.setPointer(
-                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
-  VisitNamedDecl(D);
-
-  D->setAliasLoc(Reader.ReadSourceLocation(Record, Idx));
-  D->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-  D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
-  D->setTargetNameLoc(Reader.ReadSourceLocation(Record, Idx));
-  D->setAliasedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitUsingDecl(UsingDecl *D) {
-  VisitNamedDecl(D);
-  D->setUsingLocation(Reader.ReadSourceLocation(Record, Idx));
-  D->setNestedNameRange(Reader.ReadSourceRange(Record, Idx));
-  D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx));
-  // FIXME: read the DNLoc component.
-
-  // FIXME: It would probably be more efficient to read these into a vector
-  // and then re-cosntruct the shadow decl set over that vector since it
-  // would avoid existence checks.
-  unsigned NumShadows = Record[Idx++];
-  for(unsigned I = 0; I != NumShadows; ++I) {
-    // Avoid invariant checking of UsingDecl::addShadowDecl, the decl may still
-    // be initializing.
-    D->Shadows.insert(cast<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])));
-  }
-  D->setTypeName(Record[Idx++]);
-  NamedDecl *Pattern = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
-  if (Pattern)
-    Reader.getContext()->setInstantiatedFromUsingDecl(D, Pattern);
-}
-
-void PCHDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
-  VisitNamedDecl(D);
-  D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setUsingDecl(cast<UsingDecl>(Reader.GetDecl(Record[Idx++])));
-  UsingShadowDecl *Pattern
-      = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]));
-  if (Pattern)
-    Reader.getContext()->setInstantiatedFromUsingShadowDecl(D, Pattern);
-}
-
-void PCHDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
-  VisitNamedDecl(D);
-  D->setNamespaceKeyLocation(Reader.ReadSourceLocation(Record, Idx));
-  D->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-  D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
-  D->setIdentLocation(Reader.ReadSourceLocation(Record, Idx));
-  D->setNominatedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setCommonAncestor(cast_or_null<DeclContext>(
-                                                Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
-  VisitValueDecl(D);
-  D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx));
-  D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx));
-  D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
-  // FIXME: read the DNLoc component.
-}
-
-void PCHDeclReader::VisitUnresolvedUsingTypenameDecl(
-                                               UnresolvedUsingTypenameDecl *D) {
-  VisitTypeDecl(D);
-  D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx));
-  D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx));
-  D->setTypenameLoc(Reader.ReadSourceLocation(Record, Idx));
-  D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
-}
-
-void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
-  ASTContext &C = *Reader.getContext();
-
-  // We need to allocate the DefinitionData struct ahead of VisitRecordDecl
-  // so that the other CXXRecordDecls can get a pointer even when the owner
-  // is still initializing.
-  bool OwnsDefinitionData = false;
-  enum DataOwnership { Data_NoDefData, Data_Owner, Data_NotOwner };
-  switch ((DataOwnership)Record[Idx++]) {
-  default:
-    assert(0 && "Out of sync with PCHDeclWriter or messed up reading");
-  case Data_NoDefData:
-    break;
-  case Data_Owner:
-    OwnsDefinitionData = true;
-    D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
-    break;
-  case Data_NotOwner:
-    D->DefinitionData
-        = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]))->DefinitionData;
-    break;
-  }
-
-  VisitRecordDecl(D);
-
-  if (OwnsDefinitionData) {
-    assert(D->DefinitionData);
-    struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData;
-
-    Data.UserDeclaredConstructor = Record[Idx++];
-    Data.UserDeclaredCopyConstructor = Record[Idx++];
-    Data.UserDeclaredCopyAssignment = Record[Idx++];
-    Data.UserDeclaredDestructor = Record[Idx++];
-    Data.Aggregate = Record[Idx++];
-    Data.PlainOldData = Record[Idx++];
-    Data.Empty = Record[Idx++];
-    Data.Polymorphic = Record[Idx++];
-    Data.Abstract = Record[Idx++];
-    Data.HasTrivialConstructor = Record[Idx++];
-    Data.HasTrivialCopyConstructor = Record[Idx++];
-    Data.HasTrivialCopyAssignment = Record[Idx++];
-    Data.HasTrivialDestructor = Record[Idx++];
-    Data.ComputedVisibleConversions = Record[Idx++];
-    Data.DeclaredDefaultConstructor = Record[Idx++];
-    Data.DeclaredCopyConstructor = Record[Idx++];
-    Data.DeclaredCopyAssignment = Record[Idx++];
-    Data.DeclaredDestructor = Record[Idx++];
-
-    // setBases() is unsuitable since it may try to iterate the bases of an
-    // uninitialized base.
-    Data.NumBases = Record[Idx++];
-    Data.Bases = new(C) CXXBaseSpecifier [Data.NumBases];
-    for (unsigned i = 0; i != Data.NumBases; ++i)
-      Data.Bases[i] = Reader.ReadCXXBaseSpecifier(Cursor, Record, Idx);
-
-    // FIXME: Make VBases lazily computed when needed to avoid storing them.
-    Data.NumVBases = Record[Idx++];
-    Data.VBases = new(C) CXXBaseSpecifier [Data.NumVBases];
-    for (unsigned i = 0; i != Data.NumVBases; ++i)
-      Data.VBases[i] = Reader.ReadCXXBaseSpecifier(Cursor, Record, Idx);
-
-    Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx);
-    Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx);
-    assert(Data.Definition && "Data.Definition should be already set!");
-    Data.FirstFriend
-        = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++]));
-  }
-
-  enum CXXRecKind {
-    CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
-  };
-  switch ((CXXRecKind)Record[Idx++]) {
-  default:
-    assert(false && "Out of sync with PCHDeclWriter::VisitCXXRecordDecl?");
-  case CXXRecNotTemplate:
-    break;
-  case CXXRecTemplate:
-    D->setDescribedClassTemplate(
-                        cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])));
-    break;
-  case CXXRecMemberSpecialization: {
-    CXXRecordDecl *RD = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]));
-    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
-    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
-    D->setInstantiationOfMemberClass(RD, TSK);
-    D->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
-    break;
-  }
-  }
-}
-
-void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
-  VisitFunctionDecl(D);
-  unsigned NumOverridenMethods = Record[Idx++];
-  while (NumOverridenMethods--) {
-    CXXMethodDecl *MD = cast<CXXMethodDecl>(Reader.GetDecl(Record[Idx++]));
-    // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
-    // MD may be initializing.
-    Reader.getContext()->addOverriddenMethod(D, MD);
-  }
-}
-
-void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  VisitCXXMethodDecl(D);
-  
-  D->IsExplicitSpecified = Record[Idx++];
-  D->ImplicitlyDefined = Record[Idx++];
-  llvm::tie(D->BaseOrMemberInitializers, D->NumBaseOrMemberInitializers)
-      = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx);
-}
-
-void PCHDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
-  VisitCXXMethodDecl(D);
-
-  D->ImplicitlyDefined = Record[Idx++];
-  D->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
-}
-
-void PCHDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
-  VisitCXXMethodDecl(D);
-  D->IsExplicitSpecified = Record[Idx++];
-}
-
-void PCHDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
-  VisitDecl(D);
-  D->setColonLoc(Reader.ReadSourceLocation(Record, Idx));
-}
-
-void PCHDeclReader::VisitFriendDecl(FriendDecl *D) {
-  VisitDecl(D);
-  if (Record[Idx++])
-    D->Friend = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
-  else
-    D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
-  D->NextFriend = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++]));
-  D->FriendLoc = Reader.ReadSourceLocation(Record, Idx);
-}
-
-void PCHDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
-  VisitDecl(D);
-  unsigned NumParams = Record[Idx++];
-  D->NumParams = NumParams;
-  D->Params = new TemplateParameterList*[NumParams];
-  for (unsigned i = 0; i != NumParams; ++i)
-    D->Params[i] = Reader.ReadTemplateParameterList(Record, Idx);
-  if (Record[Idx++]) // HasFriendDecl
-    D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
-  else
-    D->Friend = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
-  D->FriendLoc = Reader.ReadSourceLocation(Record, Idx);
-}
-
-void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) {
-  VisitNamedDecl(D);
-
-  NamedDecl *TemplatedDecl
-    = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
-  TemplateParameterList* TemplateParams
-      = Reader.ReadTemplateParameterList(Record, Idx); 
-  D->init(TemplatedDecl, TemplateParams);
-}
-
-void PCHDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
-  VisitTemplateDecl(D);
-
-  D->IdentifierNamespace = Record[Idx++];
-  RedeclarableTemplateDecl *PrevDecl =
-      cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
-  assert((PrevDecl == 0 || PrevDecl->getKind() == D->getKind()) &&
-         "PrevDecl kind mismatch");
-  if (PrevDecl)
-    D->CommonOrPrev = PrevDecl;
-  if (PrevDecl == 0) {
-    if (RedeclarableTemplateDecl *RTD
-          = cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
-      assert(RTD->getKind() == D->getKind() &&
-             "InstantiatedFromMemberTemplate kind mismatch");
-      D->setInstantiatedFromMemberTemplateImpl(RTD);
-      if (Record[Idx++])
-        D->setMemberSpecialization();
-    }
-
-    RedeclarableTemplateDecl *LatestDecl = 
-        cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
-  
-    // This decl is a first one and the latest declaration that it points to is
-    // in the same PCH. However, if this actually needs to point to a
-    // redeclaration in another chained PCH, we need to update it by checking
-    // the FirstLatestDeclIDs map which tracks this kind of decls.
-    assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?");
-    PCHReader::FirstLatestDeclIDMap::iterator I
-        = Reader.FirstLatestDeclIDs.find(ThisDeclID);
-    if (I != Reader.FirstLatestDeclIDs.end()) {
-      Decl *NewLatest = Reader.GetDecl(I->second);
-      assert((LatestDecl->getLocation().isInvalid() ||
-              NewLatest->getLocation().isInvalid()  ||
-              Reader.SourceMgr.isBeforeInTranslationUnit(
-                                                   LatestDecl->getLocation(),
-                                                   NewLatest->getLocation())) &&
-             "The new latest is supposed to come after the previous latest");
-      LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
-    }
-
-    assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch");
-    D->getCommonPtr()->Latest = LatestDecl;
-  }
-}
-
-void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
-  VisitRedeclarableTemplateDecl(D);
-
-  if (D->getPreviousDeclaration() == 0) {
-    // This ClassTemplateDecl owns a CommonPtr; read it.
-
-    // FoldingSets are filled in VisitClassTemplateSpecializationDecl.
-    unsigned size = Record[Idx++];
-    while (size--)
-      cast<ClassTemplateSpecializationDecl>(Reader.GetDecl(Record[Idx++]));
-
-    size = Record[Idx++];
-    while (size--)
-      cast<ClassTemplatePartialSpecializationDecl>(
-                                                 Reader.GetDecl(Record[Idx++]));
-
-    // InjectedClassNameType is computed.
-  }
-}
-
-void PCHDeclReader::VisitClassTemplateSpecializationDecl(
-                                           ClassTemplateSpecializationDecl *D) {
-  VisitCXXRecordDecl(D);
-
-  if (Decl *InstD = Reader.GetDecl(Record[Idx++])) {
-    if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) {
-      D->setInstantiationOf(CTD);
-    } else {
-      llvm::SmallVector<TemplateArgument, 8> TemplArgs;
-      Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
-      D->setInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(InstD),
-                            TemplArgs.data(), TemplArgs.size());
-    }
-  }
-
-  // Explicit info.
-  if (TypeSourceInfo *TyInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx)) {
-    D->setTypeAsWritten(TyInfo);
-    D->setExternLoc(Reader.ReadSourceLocation(Record, Idx));
-    D->setTemplateKeywordLoc(Reader.ReadSourceLocation(Record, Idx));
-  }
-
-  llvm::SmallVector<TemplateArgument, 8> TemplArgs;
-  Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
-  D->initTemplateArgs(TemplArgs.data(), TemplArgs.size());
-  SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
-  if (POI.isValid())
-    D->setPointOfInstantiation(POI);
-  D->setSpecializationKind((TemplateSpecializationKind)Record[Idx++]);
-
-  if (D->isCanonicalDecl()) { // It's kept in the folding set.
-    ClassTemplateDecl *CanonPattern
-                       = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
-    if (ClassTemplatePartialSpecializationDecl *Partial
-            = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
-      CanonPattern->getPartialSpecializations().InsertNode(Partial);
-    } else {
-      CanonPattern->getSpecializations().InsertNode(D);
-    }
-  }
-}
-
-void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl(
-                                    ClassTemplatePartialSpecializationDecl *D) {
-  VisitClassTemplateSpecializationDecl(D);
-
-  D->initTemplateParameters(Reader.ReadTemplateParameterList(Record, Idx));
-  
-  TemplateArgumentListInfo ArgInfos;
-  unsigned NumArgs = Record[Idx++];
-  while (NumArgs--)
-    ArgInfos.addArgument(Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx));
-  D->initTemplateArgsAsWritten(ArgInfos);
-  
-  D->setSequenceNumber(Record[Idx++]);
-
-  // These are read/set from/to the first declaration.
-  if (D->getPreviousDeclaration() == 0) {
-    D->setInstantiatedFromMember(
-        cast_or_null<ClassTemplatePartialSpecializationDecl>(
-                                                Reader.GetDecl(Record[Idx++])));
-    if (Record[Idx++])
-      D->setMemberSpecialization();
-  }
-}
-
-void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
-  VisitRedeclarableTemplateDecl(D);
-
-  if (D->getPreviousDeclaration() == 0) {
-    // This FunctionTemplateDecl owns a CommonPtr; read it.
-
-    // Read the function specialization declarations.
-    // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled
-    // through the specialized FunctionDecl's setFunctionTemplateSpecialization.
-    unsigned NumSpecs = Record[Idx++];
-    while (NumSpecs--)
-      Reader.GetDecl(Record[Idx++]);
-  }
-}
-
-void PCHDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
-  VisitTypeDecl(D);
-
-  D->setDeclaredWithTypename(Record[Idx++]);
-  D->setParameterPack(Record[Idx++]);
-
-  bool Inherited = Record[Idx++];
-  TypeSourceInfo *DefArg = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
-  D->setDefaultArgument(DefArg, Inherited);
-}
-
-void PCHDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
-  VisitVarDecl(D);
-  // TemplateParmPosition.
-  D->setDepth(Record[Idx++]);
-  D->setPosition(Record[Idx++]);
-  // Rest of NonTypeTemplateParmDecl.
-  if (Record[Idx++]) {
-    Expr *DefArg = Reader.ReadExpr(Cursor);
-    bool Inherited = Record[Idx++];
-    D->setDefaultArgument(DefArg, Inherited);
- }
-}
-
-void PCHDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
-  VisitTemplateDecl(D);
-  // TemplateParmPosition.
-  D->setDepth(Record[Idx++]);
-  D->setPosition(Record[Idx++]);
-  // Rest of TemplateTemplateParmDecl.
-  TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx);
-  bool IsInherited = Record[Idx++];
-  D->setDefaultArgument(Arg, IsInherited);
-}
-
-void PCHDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
-  VisitDecl(D);
-  D->AssertExpr = Reader.ReadExpr(Cursor);
-  D->Message = cast<StringLiteral>(Reader.ReadExpr(Cursor));
-}
-
-std::pair<uint64_t, uint64_t>
-PCHDeclReader::VisitDeclContext(DeclContext *DC) {
-  uint64_t LexicalOffset = Record[Idx++];
-  uint64_t VisibleOffset = Record[Idx++];
-  return std::make_pair(LexicalOffset, VisibleOffset);
-}
-
-template <typename T>
-void PCHDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
-  enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
-  RedeclKind Kind = (RedeclKind)Record[Idx++];
-  switch (Kind) {
-  default:
-    assert(0 && "Out of sync with PCHDeclWriter::VisitRedeclarable or messed up"
-                " reading");
-  case NoRedeclaration:
-    break;
-  case PointsToPrevious:
-    D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(
-                                cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
-    break;
-  case PointsToLatest:
-    D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(
-                                cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
-    break;
-  }
-
-  assert(!(Kind == PointsToPrevious &&
-           Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
-               Reader.FirstLatestDeclIDs.end()) &&
-         "This decl is not first, it should not be in the map");
-  if (Kind == PointsToPrevious)
-    return;
-
-  // This decl is a first one and the latest declaration that it points to is in
-  // the same PCH. However, if this actually needs to point to a redeclaration
-  // in another chained PCH, we need to update it by checking the
-  // FirstLatestDeclIDs map which tracks this kind of decls.
-  assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) &&
-         "Invalid ThisDeclID ?");
-  PCHReader::FirstLatestDeclIDMap::iterator I
-      = Reader.FirstLatestDeclIDs.find(ThisDeclID);
-  if (I != Reader.FirstLatestDeclIDs.end()) {
-    Decl *NewLatest = Reader.GetDecl(I->second);
-    assert((D->getMostRecentDeclaration()->getLocation().isInvalid() ||
-            NewLatest->getLocation().isInvalid() ||
-            Reader.SourceMgr.isBeforeInTranslationUnit(
-                                   D->getMostRecentDeclaration()->getLocation(),
-                                   NewLatest->getLocation())) &&
-           "The new latest is supposed to come after the previous latest");
-    D->RedeclLink
-        = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest));
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Attribute Reading
-//===----------------------------------------------------------------------===//
-
-/// \brief Reads attributes from the current stream position.
-Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
-  unsigned Code = DeclsCursor.ReadCode();
-  assert(Code == llvm::bitc::UNABBREV_RECORD &&
-         "Expected unabbreviated record"); (void)Code;
-
-  RecordData Record;
-  unsigned Idx = 0;
-  unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
-  assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
-  (void)RecCode;
-
-#define SIMPLE_ATTR(Name)                       \
- case attr::Name:                               \
-   New = ::new (*Context) Name##Attr();         \
-   break
-
-#define STRING_ATTR(Name)                                       \
- case attr::Name:                                               \
-   New = ::new (*Context) Name##Attr(*Context, ReadString(Record, Idx));  \
-   break
-
-#define UNSIGNED_ATTR(Name)                             \
- case attr::Name:                                       \
-   New = ::new (*Context) Name##Attr(Record[Idx++]);    \
-   break
-
-  Attr *Attrs = 0;
-  while (Idx < Record.size()) {
-    Attr *New = 0;
-    attr::Kind Kind = (attr::Kind)Record[Idx++];
-    bool IsInherited = Record[Idx++];
-
-    switch (Kind) {
-    default:
-      assert(0 && "Unknown attribute!");
-      break;
-    STRING_ATTR(Alias);
-    SIMPLE_ATTR(AlignMac68k);
-    UNSIGNED_ATTR(Aligned);
-    SIMPLE_ATTR(AlwaysInline);
-    SIMPLE_ATTR(AnalyzerNoReturn);
-    STRING_ATTR(Annotate);
-    STRING_ATTR(AsmLabel);
-    SIMPLE_ATTR(BaseCheck);
-
-    case attr::Blocks:
-      New = ::new (*Context) BlocksAttr(
-                                  (BlocksAttr::BlocksAttrTypes)Record[Idx++]);
-      break;
-
-    SIMPLE_ATTR(CDecl);
-
-    case attr::Cleanup:
-      New = ::new (*Context) CleanupAttr(
-                                  cast<FunctionDecl>(GetDecl(Record[Idx++])));
-      break;
-
-    SIMPLE_ATTR(Const);
-    UNSIGNED_ATTR(Constructor);
-    SIMPLE_ATTR(DLLExport);
-    SIMPLE_ATTR(DLLImport);
-    SIMPLE_ATTR(Deprecated);
-    UNSIGNED_ATTR(Destructor);
-    SIMPLE_ATTR(FastCall);
-    SIMPLE_ATTR(Final);
-
-    case attr::Format: {
-      std::string Type = ReadString(Record, Idx);
-      unsigned FormatIdx = Record[Idx++];
-      unsigned FirstArg = Record[Idx++];
-      New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg);
-      break;
-    }
-
-    case attr::FormatArg: {
-      unsigned FormatIdx = Record[Idx++];
-      New = ::new (*Context) FormatArgAttr(FormatIdx);
-      break;
-    }
-
-    case attr::Sentinel: {
-      int sentinel = Record[Idx++];
-      int nullPos = Record[Idx++];
-      New = ::new (*Context) SentinelAttr(sentinel, nullPos);
-      break;
-    }
-
-    SIMPLE_ATTR(GNUInline);
-    SIMPLE_ATTR(Hiding);
-
-    case attr::IBAction:
-      New = ::new (*Context) IBActionAttr();
-      break;
-
-    case attr::IBOutlet:
-      New = ::new (*Context) IBOutletAttr();
-      break;
-
-    case attr::IBOutletCollection: {
-      ObjCInterfaceDecl *D =
-        cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
-      New = ::new (*Context) IBOutletCollectionAttr(D);
-      break;
-    }
-
-    SIMPLE_ATTR(Malloc);
-    SIMPLE_ATTR(NoDebug);
-    SIMPLE_ATTR(NoInline);
-    SIMPLE_ATTR(NoReturn);
-    SIMPLE_ATTR(NoThrow);
-
-    case attr::NonNull: {
-      unsigned Size = Record[Idx++];
-      llvm::SmallVector<unsigned, 16> ArgNums;
-      ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size);
-      Idx += Size;
-      New = ::new (*Context) NonNullAttr(*Context, ArgNums.data(), Size);
-      break;
-    }
-
-    case attr::ReqdWorkGroupSize: {
-      unsigned X = Record[Idx++];
-      unsigned Y = Record[Idx++];
-      unsigned Z = Record[Idx++];
-      New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z);
-      break;
-    }
-
-    SIMPLE_ATTR(ObjCException);
-    SIMPLE_ATTR(ObjCNSObject);
-    SIMPLE_ATTR(CFReturnsNotRetained);
-    SIMPLE_ATTR(CFReturnsRetained);
-    SIMPLE_ATTR(NSReturnsNotRetained);
-    SIMPLE_ATTR(NSReturnsRetained);
-    SIMPLE_ATTR(Overloadable);
-    SIMPLE_ATTR(Override);
-    SIMPLE_ATTR(Packed);
-    UNSIGNED_ATTR(MaxFieldAlignment);
-    SIMPLE_ATTR(Pure);
-    UNSIGNED_ATTR(Regparm);
-    STRING_ATTR(Section);
-    SIMPLE_ATTR(StdCall);
-    SIMPLE_ATTR(ThisCall);
-    SIMPLE_ATTR(TransparentUnion);
-    SIMPLE_ATTR(Unavailable);
-    SIMPLE_ATTR(Unused);
-    SIMPLE_ATTR(Used);
-
-    case attr::Visibility:
-      New = ::new (*Context) VisibilityAttr(
-                              (VisibilityAttr::VisibilityTypes)Record[Idx++],
-                              (bool)Record[Idx++]);
-      break;
-
-    SIMPLE_ATTR(WarnUnusedResult);
-    SIMPLE_ATTR(Weak);
-    SIMPLE_ATTR(WeakRef);
-    SIMPLE_ATTR(WeakImport);
-    }
-
-    assert(New && "Unable to decode attribute?");
-    New->setInherited(IsInherited);
-    New->setNext(Attrs);
-    Attrs = New;
-  }
-#undef UNSIGNED_ATTR
-#undef STRING_ATTR
-#undef SIMPLE_ATTR
-
-  // The list of attributes was built backwards. Reverse the list
-  // before returning it.
-  Attr *PrevAttr = 0, *NextAttr = 0;
-  while (Attrs) {
-    NextAttr = Attrs->getNext();
-    Attrs->setNext(PrevAttr);
-    PrevAttr = Attrs;
-    Attrs = NextAttr;
-  }
-
-  return PrevAttr;
-}
-
-//===----------------------------------------------------------------------===//
-// PCHReader Implementation
-//===----------------------------------------------------------------------===//
-
-/// \brief Note that we have loaded the declaration with the given
-/// Index.
-///
-/// This routine notes that this declaration has already been loaded,
-/// so that future GetDecl calls will return this declaration rather
-/// than trying to load a new declaration.
-inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
-  assert(!DeclsLoaded[Index] && "Decl loaded twice?");
-  DeclsLoaded[Index] = D;
-}
-
-
-/// \brief Determine whether the consumer will be interested in seeing
-/// this declaration (via HandleTopLevelDecl).
-///
-/// This routine should return true for anything that might affect
-/// code generation, e.g., inline function definitions, Objective-C
-/// declarations with metadata, etc.
-static bool isConsumerInterestedIn(Decl *D) {
-  if (isa<FileScopeAsmDecl>(D))
-    return true;
-  if (VarDecl *Var = dyn_cast<VarDecl>(D))
-    return Var->isFileVarDecl() &&
-           Var->isThisDeclarationADefinition() == VarDecl::Definition;
-  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
-    return Func->isThisDeclarationADefinition();
-  return isa<ObjCProtocolDecl>(D) || isa<ObjCImplementationDecl>(D);
-}
-
-/// \brief Get the correct cursor and offset for loading a type.
-PCHReader::RecordLocation
-PCHReader::DeclCursorForIndex(unsigned Index, pch::DeclID ID) {
-  // See if there's an override.
-  DeclReplacementMap::iterator It = ReplacedDecls.find(ID);
-  if (It != ReplacedDecls.end())
-    return RecordLocation(&It->second.first->DeclsCursor, It->second.second);
-
-  PerFileData *F = 0;
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    F = Chain[N - I - 1];
-    if (Index < F->LocalNumDecls)
-      break;
-    Index -= F->LocalNumDecls;
-  }
-  assert(F && F->LocalNumDecls > Index && "Broken chain");
-  return RecordLocation(&F->DeclsCursor, F->DeclOffsets[Index]);
-}
-
-/// \brief Read the declaration at the given offset from the PCH file.
-Decl *PCHReader::ReadDeclRecord(unsigned Index, pch::DeclID ID) {
-  RecordLocation Loc = DeclCursorForIndex(Index, ID);
-  llvm::BitstreamCursor &DeclsCursor = *Loc.first;
-  // Keep track of where we are in the stream, then jump back there
-  // after reading this declaration.
-  SavedStreamPosition SavedPosition(DeclsCursor);
-
-  ReadingKindTracker ReadingKind(Read_Decl, *this);
-
-  // Note that we are loading a declaration record.
-  Deserializing ADecl(this);
-
-  DeclsCursor.JumpToBit(Loc.second);
-  RecordData Record;
-  unsigned Code = DeclsCursor.ReadCode();
-  unsigned Idx = 0;
-  PCHDeclReader Reader(*this, DeclsCursor, ID, Record, Idx);
-
-  Decl *D = 0;
-  switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) {
-  case pch::DECL_ATTR:
-  case pch::DECL_CONTEXT_LEXICAL:
-  case pch::DECL_CONTEXT_VISIBLE:
-    assert(false && "Record cannot be de-serialized with ReadDeclRecord");
-    break;
-  case pch::DECL_TRANSLATION_UNIT:
-    assert(Index == 0 && "Translation unit must be at index 0");
-    D = Context->getTranslationUnitDecl();
-    break;
-  case pch::DECL_TYPEDEF:
-    D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0);
-    break;
-  case pch::DECL_ENUM:
-    D = EnumDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_RECORD:
-    D = RecordDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_ENUM_CONSTANT:
-    D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),
-                                 0, llvm::APSInt());
-    break;
-  case pch::DECL_FUNCTION:
-    D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(),
-                             QualType(), 0);
-    break;
-  case pch::DECL_LINKAGE_SPEC:
-    D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(),
-                                (LinkageSpecDecl::LanguageIDs)0,
-                                false);
-    break;
-  case pch::DECL_NAMESPACE:
-    D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0);
-    break;
-  case pch::DECL_NAMESPACE_ALIAS:
-    D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(),
-                                   SourceLocation(), 0, SourceRange(), 0,
-                                   SourceLocation(), 0);
-    break;
-  case pch::DECL_USING:
-    D = UsingDecl::Create(*Context, 0, SourceRange(), SourceLocation(),
-                          0, DeclarationNameInfo(), false);
-    break;
-  case pch::DECL_USING_SHADOW:
-    D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0);
-    break;
-  case pch::DECL_USING_DIRECTIVE:
-    D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(),
-                                   SourceLocation(), SourceRange(), 0,
-                                   SourceLocation(), 0, 0);
-    break;
-  case pch::DECL_UNRESOLVED_USING_VALUE:
-    D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(),
-                                         SourceRange(), 0,
-                                         DeclarationNameInfo());
-    break;
-  case pch::DECL_UNRESOLVED_USING_TYPENAME:
-    D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(),
-                                            SourceLocation(), SourceRange(),
-                                            0, SourceLocation(),
-                                            DeclarationName());
-    break;
-  case pch::DECL_CXX_RECORD:
-    D = CXXRecordDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_CXX_METHOD:
-    D = CXXMethodDecl::Create(*Context, 0, DeclarationNameInfo(),
-                              QualType(), 0);
-    break;
-  case pch::DECL_CXX_CONSTRUCTOR:
-    D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_CXX_DESTRUCTOR:
-    D = CXXDestructorDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_CXX_CONVERSION:
-    D = CXXConversionDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_ACCESS_SPEC:
-    D = AccessSpecDecl::Create(*Context, AS_none, 0, SourceLocation(),
-                               SourceLocation());
-    break;
-  case pch::DECL_FRIEND:
-    D = FriendDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_FRIEND_TEMPLATE:
-    D = FriendTemplateDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_CLASS_TEMPLATE:
-    D = ClassTemplateDecl::Create(*Context, 0, SourceLocation(),
-                                  DeclarationName(), 0, 0, 0);
-    break;
-  case pch::DECL_CLASS_TEMPLATE_SPECIALIZATION:
-    D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
-    D = ClassTemplatePartialSpecializationDecl::Create(*Context,
-                                                            Decl::EmptyShell());
-    break;
-  case pch::DECL_FUNCTION_TEMPLATE:
-    D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(),
-                                     DeclarationName(), 0, 0);
-    break;
-  case pch::DECL_TEMPLATE_TYPE_PARM:
-    D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell());
-    break;
-  case pch::DECL_NON_TYPE_TEMPLATE_PARM:
-    D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
-                                        QualType(),0);
-    break;
-  case pch::DECL_TEMPLATE_TEMPLATE_PARM:
-    D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(),0,0,0,0);
-    break;
-  case pch::DECL_STATIC_ASSERT:
-    D = StaticAssertDecl::Create(*Context, 0, SourceLocation(), 0, 0);
-    break;
-
-  case pch::DECL_OBJC_METHOD:
-    D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(),
-                               Selector(), QualType(), 0, 0);
-    break;
-  case pch::DECL_OBJC_INTERFACE:
-    D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0);
-    break;
-  case pch::DECL_OBJC_IVAR:
-    D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
-                             ObjCIvarDecl::None);
-    break;
-  case pch::DECL_OBJC_PROTOCOL:
-    D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0);
-    break;
-  case pch::DECL_OBJC_AT_DEFS_FIELD:
-    D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0,
-                                    QualType(), 0);
-    break;
-  case pch::DECL_OBJC_CLASS:
-    D = ObjCClassDecl::Create(*Context, 0, SourceLocation());
-    break;
-  case pch::DECL_OBJC_FORWARD_PROTOCOL:
-    D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation());
-    break;
-  case pch::DECL_OBJC_CATEGORY:
-    D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), 
-                                 SourceLocation(), SourceLocation(), 0);
-    break;
-  case pch::DECL_OBJC_CATEGORY_IMPL:
-    D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0);
-    break;
-  case pch::DECL_OBJC_IMPLEMENTATION:
-    D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0);
-    break;
-  case pch::DECL_OBJC_COMPATIBLE_ALIAS:
-    D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0);
-    break;
-  case pch::DECL_OBJC_PROPERTY:
-    D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(),
-                                 0);
-    break;
-  case pch::DECL_OBJC_PROPERTY_IMPL:
-    D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(),
-                                     SourceLocation(), 0,
-                                     ObjCPropertyImplDecl::Dynamic, 0);
-    break;
-  case pch::DECL_FIELD:
-    D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0,
-                          false);
-    break;
-  case pch::DECL_VAR:
-    D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
-                        VarDecl::None, VarDecl::None);
-    break;
-
-  case pch::DECL_IMPLICIT_PARAM:
-    D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
-    break;
-
-  case pch::DECL_PARM_VAR:
-    D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
-                            VarDecl::None, VarDecl::None, 0);
-    break;
-  case pch::DECL_FILE_SCOPE_ASM:
-    D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0);
-    break;
-  case pch::DECL_BLOCK:
-    D = BlockDecl::Create(*Context, 0, SourceLocation());
-    break;
-  }
-
-  assert(D && "Unknown declaration reading PCH file");
-  LoadedDecl(Index, D);
-  Reader.Visit(D);
-
-  // If this declaration is also a declaration context, get the
-  // offsets for its tables of lexical and visible declarations.
-  if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
-    std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
-    if (Offsets.first || Offsets.second) {
-      DC->setHasExternalLexicalStorage(Offsets.first != 0);
-      DC->setHasExternalVisibleStorage(Offsets.second != 0);
-      DeclContextInfo Info;
-      if (ReadDeclContextStorage(DeclsCursor, Offsets, Info))
-        return 0;
-      DeclContextInfos &Infos = DeclContextOffsets[DC];
-      // Reading the TU will happen after reading its update blocks, so we need
-      // to make sure we insert in front. For all other contexts, the vector
-      // is empty here anyway, so there's no loss in efficiency.
-      Infos.insert(Infos.begin(), Info);
-    }
-  }
-  assert(Idx == Record.size());
-
-  // If we have deserialized a declaration that has a definition the
-  // AST consumer might need to know about, queue it.
-  // We don't pass it to the consumer immediately because we may be in recursive
-  // loading, and some declarations may still be initializing.
-  if (isConsumerInterestedIn(D))
-    InterestingDecls.push_back(D);
-
-  return D;
-}
-
-bool PCHReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
-                                   const std::pair<uint64_t, uint64_t> &Offsets,
-                                       DeclContextInfo &Info) {
-  SavedStreamPosition SavedPosition(Cursor);
-  // First the lexical decls.
-  if (Offsets.first != 0) {
-    Cursor.JumpToBit(Offsets.first);
-
-    RecordData Record;
-    const char *Blob;
-    unsigned BlobLen;
-    unsigned Code = Cursor.ReadCode();
-    unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
-    if (RecCode != pch::DECL_CONTEXT_LEXICAL) {
-      Error("Expected lexical block");
-      return true;
-    }
-
-    Info.LexicalDecls = reinterpret_cast<const pch::DeclID*>(Blob);
-    Info.NumLexicalDecls = BlobLen / sizeof(pch::DeclID);
-  } else {
-    Info.LexicalDecls = 0;
-    Info.NumLexicalDecls = 0;
-  }
-
-  // Now the visible decls.
-  Info.Stream = &Cursor;
-  Info.OffsetToVisibleDecls = Offsets.second;
-
-  return false;
-}
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
deleted file mode 100644
index 41c8a9a..0000000
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ /dev/null
@@ -1,1775 +0,0 @@
-//===--- PCHReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Statement/expression deserialization.  This implements the
-// PCHReader::ReadStmt method.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/PCHReader.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/StmtVisitor.h"
-using namespace clang;
-
-namespace clang {
-
-  class PCHStmtReader : public StmtVisitor<PCHStmtReader> {
-    PCHReader &Reader;
-    llvm::BitstreamCursor &DeclsCursor;
-    const PCHReader::RecordData &Record;
-    unsigned &Idx;
-
-  public:
-    PCHStmtReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor,
-                  const PCHReader::RecordData &Record, unsigned &Idx)
-      : Reader(Reader), DeclsCursor(Cursor), Record(Record), Idx(Idx) { }
-
-    /// \brief The number of record fields required for the Stmt class
-    /// itself.
-    static const unsigned NumStmtFields = 0;
-
-    /// \brief The number of record fields required for the Expr class
-    /// itself.
-    static const unsigned NumExprFields = NumStmtFields + 3;
-    
-    /// \brief Read and initialize a ExplicitTemplateArgumentList structure.
-    void ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList,
-                                          unsigned NumTemplateArgs);
-
-    void VisitStmt(Stmt *S);
-    void VisitNullStmt(NullStmt *S);
-    void VisitCompoundStmt(CompoundStmt *S);
-    void VisitSwitchCase(SwitchCase *S);
-    void VisitCaseStmt(CaseStmt *S);
-    void VisitDefaultStmt(DefaultStmt *S);
-    void VisitLabelStmt(LabelStmt *S);
-    void VisitIfStmt(IfStmt *S);
-    void VisitSwitchStmt(SwitchStmt *S);
-    void VisitWhileStmt(WhileStmt *S);
-    void VisitDoStmt(DoStmt *S);
-    void VisitForStmt(ForStmt *S);
-    void VisitGotoStmt(GotoStmt *S);
-    void VisitIndirectGotoStmt(IndirectGotoStmt *S);
-    void VisitContinueStmt(ContinueStmt *S);
-    void VisitBreakStmt(BreakStmt *S);
-    void VisitReturnStmt(ReturnStmt *S);
-    void VisitDeclStmt(DeclStmt *S);
-    void VisitAsmStmt(AsmStmt *S);
-    void VisitExpr(Expr *E);
-    void VisitPredefinedExpr(PredefinedExpr *E);
-    void VisitDeclRefExpr(DeclRefExpr *E);
-    void VisitIntegerLiteral(IntegerLiteral *E);
-    void VisitFloatingLiteral(FloatingLiteral *E);
-    void VisitImaginaryLiteral(ImaginaryLiteral *E);
-    void VisitStringLiteral(StringLiteral *E);
-    void VisitCharacterLiteral(CharacterLiteral *E);
-    void VisitParenExpr(ParenExpr *E);
-    void VisitParenListExpr(ParenListExpr *E);
-    void VisitUnaryOperator(UnaryOperator *E);
-    void VisitOffsetOfExpr(OffsetOfExpr *E);
-    void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
-    void VisitArraySubscriptExpr(ArraySubscriptExpr *E);
-    void VisitCallExpr(CallExpr *E);
-    void VisitMemberExpr(MemberExpr *E);
-    void VisitCastExpr(CastExpr *E);
-    void VisitBinaryOperator(BinaryOperator *E);
-    void VisitCompoundAssignOperator(CompoundAssignOperator *E);
-    void VisitConditionalOperator(ConditionalOperator *E);
-    void VisitImplicitCastExpr(ImplicitCastExpr *E);
-    void VisitExplicitCastExpr(ExplicitCastExpr *E);
-    void VisitCStyleCastExpr(CStyleCastExpr *E);
-    void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
-    void VisitExtVectorElementExpr(ExtVectorElementExpr *E);
-    void VisitInitListExpr(InitListExpr *E);
-    void VisitDesignatedInitExpr(DesignatedInitExpr *E);
-    void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
-    void VisitVAArgExpr(VAArgExpr *E);
-    void VisitAddrLabelExpr(AddrLabelExpr *E);
-    void VisitStmtExpr(StmtExpr *E);
-    void VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
-    void VisitChooseExpr(ChooseExpr *E);
-    void VisitGNUNullExpr(GNUNullExpr *E);
-    void VisitShuffleVectorExpr(ShuffleVectorExpr *E);
-    void VisitBlockExpr(BlockExpr *E);
-    void VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
-    void VisitObjCStringLiteral(ObjCStringLiteral *E);
-    void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
-    void VisitObjCSelectorExpr(ObjCSelectorExpr *E);
-    void VisitObjCProtocolExpr(ObjCProtocolExpr *E);
-    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E);
-    void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
-    void VisitObjCImplicitSetterGetterRefExpr(
-                            ObjCImplicitSetterGetterRefExpr *E);
-    void VisitObjCMessageExpr(ObjCMessageExpr *E);
-    void VisitObjCSuperExpr(ObjCSuperExpr *E);
-    void VisitObjCIsaExpr(ObjCIsaExpr *E);
-
-    void VisitObjCForCollectionStmt(ObjCForCollectionStmt *);
-    void VisitObjCAtCatchStmt(ObjCAtCatchStmt *);
-    void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *);
-    void VisitObjCAtTryStmt(ObjCAtTryStmt *);
-    void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *);
-    void VisitObjCAtThrowStmt(ObjCAtThrowStmt *);
-
-    // C++ Statements
-    void VisitCXXCatchStmt(CXXCatchStmt *S);
-    void VisitCXXTryStmt(CXXTryStmt *S);
-
-    void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
-    void VisitCXXConstructExpr(CXXConstructExpr *E);
-    void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
-    void VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
-    void VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
-    void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
-    void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
-    void VisitCXXConstCastExpr(CXXConstCastExpr *E);
-    void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
-    void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
-    void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
-    void VisitCXXTypeidExpr(CXXTypeidExpr *E);
-    void VisitCXXThisExpr(CXXThisExpr *E);
-    void VisitCXXThrowExpr(CXXThrowExpr *E);
-    void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
-    void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
-    void VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E);
-    
-    void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
-    void VisitCXXNewExpr(CXXNewExpr *E);
-    void VisitCXXDeleteExpr(CXXDeleteExpr *E);
-    void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
-    
-    void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E);
-    
-    void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
-    void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
-    void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
-
-    void VisitOverloadExpr(OverloadExpr *E);
-    void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
-    void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
-
-    void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
-  };
-}
-
-void PCHStmtReader::
-ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList,
-                                 unsigned NumTemplateArgs) {
-  TemplateArgumentListInfo ArgInfo;
-  ArgInfo.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx));
-  ArgInfo.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx));
-  for (unsigned i = 0; i != NumTemplateArgs; ++i)
-    ArgInfo.addArgument(
-        Reader.ReadTemplateArgumentLoc(DeclsCursor, Record, Idx));
-  ArgList.initializeFrom(ArgInfo);
-}
-
-void PCHStmtReader::VisitStmt(Stmt *S) {
-  assert(Idx == NumStmtFields && "Incorrect statement field count");
-}
-
-void PCHStmtReader::VisitNullStmt(NullStmt *S) {
-  VisitStmt(S);
-  S->setSemiLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) {
-  VisitStmt(S);
-  llvm::SmallVector<Stmt *, 16> Stmts;
-  unsigned NumStmts = Record[Idx++];
-  while (NumStmts--)
-    Stmts.push_back(Reader.ReadSubStmt());
-  S->setStmts(*Reader.getContext(), Stmts.data(), Stmts.size());
-  S->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitSwitchCase(SwitchCase *S) {
-  VisitStmt(S);
-  Reader.RecordSwitchCaseID(S, Record[Idx++]);
-}
-
-void PCHStmtReader::VisitCaseStmt(CaseStmt *S) {
-  VisitSwitchCase(S);
-  S->setLHS(Reader.ReadSubExpr());
-  S->setRHS(Reader.ReadSubExpr());
-  S->setSubStmt(Reader.ReadSubStmt());
-  S->setCaseLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setEllipsisLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) {
-  VisitSwitchCase(S);
-  S->setSubStmt(Reader.ReadSubStmt());
-  S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitLabelStmt(LabelStmt *S) {
-  VisitStmt(S);
-  S->setID(Reader.GetIdentifierInfo(Record, Idx));
-  S->setSubStmt(Reader.ReadSubStmt());
-  S->setIdentLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  Reader.RecordLabelStmt(S, Record[Idx++]);
-}
-
-void PCHStmtReader::VisitIfStmt(IfStmt *S) {
-  VisitStmt(S);
-  S->setConditionVariable(*Reader.getContext(),
-                          cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
-  S->setCond(Reader.ReadSubExpr());
-  S->setThen(Reader.ReadSubStmt());
-  S->setElse(Reader.ReadSubStmt());
-  S->setIfLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setElseLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) {
-  VisitStmt(S);
-  S->setConditionVariable(*Reader.getContext(),
-                          cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
-  S->setCond(Reader.ReadSubExpr());
-  S->setBody(Reader.ReadSubStmt());
-  S->setSwitchLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  SwitchCase *PrevSC = 0;
-  for (unsigned N = Record.size(); Idx != N; ++Idx) {
-    SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]);
-    if (PrevSC)
-      PrevSC->setNextSwitchCase(SC);
-    else
-      S->setSwitchCaseList(SC);
-
-    // Retain this SwitchCase, since SwitchStmt::addSwitchCase() would
-    // normally retain it (but we aren't calling addSwitchCase).
-    SC->Retain();
-    PrevSC = SC;
-  }
-}
-
-void PCHStmtReader::VisitWhileStmt(WhileStmt *S) {
-  VisitStmt(S);
-  S->setConditionVariable(*Reader.getContext(),
-                          cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
-  S->setCond(Reader.ReadSubExpr());
-  S->setBody(Reader.ReadSubStmt());
-  S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitDoStmt(DoStmt *S) {
-  VisitStmt(S);
-  S->setCond(Reader.ReadSubExpr());
-  S->setBody(Reader.ReadSubStmt());
-  S->setDoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitForStmt(ForStmt *S) {
-  VisitStmt(S);
-  S->setInit(Reader.ReadSubStmt());
-  S->setCond(Reader.ReadSubExpr());
-  S->setConditionVariable(*Reader.getContext(),
-                          cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
-  S->setInc(Reader.ReadSubExpr());
-  S->setBody(Reader.ReadSubStmt());
-  S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitGotoStmt(GotoStmt *S) {
-  VisitStmt(S);
-  Reader.SetLabelOf(S, Record[Idx++]);
-  S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
-  VisitStmt(S);
-  S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setTarget(Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitContinueStmt(ContinueStmt *S) {
-  VisitStmt(S);
-  S->setContinueLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitBreakStmt(BreakStmt *S) {
-  VisitStmt(S);
-  S->setBreakLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitReturnStmt(ReturnStmt *S) {
-  VisitStmt(S);
-  S->setRetValue(Reader.ReadSubExpr());
-  S->setReturnLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setNRVOCandidate(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHStmtReader::VisitDeclStmt(DeclStmt *S) {
-  VisitStmt(S);
-  S->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-
-  if (Idx + 1 == Record.size()) {
-    // Single declaration
-    S->setDeclGroup(DeclGroupRef(Reader.GetDecl(Record[Idx++])));
-  } else {
-    llvm::SmallVector<Decl *, 16> Decls;
-    Decls.reserve(Record.size() - Idx);
-    for (unsigned N = Record.size(); Idx != N; ++Idx)
-      Decls.push_back(Reader.GetDecl(Record[Idx]));
-    S->setDeclGroup(DeclGroupRef(DeclGroup::Create(*Reader.getContext(),
-                                                   Decls.data(),
-                                                   Decls.size())));
-  }
-}
-
-void PCHStmtReader::VisitAsmStmt(AsmStmt *S) {
-  VisitStmt(S);
-  unsigned NumOutputs = Record[Idx++];
-  unsigned NumInputs = Record[Idx++];
-  unsigned NumClobbers = Record[Idx++];
-  S->setAsmLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setVolatile(Record[Idx++]);
-  S->setSimple(Record[Idx++]);
-  S->setMSAsm(Record[Idx++]);
-
-  S->setAsmString(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
-
-  // Outputs and inputs
-  llvm::SmallVector<IdentifierInfo *, 16> Names;
-  llvm::SmallVector<StringLiteral*, 16> Constraints;
-  llvm::SmallVector<Stmt*, 16> Exprs;
-  for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) {
-    Names.push_back(Reader.GetIdentifierInfo(Record, Idx));
-    Constraints.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
-    Exprs.push_back(Reader.ReadSubStmt());
-  }
-
-  // Constraints
-  llvm::SmallVector<StringLiteral*, 16> Clobbers;
-  for (unsigned I = 0; I != NumClobbers; ++I)
-    Clobbers.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
-
-  S->setOutputsAndInputsAndClobbers(*Reader.getContext(),
-                                    Names.data(), Constraints.data(), 
-                                    Exprs.data(), NumOutputs, NumInputs, 
-                                    Clobbers.data(), NumClobbers);
-}
-
-void PCHStmtReader::VisitExpr(Expr *E) {
-  VisitStmt(E);
-  E->setType(Reader.GetType(Record[Idx++]));
-  E->setTypeDependent(Record[Idx++]);
-  E->setValueDependent(Record[Idx++]);
-  assert(Idx == NumExprFields && "Incorrect expression field count");
-}
-
-void PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
-  VisitExpr(E);
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
-}
-
-void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
-  VisitExpr(E);
-
-  bool HasQualifier = Record[Idx++];
-  unsigned NumTemplateArgs = Record[Idx++];
-  
-  E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) |
-      (NumTemplateArgs ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0));
-  
-  if (HasQualifier) {
-    E->getNameQualifier()->NNS = Reader.ReadNestedNameSpecifier(Record, Idx);
-    E->getNameQualifier()->Range = Reader.ReadSourceRange(Record, Idx);
-  }
-
-  if (NumTemplateArgs)
-    ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(),
-                                     NumTemplateArgs);
-
-  E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
-  // FIXME: read DeclarationNameLoc.
-  E->setLocation(Reader.ReadSourceLocation(Record, Idx));
-}
-
-void PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
-  VisitExpr(E);
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setValue(Reader.ReadAPInt(Record, Idx));
-}
-
-void PCHStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
-  VisitExpr(E);
-  E->setValue(Reader.ReadAPFloat(Record, Idx));
-  E->setExact(Record[Idx++]);
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) {
-  VisitExpr(E);
-  E->setSubExpr(Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitStringLiteral(StringLiteral *E) {
-  VisitExpr(E);
-  unsigned Len = Record[Idx++];
-  assert(Record[Idx] == E->getNumConcatenated() &&
-         "Wrong number of concatenated tokens!");
-  ++Idx;
-  E->setWide(Record[Idx++]);
-
-  // Read string data
-  llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len);
-  E->setString(*Reader.getContext(), Str.str());
-  Idx += Len;
-
-  // Read source locations
-  for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
-    E->setStrTokenLoc(I, SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
-  VisitExpr(E);
-  E->setValue(Record[Idx++]);
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setWide(Record[Idx++]);
-}
-
-void PCHStmtReader::VisitParenExpr(ParenExpr *E) {
-  VisitExpr(E);
-  E->setLParen(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParen(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setSubExpr(Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitParenListExpr(ParenListExpr *E) {
-  VisitExpr(E);
-  unsigned NumExprs = Record[Idx++];
-  E->Exprs = new (*Reader.getContext()) Stmt*[NumExprs];
-  for (unsigned i = 0; i != NumExprs; ++i)
-    E->Exprs[i] = Reader.ReadSubStmt();
-  E->NumExprs = NumExprs;
-  E->LParenLoc = Reader.ReadSourceLocation(Record, Idx);
-  E->RParenLoc = Reader.ReadSourceLocation(Record, Idx);
-}
-
-void PCHStmtReader::VisitUnaryOperator(UnaryOperator *E) {
-  VisitExpr(E);
-  E->setSubExpr(Reader.ReadSubExpr());
-  E->setOpcode((UnaryOperator::Opcode)Record[Idx++]);
-  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
-  typedef OffsetOfExpr::OffsetOfNode Node;
-  VisitExpr(E);
-  assert(E->getNumComponents() == Record[Idx]);
-  ++Idx;
-  assert(E->getNumExpressions() == Record[Idx]);
-  ++Idx;
-  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-  for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
-    Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]);
-    SourceLocation Start = SourceLocation::getFromRawEncoding(Record[Idx++]);
-    SourceLocation End = SourceLocation::getFromRawEncoding(Record[Idx++]);
-    switch (Kind) {
-    case Node::Array:
-      E->setComponent(I, Node(Start, Record[Idx++], End));
-      break;
-        
-    case Node::Field:
-      E->setComponent(I, 
-             Node(Start,  
-                  dyn_cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])),
-                  End));
-      break;
-
-    case Node::Identifier:
-      E->setComponent(I, Node(Start, Reader.GetIdentifier(Record[Idx++]), End));
-      break;
-        
-    case Node::Base: {
-      CXXBaseSpecifier *Base = new (*Reader.getContext()) CXXBaseSpecifier();
-      *Base = Reader.ReadCXXBaseSpecifier(DeclsCursor, Record, Idx);
-      E->setComponent(I, Node(Base));
-      break;
-    }
-    }
-  }
-  
-  for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I)
-    E->setIndexExpr(I, Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
-  VisitExpr(E);
-  E->setSizeof(Record[Idx++]);
-  if (Record[Idx] == 0) {
-    E->setArgument(Reader.ReadSubExpr());
-    ++Idx;
-  } else {
-    E->setArgument(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-  }
-  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
-  VisitExpr(E);
-  E->setLHS(Reader.ReadSubExpr());
-  E->setRHS(Reader.ReadSubExpr());
-  E->setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCallExpr(CallExpr *E) {
-  VisitExpr(E);
-  E->setNumArgs(*Reader.getContext(), Record[Idx++]);
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setCallee(Reader.ReadSubExpr());
-  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
-    E->setArg(I, Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitMemberExpr(MemberExpr *E) {
-  // Don't call VisitExpr, this is fully initialized at creation.
-  assert(E->getStmtClass() == Stmt::MemberExprClass &&
-         "It's a subclass, we must advance Idx!");
-}
-
-void PCHStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) {
-  VisitExpr(E);
-  E->setBase(Reader.ReadSubExpr());
-  E->setIsaMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setArrow(Record[Idx++]);
-}
-
-void PCHStmtReader::VisitCastExpr(CastExpr *E) {
-  VisitExpr(E);
-  unsigned NumBaseSpecs = Record[Idx++];
-  assert(NumBaseSpecs == E->path_size());
-  E->setSubExpr(Reader.ReadSubExpr());
-  E->setCastKind((CastExpr::CastKind)Record[Idx++]);
-  CastExpr::path_iterator BaseI = E->path_begin();
-  while (NumBaseSpecs--) {
-    CXXBaseSpecifier *BaseSpec = new (*Reader.getContext()) CXXBaseSpecifier;
-    *BaseSpec = Reader.ReadCXXBaseSpecifier(DeclsCursor, Record, Idx);
-    *BaseI++ = BaseSpec;
-  }
-}
-
-void PCHStmtReader::VisitBinaryOperator(BinaryOperator *E) {
-  VisitExpr(E);
-  E->setLHS(Reader.ReadSubExpr());
-  E->setRHS(Reader.ReadSubExpr());
-  E->setOpcode((BinaryOperator::Opcode)Record[Idx++]);
-  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
-  VisitBinaryOperator(E);
-  E->setComputationLHSType(Reader.GetType(Record[Idx++]));
-  E->setComputationResultType(Reader.GetType(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
-  VisitExpr(E);
-  E->setCond(Reader.ReadSubExpr());
-  E->setLHS(Reader.ReadSubExpr());
-  E->setRHS(Reader.ReadSubExpr());
-  E->setQuestionLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
-  VisitCastExpr(E);
-  E->setCategory(static_cast<ImplicitCastExpr::ResultCategory>(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
-  VisitCastExpr(E);
-  E->setTypeInfoAsWritten(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-}
-
-void PCHStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
-  VisitExplicitCastExpr(E);
-  E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
-  VisitExpr(E);
-  E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-  E->setInitializer(Reader.ReadSubExpr());
-  E->setFileScope(Record[Idx++]);
-}
-
-void PCHStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
-  VisitExpr(E);
-  E->setBase(Reader.ReadSubExpr());
-  E->setAccessor(Reader.GetIdentifierInfo(Record, Idx));
-  E->setAccessorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitInitListExpr(InitListExpr *E) {
-  VisitExpr(E);
-  unsigned NumInits = Record[Idx++];
-  E->reserveInits(*Reader.getContext(), NumInits);
-  for (unsigned I = 0; I != NumInits; ++I)
-    E->updateInit(*Reader.getContext(), I, Reader.ReadSubExpr());
-  E->setSyntacticForm(cast_or_null<InitListExpr>(Reader.ReadSubStmt()));
-  E->setLBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setInitializedFieldInUnion(
-                      cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])));
-  E->sawArrayRangeDesignator(Record[Idx++]);
-}
-
-void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
-  typedef DesignatedInitExpr::Designator Designator;
-
-  VisitExpr(E);
-  unsigned NumSubExprs = Record[Idx++];
-  assert(NumSubExprs == E->getNumSubExprs() && "Wrong number of subexprs");
-  for (unsigned I = 0; I != NumSubExprs; ++I)
-    E->setSubExpr(I, Reader.ReadSubExpr());
-  E->setEqualOrColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setGNUSyntax(Record[Idx++]);
-
-  llvm::SmallVector<Designator, 4> Designators;
-  while (Idx < Record.size()) {
-    switch ((pch::DesignatorTypes)Record[Idx++]) {
-    case pch::DESIG_FIELD_DECL: {
-      FieldDecl *Field = cast<FieldDecl>(Reader.GetDecl(Record[Idx++]));
-      SourceLocation DotLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      SourceLocation FieldLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      Designators.push_back(Designator(Field->getIdentifier(), DotLoc,
-                                       FieldLoc));
-      Designators.back().setField(Field);
-      break;
-    }
-
-    case pch::DESIG_FIELD_NAME: {
-      const IdentifierInfo *Name = Reader.GetIdentifierInfo(Record, Idx);
-      SourceLocation DotLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      SourceLocation FieldLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      Designators.push_back(Designator(Name, DotLoc, FieldLoc));
-      break;
-    }
-
-    case pch::DESIG_ARRAY: {
-      unsigned Index = Record[Idx++];
-      SourceLocation LBracketLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      SourceLocation RBracketLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc));
-      break;
-    }
-
-    case pch::DESIG_ARRAY_RANGE: {
-      unsigned Index = Record[Idx++];
-      SourceLocation LBracketLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      SourceLocation EllipsisLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      SourceLocation RBracketLoc
-        = SourceLocation::getFromRawEncoding(Record[Idx++]);
-      Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc,
-                                       RBracketLoc));
-      break;
-    }
-    }
-  }
-  E->setDesignators(*Reader.getContext(), 
-                    Designators.data(), Designators.size());
-}
-
-void PCHStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
-  VisitExpr(E);
-}
-
-void PCHStmtReader::VisitVAArgExpr(VAArgExpr *E) {
-  VisitExpr(E);
-  E->setSubExpr(Reader.ReadSubExpr());
-  E->setWrittenTypeInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-  E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
-  VisitExpr(E);
-  E->setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  Reader.SetLabelOf(E, Record[Idx++]);
-}
-
-void PCHStmtReader::VisitStmtExpr(StmtExpr *E) {
-  VisitExpr(E);
-  E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setSubStmt(cast_or_null<CompoundStmt>(Reader.ReadSubStmt()));
-}
-
-void PCHStmtReader::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
-  VisitExpr(E);
-  E->setArgTInfo1(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-  E->setArgTInfo2(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-  E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitChooseExpr(ChooseExpr *E) {
-  VisitExpr(E);
-  E->setCond(Reader.ReadSubExpr());
-  E->setLHS(Reader.ReadSubExpr());
-  E->setRHS(Reader.ReadSubExpr());
-  E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitGNUNullExpr(GNUNullExpr *E) {
-  VisitExpr(E);
-  E->setTokenLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
-  VisitExpr(E);
-  llvm::SmallVector<Expr *, 16> Exprs;
-  unsigned NumExprs = Record[Idx++];
-  while (NumExprs--)
-    Exprs.push_back(Reader.ReadSubExpr());
-  E->setExprs(*Reader.getContext(), Exprs.data(), Exprs.size());
-  E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitBlockExpr(BlockExpr *E) {
-  VisitExpr(E);
-  E->setBlockDecl(cast_or_null<BlockDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setHasBlockDeclRefExprs(Record[Idx++]);
-}
-
-void PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
-  VisitExpr(E);
-  E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setByRef(Record[Idx++]);
-  E->setConstQualAdded(Record[Idx++]);
-  E->setCopyConstructorExpr(Reader.ReadSubExpr());
-}
-
-//===----------------------------------------------------------------------===//
-// Objective-C Expressions and Statements
-
-void PCHStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) {
-  VisitExpr(E);
-  E->setString(cast<StringLiteral>(Reader.ReadSubStmt()));
-  E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
-  VisitExpr(E);
-  E->setEncodedTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor,Record,Idx));
-  E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
-  VisitExpr(E);
-  E->setSelector(Reader.GetSelector(Record, Idx));
-  E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
-  VisitExpr(E);
-  E->setProtocol(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
-  VisitExpr(E);
-  E->setDecl(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setBase(Reader.ReadSubExpr());
-  E->setIsArrow(Record[Idx++]);
-  E->setIsFreeIvar(Record[Idx++]);
-}
-
-void PCHStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
-  VisitExpr(E);
-  E->setProperty(cast<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setBase(Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitObjCImplicitSetterGetterRefExpr(
-                                      ObjCImplicitSetterGetterRefExpr *E) {
-  VisitExpr(E);
-  E->setGetterMethod(
-                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setSetterMethod(
-                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setInterfaceDecl(
-              cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setBase(Reader.ReadSubExpr());
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
-  VisitExpr(E);
-  assert(Record[Idx] == E->getNumArgs());
-  ++Idx;
-  ObjCMessageExpr::ReceiverKind Kind
-    = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]);
-  switch (Kind) {
-  case ObjCMessageExpr::Instance:
-    E->setInstanceReceiver(Reader.ReadSubExpr());
-    break;
-
-  case ObjCMessageExpr::Class:
-    E->setClassReceiver(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-    break;
-
-  case ObjCMessageExpr::SuperClass:
-  case ObjCMessageExpr::SuperInstance: {
-    QualType T = Reader.GetType(Record[Idx++]);
-    SourceLocation SuperLoc = SourceLocation::getFromRawEncoding(Record[Idx++]);
-    E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance);
-    break;
-  }
-  }
-
-  assert(Kind == E->getReceiverKind());
-
-  if (Record[Idx++])
-    E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
-  else
-    E->setSelector(Reader.GetSelector(Record, Idx));
-
-  E->setLeftLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRightLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-
-  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
-    E->setArg(I, Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitObjCSuperExpr(ObjCSuperExpr *E) {
-  VisitExpr(E);
-  E->setLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
-  VisitStmt(S);
-  S->setElement(Reader.ReadSubStmt());
-  S->setCollection(Reader.ReadSubExpr());
-  S->setBody(Reader.ReadSubStmt());
-  S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
-  VisitStmt(S);
-  S->setCatchBody(Reader.ReadSubStmt());
-  S->setCatchParamDecl(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
-  S->setAtCatchLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
-  VisitStmt(S);
-  S->setFinallyBody(Reader.ReadSubStmt());
-  S->setAtFinallyLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
-  VisitStmt(S);
-  assert(Record[Idx] == S->getNumCatchStmts());
-  ++Idx;
-  bool HasFinally = Record[Idx++];
-  S->setTryBody(Reader.ReadSubStmt());
-  for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I)
-    S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(Reader.ReadSubStmt()));
-
-  if (HasFinally)
-    S->setFinallyStmt(Reader.ReadSubStmt());
-  S->setAtTryLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
-  VisitStmt(S);
-  S->setSynchExpr(Reader.ReadSubStmt());
-  S->setSynchBody(Reader.ReadSubStmt());
-  S->setAtSynchronizedLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
-  VisitStmt(S);
-  S->setThrowExpr(Reader.ReadSubStmt());
-  S->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-//===----------------------------------------------------------------------===//
-// C++ Expressions and Statements
-//===----------------------------------------------------------------------===//
-
-void PCHStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) {
-  VisitStmt(S);
-  S->CatchLoc = Reader.ReadSourceLocation(Record, Idx);
-  S->ExceptionDecl = cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]));
-  S->HandlerBlock = Reader.ReadSubStmt();
-}
-
-void PCHStmtReader::VisitCXXTryStmt(CXXTryStmt *S) {
-  VisitStmt(S);
-  assert(Record[Idx] == S->getNumHandlers() && "NumStmtFields is wrong ?");
-  ++Idx;
-  S->TryLoc = Reader.ReadSourceLocation(Record, Idx);
-  S->getStmts()[0] = Reader.ReadSubStmt();
-  for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i)
-    S->getStmts()[i + 1] = Reader.ReadSubStmt();
-}
-
-void PCHStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
-  VisitCallExpr(E);
-  E->setOperator((OverloadedOperatorKind)Record[Idx++]);
-}
-
-void PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
-  VisitExpr(E);
-  E->NumArgs = Record[Idx++];
-  if (E->NumArgs)
-    E->Args = new (*Reader.getContext()) Stmt*[E->NumArgs];
-  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
-    E->setArg(I, Reader.ReadSubExpr());
-  E->setConstructor(cast<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setElidable(Record[Idx++]);  
-  E->setRequiresZeroInitialization(Record[Idx++]);
-  E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]);
-}
-
-void PCHStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
-  VisitCXXConstructExpr(E);
-  E->TyBeginLoc = Reader.ReadSourceLocation(Record, Idx);
-  E->RParenLoc = Reader.ReadSourceLocation(Record, Idx);
-}
-
-void PCHStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
-  VisitExplicitCastExpr(E);
-  E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
-  return VisitCXXNamedCastExpr(E);
-}
-
-void PCHStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
-  return VisitCXXNamedCastExpr(E);
-}
-
-void PCHStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
-  return VisitCXXNamedCastExpr(E);
-}
-
-void PCHStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
-  return VisitCXXNamedCastExpr(E);
-}
-
-void PCHStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
-  VisitExplicitCastExpr(E);
-  E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
-  VisitExpr(E);
-  E->setValue(Record[Idx++]);
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
-  VisitExpr(E);
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
-  VisitExpr(E);
-  E->setSourceRange(Reader.ReadSourceRange(Record, Idx));
-  if (E->isTypeOperand()) { // typeid(int)
-    E->setTypeOperandSourceInfo(
-        Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-    return;
-  }
-  
-  // typeid(42+2)
-  E->setExprOperand(Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitCXXThisExpr(CXXThisExpr *E) {
-  VisitExpr(E);
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setImplicit(Record[Idx++]);
-}
-
-void PCHStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) {
-  VisitExpr(E);
-  E->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setSubExpr(Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
-  VisitExpr(E);
-
-  assert(Record[Idx] == E->Param.getInt() && "We messed up at creation ?");
-  ++Idx; // HasOtherExprStored and SubExpr was handled during creation.
-  E->Param.setPointer(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
-  E->Loc = Reader.ReadSourceLocation(Record, Idx);
-}
-
-void PCHStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
-  VisitExpr(E);
-  E->setTemporary(Reader.ReadCXXTemporary(Record, Idx));
-  E->setSubExpr(Reader.ReadSubExpr());
-}
-
-void PCHStmtReader::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E) {
-  VisitExpr(E);
-  E->SubExpr = Reader.ReadSubExpr();
-  E->ExtendsLifetime = Record[Idx++];
-  E->RequiresTemporaryCopy = Record[Idx++];
-}
-
-void PCHStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
-  VisitExpr(E);
-  E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCXXNewExpr(CXXNewExpr *E) {
-  VisitExpr(E);
-  E->setGlobalNew(Record[Idx++]);
-  E->setHasInitializer(Record[Idx++]);
-  bool isArray = Record[Idx++];
-  unsigned NumPlacementArgs = Record[Idx++];
-  unsigned NumCtorArgs = Record[Idx++];
-  E->setOperatorNew(cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setOperatorDelete(
-                    cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setConstructor(
-               cast_or_null<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++])));
-  SourceRange TypeIdParens;
-  TypeIdParens.setBegin(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  TypeIdParens.setEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->TypeIdParens = TypeIdParens;
-  E->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  
-  E->AllocateArgsArray(*Reader.getContext(), isArray, NumPlacementArgs,
-                       NumCtorArgs);
-
-  // Install all the subexpressions.
-  for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end();
-       I != e; ++I)
-    *I = Reader.ReadSubStmt();
-}
-
-void PCHStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
-  VisitExpr(E);
-  E->setGlobalDelete(Record[Idx++]);
-  E->setArrayForm(Record[Idx++]);
-  E->setOperatorDelete(
-                     cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setArgument(Reader.ReadSubExpr());
-  E->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-
-void PCHStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
-  VisitExpr(E);
-
-  E->setBase(Reader.ReadSubExpr());
-  E->setArrow(Record[Idx++]);
-  E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx));
-  E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
-  E->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-  E->setScopeTypeInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-  E->setColonColonLoc(Reader.ReadSourceLocation(Record, Idx));
-  E->setTildeLoc(Reader.ReadSourceLocation(Record, Idx));
-  
-  IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx);
-  if (II)
-    E->setDestroyedType(II, Reader.ReadSourceLocation(Record, Idx));
-  else
-    E->setDestroyedType(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
-}
-
-void PCHStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
-  VisitExpr(E);
-  unsigned NumTemps = Record[Idx++];
-  if (NumTemps) {
-    E->setNumTemporaries(*Reader.getContext(), NumTemps);
-    for (unsigned i = 0; i != NumTemps; ++i)
-      E->setTemporary(i, Reader.ReadCXXTemporary(Record, Idx));
-  }
-  E->setSubExpr(Reader.ReadSubExpr());
-}
-
-void
-PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
-  VisitExpr(E);
-  
-  unsigned NumTemplateArgs = Record[Idx++];
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
-         "Read wrong record during creation ?");
-  if (E->hasExplicitTemplateArgs())
-    ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(),
-                                     NumTemplateArgs);
-
-  E->setBase(Reader.ReadSubExpr());
-  E->setBaseType(Reader.GetType(Record[Idx++]));
-  E->setArrow(Record[Idx++]);
-  E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx));
-  E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
-  E->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-  E->setFirstQualifierFoundInScope(
-                        cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])));
-  // FIXME: read whole DeclarationNameInfo.
-  E->setMember(Reader.ReadDeclarationName(Record, Idx));
-  E->setMemberLoc(Reader.ReadSourceLocation(Record, Idx));
-}
-
-void
-PCHStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
-  VisitExpr(E);
-  
-  unsigned NumTemplateArgs = Record[Idx++];
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
-         "Read wrong record during creation ?");
-  if (E->hasExplicitTemplateArgs())
-    ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
-                                     NumTemplateArgs);
-
-  // FIXME: read whole DeclarationNameInfo.
-  E->setDeclName(Reader.ReadDeclarationName(Record, Idx));
-  E->setLocation(Reader.ReadSourceLocation(Record, Idx));
-  E->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-  E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
-}
-
-void
-PCHStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
-  VisitExpr(E);
-  assert(Record[Idx] == E->arg_size() && "Read wrong record during creation ?");
-  ++Idx; // NumArgs;
-  for (unsigned I = 0, N = E->arg_size(); I != N; ++I)
-    E->setArg(I, Reader.ReadSubExpr());
-  E->setTypeBeginLoc(Reader.ReadSourceLocation(Record, Idx));
-  E->setTypeAsWritten(Reader.GetType(Record[Idx++]));
-  E->setLParenLoc(Reader.ReadSourceLocation(Record, Idx));
-  E->setRParenLoc(Reader.ReadSourceLocation(Record, Idx));
-}
-
-void PCHStmtReader::VisitOverloadExpr(OverloadExpr *E) {
-  VisitExpr(E);
-  
-  unsigned NumTemplateArgs = Record[Idx++];
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
-         "Read wrong record during creation ?");
-  if (E->hasExplicitTemplateArgs())
-    ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
-                                     NumTemplateArgs);
-
-  unsigned NumDecls = Record[Idx++];
-  UnresolvedSet<8> Decls;
-  for (unsigned i = 0; i != NumDecls; ++i) {
-    NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
-    AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
-    Decls.addDecl(D, AS);
-  }
-  E->initializeResults(*Reader.getContext(), Decls.begin(), Decls.end());
-
-  // FIXME: read whole DeclarationNameInfo.
-  E->setName(Reader.ReadDeclarationName(Record, Idx));
-  E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
-  E->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
-  E->setNameLoc(Reader.ReadSourceLocation(Record, Idx));
-}
-
-void PCHStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
-  VisitOverloadExpr(E);
-  E->setArrow(Record[Idx++]);
-  E->setHasUnresolvedUsing(Record[Idx++]);
-  E->setBase(Reader.ReadSubExpr());
-  E->setBaseType(Reader.GetType(Record[Idx++]));
-  E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx));
-}
-
-void PCHStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
-  VisitOverloadExpr(E);
-  E->setRequiresADL(Record[Idx++]);
-  E->setOverloaded(Record[Idx++]);
-  E->setNamingClass(cast_or_null<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
-void PCHStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
-  VisitExpr(E);
-  E->UTT = (UnaryTypeTrait)Record[Idx++];
-  SourceRange Range = Reader.ReadSourceRange(Record, Idx);
-  E->Loc = Range.getBegin();
-  E->RParen = Range.getEnd();
-  E->QueriedType = Reader.GetType(Record[Idx++]);
-}
-
-Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) {
-  switch (ReadingKind) {
-  case Read_Decl:
-  case Read_Type:
-    return ReadStmtFromStream(Cursor);
-  case Read_Stmt:
-    return ReadSubStmt();
-  }
-
-  llvm_unreachable("ReadingKind not set ?");
-  return 0;
-}
-
-Expr *PCHReader::ReadExpr(llvm::BitstreamCursor &Cursor) {
-  return cast_or_null<Expr>(ReadStmt(Cursor));
-}
-
-Expr *PCHReader::ReadSubExpr() {
-  return cast_or_null<Expr>(ReadSubStmt());
-}
-
-// Within the bitstream, expressions are stored in Reverse Polish
-// Notation, with each of the subexpressions preceding the
-// expression they are stored in. Subexpressions are stored from last to first.
-// To evaluate expressions, we continue reading expressions and placing them on
-// the stack, with expressions having operands removing those operands from the
-// stack. Evaluation terminates when we see a STMT_STOP record, and
-// the single remaining expression on the stack is our result.
-Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
-
-  ReadingKindTracker ReadingKind(Read_Stmt, *this);
-  
-#ifndef NDEBUG
-  unsigned PrevNumStmts = StmtStack.size();
-#endif
-
-  RecordData Record;
-  unsigned Idx;
-  PCHStmtReader Reader(*this, Cursor, Record, Idx);
-  Stmt::EmptyShell Empty;
-
-  while (true) {
-    unsigned Code = Cursor.ReadCode();
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (Cursor.ReadBlockEnd()) {
-        Error("error at end of block in PCH file");
-        return 0;
-      }
-      break;
-    }
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      // No known subblocks, always skip them.
-      Cursor.ReadSubBlockID();
-      if (Cursor.SkipBlock()) {
-        Error("malformed block record in PCH file");
-        return 0;
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      Cursor.ReadAbbrevRecord();
-      continue;
-    }
-
-    Stmt *S = 0;
-    Idx = 0;
-    Record.clear();
-    bool Finished = false;
-    switch ((pch::StmtCode)Cursor.ReadRecord(Code, Record)) {
-    case pch::STMT_STOP:
-      Finished = true;
-      break;
-
-    case pch::STMT_NULL_PTR:
-      S = 0;
-      break;
-
-    case pch::STMT_NULL:
-      S = new (Context) NullStmt(Empty);
-      break;
-
-    case pch::STMT_COMPOUND:
-      S = new (Context) CompoundStmt(Empty);
-      break;
-
-    case pch::STMT_CASE:
-      S = new (Context) CaseStmt(Empty);
-      break;
-
-    case pch::STMT_DEFAULT:
-      S = new (Context) DefaultStmt(Empty);
-      break;
-
-    case pch::STMT_LABEL:
-      S = new (Context) LabelStmt(Empty);
-      break;
-
-    case pch::STMT_IF:
-      S = new (Context) IfStmt(Empty);
-      break;
-
-    case pch::STMT_SWITCH:
-      S = new (Context) SwitchStmt(Empty);
-      break;
-
-    case pch::STMT_WHILE:
-      S = new (Context) WhileStmt(Empty);
-      break;
-
-    case pch::STMT_DO:
-      S = new (Context) DoStmt(Empty);
-      break;
-
-    case pch::STMT_FOR:
-      S = new (Context) ForStmt(Empty);
-      break;
-
-    case pch::STMT_GOTO:
-      S = new (Context) GotoStmt(Empty);
-      break;
-
-    case pch::STMT_INDIRECT_GOTO:
-      S = new (Context) IndirectGotoStmt(Empty);
-      break;
-
-    case pch::STMT_CONTINUE:
-      S = new (Context) ContinueStmt(Empty);
-      break;
-
-    case pch::STMT_BREAK:
-      S = new (Context) BreakStmt(Empty);
-      break;
-
-    case pch::STMT_RETURN:
-      S = new (Context) ReturnStmt(Empty);
-      break;
-
-    case pch::STMT_DECL:
-      S = new (Context) DeclStmt(Empty);
-      break;
-
-    case pch::STMT_ASM:
-      S = new (Context) AsmStmt(Empty);
-      break;
-
-    case pch::EXPR_PREDEFINED:
-      S = new (Context) PredefinedExpr(Empty);
-      break;
-
-    case pch::EXPR_DECL_REF:
-      S = DeclRefExpr::CreateEmpty(*Context,
-                         /*HasQualifier=*/Record[PCHStmtReader::NumExprFields],
-                  /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields + 1]);
-      break;
-
-    case pch::EXPR_INTEGER_LITERAL:
-      S = new (Context) IntegerLiteral(Empty);
-      break;
-
-    case pch::EXPR_FLOATING_LITERAL:
-      S = new (Context) FloatingLiteral(Empty);
-      break;
-
-    case pch::EXPR_IMAGINARY_LITERAL:
-      S = new (Context) ImaginaryLiteral(Empty);
-      break;
-
-    case pch::EXPR_STRING_LITERAL:
-      S = StringLiteral::CreateEmpty(*Context,
-                                     Record[PCHStmtReader::NumExprFields + 1]);
-      break;
-
-    case pch::EXPR_CHARACTER_LITERAL:
-      S = new (Context) CharacterLiteral(Empty);
-      break;
-
-    case pch::EXPR_PAREN:
-      S = new (Context) ParenExpr(Empty);
-      break;
-
-    case pch::EXPR_PAREN_LIST:
-      S = new (Context) ParenListExpr(Empty);
-      break;
-
-    case pch::EXPR_UNARY_OPERATOR:
-      S = new (Context) UnaryOperator(Empty);
-      break;
-
-    case pch::EXPR_OFFSETOF:
-      S = OffsetOfExpr::CreateEmpty(*Context, 
-                                    Record[PCHStmtReader::NumExprFields],
-                                    Record[PCHStmtReader::NumExprFields + 1]);
-      break;
-        
-    case pch::EXPR_SIZEOF_ALIGN_OF:
-      S = new (Context) SizeOfAlignOfExpr(Empty);
-      break;
-
-    case pch::EXPR_ARRAY_SUBSCRIPT:
-      S = new (Context) ArraySubscriptExpr(Empty);
-      break;
-
-    case pch::EXPR_CALL:
-      S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty);
-      break;
-
-    case pch::EXPR_MEMBER: {
-      // We load everything here and fully initialize it at creation.
-      // That way we can use MemberExpr::Create and don't have to duplicate its
-      // logic with a MemberExpr::CreateEmpty.
-
-      assert(Idx == 0);
-      NestedNameSpecifier *NNS = 0;
-      SourceRange QualifierRange;
-      if (Record[Idx++]) { // HasQualifier.
-        NNS = ReadNestedNameSpecifier(Record, Idx);
-        QualifierRange = ReadSourceRange(Record, Idx);
-      }
-
-      TemplateArgumentListInfo ArgInfo;
-      unsigned NumTemplateArgs = Record[Idx++];
-      if (NumTemplateArgs) {
-        ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx));
-        ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx));
-        for (unsigned i = 0; i != NumTemplateArgs; ++i)
-          ArgInfo.addArgument(ReadTemplateArgumentLoc(Cursor, Record, Idx));
-      }
-      
-      NamedDecl *FoundD = cast_or_null<NamedDecl>(GetDecl(Record[Idx++]));
-      AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
-      DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS);
-
-      QualType T = GetType(Record[Idx++]);
-      Expr *Base = ReadSubExpr();
-      ValueDecl *MemberD = cast<ValueDecl>(GetDecl(Record[Idx++]));
-      // FIXME: read DeclarationNameLoc.
-      SourceLocation MemberLoc = ReadSourceLocation(Record, Idx);
-      DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc);
-      bool IsArrow = Record[Idx++];
-
-      S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange,
-                             MemberD, FoundDecl, MemberNameInfo,
-                             NumTemplateArgs ? &ArgInfo : 0, T);
-      break;
-    }
-
-    case pch::EXPR_BINARY_OPERATOR:
-      S = new (Context) BinaryOperator(Empty);
-      break;
-
-    case pch::EXPR_COMPOUND_ASSIGN_OPERATOR:
-      S = new (Context) CompoundAssignOperator(Empty);
-      break;
-
-    case pch::EXPR_CONDITIONAL_OPERATOR:
-      S = new (Context) ConditionalOperator(Empty);
-      break;
-
-    case pch::EXPR_IMPLICIT_CAST:
-      S = ImplicitCastExpr::CreateEmpty(*Context,
-                       /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
-      break;
-
-    case pch::EXPR_CSTYLE_CAST:
-      S = CStyleCastExpr::CreateEmpty(*Context,
-                       /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
-      break;
-
-    case pch::EXPR_COMPOUND_LITERAL:
-      S = new (Context) CompoundLiteralExpr(Empty);
-      break;
-
-    case pch::EXPR_EXT_VECTOR_ELEMENT:
-      S = new (Context) ExtVectorElementExpr(Empty);
-      break;
-
-    case pch::EXPR_INIT_LIST:
-      S = new (Context) InitListExpr(*getContext(), Empty);
-      break;
-
-    case pch::EXPR_DESIGNATED_INIT:
-      S = DesignatedInitExpr::CreateEmpty(*Context,
-                                     Record[PCHStmtReader::NumExprFields] - 1);
-
-      break;
-
-    case pch::EXPR_IMPLICIT_VALUE_INIT:
-      S = new (Context) ImplicitValueInitExpr(Empty);
-      break;
-
-    case pch::EXPR_VA_ARG:
-      S = new (Context) VAArgExpr(Empty);
-      break;
-
-    case pch::EXPR_ADDR_LABEL:
-      S = new (Context) AddrLabelExpr(Empty);
-      break;
-
-    case pch::EXPR_STMT:
-      S = new (Context) StmtExpr(Empty);
-      break;
-
-    case pch::EXPR_TYPES_COMPATIBLE:
-      S = new (Context) TypesCompatibleExpr(Empty);
-      break;
-
-    case pch::EXPR_CHOOSE:
-      S = new (Context) ChooseExpr(Empty);
-      break;
-
-    case pch::EXPR_GNU_NULL:
-      S = new (Context) GNUNullExpr(Empty);
-      break;
-
-    case pch::EXPR_SHUFFLE_VECTOR:
-      S = new (Context) ShuffleVectorExpr(Empty);
-      break;
-
-    case pch::EXPR_BLOCK:
-      S = new (Context) BlockExpr(Empty);
-      break;
-
-    case pch::EXPR_BLOCK_DECL_REF:
-      S = new (Context) BlockDeclRefExpr(Empty);
-      break;
-
-    case pch::EXPR_OBJC_STRING_LITERAL:
-      S = new (Context) ObjCStringLiteral(Empty);
-      break;
-    case pch::EXPR_OBJC_ENCODE:
-      S = new (Context) ObjCEncodeExpr(Empty);
-      break;
-    case pch::EXPR_OBJC_SELECTOR_EXPR:
-      S = new (Context) ObjCSelectorExpr(Empty);
-      break;
-    case pch::EXPR_OBJC_PROTOCOL_EXPR:
-      S = new (Context) ObjCProtocolExpr(Empty);
-      break;
-    case pch::EXPR_OBJC_IVAR_REF_EXPR:
-      S = new (Context) ObjCIvarRefExpr(Empty);
-      break;
-    case pch::EXPR_OBJC_PROPERTY_REF_EXPR:
-      S = new (Context) ObjCPropertyRefExpr(Empty);
-      break;
-    case pch::EXPR_OBJC_KVC_REF_EXPR:
-      S = new (Context) ObjCImplicitSetterGetterRefExpr(Empty);
-      break;
-    case pch::EXPR_OBJC_MESSAGE_EXPR:
-      S = ObjCMessageExpr::CreateEmpty(*Context,
-                                     Record[PCHStmtReader::NumExprFields]);
-      break;
-    case pch::EXPR_OBJC_SUPER_EXPR:
-      S = new (Context) ObjCSuperExpr(Empty);
-      break;
-    case pch::EXPR_OBJC_ISA:
-      S = new (Context) ObjCIsaExpr(Empty);
-      break;
-    case pch::STMT_OBJC_FOR_COLLECTION:
-      S = new (Context) ObjCForCollectionStmt(Empty);
-      break;
-    case pch::STMT_OBJC_CATCH:
-      S = new (Context) ObjCAtCatchStmt(Empty);
-      break;
-    case pch::STMT_OBJC_FINALLY:
-      S = new (Context) ObjCAtFinallyStmt(Empty);
-      break;
-    case pch::STMT_OBJC_AT_TRY:
-      S = ObjCAtTryStmt::CreateEmpty(*Context, 
-                                     Record[PCHStmtReader::NumStmtFields],
-                                     Record[PCHStmtReader::NumStmtFields + 1]);
-      break;
-    case pch::STMT_OBJC_AT_SYNCHRONIZED:
-      S = new (Context) ObjCAtSynchronizedStmt(Empty);
-      break;
-    case pch::STMT_OBJC_AT_THROW:
-      S = new (Context) ObjCAtThrowStmt(Empty);
-      break;
-
-    case pch::STMT_CXX_CATCH:
-      S = new (Context) CXXCatchStmt(Empty);
-      break;
-
-    case pch::STMT_CXX_TRY:
-      S = CXXTryStmt::Create(*Context, Empty,
-             /*NumHandlers=*/Record[PCHStmtReader::NumStmtFields]);
-      break;
-
-    case pch::EXPR_CXX_OPERATOR_CALL:
-      S = new (Context) CXXOperatorCallExpr(*Context, Empty);
-      break;
-
-    case pch::EXPR_CXX_MEMBER_CALL:
-      S = new (Context) CXXMemberCallExpr(*Context, Empty);
-      break;
-        
-    case pch::EXPR_CXX_CONSTRUCT:
-      S = new (Context) CXXConstructExpr(Empty);
-      break;
-      
-    case pch::EXPR_CXX_TEMPORARY_OBJECT:
-      S = new (Context) CXXTemporaryObjectExpr(Empty);
-      break;
-
-    case pch::EXPR_CXX_STATIC_CAST:
-      S = CXXStaticCastExpr::CreateEmpty(*Context,
-                       /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
-      break;
-
-    case pch::EXPR_CXX_DYNAMIC_CAST:
-      S = CXXDynamicCastExpr::CreateEmpty(*Context,
-                       /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
-      break;
-
-    case pch::EXPR_CXX_REINTERPRET_CAST:
-      S = CXXReinterpretCastExpr::CreateEmpty(*Context,
-                       /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
-      break;
-
-    case pch::EXPR_CXX_CONST_CAST:
-      S = CXXConstCastExpr::CreateEmpty(*Context);
-      break;
-
-    case pch::EXPR_CXX_FUNCTIONAL_CAST:
-      S = CXXFunctionalCastExpr::CreateEmpty(*Context,
-                       /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
-      break;
-
-    case pch::EXPR_CXX_BOOL_LITERAL:
-      S = new (Context) CXXBoolLiteralExpr(Empty);
-      break;
-
-    case pch::EXPR_CXX_NULL_PTR_LITERAL:
-      S = new (Context) CXXNullPtrLiteralExpr(Empty);
-      break;
-    case pch::EXPR_CXX_TYPEID_EXPR:
-      S = new (Context) CXXTypeidExpr(Empty, true);
-      break;
-    case pch::EXPR_CXX_TYPEID_TYPE:
-      S = new (Context) CXXTypeidExpr(Empty, false);
-      break;
-    case pch::EXPR_CXX_THIS:
-      S = new (Context) CXXThisExpr(Empty);
-      break;
-    case pch::EXPR_CXX_THROW:
-      S = new (Context) CXXThrowExpr(Empty);
-      break;
-    case pch::EXPR_CXX_DEFAULT_ARG: {
-      bool HasOtherExprStored = Record[PCHStmtReader::NumExprFields];
-      if (HasOtherExprStored) {
-        Expr *SubExpr = ReadSubExpr();
-        S = CXXDefaultArgExpr::Create(*Context, SourceLocation(), 0, SubExpr);
-      } else
-        S = new (Context) CXXDefaultArgExpr(Empty);
-      break;
-    }
-    case pch::EXPR_CXX_BIND_TEMPORARY:
-      S = new (Context) CXXBindTemporaryExpr(Empty);
-      break;
-    case pch::EXPR_CXX_BIND_REFERENCE:
-      S = new (Context) CXXBindReferenceExpr(Empty);
-      break;
-
-    case pch::EXPR_CXX_SCALAR_VALUE_INIT:
-      S = new (Context) CXXScalarValueInitExpr(Empty);
-      break;
-    case pch::EXPR_CXX_NEW:
-      S = new (Context) CXXNewExpr(Empty);
-      break;
-    case pch::EXPR_CXX_DELETE:
-      S = new (Context) CXXDeleteExpr(Empty);
-      break;
-    case pch::EXPR_CXX_PSEUDO_DESTRUCTOR:
-      S = new (Context) CXXPseudoDestructorExpr(Empty);
-      break;
-        
-    case pch::EXPR_CXX_EXPR_WITH_TEMPORARIES:
-      S = new (Context) CXXExprWithTemporaries(Empty);
-      break;
-      
-    case pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
-      S = CXXDependentScopeMemberExpr::CreateEmpty(*Context,
-                      /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]);
-      break;
-      
-    case pch::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:
-      S = DependentScopeDeclRefExpr::CreateEmpty(*Context,
-                      /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]);
-      break;
-      
-    case pch::EXPR_CXX_UNRESOLVED_CONSTRUCT:
-      S = CXXUnresolvedConstructExpr::CreateEmpty(*Context,
-                              /*NumArgs=*/Record[PCHStmtReader::NumExprFields]);
-      break;
-      
-    case pch::EXPR_CXX_UNRESOLVED_MEMBER:
-      S = UnresolvedMemberExpr::CreateEmpty(*Context,
-                      /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]);
-      break;
-      
-    case pch::EXPR_CXX_UNRESOLVED_LOOKUP:
-      S = UnresolvedLookupExpr::CreateEmpty(*Context,
-                      /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]);
-      break;
-      
-    case pch::EXPR_CXX_UNARY_TYPE_TRAIT:
-      S = new (Context) UnaryTypeTraitExpr(Empty);
-      break;
-    }
-    
-    // We hit a STMT_STOP, so we're done with this expression.
-    if (Finished)
-      break;
-
-    ++NumStatementsRead;
-
-    if (S)
-      Reader.Visit(S);
-
-    assert(Idx == Record.size() && "Invalid deserialization of statement");
-    StmtStack.push_back(S);
-  }
-
-#ifndef NDEBUG
-  assert(StmtStack.size() > PrevNumStmts && "Read too many sub stmts!");
-  assert(StmtStack.size() == PrevNumStmts + 1 && "Extra expressions on stack!");
-#endif
-
-  return StmtStack.pop_back_val();
-}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
deleted file mode 100644
index 76fd552..0000000
--- a/lib/Frontend/PCHWriter.cpp
+++ /dev/null
@@ -1,3094 +0,0 @@
-//===--- PCHWriter.cpp - Precompiled Headers Writer -----------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file defines the PCHWriter class, which writes a precompiled header.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/PCHWriter.h"
-#include "clang/Sema/Sema.h"
-#include "clang/Sema/IdentifierResolver.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclContextInternals.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/TypeLocVisitor.h"
-#include "clang/Frontend/PCHReader.h"
-#include "clang/Lex/MacroInfo.h"
-#include "clang/Lex/PreprocessingRecord.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/OnDiskHashTable.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/SourceManagerInternals.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Version.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Bitcode/BitstreamWriter.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/System/Path.h"
-#include <cstdio>
-using namespace clang;
-
-template <typename T, typename Allocator>
-T *data(std::vector<T, Allocator> &v) {
-  return v.empty() ? 0 : &v.front();
-}
-template <typename T, typename Allocator>
-const T *data(const std::vector<T, Allocator> &v) {
-  return v.empty() ? 0 : &v.front();
-}
-
-//===----------------------------------------------------------------------===//
-// Type serialization
-//===----------------------------------------------------------------------===//
-
-namespace {
-  class PCHTypeWriter {
-    PCHWriter &Writer;
-    PCHWriter::RecordData &Record;
-
-  public:
-    /// \brief Type code that corresponds to the record generated.
-    pch::TypeCode Code;
-
-    PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
-      : Writer(Writer), Record(Record), Code(pch::TYPE_EXT_QUAL) { }
-
-    void VisitArrayType(const ArrayType *T);
-    void VisitFunctionType(const FunctionType *T);
-    void VisitTagType(const TagType *T);
-
-#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
-#define ABSTRACT_TYPE(Class, Base)
-#include "clang/AST/TypeNodes.def"
-  };
-}
-
-void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
-  assert(false && "Built-in types are never serialized");
-}
-
-void PCHTypeWriter::VisitComplexType(const ComplexType *T) {
-  Writer.AddTypeRef(T->getElementType(), Record);
-  Code = pch::TYPE_COMPLEX;
-}
-
-void PCHTypeWriter::VisitPointerType(const PointerType *T) {
-  Writer.AddTypeRef(T->getPointeeType(), Record);
-  Code = pch::TYPE_POINTER;
-}
-
-void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
-  Writer.AddTypeRef(T->getPointeeType(), Record);
-  Code = pch::TYPE_BLOCK_POINTER;
-}
-
-void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
-  Writer.AddTypeRef(T->getPointeeType(), Record);
-  Code = pch::TYPE_LVALUE_REFERENCE;
-}
-
-void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
-  Writer.AddTypeRef(T->getPointeeType(), Record);
-  Code = pch::TYPE_RVALUE_REFERENCE;
-}
-
-void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
-  Writer.AddTypeRef(T->getPointeeType(), Record);
-  Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
-  Code = pch::TYPE_MEMBER_POINTER;
-}
-
-void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
-  Writer.AddTypeRef(T->getElementType(), Record);
-  Record.push_back(T->getSizeModifier()); // FIXME: stable values
-  Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values
-}
-
-void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
-  VisitArrayType(T);
-  Writer.AddAPInt(T->getSize(), Record);
-  Code = pch::TYPE_CONSTANT_ARRAY;
-}
-
-void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
-  VisitArrayType(T);
-  Code = pch::TYPE_INCOMPLETE_ARRAY;
-}
-
-void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
-  VisitArrayType(T);
-  Writer.AddSourceLocation(T->getLBracketLoc(), Record);
-  Writer.AddSourceLocation(T->getRBracketLoc(), Record);
-  Writer.AddStmt(T->getSizeExpr());
-  Code = pch::TYPE_VARIABLE_ARRAY;
-}
-
-void PCHTypeWriter::VisitVectorType(const VectorType *T) {
-  Writer.AddTypeRef(T->getElementType(), Record);
-  Record.push_back(T->getNumElements());
-  Record.push_back(T->getAltiVecSpecific());
-  Code = pch::TYPE_VECTOR;
-}
-
-void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
-  VisitVectorType(T);
-  Code = pch::TYPE_EXT_VECTOR;
-}
-
-void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
-  Writer.AddTypeRef(T->getResultType(), Record);
-  FunctionType::ExtInfo C = T->getExtInfo();
-  Record.push_back(C.getNoReturn());
-  Record.push_back(C.getRegParm());
-  // FIXME: need to stabilize encoding of calling convention...
-  Record.push_back(C.getCC());
-}
-
-void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
-  VisitFunctionType(T);
-  Code = pch::TYPE_FUNCTION_NO_PROTO;
-}
-
-void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
-  VisitFunctionType(T);
-  Record.push_back(T->getNumArgs());
-  for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
-    Writer.AddTypeRef(T->getArgType(I), Record);
-  Record.push_back(T->isVariadic());
-  Record.push_back(T->getTypeQuals());
-  Record.push_back(T->hasExceptionSpec());
-  Record.push_back(T->hasAnyExceptionSpec());
-  Record.push_back(T->getNumExceptions());
-  for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
-    Writer.AddTypeRef(T->getExceptionType(I), Record);
-  Code = pch::TYPE_FUNCTION_PROTO;
-}
-
-void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
-  Writer.AddDeclRef(T->getDecl(), Record);
-  Code = pch::TYPE_UNRESOLVED_USING;
-}
-
-void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
-  Writer.AddDeclRef(T->getDecl(), Record);
-  assert(!T->isCanonicalUnqualified() && "Invalid typedef ?");
-  Writer.AddTypeRef(T->getCanonicalTypeInternal(), Record);
-  Code = pch::TYPE_TYPEDEF;
-}
-
-void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
-  Writer.AddStmt(T->getUnderlyingExpr());
-  Code = pch::TYPE_TYPEOF_EXPR;
-}
-
-void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) {
-  Writer.AddTypeRef(T->getUnderlyingType(), Record);
-  Code = pch::TYPE_TYPEOF;
-}
-
-void PCHTypeWriter::VisitDecltypeType(const DecltypeType *T) {
-  Writer.AddStmt(T->getUnderlyingExpr());
-  Code = pch::TYPE_DECLTYPE;
-}
-
-void PCHTypeWriter::VisitTagType(const TagType *T) {
-  Record.push_back(T->isDependentType());
-  Writer.AddDeclRef(T->getDecl(), Record);
-  assert(!T->isBeingDefined() &&
-         "Cannot serialize in the middle of a type definition");
-}
-
-void PCHTypeWriter::VisitRecordType(const RecordType *T) {
-  VisitTagType(T);
-  Code = pch::TYPE_RECORD;
-}
-
-void PCHTypeWriter::VisitEnumType(const EnumType *T) {
-  VisitTagType(T);
-  Code = pch::TYPE_ENUM;
-}
-
-void
-PCHTypeWriter::VisitSubstTemplateTypeParmType(
-                                        const SubstTemplateTypeParmType *T) {
-  Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
-  Writer.AddTypeRef(T->getReplacementType(), Record);
-  Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM;
-}
-
-void
-PCHTypeWriter::VisitTemplateSpecializationType(
-                                       const TemplateSpecializationType *T) {
-  Record.push_back(T->isDependentType());
-  Writer.AddTemplateName(T->getTemplateName(), Record);
-  Record.push_back(T->getNumArgs());
-  for (TemplateSpecializationType::iterator ArgI = T->begin(), ArgE = T->end();
-         ArgI != ArgE; ++ArgI)
-    Writer.AddTemplateArgument(*ArgI, Record);
-  Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType()
-                                                : T->getCanonicalTypeInternal(),
-                    Record);
-  Code = pch::TYPE_TEMPLATE_SPECIALIZATION;
-}
-
-void
-PCHTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
-  VisitArrayType(T);
-  Writer.AddStmt(T->getSizeExpr());
-  Writer.AddSourceRange(T->getBracketsRange(), Record);
-  Code = pch::TYPE_DEPENDENT_SIZED_ARRAY;
-}
-
-void
-PCHTypeWriter::VisitDependentSizedExtVectorType(
-                                        const DependentSizedExtVectorType *T) {
-  // FIXME: Serialize this type (C++ only)
-  assert(false && "Cannot serialize dependent sized extended vector types");
-}
-
-void
-PCHTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
-  Record.push_back(T->getDepth());
-  Record.push_back(T->getIndex());
-  Record.push_back(T->isParameterPack());
-  Writer.AddIdentifierRef(T->getName(), Record);
-  Code = pch::TYPE_TEMPLATE_TYPE_PARM;
-}
-
-void
-PCHTypeWriter::VisitDependentNameType(const DependentNameType *T) {
-  Record.push_back(T->getKeyword());
-  Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
-  Writer.AddIdentifierRef(T->getIdentifier(), Record);
-  Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType()
-                                                : T->getCanonicalTypeInternal(),
-                    Record);
-  Code = pch::TYPE_DEPENDENT_NAME;
-}
-
-void
-PCHTypeWriter::VisitDependentTemplateSpecializationType(
-                                const DependentTemplateSpecializationType *T) {
-  Record.push_back(T->getKeyword());
-  Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
-  Writer.AddIdentifierRef(T->getIdentifier(), Record);
-  Record.push_back(T->getNumArgs());
-  for (DependentTemplateSpecializationType::iterator
-         I = T->begin(), E = T->end(); I != E; ++I)
-    Writer.AddTemplateArgument(*I, Record);
-  Code = pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION;
-}
-
-void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
-  Record.push_back(T->getKeyword());
-  Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
-  Writer.AddTypeRef(T->getNamedType(), Record);
-  Code = pch::TYPE_ELABORATED;
-}
-
-void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
-  Writer.AddDeclRef(T->getDecl(), Record);
-  Writer.AddTypeRef(T->getInjectedSpecializationType(), Record);
-  Code = pch::TYPE_INJECTED_CLASS_NAME;
-}
-
-void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
-  Writer.AddDeclRef(T->getDecl(), Record);
-  Code = pch::TYPE_OBJC_INTERFACE;
-}
-
-void PCHTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
-  Writer.AddTypeRef(T->getBaseType(), Record);
-  Record.push_back(T->getNumProtocols());
-  for (ObjCObjectType::qual_iterator I = T->qual_begin(),
-       E = T->qual_end(); I != E; ++I)
-    Writer.AddDeclRef(*I, Record);
-  Code = pch::TYPE_OBJC_OBJECT;
-}
-
-void
-PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
-  Writer.AddTypeRef(T->getPointeeType(), Record);
-  Code = pch::TYPE_OBJC_OBJECT_POINTER;
-}
-
-namespace {
-
-class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
-  PCHWriter &Writer;
-  PCHWriter::RecordData &Record;
-
-public:
-  TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
-    : Writer(Writer), Record(Record) { }
-
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
-    void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
-#include "clang/AST/TypeLocNodes.def"
-
-  void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);
-  void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
-};
-
-}
-
-void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
-  // nothing to do
-}
-void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getBuiltinLoc(), Record);
-  if (TL.needsExtraLocalData()) {
-    Record.push_back(TL.getWrittenTypeSpec());
-    Record.push_back(TL.getWrittenSignSpec());
-    Record.push_back(TL.getWrittenWidthSpec());
-    Record.push_back(TL.hasModeAttr());
-  }
-}
-void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getStarLoc(), Record);
-}
-void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getCaretLoc(), Record);
-}
-void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getAmpLoc(), Record);
-}
-void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record);
-}
-void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getStarLoc(), Record);
-}
-void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getLBracketLoc(), Record);
-  Writer.AddSourceLocation(TL.getRBracketLoc(), Record);
-  Record.push_back(TL.getSizeExpr() ? 1 : 0);
-  if (TL.getSizeExpr())
-    Writer.AddStmt(TL.getSizeExpr());
-}
-void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
-                                            DependentSizedArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
-                                        DependentSizedExtVectorTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
-  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
-  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
-    Writer.AddDeclRef(TL.getArg(i), Record);
-}
-void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
-  VisitFunctionTypeLoc(TL);
-}
-void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
-  VisitFunctionTypeLoc(TL);
-}
-void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
-  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
-  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
-}
-void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
-  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
-  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
-  Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record);
-}
-void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
-                                            SubstTemplateTypeParmTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
-                                           TemplateSpecializationTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record);
-  Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
-  Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
-  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
-    Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(),
-                                      TL.getArgLoc(i).getLocInfo(), Record);
-}
-void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
-  Writer.AddSourceRange(TL.getQualifierRange(), Record);
-}
-void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
-  Writer.AddSourceRange(TL.getQualifierRange(), Record);
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc(
-       DependentTemplateSpecializationTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
-  Writer.AddSourceRange(TL.getQualifierRange(), Record);
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-  Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
-  Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
-  for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
-    Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(),
-                                      TL.getArgLoc(I).getLocInfo(), Record);
-}
-void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
-  Record.push_back(TL.hasBaseTypeAsWritten());
-  Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
-  Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
-  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
-    Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
-}
-void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getStarLoc(), Record);
-}
-
-//===----------------------------------------------------------------------===//
-// PCHWriter Implementation
-//===----------------------------------------------------------------------===//
-
-static void EmitBlockID(unsigned ID, const char *Name,
-                        llvm::BitstreamWriter &Stream,
-                        PCHWriter::RecordData &Record) {
-  Record.clear();
-  Record.push_back(ID);
-  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
-
-  // Emit the block name if present.
-  if (Name == 0 || Name[0] == 0) return;
-  Record.clear();
-  while (*Name)
-    Record.push_back(*Name++);
-  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
-}
-
-static void EmitRecordID(unsigned ID, const char *Name,
-                         llvm::BitstreamWriter &Stream,
-                         PCHWriter::RecordData &Record) {
-  Record.clear();
-  Record.push_back(ID);
-  while (*Name)
-    Record.push_back(*Name++);
-  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
-}
-
-static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
-                          PCHWriter::RecordData &Record) {
-#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record)
-  RECORD(STMT_STOP);
-  RECORD(STMT_NULL_PTR);
-  RECORD(STMT_NULL);
-  RECORD(STMT_COMPOUND);
-  RECORD(STMT_CASE);
-  RECORD(STMT_DEFAULT);
-  RECORD(STMT_LABEL);
-  RECORD(STMT_IF);
-  RECORD(STMT_SWITCH);
-  RECORD(STMT_WHILE);
-  RECORD(STMT_DO);
-  RECORD(STMT_FOR);
-  RECORD(STMT_GOTO);
-  RECORD(STMT_INDIRECT_GOTO);
-  RECORD(STMT_CONTINUE);
-  RECORD(STMT_BREAK);
-  RECORD(STMT_RETURN);
-  RECORD(STMT_DECL);
-  RECORD(STMT_ASM);
-  RECORD(EXPR_PREDEFINED);
-  RECORD(EXPR_DECL_REF);
-  RECORD(EXPR_INTEGER_LITERAL);
-  RECORD(EXPR_FLOATING_LITERAL);
-  RECORD(EXPR_IMAGINARY_LITERAL);
-  RECORD(EXPR_STRING_LITERAL);
-  RECORD(EXPR_CHARACTER_LITERAL);
-  RECORD(EXPR_PAREN);
-  RECORD(EXPR_UNARY_OPERATOR);
-  RECORD(EXPR_SIZEOF_ALIGN_OF);
-  RECORD(EXPR_ARRAY_SUBSCRIPT);
-  RECORD(EXPR_CALL);
-  RECORD(EXPR_MEMBER);
-  RECORD(EXPR_BINARY_OPERATOR);
-  RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR);
-  RECORD(EXPR_CONDITIONAL_OPERATOR);
-  RECORD(EXPR_IMPLICIT_CAST);
-  RECORD(EXPR_CSTYLE_CAST);
-  RECORD(EXPR_COMPOUND_LITERAL);
-  RECORD(EXPR_EXT_VECTOR_ELEMENT);
-  RECORD(EXPR_INIT_LIST);
-  RECORD(EXPR_DESIGNATED_INIT);
-  RECORD(EXPR_IMPLICIT_VALUE_INIT);
-  RECORD(EXPR_VA_ARG);
-  RECORD(EXPR_ADDR_LABEL);
-  RECORD(EXPR_STMT);
-  RECORD(EXPR_TYPES_COMPATIBLE);
-  RECORD(EXPR_CHOOSE);
-  RECORD(EXPR_GNU_NULL);
-  RECORD(EXPR_SHUFFLE_VECTOR);
-  RECORD(EXPR_BLOCK);
-  RECORD(EXPR_BLOCK_DECL_REF);
-  RECORD(EXPR_OBJC_STRING_LITERAL);
-  RECORD(EXPR_OBJC_ENCODE);
-  RECORD(EXPR_OBJC_SELECTOR_EXPR);
-  RECORD(EXPR_OBJC_PROTOCOL_EXPR);
-  RECORD(EXPR_OBJC_IVAR_REF_EXPR);
-  RECORD(EXPR_OBJC_PROPERTY_REF_EXPR);
-  RECORD(EXPR_OBJC_KVC_REF_EXPR);
-  RECORD(EXPR_OBJC_MESSAGE_EXPR);
-  RECORD(EXPR_OBJC_SUPER_EXPR);
-  RECORD(STMT_OBJC_FOR_COLLECTION);
-  RECORD(STMT_OBJC_CATCH);
-  RECORD(STMT_OBJC_FINALLY);
-  RECORD(STMT_OBJC_AT_TRY);
-  RECORD(STMT_OBJC_AT_SYNCHRONIZED);
-  RECORD(STMT_OBJC_AT_THROW);
-  RECORD(EXPR_CXX_OPERATOR_CALL);
-  RECORD(EXPR_CXX_CONSTRUCT);
-  RECORD(EXPR_CXX_STATIC_CAST);
-  RECORD(EXPR_CXX_DYNAMIC_CAST);
-  RECORD(EXPR_CXX_REINTERPRET_CAST);
-  RECORD(EXPR_CXX_CONST_CAST);
-  RECORD(EXPR_CXX_FUNCTIONAL_CAST);
-  RECORD(EXPR_CXX_BOOL_LITERAL);
-  RECORD(EXPR_CXX_NULL_PTR_LITERAL);
-#undef RECORD
-}
-
-void PCHWriter::WriteBlockInfoBlock() {
-  RecordData Record;
-  Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3);
-
-#define BLOCK(X) EmitBlockID(pch::X ## _ID, #X, Stream, Record)
-#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record)
-
-  // PCH Top-Level Block.
-  BLOCK(PCH_BLOCK);
-  RECORD(ORIGINAL_FILE_NAME);
-  RECORD(TYPE_OFFSET);
-  RECORD(DECL_OFFSET);
-  RECORD(LANGUAGE_OPTIONS);
-  RECORD(METADATA);
-  RECORD(IDENTIFIER_OFFSET);
-  RECORD(IDENTIFIER_TABLE);
-  RECORD(EXTERNAL_DEFINITIONS);
-  RECORD(SPECIAL_TYPES);
-  RECORD(STATISTICS);
-  RECORD(TENTATIVE_DEFINITIONS);
-  RECORD(UNUSED_FILESCOPED_DECLS);
-  RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS);
-  RECORD(SELECTOR_OFFSETS);
-  RECORD(METHOD_POOL);
-  RECORD(PP_COUNTER_VALUE);
-  RECORD(SOURCE_LOCATION_OFFSETS);
-  RECORD(SOURCE_LOCATION_PRELOADS);
-  RECORD(STAT_CACHE);
-  RECORD(EXT_VECTOR_DECLS);
-  RECORD(VERSION_CONTROL_BRANCH_REVISION);
-  RECORD(MACRO_DEFINITION_OFFSETS);
-  RECORD(CHAINED_METADATA);
-  RECORD(REFERENCED_SELECTOR_POOL);
-  
-  // SourceManager Block.
-  BLOCK(SOURCE_MANAGER_BLOCK);
-  RECORD(SM_SLOC_FILE_ENTRY);
-  RECORD(SM_SLOC_BUFFER_ENTRY);
-  RECORD(SM_SLOC_BUFFER_BLOB);
-  RECORD(SM_SLOC_INSTANTIATION_ENTRY);
-  RECORD(SM_LINE_TABLE);
-
-  // Preprocessor Block.
-  BLOCK(PREPROCESSOR_BLOCK);
-  RECORD(PP_MACRO_OBJECT_LIKE);
-  RECORD(PP_MACRO_FUNCTION_LIKE);
-  RECORD(PP_TOKEN);
-  RECORD(PP_MACRO_INSTANTIATION);
-  RECORD(PP_MACRO_DEFINITION);
-  
-  // Decls and Types block.
-  BLOCK(DECLTYPES_BLOCK);
-  RECORD(TYPE_EXT_QUAL);
-  RECORD(TYPE_COMPLEX);
-  RECORD(TYPE_POINTER);
-  RECORD(TYPE_BLOCK_POINTER);
-  RECORD(TYPE_LVALUE_REFERENCE);
-  RECORD(TYPE_RVALUE_REFERENCE);
-  RECORD(TYPE_MEMBER_POINTER);
-  RECORD(TYPE_CONSTANT_ARRAY);
-  RECORD(TYPE_INCOMPLETE_ARRAY);
-  RECORD(TYPE_VARIABLE_ARRAY);
-  RECORD(TYPE_VECTOR);
-  RECORD(TYPE_EXT_VECTOR);
-  RECORD(TYPE_FUNCTION_PROTO);
-  RECORD(TYPE_FUNCTION_NO_PROTO);
-  RECORD(TYPE_TYPEDEF);
-  RECORD(TYPE_TYPEOF_EXPR);
-  RECORD(TYPE_TYPEOF);
-  RECORD(TYPE_RECORD);
-  RECORD(TYPE_ENUM);
-  RECORD(TYPE_OBJC_INTERFACE);
-  RECORD(TYPE_OBJC_OBJECT);
-  RECORD(TYPE_OBJC_OBJECT_POINTER);
-  RECORD(DECL_ATTR);
-  RECORD(DECL_TRANSLATION_UNIT);
-  RECORD(DECL_TYPEDEF);
-  RECORD(DECL_ENUM);
-  RECORD(DECL_RECORD);
-  RECORD(DECL_ENUM_CONSTANT);
-  RECORD(DECL_FUNCTION);
-  RECORD(DECL_OBJC_METHOD);
-  RECORD(DECL_OBJC_INTERFACE);
-  RECORD(DECL_OBJC_PROTOCOL);
-  RECORD(DECL_OBJC_IVAR);
-  RECORD(DECL_OBJC_AT_DEFS_FIELD);
-  RECORD(DECL_OBJC_CLASS);
-  RECORD(DECL_OBJC_FORWARD_PROTOCOL);
-  RECORD(DECL_OBJC_CATEGORY);
-  RECORD(DECL_OBJC_CATEGORY_IMPL);
-  RECORD(DECL_OBJC_IMPLEMENTATION);
-  RECORD(DECL_OBJC_COMPATIBLE_ALIAS);
-  RECORD(DECL_OBJC_PROPERTY);
-  RECORD(DECL_OBJC_PROPERTY_IMPL);
-  RECORD(DECL_FIELD);
-  RECORD(DECL_VAR);
-  RECORD(DECL_IMPLICIT_PARAM);
-  RECORD(DECL_PARM_VAR);
-  RECORD(DECL_FILE_SCOPE_ASM);
-  RECORD(DECL_BLOCK);
-  RECORD(DECL_CONTEXT_LEXICAL);
-  RECORD(DECL_CONTEXT_VISIBLE);
-  // Statements and Exprs can occur in the Decls and Types block.
-  AddStmtsExprs(Stream, Record);
-#undef RECORD
-#undef BLOCK
-  Stream.ExitBlock();
-}
-
-/// \brief Adjusts the given filename to only write out the portion of the
-/// filename that is not part of the system root directory.
-///
-/// \param Filename the file name to adjust.
-///
-/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and
-/// the returned filename will be adjusted by this system root.
-///
-/// \returns either the original filename (if it needs no adjustment) or the
-/// adjusted filename (which points into the @p Filename parameter).
-static const char *
-adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) {
-  assert(Filename && "No file name to adjust?");
-
-  if (!isysroot)
-    return Filename;
-
-  // Verify that the filename and the system root have the same prefix.
-  unsigned Pos = 0;
-  for (; Filename[Pos] && isysroot[Pos]; ++Pos)
-    if (Filename[Pos] != isysroot[Pos])
-      return Filename; // Prefixes don't match.
-
-  // We hit the end of the filename before we hit the end of the system root.
-  if (!Filename[Pos])
-    return Filename;
-
-  // If the file name has a '/' at the current position, skip over the '/'.
-  // We distinguish sysroot-based includes from absolute includes by the
-  // absence of '/' at the beginning of sysroot-based includes.
-  if (Filename[Pos] == '/')
-    ++Pos;
-
-  return Filename + Pos;
-}
-
-/// \brief Write the PCH metadata (e.g., i686-apple-darwin9).
-void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
-  using namespace llvm;
-
-  // Metadata
-  const TargetInfo &Target = Context.Target;
-  BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev();
-  MetaAbbrev->Add(BitCodeAbbrevOp(
-                    Chain ? pch::CHAINED_METADATA : pch::METADATA));
-  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major
-  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor
-  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major
-  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor
-  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
-  // Target triple or chained PCH name
-  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
-  unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
-
-  RecordData Record;
-  Record.push_back(Chain ? pch::CHAINED_METADATA : pch::METADATA);
-  Record.push_back(pch::VERSION_MAJOR);
-  Record.push_back(pch::VERSION_MINOR);
-  Record.push_back(CLANG_VERSION_MAJOR);
-  Record.push_back(CLANG_VERSION_MINOR);
-  Record.push_back(isysroot != 0);
-  // FIXME: This writes the absolute path for chained headers.
-  const std::string &BlobStr = Chain ? Chain->getFileName() : Target.getTriple().getTriple();
-  Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, BlobStr);
-
-  // Original file name
-  SourceManager &SM = Context.getSourceManager();
-  if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
-    BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev();
-    FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME));
-    FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
-    unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);
-
-    llvm::sys::Path MainFilePath(MainFile->getName());
-
-    MainFilePath.makeAbsolute();
-
-    const char *MainFileNameStr = MainFilePath.c_str();
-    MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr,
-                                                      isysroot);
-    RecordData Record;
-    Record.push_back(pch::ORIGINAL_FILE_NAME);
-    Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
-  }
-
-  // Repository branch/version information.
-  BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev();
-  RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION));
-  RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
-  unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev);
-  Record.clear();
-  Record.push_back(pch::VERSION_CONTROL_BRANCH_REVISION);
-  Stream.EmitRecordWithBlob(RepoAbbrevCode, Record,
-                            getClangFullRepositoryVersion());
-}
-
-/// \brief Write the LangOptions structure.
-void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
-  RecordData Record;
-  Record.push_back(LangOpts.Trigraphs);
-  Record.push_back(LangOpts.BCPLComment);  // BCPL-style '//' comments.
-  Record.push_back(LangOpts.DollarIdents);  // '$' allowed in identifiers.
-  Record.push_back(LangOpts.AsmPreprocessor);  // Preprocessor in asm mode.
-  Record.push_back(LangOpts.GNUMode);  // True in gnu99 mode false in c99 mode (etc)
-  Record.push_back(LangOpts.GNUKeywords);  // Allow GNU-extension keywords
-  Record.push_back(LangOpts.ImplicitInt);  // C89 implicit 'int'.
-  Record.push_back(LangOpts.Digraphs);  // C94, C99 and C++
-  Record.push_back(LangOpts.HexFloats);  // C99 Hexadecimal float constants.
-  Record.push_back(LangOpts.C99);  // C99 Support
-  Record.push_back(LangOpts.Microsoft);  // Microsoft extensions.
-  Record.push_back(LangOpts.CPlusPlus);  // C++ Support
-  Record.push_back(LangOpts.CPlusPlus0x);  // C++0x Support
-  Record.push_back(LangOpts.CXXOperatorNames);  // Treat C++ operator names as keywords.
-
-  Record.push_back(LangOpts.ObjC1);  // Objective-C 1 support enabled.
-  Record.push_back(LangOpts.ObjC2);  // Objective-C 2 support enabled.
-  Record.push_back(LangOpts.ObjCNonFragileABI);  // Objective-C
-                                                 // modern abi enabled.
-  Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced
-                                                 // modern abi enabled.
-  Record.push_back(LangOpts.NoConstantCFStrings); // non cfstring generation enabled..
-
-  Record.push_back(LangOpts.PascalStrings);  // Allow Pascal strings
-  Record.push_back(LangOpts.WritableStrings);  // Allow writable strings
-  Record.push_back(LangOpts.LaxVectorConversions);
-  Record.push_back(LangOpts.AltiVec);
-  Record.push_back(LangOpts.Exceptions);  // Support exception handling.
-  Record.push_back(LangOpts.SjLjExceptions);
-
-  Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime.
-  Record.push_back(LangOpts.Freestanding); // Freestanding implementation
-  Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin)
-
-  // Whether static initializers are protected by locks.
-  Record.push_back(LangOpts.ThreadsafeStatics);
-  Record.push_back(LangOpts.POSIXThreads);
-  Record.push_back(LangOpts.Blocks); // block extension to C
-  Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if
-                                  // they are unused.
-  Record.push_back(LangOpts.MathErrno); // Math functions must respect errno
-                                  // (modulo the platform support).
-
-  Record.push_back(LangOpts.getSignedOverflowBehavior());
-  Record.push_back(LangOpts.HeinousExtensions);
-
-  Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined.
-  Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be
-                                  // defined.
-  Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as
-                                  // opposed to __DYNAMIC__).
-  Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero.
-
-  Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be
-                                  // used (instead of C99 semantics).
-  Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined.
-  Record.push_back(LangOpts.AccessControl); // Whether C++ access control should
-                                            // be enabled.
-  Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or
-                                           // unsigned type
-  Record.push_back(LangOpts.ShortWChar);  // force wchar_t to be unsigned short
-  Record.push_back(LangOpts.getGCMode());
-  Record.push_back(LangOpts.getVisibilityMode());
-  Record.push_back(LangOpts.getStackProtectorMode());
-  Record.push_back(LangOpts.InstantiationDepth);
-  Record.push_back(LangOpts.OpenCL);
-  Record.push_back(LangOpts.CatchUndefined);
-  Record.push_back(LangOpts.ElideConstructors);
-  Record.push_back(LangOpts.SpellChecking);
-  Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record);
-}
-
-//===----------------------------------------------------------------------===//
-// stat cache Serialization
-//===----------------------------------------------------------------------===//
-
-namespace {
-// Trait used for the on-disk hash table of stat cache results.
-class PCHStatCacheTrait {
-public:
-  typedef const char * key_type;
-  typedef key_type key_type_ref;
-
-  typedef std::pair<int, struct stat> data_type;
-  typedef const data_type& data_type_ref;
-
-  static unsigned ComputeHash(const char *path) {
-    return llvm::HashString(path);
-  }
-
-  std::pair<unsigned,unsigned>
-    EmitKeyDataLength(llvm::raw_ostream& Out, const char *path,
-                      data_type_ref Data) {
-    unsigned StrLen = strlen(path);
-    clang::io::Emit16(Out, StrLen);
-    unsigned DataLen = 1; // result value
-    if (Data.first == 0)
-      DataLen += 4 + 4 + 2 + 8 + 8;
-    clang::io::Emit8(Out, DataLen);
-    return std::make_pair(StrLen + 1, DataLen);
-  }
-
-  void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) {
-    Out.write(path, KeyLen);
-  }
-
-  void EmitData(llvm::raw_ostream& Out, key_type_ref,
-                data_type_ref Data, unsigned DataLen) {
-    using namespace clang::io;
-    uint64_t Start = Out.tell(); (void)Start;
-
-    // Result of stat()
-    Emit8(Out, Data.first? 1 : 0);
-
-    if (Data.first == 0) {
-      Emit32(Out, (uint32_t) Data.second.st_ino);
-      Emit32(Out, (uint32_t) Data.second.st_dev);
-      Emit16(Out, (uint16_t) Data.second.st_mode);
-      Emit64(Out, (uint64_t) Data.second.st_mtime);
-      Emit64(Out, (uint64_t) Data.second.st_size);
-    }
-
-    assert(Out.tell() - Start == DataLen && "Wrong data length");
-  }
-};
-} // end anonymous namespace
-
-/// \brief Write the stat() system call cache to the PCH file.
-void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) {
-  // Build the on-disk hash table containing information about every
-  // stat() call.
-  OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator;
-  unsigned NumStatEntries = 0;
-  for (MemorizeStatCalls::iterator Stat = StatCalls.begin(),
-                                StatEnd = StatCalls.end();
-       Stat != StatEnd; ++Stat, ++NumStatEntries) {
-    const char *Filename = Stat->first();
-    Generator.insert(Filename, Stat->second);
-  }
-
-  // Create the on-disk hash table in a buffer.
-  llvm::SmallString<4096> StatCacheData;
-  uint32_t BucketOffset;
-  {
-    llvm::raw_svector_ostream Out(StatCacheData);
-    // Make sure that no bucket is at offset 0
-    clang::io::Emit32(Out, 0);
-    BucketOffset = Generator.Emit(Out);
-  }
-
-  // Create a blob abbreviation
-  using namespace llvm;
-  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::STAT_CACHE));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
-  unsigned StatCacheAbbrev = Stream.EmitAbbrev(Abbrev);
-
-  // Write the stat cache
-  RecordData Record;
-  Record.push_back(pch::STAT_CACHE);
-  Record.push_back(BucketOffset);
-  Record.push_back(NumStatEntries);
-  Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str());
-}
-
-//===----------------------------------------------------------------------===//
-// Source Manager Serialization
-//===----------------------------------------------------------------------===//
-
-/// \brief Create an abbreviation for the SLocEntry that refers to a
-/// file.
-static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
-  using namespace llvm;
-  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
-  // FileEntry fields.
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time
-  // HeaderFileInfo fields.
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isImport
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // DirInfo
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumIncludes
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // ControllingMacro
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
-  return Stream.EmitAbbrev(Abbrev);
-}
-
-/// \brief Create an abbreviation for the SLocEntry that refers to a
-/// buffer.
-static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
-  using namespace llvm;
-  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
-  return Stream.EmitAbbrev(Abbrev);
-}
-
-/// \brief Create an abbreviation for the SLocEntry that refers to a
-/// buffer's blob.
-static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
-  using namespace llvm;
-  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
-  return Stream.EmitAbbrev(Abbrev);
-}
-
-/// \brief Create an abbreviation for the SLocEntry that refers to an
-/// buffer.
-static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) {
-  using namespace llvm;
-  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
-  return Stream.EmitAbbrev(Abbrev);
-}
-
-/// \brief Writes the block containing the serialized form of the
-/// source manager.
-///
-/// TODO: We should probably use an on-disk hash table (stored in a
-/// blob), indexed based on the file name, so that we only create
-/// entries for files that we actually need. In the common case (no
-/// errors), we probably won't have to create file entries for any of
-/// the files in the AST.
-void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
-                                        const Preprocessor &PP,
-                                        const char *isysroot) {
-  RecordData Record;
-
-  // Enter the source manager block.
-  Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
-
-  // Abbreviations for the various kinds of source-location entries.
-  unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream);
-  unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream);
-  unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream);
-  unsigned SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream);
-
-  // Write the line table.
-  if (SourceMgr.hasLineTable()) {
-    LineTableInfo &LineTable = SourceMgr.getLineTable();
-
-    // Emit the file names
-    Record.push_back(LineTable.getNumFilenames());
-    for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
-      // Emit the file name
-      const char *Filename = LineTable.getFilename(I);
-      Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
-      unsigned FilenameLen = Filename? strlen(Filename) : 0;
-      Record.push_back(FilenameLen);
-      if (FilenameLen)
-        Record.insert(Record.end(), Filename, Filename + FilenameLen);
-    }
-
-    // Emit the line entries
-    for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
-         L != LEnd; ++L) {
-      // Emit the file ID
-      Record.push_back(L->first);
-
-      // Emit the line entries
-      Record.push_back(L->second.size());
-      for (std::vector<LineEntry>::iterator LE = L->second.begin(),
-                                         LEEnd = L->second.end();
-           LE != LEEnd; ++LE) {
-        Record.push_back(LE->FileOffset);
-        Record.push_back(LE->LineNo);
-        Record.push_back(LE->FilenameID);
-        Record.push_back((unsigned)LE->FileKind);
-        Record.push_back(LE->IncludeOffset);
-      }
-    }
-    Stream.EmitRecord(pch::SM_LINE_TABLE, Record);
-  }
-
-  // Write out the source location entry table. We skip the first
-  // entry, which is always the same dummy entry.
-  std::vector<uint32_t> SLocEntryOffsets;
-  RecordData PreloadSLocs;
-  unsigned BaseSLocID = Chain ? Chain->getTotalNumSLocs() : 0;
-  SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1 - BaseSLocID);
-  for (unsigned I = BaseSLocID + 1, N = SourceMgr.sloc_entry_size();
-       I != N; ++I) {
-    // Get this source location entry.
-    const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
-
-    // Record the offset of this source-location entry.
-    SLocEntryOffsets.push_back(Stream.GetCurrentBitNo());
-
-    // Figure out which record code to use.
-    unsigned Code;
-    if (SLoc->isFile()) {
-      if (SLoc->getFile().getContentCache()->Entry)
-        Code = pch::SM_SLOC_FILE_ENTRY;
-      else
-        Code = pch::SM_SLOC_BUFFER_ENTRY;
-    } else
-      Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
-    Record.clear();
-    Record.push_back(Code);
-
-    Record.push_back(SLoc->getOffset());
-    if (SLoc->isFile()) {
-      const SrcMgr::FileInfo &File = SLoc->getFile();
-      Record.push_back(File.getIncludeLoc().getRawEncoding());
-      Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
-      Record.push_back(File.hasLineDirectives());
-
-      const SrcMgr::ContentCache *Content = File.getContentCache();
-      if (Content->Entry) {
-        // The source location entry is a file. The blob associated
-        // with this entry is the file name.
-
-        // Emit size/modification time for this file.
-        Record.push_back(Content->Entry->getSize());
-        Record.push_back(Content->Entry->getModificationTime());
-
-        // Emit header-search information associated with this file.
-        HeaderFileInfo HFI;
-        HeaderSearch &HS = PP.getHeaderSearchInfo();
-        if (Content->Entry->getUID() < HS.header_file_size())
-          HFI = HS.header_file_begin()[Content->Entry->getUID()];
-        Record.push_back(HFI.isImport);
-        Record.push_back(HFI.DirInfo);
-        Record.push_back(HFI.NumIncludes);
-        AddIdentifierRef(HFI.ControllingMacro, Record);
-
-        // Turn the file name into an absolute path, if it isn't already.
-        const char *Filename = Content->Entry->getName();
-        llvm::sys::Path FilePath(Filename, strlen(Filename));
-        FilePath.makeAbsolute();
-        Filename = FilePath.c_str();
-
-        Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
-        Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename);
-
-        // FIXME: For now, preload all file source locations, so that
-        // we get the appropriate File entries in the reader. This is
-        // a temporary measure.
-        PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size());
-      } else {
-        // The source location entry is a buffer. The blob associated
-        // with this entry contains the contents of the buffer.
-
-        // We add one to the size so that we capture the trailing NULL
-        // that is required by llvm::MemoryBuffer::getMemBuffer (on
-        // the reader side).
-        const llvm::MemoryBuffer *Buffer
-          = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager());
-        const char *Name = Buffer->getBufferIdentifier();
-        Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
-                                  llvm::StringRef(Name, strlen(Name) + 1));
-        Record.clear();
-        Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
-        Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
-                                  llvm::StringRef(Buffer->getBufferStart(),
-                                                  Buffer->getBufferSize() + 1));
-
-        if (strcmp(Name, "<built-in>") == 0)
-          PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size());
-      }
-    } else {
-      // The source location entry is an instantiation.
-      const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
-      Record.push_back(Inst.getSpellingLoc().getRawEncoding());
-      Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
-      Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
-
-      // Compute the token length for this macro expansion.
-      unsigned NextOffset = SourceMgr.getNextOffset();
-      if (I + 1 != N)
-        NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset();
-      Record.push_back(NextOffset - SLoc->getOffset() - 1);
-      Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
-    }
-  }
-
-  Stream.ExitBlock();
-
-  if (SLocEntryOffsets.empty())
-    return;
-
-  // Write the source-location offsets table into the PCH block. This
-  // table is used for lazily loading source-location information.
-  using namespace llvm;
-  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::SOURCE_LOCATION_OFFSETS));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets
-  unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev);
-
-  Record.clear();
-  Record.push_back(pch::SOURCE_LOCATION_OFFSETS);
-  Record.push_back(SLocEntryOffsets.size());
-  Record.push_back(SourceMgr.getNextOffset());
-  Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,
-                            (const char *)data(SLocEntryOffsets),
-                           SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0]));
-
-  // Write the source location entry preloads array, telling the PCH
-  // reader which source locations entries it should load eagerly.
-  Stream.EmitRecord(pch::SOURCE_LOCATION_PRELOADS, PreloadSLocs);
-}
-
-//===----------------------------------------------------------------------===//
-// Preprocessor Serialization
-//===----------------------------------------------------------------------===//
-
-/// \brief Writes the block containing the serialized form of the
-/// preprocessor.
-///
-void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
-  RecordData Record;
-
-  // If the preprocessor __COUNTER__ value has been bumped, remember it.
-  if (PP.getCounterValue() != 0) {
-    Record.push_back(PP.getCounterValue());
-    Stream.EmitRecord(pch::PP_COUNTER_VALUE, Record);
-    Record.clear();
-  }
-
-  // Enter the preprocessor block.
-  Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2);
-
-  // If the PCH file contains __DATE__ or __TIME__ emit a warning about this.
-  // FIXME: use diagnostics subsystem for localization etc.
-  if (PP.SawDateOrTime())
-    fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
-
-  // Loop over all the macro definitions that are live at the end of the file,
-  // emitting each to the PP section.
-  PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
-  for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
-       I != E; ++I) {
-    // FIXME: This emits macros in hash table order, we should do it in a stable
-    // order so that output is reproducible.
-    MacroInfo *MI = I->second;
-
-    // Don't emit builtin macros like __LINE__ to the PCH file unless they have
-    // been redefined by the header (in which case they are not isBuiltinMacro).
-    // Also skip macros from a PCH file if we're chaining.
-    if (MI->isBuiltinMacro() || (Chain && MI->isFromPCH()))
-      continue;
-
-    AddIdentifierRef(I->first, Record);
-    MacroOffsets[I->first] = Stream.GetCurrentBitNo();
-    Record.push_back(MI->getDefinitionLoc().getRawEncoding());
-    Record.push_back(MI->isUsed());
-
-    unsigned Code;
-    if (MI->isObjectLike()) {
-      Code = pch::PP_MACRO_OBJECT_LIKE;
-    } else {
-      Code = pch::PP_MACRO_FUNCTION_LIKE;
-
-      Record.push_back(MI->isC99Varargs());
-      Record.push_back(MI->isGNUVarargs());
-      Record.push_back(MI->getNumArgs());
-      for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
-           I != E; ++I)
-        AddIdentifierRef(*I, Record);
-    }
-    
-    // If we have a detailed preprocessing record, record the macro definition
-    // ID that corresponds to this macro.
-    if (PPRec)
-      Record.push_back(getMacroDefinitionID(PPRec->findMacroDefinition(MI)));
-    
-    Stream.EmitRecord(Code, Record);
-    Record.clear();
-
-    // Emit the tokens array.
-    for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
-      // Note that we know that the preprocessor does not have any annotation
-      // tokens in it because they are created by the parser, and thus can't be
-      // in a macro definition.
-      const Token &Tok = MI->getReplacementToken(TokNo);
-
-      Record.push_back(Tok.getLocation().getRawEncoding());
-      Record.push_back(Tok.getLength());
-
-      // FIXME: When reading literal tokens, reconstruct the literal pointer if
-      // it is needed.
-      AddIdentifierRef(Tok.getIdentifierInfo(), Record);
-
-      // FIXME: Should translate token kind to a stable encoding.
-      Record.push_back(Tok.getKind());
-      // FIXME: Should translate token flags to a stable encoding.
-      Record.push_back(Tok.getFlags());
-
-      Stream.EmitRecord(pch::PP_TOKEN, Record);
-      Record.clear();
-    }
-    ++NumMacros;
-  }
-  
-  // If the preprocessor has a preprocessing record, emit it.
-  unsigned NumPreprocessingRecords = 0;
-  if (PPRec) {
-    for (PreprocessingRecord::iterator E = PPRec->begin(), EEnd = PPRec->end();
-         E != EEnd; ++E) {
-      Record.clear();
-      
-      if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
-        Record.push_back(NumPreprocessingRecords++);
-        AddSourceLocation(MI->getSourceRange().getBegin(), Record);
-        AddSourceLocation(MI->getSourceRange().getEnd(), Record);
-        AddIdentifierRef(MI->getName(), Record);
-        Record.push_back(getMacroDefinitionID(MI->getDefinition()));
-        Stream.EmitRecord(pch::PP_MACRO_INSTANTIATION, Record);
-        continue;
-      }
-      
-      if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
-        // Record this macro definition's location.
-        pch::IdentID ID = getMacroDefinitionID(MD);
-        if (ID != MacroDefinitionOffsets.size()) {
-          if (ID > MacroDefinitionOffsets.size())
-            MacroDefinitionOffsets.resize(ID + 1);
-          
-          MacroDefinitionOffsets[ID] = Stream.GetCurrentBitNo();            
-        } else
-          MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo());
-        
-        Record.push_back(NumPreprocessingRecords++);
-        Record.push_back(ID);
-        AddSourceLocation(MD->getSourceRange().getBegin(), Record);
-        AddSourceLocation(MD->getSourceRange().getEnd(), Record);
-        AddIdentifierRef(MD->getName(), Record);
-        AddSourceLocation(MD->getLocation(), Record);
-        Stream.EmitRecord(pch::PP_MACRO_DEFINITION, Record);
-        continue;
-      }
-    }
-  }
-  
-  Stream.ExitBlock();
-  
-  // Write the offsets table for the preprocessing record.
-  if (NumPreprocessingRecords > 0) {
-    // Write the offsets table for identifier IDs.
-    using namespace llvm;
-    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-    Abbrev->Add(BitCodeAbbrevOp(pch::MACRO_DEFINITION_OFFSETS));
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of records
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macro defs
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
-    unsigned MacroDefOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
-    
-    Record.clear();
-    Record.push_back(pch::MACRO_DEFINITION_OFFSETS);
-    Record.push_back(NumPreprocessingRecords);
-    Record.push_back(MacroDefinitionOffsets.size());
-    Stream.EmitRecordWithBlob(MacroDefOffsetAbbrev, Record,
-                              (const char *)data(MacroDefinitionOffsets),
-                              MacroDefinitionOffsets.size() * sizeof(uint32_t));
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Type Serialization
-//===----------------------------------------------------------------------===//
-
-/// \brief Write the representation of a type to the PCH stream.
-void PCHWriter::WriteType(QualType T) {
-  pch::TypeID &ID = TypeIDs[T];
-  if (ID == 0) // we haven't seen this type before.
-    ID = NextTypeID++;
-
-  // Record the offset for this type.
-  unsigned Index = ID - FirstTypeID;
-  if (TypeOffsets.size() == Index)
-    TypeOffsets.push_back(Stream.GetCurrentBitNo());
-  else if (TypeOffsets.size() < Index) {
-    TypeOffsets.resize(Index + 1);
-    TypeOffsets[Index] = Stream.GetCurrentBitNo();
-  }
-
-  RecordData Record;
-
-  // Emit the type's representation.
-  PCHTypeWriter W(*this, Record);
-
-  if (T.hasLocalNonFastQualifiers()) {
-    Qualifiers Qs = T.getLocalQualifiers();
-    AddTypeRef(T.getLocalUnqualifiedType(), Record);
-    Record.push_back(Qs.getAsOpaqueValue());
-    W.Code = pch::TYPE_EXT_QUAL;
-  } else {
-    switch (T->getTypeClass()) {
-      // For all of the concrete, non-dependent types, call the
-      // appropriate visitor function.
-#define TYPE(Class, Base) \
-    case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
-#define ABSTRACT_TYPE(Class, Base)
-#include "clang/AST/TypeNodes.def"
-    }
-  }
-
-  // Emit the serialized record.
-  Stream.EmitRecord(W.Code, Record);
-
-  // Flush any expressions that were written as part of this type.
-  FlushStmts();
-}
-
-//===----------------------------------------------------------------------===//
-// Declaration Serialization
-//===----------------------------------------------------------------------===//
-
-/// \brief Write the block containing all of the declaration IDs
-/// lexically declared within the given DeclContext.
-///
-/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
-/// bistream, or 0 if no block was written.
-uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
-                                                 DeclContext *DC) {
-  if (DC->decls_empty())
-    return 0;
-
-  uint64_t Offset = Stream.GetCurrentBitNo();
-  RecordData Record;
-  Record.push_back(pch::DECL_CONTEXT_LEXICAL);
-  llvm::SmallVector<pch::DeclID, 64> Decls;
-  for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
-         D != DEnd; ++D)
-    Decls.push_back(GetDeclRef(*D));
-
-  ++NumLexicalDeclContexts;
-  Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record,
-     reinterpret_cast<char*>(Decls.data()), Decls.size() * sizeof(pch::DeclID));
-  return Offset;
-}
-
-/// \brief Write the block containing all of the declaration IDs
-/// visible from the given DeclContext.
-///
-/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
-/// bistream, or 0 if no block was written.
-uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
-                                                 DeclContext *DC) {
-  if (DC->getPrimaryContext() != DC)
-    return 0;
-
-  // Since there is no name lookup into functions or methods, don't bother to
-  // build a visible-declarations table for these entities.
-  if (DC->isFunctionOrMethod())
-    return 0;
-
-  // If not in C++, we perform name lookup for the translation unit via the
-  // IdentifierInfo chains, don't bother to build a visible-declarations table.
-  // FIXME: In C++ we need the visible declarations in order to "see" the
-  // friend declarations, is there a way to do this without writing the table ?
-  if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus)
-    return 0;
-
-  // Force the DeclContext to build a its name-lookup table.
-  DC->lookup(DeclarationName());
-
-  // Serialize the contents of the mapping used for lookup. Note that,
-  // although we have two very different code paths, the serialized
-  // representation is the same for both cases: a declaration name,
-  // followed by a size, followed by references to the visible
-  // declarations that have that name.
-  uint64_t Offset = Stream.GetCurrentBitNo();
-  RecordData Record;
-  StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
-  if (!Map)
-    return 0;
-
-  for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
-       D != DEnd; ++D) {
-    AddDeclarationName(D->first, Record);
-    DeclContext::lookup_result Result = D->second.getLookupResult(Context);
-    Record.push_back(Result.second - Result.first);
-    for (; Result.first != Result.second; ++Result.first)
-      AddDeclRef(*Result.first, Record);
-  }
-
-  if (Record.size() == 0)
-    return 0;
-
-  Stream.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record);
-  ++NumVisibleDeclContexts;
-  return Offset;
-}
-
-void PCHWriter::WriteTypeDeclOffsets() {
-  using namespace llvm;
-  RecordData Record;
-
-  // Write the type offsets array
-  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::TYPE_OFFSET));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
-  unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
-  Record.clear();
-  Record.push_back(pch::TYPE_OFFSET);
-  Record.push_back(TypeOffsets.size());
-  Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record,
-                            (const char *)data(TypeOffsets),
-                            TypeOffsets.size() * sizeof(TypeOffsets[0]));
-
-  // Write the declaration offsets array
-  Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::DECL_OFFSET));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
-  unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
-  Record.clear();
-  Record.push_back(pch::DECL_OFFSET);
-  Record.push_back(DeclOffsets.size());
-  Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record,
-                            (const char *)data(DeclOffsets),
-                            DeclOffsets.size() * sizeof(DeclOffsets[0]));
-}
-
-//===----------------------------------------------------------------------===//
-// Global Method Pool and Selector Serialization
-//===----------------------------------------------------------------------===//
-
-namespace {
-// Trait used for the on-disk hash table used in the method pool.
-class PCHMethodPoolTrait {
-  PCHWriter &Writer;
-
-public:
-  typedef Selector key_type;
-  typedef key_type key_type_ref;
-
-  struct data_type {
-    pch::SelectorID ID;
-    ObjCMethodList Instance, Factory;
-  };
-  typedef const data_type& data_type_ref;
-
-  explicit PCHMethodPoolTrait(PCHWriter &Writer) : Writer(Writer) { }
-
-  static unsigned ComputeHash(Selector Sel) {
-    unsigned N = Sel.getNumArgs();
-    if (N == 0)
-      ++N;
-    unsigned R = 5381;
-    for (unsigned I = 0; I != N; ++I)
-      if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
-        R = llvm::HashString(II->getName(), R);
-    return R;
-  }
-
-  std::pair<unsigned,unsigned>
-    EmitKeyDataLength(llvm::raw_ostream& Out, Selector Sel,
-                      data_type_ref Methods) {
-    unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
-    clang::io::Emit16(Out, KeyLen);
-    unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
-    for (const ObjCMethodList *Method = &Methods.Instance; Method;
-         Method = Method->Next)
-      if (Method->Method)
-        DataLen += 4;
-    for (const ObjCMethodList *Method = &Methods.Factory; Method;
-         Method = Method->Next)
-      if (Method->Method)
-        DataLen += 4;
-    clang::io::Emit16(Out, DataLen);
-    return std::make_pair(KeyLen, DataLen);
-  }
-
-  void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) {
-    uint64_t Start = Out.tell();
-    assert((Start >> 32) == 0 && "Selector key offset too large");
-    Writer.SetSelectorOffset(Sel, Start);
-    unsigned N = Sel.getNumArgs();
-    clang::io::Emit16(Out, N);
-    if (N == 0)
-      N = 1;
-    for (unsigned I = 0; I != N; ++I)
-      clang::io::Emit32(Out,
-                    Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
-  }
-
-  void EmitData(llvm::raw_ostream& Out, key_type_ref,
-                data_type_ref Methods, unsigned DataLen) {
-    uint64_t Start = Out.tell(); (void)Start;
-    clang::io::Emit32(Out, Methods.ID);
-    unsigned NumInstanceMethods = 0;
-    for (const ObjCMethodList *Method = &Methods.Instance; Method;
-         Method = Method->Next)
-      if (Method->Method)
-        ++NumInstanceMethods;
-
-    unsigned NumFactoryMethods = 0;
-    for (const ObjCMethodList *Method = &Methods.Factory; Method;
-         Method = Method->Next)
-      if (Method->Method)
-        ++NumFactoryMethods;
-
-    clang::io::Emit16(Out, NumInstanceMethods);
-    clang::io::Emit16(Out, NumFactoryMethods);
-    for (const ObjCMethodList *Method = &Methods.Instance; Method;
-         Method = Method->Next)
-      if (Method->Method)
-        clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
-    for (const ObjCMethodList *Method = &Methods.Factory; Method;
-         Method = Method->Next)
-      if (Method->Method)
-        clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
-
-    assert(Out.tell() - Start == DataLen && "Data length is wrong");
-  }
-};
-} // end anonymous namespace
-
-/// \brief Write ObjC data: selectors and the method pool.
-///
-/// The method pool contains both instance and factory methods, stored
-/// in an on-disk hash table indexed by the selector. The hash table also
-/// contains an empty entry for every other selector known to Sema.
-void PCHWriter::WriteSelectors(Sema &SemaRef) {
-  using namespace llvm;
-
-  // Do we have to do anything at all?
-  if (SemaRef.MethodPool.empty() && SelectorIDs.empty())
-    return;
-  unsigned NumTableEntries = 0;
-  // Create and write out the blob that contains selectors and the method pool.
-  {
-    OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator;
-
-    // Create the on-disk hash table representation. We walk through every
-    // selector we've seen and look it up in the method pool.
-    SelectorOffsets.resize(NextSelectorID - FirstSelectorID);
-    for (llvm::DenseMap<Selector, pch::SelectorID>::iterator
-             I = SelectorIDs.begin(), E = SelectorIDs.end();
-         I != E; ++I) {
-      Selector S = I->first;
-      Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S);
-      PCHMethodPoolTrait::data_type Data = {
-        I->second,
-        ObjCMethodList(),
-        ObjCMethodList()
-      };
-      if (F != SemaRef.MethodPool.end()) {
-        Data.Instance = F->second.first;
-        Data.Factory = F->second.second;
-      }
-      // Only write this selector if it's not in an existing PCH or something
-      // changed.
-      if (Chain && I->second < FirstSelectorID) {
-        // Selector already exists. Did it change?
-        bool changed = false;
-        for (ObjCMethodList *M = &Data.Instance; !changed && M && M->Method;
-             M = M->Next) {
-          if (M->Method->getPCHLevel() == 0)
-            changed = true;
-        }
-        for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method;
-             M = M->Next) {
-          if (M->Method->getPCHLevel() == 0)
-            changed = true;
-        }
-        if (!changed)
-          continue;
-      } else if (Data.Instance.Method || Data.Factory.Method) {
-        // A new method pool entry.
-        ++NumTableEntries;
-      }
-      Generator.insert(S, Data);
-    }
-
-    // Create the on-disk hash table in a buffer.
-    llvm::SmallString<4096> MethodPool;
-    uint32_t BucketOffset;
-    {
-      PCHMethodPoolTrait Trait(*this);
-      llvm::raw_svector_ostream Out(MethodPool);
-      // Make sure that no bucket is at offset 0
-      clang::io::Emit32(Out, 0);
-      BucketOffset = Generator.Emit(Out, Trait);
-    }
-
-    // Create a blob abbreviation
-    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-    Abbrev->Add(BitCodeAbbrevOp(pch::METHOD_POOL));
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
-    unsigned MethodPoolAbbrev = Stream.EmitAbbrev(Abbrev);
-
-    // Write the method pool
-    RecordData Record;
-    Record.push_back(pch::METHOD_POOL);
-    Record.push_back(BucketOffset);
-    Record.push_back(NumTableEntries);
-    Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str());
-
-    // Create a blob abbreviation for the selector table offsets.
-    Abbrev = new BitCodeAbbrev();
-    Abbrev->Add(BitCodeAbbrevOp(pch::SELECTOR_OFFSETS));
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
-    unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
-
-    // Write the selector offsets table.
-    Record.clear();
-    Record.push_back(pch::SELECTOR_OFFSETS);
-    Record.push_back(SelectorOffsets.size());
-    Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
-                              (const char *)data(SelectorOffsets),
-                              SelectorOffsets.size() * 4);
-  }
-}
-
-/// \brief Write the selectors referenced in @selector expression into PCH file.
-void PCHWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
-  using namespace llvm;
-  if (SemaRef.ReferencedSelectors.empty())
-    return;
-
-  RecordData Record;
-
-  // Note: this writes out all references even for a dependent PCH. But it is
-  // very tricky to fix, and given that @selector shouldn't really appear in
-  // headers, probably not worth it. It's not a correctness issue.
-  for (DenseMap<Selector, SourceLocation>::iterator S =
-       SemaRef.ReferencedSelectors.begin(),
-       E = SemaRef.ReferencedSelectors.end(); S != E; ++S) {
-    Selector Sel = (*S).first;
-    SourceLocation Loc = (*S).second;
-    AddSelectorRef(Sel, Record);
-    AddSourceLocation(Loc, Record);
-  }
-  Stream.EmitRecord(pch::REFERENCED_SELECTOR_POOL, Record);
-}
-
-//===----------------------------------------------------------------------===//
-// Identifier Table Serialization
-//===----------------------------------------------------------------------===//
-
-namespace {
-class PCHIdentifierTableTrait {
-  PCHWriter &Writer;
-  Preprocessor &PP;
-
-  /// \brief Determines whether this is an "interesting" identifier
-  /// that needs a full IdentifierInfo structure written into the hash
-  /// table.
-  static bool isInterestingIdentifier(const IdentifierInfo *II) {
-    return II->isPoisoned() ||
-      II->isExtensionToken() ||
-      II->hasMacroDefinition() ||
-      II->getObjCOrBuiltinID() ||
-      II->getFETokenInfo<void>();
-  }
-
-public:
-  typedef const IdentifierInfo* key_type;
-  typedef key_type  key_type_ref;
-
-  typedef pch::IdentID data_type;
-  typedef data_type data_type_ref;
-
-  PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP)
-    : Writer(Writer), PP(PP) { }
-
-  static unsigned ComputeHash(const IdentifierInfo* II) {
-    return llvm::HashString(II->getName());
-  }
-
-  std::pair<unsigned,unsigned>
-    EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II,
-                      pch::IdentID ID) {
-    unsigned KeyLen = II->getLength() + 1;
-    unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
-    if (isInterestingIdentifier(II)) {
-      DataLen += 2; // 2 bytes for builtin ID, flags
-      if (II->hasMacroDefinition() &&
-          !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro())
-        DataLen += 4;
-      for (IdentifierResolver::iterator D = IdentifierResolver::begin(II),
-                                     DEnd = IdentifierResolver::end();
-           D != DEnd; ++D)
-        DataLen += sizeof(pch::DeclID);
-    }
-    clang::io::Emit16(Out, DataLen);
-    // We emit the key length after the data length so that every
-    // string is preceded by a 16-bit length. This matches the PTH
-    // format for storing identifiers.
-    clang::io::Emit16(Out, KeyLen);
-    return std::make_pair(KeyLen, DataLen);
-  }
-
-  void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II,
-               unsigned KeyLen) {
-    // Record the location of the key data.  This is used when generating
-    // the mapping from persistent IDs to strings.
-    Writer.SetIdentifierOffset(II, Out.tell());
-    Out.write(II->getNameStart(), KeyLen);
-  }
-
-  void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II,
-                pch::IdentID ID, unsigned) {
-    if (!isInterestingIdentifier(II)) {
-      clang::io::Emit32(Out, ID << 1);
-      return;
-    }
-
-    clang::io::Emit32(Out, (ID << 1) | 0x01);
-    uint32_t Bits = 0;
-    bool hasMacroDefinition =
-      II->hasMacroDefinition() &&
-      !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro();
-    Bits = (uint32_t)II->getObjCOrBuiltinID();
-    Bits = (Bits << 1) | unsigned(hasMacroDefinition);
-    Bits = (Bits << 1) | unsigned(II->isExtensionToken());
-    Bits = (Bits << 1) | unsigned(II->isPoisoned());
-    Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
-    Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
-    clang::io::Emit16(Out, Bits);
-
-    if (hasMacroDefinition)
-      clang::io::Emit32(Out, Writer.getMacroOffset(II));
-
-    // Emit the declaration IDs in reverse order, because the
-    // IdentifierResolver provides the declarations as they would be
-    // visible (e.g., the function "stat" would come before the struct
-    // "stat"), but IdentifierResolver::AddDeclToIdentifierChain()
-    // adds declarations to the end of the list (so we need to see the
-    // struct "status" before the function "status").
-    // Only emit declarations that aren't from a chained PCH, though.
-    llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II),
-                                        IdentifierResolver::end());
-    for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(),
-                                                      DEnd = Decls.rend();
-         D != DEnd; ++D)
-      clang::io::Emit32(Out, Writer.getDeclID(*D));
-  }
-};
-} // end anonymous namespace
-
-/// \brief Write the identifier table into the PCH file.
-///
-/// The identifier table consists of a blob containing string data
-/// (the actual identifiers themselves) and a separate "offsets" index
-/// that maps identifier IDs to locations within the blob.
-void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
-  using namespace llvm;
-
-  // Create and write out the blob that contains the identifier
-  // strings.
-  {
-    OnDiskChainedHashTableGenerator<PCHIdentifierTableTrait> Generator;
-
-    // Look for any identifiers that were named while processing the
-    // headers, but are otherwise not needed. We add these to the hash
-    // table to enable checking of the predefines buffer in the case
-    // where the user adds new macro definitions when building the PCH
-    // file.
-    for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
-                                IDEnd = PP.getIdentifierTable().end();
-         ID != IDEnd; ++ID)
-      getIdentifierRef(ID->second);
-
-    // Create the on-disk hash table representation. We only store offsets
-    // for identifiers that appear here for the first time.
-    IdentifierOffsets.resize(NextIdentID - FirstIdentID);
-    for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator
-           ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
-         ID != IDEnd; ++ID) {
-      assert(ID->first && "NULL identifier in identifier table");
-      if (!Chain || !ID->first->isFromPCH())
-        Generator.insert(ID->first, ID->second);
-    }
-
-    // Create the on-disk hash table in a buffer.
-    llvm::SmallString<4096> IdentifierTable;
-    uint32_t BucketOffset;
-    {
-      PCHIdentifierTableTrait Trait(*this, PP);
-      llvm::raw_svector_ostream Out(IdentifierTable);
-      // Make sure that no bucket is at offset 0
-      clang::io::Emit32(Out, 0);
-      BucketOffset = Generator.Emit(Out, Trait);
-    }
-
-    // Create a blob abbreviation
-    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-    Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE));
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
-    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
-    unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);
-
-    // Write the identifier table
-    RecordData Record;
-    Record.push_back(pch::IDENTIFIER_TABLE);
-    Record.push_back(BucketOffset);
-    Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str());
-  }
-
-  // Write the offsets table for identifier IDs.
-  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
-  Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_OFFSET));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
-  unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
-
-  RecordData Record;
-  Record.push_back(pch::IDENTIFIER_OFFSET);
-  Record.push_back(IdentifierOffsets.size());
-  Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
-                            (const char *)data(IdentifierOffsets),
-                            IdentifierOffsets.size() * sizeof(uint32_t));
-}
-
-//===----------------------------------------------------------------------===//
-// General Serialization Routines
-//===----------------------------------------------------------------------===//
-
-/// \brief Write a record containing the given attributes.
-void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
-  RecordData Record;
-  for (; Attr; Attr = Attr->getNext()) {
-    Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs
-    Record.push_back(Attr->isInherited());
-    switch (Attr->getKind()) {
-    default:
-      assert(0 && "Does not support PCH writing for this attribute yet!");
-      break;
-    case attr::Alias:
-      AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
-      break;
-
-    case attr::AlignMac68k:
-      break;
-
-    case attr::Aligned:
-      Record.push_back(cast<AlignedAttr>(Attr)->getAlignment());
-      break;
-
-    case attr::AlwaysInline:
-      break;
-
-    case attr::AnalyzerNoReturn:
-      break;
-
-    case attr::Annotate:
-      AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record);
-      break;
-
-    case attr::AsmLabel:
-      AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
-      break;
-
-    case attr::BaseCheck:
-      break;
-
-    case attr::Blocks:
-      Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
-      break;
-
-    case attr::CDecl:
-      break;
-
-    case attr::Cleanup:
-      AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
-      break;
-
-    case attr::Const:
-      break;
-
-    case attr::Constructor:
-      Record.push_back(cast<ConstructorAttr>(Attr)->getPriority());
-      break;
-
-    case attr::DLLExport:
-    case attr::DLLImport:
-    case attr::Deprecated:
-      break;
-
-    case attr::Destructor:
-      Record.push_back(cast<DestructorAttr>(Attr)->getPriority());
-      break;
-
-    case attr::FastCall:
-    case attr::Final:
-      break;
-
-    case attr::Format: {
-      const FormatAttr *Format = cast<FormatAttr>(Attr);
-      AddString(Format->getType(), Record);
-      Record.push_back(Format->getFormatIdx());
-      Record.push_back(Format->getFirstArg());
-      break;
-    }
-
-    case attr::FormatArg: {
-      const FormatArgAttr *Format = cast<FormatArgAttr>(Attr);
-      Record.push_back(Format->getFormatIdx());
-      break;
-    }
-
-    case attr::Sentinel : {
-      const SentinelAttr *Sentinel = cast<SentinelAttr>(Attr);
-      Record.push_back(Sentinel->getSentinel());
-      Record.push_back(Sentinel->getNullPos());
-      break;
-    }
-
-    case attr::GNUInline:
-    case attr::Hiding:
-    case attr::IBAction:
-    case attr::IBOutlet:
-    case attr::Malloc:
-    case attr::NoDebug:
-    case attr::NoInline:
-    case attr::NoReturn:
-    case attr::NoThrow:
-      break;
-
-    case attr::IBOutletCollection: {
-      const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr);
-      AddDeclRef(ICA->getClass(), Record);
-      break;
-    }
-
-    case attr::NonNull: {
-      const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
-      Record.push_back(NonNull->size());
-      Record.insert(Record.end(), NonNull->begin(), NonNull->end());
-      break;
-    }
-
-    case attr::CFReturnsNotRetained:
-    case attr::CFReturnsRetained:
-    case attr::NSReturnsNotRetained:
-    case attr::NSReturnsRetained:
-    case attr::ObjCException:
-    case attr::ObjCNSObject:
-    case attr::Overloadable:
-    case attr::Override:
-      break;
-
-    case attr::MaxFieldAlignment:
-      Record.push_back(cast<MaxFieldAlignmentAttr>(Attr)->getAlignment());
-      break;
-
-    case attr::Packed:
-      break;
-
-    case attr::Pure:
-      break;
-
-    case attr::Regparm:
-      Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
-      break;
-
-    case attr::ReqdWorkGroupSize:
-      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim());
-      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim());
-      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim());
-      break;
-
-    case attr::Section:
-      AddString(cast<SectionAttr>(Attr)->getName(), Record);
-      break;
-
-    case attr::StdCall:
-    case attr::TransparentUnion:
-    case attr::Unavailable:
-    case attr::Unused:
-    case attr::Used:
-      break;
-
-    case attr::Visibility:
-      // FIXME: stable encoding
-      Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility());
-      Record.push_back(cast<VisibilityAttr>(Attr)->isFromPragma());
-      break;
-
-    case attr::WarnUnusedResult:
-    case attr::Weak:
-    case attr::WeakRef:
-    case attr::WeakImport:
-      break;
-    }
-  }
-
-  Stream.EmitRecord(pch::DECL_ATTR, Record);
-}
-
-void PCHWriter::AddString(const std::string &Str, RecordData &Record) {
-  Record.push_back(Str.size());
-  Record.insert(Record.end(), Str.begin(), Str.end());
-}
-
-/// \brief Note that the identifier II occurs at the given offset
-/// within the identifier table.
-void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
-  pch::IdentID ID = IdentifierIDs[II];
-  // Only store offsets new to this PCH file. Other identifier names are looked
-  // up earlier in the chain and thus don't need an offset.
-  if (ID >= FirstIdentID)
-    IdentifierOffsets[ID - FirstIdentID] = Offset;
-}
-
-/// \brief Note that the selector Sel occurs at the given offset
-/// within the method pool/selector table.
-void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
-  unsigned ID = SelectorIDs[Sel];
-  assert(ID && "Unknown selector");
-  // Don't record offsets for selectors that are also available in a different
-  // file.
-  if (ID < FirstSelectorID)
-    return;
-  SelectorOffsets[ID - FirstSelectorID] = Offset;
-}
-
-PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
-  : Stream(Stream), Chain(0), FirstDeclID(1), NextDeclID(FirstDeclID),
-    FirstTypeID(pch::NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
-    FirstIdentID(1), NextIdentID(FirstIdentID), FirstSelectorID(1),
-    NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit),
-    NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
-    NumVisibleDeclContexts(0) {
-}
-
-void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
-                         const char *isysroot) {
-  // Emit the file header.
-  Stream.Emit((unsigned)'C', 8);
-  Stream.Emit((unsigned)'P', 8);
-  Stream.Emit((unsigned)'C', 8);
-  Stream.Emit((unsigned)'H', 8);
-
-  WriteBlockInfoBlock();
-
-  if (Chain)
-    WritePCHChain(SemaRef, StatCalls, isysroot);
-  else
-    WritePCHCore(SemaRef, StatCalls, isysroot);
-}
-
-void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
-                             const char *isysroot) {
-  using namespace llvm;
-
-  ASTContext &Context = SemaRef.Context;
-  Preprocessor &PP = SemaRef.PP;
-
-  // The translation unit is the first declaration we'll emit.
-  DeclIDs[Context.getTranslationUnitDecl()] = 1;
-  ++NextDeclID;
-  DeclTypesToEmit.push(Context.getTranslationUnitDecl());
-
-  // Make sure that we emit IdentifierInfos (and any attached
-  // declarations) for builtins.
-  {
-    IdentifierTable &Table = PP.getIdentifierTable();
-    llvm::SmallVector<const char *, 32> BuiltinNames;
-    Context.BuiltinInfo.GetBuiltinNames(BuiltinNames,
-                                        Context.getLangOptions().NoBuiltin);
-    for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I)
-      getIdentifierRef(&Table.get(BuiltinNames[I]));
-  }
-
-  // Build a record containing all of the tentative definitions in this file, in
-  // TentativeDefinitions order.  Generally, this record will be empty for
-  // headers.
-  RecordData TentativeDefinitions;
-  for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) {
-    AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
-  }
-
-  // Build a record containing all of the file scoped decls in this file.
-  RecordData UnusedFileScopedDecls;
-  for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i)
-    AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls);
-
-  RecordData WeakUndeclaredIdentifiers;
-  if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
-    WeakUndeclaredIdentifiers.push_back(
-                                      SemaRef.WeakUndeclaredIdentifiers.size());
-    for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator
-         I = SemaRef.WeakUndeclaredIdentifiers.begin(),
-         E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) {
-      AddIdentifierRef(I->first, WeakUndeclaredIdentifiers);
-      AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers);
-      AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers);
-      WeakUndeclaredIdentifiers.push_back(I->second.getUsed());
-    }
-  }
-
-  // Build a record containing all of the locally-scoped external
-  // declarations in this header file. Generally, this record will be
-  // empty.
-  RecordData LocallyScopedExternalDecls;
-  // FIXME: This is filling in the PCH file in densemap order which is
-  // nondeterminstic!
-  for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
-         TD = SemaRef.LocallyScopedExternalDecls.begin(),
-         TDEnd = SemaRef.LocallyScopedExternalDecls.end();
-       TD != TDEnd; ++TD)
-    AddDeclRef(TD->second, LocallyScopedExternalDecls);
-
-  // Build a record containing all of the ext_vector declarations.
-  RecordData ExtVectorDecls;
-  for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I)
-    AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls);
-
-  // Build a record containing all of the VTable uses information.
-  RecordData VTableUses;
-  if (!SemaRef.VTableUses.empty()) {
-    VTableUses.push_back(SemaRef.VTableUses.size());
-    for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
-      AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
-      AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
-      VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]);
-    }
-  }
-
-  // Build a record containing all of dynamic classes declarations.
-  RecordData DynamicClasses;
-  for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
-    AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
-
-  // Build a record containing all of pending implicit instantiations.
-  RecordData PendingImplicitInstantiations;
-  for (std::deque<Sema::PendingImplicitInstantiation>::iterator
-         I = SemaRef.PendingImplicitInstantiations.begin(),
-         N = SemaRef.PendingImplicitInstantiations.end(); I != N; ++I) {
-    AddDeclRef(I->first, PendingImplicitInstantiations);
-    AddSourceLocation(I->second, PendingImplicitInstantiations);
-  }
-  assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
-         "There are local ones at end of translation unit!");
-
-  // Build a record containing some declaration references.
-  RecordData SemaDeclRefs;
-  if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
-    AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs);
-    AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs);
-  }
-
-  // Write the remaining PCH contents.
-  RecordData Record;
-  Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5);
-  WriteMetadata(Context, isysroot);
-  WriteLanguageOptions(Context.getLangOptions());
-  if (StatCalls && !isysroot)
-    WriteStatCache(*StatCalls);
-  WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
-  // Write the record of special types.
-  Record.clear();
-
-  AddTypeRef(Context.getBuiltinVaListType(), Record);
-  AddTypeRef(Context.getObjCIdType(), Record);
-  AddTypeRef(Context.getObjCSelType(), Record);
-  AddTypeRef(Context.getObjCProtoType(), Record);
-  AddTypeRef(Context.getObjCClassType(), Record);
-  AddTypeRef(Context.getRawCFConstantStringType(), Record);
-  AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record);
-  AddTypeRef(Context.getFILEType(), Record);
-  AddTypeRef(Context.getjmp_bufType(), Record);
-  AddTypeRef(Context.getsigjmp_bufType(), Record);
-  AddTypeRef(Context.ObjCIdRedefinitionType, Record);
-  AddTypeRef(Context.ObjCClassRedefinitionType, Record);
-  AddTypeRef(Context.getRawBlockdescriptorType(), Record);
-  AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record);
-  AddTypeRef(Context.ObjCSelRedefinitionType, Record);
-  AddTypeRef(Context.getRawNSConstantStringType(), Record);
-  Record.push_back(Context.isInt128Installed());
-  Stream.EmitRecord(pch::SPECIAL_TYPES, Record);
-
-  // Keep writing types and declarations until all types and
-  // declarations have been written.
-  Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
-  WriteDeclsBlockAbbrevs();
-  while (!DeclTypesToEmit.empty()) {
-    DeclOrType DOT = DeclTypesToEmit.front();
-    DeclTypesToEmit.pop();
-    if (DOT.isType())
-      WriteType(DOT.getType());
-    else
-      WriteDecl(Context, DOT.getDecl());
-  }
-  Stream.ExitBlock();
-
-  WritePreprocessor(PP);
-  WriteSelectors(SemaRef);
-  WriteReferencedSelectorsPool(SemaRef);
-  WriteIdentifierTable(PP);
-
-  WriteTypeDeclOffsets();
-
-  // Write the record containing external, unnamed definitions.
-  if (!ExternalDefinitions.empty())
-    Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions);
-
-  // Write the record containing tentative definitions.
-  if (!TentativeDefinitions.empty())
-    Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions);
-
-  // Write the record containing unused file scoped decls.
-  if (!UnusedFileScopedDecls.empty())
-    Stream.EmitRecord(pch::UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);
-
-  // Write the record containing weak undeclared identifiers.
-  if (!WeakUndeclaredIdentifiers.empty())
-    Stream.EmitRecord(pch::WEAK_UNDECLARED_IDENTIFIERS,
-                      WeakUndeclaredIdentifiers);
-
-  // Write the record containing locally-scoped external definitions.
-  if (!LocallyScopedExternalDecls.empty())
-    Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS,
-                      LocallyScopedExternalDecls);
-
-  // Write the record containing ext_vector type names.
-  if (!ExtVectorDecls.empty())
-    Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls);
-
-  // Write the record containing VTable uses information.
-  if (!VTableUses.empty())
-    Stream.EmitRecord(pch::VTABLE_USES, VTableUses);
-
-  // Write the record containing dynamic classes declarations.
-  if (!DynamicClasses.empty())
-    Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses);
-
-  // Write the record containing pending implicit instantiations.
-  if (!PendingImplicitInstantiations.empty())
-    Stream.EmitRecord(pch::PENDING_IMPLICIT_INSTANTIATIONS,
-                      PendingImplicitInstantiations);
-
-  // Write the record containing declaration references of Sema.
-  if (!SemaDeclRefs.empty())
-    Stream.EmitRecord(pch::SEMA_DECL_REFS, SemaDeclRefs);
-
-  // Some simple statistics
-  Record.clear();
-  Record.push_back(NumStatements);
-  Record.push_back(NumMacros);
-  Record.push_back(NumLexicalDeclContexts);
-  Record.push_back(NumVisibleDeclContexts);
-  Stream.EmitRecord(pch::STATISTICS, Record);
-  Stream.ExitBlock();
-}
-
-void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
-                              const char *isysroot) {
-  using namespace llvm;
-
-  FirstDeclID += Chain->getTotalNumDecls();
-  FirstTypeID += Chain->getTotalNumTypes();
-  FirstIdentID += Chain->getTotalNumIdentifiers();
-  FirstSelectorID += Chain->getTotalNumSelectors();
-  NextDeclID = FirstDeclID;
-  NextTypeID = FirstTypeID;
-  NextIdentID = FirstIdentID;
-  NextSelectorID = FirstSelectorID;
-
-  ASTContext &Context = SemaRef.Context;
-  Preprocessor &PP = SemaRef.PP;
-
-  RecordData Record;
-  Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5);
-  WriteMetadata(Context, isysroot);
-  if (StatCalls && !isysroot)
-    WriteStatCache(*StatCalls);
-  // FIXME: Source manager block should only write new stuff, which could be
-  // done by tracking the largest ID in the chain
-  WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
-
-  // The special types are in the chained PCH.
-
-  // 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();
-  llvm::SmallVector<pch::DeclID, 64> NewGlobalDecls;
-  for (DeclContext::decl_iterator I = TU->noload_decls_begin(),
-                                  E = TU->noload_decls_end();
-       I != E; ++I) {
-    if ((*I)->getPCHLevel() == 0)
-      NewGlobalDecls.push_back(GetDeclRef(*I));
-    else if ((*I)->isChangedSinceDeserialization())
-      (void)GetDeclRef(*I); // Make sure it's written, but don't record it.
-  }
-  // We also need to write a lexical updates block for the TU.
-  llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev();
-  Abv->Add(llvm::BitCodeAbbrevOp(pch::TU_UPDATE_LEXICAL));
-  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
-  unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(Abv);
-  Record.clear();
-  Record.push_back(pch::TU_UPDATE_LEXICAL);
-  Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
-                          reinterpret_cast<const char*>(NewGlobalDecls.data()),
-                          NewGlobalDecls.size() * sizeof(pch::DeclID));
-
-  // Build a record containing all of the new tentative definitions in this
-  // file, in TentativeDefinitions order.
-  RecordData TentativeDefinitions;
-  for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) {
-    if (SemaRef.TentativeDefinitions[i]->getPCHLevel() == 0)
-      AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
-  }
-
-  // Build a record containing all of the file scoped decls in this file.
-  RecordData UnusedFileScopedDecls;
-  for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i) {
-    if (SemaRef.UnusedFileScopedDecls[i]->getPCHLevel() == 0)
-      AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls);
-  }
-
-  // We write the entire table, overwriting the tables from the chain.
-  RecordData WeakUndeclaredIdentifiers;
-  if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
-    WeakUndeclaredIdentifiers.push_back(
-                                      SemaRef.WeakUndeclaredIdentifiers.size());
-    for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator
-         I = SemaRef.WeakUndeclaredIdentifiers.begin(),
-         E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) {
-      AddIdentifierRef(I->first, WeakUndeclaredIdentifiers);
-      AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers);
-      AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers);
-      WeakUndeclaredIdentifiers.push_back(I->second.getUsed());
-    }
-  }
-
-  // Build a record containing all of the locally-scoped external
-  // declarations in this header file. Generally, this record will be
-  // empty.
-  RecordData LocallyScopedExternalDecls;
-  // FIXME: This is filling in the PCH file in densemap order which is
-  // nondeterminstic!
-  for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
-         TD = SemaRef.LocallyScopedExternalDecls.begin(),
-         TDEnd = SemaRef.LocallyScopedExternalDecls.end();
-       TD != TDEnd; ++TD) {
-    if (TD->second->getPCHLevel() == 0)
-      AddDeclRef(TD->second, LocallyScopedExternalDecls);
-  }
-
-  // Build a record containing all of the ext_vector declarations.
-  RecordData ExtVectorDecls;
-  for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) {
-    if (SemaRef.ExtVectorDecls[I]->getPCHLevel() == 0)
-      AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls);
-  }
-
-  // Build a record containing all of the VTable uses information.
-  // We write everything here, because it's too hard to determine whether
-  // a use is new to this part.
-  RecordData VTableUses;
-  if (!SemaRef.VTableUses.empty()) {
-    VTableUses.push_back(SemaRef.VTableUses.size());
-    for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
-      AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
-      AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
-      VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]);
-    }
-  }
-
-  // Build a record containing all of dynamic classes declarations.
-  RecordData DynamicClasses;
-  for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
-    if (SemaRef.DynamicClasses[I]->getPCHLevel() == 0)
-      AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
-
-  // Build a record containing all of pending implicit instantiations.
-  RecordData PendingImplicitInstantiations;
-  for (std::deque<Sema::PendingImplicitInstantiation>::iterator
-         I = SemaRef.PendingImplicitInstantiations.begin(),
-         N = SemaRef.PendingImplicitInstantiations.end(); I != N; ++I) {
-    if (I->first->getPCHLevel() == 0) {
-      AddDeclRef(I->first, PendingImplicitInstantiations);
-      AddSourceLocation(I->second, PendingImplicitInstantiations);
-    }
-  }
-  assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
-         "There are local ones at end of translation unit!");
-
-  // Build a record containing some declaration references.
-  // It's not worth the effort to avoid duplication here.
-  RecordData SemaDeclRefs;
-  if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
-    AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs);
-    AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs);
-  }
-
-  Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
-  WriteDeclsBlockAbbrevs();
-  while (!DeclTypesToEmit.empty()) {
-    DeclOrType DOT = DeclTypesToEmit.front();
-    DeclTypesToEmit.pop();
-    if (DOT.isType())
-      WriteType(DOT.getType());
-    else
-      WriteDecl(Context, DOT.getDecl());
-  }
-  Stream.ExitBlock();
-
-  WritePreprocessor(PP);
-  WriteSelectors(SemaRef);
-  WriteReferencedSelectorsPool(SemaRef);
-  WriteIdentifierTable(PP);
-  WriteTypeDeclOffsets();
-
-  /// Build a record containing first declarations from a chained PCH and the
-  /// most recent declarations in this PCH that they point to.
-  RecordData FirstLatestDeclIDs;
-  for (FirstLatestDeclMap::iterator
-        I = FirstLatestDecls.begin(), E = FirstLatestDecls.end(); I != E; ++I) {
-    assert(I->first->getPCHLevel() > I->second->getPCHLevel() &&
-           "Expected first & second to be in different PCHs");
-    AddDeclRef(I->first, FirstLatestDeclIDs);
-    AddDeclRef(I->second, FirstLatestDeclIDs);
-  }
-  if (!FirstLatestDeclIDs.empty())
-    Stream.EmitRecord(pch::REDECLS_UPDATE_LATEST, FirstLatestDeclIDs);
-
-  // Write the record containing external, unnamed definitions.
-  if (!ExternalDefinitions.empty())
-    Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions);
-
-  // Write the record containing tentative definitions.
-  if (!TentativeDefinitions.empty())
-    Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions);
-
-  // Write the record containing unused file scoped decls.
-  if (!UnusedFileScopedDecls.empty())
-    Stream.EmitRecord(pch::UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);
-
-  // Write the record containing weak undeclared identifiers.
-  if (!WeakUndeclaredIdentifiers.empty())
-    Stream.EmitRecord(pch::WEAK_UNDECLARED_IDENTIFIERS,
-                      WeakUndeclaredIdentifiers);
-
-  // Write the record containing locally-scoped external definitions.
-  if (!LocallyScopedExternalDecls.empty())
-    Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS,
-                      LocallyScopedExternalDecls);
-
-  // Write the record containing ext_vector type names.
-  if (!ExtVectorDecls.empty())
-    Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls);
-
-  // Write the record containing VTable uses information.
-  if (!VTableUses.empty())
-    Stream.EmitRecord(pch::VTABLE_USES, VTableUses);
-
-  // Write the record containing dynamic classes declarations.
-  if (!DynamicClasses.empty())
-    Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses);
-
-  // Write the record containing pending implicit instantiations.
-  if (!PendingImplicitInstantiations.empty())
-    Stream.EmitRecord(pch::PENDING_IMPLICIT_INSTANTIATIONS,
-                      PendingImplicitInstantiations);
-
-  // Write the record containing declaration references of Sema.
-  if (!SemaDeclRefs.empty())
-    Stream.EmitRecord(pch::SEMA_DECL_REFS, SemaDeclRefs);
-
-  Record.clear();
-  Record.push_back(NumStatements);
-  Record.push_back(NumMacros);
-  Record.push_back(NumLexicalDeclContexts);
-  Record.push_back(NumVisibleDeclContexts);
-  WriteDeclUpdateBlock();
-  Stream.EmitRecord(pch::STATISTICS, Record);
-  Stream.ExitBlock();
-}
-
-void PCHWriter::WriteDeclUpdateBlock() {
-  if (ReplacedDecls.empty())
-    return;
-
-  RecordData Record;
-  for (llvm::SmallVector<std::pair<pch::DeclID, uint64_t>, 16>::iterator
-           I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) {
-    Record.push_back(I->first);
-    Record.push_back(I->second);
-  }
-  Stream.EmitRecord(pch::DECL_REPLACEMENTS, Record);
-}
-
-void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
-  Record.push_back(Loc.getRawEncoding());
-}
-
-void PCHWriter::AddSourceRange(SourceRange Range, RecordData &Record) {
-  AddSourceLocation(Range.getBegin(), Record);
-  AddSourceLocation(Range.getEnd(), Record);
-}
-
-void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
-  Record.push_back(Value.getBitWidth());
-  unsigned N = Value.getNumWords();
-  const uint64_t* Words = Value.getRawData();
-  for (unsigned I = 0; I != N; ++I)
-    Record.push_back(Words[I]);
-}
-
-void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) {
-  Record.push_back(Value.isUnsigned());
-  AddAPInt(Value, Record);
-}
-
-void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) {
-  AddAPInt(Value.bitcastToAPInt(), Record);
-}
-
-void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
-  Record.push_back(getIdentifierRef(II));
-}
-
-pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) {
-  if (II == 0)
-    return 0;
-
-  pch::IdentID &ID = IdentifierIDs[II];
-  if (ID == 0)
-    ID = NextIdentID++;
-  return ID;
-}
-
-pch::IdentID PCHWriter::getMacroDefinitionID(MacroDefinition *MD) {
-  if (MD == 0)
-    return 0;
-  
-  pch::IdentID &ID = MacroDefinitions[MD];
-  if (ID == 0)
-    ID = MacroDefinitions.size();
-  return ID;
-}
-
-void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
-  Record.push_back(getSelectorRef(SelRef));
-}
-
-pch::SelectorID PCHWriter::getSelectorRef(Selector Sel) {
-  if (Sel.getAsOpaquePtr() == 0) {
-    return 0;
-  }
-
-  pch::SelectorID &SID = SelectorIDs[Sel];
-  if (SID == 0 && Chain) {
-    // This might trigger a ReadSelector callback, which will set the ID for
-    // this selector.
-    Chain->LoadSelector(Sel);
-  }
-  if (SID == 0) {
-    SID = NextSelectorID++;
-  }
-  return SID;
-}
-
-void PCHWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record) {
-  AddDeclRef(Temp->getDestructor(), Record);
-}
-
-void PCHWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
-                                           const TemplateArgumentLocInfo &Arg,
-                                           RecordData &Record) {
-  switch (Kind) {
-  case TemplateArgument::Expression:
-    AddStmt(Arg.getAsExpr());
-    break;
-  case TemplateArgument::Type:
-    AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record);
-    break;
-  case TemplateArgument::Template:
-    AddSourceRange(Arg.getTemplateQualifierRange(), Record);
-    AddSourceLocation(Arg.getTemplateNameLoc(), Record);
-    break;
-  case TemplateArgument::Null:
-  case TemplateArgument::Integral:
-  case TemplateArgument::Declaration:
-  case TemplateArgument::Pack:
-    break;
-  }
-}
-
-void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
-                                       RecordData &Record) {
-  AddTemplateArgument(Arg.getArgument(), Record);
-
-  if (Arg.getArgument().getKind() == TemplateArgument::Expression) {
-    bool InfoHasSameExpr
-      = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr();
-    Record.push_back(InfoHasSameExpr);
-    if (InfoHasSameExpr)
-      return; // Avoid storing the same expr twice.
-  }
-  AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo(),
-                             Record);
-}
-
-void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) {
-  if (TInfo == 0) {
-    AddTypeRef(QualType(), Record);
-    return;
-  }
-
-  AddTypeRef(TInfo->getType(), Record);
-  TypeLocWriter TLW(*this, Record);
-  for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
-    TLW.Visit(TL);
-}
-
-void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
-  if (T.isNull()) {
-    Record.push_back(pch::PREDEF_TYPE_NULL_ID);
-    return;
-  }
-
-  unsigned FastQuals = T.getLocalFastQualifiers();
-  T.removeFastQualifiers();
-
-  if (T.hasLocalNonFastQualifiers()) {
-    pch::TypeID &ID = TypeIDs[T];
-    if (ID == 0) {
-      // We haven't seen these qualifiers applied to this type before.
-      // Assign it a new ID.  This is the only time we enqueue a
-      // qualified type, and it has no CV qualifiers.
-      ID = NextTypeID++;
-      DeclTypesToEmit.push(T);
-    }
-
-    // Encode the type qualifiers in the type reference.
-    Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
-    return;
-  }
-
-  assert(!T.hasLocalQualifiers());
-
-  if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
-    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;
-    case BuiltinType::Char_U:     ID = pch::PREDEF_TYPE_CHAR_U_ID;     break;
-    case BuiltinType::UChar:      ID = pch::PREDEF_TYPE_UCHAR_ID;      break;
-    case BuiltinType::UShort:     ID = pch::PREDEF_TYPE_USHORT_ID;     break;
-    case BuiltinType::UInt:       ID = pch::PREDEF_TYPE_UINT_ID;       break;
-    case BuiltinType::ULong:      ID = pch::PREDEF_TYPE_ULONG_ID;      break;
-    case BuiltinType::ULongLong:  ID = pch::PREDEF_TYPE_ULONGLONG_ID;  break;
-    case BuiltinType::UInt128:    ID = pch::PREDEF_TYPE_UINT128_ID;    break;
-    case BuiltinType::Char_S:     ID = pch::PREDEF_TYPE_CHAR_S_ID;     break;
-    case BuiltinType::SChar:      ID = pch::PREDEF_TYPE_SCHAR_ID;      break;
-    case BuiltinType::WChar:      ID = pch::PREDEF_TYPE_WCHAR_ID;      break;
-    case BuiltinType::Short:      ID = pch::PREDEF_TYPE_SHORT_ID;      break;
-    case BuiltinType::Int:        ID = pch::PREDEF_TYPE_INT_ID;        break;
-    case BuiltinType::Long:       ID = pch::PREDEF_TYPE_LONG_ID;       break;
-    case BuiltinType::LongLong:   ID = pch::PREDEF_TYPE_LONGLONG_ID;   break;
-    case BuiltinType::Int128:     ID = pch::PREDEF_TYPE_INT128_ID;     break;
-    case BuiltinType::Float:      ID = pch::PREDEF_TYPE_FLOAT_ID;      break;
-    case BuiltinType::Double:     ID = pch::PREDEF_TYPE_DOUBLE_ID;     break;
-    case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
-    case BuiltinType::NullPtr:    ID = pch::PREDEF_TYPE_NULLPTR_ID;    break;
-    case BuiltinType::Char16:     ID = pch::PREDEF_TYPE_CHAR16_ID;     break;
-    case BuiltinType::Char32:     ID = pch::PREDEF_TYPE_CHAR32_ID;     break;
-    case BuiltinType::Overload:   ID = pch::PREDEF_TYPE_OVERLOAD_ID;   break;
-    case BuiltinType::Dependent:  ID = pch::PREDEF_TYPE_DEPENDENT_ID;  break;
-    case BuiltinType::ObjCId:     ID = pch::PREDEF_TYPE_OBJC_ID;       break;
-    case BuiltinType::ObjCClass:  ID = pch::PREDEF_TYPE_OBJC_CLASS;    break;
-    case BuiltinType::ObjCSel:    ID = pch::PREDEF_TYPE_OBJC_SEL;      break;
-    case BuiltinType::UndeducedAuto:
-      assert(0 && "Should not see undeduced auto here");
-      break;
-    }
-
-    Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
-    return;
-  }
-
-  pch::TypeID &ID = TypeIDs[T];
-  if (ID == 0) {
-    // We haven't seen this type before. Assign it a new ID and put it
-    // into the queue of types to emit.
-    ID = NextTypeID++;
-    DeclTypesToEmit.push(T);
-  }
-
-  // Encode the type qualifiers in the type reference.
-  Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
-}
-
-void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
-  Record.push_back(GetDeclRef(D));
-}
-
-pch::DeclID PCHWriter::GetDeclRef(const Decl *D) {
-  if (D == 0) {
-    return 0;
-  }
-
-  pch::DeclID &ID = DeclIDs[D];
-  if (ID == 0) {
-    // We haven't seen this declaration before. Give it a new ID and
-    // enqueue it in the list of declarations to emit.
-    ID = NextDeclID++;
-    DeclTypesToEmit.push(const_cast<Decl *>(D));
-  } else if (ID < FirstDeclID && D->isChangedSinceDeserialization()) {
-    // We don't add it to the replacement collection here, because we don't
-    // have the offset yet.
-    DeclTypesToEmit.push(const_cast<Decl *>(D));
-    // Reset the flag, so that we don't add this decl multiple times.
-    const_cast<Decl *>(D)->setChangedSinceDeserialization(false);
-  }
-
-  return ID;
-}
-
-pch::DeclID PCHWriter::getDeclID(const Decl *D) {
-  if (D == 0)
-    return 0;
-
-  assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!");
-  return DeclIDs[D];
-}
-
-void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
-  // FIXME: Emit a stable enum for NameKind.  0 = Identifier etc.
-  Record.push_back(Name.getNameKind());
-  switch (Name.getNameKind()) {
-  case DeclarationName::Identifier:
-    AddIdentifierRef(Name.getAsIdentifierInfo(), Record);
-    break;
-
-  case DeclarationName::ObjCZeroArgSelector:
-  case DeclarationName::ObjCOneArgSelector:
-  case DeclarationName::ObjCMultiArgSelector:
-    AddSelectorRef(Name.getObjCSelector(), Record);
-    break;
-
-  case DeclarationName::CXXConstructorName:
-  case DeclarationName::CXXDestructorName:
-  case DeclarationName::CXXConversionFunctionName:
-    AddTypeRef(Name.getCXXNameType(), Record);
-    break;
-
-  case DeclarationName::CXXOperatorName:
-    Record.push_back(Name.getCXXOverloadedOperator());
-    break;
-
-  case DeclarationName::CXXLiteralOperatorName:
-    AddIdentifierRef(Name.getCXXLiteralIdentifier(), Record);
-    break;
-
-  case DeclarationName::CXXUsingDirective:
-    // No extra data to emit
-    break;
-  }
-}
-
-void PCHWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
-                                       RecordData &Record) {
-  // Nested name specifiers usually aren't too long. I think that 8 would
-  // typically accomodate the vast majority.
-  llvm::SmallVector<NestedNameSpecifier *, 8> NestedNames;
-
-  // Push each of the NNS's onto a stack for serialization in reverse order.
-  while (NNS) {
-    NestedNames.push_back(NNS);
-    NNS = NNS->getPrefix();
-  }
-
-  Record.push_back(NestedNames.size());
-  while(!NestedNames.empty()) {
-    NNS = NestedNames.pop_back_val();
-    NestedNameSpecifier::SpecifierKind Kind = NNS->getKind();
-    Record.push_back(Kind);
-    switch (Kind) {
-    case NestedNameSpecifier::Identifier:
-      AddIdentifierRef(NNS->getAsIdentifier(), Record);
-      break;
-
-    case NestedNameSpecifier::Namespace:
-      AddDeclRef(NNS->getAsNamespace(), Record);
-      break;
-
-    case NestedNameSpecifier::TypeSpec:
-    case NestedNameSpecifier::TypeSpecWithTemplate:
-      AddTypeRef(QualType(NNS->getAsType(), 0), Record);
-      Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);
-      break;
-
-    case NestedNameSpecifier::Global:
-      // Don't need to write an associated value.
-      break;
-    }
-  }
-}
-
-void PCHWriter::AddTemplateName(TemplateName Name, RecordData &Record) {
-  TemplateName::NameKind Kind = Name.getKind(); 
-  Record.push_back(Kind);
-  switch (Kind) {
-  case TemplateName::Template:
-    AddDeclRef(Name.getAsTemplateDecl(), Record);
-    break;
-
-  case TemplateName::OverloadedTemplate: {
-    OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate();
-    Record.push_back(OvT->size());
-    for (OverloadedTemplateStorage::iterator I = OvT->begin(), E = OvT->end();
-           I != E; ++I)
-      AddDeclRef(*I, Record);
-    break;
-  }
-    
-  case TemplateName::QualifiedTemplate: {
-    QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName();
-    AddNestedNameSpecifier(QualT->getQualifier(), Record);
-    Record.push_back(QualT->hasTemplateKeyword());
-    AddDeclRef(QualT->getTemplateDecl(), Record);
-    break;
-  }
-    
-  case TemplateName::DependentTemplate: {
-    DependentTemplateName *DepT = Name.getAsDependentTemplateName();
-    AddNestedNameSpecifier(DepT->getQualifier(), Record);
-    Record.push_back(DepT->isIdentifier());
-    if (DepT->isIdentifier())
-      AddIdentifierRef(DepT->getIdentifier(), Record);
-    else
-      Record.push_back(DepT->getOperator());
-    break;
-  }
-  }
-}
-
-void PCHWriter::AddTemplateArgument(const TemplateArgument &Arg, 
-                                    RecordData &Record) {
-  Record.push_back(Arg.getKind());
-  switch (Arg.getKind()) {
-  case TemplateArgument::Null:
-    break;
-  case TemplateArgument::Type:
-    AddTypeRef(Arg.getAsType(), Record);
-    break;
-  case TemplateArgument::Declaration:
-    AddDeclRef(Arg.getAsDecl(), Record);
-    break;
-  case TemplateArgument::Integral:
-    AddAPSInt(*Arg.getAsIntegral(), Record);
-    AddTypeRef(Arg.getIntegralType(), Record);
-    break;
-  case TemplateArgument::Template:
-    AddTemplateName(Arg.getAsTemplate(), Record);
-    break;
-  case TemplateArgument::Expression:
-    AddStmt(Arg.getAsExpr());
-    break;
-  case TemplateArgument::Pack:
-    Record.push_back(Arg.pack_size());
-    for (TemplateArgument::pack_iterator I=Arg.pack_begin(), E=Arg.pack_end();
-           I != E; ++I)
-      AddTemplateArgument(*I, Record);
-    break;
-  }
-}
-
-void
-PCHWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams,
-                                    RecordData &Record) {
-  assert(TemplateParams && "No TemplateParams!");
-  AddSourceLocation(TemplateParams->getTemplateLoc(), Record);
-  AddSourceLocation(TemplateParams->getLAngleLoc(), Record);
-  AddSourceLocation(TemplateParams->getRAngleLoc(), Record);
-  Record.push_back(TemplateParams->size());
-  for (TemplateParameterList::const_iterator
-         P = TemplateParams->begin(), PEnd = TemplateParams->end();
-         P != PEnd; ++P)
-    AddDeclRef(*P, Record);
-}
-
-/// \brief Emit a template argument list.
-void
-PCHWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs,
-                                   RecordData &Record) {
-  assert(TemplateArgs && "No TemplateArgs!");
-  Record.push_back(TemplateArgs->flat_size());
-  for (int i=0, e = TemplateArgs->flat_size(); i != e; ++i)
-    AddTemplateArgument(TemplateArgs->get(i), Record);
-}
-
-
-void
-PCHWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record) {
-  Record.push_back(Set.size());
-  for (UnresolvedSetImpl::const_iterator
-         I = Set.begin(), E = Set.end(); I != E; ++I) {
-    AddDeclRef(I.getDecl(), Record);
-    Record.push_back(I.getAccess());
-  }
-}
-
-void PCHWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
-                                    RecordData &Record) {
-  Record.push_back(Base.isVirtual());
-  Record.push_back(Base.isBaseOfClass());
-  Record.push_back(Base.getAccessSpecifierAsWritten());
-  AddTypeSourceInfo(Base.getTypeSourceInfo(), Record);
-  AddSourceRange(Base.getSourceRange(), Record);
-}
-
-void PCHWriter::AddCXXBaseOrMemberInitializers(
-                        const CXXBaseOrMemberInitializer * const *BaseOrMembers,
-                        unsigned NumBaseOrMembers, RecordData &Record) {
-  Record.push_back(NumBaseOrMembers);
-  for (unsigned i=0; i != NumBaseOrMembers; ++i) {
-    const CXXBaseOrMemberInitializer *Init = BaseOrMembers[i];
-
-    Record.push_back(Init->isBaseInitializer());
-    if (Init->isBaseInitializer()) {
-      AddTypeSourceInfo(Init->getBaseClassInfo(), Record);
-      Record.push_back(Init->isBaseVirtual());
-    } else {
-      AddDeclRef(Init->getMember(), Record);
-    }
-    AddSourceLocation(Init->getMemberLocation(), Record);
-    AddStmt(Init->getInit());
-    AddDeclRef(Init->getAnonUnionMember(), Record);
-    AddSourceLocation(Init->getLParenLoc(), Record);
-    AddSourceLocation(Init->getRParenLoc(), Record);
-    Record.push_back(Init->isWritten());
-    if (Init->isWritten()) {
-      Record.push_back(Init->getSourceOrder());
-    } else {
-      Record.push_back(Init->getNumArrayIndices());
-      for (unsigned i=0, e=Init->getNumArrayIndices(); i != e; ++i)
-        AddDeclRef(Init->getArrayIndex(i), Record);
-    }
-  }
-}
-
-void PCHWriter::SetReader(PCHReader *Reader) {
-  assert(Reader && "Cannot remove chain");
-  assert(FirstDeclID == NextDeclID &&
-         FirstTypeID == NextTypeID &&
-         FirstIdentID == NextIdentID &&
-         FirstSelectorID == NextSelectorID &&
-         "Setting chain after writing has started.");
-  Chain = Reader;
-}
-
-void PCHWriter::IdentifierRead(pch::IdentID ID, IdentifierInfo *II) {
-  IdentifierIDs[II] = ID;
-}
-
-void PCHWriter::TypeRead(pch::TypeID ID, QualType T) {
-  TypeIDs[T] = ID;
-}
-
-void PCHWriter::DeclRead(pch::DeclID ID, const Decl *D) {
-  DeclIDs[D] = ID;
-}
-
-void PCHWriter::SelectorRead(pch::SelectorID ID, Selector S) {
-  SelectorIDs[S] = ID;
-}
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
deleted file mode 100644
index 9893d25..0000000
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ /dev/null
@@ -1,1174 +0,0 @@
-//===--- PCHWriterDecl.cpp - Declaration Serialization --------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements serialization for Declarations.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/PCHWriter.h"
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Bitcode/BitstreamWriter.h"
-#include "llvm/Support/ErrorHandling.h"
-using namespace clang;
-
-//===----------------------------------------------------------------------===//
-// Declaration serialization
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-  class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> {
-
-    PCHWriter &Writer;
-    ASTContext &Context;
-    PCHWriter::RecordData &Record;
-
-  public:
-    pch::DeclCode Code;
-    unsigned AbbrevToUse;
-
-    PCHDeclWriter(PCHWriter &Writer, ASTContext &Context,
-                  PCHWriter::RecordData &Record)
-      : Writer(Writer), Context(Context), Record(Record) {
-    }
-    
-    void Visit(Decl *D);
-
-    void VisitDecl(Decl *D);
-    void VisitTranslationUnitDecl(TranslationUnitDecl *D);
-    void VisitNamedDecl(NamedDecl *D);
-    void VisitNamespaceDecl(NamespaceDecl *D);
-    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
-    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
-    void VisitTypeDecl(TypeDecl *D);
-    void VisitTypedefDecl(TypedefDecl *D);
-    void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
-    void VisitTagDecl(TagDecl *D);
-    void VisitEnumDecl(EnumDecl *D);
-    void VisitRecordDecl(RecordDecl *D);
-    void VisitCXXRecordDecl(CXXRecordDecl *D);
-    void VisitClassTemplateSpecializationDecl(
-                                            ClassTemplateSpecializationDecl *D);
-    void VisitClassTemplatePartialSpecializationDecl(
-                                     ClassTemplatePartialSpecializationDecl *D);
-    void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
-    void VisitValueDecl(ValueDecl *D);
-    void VisitEnumConstantDecl(EnumConstantDecl *D);
-    void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
-    void VisitDeclaratorDecl(DeclaratorDecl *D);
-    void VisitFunctionDecl(FunctionDecl *D);
-    void VisitCXXMethodDecl(CXXMethodDecl *D);
-    void VisitCXXConstructorDecl(CXXConstructorDecl *D);
-    void VisitCXXDestructorDecl(CXXDestructorDecl *D);
-    void VisitCXXConversionDecl(CXXConversionDecl *D);
-    void VisitFieldDecl(FieldDecl *D);
-    void VisitVarDecl(VarDecl *D);
-    void VisitImplicitParamDecl(ImplicitParamDecl *D);
-    void VisitParmVarDecl(ParmVarDecl *D);
-    void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
-    void VisitTemplateDecl(TemplateDecl *D);
-    void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
-    void VisitClassTemplateDecl(ClassTemplateDecl *D);
-    void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
-    void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
-    void VisitUsingDecl(UsingDecl *D);
-    void VisitUsingShadowDecl(UsingShadowDecl *D);
-    void VisitLinkageSpecDecl(LinkageSpecDecl *D);
-    void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
-    void VisitAccessSpecDecl(AccessSpecDecl *D);
-    void VisitFriendDecl(FriendDecl *D);
-    void VisitFriendTemplateDecl(FriendTemplateDecl *D);
-    void VisitStaticAssertDecl(StaticAssertDecl *D);
-    void VisitBlockDecl(BlockDecl *D);
-
-    void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
-                          uint64_t VisibleOffset);
-    template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
-
-
-    // FIXME: Put in the same order is DeclNodes.td?
-    void VisitObjCMethodDecl(ObjCMethodDecl *D);
-    void VisitObjCContainerDecl(ObjCContainerDecl *D);
-    void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
-    void VisitObjCIvarDecl(ObjCIvarDecl *D);
-    void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
-    void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
-    void VisitObjCClassDecl(ObjCClassDecl *D);
-    void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
-    void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
-    void VisitObjCImplDecl(ObjCImplDecl *D);
-    void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
-    void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
-    void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
-    void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
-    void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
-  };
-}
-
-void PCHDeclWriter::Visit(Decl *D) {
-  DeclVisitor<PCHDeclWriter>::Visit(D);
-
-  // Handle FunctionDecl's body here and write it after all other Stmts/Exprs
-  // have been written. We want it last because we will not read it back when
-  // retrieving it from the PCH, we'll just lazily set the offset. 
-  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    Record.push_back(FD->isThisDeclarationADefinition());
-    if (FD->isThisDeclarationADefinition())
-      Writer.AddStmt(FD->getBody());
-  }
-}
-
-void PCHDeclWriter::VisitDecl(Decl *D) {
-  Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
-  Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
-  Writer.AddSourceLocation(D->getLocation(), Record);
-  Record.push_back(D->isInvalidDecl());
-  Record.push_back(D->hasAttrs());
-  Record.push_back(D->isImplicit());
-  Record.push_back(D->isUsed(false));
-  Record.push_back(D->getAccess());
-  Record.push_back(D->getPCHLevel());
-}
-
-void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
-  VisitDecl(D);
-  Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
-  Code = pch::DECL_TRANSLATION_UNIT;
-}
-
-void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
-  VisitDecl(D);
-  Writer.AddDeclarationName(D->getDeclName(), Record);
-}
-
-void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
-}
-
-void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
-  VisitTypeDecl(D);
-  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
-  Code = pch::DECL_TYPEDEF;
-}
-
-void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
-  VisitTypeDecl(D);
-  Record.push_back(D->getIdentifierNamespace());
-  VisitRedeclarable(D);
-  Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
-  Record.push_back(D->isDefinition());
-  Record.push_back(D->isEmbeddedInDeclarator());
-  Writer.AddSourceLocation(D->getRBraceLoc(), Record);
-  Writer.AddSourceLocation(D->getTagKeywordLoc(), Record);
-  // FIXME: maybe write optional qualifier and its range.
-  Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
-}
-
-void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
-  VisitTagDecl(D);
-  Writer.AddTypeRef(D->getIntegerType(), Record);
-  Writer.AddTypeRef(D->getPromotionType(), Record);
-  Record.push_back(D->getNumPositiveBits());
-  Record.push_back(D->getNumNegativeBits());
-  Writer.AddDeclRef(D->getInstantiatedFromMemberEnum(), Record);
-  Code = pch::DECL_ENUM;
-}
-
-void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
-  VisitTagDecl(D);
-  Record.push_back(D->hasFlexibleArrayMember());
-  Record.push_back(D->isAnonymousStructOrUnion());
-  Record.push_back(D->hasObjectMember());
-  Code = pch::DECL_RECORD;
-}
-
-void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddTypeRef(D->getType(), Record);
-}
-
-void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
-  VisitValueDecl(D);
-  Record.push_back(D->getInitExpr()? 1 : 0);
-  if (D->getInitExpr())
-    Writer.AddStmt(D->getInitExpr());
-  Writer.AddAPSInt(D->getInitVal(), Record);
-  Code = pch::DECL_ENUM_CONSTANT;
-}
-
-void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
-  VisitValueDecl(D);
-  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
-  // FIXME: write optional qualifier and its range.
-}
-
-void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  VisitDeclaratorDecl(D);
-  // FIXME: write DeclarationNameLoc.
-
-  Record.push_back(D->getIdentifierNamespace());
-  Record.push_back(D->getTemplatedKind());
-  switch (D->getTemplatedKind()) {
-  default: assert(false && "Unhandled TemplatedKind!");
-    break;
-  case FunctionDecl::TK_NonTemplate:
-    break;
-  case FunctionDecl::TK_FunctionTemplate:
-    Writer.AddDeclRef(D->getDescribedFunctionTemplate(), Record);
-    break;
-  case FunctionDecl::TK_MemberSpecialization: {
-    MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo();
-    Writer.AddDeclRef(MemberInfo->getInstantiatedFrom(), Record);
-    Record.push_back(MemberInfo->getTemplateSpecializationKind());
-    Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record);
-    break;
-  }
-  case FunctionDecl::TK_FunctionTemplateSpecialization: {
-    FunctionTemplateSpecializationInfo *
-      FTSInfo = D->getTemplateSpecializationInfo();
-    // We want it canonical to guarantee that it has a Common*.
-    Writer.AddDeclRef(FTSInfo->getTemplate()->getCanonicalDecl(), Record);
-    Record.push_back(FTSInfo->getTemplateSpecializationKind());
-    
-    // Template arguments.
-    Writer.AddTemplateArgumentList(FTSInfo->TemplateArguments, Record);
-    
-    // Template args as written.
-    Record.push_back(FTSInfo->TemplateArgumentsAsWritten != 0);
-    if (FTSInfo->TemplateArgumentsAsWritten) {
-      Record.push_back(FTSInfo->TemplateArgumentsAsWritten->size());
-      for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->size(); i!=e; ++i)
-        Writer.AddTemplateArgumentLoc((*FTSInfo->TemplateArgumentsAsWritten)[i],
-                                      Record);
-      Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getLAngleLoc(),
-                               Record);
-      Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getRAngleLoc(),
-                               Record);
-    }
-    
-    Writer.AddSourceLocation(FTSInfo->getPointOfInstantiation(), Record);
-    break;
-  }
-  case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
-    DependentFunctionTemplateSpecializationInfo *
-      DFTSInfo = D->getDependentSpecializationInfo();
-    
-    // Templates.
-    Record.push_back(DFTSInfo->getNumTemplates());
-    for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i)
-      Writer.AddDeclRef(DFTSInfo->getTemplate(i), Record);
-    
-    // Templates args.
-    Record.push_back(DFTSInfo->getNumTemplateArgs());
-    for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i)
-      Writer.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i), Record);
-    Writer.AddSourceLocation(DFTSInfo->getLAngleLoc(), Record);
-    Writer.AddSourceLocation(DFTSInfo->getRAngleLoc(), Record);
-    break;
-  }
-  }
-
-  // FunctionDecl's body is handled last at PCHWriterDecl::Visit,
-  // after everything else is written.
-
-  VisitRedeclarable(D);
-  Record.push_back(D->getStorageClass()); // FIXME: stable encoding
-  Record.push_back(D->getStorageClassAsWritten());
-  Record.push_back(D->isInlineSpecified());
-  Record.push_back(D->isVirtualAsWritten());
-  Record.push_back(D->isPure());
-  Record.push_back(D->hasInheritedPrototype());
-  Record.push_back(D->hasWrittenPrototype());
-  Record.push_back(D->isDeleted());
-  Record.push_back(D->isTrivial());
-  Record.push_back(D->isCopyAssignment());
-  Record.push_back(D->hasImplicitReturnZero());
-  Writer.AddSourceLocation(D->getLocEnd(), Record);
-
-  Record.push_back(D->param_size());
-  for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
-       P != PEnd; ++P)
-    Writer.AddDeclRef(*P, Record);
-  Code = pch::DECL_FUNCTION;
-}
-
-void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
-  VisitNamedDecl(D);
-  // FIXME: convert to LazyStmtPtr?
-  // Unlike C/C++, method bodies will never be in header files.
-  bool HasBodyStuff = D->getBody() != 0     ||
-                      D->getSelfDecl() != 0 || D->getCmdDecl() != 0;
-  Record.push_back(HasBodyStuff);
-  if (HasBodyStuff) {
-    Writer.AddStmt(D->getBody());
-    Writer.AddDeclRef(D->getSelfDecl(), Record);
-    Writer.AddDeclRef(D->getCmdDecl(), Record);
-  }
-  Record.push_back(D->isInstanceMethod());
-  Record.push_back(D->isVariadic());
-  Record.push_back(D->isSynthesized());
-  Record.push_back(D->isDefined());
-  // FIXME: stable encoding for @required/@optional
-  Record.push_back(D->getImplementationControl());
-  // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
-  Record.push_back(D->getObjCDeclQualifier());
-  Record.push_back(D->getNumSelectorArgs());
-  Writer.AddTypeRef(D->getResultType(), Record);
-  Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record);
-  Writer.AddSourceLocation(D->getLocEnd(), Record);
-  Record.push_back(D->param_size());
-  for (ObjCMethodDecl::param_iterator P = D->param_begin(),
-                                   PEnd = D->param_end(); P != PEnd; ++P)
-    Writer.AddDeclRef(*P, Record);
-  Code = pch::DECL_OBJC_METHOD;
-}
-
-void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddSourceRange(D->getAtEndRange(), Record);
-  // Abstract class (no need to define a stable pch::DECL code).
-}
-
-void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
-  VisitObjCContainerDecl(D);
-  Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
-  Writer.AddDeclRef(D->getSuperClass(), Record);
-  Record.push_back(D->protocol_size());
-  for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
-         PEnd = D->protocol_end();
-       P != PEnd; ++P)
-    Writer.AddDeclRef(*P, Record);
-  for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
-         PLEnd = D->protocol_loc_end();
-       PL != PLEnd; ++PL)
-    Writer.AddSourceLocation(*PL, Record);
-  Record.push_back(D->ivar_size());
-  for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
-                                     IEnd = D->ivar_end(); I != IEnd; ++I)
-    Writer.AddDeclRef(*I, Record);
-  Writer.AddDeclRef(D->getCategoryList(), Record);
-  Record.push_back(D->isForwardDecl());
-  Record.push_back(D->isImplicitInterfaceDecl());
-  Writer.AddSourceLocation(D->getClassLoc(), Record);
-  Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
-  Writer.AddSourceLocation(D->getLocEnd(), Record);
-  Code = pch::DECL_OBJC_INTERFACE;
-}
-
-void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
-  VisitFieldDecl(D);
-  // FIXME: stable encoding for @public/@private/@protected/@package
-  Record.push_back(D->getAccessControl());
-  Record.push_back(D->getSynthesize());
-  Code = pch::DECL_OBJC_IVAR;
-}
-
-void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
-  VisitObjCContainerDecl(D);
-  Record.push_back(D->isForwardDecl());
-  Writer.AddSourceLocation(D->getLocEnd(), Record);
-  Record.push_back(D->protocol_size());
-  for (ObjCProtocolDecl::protocol_iterator
-       I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
-    Writer.AddDeclRef(*I, Record);
-  for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
-         PLEnd = D->protocol_loc_end();
-       PL != PLEnd; ++PL)
-    Writer.AddSourceLocation(*PL, Record);
-  Code = pch::DECL_OBJC_PROTOCOL;
-}
-
-void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
-  VisitFieldDecl(D);
-  Code = pch::DECL_OBJC_AT_DEFS_FIELD;
-}
-
-void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
-  VisitDecl(D);
-  Record.push_back(D->size());
-  for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
-    Writer.AddDeclRef(I->getInterface(), Record);
-  for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
-    Writer.AddSourceLocation(I->getLocation(), Record);
-  Code = pch::DECL_OBJC_CLASS;
-}
-
-void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
-  VisitDecl(D);
-  Record.push_back(D->protocol_size());
-  for (ObjCForwardProtocolDecl::protocol_iterator
-       I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
-    Writer.AddDeclRef(*I, Record);
-  for (ObjCForwardProtocolDecl::protocol_loc_iterator 
-         PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
-       PL != PLEnd; ++PL)
-    Writer.AddSourceLocation(*PL, Record);
-  Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
-}
-
-void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
-  VisitObjCContainerDecl(D);
-  Writer.AddDeclRef(D->getClassInterface(), Record);
-  Record.push_back(D->protocol_size());
-  for (ObjCCategoryDecl::protocol_iterator
-       I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
-    Writer.AddDeclRef(*I, Record);
-  for (ObjCCategoryDecl::protocol_loc_iterator 
-         PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
-       PL != PLEnd; ++PL)
-    Writer.AddSourceLocation(*PL, Record);
-  Writer.AddDeclRef(D->getNextClassCategory(), Record);
-  Writer.AddSourceLocation(D->getAtLoc(), Record);
-  Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
-  Code = pch::DECL_OBJC_CATEGORY;
-}
-
-void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddDeclRef(D->getClassInterface(), Record);
-  Code = pch::DECL_OBJC_COMPATIBLE_ALIAS;
-}
-
-void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddSourceLocation(D->getAtLoc(), Record);
-  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
-  // FIXME: stable encoding
-  Record.push_back((unsigned)D->getPropertyAttributes());
-  Record.push_back((unsigned)D->getPropertyAttributesAsWritten());
-  // FIXME: stable encoding
-  Record.push_back((unsigned)D->getPropertyImplementation());
-  Writer.AddDeclarationName(D->getGetterName(), Record);
-  Writer.AddDeclarationName(D->getSetterName(), Record);
-  Writer.AddDeclRef(D->getGetterMethodDecl(), Record);
-  Writer.AddDeclRef(D->getSetterMethodDecl(), Record);
-  Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
-  Code = pch::DECL_OBJC_PROPERTY;
-}
-
-void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
-  VisitObjCContainerDecl(D);
-  Writer.AddDeclRef(D->getClassInterface(), Record);
-  // Abstract class (no need to define a stable pch::DECL code).
-}
-
-void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
-  VisitObjCImplDecl(D);
-  Writer.AddIdentifierRef(D->getIdentifier(), Record);
-  Code = pch::DECL_OBJC_CATEGORY_IMPL;
-}
-
-void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
-  VisitObjCImplDecl(D);
-  Writer.AddDeclRef(D->getSuperClass(), Record);
-  Writer.AddCXXBaseOrMemberInitializers(D->IvarInitializers,
-                                        D->NumIvarInitializers, Record);
-  Code = pch::DECL_OBJC_IMPLEMENTATION;
-}
-
-void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
-  VisitDecl(D);
-  Writer.AddSourceLocation(D->getLocStart(), Record);
-  Writer.AddDeclRef(D->getPropertyDecl(), Record);
-  Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
-  Writer.AddStmt(D->getGetterCXXConstructor());
-  Writer.AddStmt(D->getSetterCXXAssignment());
-  Code = pch::DECL_OBJC_PROPERTY_IMPL;
-}
-
-void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
-  VisitDeclaratorDecl(D);
-  Record.push_back(D->isMutable());
-  Record.push_back(D->getBitWidth()? 1 : 0);
-  if (D->getBitWidth())
-    Writer.AddStmt(D->getBitWidth());
-  if (!D->getDeclName())
-    Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record);
-  Code = pch::DECL_FIELD;
-}
-
-void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
-  VisitDeclaratorDecl(D);
-  Record.push_back(D->getStorageClass()); // FIXME: stable encoding
-  Record.push_back(D->getStorageClassAsWritten());
-  Record.push_back(D->isThreadSpecified());
-  Record.push_back(D->hasCXXDirectInitializer());
-  Record.push_back(D->isExceptionVariable());
-  Record.push_back(D->isNRVOVariable());
-  VisitRedeclarable(D);
-  Record.push_back(D->getInit() ? 1 : 0);
-  if (D->getInit())
-    Writer.AddStmt(D->getInit());
-
-  MemberSpecializationInfo *SpecInfo
-    = D->isStaticDataMember() ? D->getMemberSpecializationInfo() : 0;
-  Record.push_back(SpecInfo != 0);
-  if (SpecInfo) {
-    Writer.AddDeclRef(SpecInfo->getInstantiatedFrom(), Record);
-    Record.push_back(SpecInfo->getTemplateSpecializationKind());
-    Writer.AddSourceLocation(SpecInfo->getPointOfInstantiation(), Record);
-  }
-
-  Code = pch::DECL_VAR;
-}
-
-void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
-  VisitVarDecl(D);
-  Code = pch::DECL_IMPLICIT_PARAM;
-}
-
-void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
-  VisitVarDecl(D);
-  Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
-  Record.push_back(D->hasInheritedDefaultArg());
-  Record.push_back(D->hasUninstantiatedDefaultArg());
-  if (D->hasUninstantiatedDefaultArg())
-    Writer.AddStmt(D->getUninstantiatedDefaultArg());
-  Code = pch::DECL_PARM_VAR;
-
-  // If the assumptions about the DECL_PARM_VAR abbrev are true, use it.  Here
-  // we dynamically check for the properties that we optimize for, but don't
-  // know are true of all PARM_VAR_DECLs.
-  if (!D->getTypeSourceInfo() &&
-      !D->hasAttrs() &&
-      !D->isImplicit() &&
-      !D->isUsed(false) &&
-      D->getAccess() == AS_none &&
-      D->getPCHLevel() == 0 &&
-      D->getStorageClass() == 0 &&
-      !D->hasCXXDirectInitializer() && // Can params have this ever?
-      D->getObjCDeclQualifier() == 0 &&
-      !D->hasInheritedDefaultArg() &&
-      D->getInit() == 0 &&
-      !D->hasUninstantiatedDefaultArg())  // No default expr.
-    AbbrevToUse = Writer.getParmVarDeclAbbrev();
-
-  // Check things we know are true of *every* PARM_VAR_DECL, which is more than
-  // just us assuming it.
-  assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls");
-  assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
-  assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
-  assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
-  assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
-  assert(!D->isStaticDataMember() &&
-         "PARM_VAR_DECL can't be static data member");
-}
-
-void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
-  VisitDecl(D);
-  Writer.AddStmt(D->getAsmString());
-  Code = pch::DECL_FILE_SCOPE_ASM;
-}
-
-void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
-  VisitDecl(D);
-  Writer.AddStmt(D->getBody());
-  Writer.AddTypeSourceInfo(D->getSignatureAsWritten(), Record);
-  Record.push_back(D->param_size());
-  for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
-       P != PEnd; ++P)
-    Writer.AddDeclRef(*P, Record);
-  Code = pch::DECL_BLOCK;
-}
-
-void PCHDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  VisitDecl(D);
-  // FIXME: It might be nice to serialize the brace locations for this
-  // declaration, which don't seem to be readily available in the AST.
-  Record.push_back(D->getLanguage());
-  Record.push_back(D->hasBraces());
-  Code = pch::DECL_LINKAGE_SPEC;
-}
-
-void PCHDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddSourceLocation(D->getLBracLoc(), Record);
-  Writer.AddSourceLocation(D->getRBracLoc(), Record);
-  Writer.AddDeclRef(D->getNextNamespace(), Record);
-
-  // Only write one reference--original or anonymous
-  Record.push_back(D->isOriginalNamespace());
-  if (D->isOriginalNamespace())
-    Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
-  else
-    Writer.AddDeclRef(D->getOriginalNamespace(), Record);
-  Code = pch::DECL_NAMESPACE;
-
-  if (Writer.hasChain() && !D->isOriginalNamespace() &&
-      D->getOriginalNamespace()->getPCHLevel() > 0) {
-    Writer.AddUpdatedNamespace(D->getOriginalNamespace());
-  }
-}
-
-void PCHDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddSourceLocation(D->getAliasLoc(), Record);
-  Writer.AddSourceRange(D->getQualifierRange(), Record);
-  Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
-  Writer.AddSourceLocation(D->getTargetNameLoc(), Record);
-  Writer.AddDeclRef(D->getNamespace(), Record);
-  Code = pch::DECL_NAMESPACE_ALIAS;
-}
-
-void PCHDeclWriter::VisitUsingDecl(UsingDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddSourceRange(D->getNestedNameRange(), Record);
-  Writer.AddSourceLocation(D->getUsingLocation(), Record);
-  Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record);
-  Record.push_back(D->getNumShadowDecls());
-  for (UsingDecl::shadow_iterator P = D->shadow_begin(),
-       PEnd = D->shadow_end(); P != PEnd; ++P)
-    Writer.AddDeclRef(*P, Record);
-  Record.push_back(D->isTypeName());
-  Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record);
-  Code = pch::DECL_USING;
-}
-
-void PCHDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddDeclRef(D->getTargetDecl(), Record);
-  Writer.AddDeclRef(D->getUsingDecl(), Record);
-  Writer.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D), Record);
-  Code = pch::DECL_USING_SHADOW;
-}
-
-void PCHDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record);
-  Writer.AddSourceRange(D->getQualifierRange(), Record);
-  Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
-  Writer.AddSourceLocation(D->getIdentLocation(), Record);
-  Writer.AddDeclRef(D->getNominatedNamespace(), Record);
-  Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record);
-  Code = pch::DECL_USING_DIRECTIVE;
-}
-
-void PCHDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
-  VisitValueDecl(D);
-  Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
-  Writer.AddSourceLocation(D->getUsingLoc(), Record);
-  Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
-  Code = pch::DECL_UNRESOLVED_USING_VALUE;
-}
-
-void PCHDeclWriter::VisitUnresolvedUsingTypenameDecl(
-                                               UnresolvedUsingTypenameDecl *D) {
-  VisitTypeDecl(D);
-  Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
-  Writer.AddSourceLocation(D->getUsingLoc(), Record);
-  Writer.AddSourceLocation(D->getTypenameLoc(), Record);
-  Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
-  Code = pch::DECL_UNRESOLVED_USING_TYPENAME;
-}
-
-void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
-  // See comments at PCHDeclReader::VisitCXXRecordDecl about why this happens
-  // before VisitRecordDecl.
-  enum { Data_NoDefData, Data_Owner, Data_NotOwner };
-  bool OwnsDefinitionData = false;
-  if (D->DefinitionData) {
-    assert(D->DefinitionData->Definition &&
-           "DefinitionData don't point to a definition decl!");
-    OwnsDefinitionData = D->DefinitionData->Definition == D;
-    if (OwnsDefinitionData) {
-      Record.push_back(Data_Owner);
-    } else {
-      Record.push_back(Data_NotOwner);
-      Writer.AddDeclRef(D->DefinitionData->Definition, Record);
-    }
-  } else
-    Record.push_back(Data_NoDefData);
-
-  VisitRecordDecl(D);
-
-  if (OwnsDefinitionData) {
-    assert(D->DefinitionData);
-    struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData;
-
-    Record.push_back(Data.UserDeclaredConstructor);
-    Record.push_back(Data.UserDeclaredCopyConstructor);
-    Record.push_back(Data.UserDeclaredCopyAssignment);
-    Record.push_back(Data.UserDeclaredDestructor);
-    Record.push_back(Data.Aggregate);
-    Record.push_back(Data.PlainOldData);
-    Record.push_back(Data.Empty);
-    Record.push_back(Data.Polymorphic);
-    Record.push_back(Data.Abstract);
-    Record.push_back(Data.HasTrivialConstructor);
-    Record.push_back(Data.HasTrivialCopyConstructor);
-    Record.push_back(Data.HasTrivialCopyAssignment);
-    Record.push_back(Data.HasTrivialDestructor);
-    Record.push_back(Data.ComputedVisibleConversions);
-    Record.push_back(Data.DeclaredDefaultConstructor);
-    Record.push_back(Data.DeclaredCopyConstructor);
-    Record.push_back(Data.DeclaredCopyAssignment);
-    Record.push_back(Data.DeclaredDestructor);
-
-    Record.push_back(D->getNumBases());
-    for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
-           E = D->bases_end(); I != E; ++I)
-      Writer.AddCXXBaseSpecifier(*I, Record);
-
-    // FIXME: Make VBases lazily computed when needed to avoid storing them.
-    Record.push_back(D->getNumVBases());
-    for (CXXRecordDecl::base_class_iterator I = D->vbases_begin(),
-           E = D->vbases_end(); I != E; ++I)
-      Writer.AddCXXBaseSpecifier(*I, Record);
-
-    Writer.AddUnresolvedSet(Data.Conversions, Record);
-    Writer.AddUnresolvedSet(Data.VisibleConversions, Record);
-    // Data.Definition is written at the top. 
-    Writer.AddDeclRef(Data.FirstFriend, Record);
-  }
-
-  enum {
-    CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
-  };
-  if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) {
-    Record.push_back(CXXRecTemplate);
-    Writer.AddDeclRef(TemplD, Record);
-  } else if (MemberSpecializationInfo *MSInfo
-               = D->getMemberSpecializationInfo()) {
-    Record.push_back(CXXRecMemberSpecialization);
-    Writer.AddDeclRef(MSInfo->getInstantiatedFrom(), Record);
-    Record.push_back(MSInfo->getTemplateSpecializationKind());
-    Writer.AddSourceLocation(MSInfo->getPointOfInstantiation(), Record);
-  } else {
-    Record.push_back(CXXRecNotTemplate);
-  }
-
-  Code = pch::DECL_CXX_RECORD;
-}
-
-void PCHDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
-  VisitFunctionDecl(D);
-  Record.push_back(D->size_overridden_methods());
-  for (CXXMethodDecl::method_iterator
-         I = D->begin_overridden_methods(), E = D->end_overridden_methods();
-         I != E; ++I)
-    Writer.AddDeclRef(*I, Record);
-  Code = pch::DECL_CXX_METHOD;
-}
-
-void PCHDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  VisitCXXMethodDecl(D);
-
-  Record.push_back(D->IsExplicitSpecified);
-  Record.push_back(D->ImplicitlyDefined);
-  Writer.AddCXXBaseOrMemberInitializers(D->BaseOrMemberInitializers,
-                                        D->NumBaseOrMemberInitializers, Record);
-
-  Code = pch::DECL_CXX_CONSTRUCTOR;
-}
-
-void PCHDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
-  VisitCXXMethodDecl(D);
-
-  Record.push_back(D->ImplicitlyDefined);
-  Writer.AddDeclRef(D->OperatorDelete, Record);
-
-  Code = pch::DECL_CXX_DESTRUCTOR;
-}
-
-void PCHDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
-  VisitCXXMethodDecl(D);
-  Record.push_back(D->IsExplicitSpecified);
-  Code = pch::DECL_CXX_CONVERSION;
-}
-
-void PCHDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) {
-  VisitDecl(D);
-  Writer.AddSourceLocation(D->getColonLoc(), Record);
-  Code = pch::DECL_ACCESS_SPEC;
-}
-
-void PCHDeclWriter::VisitFriendDecl(FriendDecl *D) {
-  VisitDecl(D);
-  Record.push_back(D->Friend.is<TypeSourceInfo*>());
-  if (D->Friend.is<TypeSourceInfo*>())
-    Writer.AddTypeSourceInfo(D->Friend.get<TypeSourceInfo*>(), Record);
-  else
-    Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record);
-  Writer.AddDeclRef(D->NextFriend, Record);
-  Writer.AddSourceLocation(D->FriendLoc, Record);
-  Code = pch::DECL_FRIEND;
-}
-
-void PCHDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
-  VisitDecl(D);
-  Record.push_back(D->getNumTemplateParameters());
-  for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i)
-    Writer.AddTemplateParameterList(D->getTemplateParameterList(i), Record);
-  Record.push_back(D->getFriendDecl() != 0);
-  if (D->getFriendDecl())
-    Writer.AddDeclRef(D->getFriendDecl(), Record);
-  else
-    Writer.AddTypeSourceInfo(D->getFriendType(), Record);
-  Writer.AddSourceLocation(D->getFriendLoc(), Record);
-  Code = pch::DECL_FRIEND_TEMPLATE;
-}
-
-void PCHDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
-  VisitNamedDecl(D);
-
-  Writer.AddDeclRef(D->getTemplatedDecl(), Record);
-  Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
-}
-
-void PCHDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
-  VisitTemplateDecl(D);
-
-  Record.push_back(D->getIdentifierNamespace());
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
-  if (D->getPreviousDeclaration() == 0) {
-    // This TemplateDecl owns the CommonPtr; write it.
-    assert(D->isCanonicalDecl());
-
-    Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
-    if (D->getInstantiatedFromMemberTemplate())
-      Record.push_back(D->isMemberSpecialization());
-
-    Writer.AddDeclRef(D->getCommonPtr()->Latest, Record);
-  } else {
-    RedeclarableTemplateDecl *First = D->getFirstDeclaration();
-    assert(First != D);
-    // If this is a most recent redeclaration that is pointed to by a first decl
-    // in a chained PCH, keep track of the association with the map so we can
-    // update the first decl during PCH reading.
-    if (First->getMostRecentDeclaration() == D &&
-        First->getPCHLevel() > D->getPCHLevel()) {
-      assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end()
-             && "The latest is already set");
-      Writer.FirstLatestDecls[First] = D;
-    }
-  }
-}
-
-void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
-  VisitRedeclarableTemplateDecl(D);
-
-  if (D->getPreviousDeclaration() == 0) {
-    typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
-    CTSDSetTy &CTSDSet = D->getSpecializations();
-    Record.push_back(CTSDSet.size());
-    for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) {
-      assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
-      Writer.AddDeclRef(&*I, Record);
-    }
-
-    typedef llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> CTPSDSetTy;
-    CTPSDSetTy &CTPSDSet = D->getPartialSpecializations();
-    Record.push_back(CTPSDSet.size());
-    for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) {
-      assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
-      Writer.AddDeclRef(&*I, Record); 
-    }
-
-    // InjectedClassNameType is computed, no need to write it.
-  }
-  Code = pch::DECL_CLASS_TEMPLATE;
-}
-
-void PCHDeclWriter::VisitClassTemplateSpecializationDecl(
-                                           ClassTemplateSpecializationDecl *D) {
-  VisitCXXRecordDecl(D);
-
-  llvm::PointerUnion<ClassTemplateDecl *,
-                     ClassTemplatePartialSpecializationDecl *> InstFrom
-    = D->getSpecializedTemplateOrPartial();
-  if (InstFrom.is<ClassTemplateDecl *>()) {
-    Writer.AddDeclRef(InstFrom.get<ClassTemplateDecl *>(), Record);
-  } else {
-    Writer.AddDeclRef(InstFrom.get<ClassTemplatePartialSpecializationDecl *>(),
-                      Record);
-    Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record);
-  }
-
-  // Explicit info.
-  Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record);
-  if (D->getTypeAsWritten()) {
-    Writer.AddSourceLocation(D->getExternLoc(), Record);
-    Writer.AddSourceLocation(D->getTemplateKeywordLoc(), Record);
-  }
-
-  Writer.AddTemplateArgumentList(&D->getTemplateArgs(), Record);
-  Writer.AddSourceLocation(D->getPointOfInstantiation(), Record);
-  Record.push_back(D->getSpecializationKind());
-
-  if (D->isCanonicalDecl()) {
-    // When reading, we'll add it to the folding set of the following template. 
-    Writer.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl(), Record);
-  }
-
-  Code = pch::DECL_CLASS_TEMPLATE_SPECIALIZATION;
-}
-
-void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl(
-                                    ClassTemplatePartialSpecializationDecl *D) {
-  VisitClassTemplateSpecializationDecl(D);
-
-  Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
-
-  Record.push_back(D->getNumTemplateArgsAsWritten());
-  for (int i = 0, e = D->getNumTemplateArgsAsWritten(); i != e; ++i)
-    Writer.AddTemplateArgumentLoc(D->getTemplateArgsAsWritten()[i], Record);
-
-  Record.push_back(D->getSequenceNumber());
-
-  // These are read/set from/to the first declaration.
-  if (D->getPreviousDeclaration() == 0) {
-    Writer.AddDeclRef(D->getInstantiatedFromMember(), Record);
-    Record.push_back(D->isMemberSpecialization());
-  }
-
-  Code = pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
-}
-
-void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
-  VisitRedeclarableTemplateDecl(D);
-
-  if (D->getPreviousDeclaration() == 0) {
-    // This FunctionTemplateDecl owns the CommonPtr; write it.
-
-    // Write the function specialization declarations.
-    Record.push_back(D->getSpecializations().size());
-    for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
-           I = D->getSpecializations().begin(),
-           E = D->getSpecializations().end()   ; I != E; ++I) {
-      assert(I->Function->isCanonicalDecl() &&
-             "Expected only canonical decls in set");
-      Writer.AddDeclRef(I->Function, Record);
-    }
-  }
-  Code = pch::DECL_FUNCTION_TEMPLATE;
-}
-
-void PCHDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
-  VisitTypeDecl(D);
-
-  Record.push_back(D->wasDeclaredWithTypename());
-  Record.push_back(D->isParameterPack());
-  Record.push_back(D->defaultArgumentWasInherited());
-  Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record);
-
-  Code = pch::DECL_TEMPLATE_TYPE_PARM;
-}
-
-void PCHDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
-  VisitVarDecl(D);
-  // TemplateParmPosition.
-  Record.push_back(D->getDepth());
-  Record.push_back(D->getPosition());
-  // Rest of NonTypeTemplateParmDecl.
-  Record.push_back(D->getDefaultArgument() != 0);
-  if (D->getDefaultArgument()) {
-    Writer.AddStmt(D->getDefaultArgument());
-    Record.push_back(D->defaultArgumentWasInherited());
-  }
-  Code = pch::DECL_NON_TYPE_TEMPLATE_PARM;
-}
-
-void PCHDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
-  VisitTemplateDecl(D);
-  // TemplateParmPosition.
-  Record.push_back(D->getDepth());
-  Record.push_back(D->getPosition());
-  // Rest of TemplateTemplateParmDecl.
-  Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record);
-  Record.push_back(D->defaultArgumentWasInherited());
-  Code = pch::DECL_TEMPLATE_TEMPLATE_PARM;
-}
-
-void PCHDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
-  VisitDecl(D);
-  Writer.AddStmt(D->getAssertExpr());
-  Writer.AddStmt(D->getMessage());
-  Code = pch::DECL_STATIC_ASSERT;
-}
-
-/// \brief Emit the DeclContext part of a declaration context decl.
-///
-/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
-/// block for this declaration context is stored. May be 0 to indicate
-/// that there are no declarations stored within this context.
-///
-/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
-/// block for this declaration context is stored. May be 0 to indicate
-/// that there are no declarations visible from this context. Note
-/// that this value will not be emitted for non-primary declaration
-/// contexts.
-void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
-                                     uint64_t VisibleOffset) {
-  Record.push_back(LexicalOffset);
-  Record.push_back(VisibleOffset);
-}
-
-template <typename T>
-void PCHDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
-  enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
-  if (D->RedeclLink.getNext() == D) {
-    Record.push_back(NoRedeclaration);
-  } else {
-    Record.push_back(D->RedeclLink.NextIsPrevious() ? PointsToPrevious
-                                                    : PointsToLatest);
-    Writer.AddDeclRef(D->RedeclLink.getPointer(), Record);
-  }
-
-  T *First = D->getFirstDeclaration();
-  T *ThisDecl = static_cast<T*>(D);
-  // If this is a most recent redeclaration that is pointed to by a first decl
-  // in a chained PCH, keep track of the association with the map so we can
-  // update the first decl during PCH reading.
-  if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl &&
-      First->getPCHLevel() > ThisDecl->getPCHLevel()) {
-    assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end()
-           && "The latest is already set");
-    Writer.FirstLatestDecls[First] = ThisDecl;
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// PCHWriter Implementation
-//===----------------------------------------------------------------------===//
-
-void PCHWriter::WriteDeclsBlockAbbrevs() {
-  using namespace llvm;
-  // Abbreviation for DECL_PARM_VAR.
-  BitCodeAbbrev *Abv = new BitCodeAbbrev();
-  Abv->Add(BitCodeAbbrevOp(pch::DECL_PARM_VAR));
-
-  // Decl
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
-  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl (!?)
-  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs
-  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit
-  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed
-  Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
-  Abv->Add(BitCodeAbbrevOp(0));                       // PCH level
-
-  // NamedDecl
-  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
-  // ValueDecl
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
-  // DeclaratorDecl
-  Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType
-  // VarDecl
-  Abv->Add(BitCodeAbbrevOp(0));                       // StorageClass
-  Abv->Add(BitCodeAbbrevOp(0));                       // StorageClassAsWritten
-  Abv->Add(BitCodeAbbrevOp(0));                       // isThreadSpecified
-  Abv->Add(BitCodeAbbrevOp(0));                       // hasCXXDirectInitializer
-  Abv->Add(BitCodeAbbrevOp(0));                       // isExceptionVariable
-  Abv->Add(BitCodeAbbrevOp(0));                       // isNRVOVariable
-  Abv->Add(BitCodeAbbrevOp(0));                       // PrevDecl
-  Abv->Add(BitCodeAbbrevOp(0));                       // HasInit
-  Abv->Add(BitCodeAbbrevOp(0));                   // HasMemberSpecializationInfo
-  // ParmVarDecl
-  Abv->Add(BitCodeAbbrevOp(0));                       // ObjCDeclQualifier
-  Abv->Add(BitCodeAbbrevOp(0));                       // HasInheritedDefaultArg
-  Abv->Add(BitCodeAbbrevOp(0));                   // HasUninstantiatedDefaultArg
-
-  ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
-
-  Abv = new BitCodeAbbrev();
-  Abv->Add(BitCodeAbbrevOp(pch::DECL_CONTEXT_LEXICAL));
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
-  DeclContextLexicalAbbrev = Stream.EmitAbbrev(Abv);
-}
-
-/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by
-/// consumers of the AST.
-///
-/// Such decls will always be deserialized from the PCH file, so we would like
-/// this to be as restrictive as possible. Currently the predicate is driven by
-/// code generation requirements, if other clients have a different notion of
-/// what is "required" then we may have to consider an alternate scheme where
-/// clients can iterate over the top-level decls and get information on them,
-/// without necessary deserializing them. We could explicitly require such
-/// clients to use a separate API call to "realize" the decl. This should be
-/// relatively painless since they would presumably only do it for top-level
-/// decls.
-static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
-  // File scoped assembly or obj-c implementation must be seen.
-  if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplementationDecl>(D))
-    return true;
-
-  return Context.DeclMustBeEmitted(D);
-}
-
-void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
-  RecordData Record;
-  PCHDeclWriter W(*this, Context, Record);
-
-  // If this declaration is also a DeclContext, write blocks for the
-  // declarations that lexically stored inside its context and those
-  // declarations that are visible from its context. These blocks
-  // are written before the declaration itself so that we can put
-  // their offsets into the record for the declaration.
-  uint64_t LexicalOffset = 0;
-  uint64_t VisibleOffset = 0;
-  DeclContext *DC = dyn_cast<DeclContext>(D);
-  if (DC) {
-    LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
-    VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
-  }
-
-  // Determine the ID for this declaration
-  pch::DeclID &IDR = DeclIDs[D];
-  if (IDR == 0)
-    IDR = NextDeclID++;
-  pch::DeclID ID = IDR;
-
-  if (ID < FirstDeclID) {
-    // We're replacing a decl in a previous file.
-    ReplacedDecls.push_back(std::make_pair(ID, Stream.GetCurrentBitNo()));
-  } else {
-    unsigned Index = ID - FirstDeclID;
-
-    // Record the offset for this declaration
-    if (DeclOffsets.size() == Index)
-      DeclOffsets.push_back(Stream.GetCurrentBitNo());
-    else if (DeclOffsets.size() < Index) {
-      DeclOffsets.resize(Index+1);
-      DeclOffsets[Index] = Stream.GetCurrentBitNo();
-    }
-  }
-
-  // Build and emit a record for this declaration
-  Record.clear();
-  W.Code = (pch::DeclCode)0;
-  W.AbbrevToUse = 0;
-  W.Visit(D);
-  if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
-
-  if (!W.Code)
-    llvm::report_fatal_error(llvm::StringRef("unexpected declaration kind '") +
-                            D->getDeclKindName() + "'");
-  Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
-
-  // If the declaration had any attributes, write them now.
-  if (D->hasAttrs())
-    WriteAttributeRecord(D->getAttrs());
-
-  // Flush any expressions that were written as part of this declaration.
-  FlushStmts();
-
-  // Note "external" declarations so that we can add them to a record in the
-  // PCH file later.
-  //
-  // FIXME: This should be renamed, the predicate is much more complicated.
-  if (isRequiredDecl(D, Context))
-    ExternalDefinitions.push_back(ID);
-}
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
deleted file mode 100644
index 0c149f2..0000000
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ /dev/null
@@ -1,1370 +0,0 @@
-//===--- PCHWriterStmt.cpp - Statement and Expression Serialization -------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements serialization for Statements and Expressions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/PCHWriter.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/StmtVisitor.h"
-#include "llvm/Bitcode/BitstreamWriter.h"
-using namespace clang;
-
-//===----------------------------------------------------------------------===//
-// Statement/expression serialization
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-  class PCHStmtWriter : public StmtVisitor<PCHStmtWriter, void> {
-    PCHWriter &Writer;
-    PCHWriter::RecordData &Record;
-
-  public:
-    pch::StmtCode Code;
-
-    PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
-      : Writer(Writer), Record(Record) { }
-    
-    void
-    AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args);
-
-    void VisitStmt(Stmt *S);
-    void VisitNullStmt(NullStmt *S);
-    void VisitCompoundStmt(CompoundStmt *S);
-    void VisitSwitchCase(SwitchCase *S);
-    void VisitCaseStmt(CaseStmt *S);
-    void VisitDefaultStmt(DefaultStmt *S);
-    void VisitLabelStmt(LabelStmt *S);
-    void VisitIfStmt(IfStmt *S);
-    void VisitSwitchStmt(SwitchStmt *S);
-    void VisitWhileStmt(WhileStmt *S);
-    void VisitDoStmt(DoStmt *S);
-    void VisitForStmt(ForStmt *S);
-    void VisitGotoStmt(GotoStmt *S);
-    void VisitIndirectGotoStmt(IndirectGotoStmt *S);
-    void VisitContinueStmt(ContinueStmt *S);
-    void VisitBreakStmt(BreakStmt *S);
-    void VisitReturnStmt(ReturnStmt *S);
-    void VisitDeclStmt(DeclStmt *S);
-    void VisitAsmStmt(AsmStmt *S);
-    void VisitExpr(Expr *E);
-    void VisitPredefinedExpr(PredefinedExpr *E);
-    void VisitDeclRefExpr(DeclRefExpr *E);
-    void VisitIntegerLiteral(IntegerLiteral *E);
-    void VisitFloatingLiteral(FloatingLiteral *E);
-    void VisitImaginaryLiteral(ImaginaryLiteral *E);
-    void VisitStringLiteral(StringLiteral *E);
-    void VisitCharacterLiteral(CharacterLiteral *E);
-    void VisitParenExpr(ParenExpr *E);
-    void VisitParenListExpr(ParenListExpr *E);
-    void VisitUnaryOperator(UnaryOperator *E);
-    void VisitOffsetOfExpr(OffsetOfExpr *E);
-    void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
-    void VisitArraySubscriptExpr(ArraySubscriptExpr *E);
-    void VisitCallExpr(CallExpr *E);
-    void VisitMemberExpr(MemberExpr *E);
-    void VisitCastExpr(CastExpr *E);
-    void VisitBinaryOperator(BinaryOperator *E);
-    void VisitCompoundAssignOperator(CompoundAssignOperator *E);
-    void VisitConditionalOperator(ConditionalOperator *E);
-    void VisitImplicitCastExpr(ImplicitCastExpr *E);
-    void VisitExplicitCastExpr(ExplicitCastExpr *E);
-    void VisitCStyleCastExpr(CStyleCastExpr *E);
-    void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
-    void VisitExtVectorElementExpr(ExtVectorElementExpr *E);
-    void VisitInitListExpr(InitListExpr *E);
-    void VisitDesignatedInitExpr(DesignatedInitExpr *E);
-    void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
-    void VisitVAArgExpr(VAArgExpr *E);
-    void VisitAddrLabelExpr(AddrLabelExpr *E);
-    void VisitStmtExpr(StmtExpr *E);
-    void VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
-    void VisitChooseExpr(ChooseExpr *E);
-    void VisitGNUNullExpr(GNUNullExpr *E);
-    void VisitShuffleVectorExpr(ShuffleVectorExpr *E);
-    void VisitBlockExpr(BlockExpr *E);
-    void VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
-
-    // Objective-C Expressions
-    void VisitObjCStringLiteral(ObjCStringLiteral *E);
-    void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
-    void VisitObjCSelectorExpr(ObjCSelectorExpr *E);
-    void VisitObjCProtocolExpr(ObjCProtocolExpr *E);
-    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E);
-    void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
-    void VisitObjCImplicitSetterGetterRefExpr(
-                        ObjCImplicitSetterGetterRefExpr *E);
-    void VisitObjCMessageExpr(ObjCMessageExpr *E);
-    void VisitObjCSuperExpr(ObjCSuperExpr *E);
-    void VisitObjCIsaExpr(ObjCIsaExpr *E);
-
-    // Objective-C Statements
-    void VisitObjCForCollectionStmt(ObjCForCollectionStmt *);
-    void VisitObjCAtCatchStmt(ObjCAtCatchStmt *);
-    void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *);
-    void VisitObjCAtTryStmt(ObjCAtTryStmt *);
-    void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *);
-    void VisitObjCAtThrowStmt(ObjCAtThrowStmt *);
-
-    // C++ Statements
-    void VisitCXXCatchStmt(CXXCatchStmt *S);
-    void VisitCXXTryStmt(CXXTryStmt *S);
-
-    void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
-    void VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
-    void VisitCXXConstructExpr(CXXConstructExpr *E);
-    void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
-    void VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
-    void VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
-    void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
-    void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
-    void VisitCXXConstCastExpr(CXXConstCastExpr *E);
-    void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
-    void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
-    void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
-    void VisitCXXTypeidExpr(CXXTypeidExpr *E);
-    void VisitCXXThisExpr(CXXThisExpr *E);
-    void VisitCXXThrowExpr(CXXThrowExpr *E);
-    void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
-    void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
-    void VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E);
-
-    void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
-    void VisitCXXNewExpr(CXXNewExpr *E);
-    void VisitCXXDeleteExpr(CXXDeleteExpr *E);
-    void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
-
-    void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E);
-    void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
-    void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
-    void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
-
-    void VisitOverloadExpr(OverloadExpr *E);
-    void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
-    void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
-
-    void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
-  };
-}
-
-void PCHStmtWriter::
-AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args) {
-  Writer.AddSourceLocation(Args.LAngleLoc, Record);
-  Writer.AddSourceLocation(Args.RAngleLoc, Record);
-  for (unsigned i=0; i != Args.NumTemplateArgs; ++i)
-    Writer.AddTemplateArgumentLoc(Args.getTemplateArgs()[i], Record);
-}
-
-void PCHStmtWriter::VisitStmt(Stmt *S) {
-}
-
-void PCHStmtWriter::VisitNullStmt(NullStmt *S) {
-  VisitStmt(S);
-  Writer.AddSourceLocation(S->getSemiLoc(), Record);
-  Code = pch::STMT_NULL;
-}
-
-void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
-  VisitStmt(S);
-  Record.push_back(S->size());
-  for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end();
-       CS != CSEnd; ++CS)
-    Writer.AddStmt(*CS);
-  Writer.AddSourceLocation(S->getLBracLoc(), Record);
-  Writer.AddSourceLocation(S->getRBracLoc(), Record);
-  Code = pch::STMT_COMPOUND;
-}
-
-void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) {
-  VisitStmt(S);
-  Record.push_back(Writer.getSwitchCaseID(S));
-}
-
-void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) {
-  VisitSwitchCase(S);
-  Writer.AddStmt(S->getLHS());
-  Writer.AddStmt(S->getRHS());
-  Writer.AddStmt(S->getSubStmt());
-  Writer.AddSourceLocation(S->getCaseLoc(), Record);
-  Writer.AddSourceLocation(S->getEllipsisLoc(), Record);
-  Writer.AddSourceLocation(S->getColonLoc(), Record);
-  Code = pch::STMT_CASE;
-}
-
-void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
-  VisitSwitchCase(S);
-  Writer.AddStmt(S->getSubStmt());
-  Writer.AddSourceLocation(S->getDefaultLoc(), Record);
-  Writer.AddSourceLocation(S->getColonLoc(), Record);
-  Code = pch::STMT_DEFAULT;
-}
-
-void PCHStmtWriter::VisitLabelStmt(LabelStmt *S) {
-  VisitStmt(S);
-  Writer.AddIdentifierRef(S->getID(), Record);
-  Writer.AddStmt(S->getSubStmt());
-  Writer.AddSourceLocation(S->getIdentLoc(), Record);
-  Record.push_back(Writer.GetLabelID(S));
-  Code = pch::STMT_LABEL;
-}
-
-void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
-  VisitStmt(S);
-  Writer.AddDeclRef(S->getConditionVariable(), Record);
-  Writer.AddStmt(S->getCond());
-  Writer.AddStmt(S->getThen());
-  Writer.AddStmt(S->getElse());
-  Writer.AddSourceLocation(S->getIfLoc(), Record);
-  Writer.AddSourceLocation(S->getElseLoc(), Record);
-  Code = pch::STMT_IF;
-}
-
-void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
-  VisitStmt(S);
-  Writer.AddDeclRef(S->getConditionVariable(), Record);
-  Writer.AddStmt(S->getCond());
-  Writer.AddStmt(S->getBody());
-  Writer.AddSourceLocation(S->getSwitchLoc(), Record);
-  for (SwitchCase *SC = S->getSwitchCaseList(); SC;
-       SC = SC->getNextSwitchCase())
-    Record.push_back(Writer.RecordSwitchCaseID(SC));
-  Code = pch::STMT_SWITCH;
-}
-
-void PCHStmtWriter::VisitWhileStmt(WhileStmt *S) {
-  VisitStmt(S);
-  Writer.AddDeclRef(S->getConditionVariable(), Record);
-  Writer.AddStmt(S->getCond());
-  Writer.AddStmt(S->getBody());
-  Writer.AddSourceLocation(S->getWhileLoc(), Record);
-  Code = pch::STMT_WHILE;
-}
-
-void PCHStmtWriter::VisitDoStmt(DoStmt *S) {
-  VisitStmt(S);
-  Writer.AddStmt(S->getCond());
-  Writer.AddStmt(S->getBody());
-  Writer.AddSourceLocation(S->getDoLoc(), Record);
-  Writer.AddSourceLocation(S->getWhileLoc(), Record);
-  Writer.AddSourceLocation(S->getRParenLoc(), Record);
-  Code = pch::STMT_DO;
-}
-
-void PCHStmtWriter::VisitForStmt(ForStmt *S) {
-  VisitStmt(S);
-  Writer.AddStmt(S->getInit());
-  Writer.AddStmt(S->getCond());
-  Writer.AddDeclRef(S->getConditionVariable(), Record);
-  Writer.AddStmt(S->getInc());
-  Writer.AddStmt(S->getBody());
-  Writer.AddSourceLocation(S->getForLoc(), Record);
-  Writer.AddSourceLocation(S->getLParenLoc(), Record);
-  Writer.AddSourceLocation(S->getRParenLoc(), Record);
-  Code = pch::STMT_FOR;
-}
-
-void PCHStmtWriter::VisitGotoStmt(GotoStmt *S) {
-  VisitStmt(S);
-  Record.push_back(Writer.GetLabelID(S->getLabel()));
-  Writer.AddSourceLocation(S->getGotoLoc(), Record);
-  Writer.AddSourceLocation(S->getLabelLoc(), Record);
-  Code = pch::STMT_GOTO;
-}
-
-void PCHStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
-  VisitStmt(S);
-  Writer.AddSourceLocation(S->getGotoLoc(), Record);
-  Writer.AddSourceLocation(S->getStarLoc(), Record);
-  Writer.AddStmt(S->getTarget());
-  Code = pch::STMT_INDIRECT_GOTO;
-}
-
-void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) {
-  VisitStmt(S);
-  Writer.AddSourceLocation(S->getContinueLoc(), Record);
-  Code = pch::STMT_CONTINUE;
-}
-
-void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) {
-  VisitStmt(S);
-  Writer.AddSourceLocation(S->getBreakLoc(), Record);
-  Code = pch::STMT_BREAK;
-}
-
-void PCHStmtWriter::VisitReturnStmt(ReturnStmt *S) {
-  VisitStmt(S);
-  Writer.AddStmt(S->getRetValue());
-  Writer.AddSourceLocation(S->getReturnLoc(), Record);
-  Writer.AddDeclRef(S->getNRVOCandidate(), Record);
-  Code = pch::STMT_RETURN;
-}
-
-void PCHStmtWriter::VisitDeclStmt(DeclStmt *S) {
-  VisitStmt(S);
-  Writer.AddSourceLocation(S->getStartLoc(), Record);
-  Writer.AddSourceLocation(S->getEndLoc(), Record);
-  DeclGroupRef DG = S->getDeclGroup();
-  for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D)
-    Writer.AddDeclRef(*D, Record);
-  Code = pch::STMT_DECL;
-}
-
-void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) {
-  VisitStmt(S);
-  Record.push_back(S->getNumOutputs());
-  Record.push_back(S->getNumInputs());
-  Record.push_back(S->getNumClobbers());
-  Writer.AddSourceLocation(S->getAsmLoc(), Record);
-  Writer.AddSourceLocation(S->getRParenLoc(), Record);
-  Record.push_back(S->isVolatile());
-  Record.push_back(S->isSimple());
-  Record.push_back(S->isMSAsm());
-  Writer.AddStmt(S->getAsmString());
-
-  // Outputs
-  for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {      
-    Writer.AddIdentifierRef(S->getOutputIdentifier(I), Record);
-    Writer.AddStmt(S->getOutputConstraintLiteral(I));
-    Writer.AddStmt(S->getOutputExpr(I));
-  }
-
-  // Inputs
-  for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) {
-    Writer.AddIdentifierRef(S->getInputIdentifier(I), Record);
-    Writer.AddStmt(S->getInputConstraintLiteral(I));
-    Writer.AddStmt(S->getInputExpr(I));
-  }
-
-  // Clobbers
-  for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
-    Writer.AddStmt(S->getClobber(I));
-
-  Code = pch::STMT_ASM;
-}
-
-void PCHStmtWriter::VisitExpr(Expr *E) {
-  VisitStmt(E);
-  Writer.AddTypeRef(E->getType(), Record);
-  Record.push_back(E->isTypeDependent());
-  Record.push_back(E->isValueDependent());
-}
-
-void PCHStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Record.push_back(E->getIdentType()); // FIXME: stable encoding
-  Code = pch::EXPR_PREDEFINED;
-}
-
-void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
-  VisitExpr(E);
-
-  Record.push_back(E->hasQualifier());
-  unsigned NumTemplateArgs = E->getNumTemplateArgs();
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() &&
-         "Template args list with no args ?");
-  Record.push_back(NumTemplateArgs);
-
-  if (E->hasQualifier()) {
-    Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
-    Writer.AddSourceRange(E->getQualifierRange(), Record);
-  }
-
-  if (NumTemplateArgs)
-    AddExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList());
-
-  Writer.AddDeclRef(E->getDecl(), Record);
-  // FIXME: write DeclarationNameLoc.
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Code = pch::EXPR_DECL_REF;
-}
-
-void PCHStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Writer.AddAPInt(E->getValue(), Record);
-  Code = pch::EXPR_INTEGER_LITERAL;
-}
-
-void PCHStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
-  VisitExpr(E);
-  Writer.AddAPFloat(E->getValue(), Record);
-  Record.push_back(E->isExact());
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Code = pch::EXPR_FLOATING_LITERAL;
-}
-
-void PCHStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getSubExpr());
-  Code = pch::EXPR_IMAGINARY_LITERAL;
-}
-
-void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) {
-  VisitExpr(E);
-  Record.push_back(E->getByteLength());
-  Record.push_back(E->getNumConcatenated());
-  Record.push_back(E->isWide());
-  // FIXME: String data should be stored as a blob at the end of the
-  // StringLiteral. However, we can't do so now because we have no
-  // provision for coping with abbreviations when we're jumping around
-  // the PCH file during deserialization.
-  Record.append(E->getString().begin(), E->getString().end());
-  for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
-    Writer.AddSourceLocation(E->getStrTokenLoc(I), Record);
-  Code = pch::EXPR_STRING_LITERAL;
-}
-
-void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) {
-  VisitExpr(E);
-  Record.push_back(E->getValue());
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Record.push_back(E->isWide());
-  Code = pch::EXPR_CHARACTER_LITERAL;
-}
-
-void PCHStmtWriter::VisitParenExpr(ParenExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getLParen(), Record);
-  Writer.AddSourceLocation(E->getRParen(), Record);
-  Writer.AddStmt(E->getSubExpr());
-  Code = pch::EXPR_PAREN;
-}
-
-void PCHStmtWriter::VisitParenListExpr(ParenListExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->NumExprs);
-  for (unsigned i=0; i != E->NumExprs; ++i)
-    Writer.AddStmt(E->Exprs[i]);
-  Writer.AddSourceLocation(E->LParenLoc, Record);
-  Writer.AddSourceLocation(E->RParenLoc, Record);
-  Code = pch::EXPR_PAREN_LIST;
-}
-
-void PCHStmtWriter::VisitUnaryOperator(UnaryOperator *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getSubExpr());
-  Record.push_back(E->getOpcode()); // FIXME: stable encoding
-  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
-  Code = pch::EXPR_UNARY_OPERATOR;
-}
-
-void PCHStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getNumComponents());
-  Record.push_back(E->getNumExpressions());
-  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
-  for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
-    const OffsetOfExpr::OffsetOfNode &ON = E->getComponent(I);
-    Record.push_back(ON.getKind()); // FIXME: Stable encoding
-    Writer.AddSourceLocation(ON.getRange().getBegin(), Record);
-    Writer.AddSourceLocation(ON.getRange().getEnd(), Record);
-    switch (ON.getKind()) {
-    case OffsetOfExpr::OffsetOfNode::Array:
-      Record.push_back(ON.getArrayExprIndex());
-      break;
-        
-    case OffsetOfExpr::OffsetOfNode::Field:
-      Writer.AddDeclRef(ON.getField(), Record);
-      break;
-        
-    case OffsetOfExpr::OffsetOfNode::Identifier:
-      Writer.AddIdentifierRef(ON.getFieldName(), Record);
-      break;
-        
-    case OffsetOfExpr::OffsetOfNode::Base:
-      Writer.AddCXXBaseSpecifier(*ON.getBase(), Record);
-      break;
-    }
-  }
-  for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I)
-    Writer.AddStmt(E->getIndexExpr(I));
-  Code = pch::EXPR_OFFSETOF;
-}
-
-void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->isSizeOf());
-  if (E->isArgumentType())
-    Writer.AddTypeSourceInfo(E->getArgumentTypeInfo(), Record);
-  else {
-    Record.push_back(0);
-    Writer.AddStmt(E->getArgumentExpr());
-  }
-  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_SIZEOF_ALIGN_OF;
-}
-
-void PCHStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getLHS());
-  Writer.AddStmt(E->getRHS());
-  Writer.AddSourceLocation(E->getRBracketLoc(), Record);
-  Code = pch::EXPR_ARRAY_SUBSCRIPT;
-}
-
-void PCHStmtWriter::VisitCallExpr(CallExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getNumArgs());
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Writer.AddStmt(E->getCallee());
-  for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
-       Arg != ArgEnd; ++Arg)
-    Writer.AddStmt(*Arg);
-  Code = pch::EXPR_CALL;
-}
-
-void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) {
-  // Don't call VisitExpr, we'll write everything here.
-
-  Record.push_back(E->hasQualifier());
-  if (E->hasQualifier()) {
-    Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
-    Writer.AddSourceRange(E->getQualifierRange(), Record);
-  }
-
-  unsigned NumTemplateArgs = E->getNumTemplateArgs();
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() &&
-         "Template args list with no args ?");
-  Record.push_back(NumTemplateArgs);
-  if (NumTemplateArgs) {
-    Writer.AddSourceLocation(E->getLAngleLoc(), Record);
-    Writer.AddSourceLocation(E->getRAngleLoc(), Record);
-    for (unsigned i=0; i != NumTemplateArgs; ++i)
-      Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record);
-  }
-  
-  DeclAccessPair FoundDecl = E->getFoundDecl();
-  Writer.AddDeclRef(FoundDecl.getDecl(), Record);
-  Record.push_back(FoundDecl.getAccess());
-
-  Writer.AddTypeRef(E->getType(), Record);
-  Writer.AddStmt(E->getBase());
-  Writer.AddDeclRef(E->getMemberDecl(), Record);
-  // FIXME: write DeclarationNameLoc.
-  Writer.AddSourceLocation(E->getMemberLoc(), Record);
-  Record.push_back(E->isArrow());
-  Code = pch::EXPR_MEMBER;
-}
-
-void PCHStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getBase());
-  Writer.AddSourceLocation(E->getIsaMemberLoc(), Record);
-  Record.push_back(E->isArrow());
-  Code = pch::EXPR_OBJC_ISA;
-}
-
-void PCHStmtWriter::VisitCastExpr(CastExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->path_size());
-  Writer.AddStmt(E->getSubExpr());
-  Record.push_back(E->getCastKind()); // FIXME: stable encoding
-
-  for (CastExpr::path_iterator
-         PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI)
-    Writer.AddCXXBaseSpecifier(**PI, Record);
-}
-
-void PCHStmtWriter::VisitBinaryOperator(BinaryOperator *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getLHS());
-  Writer.AddStmt(E->getRHS());
-  Record.push_back(E->getOpcode()); // FIXME: stable encoding
-  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
-  Code = pch::EXPR_BINARY_OPERATOR;
-}
-
-void PCHStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
-  VisitBinaryOperator(E);
-  Writer.AddTypeRef(E->getComputationLHSType(), Record);
-  Writer.AddTypeRef(E->getComputationResultType(), Record);
-  Code = pch::EXPR_COMPOUND_ASSIGN_OPERATOR;
-}
-
-void PCHStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getCond());
-  Writer.AddStmt(E->getLHS());
-  Writer.AddStmt(E->getRHS());
-  Writer.AddSourceLocation(E->getQuestionLoc(), Record);
-  Writer.AddSourceLocation(E->getColonLoc(), Record);
-  Code = pch::EXPR_CONDITIONAL_OPERATOR;
-}
-
-void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
-  VisitCastExpr(E);
-  Record.push_back(E->getCategory());
-  Code = pch::EXPR_IMPLICIT_CAST;
-}
-
-void PCHStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
-  VisitCastExpr(E);
-  Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record);
-}
-
-void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
-  VisitExplicitCastExpr(E);
-  Writer.AddSourceLocation(E->getLParenLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_CSTYLE_CAST;
-}
-
-void PCHStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getLParenLoc(), Record);
-  Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
-  Writer.AddStmt(E->getInitializer());
-  Record.push_back(E->isFileScope());
-  Code = pch::EXPR_COMPOUND_LITERAL;
-}
-
-void PCHStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getBase());
-  Writer.AddIdentifierRef(&E->getAccessor(), Record);
-  Writer.AddSourceLocation(E->getAccessorLoc(), Record);
-  Code = pch::EXPR_EXT_VECTOR_ELEMENT;
-}
-
-void PCHStmtWriter::VisitInitListExpr(InitListExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getNumInits());
-  for (unsigned I = 0, N = E->getNumInits(); I != N; ++I)
-    Writer.AddStmt(E->getInit(I));
-  Writer.AddStmt(E->getSyntacticForm());
-  Writer.AddSourceLocation(E->getLBraceLoc(), Record);
-  Writer.AddSourceLocation(E->getRBraceLoc(), Record);
-  Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record);
-  Record.push_back(E->hadArrayRangeDesignator());
-  Code = pch::EXPR_INIT_LIST;
-}
-
-void PCHStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getNumSubExprs());
-  for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
-    Writer.AddStmt(E->getSubExpr(I));
-  Writer.AddSourceLocation(E->getEqualOrColonLoc(), Record);
-  Record.push_back(E->usesGNUSyntax());
-  for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
-                                             DEnd = E->designators_end();
-       D != DEnd; ++D) {
-    if (D->isFieldDesignator()) {
-      if (FieldDecl *Field = D->getField()) {
-        Record.push_back(pch::DESIG_FIELD_DECL);
-        Writer.AddDeclRef(Field, Record);
-      } else {
-        Record.push_back(pch::DESIG_FIELD_NAME);
-        Writer.AddIdentifierRef(D->getFieldName(), Record);
-      }
-      Writer.AddSourceLocation(D->getDotLoc(), Record);
-      Writer.AddSourceLocation(D->getFieldLoc(), Record);
-    } else if (D->isArrayDesignator()) {
-      Record.push_back(pch::DESIG_ARRAY);
-      Record.push_back(D->getFirstExprIndex());
-      Writer.AddSourceLocation(D->getLBracketLoc(), Record);
-      Writer.AddSourceLocation(D->getRBracketLoc(), Record);
-    } else {
-      assert(D->isArrayRangeDesignator() && "Unknown designator");
-      Record.push_back(pch::DESIG_ARRAY_RANGE);
-      Record.push_back(D->getFirstExprIndex());
-      Writer.AddSourceLocation(D->getLBracketLoc(), Record);
-      Writer.AddSourceLocation(D->getEllipsisLoc(), Record);
-      Writer.AddSourceLocation(D->getRBracketLoc(), Record);
-    }
-  }
-  Code = pch::EXPR_DESIGNATED_INIT;
-}
-
-void PCHStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
-  VisitExpr(E);
-  Code = pch::EXPR_IMPLICIT_VALUE_INIT;
-}
-
-void PCHStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getSubExpr());
-  Writer.AddTypeSourceInfo(E->getWrittenTypeInfo(), Record);
-  Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_VA_ARG;
-}
-
-void PCHStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getAmpAmpLoc(), Record);
-  Writer.AddSourceLocation(E->getLabelLoc(), Record);
-  Record.push_back(Writer.GetLabelID(E->getLabel()));
-  Code = pch::EXPR_ADDR_LABEL;
-}
-
-void PCHStmtWriter::VisitStmtExpr(StmtExpr *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getSubStmt());
-  Writer.AddSourceLocation(E->getLParenLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_STMT;
-}
-
-void PCHStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
-  VisitExpr(E);
-  Writer.AddTypeSourceInfo(E->getArgTInfo1(), Record);
-  Writer.AddTypeSourceInfo(E->getArgTInfo2(), Record);
-  Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_TYPES_COMPATIBLE;
-}
-
-void PCHStmtWriter::VisitChooseExpr(ChooseExpr *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getCond());
-  Writer.AddStmt(E->getLHS());
-  Writer.AddStmt(E->getRHS());
-  Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_CHOOSE;
-}
-
-void PCHStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getTokenLocation(), Record);
-  Code = pch::EXPR_GNU_NULL;
-}
-
-void PCHStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getNumSubExprs());
-  for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
-    Writer.AddStmt(E->getExpr(I));
-  Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_SHUFFLE_VECTOR;
-}
-
-void PCHStmtWriter::VisitBlockExpr(BlockExpr *E) {
-  VisitExpr(E);
-  Writer.AddDeclRef(E->getBlockDecl(), Record);
-  Record.push_back(E->hasBlockDeclRefExprs());
-  Code = pch::EXPR_BLOCK;
-}
-
-void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
-  VisitExpr(E);
-  Writer.AddDeclRef(E->getDecl(), Record);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Record.push_back(E->isByRef());
-  Record.push_back(E->isConstQualAdded());
-  Writer.AddStmt(E->getCopyConstructorExpr());
-  Code = pch::EXPR_BLOCK_DECL_REF;
-}
-
-//===----------------------------------------------------------------------===//
-// Objective-C Expressions and Statements.
-//===----------------------------------------------------------------------===//
-
-void PCHStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getString());
-  Writer.AddSourceLocation(E->getAtLoc(), Record);
-  Code = pch::EXPR_OBJC_STRING_LITERAL;
-}
-
-void PCHStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
-  VisitExpr(E);
-  Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record);
-  Writer.AddSourceLocation(E->getAtLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_OBJC_ENCODE;
-}
-
-void PCHStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
-  VisitExpr(E);
-  Writer.AddSelectorRef(E->getSelector(), Record);
-  Writer.AddSourceLocation(E->getAtLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_OBJC_SELECTOR_EXPR;
-}
-
-void PCHStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
-  VisitExpr(E);
-  Writer.AddDeclRef(E->getProtocol(), Record);
-  Writer.AddSourceLocation(E->getAtLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_OBJC_PROTOCOL_EXPR;
-}
-
-void PCHStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
-  VisitExpr(E);
-  Writer.AddDeclRef(E->getDecl(), Record);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Writer.AddStmt(E->getBase());
-  Record.push_back(E->isArrow());
-  Record.push_back(E->isFreeIvar());
-  Code = pch::EXPR_OBJC_IVAR_REF_EXPR;
-}
-
-void PCHStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
-  VisitExpr(E);
-  Writer.AddDeclRef(E->getProperty(), Record);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Writer.AddStmt(E->getBase());
-  Code = pch::EXPR_OBJC_PROPERTY_REF_EXPR;
-}
-
-void PCHStmtWriter::VisitObjCImplicitSetterGetterRefExpr(
-                                  ObjCImplicitSetterGetterRefExpr *E) {
-  VisitExpr(E);
-  Writer.AddDeclRef(E->getGetterMethod(), Record);
-  Writer.AddDeclRef(E->getSetterMethod(), Record);
-
-  // NOTE: InterfaceDecl and Base are mutually exclusive.
-  Writer.AddDeclRef(E->getInterfaceDecl(), Record);
-  Writer.AddStmt(E->getBase());
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Writer.AddSourceLocation(E->getClassLoc(), Record);
-  Code = pch::EXPR_OBJC_KVC_REF_EXPR;
-}
-
-void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getNumArgs());
-  Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding
-  switch (E->getReceiverKind()) {
-  case ObjCMessageExpr::Instance:
-    Writer.AddStmt(E->getInstanceReceiver());
-    break;
-
-  case ObjCMessageExpr::Class:
-    Writer.AddTypeSourceInfo(E->getClassReceiverTypeInfo(), Record);
-    break;
-
-  case ObjCMessageExpr::SuperClass:
-  case ObjCMessageExpr::SuperInstance:
-    Writer.AddTypeRef(E->getSuperType(), Record);
-    Writer.AddSourceLocation(E->getSuperLoc(), Record);
-    break;
-  }
-
-  if (E->getMethodDecl()) {
-    Record.push_back(1);
-    Writer.AddDeclRef(E->getMethodDecl(), Record);
-  } else {
-    Record.push_back(0);
-    Writer.AddSelectorRef(E->getSelector(), Record);    
-  }
-    
-  Writer.AddSourceLocation(E->getLeftLoc(), Record);
-  Writer.AddSourceLocation(E->getRightLoc(), Record);
-
-  for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
-       Arg != ArgEnd; ++Arg)
-    Writer.AddStmt(*Arg);
-  Code = pch::EXPR_OBJC_MESSAGE_EXPR;
-}
-
-void PCHStmtWriter::VisitObjCSuperExpr(ObjCSuperExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getLoc(), Record);
-  Code = pch::EXPR_OBJC_SUPER_EXPR;
-}
-
-void PCHStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
-  VisitStmt(S);
-  Writer.AddStmt(S->getElement());
-  Writer.AddStmt(S->getCollection());
-  Writer.AddStmt(S->getBody());
-  Writer.AddSourceLocation(S->getForLoc(), Record);
-  Writer.AddSourceLocation(S->getRParenLoc(), Record);
-  Code = pch::STMT_OBJC_FOR_COLLECTION;
-}
-
-void PCHStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
-  Writer.AddStmt(S->getCatchBody());
-  Writer.AddDeclRef(S->getCatchParamDecl(), Record);
-  Writer.AddSourceLocation(S->getAtCatchLoc(), Record);
-  Writer.AddSourceLocation(S->getRParenLoc(), Record);
-  Code = pch::STMT_OBJC_CATCH;
-}
-
-void PCHStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
-  Writer.AddStmt(S->getFinallyBody());
-  Writer.AddSourceLocation(S->getAtFinallyLoc(), Record);
-  Code = pch::STMT_OBJC_FINALLY;
-}
-
-void PCHStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
-  Record.push_back(S->getNumCatchStmts());
-  Record.push_back(S->getFinallyStmt() != 0);
-  Writer.AddStmt(S->getTryBody());
-  for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I)
-    Writer.AddStmt(S->getCatchStmt(I));
-  if (S->getFinallyStmt())
-    Writer.AddStmt(S->getFinallyStmt());
-  Writer.AddSourceLocation(S->getAtTryLoc(), Record);
-  Code = pch::STMT_OBJC_AT_TRY;
-}
-
-void PCHStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
-  Writer.AddStmt(S->getSynchExpr());
-  Writer.AddStmt(S->getSynchBody());
-  Writer.AddSourceLocation(S->getAtSynchronizedLoc(), Record);
-  Code = pch::STMT_OBJC_AT_SYNCHRONIZED;
-}
-
-void PCHStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
-  Writer.AddStmt(S->getThrowExpr());
-  Writer.AddSourceLocation(S->getThrowLoc(), Record);
-  Code = pch::STMT_OBJC_AT_THROW;
-}
-
-//===----------------------------------------------------------------------===//
-// C++ Expressions and Statements.
-//===----------------------------------------------------------------------===//
-
-void PCHStmtWriter::VisitCXXCatchStmt(CXXCatchStmt *S) {
-  VisitStmt(S);
-  Writer.AddSourceLocation(S->getCatchLoc(), Record);
-  Writer.AddDeclRef(S->getExceptionDecl(), Record);
-  Writer.AddStmt(S->getHandlerBlock());
-  Code = pch::STMT_CXX_CATCH;
-}
-
-void PCHStmtWriter::VisitCXXTryStmt(CXXTryStmt *S) {
-  VisitStmt(S);
-  Record.push_back(S->getNumHandlers());
-  Writer.AddSourceLocation(S->getTryLoc(), Record);
-  Writer.AddStmt(S->getTryBlock());
-  for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i)
-    Writer.AddStmt(S->getHandler(i));
-  Code = pch::STMT_CXX_TRY;
-}
-
-void PCHStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
-  VisitCallExpr(E);
-  Record.push_back(E->getOperator());
-  Code = pch::EXPR_CXX_OPERATOR_CALL;
-}
-
-void PCHStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
-  VisitCallExpr(E);
-  Code = pch::EXPR_CXX_MEMBER_CALL;
-}
-
-void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getNumArgs());
-  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
-    Writer.AddStmt(E->getArg(I));
-  Writer.AddDeclRef(E->getConstructor(), Record);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Record.push_back(E->isElidable());
-  Record.push_back(E->requiresZeroInitialization());
-  Record.push_back(E->getConstructionKind()); // FIXME: stable encoding
-  Code = pch::EXPR_CXX_CONSTRUCT;
-}
-
-void PCHStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
-  VisitCXXConstructExpr(E);
-  Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_CXX_TEMPORARY_OBJECT;
-}
-
-void PCHStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
-  VisitExplicitCastExpr(E);
-  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
-}
-
-void PCHStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
-  VisitCXXNamedCastExpr(E);
-  Code = pch::EXPR_CXX_STATIC_CAST;
-}
-
-void PCHStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
-  VisitCXXNamedCastExpr(E);
-  Code = pch::EXPR_CXX_DYNAMIC_CAST;
-}
-
-void PCHStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
-  VisitCXXNamedCastExpr(E);
-  Code = pch::EXPR_CXX_REINTERPRET_CAST;
-}
-
-void PCHStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
-  VisitCXXNamedCastExpr(E);
-  Code = pch::EXPR_CXX_CONST_CAST;
-}
-
-void PCHStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
-  VisitExplicitCastExpr(E);
-  Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_CXX_FUNCTIONAL_CAST;
-}
-
-void PCHStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getValue());
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Code = pch::EXPR_CXX_BOOL_LITERAL;
-}
-
-void PCHStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Code = pch::EXPR_CXX_NULL_PTR_LITERAL;
-}
-
-void PCHStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceRange(E->getSourceRange(), Record);
-  if (E->isTypeOperand()) {
-    Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record);
-    Code = pch::EXPR_CXX_TYPEID_TYPE;
-  } else {
-    Writer.AddStmt(E->getExprOperand());
-    Code = pch::EXPR_CXX_TYPEID_EXPR;
-  }
-}
-
-void PCHStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Record.push_back(E->isImplicit());
-  Code = pch::EXPR_CXX_THIS;
-}
-
-void PCHStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getThrowLoc(), Record);
-  Writer.AddStmt(E->getSubExpr());
-  Code = pch::EXPR_CXX_THROW;
-}
-
-void PCHStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
-  VisitExpr(E);
-
-  bool HasOtherExprStored = E->Param.getInt();
-  // Store these first, the reader reads them before creation.
-  Record.push_back(HasOtherExprStored);
-  if (HasOtherExprStored)
-    Writer.AddStmt(E->getExpr());
-  Writer.AddDeclRef(E->getParam(), Record);
-  Writer.AddSourceLocation(E->getUsedLocation(), Record);
-
-  Code = pch::EXPR_CXX_DEFAULT_ARG;
-}
-
-void PCHStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
-  VisitExpr(E);
-  Writer.AddCXXTemporary(E->getTemporary(), Record);
-  Writer.AddStmt(E->getSubExpr());
-  Code = pch::EXPR_CXX_BIND_TEMPORARY;
-}
-
-void PCHStmtWriter::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E) {
-  VisitExpr(E);
-  Writer.AddStmt(E->getSubExpr());
-  Record.push_back(E->extendsLifetime());
-  Record.push_back(E->requiresTemporaryCopy());
-  Code = pch::EXPR_CXX_BIND_REFERENCE;
-}
-
-void PCHStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
-  VisitExpr(E);
-  Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_CXX_SCALAR_VALUE_INIT;
-}
-
-void PCHStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->isGlobalNew());
-  Record.push_back(E->hasInitializer());
-  Record.push_back(E->isArray());
-  Record.push_back(E->getNumPlacementArgs());
-  Record.push_back(E->getNumConstructorArgs());
-  Writer.AddDeclRef(E->getOperatorNew(), Record);
-  Writer.AddDeclRef(E->getOperatorDelete(), Record);
-  Writer.AddDeclRef(E->getConstructor(), Record);
-  Writer.AddSourceRange(E->getTypeIdParens(), Record);
-  Writer.AddSourceLocation(E->getStartLoc(), Record);
-  Writer.AddSourceLocation(E->getEndLoc(), Record);
-  for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end();
-       I != e; ++I)
-    Writer.AddStmt(*I);
-  
-  Code = pch::EXPR_CXX_NEW;
-}
-
-void PCHStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->isGlobalDelete());
-  Record.push_back(E->isArrayForm());
-  Writer.AddDeclRef(E->getOperatorDelete(), Record);
-  Writer.AddStmt(E->getArgument());
-  Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record);
-  
-  Code = pch::EXPR_CXX_DELETE;
-}
-
-void PCHStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
-  VisitExpr(E);
-
-  Writer.AddStmt(E->getBase());
-  Record.push_back(E->isArrow());
-  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
-  Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
-  Writer.AddSourceRange(E->getQualifierRange(), Record);
-  Writer.AddTypeSourceInfo(E->getScopeTypeInfo(), Record);
-  Writer.AddSourceLocation(E->getColonColonLoc(), Record);
-  Writer.AddSourceLocation(E->getTildeLoc(), Record);
-
-  // PseudoDestructorTypeStorage.
-  Writer.AddIdentifierRef(E->getDestroyedTypeIdentifier(), Record);
-  if (E->getDestroyedTypeIdentifier())
-    Writer.AddSourceLocation(E->getDestroyedTypeLoc(), Record);
-  else
-    Writer.AddTypeSourceInfo(E->getDestroyedTypeInfo(), Record);
-
-  Code = pch::EXPR_CXX_PSEUDO_DESTRUCTOR;
-}
-
-void PCHStmtWriter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
-  VisitExpr(E);
-  Record.push_back(E->getNumTemporaries());
-  for (unsigned i = 0, e = E->getNumTemporaries(); i != e; ++i)
-    Writer.AddCXXTemporary(E->getTemporary(i), Record);
-  
-  Writer.AddStmt(E->getSubExpr());
-  Code = pch::EXPR_CXX_EXPR_WITH_TEMPORARIES;
-}
-
-void
-PCHStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
-  VisitExpr(E);
-  
-  // Don't emit anything here, NumTemplateArgs must be emitted first.
-
-  if (E->hasExplicitTemplateArgs()) {
-    const ExplicitTemplateArgumentList &Args
-      = *E->getExplicitTemplateArgumentList();
-    assert(Args.NumTemplateArgs &&
-           "Num of template args was zero! PCH reading will mess up!");
-    Record.push_back(Args.NumTemplateArgs);
-    AddExplicitTemplateArgumentList(Args);
-  } else {
-    Record.push_back(0);
-  }
-  
-  if (!E->isImplicitAccess())
-    Writer.AddStmt(E->getBase());
-  else
-    Writer.AddStmt(0);
-  Writer.AddTypeRef(E->getBaseType(), Record);
-  Record.push_back(E->isArrow());
-  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
-  Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
-  Writer.AddSourceRange(E->getQualifierRange(), Record);
-  Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record);
-  // FIXME: write whole DeclarationNameInfo.
-  Writer.AddDeclarationName(E->getMember(), Record);
-  Writer.AddSourceLocation(E->getMemberLoc(), Record);
-  Code = pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
-}
-
-void
-PCHStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
-  VisitExpr(E);
-  
-  // Don't emit anything here, NumTemplateArgs must be emitted first.
-
-  if (E->hasExplicitTemplateArgs()) {
-    const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
-    assert(Args.NumTemplateArgs &&
-           "Num of template args was zero! PCH reading will mess up!");
-    Record.push_back(Args.NumTemplateArgs);
-    AddExplicitTemplateArgumentList(Args);
-  } else {
-    Record.push_back(0);
-  }
-
-  // FIXME: write whole DeclarationNameInfo.
-  Writer.AddDeclarationName(E->getDeclName(), Record);
-  Writer.AddSourceLocation(E->getLocation(), Record);
-  Writer.AddSourceRange(E->getQualifierRange(), Record);
-  Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
-  Code = pch::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF;
-}
-
-void
-PCHStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->arg_size());
-  for (CXXUnresolvedConstructExpr::arg_iterator
-         ArgI = E->arg_begin(), ArgE = E->arg_end(); ArgI != ArgE; ++ArgI)
-    Writer.AddStmt(*ArgI);
-  Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
-  Writer.AddTypeRef(E->getTypeAsWritten(), Record);
-  Writer.AddSourceLocation(E->getLParenLoc(), Record);
-  Writer.AddSourceLocation(E->getRParenLoc(), Record);
-  Code = pch::EXPR_CXX_UNRESOLVED_CONSTRUCT;
-}
-
-void PCHStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
-  VisitExpr(E);
-  
-  // Don't emit anything here, NumTemplateArgs must be emitted first.
-
-  if (E->hasExplicitTemplateArgs()) {
-    const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
-    assert(Args.NumTemplateArgs &&
-           "Num of template args was zero! PCH reading will mess up!");
-    Record.push_back(Args.NumTemplateArgs);
-    AddExplicitTemplateArgumentList(Args);
-  } else {
-    Record.push_back(0);
-  }
-
-  Record.push_back(E->getNumDecls());
-  for (OverloadExpr::decls_iterator
-         OvI = E->decls_begin(), OvE = E->decls_end(); OvI != OvE; ++OvI) {
-    Writer.AddDeclRef(OvI.getDecl(), Record);
-    Record.push_back(OvI.getAccess());
-  }
-
-  // FIXME: write whole DeclarationNameInfo.
-  Writer.AddDeclarationName(E->getName(), Record);
-  Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
-  Writer.AddSourceRange(E->getQualifierRange(), Record);
-  Writer.AddSourceLocation(E->getNameLoc(), Record);
-}
-
-void PCHStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
-  VisitOverloadExpr(E);
-  Record.push_back(E->isArrow());
-  Record.push_back(E->hasUnresolvedUsing());
-  Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : 0);
-  Writer.AddTypeRef(E->getBaseType(), Record);
-  Writer.AddSourceLocation(E->getOperatorLoc(), Record);
-  Code = pch::EXPR_CXX_UNRESOLVED_MEMBER;
-}
-
-void PCHStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
-  VisitOverloadExpr(E);
-  Record.push_back(E->requiresADL());
-  Record.push_back(E->isOverloaded());
-  Writer.AddDeclRef(E->getNamingClass(), Record);
-  Code = pch::EXPR_CXX_UNRESOLVED_LOOKUP;
-}
-
-void PCHStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
-  VisitExpr(E);
-  Record.push_back(E->getTrait());
-  Writer.AddSourceRange(E->getSourceRange(), Record);
-  Writer.AddTypeRef(E->getQueriedType(), Record);
-  Code = pch::EXPR_CXX_UNARY_TYPE_TRAIT;
-}
-
-//===----------------------------------------------------------------------===//
-// PCHWriter Implementation
-//===----------------------------------------------------------------------===//
-
-unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) {
-  assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() &&
-         "SwitchCase recorded twice");
-  unsigned NextID = SwitchCaseIDs.size();
-  SwitchCaseIDs[S] = NextID;
-  return NextID;
-}
-
-unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) {
-  assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() &&
-         "SwitchCase hasn't been seen yet");
-  return SwitchCaseIDs[S];
-}
-
-/// \brief Retrieve the ID for the given label statement, which may
-/// or may not have been emitted yet.
-unsigned PCHWriter::GetLabelID(LabelStmt *S) {
-  std::map<LabelStmt *, unsigned>::iterator Pos = LabelIDs.find(S);
-  if (Pos != LabelIDs.end())
-    return Pos->second;
-
-  unsigned NextID = LabelIDs.size();
-  LabelIDs[S] = NextID;
-  return NextID;
-}
-
-/// \brief Write the given substatement or subexpression to the
-/// bitstream.
-void PCHWriter::WriteSubStmt(Stmt *S) {
-  RecordData Record;
-  PCHStmtWriter Writer(*this, Record);
-  ++NumStatements;
-  
-  if (!S) {
-    Stream.EmitRecord(pch::STMT_NULL_PTR, Record);
-    return;
-  }
-
-  // Redirect PCHWriter::AddStmt to collect sub stmts.
-  llvm::SmallVector<Stmt *, 16> SubStmts;
-  CollectedStmts = &SubStmts;
-
-  Writer.Code = pch::STMT_NULL_PTR;
-  Writer.Visit(S);
-  
-#ifndef NDEBUG
-  if (Writer.Code == pch::STMT_NULL_PTR) {
-    SourceManager &SrcMgr
-      = DeclIDs.begin()->first->getASTContext().getSourceManager();
-    S->dump(SrcMgr);
-    assert(0 && "Unhandled sub statement writing PCH file");
-  }
-#endif
-
-  // Revert PCHWriter::AddStmt.
-  CollectedStmts = &StmtsToEmit;
-
-  // Write the sub stmts in reverse order, last to first. When reading them back
-  // we will read them in correct order by "pop"ing them from the Stmts stack.
-  // This simplifies reading and allows to store a variable number of sub stmts
-  // without knowing it in advance.
-  while (!SubStmts.empty())
-    WriteSubStmt(SubStmts.pop_back_val());
-  
-  Stream.EmitRecord(Writer.Code, Record);
-}
-
-/// \brief Flush all of the statements that have been added to the
-/// queue via AddStmt().
-void PCHWriter::FlushStmts() {
-  RecordData Record;
-
-  for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) {
-    WriteSubStmt(StmtsToEmit[I]);
-    
-    assert(N == StmtsToEmit.size() &&
-           "Substatement writen via AddStmt rather than WriteSubStmt!");
-
-    // Note that we are at the end of a full expression. Any
-    // expression records that follow this one are part of a different
-    // expression.
-    Stream.EmitRecord(pch::STMT_STOP, Record);
-  }
-
-  StmtsToEmit.clear();
-}
