diff options
Diffstat (limited to 'clang/lib/Serialization')
| -rw-r--r-- | clang/lib/Serialization/CMakeLists.txt | 19 | ||||
| -rw-r--r-- | clang/lib/Serialization/GeneratePCH.cpp | 64 | ||||
| -rw-r--r-- | clang/lib/Serialization/Makefile | 19 | ||||
| -rw-r--r-- | clang/lib/Serialization/PCHReader.cpp | 3857 | ||||
| -rw-r--r-- | clang/lib/Serialization/PCHReaderDecl.cpp | 1600 | ||||
| -rw-r--r-- | clang/lib/Serialization/PCHReaderStmt.cpp | 1775 | ||||
| -rw-r--r-- | clang/lib/Serialization/PCHWriter.cpp | 3094 | ||||
| -rw-r--r-- | clang/lib/Serialization/PCHWriterDecl.cpp | 1174 | ||||
| -rw-r--r-- | clang/lib/Serialization/PCHWriterStmt.cpp | 1370 | 
9 files changed, 12972 insertions, 0 deletions
diff --git a/clang/lib/Serialization/CMakeLists.txt b/clang/lib/Serialization/CMakeLists.txt new file mode 100644 index 00000000000..a7cd4b58ee6 --- /dev/null +++ b/clang/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/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp new file mode 100644 index 00000000000..55eaa9c0840 --- /dev/null +++ b/clang/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/clang/lib/Serialization/Makefile b/clang/lib/Serialization/Makefile new file mode 100644 index 00000000000..e89ddc38ec9 --- /dev/null +++ b/clang/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/clang/lib/Serialization/PCHReader.cpp b/clang/lib/Serialization/PCHReader.cpp new file mode 100644 index 00000000000..852bbaf21aa --- /dev/null +++ b/clang/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/clang/lib/Serialization/PCHReaderDecl.cpp b/clang/lib/Serialization/PCHReaderDecl.cpp new file mode 100644 index 00000000000..9b27b036b69 --- /dev/null +++ b/clang/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/clang/lib/Serialization/PCHReaderStmt.cpp b/clang/lib/Serialization/PCHReaderStmt.cpp new file mode 100644 index 00000000000..727dce39d7c --- /dev/null +++ b/clang/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/clang/lib/Serialization/PCHWriter.cpp b/clang/lib/Serialization/PCHWriter.cpp new file mode 100644 index 00000000000..f75373a33be --- /dev/null +++ b/clang/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/clang/lib/Serialization/PCHWriterDecl.cpp b/clang/lib/Serialization/PCHWriterDecl.cpp new file mode 100644 index 00000000000..a9ec5276e84 --- /dev/null +++ b/clang/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/clang/lib/Serialization/PCHWriterStmt.cpp b/clang/lib/Serialization/PCHWriterStmt.cpp new file mode 100644 index 00000000000..182a2726034 --- /dev/null +++ b/clang/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(); +}  | 

