diff --git a/lib/Serialization/CMakeLists.txt b/lib/Serialization/CMakeLists.txt
new file mode 100644
index 0000000..a7cd4b5
--- /dev/null
+++ b/lib/Serialization/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangSerialization
+  PCHReader.cpp
+  PCHReaderDecl.cpp
+  PCHReaderStmt.cpp
+  PCHWriter.cpp
+  PCHWriterDecl.cpp
+  PCHWriterStmt.cpp
+  )
+
+add_dependencies(clangSerialization
+  ClangAttrClasses
+  ClangAttrList
+  ClangDiagnosticFrontend
+  ClangDiagnosticLex
+  ClangDiagnosticSema
+  ClangDeclNodes
+  ClangStmtNodes)
diff --git a/lib/Serialization/GeneratePCH.cpp b/lib/Serialization/GeneratePCH.cpp
new file mode 100644
index 0000000..55eaa9c
--- /dev/null
+++ b/lib/Serialization/GeneratePCH.cpp
@@ -0,0 +1,64 @@
+//===--- 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/Serialization/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/Serialization/Makefile b/lib/Serialization/Makefile
new file mode 100644
index 0000000..e89ddc3
--- /dev/null
+++ b/lib/Serialization/Makefile
@@ -0,0 +1,19 @@
+##===- clang/lib/Serialization/Makefile --------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+#
+#  This implements the semantic analyzer and AST builder library for the 
+#  C-Language front-end.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../..
+LIBRARYNAME := clangSerialization
+
+include $(CLANG_LEVEL)/Makefile
+
diff --git a/lib/Serialization/PCHReader.cpp b/lib/Serialization/PCHReader.cpp
new file mode 100644
index 0000000..852bbaf
--- /dev/null
+++ b/lib/Serialization/PCHReader.cpp
@@ -0,0 +1,3857 @@
+//===--- 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/Serialization/PCHReader.h"
+#include "clang/Serialization/PCHDeserializationListener.h"
+#include "clang/Frontend/FrontendDiagnostic.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/Serialization/PCHReaderDecl.cpp b/lib/Serialization/PCHReaderDecl.cpp
new file mode 100644
index 0000000..9b27b03
--- /dev/null
+++ b/lib/Serialization/PCHReaderDecl.cpp
@@ -0,0 +1,1600 @@
+//===--- 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/Serialization/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/Serialization/PCHReaderStmt.cpp b/lib/Serialization/PCHReaderStmt.cpp
new file mode 100644
index 0000000..727dce3
--- /dev/null
+++ b/lib/Serialization/PCHReaderStmt.cpp
@@ -0,0 +1,1775 @@
+//===--- 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/Serialization/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/Serialization/PCHWriter.cpp b/lib/Serialization/PCHWriter.cpp
new file mode 100644
index 0000000..f75373a
--- /dev/null
+++ b/lib/Serialization/PCHWriter.cpp
@@ -0,0 +1,3094 @@
+//===--- 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/Serialization/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/Serialization/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/Serialization/PCHWriterDecl.cpp b/lib/Serialization/PCHWriterDecl.cpp
new file mode 100644
index 0000000..a9ec527
--- /dev/null
+++ b/lib/Serialization/PCHWriterDecl.cpp
@@ -0,0 +1,1174 @@
+//===--- 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/Serialization/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/Serialization/PCHWriterStmt.cpp b/lib/Serialization/PCHWriterStmt.cpp
new file mode 100644
index 0000000..182a272
--- /dev/null
+++ b/lib/Serialization/PCHWriterStmt.cpp
@@ -0,0 +1,1370 @@
+//===--- 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/Serialization/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();
+}
