diff options
Diffstat (limited to 'clang/lib/Serialization')
| -rw-r--r-- | clang/lib/Serialization/ASTCommon.cpp | 77 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTCommon.h | 63 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 6380 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 2481 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderInternals.h | 242 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 2227 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 4552 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 1728 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 1667 | ||||
| -rw-r--r-- | clang/lib/Serialization/CMakeLists.txt | 27 | ||||
| -rw-r--r-- | clang/lib/Serialization/GeneratePCH.cpp | 69 | ||||
| -rw-r--r-- | clang/lib/Serialization/Makefile | 19 | ||||
| -rw-r--r-- | clang/lib/Serialization/Module.cpp | 114 | ||||
| -rw-r--r-- | clang/lib/Serialization/ModuleManager.cpp | 254 | 
14 files changed, 19900 insertions, 0 deletions
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp new file mode 100644 index 0000000..67f74f7 --- /dev/null +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -0,0 +1,77 @@ +//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- 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 common functions that both ASTReader and ASTWriter use. +// +//===----------------------------------------------------------------------===// + +#include "ASTCommon.h" +#include "clang/Serialization/ASTDeserializationListener.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/StringExtras.h" + +using namespace clang; + +// Give ASTDeserializationListener's VTable a home. +ASTDeserializationListener::~ASTDeserializationListener() { } + +serialization::TypeIdx +serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { +  unsigned ID = 0; +  switch (BT->getKind()) { +  case BuiltinType::Void:       ID = PREDEF_TYPE_VOID_ID;       break; +  case BuiltinType::Bool:       ID = PREDEF_TYPE_BOOL_ID;       break; +  case BuiltinType::Char_U:     ID = PREDEF_TYPE_CHAR_U_ID;     break; +  case BuiltinType::UChar:      ID = PREDEF_TYPE_UCHAR_ID;      break; +  case BuiltinType::UShort:     ID = PREDEF_TYPE_USHORT_ID;     break; +  case BuiltinType::UInt:       ID = PREDEF_TYPE_UINT_ID;       break; +  case BuiltinType::ULong:      ID = PREDEF_TYPE_ULONG_ID;      break; +  case BuiltinType::ULongLong:  ID = PREDEF_TYPE_ULONGLONG_ID;  break; +  case BuiltinType::UInt128:    ID = PREDEF_TYPE_UINT128_ID;    break; +  case BuiltinType::Char_S:     ID = PREDEF_TYPE_CHAR_S_ID;     break; +  case BuiltinType::SChar:      ID = PREDEF_TYPE_SCHAR_ID;      break; +  case BuiltinType::WChar_S: +  case BuiltinType::WChar_U:    ID = PREDEF_TYPE_WCHAR_ID;      break; +  case BuiltinType::Short:      ID = PREDEF_TYPE_SHORT_ID;      break; +  case BuiltinType::Int:        ID = PREDEF_TYPE_INT_ID;        break; +  case BuiltinType::Long:       ID = PREDEF_TYPE_LONG_ID;       break; +  case BuiltinType::LongLong:   ID = PREDEF_TYPE_LONGLONG_ID;   break; +  case BuiltinType::Int128:     ID = PREDEF_TYPE_INT128_ID;     break; +  case BuiltinType::Half:       ID = PREDEF_TYPE_HALF_ID;       break; +  case BuiltinType::Float:      ID = PREDEF_TYPE_FLOAT_ID;      break; +  case BuiltinType::Double:     ID = PREDEF_TYPE_DOUBLE_ID;     break; +  case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break; +  case BuiltinType::NullPtr:    ID = PREDEF_TYPE_NULLPTR_ID;    break; +  case BuiltinType::Char16:     ID = PREDEF_TYPE_CHAR16_ID;     break; +  case BuiltinType::Char32:     ID = PREDEF_TYPE_CHAR32_ID;     break; +  case BuiltinType::Overload:   ID = PREDEF_TYPE_OVERLOAD_ID;   break; +  case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER;  break; +  case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break; +  case BuiltinType::Dependent:  ID = PREDEF_TYPE_DEPENDENT_ID;  break; +  case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY;   break; +  case BuiltinType::ARCUnbridgedCast: +                                ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST; break; +  case BuiltinType::ObjCId:     ID = PREDEF_TYPE_OBJC_ID;       break; +  case BuiltinType::ObjCClass:  ID = PREDEF_TYPE_OBJC_CLASS;    break; +  case BuiltinType::ObjCSel:    ID = PREDEF_TYPE_OBJC_SEL;      break; +  } + +  return TypeIdx(ID); +} + +unsigned serialization::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; +} diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h new file mode 100644 index 0000000..16db8e3 --- /dev/null +++ b/clang/lib/Serialization/ASTCommon.h @@ -0,0 +1,63 @@ +//===- ASTCommon.h - Common stuff for ASTReader/ASTWriter -*- 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 common functions that both ASTReader and ASTWriter use. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H +#define LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H + +#include "clang/Serialization/ASTBitCodes.h" +#include "clang/AST/ASTContext.h" + +namespace clang { + +namespace serialization { + +enum DeclUpdateKind { +  UPD_CXX_ADDED_IMPLICIT_MEMBER, +  UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, +  UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, +  UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER +}; + +TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); + +template <typename IdxForTypeTy> +TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) { +  if (T.isNull()) +    return PREDEF_TYPE_NULL_ID; + +  unsigned FastQuals = T.getLocalFastQualifiers(); +  T.removeLocalFastQualifiers(); + +  if (T.hasLocalNonFastQualifiers()) +    return IdxForType(T).asTypeID(FastQuals); + +  assert(!T.hasLocalQualifiers()); + +  if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) +    return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); + +  if (T == Context.AutoDeductTy) +    return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); +  if (T == Context.AutoRRefDeductTy) +    return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); + +  return IdxForType(T).asTypeID(FastQuals); +} + +unsigned ComputeHash(Selector Sel); + +} // namespace serialization + +} // namespace clang + +#endif diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp new file mode 100644 index 0000000..fd0c171 --- /dev/null +++ b/clang/lib/Serialization/ASTReader.cpp @@ -0,0 +1,6380 @@ +//===--- ASTReader.cpp - AST File 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 ASTReader class, which reads AST files. +// +//===----------------------------------------------------------------------===// + +#include "clang/Serialization/ASTReader.h" +#include "clang/Serialization/ASTDeserializationListener.h" +#include "clang/Serialization/ModuleManager.h" +#include "clang/Serialization/SerializationDiagnostic.h" +#include "ASTCommon.h" +#include "ASTReaderInternals.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/Scope.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/NestedNameSpecifier.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/FileSystemStatCache.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Version.h" +#include "clang/Basic/VersionTuple.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/system_error.h" +#include <algorithm> +#include <iterator> +#include <cstdio> +#include <sys/stat.h> + +using namespace clang; +using namespace clang::serialization; +using namespace clang::serialization::reader; + +//===----------------------------------------------------------------------===// +// PCH validator implementation +//===----------------------------------------------------------------------===// + +ASTReaderListener::~ASTReaderListener() {} + +bool +PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { +  const LangOptions &PPLangOpts = PP.getLangOpts(); +   +#define LANGOPT(Name, Bits, Default, Description)         \ +  if (PPLangOpts.Name != LangOpts.Name) {                 \ +    Reader.Diag(diag::err_pch_langopt_mismatch)           \ +      << Description << LangOpts.Name << PPLangOpts.Name; \ +    return true;                                          \ +  } + +#define VALUE_LANGOPT(Name, Bits, Default, Description) \ +  if (PPLangOpts.Name != LangOpts.Name) {               \ +    Reader.Diag(diag::err_pch_langopt_value_mismatch)   \ +      << Description;                                   \ +  return true;                                          \ +} + +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ +  if (PPLangOpts.get##Name() != LangOpts.get##Name()) {      \ +    Reader.Diag(diag::err_pch_langopt_value_mismatch)        \ +      << Description;                                        \ +    return true;                                             \ +  } + +#define BENIGN_LANGOPT(Name, Bits, Default, Description) +#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) +#include "clang/Basic/LangOptions.def" +   +  return false; +} + +bool PCHValidator::ReadTargetTriple(StringRef Triple) { +  if (Triple == PP.getTargetInfo().getTriple().str()) +    return false; + +  Reader.Diag(diag::warn_pch_target_triple) +    << Triple << PP.getTargetInfo().getTriple().str(); +  return true; +} + +namespace { +  struct EmptyStringRef { +    bool operator ()(StringRef r) const { return r.empty(); } +  }; +  struct EmptyBlock { +    bool operator ()(const PCHPredefinesBlock &r) const {return r.Data.empty();} +  }; +} + +static bool EqualConcatenations(SmallVector<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. +  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, StringRef::size_type> +FindMacro(const PCHPredefinesBlocks &Buffers, StringRef MacroDef) { +  std::pair<FileID, StringRef::size_type> Res; +  for (unsigned I = 0, N = Buffers.size(); I != N; ++I) { +    Res.second = Buffers[I].Data.find(MacroDef); +    if (Res.second != StringRef::npos) { +      Res.first = Buffers[I].BufferID; +      break; +    } +  } +  return Res; +} + +bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, +                                        StringRef OriginalFileName, +                                        std::string &SuggestedPredefines, +                                        FileManager &FileMgr) { +  // 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. +  SmallString<256> PCHInclude; +  PCHInclude += "#include \""; +  PCHInclude += HeaderSearch::NormalizeDashIncludePath(OriginalFileName, +                                                       FileMgr); +  PCHInclude += "\"\n"; +  std::pair<StringRef,StringRef> Split = +    StringRef(PP.getPredefines()).split(PCHInclude.str()); +  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. +  SmallVector<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. +  SmallVector<StringRef, 8> PCHLines; +  for (unsigned I = 0, N = Buffers.size(); I != N; ++I) +    Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + +  SmallVector<StringRef, 8> CmdLineLines; +  Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + +  // Pick out implicit #includes after the PCH and don't consider them for +  // validation; we will insert them into SuggestedPredefines so that the +  // preprocessor includes them. +  std::string IncludesAfterPCH; +  SmallVector<StringRef, 8> AfterPCHLines; +  Right.split(AfterPCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); +  for (unsigned i = 0, e = AfterPCHLines.size(); i != e; ++i) { +    if (AfterPCHLines[i].startswith("#include ")) { +      IncludesAfterPCH += AfterPCHLines[i]; +      IncludesAfterPCH += '\n'; +    } else { +      CmdLineLines.push_back(AfterPCHLines[i]); +    } +  } + +  // Make sure we add the includes last into SuggestedPredefines before we +  // exit this function. +  struct AddIncludesRAII { +    std::string &SuggestedPredefines; +    std::string &IncludesAfterPCH; + +    AddIncludesRAII(std::string &SuggestedPredefines, +                    std::string &IncludesAfterPCH) +      : SuggestedPredefines(SuggestedPredefines), +        IncludesAfterPCH(IncludesAfterPCH) { } +    ~AddIncludesRAII() { +      SuggestedPredefines += IncludesAfterPCH; +    } +  } AddIncludes(SuggestedPredefines, IncludesAfterPCH); + +  // 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<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) { +    StringRef Missing = MissingPredefines[I]; +    if (Missing.startswith("#include ")) { +      // An -include was specified when generating the PCH; it is included in +      // the PCH, just ignore it. +      continue; +    } +    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"); +    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(); +    SmallVector<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, StringRef::size_type> MacroLoc = +          FindMacro(Buffers, Missing); +      assert(MacroLoc.second!=StringRef::npos && "Unable to find macro!"); +      SourceLocation PCHMissingLoc = +          SourceMgr.getLocForStartOfFile(MacroLoc.first) +            .getLocWithOffset(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, StringRef::size_type> MacroLoc = +        FindMacro(Buffers, Missing); +    assert(MacroLoc.second!=StringRef::npos && "Unable to find macro!"); +    SourceLocation PCHMissingLoc = +        SourceMgr.getLocForStartOfFile(MacroLoc.first) +          .getLocWithOffset(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<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) { +    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"); +    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); +} + +//===----------------------------------------------------------------------===// +// AST reader implementation +//===----------------------------------------------------------------------===// + +void +ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) { +  DeserializationListener = Listener; +} + + + +unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) { +  return serialization::ComputeHash(Sel); +} + + +std::pair<unsigned, unsigned> +ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) { +  using namespace clang::io; +  unsigned KeyLen = ReadUnalignedLE16(d); +  unsigned DataLen = ReadUnalignedLE16(d); +  return std::make_pair(KeyLen, DataLen); +} + +ASTSelectorLookupTrait::internal_key_type  +ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { +  using namespace clang::io; +  SelectorTable &SelTable = Reader.getContext().Selectors; +  unsigned N = ReadUnalignedLE16(d); +  IdentifierInfo *FirstII +    = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); +  if (N == 0) +    return SelTable.getNullarySelector(FirstII); +  else if (N == 1) +    return SelTable.getUnarySelector(FirstII); + +  SmallVector<IdentifierInfo *, 16> Args; +  Args.push_back(FirstII); +  for (unsigned I = 1; I != N; ++I) +    Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d))); + +  return SelTable.getSelector(N, Args.data()); +} + +ASTSelectorLookupTrait::data_type  +ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,  +                                 unsigned DataLen) { +  using namespace clang::io; + +  data_type Result; + +  Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d)); +  unsigned NumInstanceMethods = ReadUnalignedLE16(d); +  unsigned NumFactoryMethods = ReadUnalignedLE16(d); + +  // Load instance methods +  for (unsigned I = 0; I != NumInstanceMethods; ++I) { +    if (ObjCMethodDecl *Method +          = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d))) +      Result.Instance.push_back(Method); +  } + +  // Load factory methods +  for (unsigned I = 0; I != NumFactoryMethods; ++I) { +    if (ObjCMethodDecl *Method +          = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d))) +      Result.Factory.push_back(Method); +  } + +  return Result; +} + +unsigned ASTIdentifierLookupTrait::ComputeHash(const internal_key_type& a) { +  return llvm::HashString(StringRef(a.first, a.second)); +} + +std::pair<unsigned, unsigned> +ASTIdentifierLookupTrait::ReadKeyDataLength(const unsigned char*& d) { +  using namespace clang::io; +  unsigned DataLen = ReadUnalignedLE16(d); +  unsigned KeyLen = ReadUnalignedLE16(d); +  return std::make_pair(KeyLen, DataLen); +} + +std::pair<const char*, unsigned> +ASTIdentifierLookupTrait::ReadKey(const unsigned char* d, unsigned n) { +  assert(n >= 2 && d[n-1] == '\0'); +  return std::make_pair((const char*) d, n-1); +} + +IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, +                                                   const unsigned char* d, +                                                   unsigned DataLen) { +  using namespace clang::io; +  unsigned RawID = ReadUnalignedLE32(d); +  bool IsInteresting = RawID & 0x01; + +  // Wipe out the "is interesting" bit. +  RawID = RawID >> 1; + +  IdentID ID = Reader.getGlobalIdentifierID(F, RawID); +  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(StringRef(k.first, k.second)); +      KnownII = II; +    } +    Reader.SetIdentifierInfo(ID, II); +    II->setIsFromAST(); +    Reader.markIdentifierUpToDate(II);     +    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 & 0x7FF; +  Bits >>= 11; + +  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(StringRef(k.first, k.second)); +    KnownII = II; +  } +  Reader.markIdentifierUpToDate(II); +  II->setIsFromAST(); + +  // 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; +  if (Poisoned) +    II->setIsPoisoned(true); +  assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword && +         "Incorrect C++ operator keyword flag"); +  (void)CPlusPlusOperatorKeyword; + +  // If this identifier is a macro, deserialize the macro +  // definition. +  if (hasMacroDefinition) { +    // FIXME: Check for conflicts? +    uint32_t Offset = ReadUnalignedLE32(d); +    unsigned LocalSubmoduleID = ReadUnalignedLE32(d); +     +    // Determine whether this macro definition should be visible now, or +    // whether it is in a hidden submodule. +    bool Visible = true; +    if (SubmoduleID GlobalSubmoduleID +          = Reader.getGlobalSubmoduleID(F, LocalSubmoduleID)) { +      if (Module *Owner = Reader.getSubmodule(GlobalSubmoduleID)) { +        if (Owner->NameVisibility == Module::Hidden) { +          // The owning module is not visible, and this macro definition should +          // not be, either. +          Visible = false; +           +          // Note that this macro definition was hidden because its owning  +          // module is not yet visible. +          Reader.HiddenNamesMap[Owner].push_back(II); +        } +      }  +    } +     +    Reader.setIdentifierIsMacro(II, F, Offset, Visible); +    DataLen -= 8; +  } + +  Reader.SetIdentifierInfo(ID, II); + +  // Read all of the declarations visible at global scope with this +  // name. +  if (DataLen > 0) { +    SmallVector<uint32_t, 4> DeclIDs; +    for (; DataLen > 0; DataLen -= 4) +      DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d))); +    Reader.SetGloballyVisibleDecls(II, DeclIDs); +  } + +  return II; +} + +unsigned  +ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const { +  llvm::FoldingSetNodeID ID; +  ID.AddInteger(Key.Kind); + +  switch (Key.Kind) { +  case DeclarationName::Identifier: +  case DeclarationName::CXXLiteralOperatorName: +    ID.AddString(((IdentifierInfo*)Key.Data)->getName()); +    break; +  case DeclarationName::ObjCZeroArgSelector: +  case DeclarationName::ObjCOneArgSelector: +  case DeclarationName::ObjCMultiArgSelector: +    ID.AddInteger(serialization::ComputeHash(Selector(Key.Data))); +    break; +  case DeclarationName::CXXOperatorName: +    ID.AddInteger((OverloadedOperatorKind)Key.Data); +    break; +  case DeclarationName::CXXConstructorName: +  case DeclarationName::CXXDestructorName: +  case DeclarationName::CXXConversionFunctionName: +  case DeclarationName::CXXUsingDirective: +    break; +  } + +  return ID.ComputeHash(); +} + +ASTDeclContextNameLookupTrait::internal_key_type  +ASTDeclContextNameLookupTrait::GetInternalKey( +                                          const external_key_type& Name) const { +  DeclNameKey Key; +  Key.Kind = Name.getNameKind(); +  switch (Name.getNameKind()) { +  case DeclarationName::Identifier: +    Key.Data = (uint64_t)Name.getAsIdentifierInfo(); +    break; +  case DeclarationName::ObjCZeroArgSelector: +  case DeclarationName::ObjCOneArgSelector: +  case DeclarationName::ObjCMultiArgSelector: +    Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr(); +    break; +  case DeclarationName::CXXOperatorName: +    Key.Data = Name.getCXXOverloadedOperator(); +    break; +  case DeclarationName::CXXLiteralOperatorName: +    Key.Data = (uint64_t)Name.getCXXLiteralIdentifier(); +    break; +  case DeclarationName::CXXConstructorName: +  case DeclarationName::CXXDestructorName: +  case DeclarationName::CXXConversionFunctionName: +  case DeclarationName::CXXUsingDirective: +    Key.Data = 0; +    break; +  } + +  return Key; +} + +std::pair<unsigned, unsigned> +ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) { +  using namespace clang::io; +  unsigned KeyLen = ReadUnalignedLE16(d); +  unsigned DataLen = ReadUnalignedLE16(d); +  return std::make_pair(KeyLen, DataLen); +} + +ASTDeclContextNameLookupTrait::internal_key_type  +ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) { +  using namespace clang::io; + +  DeclNameKey Key; +  Key.Kind = (DeclarationName::NameKind)*d++; +  switch (Key.Kind) { +  case DeclarationName::Identifier: +    Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); +    break; +  case DeclarationName::ObjCZeroArgSelector: +  case DeclarationName::ObjCOneArgSelector: +  case DeclarationName::ObjCMultiArgSelector: +    Key.Data = +       (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d)) +                   .getAsOpaquePtr(); +    break; +  case DeclarationName::CXXOperatorName: +    Key.Data = *d++; // OverloadedOperatorKind +    break; +  case DeclarationName::CXXLiteralOperatorName: +    Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)); +    break; +  case DeclarationName::CXXConstructorName: +  case DeclarationName::CXXDestructorName: +  case DeclarationName::CXXConversionFunctionName: +  case DeclarationName::CXXUsingDirective: +    Key.Data = 0; +    break; +  } + +  return Key; +} + +ASTDeclContextNameLookupTrait::data_type  +ASTDeclContextNameLookupTrait::ReadData(internal_key_type,  +                                        const unsigned char* d, +                                        unsigned DataLen) { +  using namespace clang::io; +  unsigned NumDecls = ReadUnalignedLE16(d); +  LE32DeclID *Start = (LE32DeclID *)d; +  return std::make_pair(Start, Start + NumDecls); +} + +bool ASTReader::ReadDeclContextStorage(ModuleFile &M, +                                       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 != DECL_CONTEXT_LEXICAL) { +      Error("Expected lexical block"); +      return true; +    } + +    Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob); +    Info.NumLexicalDecls = BlobLen / sizeof(KindDeclIDPair); +  } + +  // Now the lookup table. +  if (Offsets.second != 0) { +    Cursor.JumpToBit(Offsets.second); + +    RecordData Record; +    const char *Blob; +    unsigned BlobLen; +    unsigned Code = Cursor.ReadCode(); +    unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen); +    if (RecCode != DECL_CONTEXT_VISIBLE) { +      Error("Expected visible lookup table block"); +      return true; +    } +    Info.NameLookupTableData +      = ASTDeclContextNameLookupTable::Create( +                    (const unsigned char *)Blob + Record[0], +                    (const unsigned char *)Blob, +                    ASTDeclContextNameLookupTrait(*this, M)); +  } + +  return false; +} + +void ASTReader::Error(StringRef Msg) { +  Error(diag::err_fe_pch_malformed, Msg); +} + +void ASTReader::Error(unsigned DiagID, +                      StringRef Arg1, StringRef Arg2) { +  if (Diags.isDiagnosticInFlight()) +    Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2); +  else +    Diag(DiagID) << Arg1 << Arg2; +} + +/// \brief Tell the AST listener about the predefines buffers in the chain. +bool ASTReader::CheckPredefinesBuffers() { +  if (Listener) +    return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers, +                                          ActualOriginalFileName, +                                          SuggestedPredefines, +                                          FileMgr); +  return false; +} + +//===----------------------------------------------------------------------===// +// Source Manager Deserialization +//===----------------------------------------------------------------------===// + +/// \brief Read the line table in the source manager block. +/// \returns true if there was an error. +bool ASTReader::ParseLineTable(ModuleFile &F, +                               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); +  } + +  // Parse the line entries +  std::vector<LineEntry> Entries; +  while (Idx < Record.size()) { +    int FID = Record[Idx++]; +    assert(FID >= 0 && "Serialized line entries for non-local file."); +    // Remap FileID from 1-based old view. +    FID += F.SLocEntryBaseID - 1; + +    // 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 ASTStatData { +public: +  const ino_t ino; +  const dev_t dev; +  const mode_t mode; +  const time_t mtime; +  const off_t size; + +  ASTStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s) +    : ino(i), dev(d), mode(mo), mtime(m), size(s) {} +}; + +class ASTStatLookupTrait { + public: +  typedef const char *external_key_type; +  typedef const char *internal_key_type; + +  typedef ASTStatData 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; + +    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 ASTStatCache : public FileSystemStatCache { +  typedef OnDiskChainedHashTable<ASTStatLookupTrait> CacheTy; +  CacheTy *Cache; + +  unsigned &NumStatHits, &NumStatMisses; +public: +  ASTStatCache(const unsigned char *Buckets, const unsigned char *Base, +               unsigned &NumStatHits, unsigned &NumStatMisses) +    : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) { +    Cache = CacheTy::Create(Buckets, Base); +  } + +  ~ASTStatCache() { delete Cache; } + +  LookupResult getStat(const char *Path, struct stat &StatBuf, +                       int *FileDescriptor) { +    // Do the lookup for the file's data in the AST file. +    CacheTy::iterator I = Cache->find(Path); + +    // If we don't get a hit in the AST file just forward to 'stat'. +    if (I == Cache->end()) { +      ++NumStatMisses; +      return statChained(Path, StatBuf, FileDescriptor); +    } + +    ++NumStatHits; +    ASTStatData Data = *I; + +    StatBuf.st_ino = Data.ino; +    StatBuf.st_dev = Data.dev; +    StatBuf.st_mtime = Data.mtime; +    StatBuf.st_mode = Data.mode; +    StatBuf.st_size = Data.size; +    return CacheExists; +  } +}; +} // end anonymous namespace + + +/// \brief Read a source manager block +ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(ModuleFile &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 AST file"); +    return Failure; +  } + +  // Enter the source manager block. +  if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) { +    Error("malformed source manager block record in AST 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 AST 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 AST 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 SM_SLOC_FILE_ENTRY: +    case SM_SLOC_BUFFER_ENTRY: +    case SM_SLOC_EXPANSION_ENTRY: +      // Once we hit one of the source location entries, we're done. +      return Success; +    } +  } +} + +/// \brief If a header file is not found at the path that we expect it to be +/// and the PCH file was moved from its original location, try to resolve the +/// file by assuming that header+PCH were moved together and the header is in +/// the same place relative to the PCH. +static std::string +resolveFileRelativeToOriginalDir(const std::string &Filename, +                                 const std::string &OriginalDir, +                                 const std::string &CurrDir) { +  assert(OriginalDir != CurrDir && +         "No point trying to resolve the file if the PCH dir didn't change"); +  using namespace llvm::sys; +  SmallString<128> filePath(Filename); +  fs::make_absolute(filePath); +  assert(path::is_absolute(OriginalDir)); +  SmallString<128> currPCHPath(CurrDir); + +  path::const_iterator fileDirI = path::begin(path::parent_path(filePath)), +                       fileDirE = path::end(path::parent_path(filePath)); +  path::const_iterator origDirI = path::begin(OriginalDir), +                       origDirE = path::end(OriginalDir); +  // Skip the common path components from filePath and OriginalDir. +  while (fileDirI != fileDirE && origDirI != origDirE && +         *fileDirI == *origDirI) { +    ++fileDirI; +    ++origDirI; +  } +  for (; origDirI != origDirE; ++origDirI) +    path::append(currPCHPath, ".."); +  path::append(currPCHPath, fileDirI, fileDirE); +  path::append(currPCHPath, path::filename(Filename)); +  return currPCHPath.str(); +} + +/// \brief Read in the source location entry with the given ID. +ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { +  if (ID == 0) +    return Success; + +  if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) { +    Error("source location entry ID out-of-range for AST file"); +    return Failure; +  } + +  ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second; +  F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]); +  llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor; +  unsigned BaseOffset = F->SLocEntryBaseOffset; + +  ++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 AST 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 AST file"); +    return Failure; + +  case SM_SLOC_FILE_ENTRY: { +    if (Record.size() < 7) { +      Error("source location entry is incorrect"); +      return Failure; +    } + +    // We will detect whether a file changed and return 'Failure' for it, but +    // we will also try to fail gracefully by setting up the SLocEntry. +    ASTReader::ASTReadResult Result = Success; + +    bool OverriddenBuffer = Record[6]; +     +    std::string OrigFilename(BlobStart, BlobStart + BlobLen); +    std::string Filename = OrigFilename; +    MaybeAddSystemRootToFilename(Filename); +    const FileEntry *File =  +      OverriddenBuffer? FileMgr.getVirtualFile(Filename, (off_t)Record[4], +                                               (time_t)Record[5]) +                      : FileMgr.getFile(Filename, /*OpenFile=*/false); +    if (File == 0 && !OriginalDir.empty() && !CurrentDir.empty() && +        OriginalDir != CurrentDir) { +      std::string resolved = resolveFileRelativeToOriginalDir(Filename, +                                                              OriginalDir, +                                                              CurrentDir); +      if (!resolved.empty()) +        File = FileMgr.getFile(resolved); +    } +    if (File == 0) +      File = FileMgr.getVirtualFile(Filename, (off_t)Record[4], +                                    (time_t)Record[5]); +    if (File == 0) { +      std::string ErrorStr = "could not find file '"; +      ErrorStr += Filename; +      ErrorStr += "' referenced by AST file"; +      Error(ErrorStr.c_str()); +      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 +        )) { +      Error(diag::err_fe_pch_file_modified, Filename); +      Result = Failure; +    } + +    SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); +    if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) { +      // This is the module's main file. +      IncludeLoc = getImportLocation(F); +    } +    FileID FID = SourceMgr.createFileID(File, IncludeLoc, +                                        (SrcMgr::CharacteristicKind)Record[2], +                                        ID, BaseOffset + Record[0]); +    SrcMgr::FileInfo &FileInfo = +          const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()); +    FileInfo.NumCreatedFIDs = Record[7]; +    if (Record[3]) +      FileInfo.setHasLineDirectives(); + +    const DeclID *FirstDecl = F->FileSortedDecls + Record[8]; +    unsigned NumFileDecls = Record[9]; +    if (NumFileDecls) { +      assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); +      FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl, +                                                             NumFileDecls)); +    } +     +    const SrcMgr::ContentCache *ContentCache +      = SourceMgr.getOrCreateContentCache(File); +    if (OverriddenBuffer && !ContentCache->BufferOverridden && +        ContentCache->ContentsEntry == ContentCache->OrigEntry) { +      unsigned Code = SLocEntryCursor.ReadCode(); +      Record.clear(); +      unsigned RecCode +        = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); +       +      if (RecCode != SM_SLOC_BUFFER_BLOB) { +        Error("AST record has invalid code"); +        return Failure; +      } +       +      llvm::MemoryBuffer *Buffer +        = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), +                                           Filename); +      SourceMgr.overrideFileContents(File, Buffer); +    } + +    if (Result == Failure) +      return Failure; +    break; +  } + +  case 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 != SM_SLOC_BUFFER_BLOB) { +      Error("AST record has invalid code"); +      return Failure; +    } + +    llvm::MemoryBuffer *Buffer +      = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), +                                         Name); +    FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, +                                                         BaseOffset + Offset); + +    if (strcmp(Name, "<built-in>") == 0 && F->Kind == MK_PCH) { +      PCHPredefinesBlock Block = { +        BufferID, +        StringRef(BlobStart, BlobLen - 1) +      }; +      PCHPredefinesBuffers.push_back(Block); +    } + +    break; +  } + +  case SM_SLOC_EXPANSION_ENTRY: { +    SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]); +    SourceMgr.createExpansionLoc(SpellingLoc, +                                     ReadSourceLocation(*F, Record[2]), +                                     ReadSourceLocation(*F, Record[3]), +                                     Record[4], +                                     ID, +                                     BaseOffset + Record[0]); +    break; +  } +  } + +  return Success; +} + +/// \brief Find the location where the module F is imported. +SourceLocation ASTReader::getImportLocation(ModuleFile *F) { +  if (F->ImportLoc.isValid()) +    return F->ImportLoc; +   +  // Otherwise we have a PCH. It's considered to be "imported" at the first +  // location of its includer. +  if (F->ImportedBy.empty() || !F->ImportedBy[0]) { +    // Main file is the importer. We assume that it is the first entry in the +    // entry table. We can't ask the manager, because at the time of PCH loading +    // the main file entry doesn't exist yet. +    // The very first entry is the invalid instantiation loc, which takes up +    // offsets 0 and 1. +    return SourceLocation::getFromRawEncoding(2U); +  } +  //return F->Loaders[0]->FirstLoc; +  return F->ImportedBy[0]->FirstLoc; +} + +/// 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 ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, +                                 unsigned BlockID) { +  if (Cursor.EnterSubBlock(BlockID)) { +    Error("malformed block record in AST file"); +    return Failure; +  } + +  while (true) { +    uint64_t Offset = Cursor.GetCurrentBitNo(); +    unsigned Code = Cursor.ReadCode(); + +    // We expect all abbrevs to be at the start of the block. +    if (Code != llvm::bitc::DEFINE_ABBREV) { +      Cursor.JumpToBit(Offset); +      return false; +    } +    Cursor.ReadAbbrevRecord(); +  } +} + +void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { +  llvm::BitstreamCursor &Stream = F.MacroCursor; + +  // 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; +  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 AST file"); +        return; +      } +      continue; + +    case llvm::bitc::DEFINE_ABBREV: +      Stream.ReadAbbrevRecord(); +      continue; +    default: break; +    } + +    // Read a record. +    const char *BlobStart = 0; +    unsigned BlobLen = 0; +    Record.clear(); +    PreprocessorRecordTypes RecType = +      (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record, BlobStart, +                                                 BlobLen); +    switch (RecType) { +    case PP_MACRO_OBJECT_LIKE: +    case 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 = getLocalIdentifier(F, Record[0]); +      if (II == 0) { +        Error("macro must have a name in AST file"); +        return; +      } +       +      SourceLocation Loc = ReadSourceLocation(F, Record[1]); +      bool isUsed = Record[2]; + +      MacroInfo *MI = PP.AllocateMacroInfo(Loc); +      MI->setIsUsed(isUsed); +      MI->setIsFromAST(); + +      bool IsPublic = Record[3]; +      unsigned NextIndex = 4; +      MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex)); +       +      if (RecType == PP_MACRO_FUNCTION_LIKE) { +        // Decode function-like macro info. +        bool isC99VarArgs = Record[NextIndex++]; +        bool isGNUVarArgs = Record[NextIndex++]; +        MacroArgs.clear(); +        unsigned NumArgs = Record[NextIndex++]; +        for (unsigned i = 0; i != NumArgs; ++i) +          MacroArgs.push_back(getLocalIdentifier(F, Record[NextIndex++])); + +        // 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, /*LoadedFromAST=*/true); + +      // 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() && +          Record[NextIndex]) { +        // We have a macro definition. Register the association +        PreprocessedEntityID +            GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]); +        PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); +        PPRec.RegisterMacroDefinition(Macro, +                            PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true)); +      } + +      ++NumMacrosRead; +      break; +    } + +    case 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(ReadSourceLocation(F, Record[0])); +      Tok.setLength(Record[1]); +      if (IdentifierInfo *II = getLocalIdentifier(F, Record[2])) +        Tok.setIdentifierInfo(II); +      Tok.setKind((tok::TokenKind)Record[3]); +      Tok.setFlag((Token::TokenFlags)Record[4]); +      Macro->AddTokenToBody(Tok); +      break; +    } +    } +  } +} + +PreprocessedEntityID  +ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const { +  ContinuousRangeMap<uint32_t, int, 2>::const_iterator  +    I = M.PreprocessedEntityRemap.find(LocalID - NUM_PREDEF_PP_ENTITY_IDS); +  assert(I != M.PreprocessedEntityRemap.end()  +         && "Invalid index into preprocessed entity index remap"); +   +  return LocalID + I->second; +} + +unsigned HeaderFileInfoTrait::ComputeHash(const char *path) { +  return llvm::HashString(llvm::sys::path::filename(path)); +} +     +HeaderFileInfoTrait::internal_key_type  +HeaderFileInfoTrait::GetInternalKey(const char *path) { return path; } +     +bool HeaderFileInfoTrait::EqualKey(internal_key_type a, internal_key_type b) { +  if (strcmp(a, b) == 0) +    return true; +   +  if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b)) +    return false; + +  // Determine whether the actual files are equivalent. +  bool Result = false; +  if (llvm::sys::fs::equivalent(a, b, Result)) +    return false; +   +  return Result; +} +     +std::pair<unsigned, unsigned> +HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) { +  unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d); +  unsigned DataLen = (unsigned) *d++; +  return std::make_pair(KeyLen + 1, DataLen); +} +     +HeaderFileInfoTrait::data_type  +HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d, +                              unsigned DataLen) { +  const unsigned char *End = d + DataLen; +  using namespace clang::io; +  HeaderFileInfo HFI; +  unsigned Flags = *d++; +  HFI.isImport = (Flags >> 5) & 0x01; +  HFI.isPragmaOnce = (Flags >> 4) & 0x01; +  HFI.DirInfo = (Flags >> 2) & 0x03; +  HFI.Resolved = (Flags >> 1) & 0x01; +  HFI.IndexHeaderMapHeader = Flags & 0x01; +  HFI.NumIncludes = ReadUnalignedLE16(d); +  HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M,  +                                                        ReadUnalignedLE32(d)); +  if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) { +    // The framework offset is 1 greater than the actual offset,  +    // since 0 is used as an indicator for "no framework name". +    StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1); +    HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); +  } +   +  assert(End == d && "Wrong data length in HeaderFileInfo deserialization"); +  (void)End; +         +  // This HeaderFileInfo was externally loaded. +  HFI.External = true; +  return HFI; +} + +void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ModuleFile &F, +                                     uint64_t LocalOffset, bool Visible) { +  if (Visible) { +    // Note that this identifier has a macro definition. +    II->setHasMacroDefinition(true); +  } +   +  // Adjust the offset to a global offset. +  UnreadMacroRecordOffsets[II] = F.GlobalBitOffset + LocalOffset; +} + +void ASTReader::ReadDefinedMacros() { +  for (ModuleReverseIterator I = ModuleMgr.rbegin(), +      E = ModuleMgr.rend(); I != E; ++I) { +    llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor; + +    // If there was no preprocessor block, skip this file. +    if (!MacroCursor.getBitStreamReader()) +      continue; + +    llvm::BitstreamCursor Cursor = MacroCursor; +    Cursor.JumpToBit((*I)->MacroStartOffset); + +    RecordData Record; +    while (true) { +      unsigned Code = Cursor.ReadCode(); +      if (Code == llvm::bitc::END_BLOCK) +        break; + +      if (Code == llvm::bitc::ENTER_SUBBLOCK) { +        // No known subblocks, always skip them. +        Cursor.ReadSubBlockID(); +        if (Cursor.SkipBlock()) { +          Error("malformed block record in AST 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 PP_MACRO_OBJECT_LIKE: +      case PP_MACRO_FUNCTION_LIKE: +        getLocalIdentifier(**I, Record[0]); +        break; + +      case PP_TOKEN: +        // Ignore tokens. +        break; +      } +    } +  } +   +  // Drain the unread macro-record offsets map. +  while (!UnreadMacroRecordOffsets.empty()) +    LoadMacroDefinition(UnreadMacroRecordOffsets.begin()); +} + +void ASTReader::LoadMacroDefinition( +                    llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) { +  assert(Pos != UnreadMacroRecordOffsets.end() && "Unknown macro definition"); +  uint64_t Offset = Pos->second; +  UnreadMacroRecordOffsets.erase(Pos); +   +  RecordLocation Loc = getLocalBitOffset(Offset); +  ReadMacroRecord(*Loc.F, Loc.Offset); +} + +void ASTReader::LoadMacroDefinition(IdentifierInfo *II) { +  llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos +    = UnreadMacroRecordOffsets.find(II); +  LoadMacroDefinition(Pos); +} + +namespace { +  /// \brief Visitor class used to look up identifirs in an AST file. +  class IdentifierLookupVisitor { +    StringRef Name; +    unsigned PriorGeneration; +    IdentifierInfo *Found; +  public: +    IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration)  +      : Name(Name), PriorGeneration(PriorGeneration), Found() { } +     +    static bool visit(ModuleFile &M, void *UserData) { +      IdentifierLookupVisitor *This +        = static_cast<IdentifierLookupVisitor *>(UserData); +       +      // If we've already searched this module file, skip it now. +      if (M.Generation <= This->PriorGeneration) +        return true; +       +      ASTIdentifierLookupTable *IdTable +        = (ASTIdentifierLookupTable *)M.IdentifierLookupTable; +      if (!IdTable) +        return false; +       +      ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(), +                                     M, This->Found); +                                      +      std::pair<const char*, unsigned> Key(This->Name.begin(),  +                                           This->Name.size()); +      ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Trait); +      if (Pos == IdTable->end()) +        return false; +       +      // Dereferencing the iterator has the effect of building the +      // IdentifierInfo node and populating it with the various +      // declarations it needs. +      This->Found = *Pos; +      return true; +    } +     +    // \brief Retrieve the identifier info found within the module +    // files. +    IdentifierInfo *getIdentifierInfo() const { return Found; } +  }; +} + +void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) { +  unsigned PriorGeneration = 0; +  if (getContext().getLangOpts().Modules) +    PriorGeneration = IdentifierGeneration[&II]; +   +  IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration); +  ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); +  markIdentifierUpToDate(&II); +} + +void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { +  if (!II) +    return; +   +  II->setOutOfDate(false); + +  // Update the generation for this identifier. +  if (getContext().getLangOpts().Modules) +    IdentifierGeneration[II] = CurrentGeneration; +} + +const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { +  std::string Filename = filenameStrRef; +  MaybeAddSystemRootToFilename(Filename); +  const FileEntry *File = FileMgr.getFile(Filename); +  if (File == 0 && !OriginalDir.empty() && !CurrentDir.empty() && +      OriginalDir != CurrentDir) { +    std::string resolved = resolveFileRelativeToOriginalDir(Filename, +                                                            OriginalDir, +                                                            CurrentDir); +    if (!resolved.empty()) +      File = FileMgr.getFile(resolved); +  } + +  return File; +} + +/// \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 ASTReader::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::is_absolute(Filename)) +    return; + +  if (isysroot.empty()) { +    // If no system root was given, default to '/' +    Filename.insert(Filename.begin(), '/'); +    return; +  } + +  unsigned Length = isysroot.size(); +  if (isysroot[Length - 1] != '/') +    Filename.insert(Filename.begin(), '/'); + +  Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end()); +} + +ASTReader::ASTReadResult +ASTReader::ReadASTBlock(ModuleFile &F) { +  llvm::BitstreamCursor &Stream = F.Stream; + +  if (Stream.EnterSubBlock(AST_BLOCK_ID)) { +    Error("malformed block record in AST file"); +    return Failure; +  } + +  // Read all of the records and blocks for the ASt file. +  RecordData Record; +  while (!Stream.AtEndOfStream()) { +    unsigned Code = Stream.ReadCode(); +    if (Code == llvm::bitc::END_BLOCK) { +      if (Stream.ReadBlockEnd()) { +        Error("error at end of module block in AST file"); +        return Failure; +      } + +      return Success; +    } + +    if (Code == llvm::bitc::ENTER_SUBBLOCK) { +      switch (Stream.ReadSubBlockID()) { +      case 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, DECLTYPES_BLOCK_ID)) { +          Error("malformed block record in AST file"); +          return Failure; +        } +        break; + +      case DECL_UPDATES_BLOCK_ID: +        if (Stream.SkipBlock()) { +          Error("malformed block record in AST file"); +          return Failure; +        } +        break; + +      case PREPROCESSOR_BLOCK_ID: +        F.MacroCursor = Stream; +        if (!PP.getExternalSource()) +          PP.setExternalSource(this); + +        if (Stream.SkipBlock() || +            ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) { +          Error("malformed block record in AST file"); +          return Failure; +        } +        F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo(); +        break; + +      case PREPROCESSOR_DETAIL_BLOCK_ID: +        F.PreprocessorDetailCursor = Stream; +        if (Stream.SkipBlock() || +            ReadBlockAbbrevs(F.PreprocessorDetailCursor,  +                             PREPROCESSOR_DETAIL_BLOCK_ID)) { +          Error("malformed preprocessor detail record in AST file"); +          return Failure; +        } +        F.PreprocessorDetailStartOffset +          = F.PreprocessorDetailCursor.GetCurrentBitNo(); +           +        if (!PP.getPreprocessingRecord()) +          PP.createPreprocessingRecord(/*RecordConditionalDirectives=*/false); +        if (!PP.getPreprocessingRecord()->getExternalSource()) +          PP.getPreprocessingRecord()->SetExternalSource(*this); +        break; +         +      case SOURCE_MANAGER_BLOCK_ID: +        switch (ReadSourceManagerBlock(F)) { +        case Success: +          break; + +        case Failure: +          Error("malformed source manager block in AST file"); +          return Failure; + +        case IgnorePCH: +          return IgnorePCH; +        } +        break; + +      case SUBMODULE_BLOCK_ID: +        switch (ReadSubmoduleBlock(F)) { +        case Success: +          break; +           +        case Failure: +          Error("malformed submodule block in AST file"); +          return Failure; +           +        case IgnorePCH: +          return IgnorePCH;             +        } +        break; + +      default: +        if (!Stream.SkipBlock()) +          break; +        Error("malformed block record in AST file"); +        return Failure; +      } +      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 ((ASTRecordTypes)Stream.ReadRecord(Code, Record, +                                              &BlobStart, &BlobLen)) { +    default:  // Default behavior: ignore. +      break; + +    case METADATA: { +      if (Record[0] != VERSION_MAJOR && !DisableValidation) { +        Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old +                                           : diag::warn_pch_version_too_new); +        return IgnorePCH; +      } + +      bool hasErrors = Record[5]; +      if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) { +        Diag(diag::err_pch_with_compiler_errors); +        return IgnorePCH; +      } + +      RelocatablePCH = Record[4]; +      if (Listener) { +        std::string TargetTriple(BlobStart, BlobLen); +        if (Listener->ReadTargetTriple(TargetTriple)) +          return IgnorePCH; +      } +      break; +    } + +    case IMPORTS: { +      // Load each of the imported PCH files.  +      unsigned Idx = 0, N = Record.size(); +      while (Idx < N) { +        // Read information about the AST file. +        ModuleKind ImportedKind = (ModuleKind)Record[Idx++]; +        unsigned Length = Record[Idx++]; +        SmallString<128> ImportedFile(Record.begin() + Idx, +                                            Record.begin() + Idx + Length); +        Idx += Length; + +        // Load the AST file. +        switch(ReadASTCore(ImportedFile, ImportedKind, &F)) { +        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 TYPE_OFFSET: { +      if (F.LocalNumTypes != 0) { +        Error("duplicate TYPE_OFFSET record in AST file"); +        return Failure; +      } +      F.TypeOffsets = (const uint32_t *)BlobStart; +      F.LocalNumTypes = Record[0]; +      unsigned LocalBaseTypeIndex = Record[1]; +      F.BaseTypeIndex = getTotalNumTypes(); +         +      if (F.LocalNumTypes > 0) { +        // Introduce the global -> local mapping for types within this module. +        GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F)); +         +        // Introduce the local -> global mapping for types within this module. +        F.TypeRemap.insertOrReplace( +          std::make_pair(LocalBaseTypeIndex,  +                         F.BaseTypeIndex - LocalBaseTypeIndex)); +         +        TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes); +      } +      break; +    } +         +    case DECL_OFFSET: { +      if (F.LocalNumDecls != 0) { +        Error("duplicate DECL_OFFSET record in AST file"); +        return Failure; +      } +      F.DeclOffsets = (const DeclOffset *)BlobStart; +      F.LocalNumDecls = Record[0]; +      unsigned LocalBaseDeclID = Record[1]; +      F.BaseDeclID = getTotalNumDecls(); +         +      if (F.LocalNumDecls > 0) { +        // Introduce the global -> local mapping for declarations within this  +        // module. +        GlobalDeclMap.insert( +          std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F)); +         +        // Introduce the local -> global mapping for declarations within this +        // module. +        F.DeclRemap.insertOrReplace( +          std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID)); +         +        // Introduce the global -> local mapping for declarations within this +        // module. +        F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID; +         +        DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls); +      } +      break; +    } +         +    case TU_UPDATE_LEXICAL: { +      DeclContext *TU = Context.getTranslationUnitDecl(); +      DeclContextInfo &Info = F.DeclContextInfos[TU]; +      Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair *>(BlobStart); +      Info.NumLexicalDecls  +        = static_cast<unsigned int>(BlobLen / sizeof(KindDeclIDPair)); +      TU->setHasExternalLexicalStorage(true); +      break; +    } + +    case UPDATE_VISIBLE: { +      unsigned Idx = 0; +      serialization::DeclID ID = ReadDeclID(F, Record, Idx); +      ASTDeclContextNameLookupTable *Table = +        ASTDeclContextNameLookupTable::Create( +                        (const unsigned char *)BlobStart + Record[Idx++], +                        (const unsigned char *)BlobStart, +                        ASTDeclContextNameLookupTrait(*this, F)); +      if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU? +        DeclContext *TU = Context.getTranslationUnitDecl(); +        F.DeclContextInfos[TU].NameLookupTableData = Table; +        TU->setHasExternalVisibleStorage(true); +      } else +        PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F)); +      break; +    } + +    case LANGUAGE_OPTIONS: +      if (ParseLanguageOptions(Record) && !DisableValidation) +        return IgnorePCH; +      break; + +    case IDENTIFIER_TABLE: +      F.IdentifierTableData = BlobStart; +      if (Record[0]) { +        F.IdentifierLookupTable +          = ASTIdentifierLookupTable::Create( +                       (const unsigned char *)F.IdentifierTableData + Record[0], +                       (const unsigned char *)F.IdentifierTableData, +                       ASTIdentifierLookupTrait(*this, F)); +         +        PP.getIdentifierTable().setExternalIdentifierLookup(this); +      } +      break; + +    case IDENTIFIER_OFFSET: { +      if (F.LocalNumIdentifiers != 0) { +        Error("duplicate IDENTIFIER_OFFSET record in AST file"); +        return Failure; +      } +      F.IdentifierOffsets = (const uint32_t *)BlobStart; +      F.LocalNumIdentifiers = Record[0]; +      unsigned LocalBaseIdentifierID = Record[1]; +      F.BaseIdentifierID = getTotalNumIdentifiers(); +         +      if (F.LocalNumIdentifiers > 0) { +        // Introduce the global -> local mapping for identifiers within this +        // module. +        GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1,  +                                                  &F)); +         +        // Introduce the local -> global mapping for identifiers within this +        // module. +        F.IdentifierRemap.insertOrReplace( +          std::make_pair(LocalBaseIdentifierID, +                         F.BaseIdentifierID - LocalBaseIdentifierID)); +         +        IdentifiersLoaded.resize(IdentifiersLoaded.size()  +                                 + F.LocalNumIdentifiers); +      } +      break; +    } +         +    case EXTERNAL_DEFINITIONS: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I])); +      break; + +    case SPECIAL_TYPES: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        SpecialTypes.push_back(getGlobalTypeID(F, Record[I])); +      break; + +    case STATISTICS: +      TotalNumStatements += Record[0]; +      TotalNumMacros += Record[1]; +      TotalLexicalDeclContexts += Record[2]; +      TotalVisibleDeclContexts += Record[3]; +      break; + +    case UNUSED_FILESCOPED_DECLS: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I])); +      break; + +    case DELEGATING_CTORS: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I])); +      break; + +    case WEAK_UNDECLARED_IDENTIFIERS: +      if (Record.size() % 4 != 0) { +        Error("invalid weak identifiers record"); +        return Failure; +      } +         +      // FIXME: Ignore weak undeclared identifiers from non-original PCH  +      // files. This isn't the way to do it :) +      WeakUndeclaredIdentifiers.clear(); +         +      // Translate the weak, undeclared identifiers into global IDs. +      for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) { +        WeakUndeclaredIdentifiers.push_back( +          getGlobalIdentifierID(F, Record[I++])); +        WeakUndeclaredIdentifiers.push_back( +          getGlobalIdentifierID(F, Record[I++])); +        WeakUndeclaredIdentifiers.push_back( +          ReadSourceLocation(F, Record, I).getRawEncoding()); +        WeakUndeclaredIdentifiers.push_back(Record[I++]); +      } +      break; + +    case LOCALLY_SCOPED_EXTERNAL_DECLS: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        LocallyScopedExternalDecls.push_back(getGlobalDeclID(F, Record[I])); +      break; + +    case SELECTOR_OFFSETS: { +      F.SelectorOffsets = (const uint32_t *)BlobStart; +      F.LocalNumSelectors = Record[0]; +      unsigned LocalBaseSelectorID = Record[1]; +      F.BaseSelectorID = getTotalNumSelectors(); +         +      if (F.LocalNumSelectors > 0) { +        // Introduce the global -> local mapping for selectors within this  +        // module. +        GlobalSelectorMap.insert(std::make_pair(getTotalNumSelectors()+1, &F)); +         +        // Introduce the local -> global mapping for selectors within this  +        // module. +        F.SelectorRemap.insertOrReplace( +          std::make_pair(LocalBaseSelectorID, +                         F.BaseSelectorID - LocalBaseSelectorID)); + +        SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);         +      } +      break; +    } +         +    case METHOD_POOL: +      F.SelectorLookupTableData = (const unsigned char *)BlobStart; +      if (Record[0]) +        F.SelectorLookupTable +          = ASTSelectorLookupTable::Create( +                        F.SelectorLookupTableData + Record[0], +                        F.SelectorLookupTableData, +                        ASTSelectorLookupTrait(*this, F)); +      TotalNumMethodPoolEntries += Record[1]; +      break; + +    case REFERENCED_SELECTOR_POOL: +      if (!Record.empty()) { +        for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) { +          ReferencedSelectorsData.push_back(getGlobalSelectorID(F,  +                                                                Record[Idx++])); +          ReferencedSelectorsData.push_back(ReadSourceLocation(F, Record, Idx). +                                              getRawEncoding()); +        } +      } +      break; + +    case PP_COUNTER_VALUE: +      if (!Record.empty() && Listener) +        Listener->ReadCounter(Record[0]); +      break; +       +    case FILE_SORTED_DECLS: +      F.FileSortedDecls = (const DeclID *)BlobStart; +      break; + +    case SOURCE_LOCATION_OFFSETS: { +      F.SLocEntryOffsets = (const uint32_t *)BlobStart; +      F.LocalNumSLocEntries = Record[0]; +      unsigned SLocSpaceSize = Record[1]; +      llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) = +          SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries, +                                              SLocSpaceSize); +      // Make our entry in the range map. BaseID is negative and growing, so +      // we invert it. Because we invert it, though, we need the other end of +      // the range. +      unsigned RangeStart = +          unsigned(-F.SLocEntryBaseID) - F.LocalNumSLocEntries + 1; +      GlobalSLocEntryMap.insert(std::make_pair(RangeStart, &F)); +      F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset); + +      // SLocEntryBaseOffset is lower than MaxLoadedOffset and decreasing. +      assert((F.SLocEntryBaseOffset & (1U << 31U)) == 0); +      GlobalSLocOffsetMap.insert( +          std::make_pair(SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset +                           - SLocSpaceSize,&F)); + +      // Initialize the remapping table. +      // Invalid stays invalid. +      F.SLocRemap.insert(std::make_pair(0U, 0)); +      // This module. Base was 2 when being compiled. +      F.SLocRemap.insert(std::make_pair(2U, +                                  static_cast<int>(F.SLocEntryBaseOffset - 2))); +       +      TotalNumSLocEntries += F.LocalNumSLocEntries; +      break; +    } + +    case MODULE_OFFSET_MAP: { +      // Additional remapping information. +      const unsigned char *Data = (const unsigned char*)BlobStart; +      const unsigned char *DataEnd = Data + BlobLen; +       +      // Continuous range maps we may be updating in our module. +      ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap); +      ContinuousRangeMap<uint32_t, int, 2>::Builder  +        IdentifierRemap(F.IdentifierRemap); +      ContinuousRangeMap<uint32_t, int, 2>::Builder  +        PreprocessedEntityRemap(F.PreprocessedEntityRemap); +      ContinuousRangeMap<uint32_t, int, 2>::Builder  +        SubmoduleRemap(F.SubmoduleRemap); +      ContinuousRangeMap<uint32_t, int, 2>::Builder  +        SelectorRemap(F.SelectorRemap); +      ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap); +      ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap); + +      while(Data < DataEnd) { +        uint16_t Len = io::ReadUnalignedLE16(Data); +        StringRef Name = StringRef((const char*)Data, Len); +        Data += Len; +        ModuleFile *OM = ModuleMgr.lookup(Name); +        if (!OM) { +          Error("SourceLocation remap refers to unknown module"); +          return Failure; +        } + +        uint32_t SLocOffset = io::ReadUnalignedLE32(Data); +        uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data); +        uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data); +        uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data); +        uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data); +        uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data); +        uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data); +         +        // Source location offset is mapped to OM->SLocEntryBaseOffset. +        SLocRemap.insert(std::make_pair(SLocOffset, +          static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset))); +        IdentifierRemap.insert( +          std::make_pair(IdentifierIDOffset,  +                         OM->BaseIdentifierID - IdentifierIDOffset)); +        PreprocessedEntityRemap.insert( +          std::make_pair(PreprocessedEntityIDOffset,  +            OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset)); +        SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset,  +                                      OM->BaseSubmoduleID - SubmoduleIDOffset)); +        SelectorRemap.insert(std::make_pair(SelectorIDOffset,  +                               OM->BaseSelectorID - SelectorIDOffset)); +        DeclRemap.insert(std::make_pair(DeclIDOffset,  +                                        OM->BaseDeclID - DeclIDOffset)); +         +        TypeRemap.insert(std::make_pair(TypeIndexOffset,  +                                    OM->BaseTypeIndex - TypeIndexOffset)); + +        // Global -> local mappings. +        F.GlobalToLocalDeclIDs[OM] = DeclIDOffset; +      } +      break; +    } + +    case SOURCE_MANAGER_LINE_TABLE: +      if (ParseLineTable(F, Record)) +        return Failure; +      break; + +    case FILE_SOURCE_LOCATION_OFFSETS: +      F.SLocFileOffsets = (const uint32_t *)BlobStart; +      F.LocalNumSLocFileEntries = Record[0]; +      break; + +    case SOURCE_LOCATION_PRELOADS: { +      // Need to transform from the local view (1-based IDs) to the global view, +      // which is based off F.SLocEntryBaseID. +      if (!F.PreloadSLocEntries.empty()) { +        Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file"); +        return Failure; +      } +       +      F.PreloadSLocEntries.swap(Record); +      break; +    } + +    case STAT_CACHE: { +      if (!DisableStatCache) { +        ASTStatCache *MyStatCache = +          new ASTStatCache((const unsigned char *)BlobStart + Record[0], +                           (const unsigned char *)BlobStart, +                           NumStatHits, NumStatMisses); +        FileMgr.addStatCache(MyStatCache); +        F.StatCache = MyStatCache; +      } +      break; +    } + +    case EXT_VECTOR_DECLS: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I])); +      break; + +    case VTABLE_USES: +      if (Record.size() % 3 != 0) { +        Error("Invalid VTABLE_USES record"); +        return Failure; +      } +         +      // Later tables overwrite earlier ones. +      // FIXME: Modules will have some trouble with this. This is clearly not +      // the right way to do this. +      VTableUses.clear(); +         +      for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) { +        VTableUses.push_back(getGlobalDeclID(F, Record[Idx++])); +        VTableUses.push_back( +          ReadSourceLocation(F, Record, Idx).getRawEncoding()); +        VTableUses.push_back(Record[Idx++]); +      } +      break; + +    case DYNAMIC_CLASSES: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        DynamicClasses.push_back(getGlobalDeclID(F, Record[I])); +      break; + +    case PENDING_IMPLICIT_INSTANTIATIONS: +      if (PendingInstantiations.size() % 2 != 0) { +        Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block"); +        return Failure; +      } +         +      // Later lists of pending instantiations overwrite earlier ones. +      // FIXME: This is most certainly wrong for modules. +      PendingInstantiations.clear(); +      for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { +        PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++])); +        PendingInstantiations.push_back( +          ReadSourceLocation(F, Record, I).getRawEncoding()); +      } +      break; + +    case SEMA_DECL_REFS: +      // Later tables overwrite earlier ones. +      // FIXME: Modules will have some trouble with this. +      SemaDeclRefs.clear(); +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I])); +      break; + +    case ORIGINAL_FILE_NAME: +      // The primary AST 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 ORIGINAL_FILE_ID: +      OriginalFileID = FileID::get(Record[0]); +      break; +         +    case ORIGINAL_PCH_DIR: +      // The primary AST will be the last to get here, so it will be the one +      // that's used. +      OriginalDir.assign(BlobStart, BlobLen); +      break; + +    case VERSION_CONTROL_BRANCH_REVISION: { +      const std::string &CurBranch = getClangFullRepositoryVersion(); +      StringRef ASTBranch(BlobStart, BlobLen); +      if (StringRef(CurBranch) != ASTBranch && !DisableValidation) { +        Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch; +        return IgnorePCH; +      } +      break; +    } + +    case PPD_ENTITIES_OFFSETS: { +      F.PreprocessedEntityOffsets = (const PPEntityOffset *)BlobStart; +      assert(BlobLen % sizeof(PPEntityOffset) == 0); +      F.NumPreprocessedEntities = BlobLen / sizeof(PPEntityOffset); + +      unsigned LocalBasePreprocessedEntityID = Record[0]; +       +      unsigned StartingID; +      if (!PP.getPreprocessingRecord()) +        PP.createPreprocessingRecord(/*RecordConditionalDirectives=*/false); +      if (!PP.getPreprocessingRecord()->getExternalSource()) +        PP.getPreprocessingRecord()->SetExternalSource(*this); +      StartingID  +        = PP.getPreprocessingRecord() +            ->allocateLoadedEntities(F.NumPreprocessedEntities); +      F.BasePreprocessedEntityID = StartingID; + +      if (F.NumPreprocessedEntities > 0) { +        // Introduce the global -> local mapping for preprocessed entities in +        // this module. +        GlobalPreprocessedEntityMap.insert(std::make_pair(StartingID, &F)); +        +        // Introduce the local -> global mapping for preprocessed entities in +        // this module. +        F.PreprocessedEntityRemap.insertOrReplace( +          std::make_pair(LocalBasePreprocessedEntityID, +            F.BasePreprocessedEntityID - LocalBasePreprocessedEntityID)); +      } + +      break; +    } +         +    case DECL_UPDATE_OFFSETS: { +      if (Record.size() % 2 != 0) { +        Error("invalid DECL_UPDATE_OFFSETS block in AST file"); +        return Failure; +      } +      for (unsigned I = 0, N = Record.size(); I != N; I += 2) +        DeclUpdateOffsets[getGlobalDeclID(F, Record[I])] +          .push_back(std::make_pair(&F, Record[I+1])); +      break; +    } + +    case DECL_REPLACEMENTS: { +      if (Record.size() % 3 != 0) { +        Error("invalid DECL_REPLACEMENTS block in AST file"); +        return Failure; +      } +      for (unsigned I = 0, N = Record.size(); I != N; I += 3) +        ReplacedDecls[getGlobalDeclID(F, Record[I])] +          = ReplacedDeclInfo(&F, Record[I+1], Record[I+2]); +      break; +    } + +    case OBJC_CATEGORIES_MAP: { +      if (F.LocalNumObjCCategoriesInMap != 0) { +        Error("duplicate OBJC_CATEGORIES_MAP record in AST file"); +        return Failure; +      } +       +      F.LocalNumObjCCategoriesInMap = Record[0]; +      F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)BlobStart; +      break; +    } +         +    case OBJC_CATEGORIES: +      F.ObjCCategories.swap(Record); +      break; +         +    case CXX_BASE_SPECIFIER_OFFSETS: { +      if (F.LocalNumCXXBaseSpecifiers != 0) { +        Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file"); +        return Failure; +      } +       +      F.LocalNumCXXBaseSpecifiers = Record[0]; +      F.CXXBaseSpecifiersOffsets = (const uint32_t *)BlobStart; +      NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers; +      break; +    } + +    case DIAG_PRAGMA_MAPPINGS: +      if (Record.size() % 2 != 0) { +        Error("invalid DIAG_USER_MAPPINGS block in AST file"); +        return Failure; +      } +         +      if (F.PragmaDiagMappings.empty()) +        F.PragmaDiagMappings.swap(Record); +      else +        F.PragmaDiagMappings.insert(F.PragmaDiagMappings.end(), +                                    Record.begin(), Record.end()); +      break; +         +    case CUDA_SPECIAL_DECL_REFS: +      // Later tables overwrite earlier ones. +      // FIXME: Modules will have trouble with this. +      CUDASpecialDeclRefs.clear(); +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I])); +      break; + +    case HEADER_SEARCH_TABLE: { +      F.HeaderFileInfoTableData = BlobStart; +      F.LocalNumHeaderFileInfos = Record[1]; +      F.HeaderFileFrameworkStrings = BlobStart + Record[2]; +      if (Record[0]) { +        F.HeaderFileInfoTable +          = HeaderFileInfoLookupTable::Create( +                   (const unsigned char *)F.HeaderFileInfoTableData + Record[0], +                   (const unsigned char *)F.HeaderFileInfoTableData, +                   HeaderFileInfoTrait(*this, F,  +                                       &PP.getHeaderSearchInfo(), +                                       BlobStart + Record[2])); +         +        PP.getHeaderSearchInfo().SetExternalSource(this); +        if (!PP.getHeaderSearchInfo().getExternalLookup()) +          PP.getHeaderSearchInfo().SetExternalLookup(this); +      } +      break; +    } +         +    case FP_PRAGMA_OPTIONS: +      // Later tables overwrite earlier ones. +      FPPragmaOptions.swap(Record); +      break; + +    case OPENCL_EXTENSIONS: +      // Later tables overwrite earlier ones. +      OpenCLExtensions.swap(Record); +      break; + +    case TENTATIVE_DEFINITIONS: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I])); +      break; +         +    case KNOWN_NAMESPACES: +      for (unsigned I = 0, N = Record.size(); I != N; ++I) +        KnownNamespaces.push_back(getGlobalDeclID(F, Record[I])); +      break; +         +    case IMPORTED_MODULES: { +      if (F.Kind != MK_Module) { +        // If we aren't loading a module (which has its own exports), make +        // all of the imported modules visible. +        // FIXME: Deal with macros-only imports. +        for (unsigned I = 0, N = Record.size(); I != N; ++I) { +          if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I])) +            ImportedModules.push_back(GlobalID); +        } +      } +      break; +    } + +    case LOCAL_REDECLARATIONS: { +      F.RedeclarationChains.swap(Record); +      break; +    } +         +    case LOCAL_REDECLARATIONS_MAP: { +      if (F.LocalNumRedeclarationsInMap != 0) { +        Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file"); +        return Failure; +      } +       +      F.LocalNumRedeclarationsInMap = Record[0]; +      F.RedeclarationsMap = (const LocalRedeclarationsInfo *)BlobStart; +      break; +    } +         +    case MERGED_DECLARATIONS: { +      for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) { +        GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]); +        SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID]; +        for (unsigned N = Record[Idx++]; N > 0; --N) +          Decls.push_back(getGlobalDeclID(F, Record[Idx++])); +      } +      break; +    } +    } +  } +  Error("premature end of bitstream in AST file"); +  return Failure; +} + +ASTReader::ASTReadResult ASTReader::validateFileEntries(ModuleFile &M) { +  llvm::BitstreamCursor &SLocEntryCursor = M.SLocEntryCursor; + +  for (unsigned i = 0, e = M.LocalNumSLocFileEntries; i != e; ++i) { +    SLocEntryCursor.JumpToBit(M.SLocFileOffsets[i]); +    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 AST 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 AST file"); +      return Failure; + +    case SM_SLOC_FILE_ENTRY: { +      // If the buffer was overridden, the file need not exist. +      if (Record[6]) +        break; +       +      StringRef Filename(BlobStart, BlobLen); +      const FileEntry *File = getFileEntry(Filename); + +      if (File == 0) { +        std::string ErrorStr = "could not find file '"; +        ErrorStr += Filename; +        ErrorStr += "' referenced by AST file"; +        Error(ErrorStr.c_str()); +        return IgnorePCH; +      } + +      if (Record.size() < 7) { +        Error("source location entry is incorrect"); +        return Failure; +      } + +      // The stat info from the FileEntry came from the cached stat +      // info of the PCH, so we cannot trust it. +      struct stat StatBuf; +      if (::stat(File->getName(), &StatBuf) != 0) { +        StatBuf.st_size = File->getSize(); +        StatBuf.st_mtime = File->getModificationTime(); +      } + +      if (((off_t)Record[4] != StatBuf.st_size +#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] != StatBuf.st_mtime +#endif +          )) { +        Error(diag::err_fe_pch_file_modified, Filename); +        return IgnorePCH; +      } + +      break; +    } +    } +  } + +  return Success; +} + +void ASTReader::makeNamesVisible(const HiddenNames &Names) { +  for (unsigned I = 0, N = Names.size(); I != N; ++I) { +    if (Decl *D = Names[I].dyn_cast<Decl *>()) +      D->Hidden = false; +    else { +      IdentifierInfo *II = Names[I].get<IdentifierInfo *>(); +      if (!II->hasMacroDefinition()) { +        II->setHasMacroDefinition(true); +        if (DeserializationListener) +          DeserializationListener->MacroVisible(II); +      } +    } +  } +} + +void ASTReader::makeModuleVisible(Module *Mod,  +                                  Module::NameVisibilityKind NameVisibility) { +  llvm::SmallPtrSet<Module *, 4> Visited; +  llvm::SmallVector<Module *, 4> Stack; +  Stack.push_back(Mod);   +  while (!Stack.empty()) { +    Mod = Stack.back(); +    Stack.pop_back(); + +    if (NameVisibility <= Mod->NameVisibility) { +      // This module already has this level of visibility (or greater), so  +      // there is nothing more to do. +      continue; +    } +     +    if (!Mod->isAvailable()) { +      // Modules that aren't available cannot be made visible. +      continue; +    } + +    // Update the module's name visibility. +    Mod->NameVisibility = NameVisibility; +     +    // If we've already deserialized any names from this module, +    // mark them as visible. +    HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod); +    if (Hidden != HiddenNamesMap.end()) { +      makeNamesVisible(Hidden->second); +      HiddenNamesMap.erase(Hidden); +    } +     +    // Push any non-explicit submodules onto the stack to be marked as +    // visible. +    for (Module::submodule_iterator Sub = Mod->submodule_begin(), +                                 SubEnd = Mod->submodule_end(); +         Sub != SubEnd; ++Sub) { +      if (!(*Sub)->IsExplicit && Visited.insert(*Sub)) +        Stack.push_back(*Sub); +    } +     +    // Push any exported modules onto the stack to be marked as visible. +    bool AnyWildcard = false; +    bool UnrestrictedWildcard = false; +    llvm::SmallVector<Module *, 4> WildcardRestrictions; +    for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) { +      Module *Exported = Mod->Exports[I].getPointer(); +      if (!Mod->Exports[I].getInt()) { +        // Export a named module directly; no wildcards involved. +        if (Visited.insert(Exported)) +          Stack.push_back(Exported); +         +        continue; +      } +       +      // Wildcard export: export all of the imported modules that match +      // the given pattern. +      AnyWildcard = true; +      if (UnrestrictedWildcard) +        continue; + +      if (Module *Restriction = Mod->Exports[I].getPointer()) +        WildcardRestrictions.push_back(Restriction); +      else { +        WildcardRestrictions.clear(); +        UnrestrictedWildcard = true; +      } +    } +     +    // If there were any wildcards, push any imported modules that were +    // re-exported by the wildcard restriction. +    if (!AnyWildcard) +      continue; +     +    for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) { +      Module *Imported = Mod->Imports[I]; +      if (Visited.count(Imported)) +        continue; +       +      bool Acceptable = UnrestrictedWildcard; +      if (!Acceptable) { +        // Check whether this module meets one of the restrictions. +        for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) { +          Module *Restriction = WildcardRestrictions[R]; +          if (Imported == Restriction || Imported->isSubModuleOf(Restriction)) { +            Acceptable = true; +            break; +          } +        } +      } +       +      if (!Acceptable) +        continue; +       +      Visited.insert(Imported); +      Stack.push_back(Imported); +    } +  } +} + +ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, +                                            ModuleKind Type) { +  // Bump the generation number. +  unsigned PreviousGeneration = CurrentGeneration++; +   +  switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) { +  case Failure: return Failure; +  case IgnorePCH: return IgnorePCH; +  case Success: break; +  } + +  // Here comes stuff that we only do once the entire chain is loaded. + +  // Check the predefines buffers. +  if (!DisableValidation && Type == MK_PCH && +      // FIXME: CheckPredefinesBuffers also sets the SuggestedPredefines; +      // if DisableValidation is true, defines that were set on command-line +      // but not in the PCH file will not be added to SuggestedPredefines. +      CheckPredefinesBuffers()) +    return IgnorePCH; + +  // Mark all of the identifiers in the identifier table as being out of date, +  // so that various accessors know to check the loaded modules when the +  // identifier is used. +  for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(), +                              IdEnd = PP.getIdentifierTable().end(); +       Id != IdEnd; ++Id) +    Id->second->setOutOfDate(true); +   +  // Resolve any unresolved module exports. +  for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) { +    UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I]; +    SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID); +    Module *ResolvedMod = getSubmodule(GlobalID); +     +    if (Unresolved.IsImport) { +      if (ResolvedMod) +        Unresolved.Mod->Imports.push_back(ResolvedMod); +      continue; +    } + +    if (ResolvedMod || Unresolved.IsWildcard) +      Unresolved.Mod->Exports.push_back( +        Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard)); +  } +  UnresolvedModuleImportExports.clear(); +   +  InitializeContext(); + +  if (DeserializationListener) +    DeserializationListener->ReaderInitialized(this); + +  if (!OriginalFileID.isInvalid()) { +    OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID +                                      + OriginalFileID.getOpaqueValue() - 1); + +    // If this AST file is a precompiled preamble, then set the preamble file ID +    // of the source manager to the file source file from which the preamble was +    // built. +    if (Type == MK_Preamble) { +      SourceMgr.setPreambleFileID(OriginalFileID); +    } else if (Type == MK_MainFile) { +      SourceMgr.setMainFileID(OriginalFileID); +    } +  } +   +  // For any Objective-C class definitions we have already loaded, make sure +  // that we load any additional categories. +  for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) { +    loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(),  +                       ObjCClassesLoaded[I], +                       PreviousGeneration); +  } +   +  return Success; +} + +ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, +                                                ModuleKind Type, +                                                ModuleFile *ImportedBy) { +  ModuleFile *M; +  bool NewModule; +  std::string ErrorStr; +  llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportedBy, +                                                CurrentGeneration, ErrorStr); + +  if (!M) { +    // We couldn't load the module. +    std::string Msg = "Unable to load module \"" + FileName.str() + "\": " +      + ErrorStr; +    Error(Msg); +    return Failure; +  } + +  if (!NewModule) { +    // We've already loaded this module. +    return Success; +  } + +  // FIXME: This seems rather a hack. Should CurrentDir be part of the +  // module? +  if (FileName != "-") { +    CurrentDir = llvm::sys::path::parent_path(FileName); +    if (CurrentDir.empty()) CurrentDir = "."; +  } + +  ModuleFile &F = *M; +  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 AST file"); +      return Failure; +    } + +    unsigned BlockID = Stream.ReadSubBlockID(); + +    // We only know the AST subblock ID. +    switch (BlockID) { +    case llvm::bitc::BLOCKINFO_BLOCK_ID: +      if (Stream.ReadBlockInfoBlock()) { +        Error("malformed BlockInfoBlock in AST file"); +        return Failure; +      } +      break; +    case AST_BLOCK_ID: +      switch (ReadASTBlock(F)) { +      case Success: +        break; + +      case Failure: +        return Failure; + +      case IgnorePCH: +        // FIXME: We could consider reading through to the end of this +        // AST block, skipping subblocks, to see if there are other +        // AST blocks elsewhere. + +        // FIXME: We can't clear loaded slocentries anymore. +        //SourceMgr.ClearPreallocatedSLocEntries(); + +        // Remove the stat cache. +        if (F.StatCache) +          FileMgr.removeStatCache((ASTStatCache*)F.StatCache); + +        return IgnorePCH; +      } +      break; +    default: +      if (Stream.SkipBlock()) { +        Error("malformed block record in AST file"); +        return Failure; +      } +      break; +    } +  } +   +  // Once read, set the ModuleFile bit base offset and update the size in  +  // bits of all files we've seen. +  F.GlobalBitOffset = TotalModulesSizeInBits; +  TotalModulesSizeInBits += F.SizeInBits; +  GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F)); + +  // Make sure that the files this module was built against are still available. +  if (!DisableValidation) { +    switch(validateFileEntries(*M)) { +    case Failure: return Failure; +    case IgnorePCH: return IgnorePCH; +    case Success: break; +    } +  } +   +  // Preload SLocEntries. +  for (unsigned I = 0, N = M->PreloadSLocEntries.size(); I != N; ++I) { +    int Index = int(M->PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID; +    // Load it through the SourceManager and don't call ReadSLocEntryRecord() +    // directly because the entry may have already been loaded in which case +    // calling ReadSLocEntryRecord() directly would trigger an assertion in +    // SourceManager. +    SourceMgr.getLoadedSLocEntryByID(Index); +  } + + +  return Success; +} + +void ASTReader::InitializeContext() {   +  // If there's a listener, notify them that we "read" the translation unit. +  if (DeserializationListener) +    DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,  +                                      Context.getTranslationUnitDecl()); + +  // Make sure we load the declaration update records for the translation unit, +  // if there are any. +  loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID,  +                        Context.getTranslationUnitDecl()); +   +  // FIXME: Find a better way to deal with collisions between these +  // built-in types. Right now, we just ignore the problem. +   +  // Load the special types. +  if (SpecialTypes.size() >= NumSpecialTypeIDs) { +    if (Context.getBuiltinVaListType().isNull()) { +      Context.setBuiltinVaListType( +        GetType(SpecialTypes[SPECIAL_TYPE_BUILTIN_VA_LIST])); +    } +     +    if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) { +      if (!Context.CFConstantStringTypeDecl) +        Context.setCFConstantStringType(GetType(String)); +    } +     +    if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) { +      QualType FileType = GetType(File); +      if (FileType.isNull()) { +        Error("FILE type is NULL"); +        return; +      } +       +      if (!Context.FILEDecl) { +        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 AST file"); +            return; +          } +          Context.setFILEDecl(Tag->getDecl()); +        } +      } +    } +     +    if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) { +      QualType Jmp_bufType = GetType(Jmp_buf); +      if (Jmp_bufType.isNull()) { +        Error("jmp_buf type is NULL"); +        return; +      } +       +      if (!Context.jmp_bufDecl) { +        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_buf type in AST file"); +            return; +          } +          Context.setjmp_bufDecl(Tag->getDecl()); +        } +      } +    } +     +    if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) { +      QualType Sigjmp_bufType = GetType(Sigjmp_buf); +      if (Sigjmp_bufType.isNull()) { +        Error("sigjmp_buf type is NULL"); +        return; +      } +       +      if (!Context.sigjmp_bufDecl) { +        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 AST file"); +          Context.setsigjmp_bufDecl(Tag->getDecl()); +        } +      } +    } + +    if (unsigned ObjCIdRedef +          = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) { +      if (Context.ObjCIdRedefinitionType.isNull()) +        Context.ObjCIdRedefinitionType = GetType(ObjCIdRedef); +    } + +    if (unsigned ObjCClassRedef +          = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) { +      if (Context.ObjCClassRedefinitionType.isNull()) +        Context.ObjCClassRedefinitionType = GetType(ObjCClassRedef); +    } + +    if (unsigned ObjCSelRedef +          = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) { +      if (Context.ObjCSelRedefinitionType.isNull()) +        Context.ObjCSelRedefinitionType = GetType(ObjCSelRedef); +    } + +    if (unsigned Ucontext_t = SpecialTypes[SPECIAL_TYPE_UCONTEXT_T]) { +      QualType Ucontext_tType = GetType(Ucontext_t); +      if (Ucontext_tType.isNull()) { +        Error("ucontext_t type is NULL"); +        return; +      } + +      if (!Context.ucontext_tDecl) { +        if (const TypedefType *Typedef = Ucontext_tType->getAs<TypedefType>()) +          Context.setucontext_tDecl(Typedef->getDecl()); +        else { +          const TagType *Tag = Ucontext_tType->getAs<TagType>(); +          assert(Tag && "Invalid ucontext_t type in AST file"); +          Context.setucontext_tDecl(Tag->getDecl()); +        } +      } +    } +  } +   +  ReadPragmaDiagnosticMappings(Context.getDiagnostics()); + +  // If there were any CUDA special declarations, deserialize them. +  if (!CUDASpecialDeclRefs.empty()) { +    assert(CUDASpecialDeclRefs.size() == 1 && "More decl refs than expected!"); +    Context.setcudaConfigureCallDecl( +                           cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0]))); +  } +   +  // Re-export any modules that were imported by a non-module AST file. +  for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) { +    if (Module *Imported = getSubmodule(ImportedModules[I])) +      makeModuleVisible(Imported, Module::AllVisible); +  } +  ImportedModules.clear(); +} + +void ASTReader::finalizeForWriting() { +  for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(), +                                 HiddenEnd = HiddenNamesMap.end(); +       Hidden != HiddenEnd; ++Hidden) { +    makeNamesVisible(Hidden->second); +  } +  HiddenNamesMap.clear(); +} + +/// \brief Retrieve the name of the original source file name +/// directly from the AST file, without actually loading the AST +/// file. +std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, +                                             FileManager &FileMgr, +                                             DiagnosticsEngine &Diags) { +  // Open the AST file. +  std::string ErrStr; +  OwningPtr<llvm::MemoryBuffer> Buffer; +  Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &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) << ASTFileName; +    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 AST subblock ID. +      switch (BlockID) { +      case AST_BLOCK_ID: +        if (Stream.EnterSubBlock(AST_BLOCK_ID)) { +          Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName; +          return std::string(); +        } +        break; + +      default: +        if (Stream.SkipBlock()) { +          Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName; +          return std::string(); +        } +        break; +      } +      continue; +    } + +    if (Code == llvm::bitc::END_BLOCK) { +      if (Stream.ReadBlockEnd()) { +        Diags.Report(diag::err_fe_pch_error_at_end_block) << ASTFileName; +        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) +          == ORIGINAL_FILE_NAME) +      return std::string(BlobStart, BlobLen); +  } + +  return std::string(); +} + +ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) { +  // Enter the submodule block. +  if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) { +    Error("malformed submodule block record in AST file"); +    return Failure; +  } + +  ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); +  bool First = true; +  Module *CurrentModule = 0; +  RecordData Record; +  while (true) { +    unsigned Code = F.Stream.ReadCode(); +    if (Code == llvm::bitc::END_BLOCK) { +      if (F.Stream.ReadBlockEnd()) { +        Error("error at end of submodule block in AST file"); +        return Failure; +      } +      return Success; +    } +     +    if (Code == llvm::bitc::ENTER_SUBBLOCK) { +      // No known subblocks, always skip them. +      F.Stream.ReadSubBlockID(); +      if (F.Stream.SkipBlock()) { +        Error("malformed block record in AST file"); +        return Failure; +      } +      continue; +    } +     +    if (Code == llvm::bitc::DEFINE_ABBREV) { +      F.Stream.ReadAbbrevRecord(); +      continue; +    } +     +    // Read a record. +    const char *BlobStart; +    unsigned BlobLen; +    Record.clear(); +    switch (F.Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { +    default:  // Default behavior: ignore. +      break; +       +    case SUBMODULE_DEFINITION: { +      if (First) { +        Error("missing submodule metadata record at beginning of block"); +        return Failure; +      } + +      if (Record.size() < 7) { +        Error("malformed module definition"); +        return Failure; +      } +       +      StringRef Name(BlobStart, BlobLen); +      SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]); +      SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]); +      bool IsFramework = Record[2]; +      bool IsExplicit = Record[3]; +      bool IsSystem = Record[4]; +      bool InferSubmodules = Record[5]; +      bool InferExplicitSubmodules = Record[6]; +      bool InferExportWildcard = Record[7]; +       +      Module *ParentModule = 0; +      if (Parent) +        ParentModule = getSubmodule(Parent); +       +      // Retrieve this (sub)module from the module map, creating it if +      // necessary. +      CurrentModule = ModMap.findOrCreateModule(Name, ParentModule,  +                                                IsFramework,  +                                                IsExplicit).first; +      SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; +      if (GlobalIndex >= SubmodulesLoaded.size() || +          SubmodulesLoaded[GlobalIndex]) { +        Error("too many submodules"); +        return Failure; +      } +       +      CurrentModule->IsFromModuleFile = true; +      CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; +      CurrentModule->InferSubmodules = InferSubmodules; +      CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules; +      CurrentModule->InferExportWildcard = InferExportWildcard; +      if (DeserializationListener) +        DeserializationListener->ModuleRead(GlobalID, CurrentModule); +       +      SubmodulesLoaded[GlobalIndex] = CurrentModule; +      break; +    } +         +    case SUBMODULE_UMBRELLA_HEADER: { +      if (First) { +        Error("missing submodule metadata record at beginning of block"); +        return Failure; +      } + +      if (!CurrentModule) +        break; +       +      StringRef FileName(BlobStart, BlobLen); +      if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) { +        if (!CurrentModule->getUmbrellaHeader()) +          ModMap.setUmbrellaHeader(CurrentModule, Umbrella); +        else if (CurrentModule->getUmbrellaHeader() != Umbrella) { +          Error("mismatched umbrella headers in submodule"); +          return Failure; +        } +      } +      break; +    } +         +    case SUBMODULE_HEADER: { +      if (First) { +        Error("missing submodule metadata record at beginning of block"); +        return Failure; +      } + +      if (!CurrentModule) +        break; +       +      // FIXME: Be more lazy about this! +      StringRef FileName(BlobStart, BlobLen); +      if (const FileEntry *File = PP.getFileManager().getFile(FileName)) { +        if (std::find(CurrentModule->Headers.begin(),  +                      CurrentModule->Headers.end(),  +                      File) == CurrentModule->Headers.end()) +          ModMap.addHeader(CurrentModule, File); +      } +      break;       +    } +         +    case SUBMODULE_UMBRELLA_DIR: { +      if (First) { +        Error("missing submodule metadata record at beginning of block"); +        return Failure; +      } +       +      if (!CurrentModule) +        break; +       +      StringRef DirName(BlobStart, BlobLen); +      if (const DirectoryEntry *Umbrella +                                  = PP.getFileManager().getDirectory(DirName)) { +        if (!CurrentModule->getUmbrellaDir()) +          ModMap.setUmbrellaDir(CurrentModule, Umbrella); +        else if (CurrentModule->getUmbrellaDir() != Umbrella) { +          Error("mismatched umbrella directories in submodule"); +          return Failure; +        } +      } +      break; +    } +         +    case SUBMODULE_METADATA: { +      if (!First) { +        Error("submodule metadata record not at beginning of block"); +        return Failure; +      } +      First = false; +       +      F.BaseSubmoduleID = getTotalNumSubmodules(); +      F.LocalNumSubmodules = Record[0]; +      unsigned LocalBaseSubmoduleID = Record[1]; +      if (F.LocalNumSubmodules > 0) { +        // Introduce the global -> local mapping for submodules within this  +        // module. +        GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F)); +         +        // Introduce the local -> global mapping for submodules within this  +        // module. +        F.SubmoduleRemap.insertOrReplace( +          std::make_pair(LocalBaseSubmoduleID, +                         F.BaseSubmoduleID - LocalBaseSubmoduleID)); +         +        SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules); +      }       +      break; +    } +         +    case SUBMODULE_IMPORTS: { +      if (First) { +        Error("missing submodule metadata record at beginning of block"); +        return Failure; +      } +       +      if (!CurrentModule) +        break; +       +      for (unsigned Idx = 0; Idx != Record.size(); ++Idx) { +        UnresolvedModuleImportExport Unresolved; +        Unresolved.File = &F; +        Unresolved.Mod = CurrentModule; +        Unresolved.ID = Record[Idx]; +        Unresolved.IsImport = true; +        Unresolved.IsWildcard = false; +        UnresolvedModuleImportExports.push_back(Unresolved); +      } +      break; +    } + +    case SUBMODULE_EXPORTS: { +      if (First) { +        Error("missing submodule metadata record at beginning of block"); +        return Failure; +      } +       +      if (!CurrentModule) +        break; +       +      for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { +        UnresolvedModuleImportExport Unresolved; +        Unresolved.File = &F; +        Unresolved.Mod = CurrentModule; +        Unresolved.ID = Record[Idx]; +        Unresolved.IsImport = false; +        Unresolved.IsWildcard = Record[Idx + 1]; +        UnresolvedModuleImportExports.push_back(Unresolved); +      } +       +      // Once we've loaded the set of exports, there's no reason to keep  +      // the parsed, unresolved exports around. +      CurrentModule->UnresolvedExports.clear(); +      break; +    } +    case SUBMODULE_REQUIRES: { +      if (First) { +        Error("missing submodule metadata record at beginning of block"); +        return Failure; +      } + +      if (!CurrentModule) +        break; + +      CurrentModule->addRequirement(StringRef(BlobStart, BlobLen),  +                                    Context.getLangOpts(), +                                    Context.getTargetInfo()); +      break; +    } +    } +  } +} + +/// \brief Parse the record that corresponds to a LangOptions data +/// structure. +/// +/// This routine parses the language options from the AST file and then gives +/// them to the AST listener if one is set. +/// +/// \returns true if the listener deems the file unacceptable, false otherwise. +bool ASTReader::ParseLanguageOptions( +                             const SmallVectorImpl<uint64_t> &Record) { +  if (Listener) { +    LangOptions LangOpts; +    unsigned Idx = 0; +#define LANGOPT(Name, Bits, Default, Description) \ +  LangOpts.Name = Record[Idx++]; +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ +  LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++])); +#include "clang/Basic/LangOptions.def" +     +    unsigned Length = Record[Idx++]; +    LangOpts.CurrentModule.assign(Record.begin() + Idx,  +                                  Record.begin() + Idx + Length); +    return Listener->ReadLanguageOptions(LangOpts); +  } + +  return false; +} + +std::pair<ModuleFile *, unsigned> +ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) { +  GlobalPreprocessedEntityMapType::iterator +  I = GlobalPreprocessedEntityMap.find(GlobalIndex); +  assert(I != GlobalPreprocessedEntityMap.end() &&  +         "Corrupted global preprocessed entity map"); +  ModuleFile *M = I->second; +  unsigned LocalIndex = GlobalIndex - M->BasePreprocessedEntityID; +  return std::make_pair(M, LocalIndex); +} + +PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { +  PreprocessedEntityID PPID = Index+1; +  std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index); +  ModuleFile &M = *PPInfo.first; +  unsigned LocalIndex = PPInfo.second; +  const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; + +  SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor);   +  M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset); + +  unsigned Code = M.PreprocessorDetailCursor.ReadCode(); +  switch (Code) { +  case llvm::bitc::END_BLOCK: +    return 0; +     +  case llvm::bitc::ENTER_SUBBLOCK: +    Error("unexpected subblock record in preprocessor detail block"); +    return 0; +       +  case llvm::bitc::DEFINE_ABBREV: +    Error("unexpected abbrevation record in preprocessor detail block"); +    return 0; +       +  default: +    break; +  } + +  if (!PP.getPreprocessingRecord()) { +    Error("no preprocessing record"); +    return 0; +  } +   +  // Read the record. +  SourceRange Range(ReadSourceLocation(M, PPOffs.Begin), +                    ReadSourceLocation(M, PPOffs.End)); +  PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); +  const char *BlobStart = 0; +  unsigned BlobLen = 0; +  RecordData Record; +  PreprocessorDetailRecordTypes RecType = +    (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.ReadRecord( +                                             Code, Record, BlobStart, BlobLen); +  switch (RecType) { +  case PPD_MACRO_EXPANSION: { +    bool isBuiltin = Record[0]; +    IdentifierInfo *Name = 0; +    MacroDefinition *Def = 0; +    if (isBuiltin) +      Name = getLocalIdentifier(M, Record[1]); +    else { +      PreprocessedEntityID +          GlobalID = getGlobalPreprocessedEntityID(M, Record[1]); +      Def =cast<MacroDefinition>(PPRec.getLoadedPreprocessedEntity(GlobalID-1)); +    } + +    MacroExpansion *ME; +    if (isBuiltin) +      ME = new (PPRec) MacroExpansion(Name, Range); +    else +      ME = new (PPRec) MacroExpansion(Def, Range); + +    return ME; +  } +       +  case PPD_MACRO_DEFINITION: { +    // Decode the identifier info and then check again; if the macro is +    // still defined and associated with the identifier, +    IdentifierInfo *II = getLocalIdentifier(M, Record[0]); +    MacroDefinition *MD +      = new (PPRec) MacroDefinition(II, Range); + +    if (DeserializationListener) +      DeserializationListener->MacroDefinitionRead(PPID, MD); + +    return MD; +  } +       +  case PPD_INCLUSION_DIRECTIVE: { +    const char *FullFileNameStart = BlobStart + Record[0]; +    StringRef FullFileName(FullFileNameStart, BlobLen - Record[0]); +    const FileEntry *File = 0; +    if (!FullFileName.empty()) +      File = PP.getFileManager().getFile(FullFileName); +     +    // FIXME: Stable encoding +    InclusionDirective::InclusionKind Kind +      = static_cast<InclusionDirective::InclusionKind>(Record[2]); +    InclusionDirective *ID +      = new (PPRec) InclusionDirective(PPRec, Kind, +                                       StringRef(BlobStart, Record[0]), +                                       Record[1], +                                       File, +                                       Range); +    return ID; +  } +  } + +  llvm_unreachable("Invalid PreprocessorDetailRecordTypes"); +} + +/// \brief \arg SLocMapI points at a chunk of a module that contains no +/// preprocessed entities or the entities it contains are not the ones we are +/// looking for. Find the next module that contains entities and return the ID +/// of the first entry. +PreprocessedEntityID ASTReader::findNextPreprocessedEntity( +                       GlobalSLocOffsetMapType::const_iterator SLocMapI) const { +  ++SLocMapI; +  for (GlobalSLocOffsetMapType::const_iterator +         EndI = GlobalSLocOffsetMap.end(); SLocMapI != EndI; ++SLocMapI) { +    ModuleFile &M = *SLocMapI->second; +    if (M.NumPreprocessedEntities) +      return getGlobalPreprocessedEntityID(M, M.BasePreprocessedEntityID); +  } + +  return getTotalNumPreprocessedEntities(); +} + +namespace { + +template <unsigned PPEntityOffset::*PPLoc> +struct PPEntityComp { +  const ASTReader &Reader; +  ModuleFile &M; + +  PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) { } + +  bool operator()(const PPEntityOffset &L, const PPEntityOffset &R) const { +    SourceLocation LHS = getLoc(L); +    SourceLocation RHS = getLoc(R); +    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); +  } + +  bool operator()(const PPEntityOffset &L, SourceLocation RHS) const { +    SourceLocation LHS = getLoc(L); +    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); +  } + +  bool operator()(SourceLocation LHS, const PPEntityOffset &R) const { +    SourceLocation RHS = getLoc(R); +    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); +  } + +  SourceLocation getLoc(const PPEntityOffset &PPE) const { +    return Reader.ReadSourceLocation(M, PPE.*PPLoc); +  } +}; + +} + +/// \brief Returns the first preprocessed entity ID that ends after \arg BLoc. +PreprocessedEntityID +ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const { +  if (SourceMgr.isLocalSourceLocation(BLoc)) +    return getTotalNumPreprocessedEntities(); + +  GlobalSLocOffsetMapType::const_iterator +    SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - +                                        BLoc.getOffset()); +  assert(SLocMapI != GlobalSLocOffsetMap.end() && +         "Corrupted global sloc offset map"); + +  if (SLocMapI->second->NumPreprocessedEntities == 0) +    return findNextPreprocessedEntity(SLocMapI); + +  ModuleFile &M = *SLocMapI->second; +  typedef const PPEntityOffset *pp_iterator; +  pp_iterator pp_begin = M.PreprocessedEntityOffsets; +  pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities; + +  size_t Count = M.NumPreprocessedEntities; +  size_t Half; +  pp_iterator First = pp_begin; +  pp_iterator PPI; + +  // Do a binary search manually instead of using std::lower_bound because +  // The end locations of entities may be unordered (when a macro expansion +  // is inside another macro argument), but for this case it is not important +  // whether we get the first macro expansion or its containing macro. +  while (Count > 0) { +    Half = Count/2; +    PPI = First; +    std::advance(PPI, Half); +    if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End), +                                            BLoc)){ +      First = PPI; +      ++First; +      Count = Count - Half - 1; +    } else +      Count = Half; +  } + +  if (PPI == pp_end) +    return findNextPreprocessedEntity(SLocMapI); + +  return getGlobalPreprocessedEntityID(M, +                                 M.BasePreprocessedEntityID + (PPI - pp_begin)); +} + +/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc. +PreprocessedEntityID +ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const { +  if (SourceMgr.isLocalSourceLocation(ELoc)) +    return getTotalNumPreprocessedEntities(); + +  GlobalSLocOffsetMapType::const_iterator +    SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - +                                        ELoc.getOffset()); +  assert(SLocMapI != GlobalSLocOffsetMap.end() && +         "Corrupted global sloc offset map"); + +  if (SLocMapI->second->NumPreprocessedEntities == 0) +    return findNextPreprocessedEntity(SLocMapI); + +  ModuleFile &M = *SLocMapI->second; +  typedef const PPEntityOffset *pp_iterator; +  pp_iterator pp_begin = M.PreprocessedEntityOffsets; +  pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities; +  pp_iterator PPI = +      std::upper_bound(pp_begin, pp_end, ELoc, +                       PPEntityComp<&PPEntityOffset::Begin>(*this, M)); + +  if (PPI == pp_end) +    return findNextPreprocessedEntity(SLocMapI); + +  return getGlobalPreprocessedEntityID(M, +                                 M.BasePreprocessedEntityID + (PPI - pp_begin)); +} + +/// \brief Returns a pair of [Begin, End) indices of preallocated +/// preprocessed entities that \arg Range encompasses. +std::pair<unsigned, unsigned> +    ASTReader::findPreprocessedEntitiesInRange(SourceRange Range) { +  if (Range.isInvalid()) +    return std::make_pair(0,0); +  assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); + +  PreprocessedEntityID BeginID = findBeginPreprocessedEntity(Range.getBegin()); +  PreprocessedEntityID EndID = findEndPreprocessedEntity(Range.getEnd()); +  return std::make_pair(BeginID, EndID); +} + +/// \brief Optionally returns true or false if the preallocated preprocessed +/// entity with index \arg Index came from file \arg FID. +llvm::Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, +                                                             FileID FID) { +  if (FID.isInvalid()) +    return false; + +  std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index); +  ModuleFile &M = *PPInfo.first; +  unsigned LocalIndex = PPInfo.second; +  const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; +   +  SourceLocation Loc = ReadSourceLocation(M, PPOffs.Begin); +  if (Loc.isInvalid()) +    return false; +   +  if (SourceMgr.isInFileID(SourceMgr.getFileLoc(Loc), FID)) +    return true; +  else +    return false; +} + +namespace { +  /// \brief Visitor used to search for information about a header file. +  class HeaderFileInfoVisitor { +    ASTReader &Reader; +    const FileEntry *FE; +     +    llvm::Optional<HeaderFileInfo> HFI; +     +  public: +    HeaderFileInfoVisitor(ASTReader &Reader, const FileEntry *FE) +      : Reader(Reader), FE(FE) { } +     +    static bool visit(ModuleFile &M, void *UserData) { +      HeaderFileInfoVisitor *This +        = static_cast<HeaderFileInfoVisitor *>(UserData); +       +      HeaderFileInfoTrait Trait(This->Reader, M,  +                                &This->Reader.getPreprocessor().getHeaderSearchInfo(), +                                M.HeaderFileFrameworkStrings, +                                This->FE->getName()); +       +      HeaderFileInfoLookupTable *Table +        = static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable); +      if (!Table) +        return false; + +      // Look in the on-disk hash table for an entry for this file name. +      HeaderFileInfoLookupTable::iterator Pos = Table->find(This->FE->getName(), +                                                            &Trait); +      if (Pos == Table->end()) +        return false; + +      This->HFI = *Pos; +      return true; +    } +     +    llvm::Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; } +  }; +} + +HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { +  HeaderFileInfoVisitor Visitor(*this, FE); +  ModuleMgr.visit(&HeaderFileInfoVisitor::visit, &Visitor); +  if (llvm::Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) { +    if (Listener) +      Listener->ReadHeaderFileInfo(*HFI, FE->getUID()); +    return *HFI; +  } +   +  return HeaderFileInfo(); +} + +void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { +  for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) { +    ModuleFile &F = *(*I); +    unsigned Idx = 0; +    while (Idx < F.PragmaDiagMappings.size()) { +      SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]); +      Diag.DiagStates.push_back(*Diag.GetCurDiagState()); +      Diag.DiagStatePoints.push_back( +          DiagnosticsEngine::DiagStatePoint(&Diag.DiagStates.back(), +                                            FullSourceLoc(Loc, SourceMgr))); +      while (1) { +        assert(Idx < F.PragmaDiagMappings.size() && +               "Invalid data, didn't find '-1' marking end of diag/map pairs"); +        if (Idx >= F.PragmaDiagMappings.size()) { +          break; // Something is messed up but at least avoid infinite loop in +                 // release build. +        } +        unsigned DiagID = F.PragmaDiagMappings[Idx++]; +        if (DiagID == (unsigned)-1) { +          break; // no more diag/map pairs for this location. +        } +        diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++]; +        DiagnosticMappingInfo MappingInfo = Diag.makeMappingInfo(Map, Loc); +        Diag.GetCurDiagState()->setMappingInfo(DiagID, MappingInfo); +      } +    } +  } +} + +/// \brief Get the correct cursor and offset for loading a type. +ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { +  GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index); +  assert(I != GlobalTypeMap.end() && "Corrupted global type map"); +  ModuleFile *M = I->second; +  return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]); +} + +/// \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 ASTReader::readTypeRecord(unsigned Index) { +  RecordLocation Loc = TypeCursorForIndex(Index); +  llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; + +  // 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); + +  unsigned Idx = 0; +  DeclsCursor.JumpToBit(Loc.Offset); +  RecordData Record; +  unsigned Code = DeclsCursor.ReadCode(); +  switch ((TypeCode)DeclsCursor.ReadRecord(Code, Record)) { +  case TYPE_EXT_QUAL: { +    if (Record.size() != 2) { +      Error("Incorrect encoding of extended qualifier type"); +      return QualType(); +    } +    QualType Base = readType(*Loc.F, Record, Idx); +    Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[Idx++]); +    return Context.getQualifiedType(Base, Quals); +  } + +  case TYPE_COMPLEX: { +    if (Record.size() != 1) { +      Error("Incorrect encoding of complex type"); +      return QualType(); +    } +    QualType ElemType = readType(*Loc.F, Record, Idx); +    return Context.getComplexType(ElemType); +  } + +  case TYPE_POINTER: { +    if (Record.size() != 1) { +      Error("Incorrect encoding of pointer type"); +      return QualType(); +    } +    QualType PointeeType = readType(*Loc.F, Record, Idx); +    return Context.getPointerType(PointeeType); +  } + +  case TYPE_BLOCK_POINTER: { +    if (Record.size() != 1) { +      Error("Incorrect encoding of block pointer type"); +      return QualType(); +    } +    QualType PointeeType = readType(*Loc.F, Record, Idx); +    return Context.getBlockPointerType(PointeeType); +  } + +  case TYPE_LVALUE_REFERENCE: { +    if (Record.size() != 2) { +      Error("Incorrect encoding of lvalue reference type"); +      return QualType(); +    } +    QualType PointeeType = readType(*Loc.F, Record, Idx); +    return Context.getLValueReferenceType(PointeeType, Record[1]); +  } + +  case TYPE_RVALUE_REFERENCE: { +    if (Record.size() != 1) { +      Error("Incorrect encoding of rvalue reference type"); +      return QualType(); +    } +    QualType PointeeType = readType(*Loc.F, Record, Idx); +    return Context.getRValueReferenceType(PointeeType); +  } + +  case TYPE_MEMBER_POINTER: { +    if (Record.size() != 2) { +      Error("Incorrect encoding of member pointer type"); +      return QualType(); +    } +    QualType PointeeType = readType(*Loc.F, Record, Idx); +    QualType ClassType = readType(*Loc.F, Record, Idx); +    if (PointeeType.isNull() || ClassType.isNull()) +      return QualType(); +     +    return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr()); +  } + +  case TYPE_CONSTANT_ARRAY: { +    QualType ElementType = readType(*Loc.F, Record, Idx); +    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 TYPE_INCOMPLETE_ARRAY: { +    QualType ElementType = readType(*Loc.F, Record, Idx); +    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; +    unsigned IndexTypeQuals = Record[2]; +    return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals); +  } + +  case TYPE_VARIABLE_ARRAY: { +    QualType ElementType = readType(*Loc.F, Record, Idx); +    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; +    unsigned IndexTypeQuals = Record[2]; +    SourceLocation LBLoc = ReadSourceLocation(*Loc.F, Record[3]); +    SourceLocation RBLoc = ReadSourceLocation(*Loc.F, Record[4]); +    return Context.getVariableArrayType(ElementType, ReadExpr(*Loc.F), +                                         ASM, IndexTypeQuals, +                                         SourceRange(LBLoc, RBLoc)); +  } + +  case TYPE_VECTOR: { +    if (Record.size() != 3) { +      Error("incorrect encoding of vector type in AST file"); +      return QualType(); +    } + +    QualType ElementType = readType(*Loc.F, Record, Idx); +    unsigned NumElements = Record[1]; +    unsigned VecKind = Record[2]; +    return Context.getVectorType(ElementType, NumElements, +                                  (VectorType::VectorKind)VecKind); +  } + +  case TYPE_EXT_VECTOR: { +    if (Record.size() != 3) { +      Error("incorrect encoding of extended vector type in AST file"); +      return QualType(); +    } + +    QualType ElementType = readType(*Loc.F, Record, Idx); +    unsigned NumElements = Record[1]; +    return Context.getExtVectorType(ElementType, NumElements); +  } + +  case TYPE_FUNCTION_NO_PROTO: { +    if (Record.size() != 6) { +      Error("incorrect encoding of no-proto function type"); +      return QualType(); +    } +    QualType ResultType = readType(*Loc.F, Record, Idx); +    FunctionType::ExtInfo Info(Record[1], Record[2], Record[3], +                               (CallingConv)Record[4], Record[5]); +    return Context.getFunctionNoProtoType(ResultType, Info); +  } + +  case TYPE_FUNCTION_PROTO: { +    QualType ResultType = readType(*Loc.F, Record, Idx); + +    FunctionProtoType::ExtProtoInfo EPI; +    EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1], +                                        /*hasregparm*/ Record[2], +                                        /*regparm*/ Record[3], +                                        static_cast<CallingConv>(Record[4]), +                                        /*produces*/ Record[5]); + +    unsigned Idx = 6; +    unsigned NumParams = Record[Idx++]; +    SmallVector<QualType, 16> ParamTypes; +    for (unsigned I = 0; I != NumParams; ++I) +      ParamTypes.push_back(readType(*Loc.F, Record, Idx)); + +    EPI.Variadic = Record[Idx++]; +    EPI.HasTrailingReturn = Record[Idx++]; +    EPI.TypeQuals = Record[Idx++]; +    EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]); +    ExceptionSpecificationType EST = +        static_cast<ExceptionSpecificationType>(Record[Idx++]); +    EPI.ExceptionSpecType = EST; +    SmallVector<QualType, 2> Exceptions; +    if (EST == EST_Dynamic) { +      EPI.NumExceptions = Record[Idx++]; +      for (unsigned I = 0; I != EPI.NumExceptions; ++I) +        Exceptions.push_back(readType(*Loc.F, Record, Idx)); +      EPI.Exceptions = Exceptions.data(); +    } else if (EST == EST_ComputedNoexcept) { +      EPI.NoexceptExpr = ReadExpr(*Loc.F); +    } else if (EST == EST_Uninstantiated) { +      EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); +      EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); +    } +    return Context.getFunctionType(ResultType, ParamTypes.data(), NumParams, +                                    EPI); +  } + +  case TYPE_UNRESOLVED_USING: { +    unsigned Idx = 0; +    return Context.getTypeDeclType( +                  ReadDeclAs<UnresolvedUsingTypenameDecl>(*Loc.F, Record, Idx)); +  } +       +  case TYPE_TYPEDEF: { +    if (Record.size() != 2) { +      Error("incorrect encoding of typedef type"); +      return QualType(); +    } +    unsigned Idx = 0; +    TypedefNameDecl *Decl = ReadDeclAs<TypedefNameDecl>(*Loc.F, Record, Idx); +    QualType Canonical = readType(*Loc.F, Record, Idx); +    if (!Canonical.isNull()) +      Canonical = Context.getCanonicalType(Canonical); +    return Context.getTypedefType(Decl, Canonical); +  } + +  case TYPE_TYPEOF_EXPR: +    return Context.getTypeOfExprType(ReadExpr(*Loc.F)); + +  case TYPE_TYPEOF: { +    if (Record.size() != 1) { +      Error("incorrect encoding of typeof(type) in AST file"); +      return QualType(); +    } +    QualType UnderlyingType = readType(*Loc.F, Record, Idx); +    return Context.getTypeOfType(UnderlyingType); +  } + +  case TYPE_DECLTYPE: { +    QualType UnderlyingType = readType(*Loc.F, Record, Idx); +    return Context.getDecltypeType(ReadExpr(*Loc.F), UnderlyingType); +  } + +  case TYPE_UNARY_TRANSFORM: { +    QualType BaseType = readType(*Loc.F, Record, Idx); +    QualType UnderlyingType = readType(*Loc.F, Record, Idx); +    UnaryTransformType::UTTKind UKind = (UnaryTransformType::UTTKind)Record[2]; +    return Context.getUnaryTransformType(BaseType, UnderlyingType, UKind); +  } + +  case TYPE_AUTO: +    return Context.getAutoType(readType(*Loc.F, Record, Idx)); + +  case TYPE_RECORD: { +    if (Record.size() != 2) { +      Error("incorrect encoding of record type"); +      return QualType(); +    } +    unsigned Idx = 0; +    bool IsDependent = Record[Idx++]; +    RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx); +    RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl()); +    QualType T = Context.getRecordType(RD); +    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); +    return T; +  } + +  case TYPE_ENUM: { +    if (Record.size() != 2) { +      Error("incorrect encoding of enum type"); +      return QualType(); +    } +    unsigned Idx = 0; +    bool IsDependent = Record[Idx++]; +    QualType T +      = Context.getEnumType(ReadDeclAs<EnumDecl>(*Loc.F, Record, Idx)); +    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); +    return T; +  } + +  case TYPE_ATTRIBUTED: { +    if (Record.size() != 3) { +      Error("incorrect encoding of attributed type"); +      return QualType(); +    } +    QualType modifiedType = readType(*Loc.F, Record, Idx); +    QualType equivalentType = readType(*Loc.F, Record, Idx); +    AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]); +    return Context.getAttributedType(kind, modifiedType, equivalentType); +  } + +  case TYPE_PAREN: { +    if (Record.size() != 1) { +      Error("incorrect encoding of paren type"); +      return QualType(); +    } +    QualType InnerType = readType(*Loc.F, Record, Idx); +    return Context.getParenType(InnerType); +  } + +  case TYPE_PACK_EXPANSION: { +    if (Record.size() != 2) { +      Error("incorrect encoding of pack expansion type"); +      return QualType(); +    } +    QualType Pattern = readType(*Loc.F, Record, Idx); +    if (Pattern.isNull()) +      return QualType(); +    llvm::Optional<unsigned> NumExpansions; +    if (Record[1]) +      NumExpansions = Record[1] - 1; +    return Context.getPackExpansionType(Pattern, NumExpansions); +  } + +  case TYPE_ELABORATED: { +    unsigned Idx = 0; +    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; +    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx); +    QualType NamedType = readType(*Loc.F, Record, Idx); +    return Context.getElaboratedType(Keyword, NNS, NamedType); +  } + +  case TYPE_OBJC_INTERFACE: { +    unsigned Idx = 0; +    ObjCInterfaceDecl *ItfD +      = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx); +    return Context.getObjCInterfaceType(ItfD->getCanonicalDecl()); +  } + +  case TYPE_OBJC_OBJECT: { +    unsigned Idx = 0; +    QualType Base = readType(*Loc.F, Record, Idx); +    unsigned NumProtos = Record[Idx++]; +    SmallVector<ObjCProtocolDecl*, 4> Protos; +    for (unsigned I = 0; I != NumProtos; ++I) +      Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx)); +    return Context.getObjCObjectType(Base, Protos.data(), NumProtos); +  } + +  case TYPE_OBJC_OBJECT_POINTER: { +    unsigned Idx = 0; +    QualType Pointee = readType(*Loc.F, Record, Idx); +    return Context.getObjCObjectPointerType(Pointee); +  } + +  case TYPE_SUBST_TEMPLATE_TYPE_PARM: { +    unsigned Idx = 0; +    QualType Parm = readType(*Loc.F, Record, Idx); +    QualType Replacement = readType(*Loc.F, Record, Idx); +    return +      Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), +                                            Replacement); +  } + +  case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: { +    unsigned Idx = 0; +    QualType Parm = readType(*Loc.F, Record, Idx); +    TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx); +    return Context.getSubstTemplateTypeParmPackType( +                                               cast<TemplateTypeParmType>(Parm), +                                                     ArgPack); +  } + +  case TYPE_INJECTED_CLASS_NAME: { +    CXXRecordDecl *D = ReadDeclAs<CXXRecordDecl>(*Loc.F, Record, Idx); +    QualType TST = readType(*Loc.F, Record, Idx); // probably derivable +    // FIXME: ASTContext::getInjectedClassNameType is not currently suitable +    // for AST reading, too much interdependencies. +    return +      QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0); +  } + +  case TYPE_TEMPLATE_TYPE_PARM: { +    unsigned Idx = 0; +    unsigned Depth = Record[Idx++]; +    unsigned Index = Record[Idx++]; +    bool Pack = Record[Idx++]; +    TemplateTypeParmDecl *D +      = ReadDeclAs<TemplateTypeParmDecl>(*Loc.F, Record, Idx); +    return Context.getTemplateTypeParmType(Depth, Index, Pack, D); +  } + +  case TYPE_DEPENDENT_NAME: { +    unsigned Idx = 0; +    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; +    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx); +    const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx); +    QualType Canon = readType(*Loc.F, Record, Idx); +    if (!Canon.isNull()) +      Canon = Context.getCanonicalType(Canon); +    return Context.getDependentNameType(Keyword, NNS, Name, Canon); +  } + +  case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: { +    unsigned Idx = 0; +    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; +    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx); +    const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx); +    unsigned NumArgs = Record[Idx++]; +    SmallVector<TemplateArgument, 8> Args; +    Args.reserve(NumArgs); +    while (NumArgs--) +      Args.push_back(ReadTemplateArgument(*Loc.F, Record, Idx)); +    return Context.getDependentTemplateSpecializationType(Keyword, NNS, Name, +                                                      Args.size(), Args.data()); +  } + +  case TYPE_DEPENDENT_SIZED_ARRAY: { +    unsigned Idx = 0; + +    // ArrayType +    QualType ElementType = readType(*Loc.F, Record, Idx); +    ArrayType::ArraySizeModifier ASM +      = (ArrayType::ArraySizeModifier)Record[Idx++]; +    unsigned IndexTypeQuals = Record[Idx++]; + +    // DependentSizedArrayType +    Expr *NumElts = ReadExpr(*Loc.F); +    SourceRange Brackets = ReadSourceRange(*Loc.F, Record, Idx); + +    return Context.getDependentSizedArrayType(ElementType, NumElts, ASM, +                                               IndexTypeQuals, Brackets); +  } + +  case TYPE_TEMPLATE_SPECIALIZATION: { +    unsigned Idx = 0; +    bool IsDependent = Record[Idx++]; +    TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx); +    SmallVector<TemplateArgument, 8> Args; +    ReadTemplateArgumentList(Args, *Loc.F, Record, Idx); +    QualType Underlying = readType(*Loc.F, Record, Idx); +    QualType T; +    if (Underlying.isNull()) +      T = Context.getCanonicalTemplateSpecializationType(Name, Args.data(), +                                                          Args.size()); +    else +      T = Context.getTemplateSpecializationType(Name, Args.data(), +                                                 Args.size(), Underlying); +    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); +    return T; +  } + +  case TYPE_ATOMIC: { +    if (Record.size() != 1) { +      Error("Incorrect encoding of atomic type"); +      return QualType(); +    } +    QualType ValueType = readType(*Loc.F, Record, Idx); +    return Context.getAtomicType(ValueType); +  } +  } +  llvm_unreachable("Invalid TypeCode!"); +} + +class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> { +  ASTReader &Reader; +  ModuleFile &F; +  llvm::BitstreamCursor &DeclsCursor; +  const ASTReader::RecordData &Record; +  unsigned &Idx; + +  SourceLocation ReadSourceLocation(const ASTReader::RecordData &R, +                                    unsigned &I) { +    return Reader.ReadSourceLocation(F, R, I); +  } + +  template<typename T> +  T *ReadDeclAs(const ASTReader::RecordData &Record, unsigned &Idx) { +    return Reader.ReadDeclAs<T>(F, Record, Idx); +  } +   +public: +  TypeLocReader(ASTReader &Reader, ModuleFile &F, +                const ASTReader::RecordData &Record, unsigned &Idx) +    : Reader(Reader), F(F), DeclsCursor(F.DeclsCursor), 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(ReadSourceLocation(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(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) { +  TL.setStarLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { +  TL.setCaretLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { +  TL.setAmpLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { +  TL.setAmpAmpLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { +  TL.setStarLoc(ReadSourceLocation(Record, Idx)); +  TL.setClassTInfo(Reader.GetTypeSourceInfo(F, Record, Idx)); +} +void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { +  TL.setLBracketLoc(ReadSourceLocation(Record, Idx)); +  TL.setRBracketLoc(ReadSourceLocation(Record, Idx)); +  if (Record[Idx++]) +    TL.setSizeExpr(Reader.ReadExpr(F)); +  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(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { +  TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx)); +  TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx)); +  TL.setTrailingReturn(Record[Idx++]); +  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { +    TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx)); +  } +} +void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { +  VisitFunctionTypeLoc(TL); +} +void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { +  VisitFunctionTypeLoc(TL); +} +void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { +  TL.setTypeofLoc(ReadSourceLocation(Record, Idx)); +  TL.setLParenLoc(ReadSourceLocation(Record, Idx)); +  TL.setRParenLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { +  TL.setTypeofLoc(ReadSourceLocation(Record, Idx)); +  TL.setLParenLoc(ReadSourceLocation(Record, Idx)); +  TL.setRParenLoc(ReadSourceLocation(Record, Idx)); +  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx)); +} +void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { +  TL.setKWLoc(ReadSourceLocation(Record, Idx)); +  TL.setLParenLoc(ReadSourceLocation(Record, Idx)); +  TL.setRParenLoc(ReadSourceLocation(Record, Idx)); +  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx)); +} +void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { +  TL.setAttrNameLoc(ReadSourceLocation(Record, Idx)); +  if (TL.hasAttrOperand()) { +    SourceRange range; +    range.setBegin(ReadSourceLocation(Record, Idx)); +    range.setEnd(ReadSourceLocation(Record, Idx)); +    TL.setAttrOperandParensRange(range); +  } +  if (TL.hasAttrExprOperand()) { +    if (Record[Idx++]) +      TL.setAttrExprOperand(Reader.ReadExpr(F)); +    else +      TL.setAttrExprOperand(0); +  } else if (TL.hasAttrEnumOperand()) +    TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc( +                                            SubstTemplateTypeParmTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc( +                                          SubstTemplateTypeParmPackTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitTemplateSpecializationTypeLoc( +                                           TemplateSpecializationTypeLoc TL) { +  TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx)); +  TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx)); +  TL.setLAngleLoc(ReadSourceLocation(Record, Idx)); +  TL.setRAngleLoc(ReadSourceLocation(Record, Idx)); +  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) +    TL.setArgLocInfo(i, +        Reader.GetTemplateArgumentLocInfo(F, +                                          TL.getTypePtr()->getArg(i).getKind(), +                                          Record, Idx)); +} +void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { +  TL.setLParenLoc(ReadSourceLocation(Record, Idx)); +  TL.setRParenLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { +  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx)); +  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); +} +void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { +  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx)); +  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( +       DependentTemplateSpecializationTypeLoc TL) { +  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx)); +  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); +  TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx)); +  TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx)); +  TL.setLAngleLoc(ReadSourceLocation(Record, Idx)); +  TL.setRAngleLoc(ReadSourceLocation(Record, Idx)); +  for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) +    TL.setArgLocInfo(I, +        Reader.GetTemplateArgumentLocInfo(F, +                                          TL.getTypePtr()->getArg(I).getKind(), +                                          Record, Idx)); +} +void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { +  TL.setEllipsisLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { +  TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { +  TL.setHasBaseTypeAsWritten(Record[Idx++]); +  TL.setLAngleLoc(ReadSourceLocation(Record, Idx)); +  TL.setRAngleLoc(ReadSourceLocation(Record, Idx)); +  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) +    TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { +  TL.setStarLoc(ReadSourceLocation(Record, Idx)); +} +void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) { +  TL.setKWLoc(ReadSourceLocation(Record, Idx)); +  TL.setLParenLoc(ReadSourceLocation(Record, Idx)); +  TL.setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F, +                                             const RecordData &Record, +                                             unsigned &Idx) { +  QualType InfoTy = readType(F, Record, Idx); +  if (InfoTy.isNull()) +    return 0; + +  TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy); +  TypeLocReader TLR(*this, F, Record, Idx); +  for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) +    TLR.Visit(TL); +  return TInfo; +} + +QualType ASTReader::GetType(TypeID ID) { +  unsigned FastQuals = ID & Qualifiers::FastMask; +  unsigned Index = ID >> Qualifiers::FastWidth; + +  if (Index < NUM_PREDEF_TYPE_IDS) { +    QualType T; +    switch ((PredefinedTypeIDs)Index) { +    case PREDEF_TYPE_NULL_ID: return QualType(); +    case PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break; +    case PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break; + +    case PREDEF_TYPE_CHAR_U_ID: +    case PREDEF_TYPE_CHAR_S_ID: +      // FIXME: Check that the signedness of CharTy is correct! +      T = Context.CharTy; +      break; + +    case PREDEF_TYPE_UCHAR_ID:      T = Context.UnsignedCharTy;     break; +    case PREDEF_TYPE_USHORT_ID:     T = Context.UnsignedShortTy;    break; +    case PREDEF_TYPE_UINT_ID:       T = Context.UnsignedIntTy;      break; +    case PREDEF_TYPE_ULONG_ID:      T = Context.UnsignedLongTy;     break; +    case PREDEF_TYPE_ULONGLONG_ID:  T = Context.UnsignedLongLongTy; break; +    case PREDEF_TYPE_UINT128_ID:    T = Context.UnsignedInt128Ty;   break; +    case PREDEF_TYPE_SCHAR_ID:      T = Context.SignedCharTy;       break; +    case PREDEF_TYPE_WCHAR_ID:      T = Context.WCharTy;            break; +    case PREDEF_TYPE_SHORT_ID:      T = Context.ShortTy;            break; +    case PREDEF_TYPE_INT_ID:        T = Context.IntTy;              break; +    case PREDEF_TYPE_LONG_ID:       T = Context.LongTy;             break; +    case PREDEF_TYPE_LONGLONG_ID:   T = Context.LongLongTy;         break; +    case PREDEF_TYPE_INT128_ID:     T = Context.Int128Ty;           break; +    case PREDEF_TYPE_HALF_ID:       T = Context.HalfTy;             break; +    case PREDEF_TYPE_FLOAT_ID:      T = Context.FloatTy;            break; +    case PREDEF_TYPE_DOUBLE_ID:     T = Context.DoubleTy;           break; +    case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy;       break; +    case PREDEF_TYPE_OVERLOAD_ID:   T = Context.OverloadTy;         break; +    case PREDEF_TYPE_BOUND_MEMBER:  T = Context.BoundMemberTy;      break; +    case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy;     break; +    case PREDEF_TYPE_DEPENDENT_ID:  T = Context.DependentTy;        break; +    case PREDEF_TYPE_UNKNOWN_ANY:   T = Context.UnknownAnyTy;       break; +    case PREDEF_TYPE_NULLPTR_ID:    T = Context.NullPtrTy;          break; +    case PREDEF_TYPE_CHAR16_ID:     T = Context.Char16Ty;           break; +    case PREDEF_TYPE_CHAR32_ID:     T = Context.Char32Ty;           break; +    case PREDEF_TYPE_OBJC_ID:       T = Context.ObjCBuiltinIdTy;    break; +    case PREDEF_TYPE_OBJC_CLASS:    T = Context.ObjCBuiltinClassTy; break; +    case PREDEF_TYPE_OBJC_SEL:      T = Context.ObjCBuiltinSelTy;   break; +    case PREDEF_TYPE_AUTO_DEDUCT:   T = Context.getAutoDeductType(); break; +         +    case PREDEF_TYPE_AUTO_RREF_DEDUCT:  +      T = Context.getAutoRRefDeductType();  +      break; + +    case PREDEF_TYPE_ARC_UNBRIDGED_CAST: +      T = Context.ARCUnbridgedCastTy; +      break; + +    } + +    assert(!T.isNull() && "Unknown predefined type"); +    return T.withFastQualifiers(FastQuals); +  } + +  Index -= NUM_PREDEF_TYPE_IDS; +  assert(Index < TypesLoaded.size() && "Type index out-of-range"); +  if (TypesLoaded[Index].isNull()) { +    TypesLoaded[Index] = readTypeRecord(Index); +    if (TypesLoaded[Index].isNull()) +      return QualType(); + +    TypesLoaded[Index]->setFromAST(); +    if (DeserializationListener) +      DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID), +                                        TypesLoaded[Index]); +  } + +  return TypesLoaded[Index].withFastQualifiers(FastQuals); +} + +QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) { +  return GetType(getGlobalTypeID(F, LocalID)); +} + +serialization::TypeID  +ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const { +  unsigned FastQuals = LocalID & Qualifiers::FastMask; +  unsigned LocalIndex = LocalID >> Qualifiers::FastWidth; +   +  if (LocalIndex < NUM_PREDEF_TYPE_IDS) +    return LocalID; + +  ContinuousRangeMap<uint32_t, int, 2>::iterator I +    = F.TypeRemap.find(LocalIndex - NUM_PREDEF_TYPE_IDS); +  assert(I != F.TypeRemap.end() && "Invalid index into type index remap"); +   +  unsigned GlobalIndex = LocalIndex + I->second; +  return (GlobalIndex << Qualifiers::FastWidth) | FastQuals; +} + +TemplateArgumentLocInfo +ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F, +                                      TemplateArgument::ArgKind Kind, +                                      const RecordData &Record, +                                      unsigned &Index) { +  switch (Kind) { +  case TemplateArgument::Expression: +    return ReadExpr(F); +  case TemplateArgument::Type: +    return GetTypeSourceInfo(F, Record, Index); +  case TemplateArgument::Template: { +    NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record,  +                                                                     Index); +    SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index); +    return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, +                                   SourceLocation()); +  } +  case TemplateArgument::TemplateExpansion: { +    NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record,  +                                                                     Index); +    SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index); +    SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index); +    return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,  +                                   EllipsisLoc); +  } +  case TemplateArgument::Null: +  case TemplateArgument::Integral: +  case TemplateArgument::Declaration: +  case TemplateArgument::Pack: +    return TemplateArgumentLocInfo(); +  } +  llvm_unreachable("unexpected template argument loc"); +} + +TemplateArgumentLoc +ASTReader::ReadTemplateArgumentLoc(ModuleFile &F, +                                   const RecordData &Record, unsigned &Index) { +  TemplateArgument Arg = ReadTemplateArgument(F, Record, Index); + +  if (Arg.getKind() == TemplateArgument::Expression) { +    if (Record[Index++]) // bool InfoHasSameExpr. +      return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr())); +  } +  return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(F, Arg.getKind(), +                                                             Record, Index)); +} + +Decl *ASTReader::GetExternalDecl(uint32_t ID) { +  return GetDecl(ID); +} + +uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record,  +                                          unsigned &Idx){ +  if (Idx >= Record.size()) +    return 0; +   +  unsigned LocalID = Record[Idx++]; +  return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]); +} + +CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { +  RecordLocation Loc = getLocalBitOffset(Offset); +  llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor; +  SavedStreamPosition SavedPosition(Cursor); +  Cursor.JumpToBit(Loc.Offset); +  ReadingKindTracker ReadingKind(Read_Decl, *this); +  RecordData Record; +  unsigned Code = Cursor.ReadCode(); +  unsigned RecCode = Cursor.ReadRecord(Code, Record); +  if (RecCode != DECL_CXX_BASE_SPECIFIERS) { +    Error("Malformed AST file: missing C++ base specifiers"); +    return 0; +  } + +  unsigned Idx = 0; +  unsigned NumBases = Record[Idx++]; +  void *Mem = Context.Allocate(sizeof(CXXBaseSpecifier) * NumBases); +  CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases]; +  for (unsigned I = 0; I != NumBases; ++I) +    Bases[I] = ReadCXXBaseSpecifier(*Loc.F, Record, Idx); +  return Bases; +} + +serialization::DeclID  +ASTReader::getGlobalDeclID(ModuleFile &F, unsigned LocalID) const { +  if (LocalID < NUM_PREDEF_DECL_IDS) +    return LocalID; + +  ContinuousRangeMap<uint32_t, int, 2>::iterator I +    = F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS); +  assert(I != F.DeclRemap.end() && "Invalid index into decl index remap"); +   +  return LocalID + I->second; +} + +bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, +                                   ModuleFile &M) const { +  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID); +  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); +  return &M == I->second; +} + +ModuleFile *ASTReader::getOwningModuleFile(Decl *D) { +  if (!D->isFromASTFile()) +    return 0; +  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID()); +  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); +  return I->second; +} + +SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { +  if (ID < NUM_PREDEF_DECL_IDS) +    return SourceLocation(); +   +  unsigned Index = ID - NUM_PREDEF_DECL_IDS; + +  if (Index > DeclsLoaded.size()) { +    Error("declaration ID out-of-range for AST file"); +    return SourceLocation(); +  } +   +  if (Decl *D = DeclsLoaded[Index]) +    return D->getLocation(); + +  unsigned RawLocation = 0; +  RecordLocation Rec = DeclCursorForID(ID, RawLocation); +  return ReadSourceLocation(*Rec.F, RawLocation); +} + +Decl *ASTReader::GetDecl(DeclID ID) { +  if (ID < NUM_PREDEF_DECL_IDS) {     +    switch ((PredefinedDeclIDs)ID) { +    case PREDEF_DECL_NULL_ID: +      return 0; +         +    case PREDEF_DECL_TRANSLATION_UNIT_ID: +      return Context.getTranslationUnitDecl(); +         +    case PREDEF_DECL_OBJC_ID_ID: +      return Context.getObjCIdDecl(); + +    case PREDEF_DECL_OBJC_SEL_ID: +      return Context.getObjCSelDecl(); + +    case PREDEF_DECL_OBJC_CLASS_ID: +      return Context.getObjCClassDecl(); +         +    case PREDEF_DECL_OBJC_PROTOCOL_ID: +      return Context.getObjCProtocolDecl(); +         +    case PREDEF_DECL_INT_128_ID: +      return Context.getInt128Decl(); + +    case PREDEF_DECL_UNSIGNED_INT_128_ID: +      return Context.getUInt128Decl(); +         +    case PREDEF_DECL_OBJC_INSTANCETYPE_ID: +      return Context.getObjCInstanceTypeDecl(); +    } +  } +   +  unsigned Index = ID - NUM_PREDEF_DECL_IDS; + +  if (Index >= DeclsLoaded.size()) { +    Error("declaration ID out-of-range for AST file"); +  } +   +  if (!DeclsLoaded[Index]) { +    ReadDeclRecord(ID); +    if (DeserializationListener) +      DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); +  } + +  return DeclsLoaded[Index]; +} + +DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M,  +                                                  DeclID GlobalID) { +  if (GlobalID < NUM_PREDEF_DECL_IDS) +    return GlobalID; +   +  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID); +  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); +  ModuleFile *Owner = I->second; + +  llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos +    = M.GlobalToLocalDeclIDs.find(Owner); +  if (Pos == M.GlobalToLocalDeclIDs.end()) +    return 0; +       +  return GlobalID - Owner->BaseDeclID + Pos->second; +} + +serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F,  +                                            const RecordData &Record, +                                            unsigned &Idx) { +  if (Idx >= Record.size()) { +    Error("Corrupted AST file"); +    return 0; +  } +   +  return getGlobalDeclID(F, Record[Idx++]); +} + +/// \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 *ASTReader::GetExternalDeclStmt(uint64_t Offset) { +  // Switch case IDs are per Decl. +  ClearSwitchCaseIDs(); + +  // Offset here is a global offset across the entire chain. +  RecordLocation Loc = getLocalBitOffset(Offset); +  Loc.F->DeclsCursor.JumpToBit(Loc.Offset); +  return ReadStmtFromStream(*Loc.F); +} + +namespace { +  class FindExternalLexicalDeclsVisitor { +    ASTReader &Reader; +    const DeclContext *DC; +    bool (*isKindWeWant)(Decl::Kind); +     +    SmallVectorImpl<Decl*> &Decls; +    bool PredefsVisited[NUM_PREDEF_DECL_IDS]; + +  public: +    FindExternalLexicalDeclsVisitor(ASTReader &Reader, const DeclContext *DC, +                                    bool (*isKindWeWant)(Decl::Kind), +                                    SmallVectorImpl<Decl*> &Decls) +      : Reader(Reader), DC(DC), isKindWeWant(isKindWeWant), Decls(Decls)  +    { +      for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I) +        PredefsVisited[I] = false; +    } + +    static bool visit(ModuleFile &M, bool Preorder, void *UserData) { +      if (Preorder) +        return false; + +      FindExternalLexicalDeclsVisitor *This +        = static_cast<FindExternalLexicalDeclsVisitor *>(UserData); + +      ModuleFile::DeclContextInfosMap::iterator Info +        = M.DeclContextInfos.find(This->DC); +      if (Info == M.DeclContextInfos.end() || !Info->second.LexicalDecls) +        return false; + +      // Load all of the declaration IDs +      for (const KindDeclIDPair *ID = Info->second.LexicalDecls, +                               *IDE = ID + Info->second.NumLexicalDecls;  +           ID != IDE; ++ID) { +        if (This->isKindWeWant && !This->isKindWeWant((Decl::Kind)ID->first)) +          continue; + +        // Don't add predefined declarations to the lexical context more +        // than once. +        if (ID->second < NUM_PREDEF_DECL_IDS) { +          if (This->PredefsVisited[ID->second]) +            continue; + +          This->PredefsVisited[ID->second] = true; +        } + +        if (Decl *D = This->Reader.GetLocalDecl(M, ID->second)) { +          if (!This->DC->isDeclInLexicalTraversal(D)) +            This->Decls.push_back(D); +        } +      } + +      return false; +    } +  }; +} + +ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC, +                                         bool (*isKindWeWant)(Decl::Kind), +                                         SmallVectorImpl<Decl*> &Decls) { +  // There might be lexical decls in multiple modules, for the TU at +  // least. Walk all of the modules in the order they were loaded. +  FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls); +  ModuleMgr.visitDepthFirst(&FindExternalLexicalDeclsVisitor::visit, &Visitor); +  ++NumLexicalDeclContextsRead; +  return ELR_Success; +} + +namespace { + +class DeclIDComp { +  ASTReader &Reader; +  ModuleFile &Mod; + +public: +  DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {} + +  bool operator()(LocalDeclID L, LocalDeclID R) const { +    SourceLocation LHS = getLocation(L); +    SourceLocation RHS = getLocation(R); +    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); +  } + +  bool operator()(SourceLocation LHS, LocalDeclID R) const { +    SourceLocation RHS = getLocation(R); +    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); +  } + +  bool operator()(LocalDeclID L, SourceLocation RHS) const { +    SourceLocation LHS = getLocation(L); +    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); +  } + +  SourceLocation getLocation(LocalDeclID ID) const { +    return Reader.getSourceManager().getFileLoc( +            Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID))); +  } +}; + +} + +void ASTReader::FindFileRegionDecls(FileID File, +                                    unsigned Offset, unsigned Length, +                                    SmallVectorImpl<Decl *> &Decls) { +  SourceManager &SM = getSourceManager(); + +  llvm::DenseMap<FileID, FileDeclsInfo>::iterator I = FileDeclIDs.find(File); +  if (I == FileDeclIDs.end()) +    return; + +  FileDeclsInfo &DInfo = I->second; +  if (DInfo.Decls.empty()) +    return; + +  SourceLocation +    BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset); +  SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length); + +  DeclIDComp DIDComp(*this, *DInfo.Mod); +  ArrayRef<serialization::LocalDeclID>::iterator +    BeginIt = std::lower_bound(DInfo.Decls.begin(), DInfo.Decls.end(), +                               BeginLoc, DIDComp); +  if (BeginIt != DInfo.Decls.begin()) +    --BeginIt; + +  // If we are pointing at a top-level decl inside an objc container, we need +  // to backtrack until we find it otherwise we will fail to report that the +  // region overlaps with an objc container. +  while (BeginIt != DInfo.Decls.begin() && +         GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt)) +             ->isTopLevelDeclInObjCContainer()) +    --BeginIt; + +  ArrayRef<serialization::LocalDeclID>::iterator +    EndIt = std::upper_bound(DInfo.Decls.begin(), DInfo.Decls.end(), +                             EndLoc, DIDComp); +  if (EndIt != DInfo.Decls.end()) +    ++EndIt; +   +  for (ArrayRef<serialization::LocalDeclID>::iterator +         DIt = BeginIt; DIt != EndIt; ++DIt) +    Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt))); +} + +namespace { +  /// \brief ModuleFile visitor used to perform name lookup into a +  /// declaration context. +  class DeclContextNameLookupVisitor { +    ASTReader &Reader; +    llvm::SmallVectorImpl<const DeclContext *> &Contexts; +    const DeclContext *DC; +    DeclarationName Name; +    SmallVectorImpl<NamedDecl *> &Decls; + +  public: +    DeclContextNameLookupVisitor(ASTReader &Reader,  +                                 SmallVectorImpl<const DeclContext *> &Contexts,  +                                 DeclarationName Name, +                                 SmallVectorImpl<NamedDecl *> &Decls) +      : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { } + +    static bool visit(ModuleFile &M, void *UserData) { +      DeclContextNameLookupVisitor *This +        = static_cast<DeclContextNameLookupVisitor *>(UserData); + +      // Check whether we have any visible declaration information for +      // this context in this module. +      ModuleFile::DeclContextInfosMap::iterator Info; +      bool FoundInfo = false; +      for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) { +        Info = M.DeclContextInfos.find(This->Contexts[I]); +        if (Info != M.DeclContextInfos.end() &&  +            Info->second.NameLookupTableData) { +          FoundInfo = true; +          break; +        } +      } + +      if (!FoundInfo) +        return false; +       +      // Look for this name within this module. +      ASTDeclContextNameLookupTable *LookupTable = +        Info->second.NameLookupTableData; +      ASTDeclContextNameLookupTable::iterator Pos +        = LookupTable->find(This->Name); +      if (Pos == LookupTable->end()) +        return false; + +      bool FoundAnything = false; +      ASTDeclContextNameLookupTrait::data_type Data = *Pos; +      for (; Data.first != Data.second; ++Data.first) { +        NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first); +        if (!ND) +          continue; + +        if (ND->getDeclName() != This->Name) { +          assert(!This->Name.getCXXNameType().isNull() &&  +                 "Name mismatch without a type"); +          continue; +        } +       +        // Record this declaration. +        FoundAnything = true; +        This->Decls.push_back(ND); +      } + +      return FoundAnything; +    } +  }; +} + +DeclContext::lookup_result +ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, +                                          DeclarationName Name) { +  assert(DC->hasExternalVisibleStorage() && +         "DeclContext has no visible decls in storage"); +  if (!Name) +    return DeclContext::lookup_result(DeclContext::lookup_iterator(0), +                                      DeclContext::lookup_iterator(0)); + +  SmallVector<NamedDecl *, 64> Decls; +   +  // Compute the declaration contexts we need to look into. Multiple such +  // declaration contexts occur when two declaration contexts from disjoint +  // modules get merged, e.g., when two namespaces with the same name are  +  // independently defined in separate modules. +  SmallVector<const DeclContext *, 2> Contexts; +  Contexts.push_back(DC); +   +  if (DC->isNamespace()) { +    MergedDeclsMap::iterator Merged +      = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC))); +    if (Merged != MergedDecls.end()) { +      for (unsigned I = 0, N = Merged->second.size(); I != N; ++I) +        Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I]))); +    } +  } +   +  DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls); +  ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor); +  ++NumVisibleDeclContextsRead; +  SetExternalVisibleDeclsForName(DC, Name, Decls); +  return const_cast<DeclContext*>(DC)->lookup(Name); +} + +namespace { +  /// \brief ModuleFile visitor used to retrieve all visible names in a +  /// declaration context. +  class DeclContextAllNamesVisitor { +    ASTReader &Reader; +    llvm::SmallVectorImpl<const DeclContext *> &Contexts; +    const DeclContext *DC; +    llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > &Decls; + +  public: +    DeclContextAllNamesVisitor(ASTReader &Reader, +                               SmallVectorImpl<const DeclContext *> &Contexts, +                               llvm::DenseMap<DeclarationName, +                                           SmallVector<NamedDecl *, 8> > &Decls) +      : Reader(Reader), Contexts(Contexts), Decls(Decls) { } + +    static bool visit(ModuleFile &M, void *UserData) { +      DeclContextAllNamesVisitor *This +        = static_cast<DeclContextAllNamesVisitor *>(UserData); + +      // Check whether we have any visible declaration information for +      // this context in this module. +      ModuleFile::DeclContextInfosMap::iterator Info; +      bool FoundInfo = false; +      for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) { +        Info = M.DeclContextInfos.find(This->Contexts[I]); +        if (Info != M.DeclContextInfos.end() && +            Info->second.NameLookupTableData) { +          FoundInfo = true; +          break; +        } +      } + +      if (!FoundInfo) +        return false; + +      ASTDeclContextNameLookupTable *LookupTable = +        Info->second.NameLookupTableData; +      bool FoundAnything = false; +      for (ASTDeclContextNameLookupTable::data_iterator +	     I = LookupTable->data_begin(), E = LookupTable->data_end(); +	   I != E; ++I) { +        ASTDeclContextNameLookupTrait::data_type Data = *I; +        for (; Data.first != Data.second; ++Data.first) { +          NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M, +                                                                 *Data.first); +          if (!ND) +            continue; + +          // Record this declaration. +          FoundAnything = true; +          This->Decls[ND->getDeclName()].push_back(ND); +        } +      } + +      return FoundAnything; +    } +  }; +} + +void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { +  if (!DC->hasExternalVisibleStorage()) +    return; +  llvm::DenseMap<DeclarationName, llvm::SmallVector<NamedDecl*, 8> > Decls; + +  // Compute the declaration contexts we need to look into. Multiple such +  // declaration contexts occur when two declaration contexts from disjoint +  // modules get merged, e.g., when two namespaces with the same name are +  // independently defined in separate modules. +  SmallVector<const DeclContext *, 2> Contexts; +  Contexts.push_back(DC); + +  if (DC->isNamespace()) { +    MergedDeclsMap::iterator Merged +      = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC))); +    if (Merged != MergedDecls.end()) { +      for (unsigned I = 0, N = Merged->second.size(); I != N; ++I) +        Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I]))); +    } +  } + +  DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls); +  ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor); +  ++NumVisibleDeclContextsRead; + +  for (llvm::DenseMap<DeclarationName, +                      llvm::SmallVector<NamedDecl*, 8> >::iterator +         I = Decls.begin(), E = Decls.end(); I != E; ++I) { +    SetExternalVisibleDeclsForName(DC, I->first, I->second); +  } +} + +/// \brief Under non-PCH compilation the consumer receives the objc methods +/// before receiving the implementation, and codegen depends on this. +/// We simulate this by deserializing and passing to consumer the methods of the +/// implementation before passing the deserialized implementation decl. +static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD, +                                       ASTConsumer *Consumer) { +  assert(ImplD && Consumer); + +  for (ObjCImplDecl::method_iterator +         I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I) +    Consumer->HandleInterestingDecl(DeclGroupRef(*I)); + +  Consumer->HandleInterestingDecl(DeclGroupRef(ImplD)); +} + +void ASTReader::PassInterestingDeclsToConsumer() { +  assert(Consumer); +  while (!InterestingDecls.empty()) { +    Decl *D = InterestingDecls.front(); +    InterestingDecls.pop_front(); + +    PassInterestingDeclToConsumer(D); +  } +} + +void ASTReader::PassInterestingDeclToConsumer(Decl *D) { +  if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) +    PassObjCImplDeclToConsumer(ImplD, Consumer); +  else +    Consumer->HandleInterestingDecl(DeclGroupRef(D)); +} + +void ASTReader::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]); +  } +  ExternalDefinitions.clear(); + +  PassInterestingDeclsToConsumer(); +} + +void ASTReader::PrintStats() { +  std::fprintf(stderr, "*** AST File 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 (unsigned TotalNumSLocEntries = getTotalNumSLocs()) +    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"); +  dump(); +  std::fprintf(stderr, "\n"); +} + +template<typename Key, typename ModuleFile, unsigned InitialCapacity> +static void  +dumpModuleIDMap(StringRef Name, +                const ContinuousRangeMap<Key, ModuleFile *,  +                                         InitialCapacity> &Map) { +  if (Map.begin() == Map.end()) +    return; +   +  typedef ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> MapType; +  llvm::errs() << Name << ":\n"; +  for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();  +       I != IEnd; ++I) { +    llvm::errs() << "  " << I->first << " -> " << I->second->FileName +      << "\n"; +  } +} + +void ASTReader::dump() { +  llvm::errs() << "*** PCH/ModuleFile Remappings:\n"; +  dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap); +  dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap); +  dumpModuleIDMap("Global type map", GlobalTypeMap); +  dumpModuleIDMap("Global declaration map", GlobalDeclMap); +  dumpModuleIDMap("Global identifier map", GlobalIdentifierMap); +  dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap); +  dumpModuleIDMap("Global selector map", GlobalSelectorMap); +  dumpModuleIDMap("Global preprocessed entity map",  +                  GlobalPreprocessedEntityMap); +   +  llvm::errs() << "\n*** PCH/Modules Loaded:"; +  for (ModuleManager::ModuleConstIterator M = ModuleMgr.begin(),  +                                       MEnd = ModuleMgr.end(); +       M != MEnd; ++M) +    (*M)->dump(); +} + +/// Return the amount of memory used by memory buffers, breaking down +/// by heap-backed versus mmap'ed memory. +void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { +  for (ModuleConstIterator I = ModuleMgr.begin(), +      E = ModuleMgr.end(); I != E; ++I) { +    if (llvm::MemoryBuffer *buf = (*I)->Buffer.get()) { +      size_t bytes = buf->getBufferSize(); +      switch (buf->getBufferKind()) { +        case llvm::MemoryBuffer::MemoryBuffer_Malloc: +          sizes.malloc_bytes += bytes; +          break; +        case llvm::MemoryBuffer::MemoryBuffer_MMap: +          sizes.mmap_bytes += bytes; +          break; +      } +    } +  } +} + +void ASTReader::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. +  for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) { +    SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I],  +                                       PreloadedDecls[I]->getDeclName()); +  } +  PreloadedDecls.clear(); + +  // 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!"); +    if (!SemaObj->StdNamespace) +      SemaObj->StdNamespace = SemaDeclRefs[0]; +    if (!SemaObj->StdBadAlloc) +      SemaObj->StdBadAlloc = SemaDeclRefs[1]; +  } + +  if (!FPPragmaOptions.empty()) { +    assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS"); +    SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0]; +  } + +  if (!OpenCLExtensions.empty()) { +    unsigned I = 0; +#define OPENCLEXT(nm)  SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++]; +#include "clang/Basic/OpenCLExtensions.def" + +    assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS"); +  } +} + +IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { +  IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart), +                                  /*PriorGeneration=*/0); +  ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); +  IdentifierInfo *II = Visitor.getIdentifierInfo(); +  markIdentifierUpToDate(II); +  return II; +} + +namespace clang { +  /// \brief An identifier-lookup iterator that enumerates all of the +  /// identifiers stored within a set of AST files. +  class ASTIdentifierIterator : public IdentifierIterator { +    /// \brief The AST reader whose identifiers are being enumerated. +    const ASTReader &Reader; + +    /// \brief The current index into the chain of AST files stored in +    /// the AST reader. +    unsigned Index; + +    /// \brief The current position within the identifier lookup table +    /// of the current AST file. +    ASTIdentifierLookupTable::key_iterator Current; + +    /// \brief The end position within the identifier lookup table of +    /// the current AST file. +    ASTIdentifierLookupTable::key_iterator End; + +  public: +    explicit ASTIdentifierIterator(const ASTReader &Reader); + +    virtual StringRef Next(); +  }; +} + +ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader) +  : Reader(Reader), Index(Reader.ModuleMgr.size() - 1) { +  ASTIdentifierLookupTable *IdTable +    = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].IdentifierLookupTable; +  Current = IdTable->key_begin(); +  End = IdTable->key_end(); +} + +StringRef ASTIdentifierIterator::Next() { +  while (Current == End) { +    // If we have exhausted all of our AST files, we're done. +    if (Index == 0) +      return StringRef(); + +    --Index; +    ASTIdentifierLookupTable *IdTable +      = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index]. +        IdentifierLookupTable; +    Current = IdTable->key_begin(); +    End = IdTable->key_end(); +  } + +  // We have any identifiers remaining in the current AST file; return +  // the next one. +  std::pair<const char*, unsigned> Key = *Current; +  ++Current; +  return StringRef(Key.first, Key.second); +} + +IdentifierIterator *ASTReader::getIdentifiers() const { +  return new ASTIdentifierIterator(*this); +} + +namespace clang { namespace serialization { +  class ReadMethodPoolVisitor { +    ASTReader &Reader; +    Selector Sel; +    unsigned PriorGeneration; +    llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods; +    llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods; + +  public: +    ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel,  +                          unsigned PriorGeneration) +      : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) { } +     +    static bool visit(ModuleFile &M, void *UserData) { +      ReadMethodPoolVisitor *This +        = static_cast<ReadMethodPoolVisitor *>(UserData); +       +      if (!M.SelectorLookupTable) +        return false; +       +      // If we've already searched this module file, skip it now. +      if (M.Generation <= This->PriorGeneration) +        return true; + +      ASTSelectorLookupTable *PoolTable +        = (ASTSelectorLookupTable*)M.SelectorLookupTable; +      ASTSelectorLookupTable::iterator Pos = PoolTable->find(This->Sel); +      if (Pos == PoolTable->end()) +        return false; +       +      ++This->Reader.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? +      ++This->Reader.NumMethodPoolEntriesRead; +      ASTSelectorLookupTrait::data_type Data = *Pos; +      if (This->Reader.DeserializationListener) +        This->Reader.DeserializationListener->SelectorRead(Data.ID,  +                                                           This->Sel); +       +      This->InstanceMethods.append(Data.Instance.begin(), Data.Instance.end()); +      This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end()); +      return true; +    } +     +    /// \brief Retrieve the instance methods found by this visitor. +    ArrayRef<ObjCMethodDecl *> getInstanceMethods() const {  +      return InstanceMethods;  +    } + +    /// \brief Retrieve the instance methods found by this visitor. +    ArrayRef<ObjCMethodDecl *> getFactoryMethods() const {  +      return FactoryMethods; +    } +  }; +} } // end namespace clang::serialization + +/// \brief Add the given set of methods to the method list. +static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods, +                             ObjCMethodList &List) { +  for (unsigned I = 0, N = Methods.size(); I != N; ++I) { +    S.addMethodToGlobalList(&List, Methods[I]); +  } +} +                              +void ASTReader::ReadMethodPool(Selector Sel) { +  // Get the selector generation and update it to the current generation. +  unsigned &Generation = SelectorGeneration[Sel]; +  unsigned PriorGeneration = Generation; +  Generation = CurrentGeneration; +   +  // Search for methods defined with this selector. +  ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration); +  ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor); +   +  if (Visitor.getInstanceMethods().empty() && +      Visitor.getFactoryMethods().empty()) { +    ++NumMethodPoolMisses; +    return; +  } +   +  if (!getSema()) +    return; +   +  Sema &S = *getSema(); +  Sema::GlobalMethodPool::iterator Pos +    = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first; +   +  addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first); +  addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second); +} + +void ASTReader::ReadKnownNamespaces( +                          SmallVectorImpl<NamespaceDecl *> &Namespaces) { +  Namespaces.clear(); +   +  for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) { +    if (NamespaceDecl *Namespace  +                = dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I]))) +      Namespaces.push_back(Namespace); +  } +} + +void ASTReader::ReadTentativeDefinitions( +                  SmallVectorImpl<VarDecl *> &TentativeDefs) { +  for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { +    VarDecl *Var = dyn_cast_or_null<VarDecl>(GetDecl(TentativeDefinitions[I])); +    if (Var) +      TentativeDefs.push_back(Var); +  } +  TentativeDefinitions.clear(); +} + +void ASTReader::ReadUnusedFileScopedDecls( +                               SmallVectorImpl<const DeclaratorDecl *> &Decls) { +  for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) { +    DeclaratorDecl *D +      = dyn_cast_or_null<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I])); +    if (D) +      Decls.push_back(D); +  } +  UnusedFileScopedDecls.clear(); +} + +void ASTReader::ReadDelegatingConstructors( +                                 SmallVectorImpl<CXXConstructorDecl *> &Decls) { +  for (unsigned I = 0, N = DelegatingCtorDecls.size(); I != N; ++I) { +    CXXConstructorDecl *D +      = dyn_cast_or_null<CXXConstructorDecl>(GetDecl(DelegatingCtorDecls[I])); +    if (D) +      Decls.push_back(D); +  } +  DelegatingCtorDecls.clear(); +} + +void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) { +  for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) { +    TypedefNameDecl *D +      = dyn_cast_or_null<TypedefNameDecl>(GetDecl(ExtVectorDecls[I])); +    if (D) +      Decls.push_back(D); +  } +  ExtVectorDecls.clear(); +} + +void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) { +  for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) { +    CXXRecordDecl *D +      = dyn_cast_or_null<CXXRecordDecl>(GetDecl(DynamicClasses[I])); +    if (D) +      Decls.push_back(D); +  } +  DynamicClasses.clear(); +} + +void  +ASTReader::ReadLocallyScopedExternalDecls(SmallVectorImpl<NamedDecl *> &Decls) { +  for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) { +    NamedDecl *D  +      = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I])); +    if (D) +      Decls.push_back(D); +  } +  LocallyScopedExternalDecls.clear(); +} + +void ASTReader::ReadReferencedSelectors( +       SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) { +  if (ReferencedSelectorsData.empty()) +    return; +   +  // If there are @selector references added them to its pool. This is for +  // implementation of -Wselector. +  unsigned int DataSize = ReferencedSelectorsData.size()-1; +  unsigned I = 0; +  while (I < DataSize) { +    Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]); +    SourceLocation SelLoc +      = SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]); +    Sels.push_back(std::make_pair(Sel, SelLoc)); +  } +  ReferencedSelectorsData.clear(); +} + +void ASTReader::ReadWeakUndeclaredIdentifiers( +       SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WeakIDs) { +  if (WeakUndeclaredIdentifiers.empty()) +    return; + +  for (unsigned I = 0, N = WeakUndeclaredIdentifiers.size(); I < N; /*none*/) { +    IdentifierInfo *WeakId  +      = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]); +    IdentifierInfo *AliasId  +      = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]); +    SourceLocation Loc +      = SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]); +    bool Used = WeakUndeclaredIdentifiers[I++]; +    WeakInfo WI(AliasId, Loc); +    WI.setUsed(Used); +    WeakIDs.push_back(std::make_pair(WeakId, WI)); +  } +  WeakUndeclaredIdentifiers.clear(); +} + +void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) { +  for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) { +    ExternalVTableUse VT; +    VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(VTableUses[Idx++])); +    VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]); +    VT.DefinitionRequired = VTableUses[Idx++]; +    VTables.push_back(VT); +  } +   +  VTableUses.clear(); +} + +void ASTReader::ReadPendingInstantiations( +       SmallVectorImpl<std::pair<ValueDecl *, SourceLocation> > &Pending) { +  for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) { +    ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++])); +    SourceLocation Loc +      = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]); +    Pending.push_back(std::make_pair(D, Loc)); +  }   +  PendingInstantiations.clear(); +} + +void ASTReader::LoadSelector(Selector Sel) { +  // It would be complicated to avoid reading the methods anyway. So don't. +  ReadMethodPool(Sel); +} + +void ASTReader::SetIdentifierInfo(IdentifierID 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 AST 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 +ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, +                              const SmallVectorImpl<uint32_t> &DeclIDs, +                                   bool Nonrecursive) { +  if (NumCurrentElementsDeserializing && !Nonrecursive) { +    PendingIdentifierInfos.push_back(PendingIdentifierInfo()); +    PendingIdentifierInfo &PII = PendingIdentifierInfos.back(); +    PII.II = II; +    PII.DeclIDs.append(DeclIDs.begin(), DeclIDs.end()); +    return; +  } + +  for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { +    NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); +    if (SemaObj) { +      // 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->pushExternalDeclIntoScope(D, II); +    } 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 *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { +  if (ID == 0) +    return 0; + +  if (IdentifiersLoaded.empty()) { +    Error("no identifier table in AST file"); +    return 0; +  } + +  ID -= 1; +  if (!IdentifiersLoaded[ID]) { +    GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1); +    assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map"); +    ModuleFile *M = I->second; +    unsigned Index = ID - M->BaseIdentifierID; +    const char *Str = M->IdentifierTableData + M->IdentifierOffsets[Index]; + +    // All of the strings in the AST 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(StringRef(Str, StrLen)); +    if (DeserializationListener) +      DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]); +  } + +  return IdentifiersLoaded[ID]; +} + +IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) { +  return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID)); +} + +IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) { +  if (LocalID < NUM_PREDEF_IDENT_IDS) +    return LocalID; +   +  ContinuousRangeMap<uint32_t, int, 2>::iterator I +    = M.IdentifierRemap.find(LocalID - NUM_PREDEF_IDENT_IDS); +  assert(I != M.IdentifierRemap.end()  +         && "Invalid index into identifier index remap"); +   +  return LocalID + I->second; +} + +bool ASTReader::ReadSLocEntry(int ID) { +  return ReadSLocEntryRecord(ID) != Success; +} + +serialization::SubmoduleID +ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) { +  if (LocalID < NUM_PREDEF_SUBMODULE_IDS) +    return LocalID; +   +  ContinuousRangeMap<uint32_t, int, 2>::iterator I +    = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS); +  assert(I != M.SubmoduleRemap.end()  +         && "Invalid index into identifier index remap"); +   +  return LocalID + I->second; +} + +Module *ASTReader::getSubmodule(SubmoduleID GlobalID) { +  if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) { +    assert(GlobalID == 0 && "Unhandled global submodule ID"); +    return 0; +  } +   +  if (GlobalID > SubmodulesLoaded.size()) { +    Error("submodule ID out of range in AST file"); +    return 0; +  } +   +  return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS]; +} +                                +Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) { +  return DecodeSelector(getGlobalSelectorID(M, LocalID)); +} + +Selector ASTReader::DecodeSelector(serialization::SelectorID ID) { +  if (ID == 0) +    return Selector(); + +  if (ID > SelectorsLoaded.size()) { +    Error("selector ID out of range in AST file"); +    return Selector(); +  } + +  if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) { +    // Load this selector from the selector table. +    GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID); +    assert(I != GlobalSelectorMap.end() && "Corrupted global selector map"); +    ModuleFile &M = *I->second; +    ASTSelectorLookupTrait Trait(*this, M); +    unsigned Idx = ID - M.BaseSelectorID - NUM_PREDEF_SELECTOR_IDS; +    SelectorsLoaded[ID - 1] = +      Trait.ReadKey(M.SelectorLookupTableData + M.SelectorOffsets[Idx], 0); +    if (DeserializationListener) +      DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]); +  } + +  return SelectorsLoaded[ID - 1]; +} + +Selector ASTReader::GetExternalSelector(serialization::SelectorID ID) { +  return DecodeSelector(ID); +} + +uint32_t ASTReader::GetNumExternalSelectors() { +  // ID 0 (the null selector) is considered an external selector. +  return getTotalNumSelectors() + 1; +} + +serialization::SelectorID +ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const { +  if (LocalID < NUM_PREDEF_SELECTOR_IDS) +    return LocalID; +   +  ContinuousRangeMap<uint32_t, int, 2>::iterator I +    = M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS); +  assert(I != M.SelectorRemap.end()  +         && "Invalid index into identifier index remap"); +   +  return LocalID + I->second; +} + +DeclarationName +ASTReader::ReadDeclarationName(ModuleFile &F,  +                               const RecordData &Record, unsigned &Idx) { +  DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; +  switch (Kind) { +  case DeclarationName::Identifier: +    return DeclarationName(GetIdentifierInfo(F, Record, Idx)); + +  case DeclarationName::ObjCZeroArgSelector: +  case DeclarationName::ObjCOneArgSelector: +  case DeclarationName::ObjCMultiArgSelector: +    return DeclarationName(ReadSelector(F, Record, Idx)); + +  case DeclarationName::CXXConstructorName: +    return Context.DeclarationNames.getCXXConstructorName( +                          Context.getCanonicalType(readType(F, Record, Idx))); + +  case DeclarationName::CXXDestructorName: +    return Context.DeclarationNames.getCXXDestructorName( +                          Context.getCanonicalType(readType(F, Record, Idx))); + +  case DeclarationName::CXXConversionFunctionName: +    return Context.DeclarationNames.getCXXConversionFunctionName( +                          Context.getCanonicalType(readType(F, Record, Idx))); + +  case DeclarationName::CXXOperatorName: +    return Context.DeclarationNames.getCXXOperatorName( +                                       (OverloadedOperatorKind)Record[Idx++]); + +  case DeclarationName::CXXLiteralOperatorName: +    return Context.DeclarationNames.getCXXLiteralOperatorName( +                                       GetIdentifierInfo(F, Record, Idx)); + +  case DeclarationName::CXXUsingDirective: +    return DeclarationName::getUsingDirectiveName(); +  } + +  llvm_unreachable("Invalid NameKind!"); +} + +void ASTReader::ReadDeclarationNameLoc(ModuleFile &F, +                                       DeclarationNameLoc &DNLoc, +                                       DeclarationName Name, +                                      const RecordData &Record, unsigned &Idx) { +  switch (Name.getNameKind()) { +  case DeclarationName::CXXConstructorName: +  case DeclarationName::CXXDestructorName: +  case DeclarationName::CXXConversionFunctionName: +    DNLoc.NamedType.TInfo = GetTypeSourceInfo(F, Record, Idx); +    break; + +  case DeclarationName::CXXOperatorName: +    DNLoc.CXXOperatorName.BeginOpNameLoc +        = ReadSourceLocation(F, Record, Idx).getRawEncoding(); +    DNLoc.CXXOperatorName.EndOpNameLoc +        = ReadSourceLocation(F, Record, Idx).getRawEncoding(); +    break; + +  case DeclarationName::CXXLiteralOperatorName: +    DNLoc.CXXLiteralOperatorName.OpNameLoc +        = ReadSourceLocation(F, Record, Idx).getRawEncoding(); +    break; + +  case DeclarationName::Identifier: +  case DeclarationName::ObjCZeroArgSelector: +  case DeclarationName::ObjCOneArgSelector: +  case DeclarationName::ObjCMultiArgSelector: +  case DeclarationName::CXXUsingDirective: +    break; +  } +} + +void ASTReader::ReadDeclarationNameInfo(ModuleFile &F, +                                        DeclarationNameInfo &NameInfo, +                                      const RecordData &Record, unsigned &Idx) { +  NameInfo.setName(ReadDeclarationName(F, Record, Idx)); +  NameInfo.setLoc(ReadSourceLocation(F, Record, Idx)); +  DeclarationNameLoc DNLoc; +  ReadDeclarationNameLoc(F, DNLoc, NameInfo.getName(), Record, Idx); +  NameInfo.setInfo(DNLoc); +} + +void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info, +                                  const RecordData &Record, unsigned &Idx) { +  Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx); +  unsigned NumTPLists = Record[Idx++]; +  Info.NumTemplParamLists = NumTPLists; +  if (NumTPLists) { +    Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists]; +    for (unsigned i=0; i != NumTPLists; ++i) +      Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx); +  } +} + +TemplateName +ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,  +                            unsigned &Idx) { +  TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; +  switch (Kind) { +  case TemplateName::Template: +      return TemplateName(ReadDeclAs<TemplateDecl>(F, Record, Idx)); + +  case TemplateName::OverloadedTemplate: { +    unsigned size = Record[Idx++]; +    UnresolvedSet<8> Decls; +    while (size--) +      Decls.addDecl(ReadDeclAs<NamedDecl>(F, Record, Idx)); + +    return Context.getOverloadedTemplateName(Decls.begin(), Decls.end()); +  } + +  case TemplateName::QualifiedTemplate: { +    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx); +    bool hasTemplKeyword = Record[Idx++]; +    TemplateDecl *Template = ReadDeclAs<TemplateDecl>(F, Record, Idx); +    return Context.getQualifiedTemplateName(NNS, hasTemplKeyword, Template); +  } + +  case TemplateName::DependentTemplate: { +    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx); +    if (Record[Idx++])  // isIdentifier +      return Context.getDependentTemplateName(NNS, +                                               GetIdentifierInfo(F, Record,  +                                                                 Idx)); +    return Context.getDependentTemplateName(NNS, +                                         (OverloadedOperatorKind)Record[Idx++]); +  } + +  case TemplateName::SubstTemplateTemplateParm: { +    TemplateTemplateParmDecl *param +      = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx); +    if (!param) return TemplateName(); +    TemplateName replacement = ReadTemplateName(F, Record, Idx); +    return Context.getSubstTemplateTemplateParm(param, replacement); +  } +       +  case TemplateName::SubstTemplateTemplateParmPack: { +    TemplateTemplateParmDecl *Param  +      = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx); +    if (!Param) +      return TemplateName(); +     +    TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx); +    if (ArgPack.getKind() != TemplateArgument::Pack) +      return TemplateName(); +     +    return Context.getSubstTemplateTemplateParmPack(Param, ArgPack); +  } +  } + +  llvm_unreachable("Unhandled template name kind!"); +} + +TemplateArgument +ASTReader::ReadTemplateArgument(ModuleFile &F, +                                const RecordData &Record, unsigned &Idx) { +  TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++]; +  switch (Kind) { +  case TemplateArgument::Null: +    return TemplateArgument(); +  case TemplateArgument::Type: +    return TemplateArgument(readType(F, Record, Idx)); +  case TemplateArgument::Declaration: +    return TemplateArgument(ReadDecl(F, Record, Idx)); +  case TemplateArgument::Integral: { +    llvm::APSInt Value = ReadAPSInt(Record, Idx); +    QualType T = readType(F, Record, Idx); +    return TemplateArgument(Value, T); +  } +  case TemplateArgument::Template:  +    return TemplateArgument(ReadTemplateName(F, Record, Idx)); +  case TemplateArgument::TemplateExpansion: { +    TemplateName Name = ReadTemplateName(F, Record, Idx); +    llvm::Optional<unsigned> NumTemplateExpansions; +    if (unsigned NumExpansions = Record[Idx++]) +      NumTemplateExpansions = NumExpansions - 1; +    return TemplateArgument(Name, NumTemplateExpansions); +  } +  case TemplateArgument::Expression: +    return TemplateArgument(ReadExpr(F)); +  case TemplateArgument::Pack: { +    unsigned NumArgs = Record[Idx++]; +    TemplateArgument *Args = new (Context) TemplateArgument[NumArgs]; +    for (unsigned I = 0; I != NumArgs; ++I) +      Args[I] = ReadTemplateArgument(F, Record, Idx); +    return TemplateArgument(Args, NumArgs); +  } +  } + +  llvm_unreachable("Unhandled template argument kind!"); +} + +TemplateParameterList * +ASTReader::ReadTemplateParameterList(ModuleFile &F, +                                     const RecordData &Record, unsigned &Idx) { +  SourceLocation TemplateLoc = ReadSourceLocation(F, Record, Idx); +  SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Idx); +  SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Idx); + +  unsigned NumParams = Record[Idx++]; +  SmallVector<NamedDecl *, 16> Params; +  Params.reserve(NumParams); +  while (NumParams--) +    Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx)); + +  TemplateParameterList* TemplateParams = +    TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, +                                  Params.data(), Params.size(), RAngleLoc); +  return TemplateParams; +} + +void +ASTReader:: +ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs, +                         ModuleFile &F, const RecordData &Record, +                         unsigned &Idx) { +  unsigned NumTemplateArgs = Record[Idx++]; +  TemplArgs.reserve(NumTemplateArgs); +  while (NumTemplateArgs--) +    TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx)); +} + +/// \brief Read a UnresolvedSet structure. +void ASTReader::ReadUnresolvedSet(ModuleFile &F, UnresolvedSetImpl &Set, +                                  const RecordData &Record, unsigned &Idx) { +  unsigned NumDecls = Record[Idx++]; +  while (NumDecls--) { +    NamedDecl *D = ReadDeclAs<NamedDecl>(F, Record, Idx); +    AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; +    Set.addDecl(D, AS); +  } +} + +CXXBaseSpecifier +ASTReader::ReadCXXBaseSpecifier(ModuleFile &F, +                                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++]); +  bool inheritConstructors = static_cast<bool>(Record[Idx++]); +  TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx); +  SourceRange Range = ReadSourceRange(F, Record, Idx); +  SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx); +  CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo,  +                          EllipsisLoc); +  Result.setInheritConstructors(inheritConstructors); +  return Result; +} + +std::pair<CXXCtorInitializer **, unsigned> +ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, +                                   unsigned &Idx) { +  CXXCtorInitializer **CtorInitializers = 0; +  unsigned NumInitializers = Record[Idx++]; +  if (NumInitializers) { +    CtorInitializers +        = new (Context) CXXCtorInitializer*[NumInitializers]; +    for (unsigned i=0; i != NumInitializers; ++i) { +      TypeSourceInfo *TInfo = 0; +      bool IsBaseVirtual = false; +      FieldDecl *Member = 0; +      IndirectFieldDecl *IndirectMember = 0; + +      CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; +      switch (Type) { +      case CTOR_INITIALIZER_BASE: +        TInfo = GetTypeSourceInfo(F, Record, Idx); +        IsBaseVirtual = Record[Idx++]; +        break; +           +      case CTOR_INITIALIZER_DELEGATING: +        TInfo = GetTypeSourceInfo(F, Record, Idx); +        break; + +       case CTOR_INITIALIZER_MEMBER: +        Member = ReadDeclAs<FieldDecl>(F, Record, Idx); +        break; + +       case CTOR_INITIALIZER_INDIRECT_MEMBER: +        IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx); +        break; +      } + +      SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx); +      Expr *Init = ReadExpr(F); +      SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); +      SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); +      bool IsWritten = Record[Idx++]; +      unsigned SourceOrderOrNumArrayIndices; +      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(ReadDeclAs<VarDecl>(F, Record, Idx)); +      } + +      CXXCtorInitializer *BOMInit; +      if (Type == CTOR_INITIALIZER_BASE) { +        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual, +                                             LParenLoc, Init, RParenLoc, +                                             MemberOrEllipsisLoc); +      } else if (Type == CTOR_INITIALIZER_DELEGATING) { +        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc, +                                                   Init, RParenLoc); +      } else if (IsWritten) { +        if (Member) +          BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, +                                               LParenLoc, Init, RParenLoc); +        else  +          BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember, +                                               MemberOrEllipsisLoc, LParenLoc, +                                               Init, RParenLoc); +      } else { +        BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc, +                                             LParenLoc, Init, RParenLoc, +                                             Indices.data(), Indices.size()); +      } + +      if (IsWritten) +        BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices); +      CtorInitializers[i] = BOMInit; +    } +  } + +  return std::make_pair(CtorInitializers, NumInitializers); +} + +NestedNameSpecifier * +ASTReader::ReadNestedNameSpecifier(ModuleFile &F, +                                   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(F, Record, Idx); +      NNS = NestedNameSpecifier::Create(Context, Prev, II); +      break; +    } + +    case NestedNameSpecifier::Namespace: { +      NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx); +      NNS = NestedNameSpecifier::Create(Context, Prev, NS); +      break; +    } + +    case NestedNameSpecifier::NamespaceAlias: { +      NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx); +      NNS = NestedNameSpecifier::Create(Context, Prev, Alias); +      break; +    } + +    case NestedNameSpecifier::TypeSpec: +    case NestedNameSpecifier::TypeSpecWithTemplate: { +      const Type *T = readType(F, Record, Idx).getTypePtrOrNull(); +      if (!T) +        return 0; +       +      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; +} + +NestedNameSpecifierLoc +ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record,  +                                      unsigned &Idx) { +  unsigned N = Record[Idx++]; +  NestedNameSpecifierLocBuilder Builder; +  for (unsigned I = 0; I != N; ++I) { +    NestedNameSpecifier::SpecifierKind Kind +      = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; +    switch (Kind) { +    case NestedNameSpecifier::Identifier: { +      IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);       +      SourceRange Range = ReadSourceRange(F, Record, Idx); +      Builder.Extend(Context, II, Range.getBegin(), Range.getEnd()); +      break; +    } + +    case NestedNameSpecifier::Namespace: { +      NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx); +      SourceRange Range = ReadSourceRange(F, Record, Idx); +      Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd()); +      break; +    } + +    case NestedNameSpecifier::NamespaceAlias: { +      NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx); +      SourceRange Range = ReadSourceRange(F, Record, Idx); +      Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd()); +      break; +    } + +    case NestedNameSpecifier::TypeSpec: +    case NestedNameSpecifier::TypeSpecWithTemplate: { +      bool Template = Record[Idx++]; +      TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx); +      if (!T) +        return NestedNameSpecifierLoc(); +      SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); + +      // FIXME: 'template' keyword location not saved anywhere, so we fake it. +      Builder.Extend(Context,  +                     Template? T->getTypeLoc().getBeginLoc() : SourceLocation(), +                     T->getTypeLoc(), ColonColonLoc); +      break; +    } + +    case NestedNameSpecifier::Global: { +      SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); +      Builder.MakeGlobal(Context, ColonColonLoc); +      break; +    } +    } +  } +   +  return Builder.getWithLocInContext(Context); +} + +SourceRange +ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record, +                           unsigned &Idx) { +  SourceLocation beg = ReadSourceLocation(F, Record, Idx); +  SourceLocation end = ReadSourceLocation(F, Record, Idx); +  return SourceRange(beg, end); +} + +/// \brief Read an integral value +llvm::APInt ASTReader::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 ASTReader::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 ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) { +  return llvm::APFloat(ReadAPInt(Record, Idx)); +} + +// \brief Read a string +std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) { +  unsigned Len = Record[Idx++]; +  std::string Result(Record.data() + Idx, Record.data() + Idx + Len); +  Idx += Len; +  return Result; +} + +VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,  +                                         unsigned &Idx) { +  unsigned Major = Record[Idx++]; +  unsigned Minor = Record[Idx++]; +  unsigned Subminor = Record[Idx++]; +  if (Minor == 0) +    return VersionTuple(Major); +  if (Subminor == 0) +    return VersionTuple(Major, Minor - 1); +  return VersionTuple(Major, Minor - 1, Subminor - 1); +} + +CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F,  +                                          const RecordData &Record, +                                          unsigned &Idx) { +  CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx); +  return CXXTemporary::Create(Context, Decl); +} + +DiagnosticBuilder ASTReader::Diag(unsigned DiagID) { +  return Diag(SourceLocation(), DiagID); +} + +DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) { +  return Diags.Report(Loc, DiagID); +} + +/// \brief Retrieve the identifier table associated with the +/// preprocessor. +IdentifierTable &ASTReader::getIdentifierTable() { +  return PP.getIdentifierTable(); +} + +/// \brief Record that the given ID maps to the given switch-case +/// statement. +void ASTReader::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 *ASTReader::getSwitchCaseWithID(unsigned ID) { +  assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID"); +  return SwitchCaseStmts[ID]; +} + +void ASTReader::ClearSwitchCaseIDs() { +  SwitchCaseStmts.clear(); +} + +void ASTReader::finishPendingActions() { +  while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty()) { +    // 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(); +    } +   +    // Load pending declaration chains. +    for (unsigned I = 0; I != PendingDeclChains.size(); ++I) { +      loadPendingDeclChain(PendingDeclChains[I]); +      PendingDeclChainsKnown.erase(PendingDeclChains[I]); +    } +    PendingDeclChains.clear(); +  } +   +  // If we deserialized any C++ or Objective-C class definitions, any +  // Objective-C protocol definitions, or any redeclarable templates, make sure +  // that all redeclarations point to the definitions. Note that this can only  +  // happen now, after the redeclaration chains have been fully wired. +  for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(), +                                           DEnd = PendingDefinitions.end(); +       D != DEnd; ++D) { +    if (TagDecl *TD = dyn_cast<TagDecl>(*D)) { +      if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) { +        // Make sure that the TagType points at the definition. +        const_cast<TagType*>(TagT)->decl = TD; +      } +       +      if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) { +        for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(), +                                         REnd = RD->redecls_end(); +             R != REnd; ++R) +          cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData; +         +      } + +      continue; +    } +     +    if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) { +      // Make sure that the ObjCInterfaceType points at the definition. +      const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl)) +        ->Decl = ID; +       +      for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(), +                                           REnd = ID->redecls_end(); +           R != REnd; ++R) +        R->Data = ID->Data; +       +      continue; +    } +     +    if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) { +      for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(), +                                          REnd = PD->redecls_end(); +           R != REnd; ++R) +        R->Data = PD->Data; +       +      continue; +    } +     +    RedeclarableTemplateDecl *RTD +      = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl(); +    for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(), +                                                REnd = RTD->redecls_end(); +         R != REnd; ++R) +      R->Common = RTD->Common;     +  } +  PendingDefinitions.clear(); +} + +void ASTReader::FinishedDeserializing() { +  assert(NumCurrentElementsDeserializing && +         "FinishedDeserializing not paired with StartedDeserializing"); +  if (NumCurrentElementsDeserializing == 1) { +    // We decrease NumCurrentElementsDeserializing only after pending actions +    // are finished, to avoid recursively re-calling finishPendingActions(). +    finishPendingActions(); +  } +  --NumCurrentElementsDeserializing; + +  if (NumCurrentElementsDeserializing == 0 && +      Consumer && !PassingDeclsToConsumer) { +    // Guard variable to avoid recursively redoing the process of passing +    // decls to consumer. +    SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, +                                                     true); + +    while (!InterestingDecls.empty()) { +      // We are not in recursive loading, so it's safe to pass the "interesting" +      // decls to the consumer. +      Decl *D = InterestingDecls.front(); +      InterestingDecls.pop_front(); +      PassInterestingDeclToConsumer(D); +    } +  } +} + +ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, +                     StringRef isysroot, bool DisableValidation, +                     bool DisableStatCache, bool AllowASTWithCompilerErrors) +  : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), +    SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), +    Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context), +    Consumer(0), ModuleMgr(FileMgr.getFileSystemOptions()), +    RelocatablePCH(false), isysroot(isysroot), +    DisableValidation(DisableValidation), +    DisableStatCache(DisableStatCache), +    AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),  +    CurrentGeneration(0), 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), +    TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), +    PassingDeclsToConsumer(false), +    NumCXXBaseSpecifiersLoaded(0) +{ +  SourceMgr.setExternalSLocEntrySource(this); +} + +ASTReader::~ASTReader() { +  for (DeclContextVisibleUpdatesPending::iterator +           I = PendingVisibleUpdates.begin(), +           E = PendingVisibleUpdates.end(); +       I != E; ++I) { +    for (DeclContextVisibleUpdates::iterator J = I->second.begin(), +                                             F = I->second.end(); +         J != F; ++J) +      delete J->first; +  } +} diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp new file mode 100644 index 0000000..8dd53ee --- /dev/null +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -0,0 +1,2481 @@ +//===--- ASTReaderDecl.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 ASTReader::ReadDeclRecord method, which is the +// entrypoint for loading a decl. +// +//===----------------------------------------------------------------------===// + +#include "ASTCommon.h" +#include "ASTReaderInternals.h" +#include "clang/Serialization/ASTReader.h" +#include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaDiagnostic.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; +using namespace clang::serialization; + +//===----------------------------------------------------------------------===// +// Declaration deserialization +//===----------------------------------------------------------------------===// + +namespace clang { +  class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> { +    ASTReader &Reader; +    ModuleFile &F; +    llvm::BitstreamCursor &Cursor; +    const DeclID ThisDeclID; +    const unsigned RawLocation; +    typedef ASTReader::RecordData RecordData; +    const RecordData &Record; +    unsigned &Idx; +    TypeID TypeIDForTypeDecl; +     +    DeclID DeclContextIDForTemplateParmDecl; +    DeclID LexicalDeclContextIDForTemplateParmDecl; + +    uint64_t GetCurrentCursorOffset(); +     +    SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) { +      return Reader.ReadSourceLocation(F, R, I); +    } +     +    SourceRange ReadSourceRange(const RecordData &R, unsigned &I) { +      return Reader.ReadSourceRange(F, R, I); +    } +     +    TypeSourceInfo *GetTypeSourceInfo(const RecordData &R, unsigned &I) { +      return Reader.GetTypeSourceInfo(F, R, I); +    } +     +    serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) { +      return Reader.ReadDeclID(F, R, I); +    } +     +    Decl *ReadDecl(const RecordData &R, unsigned &I) { +      return Reader.ReadDecl(F, R, I); +    } + +    template<typename T> +    T *ReadDeclAs(const RecordData &R, unsigned &I) { +      return Reader.ReadDeclAs<T>(F, R, I); +    } + +    void ReadQualifierInfo(QualifierInfo &Info, +                           const RecordData &R, unsigned &I) { +      Reader.ReadQualifierInfo(F, Info, R, I); +    } +     +    void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name, +                                const RecordData &R, unsigned &I) { +      Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I); +    } +     +    void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo, +                                const RecordData &R, unsigned &I) { +      Reader.ReadDeclarationNameInfo(F, NameInfo, R, I); +    } + +    serialization::SubmoduleID readSubmoduleID(const RecordData &R,  +                                               unsigned &I) { +      if (I >= R.size()) +        return 0; +       +      return Reader.getGlobalSubmoduleID(F, R[I++]); +    } +     +    Module *readModule(const RecordData &R, unsigned &I) { +      return Reader.getSubmodule(readSubmoduleID(R, I)); +    } +     +    void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, +                               const RecordData &R, unsigned &I); + +    /// \brief RAII class used to capture the first ID within a redeclaration +    /// chain and to introduce it into the list of pending redeclaration chains +    /// on destruction. +    /// +    /// The caller can choose not to introduce this ID into the redeclaration +    /// chain by calling \c suppress(). +    class RedeclarableResult { +      ASTReader &Reader; +      GlobalDeclID FirstID; +      mutable bool Owning; +       +      RedeclarableResult &operator=(RedeclarableResult&); // DO NOT IMPLEMENT +       +    public: +      RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID) +        : Reader(Reader), FirstID(FirstID), Owning(true) { } + +      RedeclarableResult(const RedeclarableResult &Other) +        : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning)  +      {  +        Other.Owning = false; +      } + +      ~RedeclarableResult() { +        // FIXME: We want to suppress this when the declaration is local to +        // a function, since there's no reason to search other AST files +        // for redeclarations (they can't exist). However, this is hard to  +        // do locally because the declaration hasn't necessarily loaded its +        // declaration context yet. Also, local externs still have the function +        // as their (semantic) declaration context, which is wrong and would +        // break this optimize. +         +        if (FirstID && Owning && Reader.PendingDeclChainsKnown.insert(FirstID)) +          Reader.PendingDeclChains.push_back(FirstID); +      } +       +      /// \brief Retrieve the first ID. +      GlobalDeclID getFirstID() const { return FirstID; } +       +      /// \brief Do not introduce this declaration ID into the set of pending +      /// declaration chains. +      void suppress() { +        Owning = false; +      } +    }; +     +    /// \brief Class used to capture the result of searching for an existing +    /// declaration of a specific kind and name, along with the ability +    /// to update the place where this result was found (the declaration +    /// chain hanging off an identifier or the DeclContext we searched in) +    /// if requested. +    class FindExistingResult { +      ASTReader &Reader; +      NamedDecl *New; +      NamedDecl *Existing; +      mutable bool AddResult; +       +      FindExistingResult &operator=(FindExistingResult&); // DO NOT IMPLEMENT +       +    public: +      FindExistingResult(ASTReader &Reader) +        : Reader(Reader), New(0), Existing(0), AddResult(false) { } +       +      FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing) +        : Reader(Reader), New(New), Existing(Existing), AddResult(true) { } +       +      FindExistingResult(const FindExistingResult &Other) +        : Reader(Other.Reader), New(Other.New), Existing(Other.Existing),  +          AddResult(Other.AddResult) +      { +        Other.AddResult = false; +      } +       +      ~FindExistingResult(); +       +      /// \brief Suppress the addition of this result into the known set of +      /// names. +      void suppress() { AddResult = false; } +       +      operator NamedDecl*() const { return Existing; } +       +      template<typename T> +      operator T*() const { return dyn_cast_or_null<T>(Existing); } +    }; +     +    FindExistingResult findExisting(NamedDecl *D); +     +  public: +    ASTDeclReader(ASTReader &Reader, ModuleFile &F, +                  llvm::BitstreamCursor &Cursor, DeclID thisDeclID, +                  unsigned RawLocation, +                  const RecordData &Record, unsigned &Idx) +      : Reader(Reader), F(F), Cursor(Cursor), ThisDeclID(thisDeclID), +        RawLocation(RawLocation), Record(Record), Idx(Idx), +        TypeIDForTypeDecl(0) { } + +    static void attachPreviousDecl(Decl *D, Decl *previous); +    static void attachLatestDecl(Decl *D, Decl *latest); + +    void Visit(Decl *D); + +    void UpdateDecl(Decl *D, ModuleFile &ModuleFile, +                    const RecordData &Record); + +    static void setNextObjCCategory(ObjCCategoryDecl *Cat, +                                    ObjCCategoryDecl *Next) { +      Cat->NextClassCategory = Next; +    } + +    void VisitDecl(Decl *D); +    void VisitTranslationUnitDecl(TranslationUnitDecl *TU); +    void VisitNamedDecl(NamedDecl *ND); +    void VisitLabelDecl(LabelDecl *LD); +    void VisitNamespaceDecl(NamespaceDecl *D); +    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); +    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); +    void VisitTypeDecl(TypeDecl *TD); +    void VisitTypedefNameDecl(TypedefNameDecl *TD); +    void VisitTypedefDecl(TypedefDecl *TD); +    void VisitTypeAliasDecl(TypeAliasDecl *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 VisitClassScopeFunctionSpecializationDecl( +                                       ClassScopeFunctionSpecializationDecl *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 VisitIndirectFieldDecl(IndirectFieldDecl *FD); +    void VisitVarDecl(VarDecl *VD); +    void VisitImplicitParamDecl(ImplicitParamDecl *PD); +    void VisitParmVarDecl(ParmVarDecl *PD); +    void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); +    void VisitTemplateDecl(TemplateDecl *D); +    RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); +    void VisitClassTemplateDecl(ClassTemplateDecl *D); +    void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); +    void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); +    void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); +    void VisitUsingDecl(UsingDecl *D); +    void VisitUsingShadowDecl(UsingShadowDecl *D); +    void VisitLinkageSpecDecl(LinkageSpecDecl *D); +    void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); +    void VisitImportDecl(ImportDecl *D); +    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>  +    RedeclarableResult VisitRedeclarable(Redeclarable<T> *D); + +    template<typename T> +    void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl); +     +    // 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 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 ASTDeclReader::GetCurrentCursorOffset() { +  return F.DeclsCursor.GetCurrentBitNo() + F.GlobalBitOffset; +} + +void ASTDeclReader::Visit(Decl *D) { +  DeclVisitor<ASTDeclReader, void>::Visit(D); + +  if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { +    if (DD->DeclInfo) { +      DeclaratorDecl::ExtInfo *Info = +          DD->DeclInfo.get<DeclaratorDecl::ExtInfo *>(); +      Info->TInfo = +          GetTypeSourceInfo(Record, Idx); +    } +    else { +      DD->DeclInfo = GetTypeSourceInfo(Record, Idx); +    } +  } + +  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).getTypePtrOrNull()); +  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { +    // if we have a fully initialized TypeDecl, we can safely read its type now. +    ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); +  } 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()); +  } else if (D->isTemplateParameter()) { +    // If we have a fully initialized template parameter, we can now +    // set its DeclContext. +    DeclContext *SemaDC = cast<DeclContext>( +                              Reader.GetDecl(DeclContextIDForTemplateParmDecl)); +    DeclContext *LexicalDC = cast<DeclContext>( +                       Reader.GetDecl(LexicalDeclContextIDForTemplateParmDecl)); +    D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext()); +  } +} + +void ASTDeclReader::VisitDecl(Decl *D) { +  if (D->isTemplateParameter()) { +    // We don't want to deserialize the DeclContext of a template +    // parameter immediately, because the template parameter might be +    // used in the formulation of its DeclContext. Use the translation +    // unit DeclContext as a placeholder. +    DeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx); +    LexicalDeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx); +    D->setDeclContext(Reader.getContext().getTranslationUnitDecl());  +  } else { +    DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx); +    DeclContext *LexicalDC = ReadDeclAs<DeclContext>(Record, Idx); +    // Avoid calling setLexicalDeclContext() directly because it uses +    // Decl::getASTContext() internally which is unsafe during derialization. +    D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext()); +  } +  D->setLocation(Reader.ReadSourceLocation(F, RawLocation)); +  D->setInvalidDecl(Record[Idx++]); +  if (Record[Idx++]) { // hasAttrs +    AttrVec Attrs; +    Reader.ReadAttributes(F, Attrs, Record, Idx); +    // Avoid calling setAttrs() directly because it uses Decl::getASTContext() +    // internally which is unsafe during derialization. +    D->setAttrsImpl(Attrs, Reader.getContext()); +  } +  D->setImplicit(Record[Idx++]); +  D->setUsed(Record[Idx++]); +  D->setReferenced(Record[Idx++]); +  D->setTopLevelDeclInObjCContainer(Record[Idx++]); +  D->setAccess((AccessSpecifier)Record[Idx++]); +  D->FromASTFile = true; +  D->setModulePrivate(Record[Idx++]); +  D->Hidden = D->isModulePrivate(); +   +  // Determine whether this declaration is part of a (sub)module. If so, it +  // may not yet be visible. +  if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) { +    // Store the owning submodule ID in the declaration. +    D->setOwningModuleID(SubmoduleID); +     +    // Module-private declarations are never visible, so there is no work to do. +    if (!D->isModulePrivate()) { +      if (Module *Owner = Reader.getSubmodule(SubmoduleID)) { +        if (Owner->NameVisibility != Module::AllVisible) { +          // The owning module is not visible. Mark this declaration as hidden. +          D->Hidden = true; +           +          // Note that this declaration was hidden because its owning module is  +          // not yet visible. +          Reader.HiddenNamesMap[Owner].push_back(D); +        } +      } +    } +  } +} + +void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { +  llvm_unreachable("Translation units are not serialized"); +} + +void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) { +  VisitDecl(ND); +  ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx)); +} + +void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { +  VisitNamedDecl(TD); +  TD->setLocStart(ReadSourceLocation(Record, Idx)); +  // Delay type reading until after we have fully initialized the decl. +  TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); +} + +void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { +  RedeclarableResult Redecl = VisitRedeclarable(TD); +  VisitTypeDecl(TD); +   +  TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); +  mergeRedeclarable(TD, Redecl); +} + +void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { +  VisitTypedefNameDecl(TD); +} + +void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { +  VisitTypedefNameDecl(TD); +} + +void ASTDeclReader::VisitTagDecl(TagDecl *TD) { +  RedeclarableResult Redecl = VisitRedeclarable(TD); +  VisitTypeDecl(TD); +   +  TD->IdentifierNamespace = Record[Idx++]; +  TD->setTagKind((TagDecl::TagKind)Record[Idx++]); +  TD->setCompleteDefinition(Record[Idx++]); +  TD->setEmbeddedInDeclarator(Record[Idx++]); +  TD->setFreeStanding(Record[Idx++]); +  TD->setRBraceLoc(ReadSourceLocation(Record, Idx)); +   +  if (Record[Idx++]) { // hasExtInfo +    TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); +    ReadQualifierInfo(*Info, Record, Idx); +    TD->TypedefNameDeclOrQualifier = Info; +  } else +    TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx)); + +  mergeRedeclarable(TD, Redecl);   +} + +void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { +  VisitTagDecl(ED); +  if (TypeSourceInfo *TI = Reader.GetTypeSourceInfo(F, Record, Idx)) +    ED->setIntegerTypeSourceInfo(TI); +  else +    ED->setIntegerType(Reader.readType(F, Record, Idx)); +  ED->setPromotionType(Reader.readType(F, Record, Idx)); +  ED->setNumPositiveBits(Record[Idx++]); +  ED->setNumNegativeBits(Record[Idx++]); +  ED->IsScoped = Record[Idx++]; +  ED->IsScopedUsingClassTag = Record[Idx++]; +  ED->IsFixed = Record[Idx++]; + +  if (EnumDecl *InstED = ReadDeclAs<EnumDecl>(Record, Idx)) { +    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; +    SourceLocation POI = ReadSourceLocation(Record, Idx); +    ED->setInstantiationOfMemberEnum(Reader.getContext(), InstED, TSK); +    ED->getMemberSpecializationInfo()->setPointOfInstantiation(POI); +  } +} + +void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { +  VisitTagDecl(RD); +  RD->setHasFlexibleArrayMember(Record[Idx++]); +  RD->setAnonymousStructOrUnion(Record[Idx++]); +  RD->setHasObjectMember(Record[Idx++]); +} + +void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { +  VisitNamedDecl(VD); +  VD->setType(Reader.readType(F, Record, Idx)); +} + +void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { +  VisitValueDecl(ECD); +  if (Record[Idx++]) +    ECD->setInitExpr(Reader.ReadExpr(F)); +  ECD->setInitVal(Reader.ReadAPSInt(Record, Idx)); +} + +void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { +  VisitValueDecl(DD); +  DD->setInnerLocStart(ReadSourceLocation(Record, Idx)); +  if (Record[Idx++]) { // hasExtInfo +    DeclaratorDecl::ExtInfo *Info +        = new (Reader.getContext()) DeclaratorDecl::ExtInfo(); +    ReadQualifierInfo(*Info, Record, Idx); +    DD->DeclInfo = Info; +  } +} + +void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { +  RedeclarableResult Redecl = VisitRedeclarable(FD); +  VisitDeclaratorDecl(FD); + +  ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx); +  FD->IdentifierNamespace = Record[Idx++]; +   +  // FunctionDecl's body is handled last at ASTDeclReader::Visit, +  // after everything else is read. +   +  FD->SClass = (StorageClass)Record[Idx++]; +  FD->SClassAsWritten = (StorageClass)Record[Idx++]; +  FD->IsInline = Record[Idx++]; +  FD->IsInlineSpecified = Record[Idx++]; +  FD->IsVirtualAsWritten = Record[Idx++]; +  FD->IsPure = Record[Idx++]; +  FD->HasInheritedPrototype = Record[Idx++]; +  FD->HasWrittenPrototype = Record[Idx++]; +  FD->IsDeleted = Record[Idx++]; +  FD->IsTrivial = Record[Idx++]; +  FD->IsDefaulted = Record[Idx++]; +  FD->IsExplicitlyDefaulted = Record[Idx++]; +  FD->HasImplicitReturnZero = Record[Idx++]; +  FD->IsConstexpr = Record[Idx++]; +  FD->EndRangeLoc = ReadSourceLocation(Record, Idx); + +  switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { +  case FunctionDecl::TK_NonTemplate: +    mergeRedeclarable(FD, Redecl);       +    break; +  case FunctionDecl::TK_FunctionTemplate: +    FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record,  +                                                                      Idx)); +    break; +  case FunctionDecl::TK_MemberSpecialization: { +    FunctionDecl *InstFD = ReadDeclAs<FunctionDecl>(Record, Idx); +    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; +    SourceLocation POI = ReadSourceLocation(Record, Idx); +    FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); +    FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); +    break; +  } +  case FunctionDecl::TK_FunctionTemplateSpecialization: { +    FunctionTemplateDecl *Template = ReadDeclAs<FunctionTemplateDecl>(Record,  +                                                                      Idx); +    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; +     +    // Template arguments. +    SmallVector<TemplateArgument, 8> TemplArgs; +    Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); +     +    // Template args as written. +    SmallVector<TemplateArgumentLoc, 8> TemplArgLocs; +    SourceLocation LAngleLoc, RAngleLoc; +    bool HasTemplateArgumentsAsWritten = Record[Idx++]; +    if (HasTemplateArgumentsAsWritten) { +      unsigned NumTemplateArgLocs = Record[Idx++]; +      TemplArgLocs.reserve(NumTemplateArgLocs); +      for (unsigned i=0; i != NumTemplateArgLocs; ++i) +        TemplArgLocs.push_back( +            Reader.ReadTemplateArgumentLoc(F, Record, Idx)); +   +      LAngleLoc = ReadSourceLocation(Record, Idx); +      RAngleLoc = ReadSourceLocation(Record, Idx); +    } +     +    SourceLocation POI = ReadSourceLocation(Record, Idx); + +    ASTContext &C = Reader.getContext(); +    TemplateArgumentList *TemplArgList +      = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size()); +    TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); +    for (unsigned i=0, e = TemplArgLocs.size(); i != e; ++i) +      TemplArgsInfo.addArgument(TemplArgLocs[i]); +    FunctionTemplateSpecializationInfo *FTInfo +        = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK, +                                                     TemplArgList, +                             HasTemplateArgumentsAsWritten ? &TemplArgsInfo : 0, +                                                     POI); +    FD->TemplateOrSpecialization = FTInfo; + +    if (FD->isCanonicalDecl()) { // if canonical add to template's set. +      // The template that contains the specializations set. It's not safe to +      // use getCanonicalDecl on Template since it may still be initializing. +      FunctionTemplateDecl *CanonTemplate +        = ReadDeclAs<FunctionTemplateDecl>(Record, Idx); +      // Get the InsertPos by FindNodeOrInsertPos() instead of calling +      // InsertNode(FTInfo) directly to avoid the getASTContext() call in +      // FunctionTemplateSpecializationInfo's Profile(). +      // We avoid getASTContext because a decl in the parent hierarchy may +      // be initializing. +      llvm::FoldingSetNodeID ID; +      FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(), +                                                  TemplArgs.size(), C); +      void *InsertPos = 0; +      CanonTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); +      assert(InsertPos && "Another specialization already inserted!"); +      CanonTemplate->getSpecializations().InsertNode(FTInfo, InsertPos); +    } +    break; +  } +  case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { +    // Templates. +    UnresolvedSet<8> TemplDecls; +    unsigned NumTemplates = Record[Idx++]; +    while (NumTemplates--) +      TemplDecls.addDecl(ReadDeclAs<NamedDecl>(Record, Idx)); +     +    // Templates args. +    TemplateArgumentListInfo TemplArgs; +    unsigned NumArgs = Record[Idx++]; +    while (NumArgs--) +      TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(F, Record, Idx)); +    TemplArgs.setLAngleLoc(ReadSourceLocation(Record, Idx)); +    TemplArgs.setRAngleLoc(ReadSourceLocation(Record, Idx)); +     +    FD->setDependentTemplateSpecialization(Reader.getContext(), +                                           TemplDecls, TemplArgs); +    break; +  } +  } + +  // Read in the parameters. +  unsigned NumParams = Record[Idx++]; +  SmallVector<ParmVarDecl *, 16> Params; +  Params.reserve(NumParams); +  for (unsigned I = 0; I != NumParams; ++I) +    Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx)); +  FD->setParams(Reader.getContext(), Params); +} + +void ASTDeclReader::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(F)); +    MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>(Record, Idx)); +    MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>(Record, Idx)); +  } +  MD->setInstanceMethod(Record[Idx++]); +  MD->setVariadic(Record[Idx++]); +  MD->setSynthesized(Record[Idx++]); +  MD->setDefined(Record[Idx++]); + +  MD->IsRedeclaration = Record[Idx++]; +  MD->HasRedeclaration = Record[Idx++]; +  if (MD->HasRedeclaration) +    Reader.getContext().setObjCMethodRedeclaration(MD, +                                       ReadDeclAs<ObjCMethodDecl>(Record, Idx)); + +  MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); +  MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); +  MD->SetRelatedResultType(Record[Idx++]); +  MD->setResultType(Reader.readType(F, Record, Idx)); +  MD->setResultTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); +  MD->setEndLoc(ReadSourceLocation(Record, Idx)); +  unsigned NumParams = Record[Idx++]; +  SmallVector<ParmVarDecl *, 16> Params; +  Params.reserve(NumParams); +  for (unsigned I = 0; I != NumParams; ++I) +    Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx)); + +  MD->SelLocsKind = Record[Idx++]; +  unsigned NumStoredSelLocs = Record[Idx++]; +  SmallVector<SourceLocation, 16> SelLocs; +  SelLocs.reserve(NumStoredSelLocs); +  for (unsigned i = 0; i != NumStoredSelLocs; ++i) +    SelLocs.push_back(ReadSourceLocation(Record, Idx)); + +  MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs); +} + +void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { +  VisitNamedDecl(CD); +  CD->setAtStartLoc(ReadSourceLocation(Record, Idx)); +  CD->setAtEndRange(ReadSourceRange(Record, Idx)); +} + +void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { +  RedeclarableResult Redecl = VisitRedeclarable(ID); +  VisitObjCContainerDecl(ID); +  TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); +  mergeRedeclarable(ID, Redecl); +   +  if (Record[Idx++]) { +    // Read the definition. +    ID->allocateDefinitionData(); +     +    // Set the definition data of the canonical declaration, so other +    // redeclarations will see it. +    ID->getCanonicalDecl()->Data = ID->Data; +     +    ObjCInterfaceDecl::DefinitionData &Data = ID->data(); +     +    // Read the superclass. +    Data.SuperClass = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); +    Data.SuperClassLoc = ReadSourceLocation(Record, Idx); + +    Data.EndLoc = ReadSourceLocation(Record, Idx); +     +    // Read the directly referenced protocols and their SourceLocations. +    unsigned NumProtocols = Record[Idx++]; +    SmallVector<ObjCProtocolDecl *, 16> Protocols; +    Protocols.reserve(NumProtocols); +    for (unsigned I = 0; I != NumProtocols; ++I) +      Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); +    SmallVector<SourceLocation, 16> ProtoLocs; +    ProtoLocs.reserve(NumProtocols); +    for (unsigned I = 0; I != NumProtocols; ++I) +      ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); +    ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), +                        Reader.getContext()); +   +    // Read the transitive closure of protocols referenced by this class. +    NumProtocols = Record[Idx++]; +    Protocols.clear(); +    Protocols.reserve(NumProtocols); +    for (unsigned I = 0; I != NumProtocols; ++I) +      Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); +    ID->data().AllReferencedProtocols.set(Protocols.data(), NumProtocols, +                                          Reader.getContext()); +   +    // We will rebuild this list lazily. +    ID->setIvarList(0); +     +    // Note that we have deserialized a definition. +    Reader.PendingDefinitions.insert(ID); +     +    // Note that we've loaded this Objective-C class. +    Reader.ObjCClassesLoaded.push_back(ID); +  } else { +    ID->Data = ID->getCanonicalDecl()->Data; +  } +} + +void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { +  VisitFieldDecl(IVD); +  IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]); +  // This field will be built lazily. +  IVD->setNextIvar(0); +  bool synth = Record[Idx++]; +  IVD->setSynthesize(synth); +} + +void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { +  RedeclarableResult Redecl = VisitRedeclarable(PD); +  VisitObjCContainerDecl(PD); +  mergeRedeclarable(PD, Redecl); +   +  if (Record[Idx++]) { +    // Read the definition. +    PD->allocateDefinitionData(); +     +    // Set the definition data of the canonical declaration, so other +    // redeclarations will see it. +    PD->getCanonicalDecl()->Data = PD->Data; + +    unsigned NumProtoRefs = Record[Idx++]; +    SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; +    ProtoRefs.reserve(NumProtoRefs); +    for (unsigned I = 0; I != NumProtoRefs; ++I) +      ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); +    SmallVector<SourceLocation, 16> ProtoLocs; +    ProtoLocs.reserve(NumProtoRefs); +    for (unsigned I = 0; I != NumProtoRefs; ++I) +      ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); +    PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), +                        Reader.getContext()); +     +    // Note that we have deserialized a definition. +    Reader.PendingDefinitions.insert(PD); +  } else { +    PD->Data = PD->getCanonicalDecl()->Data; +  } +} + +void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { +  VisitFieldDecl(FD); +} + +void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { +  VisitObjCContainerDecl(CD); +  CD->setCategoryNameLoc(ReadSourceLocation(Record, Idx)); +  CD->setIvarLBraceLoc(ReadSourceLocation(Record, Idx)); +  CD->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); +   +  // Note that this category has been deserialized. We do this before +  // deserializing the interface declaration, so that it will consider this +  /// category. +  Reader.CategoriesDeserialized.insert(CD); + +  CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); +  unsigned NumProtoRefs = Record[Idx++]; +  SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; +  ProtoRefs.reserve(NumProtoRefs); +  for (unsigned I = 0; I != NumProtoRefs; ++I) +    ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); +  SmallVector<SourceLocation, 16> ProtoLocs; +  ProtoLocs.reserve(NumProtoRefs); +  for (unsigned I = 0; I != NumProtoRefs; ++I) +    ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); +  CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), +                      Reader.getContext()); +  CD->setHasSynthBitfield(Record[Idx++]); +} + +void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { +  VisitNamedDecl(CAD); +  CAD->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); +} + +void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { +  VisitNamedDecl(D); +  D->setAtLoc(ReadSourceLocation(Record, Idx)); +  D->setLParenLoc(ReadSourceLocation(Record, Idx)); +  D->setType(GetTypeSourceInfo(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(F,Record, Idx).getObjCSelector()); +  D->setSetterName(Reader.ReadDeclarationName(F,Record, Idx).getObjCSelector()); +  D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx)); +  D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx)); +  D->setPropertyIvarDecl(ReadDeclAs<ObjCIvarDecl>(Record, Idx)); +} + +void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { +  VisitObjCContainerDecl(D); +  D->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); +} + +void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { +  VisitObjCImplDecl(D); +  D->setIdentifier(Reader.GetIdentifierInfo(F, Record, Idx)); +  D->CategoryNameLoc = ReadSourceLocation(Record, Idx); +} + +void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { +  VisitObjCImplDecl(D); +  D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); +  D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx)); +  D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); +  llvm::tie(D->IvarInitializers, D->NumIvarInitializers) +      = Reader.ReadCXXCtorInitializers(F, Record, Idx); +  D->setHasSynthBitfield(Record[Idx++]); +} + + +void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { +  VisitDecl(D); +  D->setAtLoc(ReadSourceLocation(Record, Idx)); +  D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>(Record, Idx)); +  D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>(Record, Idx); +  D->IvarLoc = ReadSourceLocation(Record, Idx); +  D->setGetterCXXConstructor(Reader.ReadExpr(F)); +  D->setSetterCXXAssignment(Reader.ReadExpr(F)); +} + +void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { +  VisitDeclaratorDecl(FD); +  FD->setMutable(Record[Idx++]); +  int BitWidthOrInitializer = Record[Idx++]; +  if (BitWidthOrInitializer == 1) +    FD->setBitWidth(Reader.ReadExpr(F)); +  else if (BitWidthOrInitializer == 2) +    FD->setInClassInitializer(Reader.ReadExpr(F)); +  if (!FD->getDeclName()) { +    if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx)) +      Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); +  } +} + +void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { +  VisitValueDecl(FD); + +  FD->ChainingSize = Record[Idx++]; +  assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2"); +  FD->Chaining = new (Reader.getContext())NamedDecl*[FD->ChainingSize]; + +  for (unsigned I = 0; I != FD->ChainingSize; ++I) +    FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx); +} + +void ASTDeclReader::VisitVarDecl(VarDecl *VD) { +  RedeclarableResult Redecl = VisitRedeclarable(VD); +  VisitDeclaratorDecl(VD); +   +  VD->VarDeclBits.SClass = (StorageClass)Record[Idx++]; +  VD->VarDeclBits.SClassAsWritten = (StorageClass)Record[Idx++]; +  VD->VarDeclBits.ThreadSpecified = Record[Idx++]; +  VD->VarDeclBits.InitStyle = Record[Idx++]; +  VD->VarDeclBits.ExceptionVar = Record[Idx++]; +  VD->VarDeclBits.NRVOVariable = Record[Idx++]; +  VD->VarDeclBits.CXXForRangeDecl = Record[Idx++]; +  VD->VarDeclBits.ARCPseudoStrong = Record[Idx++]; + +  // Only true variables (not parameters or implicit parameters) can be merged. +  if (VD->getKind() == Decl::Var) +    mergeRedeclarable(VD, Redecl); +   +  if (uint64_t Val = Record[Idx++]) { +    VD->setInit(Reader.ReadExpr(F)); +    if (Val > 1) { +      EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); +      Eval->CheckedICE = true; +      Eval->IsICE = Val == 3; +    } +  } + +  if (Record[Idx++]) { // HasMemberSpecializationInfo. +    VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx); +    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; +    SourceLocation POI = ReadSourceLocation(Record, Idx); +    Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); +  } +} + +void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { +  VisitVarDecl(PD); +} + +void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { +  VisitVarDecl(PD); +  unsigned isObjCMethodParam = Record[Idx++]; +  unsigned scopeDepth = Record[Idx++]; +  unsigned scopeIndex = Record[Idx++]; +  unsigned declQualifier = Record[Idx++]; +  if (isObjCMethodParam) { +    assert(scopeDepth == 0); +    PD->setObjCMethodScopeInfo(scopeIndex); +    PD->ParmVarDeclBits.ScopeDepthOrObjCQuals = declQualifier; +  } else { +    PD->setScopeInfo(scopeDepth, scopeIndex); +  } +  PD->ParmVarDeclBits.IsKNRPromoted = Record[Idx++]; +  PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++]; +  if (Record[Idx++]) // hasUninstantiatedDefaultArg. +    PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F)); +} + +void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { +  VisitDecl(AD); +  AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(F))); +  AD->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { +  VisitDecl(BD); +  BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(F))); +  BD->setSignatureAsWritten(GetTypeSourceInfo(Record, Idx)); +  unsigned NumParams = Record[Idx++]; +  SmallVector<ParmVarDecl *, 16> Params; +  Params.reserve(NumParams); +  for (unsigned I = 0; I != NumParams; ++I) +    Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx)); +  BD->setParams(Params); + +  BD->setIsVariadic(Record[Idx++]); +  BD->setBlockMissingReturnType(Record[Idx++]); +  BD->setIsConversionFromLambda(Record[Idx++]); + +  bool capturesCXXThis = Record[Idx++]; +  unsigned numCaptures = Record[Idx++]; +  SmallVector<BlockDecl::Capture, 16> captures; +  captures.reserve(numCaptures); +  for (unsigned i = 0; i != numCaptures; ++i) { +    VarDecl *decl = ReadDeclAs<VarDecl>(Record, Idx); +    unsigned flags = Record[Idx++]; +    bool byRef = (flags & 1); +    bool nested = (flags & 2); +    Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : 0); + +    captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr)); +  } +  BD->setCaptures(Reader.getContext(), captures.begin(), +                  captures.end(), capturesCXXThis); +} + +void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { +  VisitDecl(D); +  D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]); +  D->setExternLoc(ReadSourceLocation(Record, Idx)); +  D->setRBraceLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTDeclReader::VisitLabelDecl(LabelDecl *D) { +  VisitNamedDecl(D); +  D->setLocStart(ReadSourceLocation(Record, Idx)); +} + + +void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { +  RedeclarableResult Redecl = VisitRedeclarable(D); +  VisitNamedDecl(D); +  D->setInline(Record[Idx++]); +  D->LocStart = ReadSourceLocation(Record, Idx); +  D->RBraceLoc = ReadSourceLocation(Record, Idx); +  mergeRedeclarable(D, Redecl); + +  if (Redecl.getFirstID() == ThisDeclID) { +    // Each module has its own anonymous namespace, which is disjoint from +    // any other module's anonymous namespaces, so don't attach the anonymous +    // namespace at all. +    NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx); +    if (F.Kind != MK_Module) +      D->setAnonymousNamespace(Anon); +  } else { +    // Link this namespace back to the first declaration, which has already +    // been deserialized. +    D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDeclaration()); +  } +} + +void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { +  VisitNamedDecl(D); +  D->NamespaceLoc = ReadSourceLocation(Record, Idx); +  D->IdentLoc = ReadSourceLocation(Record, Idx); +  D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +  D->Namespace = ReadDeclAs<NamedDecl>(Record, Idx); +} + +void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { +  VisitNamedDecl(D); +  D->setUsingLocation(ReadSourceLocation(Record, Idx)); +  D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +  ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); +  D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>(Record, Idx)); +  D->setTypeName(Record[Idx++]); +  if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx)) +    Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern); +} + +void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { +  VisitNamedDecl(D); +  D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx)); +  D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx); +  UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx); +  if (Pattern) +    Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern); +} + +void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { +  VisitNamedDecl(D); +  D->UsingLoc = ReadSourceLocation(Record, Idx); +  D->NamespaceLoc = ReadSourceLocation(Record, Idx); +  D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +  D->NominatedNamespace = ReadDeclAs<NamedDecl>(Record, Idx); +  D->CommonAncestor = ReadDeclAs<DeclContext>(Record, Idx); +} + +void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { +  VisitValueDecl(D); +  D->setUsingLoc(ReadSourceLocation(Record, Idx)); +  D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +  ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); +} + +void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( +                                               UnresolvedUsingTypenameDecl *D) { +  VisitTypeDecl(D); +  D->TypenameLocation = ReadSourceLocation(Record, Idx); +  D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +} + +void ASTDeclReader::ReadCXXDefinitionData( +                                   struct CXXRecordDecl::DefinitionData &Data, +                                   const RecordData &Record, unsigned &Idx) { +  // Note: the caller has deserialized the IsLambda bit already. +  Data.UserDeclaredConstructor = Record[Idx++]; +  Data.UserDeclaredCopyConstructor = Record[Idx++]; +  Data.UserDeclaredMoveConstructor = Record[Idx++]; +  Data.UserDeclaredCopyAssignment = Record[Idx++]; +  Data.UserDeclaredMoveAssignment = 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.IsStandardLayout = Record[Idx++]; +  Data.HasNoNonEmptyBases = Record[Idx++]; +  Data.HasPrivateFields = Record[Idx++]; +  Data.HasProtectedFields = Record[Idx++]; +  Data.HasPublicFields = Record[Idx++]; +  Data.HasMutableFields = Record[Idx++]; +  Data.HasOnlyCMembers = Record[Idx++]; +  Data.HasTrivialDefaultConstructor = Record[Idx++]; +  Data.HasConstexprNonCopyMoveConstructor = Record[Idx++]; +  Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++]; +  Data.DefaultedCopyConstructorIsConstexpr = Record[Idx++]; +  Data.DefaultedMoveConstructorIsConstexpr = Record[Idx++]; +  Data.HasConstexprDefaultConstructor = Record[Idx++]; +  Data.HasConstexprCopyConstructor = Record[Idx++]; +  Data.HasConstexprMoveConstructor = Record[Idx++]; +  Data.HasTrivialCopyConstructor = Record[Idx++]; +  Data.HasTrivialMoveConstructor = Record[Idx++]; +  Data.HasTrivialCopyAssignment = Record[Idx++]; +  Data.HasTrivialMoveAssignment = Record[Idx++]; +  Data.HasTrivialDestructor = Record[Idx++]; +  Data.HasIrrelevantDestructor = Record[Idx++]; +  Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++]; +  Data.ComputedVisibleConversions = Record[Idx++]; +  Data.UserProvidedDefaultConstructor = Record[Idx++]; +  Data.DeclaredDefaultConstructor = Record[Idx++]; +  Data.DeclaredCopyConstructor = Record[Idx++]; +  Data.DeclaredMoveConstructor = Record[Idx++]; +  Data.DeclaredCopyAssignment = Record[Idx++]; +  Data.DeclaredMoveAssignment = Record[Idx++]; +  Data.DeclaredDestructor = Record[Idx++]; +  Data.FailedImplicitMoveConstructor = Record[Idx++]; +  Data.FailedImplicitMoveAssignment = Record[Idx++]; + +  Data.NumBases = Record[Idx++]; +  if (Data.NumBases) +    Data.Bases = Reader.readCXXBaseSpecifiers(F, Record, Idx); +  Data.NumVBases = Record[Idx++]; +  if (Data.NumVBases) +    Data.VBases = Reader.readCXXBaseSpecifiers(F, Record, Idx); +   +  Reader.ReadUnresolvedSet(F, Data.Conversions, Record, Idx); +  Reader.ReadUnresolvedSet(F, Data.VisibleConversions, Record, Idx); +  assert(Data.Definition && "Data.Definition should be already set!"); +  Data.FirstFriend = ReadDeclAs<FriendDecl>(Record, Idx); +   +  if (Data.IsLambda) { +    typedef LambdaExpr::Capture Capture; +    CXXRecordDecl::LambdaDefinitionData &Lambda +      = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); +    Lambda.Dependent = Record[Idx++]; +    Lambda.NumCaptures = Record[Idx++]; +    Lambda.NumExplicitCaptures = Record[Idx++]; +    Lambda.ManglingNumber = Record[Idx++]; +    Lambda.ContextDecl = ReadDecl(Record, Idx); +    Lambda.Captures  +      = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures); +    Capture *ToCapture = Lambda.Captures; +    for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { +      SourceLocation Loc = ReadSourceLocation(Record, Idx); +      bool IsImplicit = Record[Idx++]; +      LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]); +      VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx); +      SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx); +      *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); +    } +  } +} + +void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { +  VisitRecordDecl(D); + +  ASTContext &C = Reader.getContext(); +  if (Record[Idx++]) { +    // Determine whether this is a lambda closure type, so that we can +    // allocate the appropriate DefinitionData structure. +    bool IsLambda = Record[Idx++]; +    if (IsLambda) +      D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, false); +    else +      D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); +     +    // Propagate the DefinitionData pointer to the canonical declaration, so +    // that all other deserialized declarations will see it. +    // FIXME: Complain if there already is a DefinitionData! +    D->getCanonicalDecl()->DefinitionData = D->DefinitionData; +     +    ReadCXXDefinitionData(*D->DefinitionData, Record, Idx); +     +    // Note that we have deserialized a definition. Any declarations  +    // deserialized before this one will be be given the DefinitionData pointer +    // at the end. +    Reader.PendingDefinitions.insert(D); +  } else { +    // Propagate DefinitionData pointer from the canonical declaration. +    D->DefinitionData = D->getCanonicalDecl()->DefinitionData;     +  } + +  enum CXXRecKind { +    CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization +  }; +  switch ((CXXRecKind)Record[Idx++]) { +  case CXXRecNotTemplate: +    break; +  case CXXRecTemplate: +    D->TemplateOrInstantiation = ReadDeclAs<ClassTemplateDecl>(Record, Idx); +    break; +  case CXXRecMemberSpecialization: { +    CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(Record, Idx); +    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; +    SourceLocation POI = ReadSourceLocation(Record, Idx); +    MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK); +    MSI->setPointOfInstantiation(POI); +    D->TemplateOrInstantiation = MSI; +    break; +  } +  } + +  // Load the key function to avoid deserializing every method so we can +  // compute it. +  if (D->IsCompleteDefinition) { +    if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx)) +      C.KeyFunctions[D] = Key; +  } +} + +void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { +  VisitFunctionDecl(D); +  unsigned NumOverridenMethods = Record[Idx++]; +  while (NumOverridenMethods--) { +    // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod, +    // MD may be initializing. +    if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx)) +      Reader.getContext().addOverriddenMethod(D, MD); +  } +} + +void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { +  VisitCXXMethodDecl(D); +   +  D->IsExplicitSpecified = Record[Idx++]; +  D->ImplicitlyDefined = Record[Idx++]; +  llvm::tie(D->CtorInitializers, D->NumCtorInitializers) +      = Reader.ReadCXXCtorInitializers(F, Record, Idx); +} + +void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { +  VisitCXXMethodDecl(D); + +  D->ImplicitlyDefined = Record[Idx++]; +  D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx); +} + +void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { +  VisitCXXMethodDecl(D); +  D->IsExplicitSpecified = Record[Idx++]; +} + +void ASTDeclReader::VisitImportDecl(ImportDecl *D) { +  VisitDecl(D); +  D->ImportedAndComplete.setPointer(readModule(Record, Idx)); +  D->ImportedAndComplete.setInt(Record[Idx++]); +  SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(D + 1); +  for (unsigned I = 0, N = Record.back(); I != N; ++I) +    StoredLocs[I] = ReadSourceLocation(Record, Idx); +  ++Idx; +} + +void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { +  VisitDecl(D); +  D->setColonLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { +  VisitDecl(D); +  if (Record[Idx++]) +    D->Friend = GetTypeSourceInfo(Record, Idx); +  else +    D->Friend = ReadDeclAs<NamedDecl>(Record, Idx); +  D->NextFriend = Record[Idx++]; +  D->UnsupportedFriend = (Record[Idx++] != 0); +  D->FriendLoc = ReadSourceLocation(Record, Idx); +} + +void ASTDeclReader::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(F, Record, Idx); +  if (Record[Idx++]) // HasFriendDecl +    D->Friend = ReadDeclAs<NamedDecl>(Record, Idx); +  else +    D->Friend = GetTypeSourceInfo(Record, Idx); +  D->FriendLoc = ReadSourceLocation(Record, Idx); +} + +void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { +  VisitNamedDecl(D); + +  NamedDecl *TemplatedDecl = ReadDeclAs<NamedDecl>(Record, Idx); +  TemplateParameterList* TemplateParams +      = Reader.ReadTemplateParameterList(F, Record, Idx);  +  D->init(TemplatedDecl, TemplateParams); +} + +ASTDeclReader::RedeclarableResult  +ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { +  RedeclarableResult Redecl = VisitRedeclarable(D); + +  // Make sure we've allocated the Common pointer first. We do this before +  // VisitTemplateDecl so that getCommonPtr() can be used during initialization. +  RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl(); +  if (!CanonD->Common) { +    CanonD->Common = CanonD->newCommon(Reader.getContext()); +    Reader.PendingDefinitions.insert(CanonD); +  } +  D->Common = CanonD->Common; + +  // If this is the first declaration of the template, fill in the information +  // for the 'common' pointer. +  if (ThisDeclID == Redecl.getFirstID()) { +    if (RedeclarableTemplateDecl *RTD +          = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) { +      assert(RTD->getKind() == D->getKind() && +             "InstantiatedFromMemberTemplate kind mismatch"); +      D->setInstantiatedFromMemberTemplate(RTD); +      if (Record[Idx++]) +        D->setMemberSpecialization(); +    } +  } +      +  VisitTemplateDecl(D); +  D->IdentifierNamespace = Record[Idx++]; +   +  return Redecl; +} + +void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { +  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + +  if (ThisDeclID == Redecl.getFirstID()) { +    // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of +    // the specializations. +    SmallVector<serialization::DeclID, 2> SpecIDs; +    SpecIDs.push_back(0); +     +    // Specializations. +    unsigned Size = Record[Idx++]; +    SpecIDs[0] += Size; +    for (unsigned I = 0; I != Size; ++I) +      SpecIDs.push_back(ReadDeclID(Record, Idx)); + +    // Partial specializations. +    Size = Record[Idx++]; +    SpecIDs[0] += Size; +    for (unsigned I = 0; I != Size; ++I) +      SpecIDs.push_back(ReadDeclID(Record, Idx)); + +    if (SpecIDs[0]) { +      typedef serialization::DeclID DeclID; +       +      ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr(); +      // FIXME: Append specializations! +      CommonPtr->LazySpecializations +        = new (Reader.getContext()) DeclID [SpecIDs.size()]; +      memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),  +             SpecIDs.size() * sizeof(DeclID)); +    } +     +    // InjectedClassNameType is computed. +  } +} + +void ASTDeclReader::VisitClassTemplateSpecializationDecl( +                                           ClassTemplateSpecializationDecl *D) { +  VisitCXXRecordDecl(D); +   +  ASTContext &C = Reader.getContext(); +  if (Decl *InstD = ReadDecl(Record, Idx)) { +    if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) { +      D->SpecializedTemplate = CTD; +    } else { +      SmallVector<TemplateArgument, 8> TemplArgs; +      Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); +      TemplateArgumentList *ArgList +        = TemplateArgumentList::CreateCopy(C, TemplArgs.data(),  +                                           TemplArgs.size()); +      ClassTemplateSpecializationDecl::SpecializedPartialSpecialization *PS +          = new (C) ClassTemplateSpecializationDecl:: +                                             SpecializedPartialSpecialization(); +      PS->PartialSpecialization +          = cast<ClassTemplatePartialSpecializationDecl>(InstD); +      PS->TemplateArgs = ArgList; +      D->SpecializedTemplate = PS; +    } +  } + +  // Explicit info. +  if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) { +    ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo +        = new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; +    ExplicitInfo->TypeAsWritten = TyInfo; +    ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx); +    ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx); +    D->ExplicitInfo = ExplicitInfo; +  } + +  SmallVector<TemplateArgument, 8> TemplArgs; +  Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); +  D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(),  +                                                     TemplArgs.size()); +  D->PointOfInstantiation = ReadSourceLocation(Record, Idx); +  D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++]; +   +  if (D->isCanonicalDecl()) { // It's kept in the folding set. +    ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(Record,Idx); +    if (ClassTemplatePartialSpecializationDecl *Partial +                       = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { +      CanonPattern->getCommonPtr()->PartialSpecializations.InsertNode(Partial); +    } else { +      CanonPattern->getCommonPtr()->Specializations.InsertNode(D); +    } +  } +} + +void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( +                                    ClassTemplatePartialSpecializationDecl *D) { +  VisitClassTemplateSpecializationDecl(D); + +  ASTContext &C = Reader.getContext(); +  D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); + +  unsigned NumArgs = Record[Idx++]; +  if (NumArgs) { +    D->NumArgsAsWritten = NumArgs; +    D->ArgsAsWritten = new (C) TemplateArgumentLoc[NumArgs]; +    for (unsigned i=0; i != NumArgs; ++i) +      D->ArgsAsWritten[i] = Reader.ReadTemplateArgumentLoc(F, Record, Idx); +  } + +  D->SequenceNumber = Record[Idx++]; + +  // These are read/set from/to the first declaration. +  if (D->getPreviousDecl() == 0) { +    D->InstantiatedFromMember.setPointer( +      ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx)); +    D->InstantiatedFromMember.setInt(Record[Idx++]); +  } +} + +void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl( +                                    ClassScopeFunctionSpecializationDecl *D) { +  VisitDecl(D); +  D->Specialization = ReadDeclAs<CXXMethodDecl>(Record, Idx); +} + +void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { +  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + +  if (ThisDeclID == Redecl.getFirstID()) { +    // This FunctionTemplateDecl owns a CommonPtr; read it. + +    // Read the function specialization declarations. +    // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled +    // when reading the specialized FunctionDecl. +    unsigned NumSpecs = Record[Idx++]; +    while (NumSpecs--) +      (void)ReadDecl(Record, Idx); +  } +} + +void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { +  VisitTypeDecl(D); + +  D->setDeclaredWithTypename(Record[Idx++]); + +  bool Inherited = Record[Idx++]; +  TypeSourceInfo *DefArg = GetTypeSourceInfo(Record, Idx); +  D->setDefaultArgument(DefArg, Inherited); +} + +void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { +  VisitDeclaratorDecl(D); +  // TemplateParmPosition. +  D->setDepth(Record[Idx++]); +  D->setPosition(Record[Idx++]); +  if (D->isExpandedParameterPack()) { +    void **Data = reinterpret_cast<void **>(D + 1); +    for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { +      Data[2*I] = Reader.readType(F, Record, Idx).getAsOpaquePtr(); +      Data[2*I + 1] = GetTypeSourceInfo(Record, Idx); +    } +  } else { +    // Rest of NonTypeTemplateParmDecl. +    D->ParameterPack = Record[Idx++]; +    if (Record[Idx++]) { +      Expr *DefArg = Reader.ReadExpr(F); +      bool Inherited = Record[Idx++]; +      D->setDefaultArgument(DefArg, Inherited); +   } +  } +} + +void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { +  VisitTemplateDecl(D); +  // TemplateParmPosition. +  D->setDepth(Record[Idx++]); +  D->setPosition(Record[Idx++]); +  // Rest of TemplateTemplateParmDecl. +  TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(F, Record, Idx); +  bool IsInherited = Record[Idx++]; +  D->setDefaultArgument(Arg, IsInherited); +  D->ParameterPack = Record[Idx++]; +} + +void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { +  VisitRedeclarableTemplateDecl(D); +} + +void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { +  VisitDecl(D); +  D->AssertExpr = Reader.ReadExpr(F); +  D->Message = cast<StringLiteral>(Reader.ReadExpr(F)); +  D->RParenLoc = ReadSourceLocation(Record, Idx); +} + +std::pair<uint64_t, uint64_t> +ASTDeclReader::VisitDeclContext(DeclContext *DC) { +  uint64_t LexicalOffset = Record[Idx++]; +  uint64_t VisibleOffset = Record[Idx++]; +  return std::make_pair(LexicalOffset, VisibleOffset); +} + +template <typename T> +ASTDeclReader::RedeclarableResult  +ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { +  DeclID FirstDeclID = ReadDeclID(Record, Idx); +   +  // 0 indicates that this declaration was the only declaration of its entity, +  // and is used for space optimization. +  if (FirstDeclID == 0) +    FirstDeclID = ThisDeclID; +   +  T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID)); +  if (FirstDecl != D) { +    // We delay loading of the redeclaration chain to avoid deeply nested calls. +    // We temporarily set the first (canonical) declaration as the previous one +    // which is the one that matters and mark the real previous DeclID to be +    // loaded & attached later on. +    D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl); +  }     +   +  // Note that this declaration has been deserialized. +  Reader.RedeclsDeserialized.insert(static_cast<T *>(D)); +                              +  // The result structure takes care to note that we need to load the  +  // other declaration chains for this ID. +  return RedeclarableResult(Reader, FirstDeclID); +} + +/// \brief Attempts to merge the given declaration (D) with another declaration +/// of the same entity. +template<typename T> +void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,  +                                      RedeclarableResult &Redecl) { +  // If modules are not available, there is no reason to perform this merge. +  if (!Reader.getContext().getLangOpts().Modules) +    return; +   +  if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) { +    if (T *Existing = ExistingRes) { +      T *ExistingCanon = Existing->getCanonicalDecl(); +      T *DCanon = static_cast<T*>(D)->getCanonicalDecl(); +      if (ExistingCanon != DCanon) { +        // Have our redeclaration link point back at the canonical declaration +        // of the existing declaration, so that this declaration has the  +        // appropriate canonical declaration. +        D->RedeclLink  +          = typename Redeclarable<T>::PreviousDeclLink(ExistingCanon); +         +        // When we merge a namespace, update its pointer to the first namespace. +        if (NamespaceDecl *Namespace +              = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) { +          Namespace->AnonOrFirstNamespaceAndInline.setPointer( +            static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon))); +        } +         +        // Don't introduce DCanon into the set of pending declaration chains. +        Redecl.suppress(); +         +        // Introduce ExistingCanon into the set of pending declaration chains, +        // if in fact it came from a module file. +        if (ExistingCanon->isFromASTFile()) { +          GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID(); +          assert(ExistingCanonID && "Unrecorded canonical declaration ID?"); +          if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID)) +            Reader.PendingDeclChains.push_back(ExistingCanonID); +        } +         +        // If this declaration was the canonical declaration, make a note of  +        // that. We accept the linear algorithm here because the number of  +        // unique canonical declarations of an entity should always be tiny. +        if (DCanon == static_cast<T*>(D)) { +          SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon]; +          if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID()) +                == Merged.end()) +            Merged.push_back(Redecl.getFirstID()); +           +          // If ExistingCanon did not come from a module file, introduce the +          // first declaration that *does* come from a module file to the  +          // set of pending declaration chains, so that we merge this  +          // declaration. +          if (!ExistingCanon->isFromASTFile() && +              Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID())) +            Reader.PendingDeclChains.push_back(Merged[0]); +        } +      } +    } +  } +} + +//===----------------------------------------------------------------------===// +// Attribute Reading +//===----------------------------------------------------------------------===// + +/// \brief Reads attributes from the current stream position. +void ASTReader::ReadAttributes(ModuleFile &F, AttrVec &Attrs, +                               const RecordData &Record, unsigned &Idx) { +  for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) { +    Attr *New = 0; +    attr::Kind Kind = (attr::Kind)Record[Idx++]; +    SourceRange Range = ReadSourceRange(F, Record, Idx); + +#include "clang/Serialization/AttrPCHRead.inc" + +    assert(New && "Unable to decode attribute?"); +    Attrs.push_back(New); +  } +} + +//===----------------------------------------------------------------------===// +// ASTReader 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 ASTReader::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) { +  // An ObjCMethodDecl is never considered as "interesting" because its +  // implementation container always is. + +  if (isa<FileScopeAsmDecl>(D) ||  +      isa<ObjCProtocolDecl>(D) ||  +      isa<ObjCImplDecl>(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->doesThisDeclarationHaveABody(); +   +  return false; +} + +/// \brief Get the correct cursor and offset for loading a declaration. +ASTReader::RecordLocation +ASTReader::DeclCursorForID(DeclID ID, unsigned &RawLocation) { +  // See if there's an override. +  DeclReplacementMap::iterator It = ReplacedDecls.find(ID); +  if (It != ReplacedDecls.end()) { +    RawLocation = It->second.RawLoc; +    return RecordLocation(It->second.Mod, It->second.Offset); +  } + +  GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); +  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); +  ModuleFile *M = I->second; +  const DeclOffset & +    DOffs =  M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS]; +  RawLocation = DOffs.Loc; +  return RecordLocation(M, DOffs.BitOffset); +} + +ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) { +  ContinuousRangeMap<uint64_t, ModuleFile*, 4>::iterator I +    = GlobalBitOffsetsMap.find(GlobalOffset); + +  assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map"); +  return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset); +} + +uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) { +  return LocalOffset + M.GlobalBitOffset; +} + +/// \brief Determine whether the two declarations refer to the same entity. +static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { +  assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); +   +  if (X == Y) +    return true; +   +  // Must be in the same context. +  if (!X->getDeclContext()->getRedeclContext()->Equals( +         Y->getDeclContext()->getRedeclContext())) +    return false; + +  // Two typedefs refer to the same entity if they have the same underlying +  // type. +  if (TypedefNameDecl *TypedefX = dyn_cast<TypedefNameDecl>(X)) +    if (TypedefNameDecl *TypedefY = dyn_cast<TypedefNameDecl>(Y)) +      return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(), +                                            TypedefY->getUnderlyingType()); +   +  // Must have the same kind. +  if (X->getKind() != Y->getKind()) +    return false; +     +  // Objective-C classes and protocols with the same name always match. +  if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) +    return true; +   +  // Compatible tags match. +  if (TagDecl *TagX = dyn_cast<TagDecl>(X)) { +    TagDecl *TagY = cast<TagDecl>(Y); +    return (TagX->getTagKind() == TagY->getTagKind()) || +      ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class) && +       (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class)); +  } +   +  // Functions with the same type and linkage match. +  // FIXME: This needs to cope with function templates, merging of  +  //prototyped/non-prototyped functions, etc. +  if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) { +    FunctionDecl *FuncY = cast<FunctionDecl>(Y); +    return (FuncX->getLinkage() == FuncY->getLinkage()) && +      FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType()); +  } +   +  // Variables with the same type and linkage match. +  if (VarDecl *VarX = dyn_cast<VarDecl>(X)) { +    VarDecl *VarY = cast<VarDecl>(Y); +    return (VarX->getLinkage() == VarY->getLinkage()) && +      VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType()); +  } +   +  // Namespaces with the same name and inlinedness match. +  if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) { +    NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y); +    return NamespaceX->isInline() == NamespaceY->isInline(); +  } +       +  // FIXME: Many other cases to implement. +  return false; +} + +ASTDeclReader::FindExistingResult::~FindExistingResult() { +  if (!AddResult || Existing) +    return; +   +  DeclContext *DC = New->getDeclContext()->getRedeclContext(); +  if (DC->isTranslationUnit() && Reader.SemaObj) { +    Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName()); +  } else if (DC->isNamespace()) { +    DC->addDecl(New); +  } +} + +ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { +  DeclarationName Name = D->getDeclName(); +  if (!Name) { +    // Don't bother trying to find unnamed declarations. +    FindExistingResult Result(Reader, D, /*Existing=*/0); +    Result.suppress(); +    return Result; +  } +   +  DeclContext *DC = D->getDeclContext()->getRedeclContext(); +  if (!DC->isFileContext()) +    return FindExistingResult(Reader); +   +  if (DC->isTranslationUnit() && Reader.SemaObj) { +    IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver; +    for (IdentifierResolver::iterator I = IdResolver.begin(Name),  +                                   IEnd = IdResolver.end(); +         I != IEnd; ++I) { +      if (isSameEntity(*I, D)) +        return FindExistingResult(Reader, D, *I); +    } +  } + +  if (DC->isNamespace()) { +    for (DeclContext::lookup_result R = DC->lookup(Name); +         R.first != R.second; ++R.first) { +      if (isSameEntity(*R.first, D)) +        return FindExistingResult(Reader, D, *R.first); +    } +  } +   +  return FindExistingResult(Reader, D, /*Existing=*/0); +} + +void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { +  assert(D && previous); +  if (TagDecl *TD = dyn_cast<TagDecl>(D)) { +    TD->RedeclLink.setPointer(cast<TagDecl>(previous)); +  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +    FD->RedeclLink.setPointer(cast<FunctionDecl>(previous)); +  } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { +    VD->RedeclLink.setPointer(cast<VarDecl>(previous)); +  } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { +    TD->RedeclLink.setPointer(cast<TypedefNameDecl>(previous)); +  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { +    ID->RedeclLink.setPointer(cast<ObjCInterfaceDecl>(previous)); +  } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { +    PD->RedeclLink.setPointer(cast<ObjCProtocolDecl>(previous)); +  } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) { +    ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous)); +  } else { +    RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); +    TD->RedeclLink.setPointer(cast<RedeclarableTemplateDecl>(previous)); +  } +} + +void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { +  assert(D && Latest); +  if (TagDecl *TD = dyn_cast<TagDecl>(D)) { +    TD->RedeclLink +      = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest)); +  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +    FD->RedeclLink  +      = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest)); +  } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { +    VD->RedeclLink +      = Redeclarable<VarDecl>::LatestDeclLink(cast<VarDecl>(Latest)); +  } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { +    TD->RedeclLink +      = Redeclarable<TypedefNameDecl>::LatestDeclLink( +                                                cast<TypedefNameDecl>(Latest)); +  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { +    ID->RedeclLink +      = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink( +                                              cast<ObjCInterfaceDecl>(Latest)); +  } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { +    PD->RedeclLink +      = Redeclarable<ObjCProtocolDecl>::LatestDeclLink( +                                                cast<ObjCProtocolDecl>(Latest)); +  } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) { +    ND->RedeclLink +      = Redeclarable<NamespaceDecl>::LatestDeclLink( +                                                   cast<NamespaceDecl>(Latest)); +  } else { +    RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); +    TD->RedeclLink +      = Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink( +                                        cast<RedeclarableTemplateDecl>(Latest)); +  } +} + +ASTReader::MergedDeclsMap::iterator +ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) { +  // If we don't have any stored merged declarations, just look in the +  // merged declarations set. +  StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID); +  if (StoredPos == StoredMergedDecls.end()) +    return MergedDecls.find(Canon); + +  // Append the stored merged declarations to the merged declarations set. +  MergedDeclsMap::iterator Pos = MergedDecls.find(Canon); +  if (Pos == MergedDecls.end()) +    Pos = MergedDecls.insert(std::make_pair(Canon,  +                                            SmallVector<DeclID, 2>())).first; +  Pos->second.append(StoredPos->second.begin(), StoredPos->second.end()); +  StoredMergedDecls.erase(StoredPos); +   +  // Sort and uniquify the set of merged declarations. +  llvm::array_pod_sort(Pos->second.begin(), Pos->second.end()); +  Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()), +                    Pos->second.end()); +  return Pos; +} + +void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) { +  Decl *previous = GetDecl(ID); +  ASTDeclReader::attachPreviousDecl(D, previous); +} + +/// \brief Read the declaration at the given offset from the AST file. +Decl *ASTReader::ReadDeclRecord(DeclID ID) { +  unsigned Index = ID - NUM_PREDEF_DECL_IDS; +  unsigned RawLocation = 0; +  RecordLocation Loc = DeclCursorForID(ID, RawLocation); +  llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; +  // 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.Offset); +  RecordData Record; +  unsigned Code = DeclsCursor.ReadCode(); +  unsigned Idx = 0; +  ASTDeclReader Reader(*this, *Loc.F, DeclsCursor, ID, RawLocation, Record,Idx); + +  Decl *D = 0; +  switch ((DeclCode)DeclsCursor.ReadRecord(Code, Record)) { +  case DECL_CONTEXT_LEXICAL: +  case DECL_CONTEXT_VISIBLE: +    llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord"); +  case DECL_TYPEDEF: +    D = TypedefDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_TYPEALIAS: +    D = TypeAliasDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_ENUM: +    D = EnumDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_RECORD: +    D = RecordDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_ENUM_CONSTANT: +    D = EnumConstantDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_FUNCTION: +    D = FunctionDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_LINKAGE_SPEC: +    D = LinkageSpecDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_LABEL: +    D = LabelDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_NAMESPACE: +    D = NamespaceDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_NAMESPACE_ALIAS: +    D = NamespaceAliasDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_USING: +    D = UsingDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_USING_SHADOW: +    D = UsingShadowDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_USING_DIRECTIVE: +    D = UsingDirectiveDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_UNRESOLVED_USING_VALUE: +    D = UnresolvedUsingValueDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_UNRESOLVED_USING_TYPENAME: +    D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CXX_RECORD: +    D = CXXRecordDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CXX_METHOD: +    D = CXXMethodDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CXX_CONSTRUCTOR: +    D = CXXConstructorDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CXX_DESTRUCTOR: +    D = CXXDestructorDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CXX_CONVERSION: +    D = CXXConversionDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_ACCESS_SPEC: +    D = AccessSpecDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_FRIEND: +    D = FriendDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_FRIEND_TEMPLATE: +    D = FriendTemplateDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CLASS_TEMPLATE: +    D = ClassTemplateDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CLASS_TEMPLATE_SPECIALIZATION: +    D = ClassTemplateSpecializationDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: +    D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION: +    D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_FUNCTION_TEMPLATE: +    D = FunctionTemplateDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_TEMPLATE_TYPE_PARM: +    D = TemplateTypeParmDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_NON_TYPE_TEMPLATE_PARM: +    D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: +    D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, Record[Idx++]); +    break; +  case DECL_TEMPLATE_TEMPLATE_PARM: +    D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_TYPE_ALIAS_TEMPLATE: +    D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_STATIC_ASSERT: +    D = StaticAssertDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_METHOD: +    D = ObjCMethodDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_INTERFACE: +    D = ObjCInterfaceDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_IVAR: +    D = ObjCIvarDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_PROTOCOL: +    D = ObjCProtocolDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_AT_DEFS_FIELD: +    D = ObjCAtDefsFieldDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_CATEGORY: +    D = ObjCCategoryDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_CATEGORY_IMPL: +    D = ObjCCategoryImplDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_IMPLEMENTATION: +    D = ObjCImplementationDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_COMPATIBLE_ALIAS: +    D = ObjCCompatibleAliasDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_PROPERTY: +    D = ObjCPropertyDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_OBJC_PROPERTY_IMPL: +    D = ObjCPropertyImplDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_FIELD: +    D = FieldDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_INDIRECTFIELD: +    D = IndirectFieldDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_VAR: +    D = VarDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_IMPLICIT_PARAM: +    D = ImplicitParamDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_PARM_VAR: +    D = ParmVarDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_FILE_SCOPE_ASM: +    D = FileScopeAsmDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_BLOCK: +    D = BlockDecl::CreateDeserialized(Context, ID); +    break; +  case DECL_CXX_BASE_SPECIFIERS: +    Error("attempt to read a C++ base-specifier record as a declaration"); +    return 0; +  case DECL_IMPORT: +    // Note: last entry of the ImportDecl record is the number of stored source  +    // locations. +    D = ImportDecl::CreateDeserialized(Context, ID, Record.back()); +    break; +  } + +  assert(D && "Unknown declaration reading AST file"); +  LoadedDecl(Index, D); +  // Set the DeclContext before doing any deserialization, to make sure internal +  // calls to Decl::getASTContext() by Decl's methods will find the +  // TranslationUnitDecl without crashing. +  D->setDeclContext(Context.getTranslationUnitDecl()); +  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) { +      if (Offsets.first != 0) +        DC->setHasExternalLexicalStorage(true); +      if (Offsets.second != 0) +        DC->setHasExternalVisibleStorage(true); +      if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets,  +                                 Loc.F->DeclContextInfos[DC])) +        return 0; +    } + +    // Now add the pending visible updates for this decl context, if it has any. +    DeclContextVisibleUpdatesPending::iterator I = +        PendingVisibleUpdates.find(ID); +    if (I != PendingVisibleUpdates.end()) { +      // There are updates. This means the context has external visible +      // storage, even if the original stored version didn't. +      DC->setHasExternalVisibleStorage(true); +      DeclContextVisibleUpdates &U = I->second; +      for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end(); +           UI != UE; ++UI) { +        DeclContextInfo &Info = UI->second->DeclContextInfos[DC]; +        delete Info.NameLookupTableData; +        Info.NameLookupTableData = UI->first; +      } +      PendingVisibleUpdates.erase(I); +    } +  } +  assert(Idx == Record.size()); + +  // Load any relevant update records. +  loadDeclUpdateRecords(ID, D); + +  // Load the categories after recursive loading is finished. +  if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) +    if (Class->isThisDeclarationADefinition()) +      loadObjCCategories(ID, Class); +   +  // 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; +} + +void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { +  // The declaration may have been modified by files later in the chain. +  // If this is the case, read the record containing the updates from each file +  // and pass it to ASTDeclReader to make the modifications. +  DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); +  if (UpdI != DeclUpdateOffsets.end()) { +    FileOffsetsTy &UpdateOffsets = UpdI->second; +    for (FileOffsetsTy::iterator +         I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { +      ModuleFile *F = I->first; +      uint64_t Offset = I->second; +      llvm::BitstreamCursor &Cursor = F->DeclsCursor; +      SavedStreamPosition SavedPosition(Cursor); +      Cursor.JumpToBit(Offset); +      RecordData Record; +      unsigned Code = Cursor.ReadCode(); +      unsigned RecCode = Cursor.ReadRecord(Code, Record); +      (void)RecCode; +      assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); +       +      unsigned Idx = 0; +      ASTDeclReader Reader(*this, *F, Cursor, ID, 0, Record, Idx); +      Reader.UpdateDecl(D, *F, Record); +    } +  } +} + +namespace { +  struct CompareLocalRedeclarationsInfoToID { +    bool operator()(const LocalRedeclarationsInfo &X, DeclID Y) { +      return X.FirstID < Y; +    } + +    bool operator()(DeclID X, const LocalRedeclarationsInfo &Y) { +      return X < Y.FirstID; +    } + +    bool operator()(const LocalRedeclarationsInfo &X,  +                    const LocalRedeclarationsInfo &Y) { +      return X.FirstID < Y.FirstID; +    } +    bool operator()(DeclID X, DeclID Y) { +      return X < Y; +    } +  }; +   +  /// \brief Module visitor class that finds all of the redeclarations of a  +  ///  +  class RedeclChainVisitor { +    ASTReader &Reader; +    SmallVectorImpl<DeclID> &SearchDecls; +    llvm::SmallPtrSet<Decl *, 16> &Deserialized; +    GlobalDeclID CanonID; +    llvm::SmallVector<Decl *, 4> Chain; +     +  public: +    RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls, +                       llvm::SmallPtrSet<Decl *, 16> &Deserialized, +                       GlobalDeclID CanonID) +      : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized), +        CanonID(CanonID) {  +      for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) +        addToChain(Reader.GetDecl(SearchDecls[I])); +    } +     +    static bool visit(ModuleFile &M, bool Preorder, void *UserData) { +      if (Preorder) +        return false; +       +      return static_cast<RedeclChainVisitor *>(UserData)->visit(M); +    } +     +    void addToChain(Decl *D) { +      if (!D) +        return; +       +      if (Deserialized.count(D)) { +        Deserialized.erase(D); +        Chain.push_back(D); +      } +    } +     +    void searchForID(ModuleFile &M, GlobalDeclID GlobalID) { +      // Map global ID of the first declaration down to the local ID +      // used in this module file. +      DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID); +      if (!ID) +        return; +       +      // Perform a binary search to find the local redeclarations for this +      // declaration (if any). +      const LocalRedeclarationsInfo *Result +        = std::lower_bound(M.RedeclarationsMap, +                           M.RedeclarationsMap + M.LocalNumRedeclarationsInMap,  +                           ID, CompareLocalRedeclarationsInfoToID()); +      if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap || +          Result->FirstID != ID) { +        // If we have a previously-canonical singleton declaration that was  +        // merged into another redeclaration chain, create a trivial chain +        // for this single declaration so that it will get wired into the  +        // complete redeclaration chain. +        if (GlobalID != CanonID &&  +            GlobalID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID &&  +            GlobalID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls) { +          addToChain(Reader.GetDecl(GlobalID)); +        } +         +        return; +      } +       +      // Dig out all of the redeclarations. +      unsigned Offset = Result->Offset; +      unsigned N = M.RedeclarationChains[Offset]; +      M.RedeclarationChains[Offset++] = 0; // Don't try to deserialize again +      for (unsigned I = 0; I != N; ++I) +        addToChain(Reader.GetLocalDecl(M, M.RedeclarationChains[Offset++])); +    } +     +    bool visit(ModuleFile &M) { +      // Visit each of the declarations. +      for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) +        searchForID(M, SearchDecls[I]); +      return false; +    } +     +    ArrayRef<Decl *> getChain() const { +      return Chain; +    } +  }; +} + +void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) { +  Decl *D = GetDecl(ID);   +  Decl *CanonDecl = D->getCanonicalDecl(); +   +  // Determine the set of declaration IDs we'll be searching for. +  llvm::SmallVector<DeclID, 1> SearchDecls; +  GlobalDeclID CanonID = 0; +  if (D == CanonDecl) { +    SearchDecls.push_back(ID); // Always first. +    CanonID = ID; +  } +  MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID); +  if (MergedPos != MergedDecls.end()) +    SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end());   +   +  // Build up the list of redeclarations. +  RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID); +  ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visit, &Visitor); +   +  // Retrieve the chains. +  ArrayRef<Decl *> Chain = Visitor.getChain(); +  if (Chain.empty()) +    return; +     +  // Hook up the chains. +  Decl *MostRecent = CanonDecl->getMostRecentDecl(); +  for (unsigned I = 0, N = Chain.size(); I != N; ++I) { +    if (Chain[I] == CanonDecl) +      continue; +     +    ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent); +    MostRecent = Chain[I]; +  } +   +  ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);   +} + +namespace { +  struct CompareObjCCategoriesInfo { +    bool operator()(const ObjCCategoriesInfo &X, DeclID Y) { +      return X.DefinitionID < Y; +    } +     +    bool operator()(DeclID X, const ObjCCategoriesInfo &Y) { +      return X < Y.DefinitionID; +    } +     +    bool operator()(const ObjCCategoriesInfo &X,  +                    const ObjCCategoriesInfo &Y) { +      return X.DefinitionID < Y.DefinitionID; +    } +    bool operator()(DeclID X, DeclID Y) { +      return X < Y; +    } +  }; + +  /// \brief Given an ObjC interface, goes through the modules and links to the +  /// interface all the categories for it. +  class ObjCCategoriesVisitor { +    ASTReader &Reader; +    serialization::GlobalDeclID InterfaceID; +    ObjCInterfaceDecl *Interface; +    llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized; +    unsigned PreviousGeneration; +    ObjCCategoryDecl *Tail; +    llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; +     +    void add(ObjCCategoryDecl *Cat) { +      // Only process each category once. +      if (!Deserialized.count(Cat)) +        return; +      Deserialized.erase(Cat); +       +      // Check for duplicate categories. +      if (Cat->getDeclName()) { +        ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()]; +        if (Existing &&  +            Reader.getOwningModuleFile(Existing)  +                                          != Reader.getOwningModuleFile(Cat)) { +          // FIXME: We should not warn for duplicates in diamond: +          // +          //   MT     // +          //  /  \    // +          // ML  MR   // +          //  \  /    // +          //   MB     // +          // +          // If there are duplicates in ML/MR, there will be warning when  +          // creating MB *and* when importing MB. We should not warn when  +          // importing. +          Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) +            << Interface->getDeclName() << Cat->getDeclName(); +          Reader.Diag(Existing->getLocation(), diag::note_previous_definition); +        } else if (!Existing) { +          // Record this category. +          Existing = Cat; +        } +      } +       +      // Add this category to the end of the chain. +      if (Tail) +        ASTDeclReader::setNextObjCCategory(Tail, Cat); +      else +        Interface->setCategoryList(Cat); +      Tail = Cat; +    } +     +  public: +    ObjCCategoriesVisitor(ASTReader &Reader, +                          serialization::GlobalDeclID InterfaceID, +                          ObjCInterfaceDecl *Interface, +                        llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized, +                          unsigned PreviousGeneration) +      : Reader(Reader), InterfaceID(InterfaceID), Interface(Interface), +        Deserialized(Deserialized), PreviousGeneration(PreviousGeneration), +        Tail(0)  +    { +      // Populate the name -> category map with the set of known categories. +      for (ObjCCategoryDecl *Cat = Interface->getCategoryList(); Cat; +           Cat = Cat->getNextClassCategory()) { +        if (Cat->getDeclName()) +          NameCategoryMap[Cat->getDeclName()] = Cat; +         +        // Keep track of the tail of the category list. +        Tail = Cat; +      } +    } + +    static bool visit(ModuleFile &M, void *UserData) { +      return static_cast<ObjCCategoriesVisitor *>(UserData)->visit(M); +    } + +    bool visit(ModuleFile &M) { +      // If we've loaded all of the category information we care about from +      // this module file, we're done. +      if (M.Generation <= PreviousGeneration) +        return true; +       +      // Map global ID of the definition down to the local ID used in this  +      // module file. If there is no such mapping, we'll find nothing here +      // (or in any module it imports). +      DeclID LocalID = Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID); +      if (!LocalID) +        return true; + +      // Perform a binary search to find the local redeclarations for this +      // declaration (if any). +      const ObjCCategoriesInfo *Result +        = std::lower_bound(M.ObjCCategoriesMap, +                           M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,  +                           LocalID, CompareObjCCategoriesInfo()); +      if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap || +          Result->DefinitionID != LocalID) { +        // We didn't find anything. If the class definition is in this module +        // file, then the module files it depends on cannot have any categories, +        // so suppress further lookup. +        return Reader.isDeclIDFromModule(InterfaceID, M); +      } +       +      // We found something. Dig out all of the categories. +      unsigned Offset = Result->Offset; +      unsigned N = M.ObjCCategories[Offset]; +      M.ObjCCategories[Offset++] = 0; // Don't try to deserialize again +      for (unsigned I = 0; I != N; ++I) +        add(cast_or_null<ObjCCategoryDecl>( +              Reader.GetLocalDecl(M, M.ObjCCategories[Offset++]))); +      return true; +    } +  }; +} + +void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID, +                                   ObjCInterfaceDecl *D, +                                   unsigned PreviousGeneration) { +  ObjCCategoriesVisitor Visitor(*this, ID, D, CategoriesDeserialized, +                                PreviousGeneration); +  ModuleMgr.visit(ObjCCategoriesVisitor::visit, &Visitor); +} + +void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, +                               const RecordData &Record) { +  unsigned Idx = 0; +  while (Idx < Record.size()) { +    switch ((DeclUpdateKind)Record[Idx++]) { +    case UPD_CXX_ADDED_IMPLICIT_MEMBER: +      cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(ModuleFile, Record, Idx)); +      break; + +    case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: +      // It will be added to the template's specializations set when loaded. +      (void)Reader.ReadDecl(ModuleFile, Record, Idx); +      break; + +    case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { +      NamespaceDecl *Anon +        = Reader.ReadDeclAs<NamespaceDecl>(ModuleFile, Record, Idx); +       +      // Each module has its own anonymous namespace, which is disjoint from +      // any other module's anonymous namespaces, so don't attach the anonymous +      // namespace at all. +      if (ModuleFile.Kind != MK_Module) { +        if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D)) +          TU->setAnonymousNamespace(Anon); +        else +          cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon); +      } +      break; +    } + +    case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: +      cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation( +          Reader.ReadSourceLocation(ModuleFile, Record, Idx)); +      break; +    } +  } +} diff --git a/clang/lib/Serialization/ASTReaderInternals.h b/clang/lib/Serialization/ASTReaderInternals.h new file mode 100644 index 0000000..e5159e9 --- /dev/null +++ b/clang/lib/Serialization/ASTReaderInternals.h @@ -0,0 +1,242 @@ +//===--- ASTReaderInternals.h - AST Reader Internals ------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//  This file provides internal definitions used in the AST reader. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H +#define LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H + +#include "clang/Basic/OnDiskHashTable.h" +#include "clang/AST/DeclarationName.h" +#include "llvm/Support/Endian.h" +#include <utility> +#include <sys/stat.h> + +namespace clang { + +class ASTReader; +class HeaderSearch; +struct HeaderFileInfo; +   +namespace serialization { + +class ModuleFile; + +namespace reader { + +/// \brief Class that performs name lookup into a DeclContext stored +/// in an AST file. +class ASTDeclContextNameLookupTrait { +  ASTReader &Reader; +  ModuleFile &F; +   +public: +  /// \brief Pair of begin/end iterators for DeclIDs. +  /// +  /// Note that these declaration IDs are local to the module that contains this +  /// particular lookup t +  typedef llvm::support::ulittle32_t LE32DeclID; +  typedef std::pair<LE32DeclID *, LE32DeclID *> data_type; + +  /// \brief Special internal key for declaration names. +  /// The hash table creates keys for comparison; we do not create +  /// a DeclarationName for the internal key to avoid deserializing types. +  struct DeclNameKey { +    DeclarationName::NameKind Kind; +    uint64_t Data; +    DeclNameKey() : Kind((DeclarationName::NameKind)0), Data(0) { } +  }; + +  typedef DeclarationName external_key_type; +  typedef DeclNameKey internal_key_type; + +  explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F) +    : Reader(Reader), F(F) { } + +  static bool EqualKey(const internal_key_type& a, +                       const internal_key_type& b) { +    return a.Kind == b.Kind && a.Data == b.Data; +  } + +  unsigned ComputeHash(const DeclNameKey &Key) const; +  internal_key_type GetInternalKey(const external_key_type& Name) const; + +  static std::pair<unsigned, unsigned> +  ReadKeyDataLength(const unsigned char*& d); + +  internal_key_type ReadKey(const unsigned char* d, unsigned); + +  data_type ReadData(internal_key_type, const unsigned char* d, +                     unsigned DataLen); +}; + +/// \brief Class that performs lookup for an identifier stored in an AST file. +class ASTIdentifierLookupTrait { +  ASTReader &Reader; +  ModuleFile &F; +   +  // 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 AST 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; +   +  ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F, +                           IdentifierInfo *II = 0) +    : Reader(Reader), F(F), 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); +   +  // This hopefully will just get inlined and removed by the optimizer. +  static const internal_key_type& +  GetInternalKey(const external_key_type& x) { return x; } +   +  // This hopefully will just get inlined and removed by the optimizer. +  static const external_key_type& +  GetExternalKey(const internal_key_type& x) { return x; } +  +  static std::pair<unsigned, unsigned> +  ReadKeyDataLength(const unsigned char*& d); + +  static std::pair<const char*, unsigned> +  ReadKey(const unsigned char* d, unsigned n); +   +  IdentifierInfo *ReadData(const internal_key_type& k, +                           const unsigned char* d, +                           unsigned DataLen); +   +  ASTReader &getReader() const { return Reader; } +   +}; +   +/// \brief The on-disk hash table used to contain information about +/// all of the identifiers in the program. +typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait> +  ASTIdentifierLookupTable; + +/// \brief Class that performs lookup for a selector's entries in the global +/// method pool stored in an AST file. +class ASTSelectorLookupTrait { +  ASTReader &Reader; +  ModuleFile &F; +   +public: +  struct data_type { +    SelectorID ID; +    llvm::SmallVector<ObjCMethodDecl *, 2> Instance; +    llvm::SmallVector<ObjCMethodDecl *, 2> Factory; +  }; +   +  typedef Selector external_key_type; +  typedef external_key_type internal_key_type; +   +  ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F)  +    : Reader(Reader), F(F) { } +   +  static bool EqualKey(const internal_key_type& a, +                       const internal_key_type& b) { +    return a == b; +  } +   +  static unsigned ComputeHash(Selector Sel); +   +  static const internal_key_type& +  GetInternalKey(const external_key_type& x) { return x; } +   +  static std::pair<unsigned, unsigned> +  ReadKeyDataLength(const unsigned char*& d); +   +  internal_key_type ReadKey(const unsigned char* d, unsigned); +  data_type ReadData(Selector, const unsigned char* d, unsigned DataLen); +}; +   +/// \brief The on-disk hash table used for the global method pool. +typedef OnDiskChainedHashTable<ASTSelectorLookupTrait> +  ASTSelectorLookupTable; +   +/// \brief Trait class used to search the on-disk hash table containing all of +/// the header search information. +/// +/// The on-disk hash table contains a mapping from each header path to  +/// information about that header (how many times it has been included, its +/// controlling macro, etc.). Note that we actually hash based on the  +/// filename, and support "deep" comparisons of file names based on current +/// inode numbers, so that the search can cope with non-normalized path names +/// and symlinks. +class HeaderFileInfoTrait { +  ASTReader &Reader; +  ModuleFile &M; +  HeaderSearch *HS; +  const char *FrameworkStrings; +  const char *SearchPath; +  struct stat SearchPathStatBuf; +  llvm::Optional<int> SearchPathStatResult; +   +  int StatSimpleCache(const char *Path, struct stat *StatBuf) { +    if (Path == SearchPath) { +      if (!SearchPathStatResult) +        SearchPathStatResult = stat(Path, &SearchPathStatBuf); +       +      *StatBuf = SearchPathStatBuf; +      return *SearchPathStatResult; +    } +     +    return stat(Path, StatBuf); +  } +   +public: +  typedef const char *external_key_type; +  typedef const char *internal_key_type; +   +  typedef HeaderFileInfo data_type; +   +  HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS, +                      const char *FrameworkStrings, +                      const char *SearchPath = 0)  +  : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings),  +    SearchPath(SearchPath) { } +   +  static unsigned ComputeHash(const char *path); +  static internal_key_type GetInternalKey(const char *path); +  bool EqualKey(internal_key_type a, internal_key_type b); +   +  static std::pair<unsigned, unsigned> +  ReadKeyDataLength(const unsigned char*& d); +   +  static internal_key_type ReadKey(const unsigned char *d, unsigned) { +    return (const char *)d; +  } +   +  data_type ReadData(const internal_key_type, const unsigned char *d, +                     unsigned DataLen); +}; + +/// \brief The on-disk hash table used for known header files. +typedef OnDiskChainedHashTable<HeaderFileInfoTrait> +  HeaderFileInfoLookupTable; +   +} // end namespace clang::serialization::reader +} // end namespace clang::serialization +} // end namespace clang + + +#endif diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp new file mode 100644 index 0000000..007ecee --- /dev/null +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -0,0 +1,2227 @@ +//===--- ASTReaderStmt.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 +// ASTReader::ReadStmt method. +// +//===----------------------------------------------------------------------===// + +#include "clang/Serialization/ASTReader.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/StmtVisitor.h" +#include "llvm/ADT/SmallString.h" +using namespace clang; +using namespace clang::serialization; + +namespace clang { + +  class ASTStmtReader : public StmtVisitor<ASTStmtReader> { +    typedef ASTReader::RecordData RecordData; +     +    ASTReader &Reader; +    ModuleFile &F; +    llvm::BitstreamCursor &DeclsCursor; +    const ASTReader::RecordData &Record; +    unsigned &Idx; + +    SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) { +      return Reader.ReadSourceLocation(F, R, I); +    } +     +    SourceRange ReadSourceRange(const RecordData &R, unsigned &I) { +      return Reader.ReadSourceRange(F, R, I); +    } +     +    TypeSourceInfo *GetTypeSourceInfo(const RecordData &R, unsigned &I) { +      return Reader.GetTypeSourceInfo(F, R, I); +    } +     +    serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) { +      return Reader.ReadDeclID(F, R, I); +    } +     +    Decl *ReadDecl(const RecordData &R, unsigned &I) { +      return Reader.ReadDecl(F, R, I); +    } +     +    template<typename T> +    T *ReadDeclAs(const RecordData &R, unsigned &I) { +      return Reader.ReadDeclAs<T>(F, R, I); +    } + +    void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name, +                                const ASTReader::RecordData &R, unsigned &I) { +      Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I); +    } +     +    void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo, +                                const ASTReader::RecordData &R, unsigned &I) { +      Reader.ReadDeclarationNameInfo(F, NameInfo, R, I); +    } + +  public: +    ASTStmtReader(ASTReader &Reader, ModuleFile &F, +                  llvm::BitstreamCursor &Cursor, +                  const ASTReader::RecordData &Record, unsigned &Idx) +      : Reader(Reader), F(F), 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 + 7; + +    /// \brief Read and initialize a ExplicitTemplateArgumentList structure. +    void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, +                                   unsigned NumTemplateArgs); +    /// \brief Read and initialize a ExplicitTemplateArgumentList structure. +    void ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList, +                                          unsigned NumTemplateArgs); + +    void VisitStmt(Stmt *S); +#define STMT(Type, Base) \ +    void Visit##Type(Type *); +#include "clang/AST/StmtNodes.inc" +  }; +} + +void ASTStmtReader:: +ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, +                          unsigned NumTemplateArgs) { +  SourceLocation TemplateKWLoc = ReadSourceLocation(Record, Idx); +  TemplateArgumentListInfo ArgInfo; +  ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx)); +  ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx)); +  for (unsigned i = 0; i != NumTemplateArgs; ++i) +    ArgInfo.addArgument( +        Reader.ReadTemplateArgumentLoc(F, Record, Idx)); +  Args.initializeFrom(TemplateKWLoc, ArgInfo); +} + +void ASTStmtReader::VisitStmt(Stmt *S) { +  assert(Idx == NumStmtFields && "Incorrect statement field count"); +} + +void ASTStmtReader::VisitNullStmt(NullStmt *S) { +  VisitStmt(S); +  S->setSemiLoc(ReadSourceLocation(Record, Idx)); +  S->HasLeadingEmptyMacro = Record[Idx++]; +} + +void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) { +  VisitStmt(S); +  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(ReadSourceLocation(Record, Idx)); +  S->setRBracLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitSwitchCase(SwitchCase *S) { +  VisitStmt(S); +  Reader.RecordSwitchCaseID(S, Record[Idx++]); +} + +void ASTStmtReader::VisitCaseStmt(CaseStmt *S) { +  VisitSwitchCase(S); +  S->setLHS(Reader.ReadSubExpr()); +  S->setRHS(Reader.ReadSubExpr()); +  S->setSubStmt(Reader.ReadSubStmt()); +  S->setCaseLoc(ReadSourceLocation(Record, Idx)); +  S->setEllipsisLoc(ReadSourceLocation(Record, Idx)); +  S->setColonLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) { +  VisitSwitchCase(S); +  S->setSubStmt(Reader.ReadSubStmt()); +  S->setDefaultLoc(ReadSourceLocation(Record, Idx)); +  S->setColonLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitLabelStmt(LabelStmt *S) { +  VisitStmt(S); +  LabelDecl *LD = ReadDeclAs<LabelDecl>(Record, Idx); +  LD->setStmt(S); +  S->setDecl(LD); +  S->setSubStmt(Reader.ReadSubStmt()); +  S->setIdentLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) { +  VisitStmt(S); +  AttrVec Attrs; +  Reader.ReadAttributes(F, Attrs, Record, Idx); +  S->Attrs = Attrs; +  S->SubStmt = Reader.ReadSubStmt(); +  S->AttrLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitIfStmt(IfStmt *S) { +  VisitStmt(S); +  S->setConditionVariable(Reader.getContext(), +                          ReadDeclAs<VarDecl>(Record, Idx)); +  S->setCond(Reader.ReadSubExpr()); +  S->setThen(Reader.ReadSubStmt()); +  S->setElse(Reader.ReadSubStmt()); +  S->setIfLoc(ReadSourceLocation(Record, Idx)); +  S->setElseLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) { +  VisitStmt(S); +  S->setConditionVariable(Reader.getContext(), +                          ReadDeclAs<VarDecl>(Record, Idx)); +  S->setCond(Reader.ReadSubExpr()); +  S->setBody(Reader.ReadSubStmt()); +  S->setSwitchLoc(ReadSourceLocation(Record, Idx)); +  if (Record[Idx++]) +    S->setAllEnumCasesCovered(); + +  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); + +    PrevSC = SC; +  } +} + +void ASTStmtReader::VisitWhileStmt(WhileStmt *S) { +  VisitStmt(S); +  S->setConditionVariable(Reader.getContext(), +                          ReadDeclAs<VarDecl>(Record, Idx)); + +  S->setCond(Reader.ReadSubExpr()); +  S->setBody(Reader.ReadSubStmt()); +  S->setWhileLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitDoStmt(DoStmt *S) { +  VisitStmt(S); +  S->setCond(Reader.ReadSubExpr()); +  S->setBody(Reader.ReadSubStmt()); +  S->setDoLoc(ReadSourceLocation(Record, Idx)); +  S->setWhileLoc(ReadSourceLocation(Record, Idx)); +  S->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitForStmt(ForStmt *S) { +  VisitStmt(S); +  S->setInit(Reader.ReadSubStmt()); +  S->setCond(Reader.ReadSubExpr()); +  S->setConditionVariable(Reader.getContext(), +                          ReadDeclAs<VarDecl>(Record, Idx)); +  S->setInc(Reader.ReadSubExpr()); +  S->setBody(Reader.ReadSubStmt()); +  S->setForLoc(ReadSourceLocation(Record, Idx)); +  S->setLParenLoc(ReadSourceLocation(Record, Idx)); +  S->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitGotoStmt(GotoStmt *S) { +  VisitStmt(S); +  S->setLabel(ReadDeclAs<LabelDecl>(Record, Idx)); +  S->setGotoLoc(ReadSourceLocation(Record, Idx)); +  S->setLabelLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) { +  VisitStmt(S); +  S->setGotoLoc(ReadSourceLocation(Record, Idx)); +  S->setStarLoc(ReadSourceLocation(Record, Idx)); +  S->setTarget(Reader.ReadSubExpr()); +} + +void ASTStmtReader::VisitContinueStmt(ContinueStmt *S) { +  VisitStmt(S); +  S->setContinueLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitBreakStmt(BreakStmt *S) { +  VisitStmt(S); +  S->setBreakLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitReturnStmt(ReturnStmt *S) { +  VisitStmt(S); +  S->setRetValue(Reader.ReadSubExpr()); +  S->setReturnLoc(ReadSourceLocation(Record, Idx)); +  S->setNRVOCandidate(ReadDeclAs<VarDecl>(Record, Idx)); +} + +void ASTStmtReader::VisitDeclStmt(DeclStmt *S) { +  VisitStmt(S); +  S->setStartLoc(ReadSourceLocation(Record, Idx)); +  S->setEndLoc(ReadSourceLocation(Record, Idx)); + +  if (Idx + 1 == Record.size()) { +    // Single declaration +    S->setDeclGroup(DeclGroupRef(ReadDecl(Record, Idx))); +  } else { +    SmallVector<Decl *, 16> Decls; +    Decls.reserve(Record.size() - Idx);     +    for (unsigned N = Record.size(); Idx != N; ) +      Decls.push_back(ReadDecl(Record, Idx)); +    S->setDeclGroup(DeclGroupRef(DeclGroup::Create(Reader.getContext(), +                                                   Decls.data(), +                                                   Decls.size()))); +  } +} + +void ASTStmtReader::VisitAsmStmt(AsmStmt *S) { +  VisitStmt(S); +  unsigned NumOutputs = Record[Idx++]; +  unsigned NumInputs = Record[Idx++]; +  unsigned NumClobbers = Record[Idx++]; +  S->setAsmLoc(ReadSourceLocation(Record, Idx)); +  S->setRParenLoc(ReadSourceLocation(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 +  SmallVector<IdentifierInfo *, 16> Names; +  SmallVector<StringLiteral*, 16> Constraints; +  SmallVector<Stmt*, 16> Exprs; +  for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) { +    Names.push_back(Reader.GetIdentifierInfo(F, Record, Idx)); +    Constraints.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); +    Exprs.push_back(Reader.ReadSubStmt()); +  } + +  // Constraints +  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 ASTStmtReader::VisitExpr(Expr *E) { +  VisitStmt(E); +  E->setType(Reader.readType(F, Record, Idx)); +  E->setTypeDependent(Record[Idx++]); +  E->setValueDependent(Record[Idx++]); +  E->setInstantiationDependent(Record[Idx++]); +  E->ExprBits.ContainsUnexpandedParameterPack = Record[Idx++]; +  E->setValueKind(static_cast<ExprValueKind>(Record[Idx++])); +  E->setObjectKind(static_cast<ExprObjectKind>(Record[Idx++])); +  assert(Idx == NumExprFields && "Incorrect expression field count"); +} + +void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { +  VisitExpr(E); +  E->setLocation(ReadSourceLocation(Record, Idx)); +  E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]); +} + +void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { +  VisitExpr(E); + +  E->DeclRefExprBits.HasQualifier = Record[Idx++]; +  E->DeclRefExprBits.HasFoundDecl = Record[Idx++]; +  E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record[Idx++]; +  E->DeclRefExprBits.HadMultipleCandidates = Record[Idx++]; +  E->DeclRefExprBits.RefersToEnclosingLocal = Record[Idx++]; +  unsigned NumTemplateArgs = 0; +  if (E->hasTemplateKWAndArgsInfo()) +    NumTemplateArgs = Record[Idx++]; + +  if (E->hasQualifier()) +    E->getInternalQualifierLoc() +      = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); + +  if (E->hasFoundDecl()) +    E->getInternalFoundDecl() = ReadDeclAs<NamedDecl>(Record, Idx); + +  if (E->hasTemplateKWAndArgsInfo()) +    ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(), +                              NumTemplateArgs); + +  E->setDecl(ReadDeclAs<ValueDecl>(Record, Idx)); +  E->setLocation(ReadSourceLocation(Record, Idx)); +  ReadDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName(), Record, Idx); +} + +void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) { +  VisitExpr(E); +  E->setLocation(ReadSourceLocation(Record, Idx)); +  E->setValue(Reader.getContext(), Reader.ReadAPInt(Record, Idx)); +} + +void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) { +  VisitExpr(E); +  E->setValue(Reader.getContext(), Reader.ReadAPFloat(Record, Idx)); +  E->setExact(Record[Idx++]); +  E->setLocation(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) { +  VisitExpr(E); +  E->setSubExpr(Reader.ReadSubExpr()); +} + +void ASTStmtReader::VisitStringLiteral(StringLiteral *E) { +  VisitExpr(E); +  unsigned Len = Record[Idx++]; +  assert(Record[Idx] == E->getNumConcatenated() && +         "Wrong number of concatenated tokens!"); +  ++Idx; +  StringLiteral::StringKind kind = +        static_cast<StringLiteral::StringKind>(Record[Idx++]); +  bool isPascal = Record[Idx++]; + +  // Read string data +  SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); +  E->setString(Reader.getContext(), Str.str(), kind, isPascal); +  Idx += Len; + +  // Read source locations +  for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) +    E->setStrTokenLoc(I, ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitCharacterLiteral(CharacterLiteral *E) { +  VisitExpr(E); +  E->setValue(Record[Idx++]); +  E->setLocation(ReadSourceLocation(Record, Idx)); +  E->setKind(static_cast<CharacterLiteral::CharacterKind>(Record[Idx++])); +} + +void ASTStmtReader::VisitParenExpr(ParenExpr *E) { +  VisitExpr(E); +  E->setLParen(ReadSourceLocation(Record, Idx)); +  E->setRParen(ReadSourceLocation(Record, Idx)); +  E->setSubExpr(Reader.ReadSubExpr()); +} + +void ASTStmtReader::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 = ReadSourceLocation(Record, Idx); +  E->RParenLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) { +  VisitExpr(E); +  E->setSubExpr(Reader.ReadSubExpr()); +  E->setOpcode((UnaryOperator::Opcode)Record[Idx++]); +  E->setOperatorLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { +  typedef OffsetOfExpr::OffsetOfNode Node; +  VisitExpr(E); +  assert(E->getNumComponents() == Record[Idx]); +  ++Idx; +  assert(E->getNumExpressions() == Record[Idx]); +  ++Idx; +  E->setOperatorLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +  E->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); +  for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { +    Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]); +    SourceLocation Start = ReadSourceLocation(Record, Idx); +    SourceLocation End = ReadSourceLocation(Record, Idx); +    switch (Kind) { +    case Node::Array: +      E->setComponent(I, Node(Start, Record[Idx++], End)); +      break; +         +    case Node::Field: +      E->setComponent(I, Node(Start, ReadDeclAs<FieldDecl>(Record, Idx), End)); +      break; + +    case Node::Identifier: +      E->setComponent(I,  +                      Node(Start,  +                           Reader.GetIdentifierInfo(F, Record, Idx), +                           End)); +      break; +         +    case Node::Base: { +      CXXBaseSpecifier *Base = new (Reader.getContext()) CXXBaseSpecifier(); +      *Base = Reader.ReadCXXBaseSpecifier(F, Record, Idx); +      E->setComponent(I, Node(Base)); +      break; +    } +    } +  } +   +  for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) +    E->setIndexExpr(I, Reader.ReadSubExpr()); +} + +void ASTStmtReader::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { +  VisitExpr(E); +  E->setKind(static_cast<UnaryExprOrTypeTrait>(Record[Idx++])); +  if (Record[Idx] == 0) { +    E->setArgument(Reader.ReadSubExpr()); +    ++Idx; +  } else { +    E->setArgument(GetTypeSourceInfo(Record, Idx)); +  } +  E->setOperatorLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { +  VisitExpr(E); +  E->setLHS(Reader.ReadSubExpr()); +  E->setRHS(Reader.ReadSubExpr()); +  E->setRBracketLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitCallExpr(CallExpr *E) { +  VisitExpr(E); +  E->setNumArgs(Reader.getContext(), Record[Idx++]); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +  E->setCallee(Reader.ReadSubExpr()); +  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) +    E->setArg(I, Reader.ReadSubExpr()); +} + +void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { +  VisitCallExpr(E); +} + +void ASTStmtReader::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 ASTStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) { +  VisitExpr(E); +  E->setBase(Reader.ReadSubExpr()); +  E->setIsaMemberLoc(ReadSourceLocation(Record, Idx)); +  E->setArrow(Record[Idx++]); +} + +void ASTStmtReader:: +VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) { +  VisitExpr(E); +  E->Operand = Reader.ReadSubExpr(); +  E->setShouldCopy(Record[Idx++]); +} + +void ASTStmtReader::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { +  VisitExplicitCastExpr(E); +  E->LParenLoc = ReadSourceLocation(Record, Idx); +  E->BridgeKeywordLoc = ReadSourceLocation(Record, Idx); +  E->Kind = Record[Idx++]; +} + +void ASTStmtReader::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(F, Record, Idx); +    *BaseI++ = BaseSpec; +  } +} + +void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { +  VisitExpr(E); +  E->setLHS(Reader.ReadSubExpr()); +  E->setRHS(Reader.ReadSubExpr()); +  E->setOpcode((BinaryOperator::Opcode)Record[Idx++]); +  E->setOperatorLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { +  VisitBinaryOperator(E); +  E->setComputationLHSType(Reader.readType(F, Record, Idx)); +  E->setComputationResultType(Reader.readType(F, Record, Idx)); +} + +void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) { +  VisitExpr(E); +  E->SubExprs[ConditionalOperator::COND] = Reader.ReadSubExpr(); +  E->SubExprs[ConditionalOperator::LHS] = Reader.ReadSubExpr(); +  E->SubExprs[ConditionalOperator::RHS] = Reader.ReadSubExpr(); +  E->QuestionLoc = ReadSourceLocation(Record, Idx); +  E->ColonLoc = ReadSourceLocation(Record, Idx); +} + +void +ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { +  VisitExpr(E); +  E->OpaqueValue = cast<OpaqueValueExpr>(Reader.ReadSubExpr()); +  E->SubExprs[BinaryConditionalOperator::COMMON] = Reader.ReadSubExpr(); +  E->SubExprs[BinaryConditionalOperator::COND] = Reader.ReadSubExpr(); +  E->SubExprs[BinaryConditionalOperator::LHS] = Reader.ReadSubExpr(); +  E->SubExprs[BinaryConditionalOperator::RHS] = Reader.ReadSubExpr(); +  E->QuestionLoc = ReadSourceLocation(Record, Idx); +  E->ColonLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { +  VisitCastExpr(E); +} + +void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) { +  VisitCastExpr(E); +  E->setTypeInfoAsWritten(GetTypeSourceInfo(Record, Idx)); +} + +void ASTStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) { +  VisitExplicitCastExpr(E); +  E->setLParenLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { +  VisitExpr(E); +  E->setLParenLoc(ReadSourceLocation(Record, Idx)); +  E->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); +  E->setInitializer(Reader.ReadSubExpr()); +  E->setFileScope(Record[Idx++]); +} + +void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { +  VisitExpr(E); +  E->setBase(Reader.ReadSubExpr()); +  E->setAccessor(Reader.GetIdentifierInfo(F, Record, Idx)); +  E->setAccessorLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { +  VisitExpr(E); +  E->setSyntacticForm(cast_or_null<InitListExpr>(Reader.ReadSubStmt())); +  E->setLBraceLoc(ReadSourceLocation(Record, Idx)); +  E->setRBraceLoc(ReadSourceLocation(Record, Idx)); +  bool isArrayFiller = Record[Idx++]; +  Expr *filler = 0; +  if (isArrayFiller) { +    filler = Reader.ReadSubExpr(); +    E->ArrayFillerOrUnionFieldInit = filler; +  } else +    E->ArrayFillerOrUnionFieldInit = ReadDeclAs<FieldDecl>(Record, Idx); +  E->sawArrayRangeDesignator(Record[Idx++]); +  E->setInitializesStdInitializerList(Record[Idx++]); +  unsigned NumInits = Record[Idx++]; +  E->reserveInits(Reader.getContext(), NumInits); +  if (isArrayFiller) { +    for (unsigned I = 0; I != NumInits; ++I) { +      Expr *init = Reader.ReadSubExpr(); +      E->updateInit(Reader.getContext(), I, init ? init : filler); +    } +  } else { +    for (unsigned I = 0; I != NumInits; ++I) +      E->updateInit(Reader.getContext(), I, Reader.ReadSubExpr()); +  } +} + +void ASTStmtReader::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(ReadSourceLocation(Record, Idx)); +  E->setGNUSyntax(Record[Idx++]); + +  SmallVector<Designator, 4> Designators; +  while (Idx < Record.size()) { +    switch ((DesignatorTypes)Record[Idx++]) { +    case DESIG_FIELD_DECL: { +      FieldDecl *Field = ReadDeclAs<FieldDecl>(Record, Idx); +      SourceLocation DotLoc +        = ReadSourceLocation(Record, Idx); +      SourceLocation FieldLoc +        = ReadSourceLocation(Record, Idx); +      Designators.push_back(Designator(Field->getIdentifier(), DotLoc, +                                       FieldLoc)); +      Designators.back().setField(Field); +      break; +    } + +    case DESIG_FIELD_NAME: { +      const IdentifierInfo *Name = Reader.GetIdentifierInfo(F, Record, Idx); +      SourceLocation DotLoc +        = ReadSourceLocation(Record, Idx); +      SourceLocation FieldLoc +        = ReadSourceLocation(Record, Idx); +      Designators.push_back(Designator(Name, DotLoc, FieldLoc)); +      break; +    } + +    case DESIG_ARRAY: { +      unsigned Index = Record[Idx++]; +      SourceLocation LBracketLoc +        = ReadSourceLocation(Record, Idx); +      SourceLocation RBracketLoc +        = ReadSourceLocation(Record, Idx); +      Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc)); +      break; +    } + +    case DESIG_ARRAY_RANGE: { +      unsigned Index = Record[Idx++]; +      SourceLocation LBracketLoc +        = ReadSourceLocation(Record, Idx); +      SourceLocation EllipsisLoc +        = ReadSourceLocation(Record, Idx); +      SourceLocation RBracketLoc +        = ReadSourceLocation(Record, Idx); +      Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc, +                                       RBracketLoc)); +      break; +    } +    } +  } +  E->setDesignators(Reader.getContext(),  +                    Designators.data(), Designators.size()); +} + +void ASTStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { +  VisitExpr(E); +} + +void ASTStmtReader::VisitVAArgExpr(VAArgExpr *E) { +  VisitExpr(E); +  E->setSubExpr(Reader.ReadSubExpr()); +  E->setWrittenTypeInfo(GetTypeSourceInfo(Record, Idx)); +  E->setBuiltinLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) { +  VisitExpr(E); +  E->setAmpAmpLoc(ReadSourceLocation(Record, Idx)); +  E->setLabelLoc(ReadSourceLocation(Record, Idx)); +  E->setLabel(ReadDeclAs<LabelDecl>(Record, Idx)); +} + +void ASTStmtReader::VisitStmtExpr(StmtExpr *E) { +  VisitExpr(E); +  E->setLParenLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +  E->setSubStmt(cast_or_null<CompoundStmt>(Reader.ReadSubStmt())); +} + +void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) { +  VisitExpr(E); +  E->setCond(Reader.ReadSubExpr()); +  E->setLHS(Reader.ReadSubExpr()); +  E->setRHS(Reader.ReadSubExpr()); +  E->setBuiltinLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitGNUNullExpr(GNUNullExpr *E) { +  VisitExpr(E); +  E->setTokenLocation(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { +  VisitExpr(E); +  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(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitBlockExpr(BlockExpr *E) { +  VisitExpr(E); +  E->setBlockDecl(ReadDeclAs<BlockDecl>(Record, Idx)); +} + +void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { +  VisitExpr(E); +  E->NumAssocs = Record[Idx++]; +  E->AssocTypes = new (Reader.getContext()) TypeSourceInfo*[E->NumAssocs]; +  E->SubExprs = +   new(Reader.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs]; + +  E->SubExprs[GenericSelectionExpr::CONTROLLING] = Reader.ReadSubExpr(); +  for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { +    E->AssocTypes[I] = GetTypeSourceInfo(Record, Idx); +    E->SubExprs[GenericSelectionExpr::END_EXPR+I] = Reader.ReadSubExpr(); +  } +  E->ResultIndex = Record[Idx++]; + +  E->GenericLoc = ReadSourceLocation(Record, Idx); +  E->DefaultLoc = ReadSourceLocation(Record, Idx); +  E->RParenLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitPseudoObjectExpr(PseudoObjectExpr *E) { +  VisitExpr(E); +  unsigned numSemanticExprs = Record[Idx++]; +  assert(numSemanticExprs + 1 == E->PseudoObjectExprBits.NumSubExprs); +  E->PseudoObjectExprBits.ResultIndex = Record[Idx++]; + +  // Read the syntactic expression. +  E->getSubExprsBuffer()[0] = Reader.ReadSubExpr(); + +  // Read all the semantic expressions. +  for (unsigned i = 0; i != numSemanticExprs; ++i) { +    Expr *subExpr = Reader.ReadSubExpr(); +    E->getSubExprsBuffer()[i+1] = subExpr; +  } +} + +void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) { +  VisitExpr(E); +  E->Op = AtomicExpr::AtomicOp(Record[Idx++]); +  E->NumSubExprs = AtomicExpr::getNumSubExprs(E->Op); +  for (unsigned I = 0; I != E->NumSubExprs; ++I) +    E->SubExprs[I] = Reader.ReadSubExpr(); +  E->BuiltinLoc = ReadSourceLocation(Record, Idx); +  E->RParenLoc = ReadSourceLocation(Record, Idx); +} + +//===----------------------------------------------------------------------===// +// Objective-C Expressions and Statements + +void ASTStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) { +  VisitExpr(E); +  E->setString(cast<StringLiteral>(Reader.ReadSubStmt())); +  E->setAtLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCNumericLiteral(ObjCNumericLiteral *E) { +  VisitExpr(E); +  // could be one of several IntegerLiteral, FloatLiteral, etc. +  E->Number = Reader.ReadSubStmt(); +  E->ObjCNumericLiteralMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx); +  E->AtLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { +  VisitExpr(E); +  unsigned NumElements = Record[Idx++]; +  assert(NumElements == E->getNumElements() && "Wrong number of elements"); +  Expr **Elements = E->getElements(); +  for (unsigned I = 0, N = NumElements; I != N; ++I) +    Elements[I] = Reader.ReadSubExpr(); +  E->ArrayWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx); +  E->Range = ReadSourceRange(Record, Idx); +} + +void ASTStmtReader::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { +  VisitExpr(E); +  unsigned NumElements = Record[Idx++]; +  assert(NumElements == E->getNumElements() && "Wrong number of elements"); +  bool HasPackExpansions = Record[Idx++]; +  assert(HasPackExpansions == E->HasPackExpansions &&"Pack expansion mismatch"); +  ObjCDictionaryLiteral::KeyValuePair *KeyValues = E->getKeyValues(); +  ObjCDictionaryLiteral::ExpansionData *Expansions = E->getExpansionData(); +  for (unsigned I = 0; I != NumElements; ++I) { +    KeyValues[I].Key = Reader.ReadSubExpr(); +    KeyValues[I].Value = Reader.ReadSubExpr(); +    if (HasPackExpansions) { +      Expansions[I].EllipsisLoc = ReadSourceLocation(Record, Idx); +      Expansions[I].NumExpansionsPlusOne = Record[Idx++]; +    } +  } +  E->DictWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx); +  E->Range = ReadSourceRange(Record, Idx); +} + +void ASTStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { +  VisitExpr(E); +  E->setEncodedTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); +  E->setAtLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { +  VisitExpr(E); +  E->setSelector(Reader.ReadSelector(F, Record, Idx)); +  E->setAtLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { +  VisitExpr(E); +  E->setProtocol(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); +  E->setAtLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { +  VisitExpr(E); +  E->setDecl(ReadDeclAs<ObjCIvarDecl>(Record, Idx)); +  E->setLocation(ReadSourceLocation(Record, Idx)); +  E->setBase(Reader.ReadSubExpr()); +  E->setIsArrow(Record[Idx++]); +  E->setIsFreeIvar(Record[Idx++]); +} + +void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { +  VisitExpr(E); +  unsigned MethodRefFlags = Record[Idx++]; +  bool Implicit = Record[Idx++] != 0; +  if (Implicit) { +    ObjCMethodDecl *Getter = ReadDeclAs<ObjCMethodDecl>(Record, Idx); +    ObjCMethodDecl *Setter = ReadDeclAs<ObjCMethodDecl>(Record, Idx); +    E->setImplicitProperty(Getter, Setter, MethodRefFlags); +  } else { +    E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(Record, Idx), +                           MethodRefFlags); +  } +  E->setLocation(ReadSourceLocation(Record, Idx)); +  E->setReceiverLocation(ReadSourceLocation(Record, Idx)); +  switch (Record[Idx++]) { +  case 0: +    E->setBase(Reader.ReadSubExpr()); +    break; +  case 1: +    E->setSuperReceiver(Reader.readType(F, Record, Idx)); +    break; +  case 2: +    E->setClassReceiver(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); +    break; +  } +} + +void ASTStmtReader::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) { +  VisitExpr(E); +  E->setRBracket(ReadSourceLocation(Record, Idx)); +  E->setBaseExpr(Reader.ReadSubExpr()); +  E->setKeyExpr(Reader.ReadSubExpr()); +  E->GetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(Record, Idx); +  E->SetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(Record, Idx); +} + +void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { +  VisitExpr(E); +  assert(Record[Idx] == E->getNumArgs()); +  ++Idx; +  unsigned NumStoredSelLocs = Record[Idx++]; +  E->SelLocsKind = Record[Idx++];  +  E->setDelegateInitCall(Record[Idx++]); +  E->IsImplicit = Record[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(GetTypeSourceInfo(Record, Idx)); +    break; + +  case ObjCMessageExpr::SuperClass: +  case ObjCMessageExpr::SuperInstance: { +    QualType T = Reader.readType(F, Record, Idx); +    SourceLocation SuperLoc = ReadSourceLocation(Record, Idx); +    E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance); +    break; +  } +  } + +  assert(Kind == E->getReceiverKind()); + +  if (Record[Idx++]) +    E->setMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx)); +  else +    E->setSelector(Reader.ReadSelector(F, Record, Idx)); + +  E->LBracLoc = ReadSourceLocation(Record, Idx); +  E->RBracLoc = ReadSourceLocation(Record, Idx); + +  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) +    E->setArg(I, Reader.ReadSubExpr()); + +  SourceLocation *Locs = E->getStoredSelLocs(); +  for (unsigned I = 0; I != NumStoredSelLocs; ++I) +    Locs[I] = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { +  VisitStmt(S); +  S->setElement(Reader.ReadSubStmt()); +  S->setCollection(Reader.ReadSubExpr()); +  S->setBody(Reader.ReadSubStmt()); +  S->setForLoc(ReadSourceLocation(Record, Idx)); +  S->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { +  VisitStmt(S); +  S->setCatchBody(Reader.ReadSubStmt()); +  S->setCatchParamDecl(ReadDeclAs<VarDecl>(Record, Idx)); +  S->setAtCatchLoc(ReadSourceLocation(Record, Idx)); +  S->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { +  VisitStmt(S); +  S->setFinallyBody(Reader.ReadSubStmt()); +  S->setAtFinallyLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { +  VisitStmt(S); +  S->setSubStmt(Reader.ReadSubStmt()); +  S->setAtLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::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(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { +  VisitStmt(S); +  S->setSynchExpr(Reader.ReadSubStmt()); +  S->setSynchBody(Reader.ReadSubStmt()); +  S->setAtSynchronizedLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { +  VisitStmt(S); +  S->setThrowExpr(Reader.ReadSubStmt()); +  S->setThrowLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) { +  VisitExpr(E); +  E->setValue(Record[Idx++]); +  E->setLocation(ReadSourceLocation(Record, Idx)); +} + +//===----------------------------------------------------------------------===// +// C++ Expressions and Statements +//===----------------------------------------------------------------------===// + +void ASTStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) { +  VisitStmt(S); +  S->CatchLoc = ReadSourceLocation(Record, Idx); +  S->ExceptionDecl = ReadDeclAs<VarDecl>(Record, Idx); +  S->HandlerBlock = Reader.ReadSubStmt(); +} + +void ASTStmtReader::VisitCXXTryStmt(CXXTryStmt *S) { +  VisitStmt(S); +  assert(Record[Idx] == S->getNumHandlers() && "NumStmtFields is wrong ?"); +  ++Idx; +  S->TryLoc = 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 ASTStmtReader::VisitCXXForRangeStmt(CXXForRangeStmt *S) { +  VisitStmt(S); +  S->setForLoc(ReadSourceLocation(Record, Idx)); +  S->setColonLoc(ReadSourceLocation(Record, Idx)); +  S->setRParenLoc(ReadSourceLocation(Record, Idx)); +  S->setRangeStmt(Reader.ReadSubStmt()); +  S->setBeginEndStmt(Reader.ReadSubStmt()); +  S->setCond(Reader.ReadSubExpr()); +  S->setInc(Reader.ReadSubExpr()); +  S->setLoopVarStmt(Reader.ReadSubStmt()); +  S->setBody(Reader.ReadSubStmt()); +} + +void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) { +  VisitStmt(S); +  S->KeywordLoc = ReadSourceLocation(Record, Idx); +  S->IsIfExists = Record[Idx++]; +  S->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +  ReadDeclarationNameInfo(S->NameInfo, Record, Idx); +  S->SubStmt = Reader.ReadSubStmt(); +} + +void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { +  VisitCallExpr(E); +  E->setOperator((OverloadedOperatorKind)Record[Idx++]); +} + +void ASTStmtReader::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(ReadDeclAs<CXXConstructorDecl>(Record, Idx)); +  E->setLocation(ReadSourceLocation(Record, Idx)); +  E->setElidable(Record[Idx++]); +  E->setHadMultipleCandidates(Record[Idx++]); +  E->setRequiresZeroInitialization(Record[Idx++]); +  E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); +  E->ParenRange = ReadSourceRange(Record, Idx); +} + +void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { +  VisitCXXConstructExpr(E); +  E->Type = GetTypeSourceInfo(Record, Idx); +} + +void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) { +  VisitExpr(E); +  unsigned NumCaptures = Record[Idx++]; +  assert(NumCaptures == E->NumCaptures);(void)NumCaptures; +  unsigned NumArrayIndexVars = Record[Idx++]; +  E->IntroducerRange = ReadSourceRange(Record, Idx); +  E->CaptureDefault = static_cast<LambdaCaptureDefault>(Record[Idx++]); +  E->ExplicitParams = Record[Idx++]; +  E->ExplicitResultType = Record[Idx++]; +  E->ClosingBrace = ReadSourceLocation(Record, Idx); +   +  // Read capture initializers. +  for (LambdaExpr::capture_init_iterator C = E->capture_init_begin(), +                                      CEnd = E->capture_init_end(); +       C != CEnd; ++C) +    *C = Reader.ReadSubExpr(); +   +  // Read array capture index variables. +  if (NumArrayIndexVars > 0) { +    unsigned *ArrayIndexStarts = E->getArrayIndexStarts(); +    for (unsigned I = 0; I != NumCaptures + 1; ++I) +      ArrayIndexStarts[I] = Record[Idx++]; +     +    VarDecl **ArrayIndexVars = E->getArrayIndexVars(); +    for (unsigned I = 0; I != NumArrayIndexVars; ++I) +      ArrayIndexVars[I] = ReadDeclAs<VarDecl>(Record, Idx); +  } +} + +void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { +  VisitExplicitCastExpr(E); +  SourceRange R = ReadSourceRange(Record, Idx); +  E->Loc = R.getBegin(); +  E->RParenLoc = R.getEnd(); +} + +void ASTStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { +  return VisitCXXNamedCastExpr(E); +} + +void ASTStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { +  return VisitCXXNamedCastExpr(E); +} + +void ASTStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) { +  return VisitCXXNamedCastExpr(E); +} + +void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) { +  return VisitCXXNamedCastExpr(E); +} + +void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { +  VisitExplicitCastExpr(E); +  E->setTypeBeginLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitUserDefinedLiteral(UserDefinedLiteral *E) { +  VisitCallExpr(E); +  E->UDSuffixLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { +  VisitExpr(E); +  E->setValue(Record[Idx++]); +  E->setLocation(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { +  VisitExpr(E); +  E->setLocation(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) { +  VisitExpr(E); +  E->setSourceRange(ReadSourceRange(Record, Idx)); +  if (E->isTypeOperand()) { // typeid(int) +    E->setTypeOperandSourceInfo( +        GetTypeSourceInfo(Record, Idx)); +    return; +  } +   +  // typeid(42+2) +  E->setExprOperand(Reader.ReadSubExpr()); +} + +void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) { +  VisitExpr(E); +  E->setLocation(ReadSourceLocation(Record, Idx)); +  E->setImplicit(Record[Idx++]); +} + +void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) { +  VisitExpr(E); +  E->ThrowLoc = ReadSourceLocation(Record, Idx); +  E->Op = Reader.ReadSubExpr(); +  E->IsThrownVariableInScope = Record[Idx++]; +} + +void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { +  VisitExpr(E); + +  assert((bool)Record[Idx] == E->Param.getInt() && "We messed up at creation ?"); +  ++Idx; // HasOtherExprStored and SubExpr was handled during creation. +  E->Param.setPointer(ReadDeclAs<ParmVarDecl>(Record, Idx)); +  E->Loc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { +  VisitExpr(E); +  E->setTemporary(Reader.ReadCXXTemporary(F, Record, Idx)); +  E->setSubExpr(Reader.ReadSubExpr()); +} + +void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { +  VisitExpr(E); +  E->TypeInfo = GetTypeSourceInfo(Record, Idx); +  E->RParenLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { +  VisitExpr(E); +  E->GlobalNew = Record[Idx++]; +  bool isArray = Record[Idx++]; +  E->UsualArrayDeleteWantsSize = Record[Idx++]; +  unsigned NumPlacementArgs = Record[Idx++]; +  E->StoredInitializationStyle = Record[Idx++]; +  E->setOperatorNew(ReadDeclAs<FunctionDecl>(Record, Idx)); +  E->setOperatorDelete(ReadDeclAs<FunctionDecl>(Record, Idx)); +  E->AllocatedTypeInfo = GetTypeSourceInfo(Record, Idx); +  E->TypeIdParens = ReadSourceRange(Record, Idx); +  E->StartLoc = ReadSourceLocation(Record, Idx); +  E->DirectInitRange = ReadSourceRange(Record, Idx); + +  E->AllocateArgsArray(Reader.getContext(), isArray, NumPlacementArgs, +                       E->StoredInitializationStyle != 0); + +  // 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 ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { +  VisitExpr(E); +  E->GlobalDelete = Record[Idx++]; +  E->ArrayForm = Record[Idx++]; +  E->ArrayFormAsWritten = Record[Idx++]; +  E->UsualArrayDeleteWantsSize = Record[Idx++]; +  E->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx); +  E->Argument = Reader.ReadSubExpr(); +  E->Loc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { +  VisitExpr(E); + +  E->Base = Reader.ReadSubExpr(); +  E->IsArrow = Record[Idx++]; +  E->OperatorLoc = ReadSourceLocation(Record, Idx); +  E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +  E->ScopeType = GetTypeSourceInfo(Record, Idx); +  E->ColonColonLoc = ReadSourceLocation(Record, Idx); +  E->TildeLoc = ReadSourceLocation(Record, Idx); +   +  IdentifierInfo *II = Reader.GetIdentifierInfo(F, Record, Idx); +  if (II) +    E->setDestroyedType(II, ReadSourceLocation(Record, Idx)); +  else +    E->setDestroyedType(GetTypeSourceInfo(Record, Idx)); +} + +void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) { +  VisitExpr(E); + +  unsigned NumObjects = Record[Idx++]; +  assert(NumObjects == E->getNumObjects()); +  for (unsigned i = 0; i != NumObjects; ++i) +    E->getObjectsBuffer()[i] = ReadDeclAs<BlockDecl>(Record, Idx); + +  E->SubExpr = Reader.ReadSubExpr(); +} + +void +ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ +  VisitExpr(E); + +  if (Record[Idx++]) // HasTemplateKWAndArgsInfo +    ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(), +                              /*NumTemplateArgs=*/Record[Idx++]); + +  E->Base = Reader.ReadSubExpr(); +  E->BaseType = Reader.readType(F, Record, Idx); +  E->IsArrow = Record[Idx++]; +  E->OperatorLoc = ReadSourceLocation(Record, Idx); +  E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +  E->FirstQualifierFoundInScope = ReadDeclAs<NamedDecl>(Record, Idx); +  ReadDeclarationNameInfo(E->MemberNameInfo, Record, Idx); +} + +void +ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { +  VisitExpr(E); + +  if (Record[Idx++]) // HasTemplateKWAndArgsInfo +    ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(), +                              /*NumTemplateArgs=*/Record[Idx++]); + +  E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +  ReadDeclarationNameInfo(E->NameInfo, Record, Idx); +} + +void +ASTStmtReader::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->Type = GetTypeSourceInfo(Record, Idx); +  E->setLParenLoc(ReadSourceLocation(Record, Idx)); +  E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + +void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { +  VisitExpr(E); + +  if (Record[Idx++]) // HasTemplateKWAndArgsInfo +    ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(), +                              /*NumTemplateArgs=*/Record[Idx++]); + +  unsigned NumDecls = Record[Idx++]; +  UnresolvedSet<8> Decls; +  for (unsigned i = 0; i != NumDecls; ++i) { +    NamedDecl *D = ReadDeclAs<NamedDecl>(Record, Idx); +    AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; +    Decls.addDecl(D, AS); +  } +  E->initializeResults(Reader.getContext(), Decls.begin(), Decls.end()); + +  ReadDeclarationNameInfo(E->NameInfo, Record, Idx); +  E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); +} + +void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { +  VisitOverloadExpr(E); +  E->IsArrow = Record[Idx++]; +  E->HasUnresolvedUsing = Record[Idx++]; +  E->Base = Reader.ReadSubExpr(); +  E->BaseType = Reader.readType(F, Record, Idx); +  E->OperatorLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { +  VisitOverloadExpr(E); +  E->RequiresADL = Record[Idx++]; +  if (E->RequiresADL) +    E->StdIsAssociatedNamespace = Record[Idx++]; +  E->Overloaded = Record[Idx++]; +  E->NamingClass = ReadDeclAs<CXXRecordDecl>(Record, Idx); +} + +void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { +  VisitExpr(E); +  E->UTT = (UnaryTypeTrait)Record[Idx++]; +  E->Value = (bool)Record[Idx++]; +  SourceRange Range = ReadSourceRange(Record, Idx); +  E->Loc = Range.getBegin(); +  E->RParen = Range.getEnd(); +  E->QueriedType = GetTypeSourceInfo(Record, Idx); +} + +void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { +  VisitExpr(E); +  E->BTT = (BinaryTypeTrait)Record[Idx++]; +  E->Value = (bool)Record[Idx++]; +  SourceRange Range = ReadSourceRange(Record, Idx); +  E->Loc = Range.getBegin(); +  E->RParen = Range.getEnd(); +  E->LhsType = GetTypeSourceInfo(Record, Idx); +  E->RhsType = GetTypeSourceInfo(Record, Idx); +} + +void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { +  VisitExpr(E); +  E->TypeTraitExprBits.NumArgs = Record[Idx++]; +  E->TypeTraitExprBits.Kind = Record[Idx++]; +  E->TypeTraitExprBits.Value = Record[Idx++]; +   +  TypeSourceInfo **Args = E->getTypeSourceInfos(); +  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) +    Args[I] = GetTypeSourceInfo(Record, Idx); +} + +void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { +  VisitExpr(E); +  E->ATT = (ArrayTypeTrait)Record[Idx++]; +  E->Value = (unsigned int)Record[Idx++]; +  SourceRange Range = ReadSourceRange(Record, Idx); +  E->Loc = Range.getBegin(); +  E->RParen = Range.getEnd(); +  E->QueriedType = GetTypeSourceInfo(Record, Idx); +} + +void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { +  VisitExpr(E); +  E->ET = (ExpressionTrait)Record[Idx++]; +  E->Value = (bool)Record[Idx++]; +  SourceRange Range = ReadSourceRange(Record, Idx); +  E->QueriedExpression = Reader.ReadSubExpr(); +  E->Loc = Range.getBegin(); +  E->RParen = Range.getEnd(); +} + +void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { +  VisitExpr(E); +  E->Value = (bool)Record[Idx++]; +  E->Range = ReadSourceRange(Record, Idx); +  E->Operand = Reader.ReadSubExpr(); +} + +void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) { +  VisitExpr(E); +  E->EllipsisLoc = ReadSourceLocation(Record, Idx); +  E->NumExpansions = Record[Idx++]; +  E->Pattern = Reader.ReadSubExpr();   +} + +void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) { +  VisitExpr(E); +  E->OperatorLoc = ReadSourceLocation(Record, Idx); +  E->PackLoc = ReadSourceLocation(Record, Idx); +  E->RParenLoc = ReadSourceLocation(Record, Idx); +  E->Length = Record[Idx++]; +  E->Pack = ReadDeclAs<NamedDecl>(Record, Idx); +} + +void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( +                                              SubstNonTypeTemplateParmExpr *E) { +  VisitExpr(E); +  E->Param = ReadDeclAs<NonTypeTemplateParmDecl>(Record, Idx); +  E->NameLoc = ReadSourceLocation(Record, Idx); +  E->Replacement = Reader.ReadSubExpr(); +} + +void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr( +                                          SubstNonTypeTemplateParmPackExpr *E) { +  VisitExpr(E); +  E->Param = ReadDeclAs<NonTypeTemplateParmDecl>(Record, Idx); +  TemplateArgument ArgPack = Reader.ReadTemplateArgument(F, Record, Idx); +  if (ArgPack.getKind() != TemplateArgument::Pack) +    return; +   +  E->Arguments = ArgPack.pack_begin(); +  E->NumArguments = ArgPack.pack_size(); +  E->NameLoc = ReadSourceLocation(Record, Idx); +} + +void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { +  VisitExpr(E); +  E->Temporary = Reader.ReadSubExpr(); +} + +void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { +  VisitExpr(E); +  E->SourceExpr = Reader.ReadSubExpr(); +  E->Loc = ReadSourceLocation(Record, Idx); +} + +//===----------------------------------------------------------------------===// +// Microsoft Expressions and Statements +//===----------------------------------------------------------------------===// +void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { +  VisitExpr(E); +  E->setSourceRange(ReadSourceRange(Record, Idx)); +  if (E->isTypeOperand()) { // __uuidof(ComType) +    E->setTypeOperandSourceInfo( +        GetTypeSourceInfo(Record, Idx)); +    return; +  } +   +  // __uuidof(expr) +  E->setExprOperand(Reader.ReadSubExpr()); +} + +void ASTStmtReader::VisitSEHExceptStmt(SEHExceptStmt *S) { +  VisitStmt(S); +  S->Loc = ReadSourceLocation(Record, Idx); +  S->Children[SEHExceptStmt::FILTER_EXPR] = Reader.ReadSubStmt(); +  S->Children[SEHExceptStmt::BLOCK] = Reader.ReadSubStmt(); +} + +void ASTStmtReader::VisitSEHFinallyStmt(SEHFinallyStmt *S) { +  VisitStmt(S); +  S->Loc = ReadSourceLocation(Record, Idx); +  S->Block = Reader.ReadSubStmt(); +} + +void ASTStmtReader::VisitSEHTryStmt(SEHTryStmt *S) { +  VisitStmt(S); +  S->IsCXXTry = Record[Idx++]; +  S->TryLoc = ReadSourceLocation(Record, Idx); +  S->Children[SEHTryStmt::TRY] = Reader.ReadSubStmt(); +  S->Children[SEHTryStmt::HANDLER] = Reader.ReadSubStmt(); +} + +//===----------------------------------------------------------------------===// +// CUDA Expressions and Statements +//===----------------------------------------------------------------------===// + +void ASTStmtReader::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) { +  VisitCallExpr(E); +  E->setConfig(cast<CallExpr>(Reader.ReadSubExpr())); +} + +//===----------------------------------------------------------------------===// +// OpenCL Expressions and Statements. +//===----------------------------------------------------------------------===// +void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) { +  VisitExpr(E); +  E->BuiltinLoc = ReadSourceLocation(Record, Idx); +  E->RParenLoc = ReadSourceLocation(Record, Idx); +  E->SrcExpr = Reader.ReadSubExpr(); +} + +//===----------------------------------------------------------------------===// +// ASTReader Implementation +//===----------------------------------------------------------------------===// + +Stmt *ASTReader::ReadStmt(ModuleFile &F) { +  switch (ReadingKind) { +  case Read_Decl: +  case Read_Type: +    return ReadStmtFromStream(F); +  case Read_Stmt: +    return ReadSubStmt(); +  } + +  llvm_unreachable("ReadingKind not set ?"); +} + +Expr *ASTReader::ReadExpr(ModuleFile &F) { +  return cast_or_null<Expr>(ReadStmt(F)); +} + +Expr *ASTReader::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 *ASTReader::ReadStmtFromStream(ModuleFile &F) { + +  ReadingKindTracker ReadingKind(Read_Stmt, *this); +  llvm::BitstreamCursor &Cursor = F.DeclsCursor; +   +  // Map of offset to previously deserialized stmt. The offset points +  /// just after the stmt record. +  llvm::DenseMap<uint64_t, Stmt *> StmtEntries; + +#ifndef NDEBUG +  unsigned PrevNumStmts = StmtStack.size(); +#endif + +  RecordData Record; +  unsigned Idx; +  ASTStmtReader Reader(*this, F, 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 AST 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 AST file"); +        return 0; +      } +      continue; +    } + +    if (Code == llvm::bitc::DEFINE_ABBREV) { +      Cursor.ReadAbbrevRecord(); +      continue; +    } + +    Stmt *S = 0; +    Idx = 0; +    Record.clear(); +    bool Finished = false; +    bool IsStmtReference = false; +    switch ((StmtCode)Cursor.ReadRecord(Code, Record)) { +    case STMT_STOP: +      Finished = true; +      break; + +    case STMT_REF_PTR: +      IsStmtReference = true; +      assert(StmtEntries.find(Record[0]) != StmtEntries.end() && +             "No stmt was recorded for this offset reference!"); +      S = StmtEntries[Record[Idx++]]; +      break; + +    case STMT_NULL_PTR: +      S = 0; +      break; + +    case STMT_NULL: +      S = new (Context) NullStmt(Empty); +      break; + +    case STMT_COMPOUND: +      S = new (Context) CompoundStmt(Empty); +      break; + +    case STMT_CASE: +      S = new (Context) CaseStmt(Empty); +      break; + +    case STMT_DEFAULT: +      S = new (Context) DefaultStmt(Empty); +      break; + +    case STMT_LABEL: +      S = new (Context) LabelStmt(Empty); +      break; + +    case STMT_ATTRIBUTED: +      S = new (Context) AttributedStmt(Empty); +      break; + +    case STMT_IF: +      S = new (Context) IfStmt(Empty); +      break; + +    case STMT_SWITCH: +      S = new (Context) SwitchStmt(Empty); +      break; + +    case STMT_WHILE: +      S = new (Context) WhileStmt(Empty); +      break; + +    case STMT_DO: +      S = new (Context) DoStmt(Empty); +      break; + +    case STMT_FOR: +      S = new (Context) ForStmt(Empty); +      break; + +    case STMT_GOTO: +      S = new (Context) GotoStmt(Empty); +      break; + +    case STMT_INDIRECT_GOTO: +      S = new (Context) IndirectGotoStmt(Empty); +      break; + +    case STMT_CONTINUE: +      S = new (Context) ContinueStmt(Empty); +      break; + +    case STMT_BREAK: +      S = new (Context) BreakStmt(Empty); +      break; + +    case STMT_RETURN: +      S = new (Context) ReturnStmt(Empty); +      break; + +    case STMT_DECL: +      S = new (Context) DeclStmt(Empty); +      break; + +    case STMT_ASM: +      S = new (Context) AsmStmt(Empty); +      break; + +    case EXPR_PREDEFINED: +      S = new (Context) PredefinedExpr(Empty); +      break; + +    case EXPR_DECL_REF: +      S = DeclRefExpr::CreateEmpty( +        Context, +        /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], +        /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], +        /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2], +        /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ? +          Record[ASTStmtReader::NumExprFields + 5] : 0); +      break; + +    case EXPR_INTEGER_LITERAL: +      S = IntegerLiteral::Create(Context, Empty); +      break; + +    case EXPR_FLOATING_LITERAL: +      S = FloatingLiteral::Create(Context, Empty); +      break; + +    case EXPR_IMAGINARY_LITERAL: +      S = new (Context) ImaginaryLiteral(Empty); +      break; + +    case EXPR_STRING_LITERAL: +      S = StringLiteral::CreateEmpty(Context, +                                     Record[ASTStmtReader::NumExprFields + 1]); +      break; + +    case EXPR_CHARACTER_LITERAL: +      S = new (Context) CharacterLiteral(Empty); +      break; + +    case EXPR_PAREN: +      S = new (Context) ParenExpr(Empty); +      break; + +    case EXPR_PAREN_LIST: +      S = new (Context) ParenListExpr(Empty); +      break; + +    case EXPR_UNARY_OPERATOR: +      S = new (Context) UnaryOperator(Empty); +      break; + +    case EXPR_OFFSETOF: +      S = OffsetOfExpr::CreateEmpty(Context,  +                                    Record[ASTStmtReader::NumExprFields], +                                    Record[ASTStmtReader::NumExprFields + 1]); +      break; +         +    case EXPR_SIZEOF_ALIGN_OF: +      S = new (Context) UnaryExprOrTypeTraitExpr(Empty); +      break; + +    case EXPR_ARRAY_SUBSCRIPT: +      S = new (Context) ArraySubscriptExpr(Empty); +      break; + +    case EXPR_CALL: +      S = new (Context) CallExpr(Context, Stmt::CallExprClass, Empty); +      break; + +    case 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); +      NestedNameSpecifierLoc QualifierLoc; +      if (Record[Idx++]) { // HasQualifier. +        QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx); +      } + +      SourceLocation TemplateKWLoc; +      TemplateArgumentListInfo ArgInfo; +      bool HasTemplateKWAndArgsInfo = Record[Idx++]; +      if (HasTemplateKWAndArgsInfo) { +        TemplateKWLoc = ReadSourceLocation(F, Record, Idx); +        unsigned NumTemplateArgs = Record[Idx++]; +        ArgInfo.setLAngleLoc(ReadSourceLocation(F, Record, Idx)); +        ArgInfo.setRAngleLoc(ReadSourceLocation(F, Record, Idx)); +        for (unsigned i = 0; i != NumTemplateArgs; ++i) +          ArgInfo.addArgument(ReadTemplateArgumentLoc(F, Record, Idx)); +      } + +      bool HadMultipleCandidates = Record[Idx++]; + +      NamedDecl *FoundD = ReadDeclAs<NamedDecl>(F, Record, Idx); +      AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; +      DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS); + +      QualType T = readType(F, Record, Idx); +      ExprValueKind VK = static_cast<ExprValueKind>(Record[Idx++]); +      ExprObjectKind OK = static_cast<ExprObjectKind>(Record[Idx++]); +      Expr *Base = ReadSubExpr(); +      ValueDecl *MemberD = ReadDeclAs<ValueDecl>(F, Record, Idx); +      SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx); +      DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc); +      bool IsArrow = Record[Idx++]; + +      S = MemberExpr::Create(Context, Base, IsArrow, QualifierLoc, +                             TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo, +                             HasTemplateKWAndArgsInfo ? &ArgInfo : 0, +                             T, VK, OK); +      ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc, +                             MemberD->getDeclName(), Record, Idx); +      if (HadMultipleCandidates) +        cast<MemberExpr>(S)->setHadMultipleCandidates(true); +      break; +    } + +    case EXPR_BINARY_OPERATOR: +      S = new (Context) BinaryOperator(Empty); +      break; + +    case EXPR_COMPOUND_ASSIGN_OPERATOR: +      S = new (Context) CompoundAssignOperator(Empty); +      break; + +    case EXPR_CONDITIONAL_OPERATOR: +      S = new (Context) ConditionalOperator(Empty); +      break; + +    case EXPR_BINARY_CONDITIONAL_OPERATOR: +      S = new (Context) BinaryConditionalOperator(Empty); +      break; + +    case EXPR_IMPLICIT_CAST: +      S = ImplicitCastExpr::CreateEmpty(Context, +                       /*PathSize*/ Record[ASTStmtReader::NumExprFields]); +      break; + +    case EXPR_CSTYLE_CAST: +      S = CStyleCastExpr::CreateEmpty(Context, +                       /*PathSize*/ Record[ASTStmtReader::NumExprFields]); +      break; + +    case EXPR_COMPOUND_LITERAL: +      S = new (Context) CompoundLiteralExpr(Empty); +      break; + +    case EXPR_EXT_VECTOR_ELEMENT: +      S = new (Context) ExtVectorElementExpr(Empty); +      break; + +    case EXPR_INIT_LIST: +      S = new (Context) InitListExpr(getContext(), Empty); +      break; + +    case EXPR_DESIGNATED_INIT: +      S = DesignatedInitExpr::CreateEmpty(Context, +                                     Record[ASTStmtReader::NumExprFields] - 1); + +      break; + +    case EXPR_IMPLICIT_VALUE_INIT: +      S = new (Context) ImplicitValueInitExpr(Empty); +      break; + +    case EXPR_VA_ARG: +      S = new (Context) VAArgExpr(Empty); +      break; + +    case EXPR_ADDR_LABEL: +      S = new (Context) AddrLabelExpr(Empty); +      break; + +    case EXPR_STMT: +      S = new (Context) StmtExpr(Empty); +      break; + +    case EXPR_CHOOSE: +      S = new (Context) ChooseExpr(Empty); +      break; + +    case EXPR_GNU_NULL: +      S = new (Context) GNUNullExpr(Empty); +      break; + +    case EXPR_SHUFFLE_VECTOR: +      S = new (Context) ShuffleVectorExpr(Empty); +      break; + +    case EXPR_BLOCK: +      S = new (Context) BlockExpr(Empty); +      break; + +    case EXPR_GENERIC_SELECTION: +      S = new (Context) GenericSelectionExpr(Empty); +      break; + +    case EXPR_OBJC_STRING_LITERAL: +      S = new (Context) ObjCStringLiteral(Empty); +      break; +    case EXPR_OBJC_NUMERIC_LITERAL: +      S = new (Context) ObjCNumericLiteral(Empty); +      break; +    case EXPR_OBJC_ARRAY_LITERAL: +      S = ObjCArrayLiteral::CreateEmpty(Context, +                                        Record[ASTStmtReader::NumExprFields]); +      break; +    case EXPR_OBJC_DICTIONARY_LITERAL: +      S = ObjCDictionaryLiteral::CreateEmpty(Context, +            Record[ASTStmtReader::NumExprFields], +            Record[ASTStmtReader::NumExprFields + 1]); +      break; +    case EXPR_OBJC_ENCODE: +      S = new (Context) ObjCEncodeExpr(Empty); +      break; +    case EXPR_OBJC_SELECTOR_EXPR: +      S = new (Context) ObjCSelectorExpr(Empty); +      break; +    case EXPR_OBJC_PROTOCOL_EXPR: +      S = new (Context) ObjCProtocolExpr(Empty); +      break; +    case EXPR_OBJC_IVAR_REF_EXPR: +      S = new (Context) ObjCIvarRefExpr(Empty); +      break; +    case EXPR_OBJC_PROPERTY_REF_EXPR: +      S = new (Context) ObjCPropertyRefExpr(Empty); +      break; +    case EXPR_OBJC_SUBSCRIPT_REF_EXPR: +      S = new (Context) ObjCSubscriptRefExpr(Empty); +      break; +    case EXPR_OBJC_KVC_REF_EXPR: +      llvm_unreachable("mismatching AST file"); +    case EXPR_OBJC_MESSAGE_EXPR: +      S = ObjCMessageExpr::CreateEmpty(Context, +                                     Record[ASTStmtReader::NumExprFields], +                                     Record[ASTStmtReader::NumExprFields + 1]); +      break; +    case EXPR_OBJC_ISA: +      S = new (Context) ObjCIsaExpr(Empty); +      break; +    case EXPR_OBJC_INDIRECT_COPY_RESTORE: +      S = new (Context) ObjCIndirectCopyRestoreExpr(Empty); +      break; +    case EXPR_OBJC_BRIDGED_CAST: +      S = new (Context) ObjCBridgedCastExpr(Empty); +      break; +    case STMT_OBJC_FOR_COLLECTION: +      S = new (Context) ObjCForCollectionStmt(Empty); +      break; +    case STMT_OBJC_CATCH: +      S = new (Context) ObjCAtCatchStmt(Empty); +      break; +    case STMT_OBJC_FINALLY: +      S = new (Context) ObjCAtFinallyStmt(Empty); +      break; +    case STMT_OBJC_AT_TRY: +      S = ObjCAtTryStmt::CreateEmpty(Context,  +                                     Record[ASTStmtReader::NumStmtFields], +                                     Record[ASTStmtReader::NumStmtFields + 1]); +      break; +    case STMT_OBJC_AT_SYNCHRONIZED: +      S = new (Context) ObjCAtSynchronizedStmt(Empty); +      break; +    case STMT_OBJC_AT_THROW: +      S = new (Context) ObjCAtThrowStmt(Empty); +      break; +    case STMT_OBJC_AUTORELEASE_POOL: +      S = new (Context) ObjCAutoreleasePoolStmt(Empty); +      break; +    case EXPR_OBJC_BOOL_LITERAL: +      S = new (Context) ObjCBoolLiteralExpr(Empty); +      break; +    case STMT_SEH_EXCEPT: +      S = new (Context) SEHExceptStmt(Empty); +      break; +    case STMT_SEH_FINALLY: +      S = new (Context) SEHFinallyStmt(Empty); +      break; +    case STMT_SEH_TRY: +      S = new (Context) SEHTryStmt(Empty); +      break; +    case STMT_CXX_CATCH: +      S = new (Context) CXXCatchStmt(Empty); +      break; + +    case STMT_CXX_TRY: +      S = CXXTryStmt::Create(Context, Empty, +             /*NumHandlers=*/Record[ASTStmtReader::NumStmtFields]); +      break; + +    case STMT_CXX_FOR_RANGE: +      S = new (Context) CXXForRangeStmt(Empty); +      break; + +    case STMT_MS_DEPENDENT_EXISTS: +      S = new (Context) MSDependentExistsStmt(SourceLocation(), true, +                                              NestedNameSpecifierLoc(), +                                              DeclarationNameInfo(), +                                              0); +      break; +         +    case EXPR_CXX_OPERATOR_CALL: +      S = new (Context) CXXOperatorCallExpr(Context, Empty); +      break; + +    case EXPR_CXX_MEMBER_CALL: +      S = new (Context) CXXMemberCallExpr(Context, Empty); +      break; +         +    case EXPR_CXX_CONSTRUCT: +      S = new (Context) CXXConstructExpr(Empty); +      break; +       +    case EXPR_CXX_TEMPORARY_OBJECT: +      S = new (Context) CXXTemporaryObjectExpr(Empty); +      break; + +    case EXPR_CXX_STATIC_CAST: +      S = CXXStaticCastExpr::CreateEmpty(Context, +                       /*PathSize*/ Record[ASTStmtReader::NumExprFields]); +      break; + +    case EXPR_CXX_DYNAMIC_CAST: +      S = CXXDynamicCastExpr::CreateEmpty(Context, +                       /*PathSize*/ Record[ASTStmtReader::NumExprFields]); +      break; + +    case EXPR_CXX_REINTERPRET_CAST: +      S = CXXReinterpretCastExpr::CreateEmpty(Context, +                       /*PathSize*/ Record[ASTStmtReader::NumExprFields]); +      break; + +    case EXPR_CXX_CONST_CAST: +      S = CXXConstCastExpr::CreateEmpty(Context); +      break; + +    case EXPR_CXX_FUNCTIONAL_CAST: +      S = CXXFunctionalCastExpr::CreateEmpty(Context, +                       /*PathSize*/ Record[ASTStmtReader::NumExprFields]); +      break; + +    case EXPR_USER_DEFINED_LITERAL: +      S = new (Context) UserDefinedLiteral(Context, Empty); +      break; + +    case EXPR_CXX_BOOL_LITERAL: +      S = new (Context) CXXBoolLiteralExpr(Empty); +      break; + +    case EXPR_CXX_NULL_PTR_LITERAL: +      S = new (Context) CXXNullPtrLiteralExpr(Empty); +      break; +    case EXPR_CXX_TYPEID_EXPR: +      S = new (Context) CXXTypeidExpr(Empty, true); +      break; +    case EXPR_CXX_TYPEID_TYPE: +      S = new (Context) CXXTypeidExpr(Empty, false); +      break; +    case EXPR_CXX_UUIDOF_EXPR: +      S = new (Context) CXXUuidofExpr(Empty, true); +      break; +    case EXPR_CXX_UUIDOF_TYPE: +      S = new (Context) CXXUuidofExpr(Empty, false); +      break; +    case EXPR_CXX_THIS: +      S = new (Context) CXXThisExpr(Empty); +      break; +    case EXPR_CXX_THROW: +      S = new (Context) CXXThrowExpr(Empty); +      break; +    case EXPR_CXX_DEFAULT_ARG: { +      bool HasOtherExprStored = Record[ASTStmtReader::NumExprFields]; +      if (HasOtherExprStored) { +        Expr *SubExpr = ReadSubExpr(); +        S = CXXDefaultArgExpr::Create(Context, SourceLocation(), 0, SubExpr); +      } else +        S = new (Context) CXXDefaultArgExpr(Empty); +      break; +    } +    case EXPR_CXX_BIND_TEMPORARY: +      S = new (Context) CXXBindTemporaryExpr(Empty); +      break; +         +    case EXPR_CXX_SCALAR_VALUE_INIT: +      S = new (Context) CXXScalarValueInitExpr(Empty); +      break; +    case EXPR_CXX_NEW: +      S = new (Context) CXXNewExpr(Empty); +      break; +    case EXPR_CXX_DELETE: +      S = new (Context) CXXDeleteExpr(Empty); +      break; +    case EXPR_CXX_PSEUDO_DESTRUCTOR: +      S = new (Context) CXXPseudoDestructorExpr(Empty); +      break; +         +    case EXPR_EXPR_WITH_CLEANUPS: +      S = ExprWithCleanups::Create(Context, Empty, +                                   Record[ASTStmtReader::NumExprFields]); +      break; +       +    case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: +      S = CXXDependentScopeMemberExpr::CreateEmpty(Context, +         /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], +                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] +                                   ? Record[ASTStmtReader::NumExprFields + 1]  +                                   : 0); +      break; +       +    case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: +      S = DependentScopeDeclRefExpr::CreateEmpty(Context, +         /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], +                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] +                                   ? Record[ASTStmtReader::NumExprFields + 1]  +                                   : 0); +      break; +       +    case EXPR_CXX_UNRESOLVED_CONSTRUCT: +      S = CXXUnresolvedConstructExpr::CreateEmpty(Context, +                              /*NumArgs=*/Record[ASTStmtReader::NumExprFields]); +      break; +       +    case EXPR_CXX_UNRESOLVED_MEMBER: +      S = UnresolvedMemberExpr::CreateEmpty(Context, +         /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], +                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] +                                   ? Record[ASTStmtReader::NumExprFields + 1]  +                                   : 0); +      break; +       +    case EXPR_CXX_UNRESOLVED_LOOKUP: +      S = UnresolvedLookupExpr::CreateEmpty(Context, +         /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], +                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] +                                   ? Record[ASTStmtReader::NumExprFields + 1]  +                                   : 0); +      break; +       +    case EXPR_CXX_UNARY_TYPE_TRAIT: +      S = new (Context) UnaryTypeTraitExpr(Empty); +      break; + +    case EXPR_BINARY_TYPE_TRAIT: +      S = new (Context) BinaryTypeTraitExpr(Empty); +      break; + +    case EXPR_TYPE_TRAIT: +      S = TypeTraitExpr::CreateDeserialized(Context,  +            Record[ASTStmtReader::NumExprFields]); +      break; +         +    case EXPR_ARRAY_TYPE_TRAIT: +      S = new (Context) ArrayTypeTraitExpr(Empty); +      break; + +    case EXPR_CXX_EXPRESSION_TRAIT: +      S = new (Context) ExpressionTraitExpr(Empty); +      break; + +    case EXPR_CXX_NOEXCEPT: +      S = new (Context) CXXNoexceptExpr(Empty); +      break; + +    case EXPR_PACK_EXPANSION: +      S = new (Context) PackExpansionExpr(Empty); +      break; +         +    case EXPR_SIZEOF_PACK: +      S = new (Context) SizeOfPackExpr(Empty); +      break; +         +    case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM: +      S = new (Context) SubstNonTypeTemplateParmExpr(Empty); +      break; +         +    case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK: +      S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty); +      break; +         +    case EXPR_MATERIALIZE_TEMPORARY: +      S = new (Context) MaterializeTemporaryExpr(Empty); +      break; +         +    case EXPR_OPAQUE_VALUE: +      S = new (Context) OpaqueValueExpr(Empty); +      break; + +    case EXPR_CUDA_KERNEL_CALL: +      S = new (Context) CUDAKernelCallExpr(Context, Empty); +      break; +         +    case EXPR_ASTYPE: +      S = new (Context) AsTypeExpr(Empty); +      break; + +    case EXPR_PSEUDO_OBJECT: { +      unsigned numSemanticExprs = Record[ASTStmtReader::NumExprFields]; +      S = PseudoObjectExpr::Create(Context, Empty, numSemanticExprs); +      break; +    } + +    case EXPR_ATOMIC: +      S = new (Context) AtomicExpr(Empty); +      break; +         +    case EXPR_LAMBDA: { +      unsigned NumCaptures = Record[ASTStmtReader::NumExprFields]; +      unsigned NumArrayIndexVars = Record[ASTStmtReader::NumExprFields + 1]; +      S = LambdaExpr::CreateDeserialized(Context, NumCaptures,  +                                         NumArrayIndexVars); +      break; +    } +    } +     +    // We hit a STMT_STOP, so we're done with this expression. +    if (Finished) +      break; + +    ++NumStatementsRead; + +    if (S && !IsStmtReference) { +      Reader.Visit(S); +      StmtEntries[Cursor.GetCurrentBitNo()] = 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/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp new file mode 100644 index 0000000..36933a9 --- /dev/null +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -0,0 +1,4552 @@ +//===--- ASTWriter.cpp - AST File 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 ASTWriter class, which writes AST files. +// +//===----------------------------------------------------------------------===// + +#include "clang/Serialization/ASTWriter.h" +#include "ASTCommon.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/DeclTemplate.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLocVisitor.h" +#include "clang/Serialization/ASTReader.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/FileSystemStatCache.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 "clang/Basic/VersionTuple.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include <algorithm> +#include <cstdio> +#include <string.h> +#include <utility> +using namespace clang; +using namespace clang::serialization; + +template <typename T, typename Allocator> +static StringRef data(const std::vector<T, Allocator> &v) { +  if (v.empty()) return StringRef(); +  return StringRef(reinterpret_cast<const char*>(&v[0]), +                         sizeof(T) * v.size()); +} + +template <typename T> +static StringRef data(const SmallVectorImpl<T> &v) { +  return StringRef(reinterpret_cast<const char*>(v.data()), +                         sizeof(T) * v.size()); +} + +//===----------------------------------------------------------------------===// +// Type serialization +//===----------------------------------------------------------------------===// + +namespace { +  class ASTTypeWriter { +    ASTWriter &Writer; +    ASTWriter::RecordDataImpl &Record; + +  public: +    /// \brief Type code that corresponds to the record generated. +    TypeCode Code; + +    ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record) +      : Writer(Writer), Record(Record), Code(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 ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) { +  llvm_unreachable("Built-in types are never serialized"); +} + +void ASTTypeWriter::VisitComplexType(const ComplexType *T) { +  Writer.AddTypeRef(T->getElementType(), Record); +  Code = TYPE_COMPLEX; +} + +void ASTTypeWriter::VisitPointerType(const PointerType *T) { +  Writer.AddTypeRef(T->getPointeeType(), Record); +  Code = TYPE_POINTER; +} + +void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) { +  Writer.AddTypeRef(T->getPointeeType(), Record); +  Code = TYPE_BLOCK_POINTER; +} + +void ASTTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) { +  Writer.AddTypeRef(T->getPointeeTypeAsWritten(), Record); +  Record.push_back(T->isSpelledAsLValue()); +  Code = TYPE_LVALUE_REFERENCE; +} + +void ASTTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) { +  Writer.AddTypeRef(T->getPointeeTypeAsWritten(), Record); +  Code = TYPE_RVALUE_REFERENCE; +} + +void ASTTypeWriter::VisitMemberPointerType(const MemberPointerType *T) { +  Writer.AddTypeRef(T->getPointeeType(), Record); +  Writer.AddTypeRef(QualType(T->getClass(), 0), Record); +  Code = TYPE_MEMBER_POINTER; +} + +void ASTTypeWriter::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 ASTTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { +  VisitArrayType(T); +  Writer.AddAPInt(T->getSize(), Record); +  Code = TYPE_CONSTANT_ARRAY; +} + +void ASTTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { +  VisitArrayType(T); +  Code = TYPE_INCOMPLETE_ARRAY; +} + +void ASTTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { +  VisitArrayType(T); +  Writer.AddSourceLocation(T->getLBracketLoc(), Record); +  Writer.AddSourceLocation(T->getRBracketLoc(), Record); +  Writer.AddStmt(T->getSizeExpr()); +  Code = TYPE_VARIABLE_ARRAY; +} + +void ASTTypeWriter::VisitVectorType(const VectorType *T) { +  Writer.AddTypeRef(T->getElementType(), Record); +  Record.push_back(T->getNumElements()); +  Record.push_back(T->getVectorKind()); +  Code = TYPE_VECTOR; +} + +void ASTTypeWriter::VisitExtVectorType(const ExtVectorType *T) { +  VisitVectorType(T); +  Code = TYPE_EXT_VECTOR; +} + +void ASTTypeWriter::VisitFunctionType(const FunctionType *T) { +  Writer.AddTypeRef(T->getResultType(), Record); +  FunctionType::ExtInfo C = T->getExtInfo(); +  Record.push_back(C.getNoReturn()); +  Record.push_back(C.getHasRegParm()); +  Record.push_back(C.getRegParm()); +  // FIXME: need to stabilize encoding of calling convention... +  Record.push_back(C.getCC()); +  Record.push_back(C.getProducesResult()); +} + +void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { +  VisitFunctionType(T); +  Code = TYPE_FUNCTION_NO_PROTO; +} + +void ASTTypeWriter::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->hasTrailingReturn()); +  Record.push_back(T->getTypeQuals()); +  Record.push_back(static_cast<unsigned>(T->getRefQualifier())); +  Record.push_back(T->getExceptionSpecType()); +  if (T->getExceptionSpecType() == EST_Dynamic) { +    Record.push_back(T->getNumExceptions()); +    for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) +      Writer.AddTypeRef(T->getExceptionType(I), Record); +  } else if (T->getExceptionSpecType() == EST_ComputedNoexcept) { +    Writer.AddStmt(T->getNoexceptExpr()); +  } else if (T->getExceptionSpecType() == EST_Uninstantiated) { +    Writer.AddDeclRef(T->getExceptionSpecDecl(), Record); +    Writer.AddDeclRef(T->getExceptionSpecTemplate(), Record); +  } +  Code = TYPE_FUNCTION_PROTO; +} + +void ASTTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) { +  Writer.AddDeclRef(T->getDecl(), Record); +  Code = TYPE_UNRESOLVED_USING; +} + +void ASTTypeWriter::VisitTypedefType(const TypedefType *T) { +  Writer.AddDeclRef(T->getDecl(), Record); +  assert(!T->isCanonicalUnqualified() && "Invalid typedef ?"); +  Writer.AddTypeRef(T->getCanonicalTypeInternal(), Record); +  Code = TYPE_TYPEDEF; +} + +void ASTTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) { +  Writer.AddStmt(T->getUnderlyingExpr()); +  Code = TYPE_TYPEOF_EXPR; +} + +void ASTTypeWriter::VisitTypeOfType(const TypeOfType *T) { +  Writer.AddTypeRef(T->getUnderlyingType(), Record); +  Code = TYPE_TYPEOF; +} + +void ASTTypeWriter::VisitDecltypeType(const DecltypeType *T) { +  Writer.AddTypeRef(T->getUnderlyingType(), Record); +  Writer.AddStmt(T->getUnderlyingExpr()); +  Code = TYPE_DECLTYPE; +} + +void ASTTypeWriter::VisitUnaryTransformType(const UnaryTransformType *T) { +  Writer.AddTypeRef(T->getBaseType(), Record); +  Writer.AddTypeRef(T->getUnderlyingType(), Record); +  Record.push_back(T->getUTTKind()); +  Code = TYPE_UNARY_TRANSFORM; +} + +void ASTTypeWriter::VisitAutoType(const AutoType *T) { +  Writer.AddTypeRef(T->getDeducedType(), Record); +  Code = TYPE_AUTO; +} + +void ASTTypeWriter::VisitTagType(const TagType *T) { +  Record.push_back(T->isDependentType()); +  Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record); +  assert(!T->isBeingDefined() && +         "Cannot serialize in the middle of a type definition"); +} + +void ASTTypeWriter::VisitRecordType(const RecordType *T) { +  VisitTagType(T); +  Code = TYPE_RECORD; +} + +void ASTTypeWriter::VisitEnumType(const EnumType *T) { +  VisitTagType(T); +  Code = TYPE_ENUM; +} + +void ASTTypeWriter::VisitAttributedType(const AttributedType *T) { +  Writer.AddTypeRef(T->getModifiedType(), Record); +  Writer.AddTypeRef(T->getEquivalentType(), Record); +  Record.push_back(T->getAttrKind()); +  Code = TYPE_ATTRIBUTED; +} + +void +ASTTypeWriter::VisitSubstTemplateTypeParmType( +                                        const SubstTemplateTypeParmType *T) { +  Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record); +  Writer.AddTypeRef(T->getReplacementType(), Record); +  Code = TYPE_SUBST_TEMPLATE_TYPE_PARM; +} + +void +ASTTypeWriter::VisitSubstTemplateTypeParmPackType( +                                      const SubstTemplateTypeParmPackType *T) { +  Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record); +  Writer.AddTemplateArgument(T->getArgumentPack(), Record); +  Code = TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK; +} + +void +ASTTypeWriter::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->isTypeAlias() ? T->getAliasedType() : +                    T->isCanonicalUnqualified() ? QualType() +                                                : T->getCanonicalTypeInternal(), +                    Record); +  Code = TYPE_TEMPLATE_SPECIALIZATION; +} + +void +ASTTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) { +  VisitArrayType(T); +  Writer.AddStmt(T->getSizeExpr()); +  Writer.AddSourceRange(T->getBracketsRange(), Record); +  Code = TYPE_DEPENDENT_SIZED_ARRAY; +} + +void +ASTTypeWriter::VisitDependentSizedExtVectorType( +                                        const DependentSizedExtVectorType *T) { +  // FIXME: Serialize this type (C++ only) +  llvm_unreachable("Cannot serialize dependent sized extended vector types"); +} + +void +ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { +  Record.push_back(T->getDepth()); +  Record.push_back(T->getIndex()); +  Record.push_back(T->isParameterPack()); +  Writer.AddDeclRef(T->getDecl(), Record); +  Code = TYPE_TEMPLATE_TYPE_PARM; +} + +void +ASTTypeWriter::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 = TYPE_DEPENDENT_NAME; +} + +void +ASTTypeWriter::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 = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION; +} + +void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) { +  Writer.AddTypeRef(T->getPattern(), Record); +  if (llvm::Optional<unsigned> NumExpansions = T->getNumExpansions()) +    Record.push_back(*NumExpansions + 1); +  else +    Record.push_back(0); +  Code = TYPE_PACK_EXPANSION; +} + +void ASTTypeWriter::VisitParenType(const ParenType *T) { +  Writer.AddTypeRef(T->getInnerType(), Record); +  Code = TYPE_PAREN; +} + +void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) { +  Record.push_back(T->getKeyword()); +  Writer.AddNestedNameSpecifier(T->getQualifier(), Record); +  Writer.AddTypeRef(T->getNamedType(), Record); +  Code = TYPE_ELABORATED; +} + +void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { +  Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record); +  Writer.AddTypeRef(T->getInjectedSpecializationType(), Record); +  Code = TYPE_INJECTED_CLASS_NAME; +} + +void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { +  Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record); +  Code = TYPE_OBJC_INTERFACE; +} + +void ASTTypeWriter::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 = TYPE_OBJC_OBJECT; +} + +void +ASTTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { +  Writer.AddTypeRef(T->getPointeeType(), Record); +  Code = TYPE_OBJC_OBJECT_POINTER; +} + +void +ASTTypeWriter::VisitAtomicType(const AtomicType *T) { +  Writer.AddTypeRef(T->getValueType(), Record); +  Code = TYPE_ATOMIC; +} + +namespace { + +class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { +  ASTWriter &Writer; +  ASTWriter::RecordDataImpl &Record; + +public: +  TypeLocWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &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); +  Writer.AddTypeSourceInfo(TL.getClassTInfo(), 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.getLocalRangeBegin(), Record); +  Writer.AddSourceLocation(TL.getLocalRangeEnd(), Record); +  Record.push_back(TL.getTrailingReturn()); +  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::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { +  Writer.AddSourceLocation(TL.getKWLoc(), Record); +  Writer.AddSourceLocation(TL.getLParenLoc(), Record); +  Writer.AddSourceLocation(TL.getRParenLoc(), Record); +  Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record); +} +void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc 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::VisitAttributedTypeLoc(AttributedTypeLoc TL) { +  Writer.AddSourceLocation(TL.getAttrNameLoc(), Record); +  if (TL.hasAttrOperand()) { +    SourceRange range = TL.getAttrOperandParensRange(); +    Writer.AddSourceLocation(range.getBegin(), Record); +    Writer.AddSourceLocation(range.getEnd(), Record); +  } +  if (TL.hasAttrExprOperand()) { +    Expr *operand = TL.getAttrExprOperand(); +    Record.push_back(operand ? 1 : 0); +    if (operand) Writer.AddStmt(operand); +  } else if (TL.hasAttrEnumOperand()) { +    Writer.AddSourceLocation(TL.getAttrEnumOperandLoc(), Record); +  } +} +void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc( +                                            SubstTemplateTypeParmTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc( +                                          SubstTemplateTypeParmPackTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitTemplateSpecializationTypeLoc( +                                           TemplateSpecializationTypeLoc TL) { +  Writer.AddSourceLocation(TL.getTemplateKeywordLoc(), Record); +  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::VisitParenTypeLoc(ParenTypeLoc TL) { +  Writer.AddSourceLocation(TL.getLParenLoc(), Record); +  Writer.AddSourceLocation(TL.getRParenLoc(), Record); +} +void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { +  Writer.AddSourceLocation(TL.getElaboratedKeywordLoc(), Record); +  Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); +} +void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { +  Writer.AddSourceLocation(TL.getElaboratedKeywordLoc(), Record); +  Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( +       DependentTemplateSpecializationTypeLoc TL) { +  Writer.AddSourceLocation(TL.getElaboratedKeywordLoc(), Record); +  Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); +  Writer.AddSourceLocation(TL.getTemplateKeywordLoc(), Record); +  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::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { +  Writer.AddSourceLocation(TL.getEllipsisLoc(), 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); +} +void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) { +  Writer.AddSourceLocation(TL.getKWLoc(), Record); +  Writer.AddSourceLocation(TL.getLParenLoc(), Record); +  Writer.AddSourceLocation(TL.getRParenLoc(), Record); +} + +//===----------------------------------------------------------------------===// +// ASTWriter Implementation +//===----------------------------------------------------------------------===// + +static void EmitBlockID(unsigned ID, const char *Name, +                        llvm::BitstreamWriter &Stream, +                        ASTWriter::RecordDataImpl &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, +                         ASTWriter::RecordDataImpl &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, +                          ASTWriter::RecordDataImpl &Record) { +#define RECORD(X) EmitRecordID(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_ATTRIBUTED); +  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_CHOOSE); +  RECORD(EXPR_GNU_NULL); +  RECORD(EXPR_SHUFFLE_VECTOR); +  RECORD(EXPR_BLOCK); +  RECORD(EXPR_GENERIC_SELECTION); +  RECORD(EXPR_OBJC_STRING_LITERAL); +  RECORD(EXPR_OBJC_NUMERIC_LITERAL); +  RECORD(EXPR_OBJC_ARRAY_LITERAL); +  RECORD(EXPR_OBJC_DICTIONARY_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(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_OBJC_BOOL_LITERAL); +  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_USER_DEFINED_LITERAL); +  RECORD(EXPR_CXX_BOOL_LITERAL); +  RECORD(EXPR_CXX_NULL_PTR_LITERAL); +  RECORD(EXPR_CXX_TYPEID_EXPR); +  RECORD(EXPR_CXX_TYPEID_TYPE); +  RECORD(EXPR_CXX_UUIDOF_EXPR); +  RECORD(EXPR_CXX_UUIDOF_TYPE); +  RECORD(EXPR_CXX_THIS); +  RECORD(EXPR_CXX_THROW); +  RECORD(EXPR_CXX_DEFAULT_ARG); +  RECORD(EXPR_CXX_BIND_TEMPORARY); +  RECORD(EXPR_CXX_SCALAR_VALUE_INIT); +  RECORD(EXPR_CXX_NEW); +  RECORD(EXPR_CXX_DELETE); +  RECORD(EXPR_CXX_PSEUDO_DESTRUCTOR); +  RECORD(EXPR_EXPR_WITH_CLEANUPS); +  RECORD(EXPR_CXX_DEPENDENT_SCOPE_MEMBER); +  RECORD(EXPR_CXX_DEPENDENT_SCOPE_DECL_REF); +  RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT); +  RECORD(EXPR_CXX_UNRESOLVED_MEMBER); +  RECORD(EXPR_CXX_UNRESOLVED_LOOKUP); +  RECORD(EXPR_CXX_UNARY_TYPE_TRAIT); +  RECORD(EXPR_CXX_NOEXCEPT); +  RECORD(EXPR_OPAQUE_VALUE); +  RECORD(EXPR_BINARY_TYPE_TRAIT); +  RECORD(EXPR_PACK_EXPANSION); +  RECORD(EXPR_SIZEOF_PACK); +  RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK); +  RECORD(EXPR_CUDA_KERNEL_CALL); +#undef RECORD +} + +void ASTWriter::WriteBlockInfoBlock() { +  RecordData Record; +  Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); + +#define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record) +#define RECORD(X) EmitRecordID(X, #X, Stream, Record) + +  // AST Top-Level Block. +  BLOCK(AST_BLOCK); +  RECORD(ORIGINAL_FILE_NAME); +  RECORD(ORIGINAL_FILE_ID); +  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(PPD_ENTITIES_OFFSETS); +  RECORD(IMPORTS); +  RECORD(REFERENCED_SELECTOR_POOL); +  RECORD(TU_UPDATE_LEXICAL); +  RECORD(LOCAL_REDECLARATIONS_MAP); +  RECORD(SEMA_DECL_REFS); +  RECORD(WEAK_UNDECLARED_IDENTIFIERS); +  RECORD(PENDING_IMPLICIT_INSTANTIATIONS); +  RECORD(DECL_REPLACEMENTS); +  RECORD(UPDATE_VISIBLE); +  RECORD(DECL_UPDATE_OFFSETS); +  RECORD(DECL_UPDATES); +  RECORD(CXX_BASE_SPECIFIER_OFFSETS); +  RECORD(DIAG_PRAGMA_MAPPINGS); +  RECORD(CUDA_SPECIAL_DECL_REFS); +  RECORD(HEADER_SEARCH_TABLE); +  RECORD(ORIGINAL_PCH_DIR); +  RECORD(FP_PRAGMA_OPTIONS); +  RECORD(OPENCL_EXTENSIONS); +  RECORD(DELEGATING_CTORS); +  RECORD(FILE_SOURCE_LOCATION_OFFSETS); +  RECORD(KNOWN_NAMESPACES); +  RECORD(MODULE_OFFSET_MAP); +  RECORD(SOURCE_MANAGER_LINE_TABLE); +  RECORD(OBJC_CATEGORIES_MAP); +  RECORD(FILE_SORTED_DECLS); +  RECORD(IMPORTED_MODULES); +  RECORD(MERGED_DECLARATIONS); +  RECORD(LOCAL_REDECLARATIONS); +  RECORD(OBJC_CATEGORIES); + +  // SourceManager Block. +  BLOCK(SOURCE_MANAGER_BLOCK); +  RECORD(SM_SLOC_FILE_ENTRY); +  RECORD(SM_SLOC_BUFFER_ENTRY); +  RECORD(SM_SLOC_BUFFER_BLOB); +  RECORD(SM_SLOC_EXPANSION_ENTRY); + +  // Preprocessor Block. +  BLOCK(PREPROCESSOR_BLOCK); +  RECORD(PP_MACRO_OBJECT_LIKE); +  RECORD(PP_MACRO_FUNCTION_LIKE); +  RECORD(PP_TOKEN); +   +  // 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(TYPE_DECLTYPE); +  RECORD(TYPE_ELABORATED); +  RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM); +  RECORD(TYPE_UNRESOLVED_USING); +  RECORD(TYPE_INJECTED_CLASS_NAME); +  RECORD(TYPE_OBJC_OBJECT); +  RECORD(TYPE_TEMPLATE_TYPE_PARM); +  RECORD(TYPE_TEMPLATE_SPECIALIZATION); +  RECORD(TYPE_DEPENDENT_NAME); +  RECORD(TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION); +  RECORD(TYPE_DEPENDENT_SIZED_ARRAY); +  RECORD(TYPE_PAREN); +  RECORD(TYPE_PACK_EXPANSION); +  RECORD(TYPE_ATTRIBUTED); +  RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK); +  RECORD(TYPE_ATOMIC); +  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_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); +  RECORD(DECL_NAMESPACE); +  RECORD(DECL_NAMESPACE_ALIAS); +  RECORD(DECL_USING); +  RECORD(DECL_USING_SHADOW); +  RECORD(DECL_USING_DIRECTIVE); +  RECORD(DECL_UNRESOLVED_USING_VALUE); +  RECORD(DECL_UNRESOLVED_USING_TYPENAME); +  RECORD(DECL_LINKAGE_SPEC); +  RECORD(DECL_CXX_RECORD); +  RECORD(DECL_CXX_METHOD); +  RECORD(DECL_CXX_CONSTRUCTOR); +  RECORD(DECL_CXX_DESTRUCTOR); +  RECORD(DECL_CXX_CONVERSION); +  RECORD(DECL_ACCESS_SPEC); +  RECORD(DECL_FRIEND); +  RECORD(DECL_FRIEND_TEMPLATE); +  RECORD(DECL_CLASS_TEMPLATE); +  RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION); +  RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION); +  RECORD(DECL_FUNCTION_TEMPLATE); +  RECORD(DECL_TEMPLATE_TYPE_PARM); +  RECORD(DECL_NON_TYPE_TEMPLATE_PARM); +  RECORD(DECL_TEMPLATE_TEMPLATE_PARM); +  RECORD(DECL_STATIC_ASSERT); +  RECORD(DECL_CXX_BASE_SPECIFIERS); +  RECORD(DECL_INDIRECTFIELD); +  RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK); +   +  // Statements and Exprs can occur in the Decls and Types block. +  AddStmtsExprs(Stream, Record); + +  BLOCK(PREPROCESSOR_DETAIL_BLOCK); +  RECORD(PPD_MACRO_EXPANSION); +  RECORD(PPD_MACRO_DEFINITION); +  RECORD(PPD_INCLUSION_DIRECTIVE); +   +#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, StringRef isysroot) { +  assert(Filename && "No file name to adjust?"); + +  if (isysroot.empty()) +    return Filename; + +  // Verify that the filename and the system root have the same prefix. +  unsigned Pos = 0; +  for (; Filename[Pos] && Pos < isysroot.size(); ++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 AST metadata (e.g., i686-apple-darwin9). +void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, +                              const std::string &OutputFile) { +  using namespace llvm; + +  // Metadata +  const TargetInfo &Target = Context.getTargetInfo(); +  BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev(); +  MetaAbbrev->Add(BitCodeAbbrevOp(METADATA)); +  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST major +  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST minor +  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major +  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor +  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable +  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Has errors +  MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple +  unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); + +  RecordData Record; +  Record.push_back(METADATA); +  Record.push_back(VERSION_MAJOR); +  Record.push_back(VERSION_MINOR); +  Record.push_back(CLANG_VERSION_MAJOR); +  Record.push_back(CLANG_VERSION_MINOR); +  Record.push_back(!isysroot.empty()); +  Record.push_back(ASTHasCompilerErrors); +  const std::string &Triple = Target.getTriple().getTriple(); +  Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple); + +  if (Chain) { +    serialization::ModuleManager &Mgr = Chain->getModuleManager(); +    llvm::SmallVector<char, 128> ModulePaths; +    Record.clear(); + +    for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end(); +         M != MEnd; ++M) { +      // Skip modules that weren't directly imported. +      if (!(*M)->isDirectlyImported()) +        continue; + +      Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding +      // FIXME: Write import location, once it matters. +      // FIXME: This writes the absolute path for AST files we depend on. +      const std::string &FileName = (*M)->FileName; +      Record.push_back(FileName.size()); +      Record.append(FileName.begin(), FileName.end()); +    } +    Stream.EmitRecord(IMPORTS, Record); +  } + +  // Original file name and file ID +  SourceManager &SM = Context.getSourceManager(); +  if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { +    BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev(); +    FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE_NAME)); +    FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name +    unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); + +    SmallString<128> MainFilePath(MainFile->getName()); + +    llvm::sys::fs::make_absolute(MainFilePath); + +    const char *MainFileNameStr = MainFilePath.c_str(); +    MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr, +                                                      isysroot); +    RecordData Record; +    Record.push_back(ORIGINAL_FILE_NAME); +    Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); +     +    Record.clear(); +    Record.push_back(SM.getMainFileID().getOpaqueValue()); +    Stream.EmitRecord(ORIGINAL_FILE_ID, Record); +  } + +  // Original PCH directory +  if (!OutputFile.empty() && OutputFile != "-") { +    BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +    Abbrev->Add(BitCodeAbbrevOp(ORIGINAL_PCH_DIR)); +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name +    unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); + +    SmallString<128> OutputPath(OutputFile); + +    llvm::sys::fs::make_absolute(OutputPath); +    StringRef origDir = llvm::sys::path::parent_path(OutputPath); + +    RecordData Record; +    Record.push_back(ORIGINAL_PCH_DIR); +    Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); +  } + +  // Repository branch/version information. +  BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev(); +  RepoAbbrev->Add(BitCodeAbbrevOp(VERSION_CONTROL_BRANCH_REVISION)); +  RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag +  unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev); +  Record.clear(); +  Record.push_back(VERSION_CONTROL_BRANCH_REVISION); +  Stream.EmitRecordWithBlob(RepoAbbrevCode, Record, +                            getClangFullRepositoryVersion()); +} + +/// \brief Write the LangOptions structure. +void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { +  RecordData Record; +#define LANGOPT(Name, Bits, Default, Description) \ +  Record.push_back(LangOpts.Name); +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ +  Record.push_back(static_cast<unsigned>(LangOpts.get##Name())); +#include "clang/Basic/LangOptions.def"   +   +  Record.push_back(LangOpts.CurrentModule.size()); +  Record.append(LangOpts.CurrentModule.begin(), LangOpts.CurrentModule.end()); +  Stream.EmitRecord(LANGUAGE_OPTIONS, Record); +} + +//===----------------------------------------------------------------------===// +// stat cache Serialization +//===----------------------------------------------------------------------===// + +namespace { +// Trait used for the on-disk hash table of stat cache results. +class ASTStatCacheTrait { +public: +  typedef const char * key_type; +  typedef key_type key_type_ref; + +  typedef 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(raw_ostream& Out, const char *path, +                      data_type_ref Data) { +    unsigned StrLen = strlen(path); +    clang::io::Emit16(Out, StrLen); +    unsigned DataLen = 4 + 4 + 2 + 8 + 8; +    clang::io::Emit8(Out, DataLen); +    return std::make_pair(StrLen + 1, DataLen); +  } + +  void EmitKey(raw_ostream& Out, const char *path, unsigned KeyLen) { +    Out.write(path, KeyLen); +  } + +  void EmitData(raw_ostream &Out, key_type_ref, +                data_type_ref Data, unsigned DataLen) { +    using namespace clang::io; +    uint64_t Start = Out.tell(); (void)Start; + +    Emit32(Out, (uint32_t) Data.st_ino); +    Emit32(Out, (uint32_t) Data.st_dev); +    Emit16(Out, (uint16_t) Data.st_mode); +    Emit64(Out, (uint64_t) Data.st_mtime); +    Emit64(Out, (uint64_t) Data.st_size); + +    assert(Out.tell() - Start == DataLen && "Wrong data length"); +  } +}; +} // end anonymous namespace + +/// \brief Write the stat() system call cache to the AST file. +void ASTWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { +  // Build the on-disk hash table containing information about every +  // stat() call. +  OnDiskChainedHashTableGenerator<ASTStatCacheTrait> Generator; +  unsigned NumStatEntries = 0; +  for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), +                                StatEnd = StatCalls.end(); +       Stat != StatEnd; ++Stat, ++NumStatEntries) { +    StringRef Filename = Stat->first(); +    Generator.insert(Filename.data(), Stat->second); +  } + +  // Create the on-disk hash table in a buffer. +  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(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(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(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 +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // BufferOverridden +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls +  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(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(SM_SLOC_BUFFER_BLOB)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob +  return Stream.EmitAbbrev(Abbrev); +} + +/// \brief Create an abbreviation for the SLocEntry that refers to a macro +/// expansion. +static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) { +  using namespace llvm; +  BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_EXPANSION_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); +} + +namespace { +  // Trait used for the on-disk hash table of header search information. +  class HeaderFileInfoTrait { +    ASTWriter &Writer; +    const HeaderSearch &HS; +     +    // Keep track of the framework names we've used during serialization. +    SmallVector<char, 128> FrameworkStringData; +    llvm::StringMap<unsigned> FrameworkNameOffset; +     +  public: +    HeaderFileInfoTrait(ASTWriter &Writer, const HeaderSearch &HS)  +      : Writer(Writer), HS(HS) { } +     +    typedef const char *key_type; +    typedef key_type key_type_ref; +     +    typedef HeaderFileInfo data_type; +    typedef const data_type &data_type_ref; +     +    static unsigned ComputeHash(const char *path) { +      // The hash is based only on the filename portion of the key, so that the +      // reader can match based on filenames when symlinking or excess path +      // elements ("foo/../", "../") change the form of the name. However, +      // complete path is still the key. +      return llvm::HashString(llvm::sys::path::filename(path)); +    } +     +    std::pair<unsigned,unsigned> +    EmitKeyDataLength(raw_ostream& Out, const char *path, +                      data_type_ref Data) { +      unsigned StrLen = strlen(path); +      clang::io::Emit16(Out, StrLen); +      unsigned DataLen = 1 + 2 + 4 + 4; +      clang::io::Emit8(Out, DataLen); +      return std::make_pair(StrLen + 1, DataLen); +    } +     +    void EmitKey(raw_ostream& Out, const char *path, unsigned KeyLen) { +      Out.write(path, KeyLen); +    } +     +    void EmitData(raw_ostream &Out, key_type_ref, +                  data_type_ref Data, unsigned DataLen) { +      using namespace clang::io; +      uint64_t Start = Out.tell(); (void)Start; +       +      unsigned char Flags = (Data.isImport << 5) +                          | (Data.isPragmaOnce << 4) +                          | (Data.DirInfo << 2) +                          | (Data.Resolved << 1) +                          | Data.IndexHeaderMapHeader; +      Emit8(Out, (uint8_t)Flags); +      Emit16(Out, (uint16_t) Data.NumIncludes); +       +      if (!Data.ControllingMacro) +        Emit32(Out, (uint32_t)Data.ControllingMacroID); +      else +        Emit32(Out, (uint32_t)Writer.getIdentifierRef(Data.ControllingMacro)); +       +      unsigned Offset = 0; +      if (!Data.Framework.empty()) { +        // If this header refers into a framework, save the framework name. +        llvm::StringMap<unsigned>::iterator Pos +          = FrameworkNameOffset.find(Data.Framework); +        if (Pos == FrameworkNameOffset.end()) { +          Offset = FrameworkStringData.size() + 1; +          FrameworkStringData.append(Data.Framework.begin(),  +                                     Data.Framework.end()); +          FrameworkStringData.push_back(0); +           +          FrameworkNameOffset[Data.Framework] = Offset; +        } else +          Offset = Pos->second; +      } +      Emit32(Out, Offset); +       +      assert(Out.tell() - Start == DataLen && "Wrong data length"); +    } +     +    const char *strings_begin() const { return FrameworkStringData.begin(); } +    const char *strings_end() const { return FrameworkStringData.end(); } +  }; +} // end anonymous namespace + +/// \brief Write the header search block for the list of files that  +/// +/// \param HS The header search structure to save. +/// +/// \param Chain Whether we're creating a chained AST file. +void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { +  SmallVector<const FileEntry *, 16> FilesByUID; +  HS.getFileMgr().GetUniqueIDMapping(FilesByUID); +   +  if (FilesByUID.size() > HS.header_file_size()) +    FilesByUID.resize(HS.header_file_size()); +   +  HeaderFileInfoTrait GeneratorTrait(*this, HS); +  OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator;   +  SmallVector<const char *, 4> SavedStrings; +  unsigned NumHeaderSearchEntries = 0; +  for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { +    const FileEntry *File = FilesByUID[UID]; +    if (!File) +      continue; + +    // Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo +    // from the external source if it was not provided already. +    const HeaderFileInfo &HFI = HS.getFileInfo(File); +    if (HFI.External && Chain) +      continue; + +    // Turn the file name into an absolute path, if it isn't already. +    const char *Filename = File->getName(); +    Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); +       +    // If we performed any translation on the file name at all, we need to +    // save this string, since the generator will refer to it later. +    if (Filename != File->getName()) { +      Filename = strdup(Filename); +      SavedStrings.push_back(Filename); +    } +     +    Generator.insert(Filename, HFI, GeneratorTrait); +    ++NumHeaderSearchEntries; +  } +   +  // Create the on-disk hash table in a buffer. +  SmallString<4096> TableData; +  uint32_t BucketOffset; +  { +    llvm::raw_svector_ostream Out(TableData); +    // Make sure that no bucket is at offset 0 +    clang::io::Emit32(Out, 0); +    BucketOffset = Generator.Emit(Out, GeneratorTrait); +  } + +  // Create a blob abbreviation +  using namespace llvm; +  BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +  unsigned TableAbbrev = Stream.EmitAbbrev(Abbrev); +   +  // Write the header search table +  RecordData Record; +  Record.push_back(HEADER_SEARCH_TABLE); +  Record.push_back(BucketOffset); +  Record.push_back(NumHeaderSearchEntries); +  Record.push_back(TableData.size()); +  TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end()); +  Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData.str()); +   +  // Free all of the strings we had to duplicate. +  for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I) +    free((void*)SavedStrings[I]); +} + +/// \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 ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, +                                        const Preprocessor &PP, +                                        StringRef isysroot) { +  RecordData Record; + +  // Enter the source manager block. +  Stream.EnterSubblock(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 SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream); + +  // Write out the source location entry table. We skip the first +  // entry, which is always the same dummy entry. +  std::vector<uint32_t> SLocEntryOffsets; +  // Write out the offsets of only source location file entries. +  // We will go through them in ASTReader::validateFileEntries(). +  std::vector<uint32_t> SLocFileEntryOffsets; +  RecordData PreloadSLocs; +  SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1); +  for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); +       I != N; ++I) { +    // Get this source location entry. +    const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(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()) { +      const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache(); +      if (Cache->OrigEntry) { +        Code = SM_SLOC_FILE_ENTRY; +        SLocFileEntryOffsets.push_back(Stream.GetCurrentBitNo()); +      } else +        Code = SM_SLOC_BUFFER_ENTRY; +    } else +      Code = SM_SLOC_EXPANSION_ENTRY; +    Record.clear(); +    Record.push_back(Code); + +    // Starting offset of this entry within this module, so skip the dummy. +    Record.push_back(SLoc->getOffset() - 2); +    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->OrigEntry) { +        assert(Content->OrigEntry == Content->ContentsEntry && +               "Writing to AST an overridden file is not supported"); + +        // 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->OrigEntry->getSize()); +        Record.push_back(Content->OrigEntry->getModificationTime()); +        Record.push_back(Content->BufferOverridden); +        Record.push_back(File.NumCreatedFIDs); +         +        FileDeclIDsTy::iterator FDI = FileDeclIDs.find(SLoc); +        if (FDI != FileDeclIDs.end()) { +          Record.push_back(FDI->second->FirstDeclIndex); +          Record.push_back(FDI->second->DeclIDs.size()); +        } else { +          Record.push_back(0); +          Record.push_back(0); +        } +         +        // Turn the file name into an absolute path, if it isn't already. +        const char *Filename = Content->OrigEntry->getName(); +        SmallString<128> FilePath(Filename); + +        // Ask the file manager to fixup the relative path for us. This will  +        // honor the working directory. +        SourceMgr.getFileManager().FixupRelativePath(FilePath); + +        // FIXME: This call to make_absolute shouldn't be necessary, the +        // call to FixupRelativePath should always return an absolute path. +        llvm::sys::fs::make_absolute(FilePath); +        Filename = FilePath.c_str(); + +        Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); +        Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename); +         +        if (Content->BufferOverridden) { +          Record.clear(); +          Record.push_back(SM_SLOC_BUFFER_BLOB); +          const llvm::MemoryBuffer *Buffer +            = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); +          Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, +                                    StringRef(Buffer->getBufferStart(), +                                              Buffer->getBufferSize() + 1));           +        } +      } 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, +                                  StringRef(Name, strlen(Name) + 1)); +        Record.clear(); +        Record.push_back(SM_SLOC_BUFFER_BLOB); +        Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, +                                  StringRef(Buffer->getBufferStart(), +                                                  Buffer->getBufferSize() + 1)); + +        if (strcmp(Name, "<built-in>") == 0) { +          PreloadSLocs.push_back(SLocEntryOffsets.size()); +        } +      } +    } else { +      // The source location entry is a macro expansion. +      const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion(); +      Record.push_back(Expansion.getSpellingLoc().getRawEncoding()); +      Record.push_back(Expansion.getExpansionLocStart().getRawEncoding()); +      Record.push_back(Expansion.isMacroArgExpansion() ? 0 +                             : Expansion.getExpansionLocEnd().getRawEncoding()); + +      // Compute the token length for this macro expansion. +      unsigned NextOffset = SourceMgr.getNextLocalOffset(); +      if (I + 1 != N) +        NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset(); +      Record.push_back(NextOffset - SLoc->getOffset() - 1); +      Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record); +    } +  } + +  Stream.ExitBlock(); + +  if (SLocEntryOffsets.empty()) +    return; + +  // Write the source-location offsets table into the AST block. This +  // table is used for lazily loading source-location information. +  using namespace llvm; +  BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets +  unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev); + +  Record.clear(); +  Record.push_back(SOURCE_LOCATION_OFFSETS); +  Record.push_back(SLocEntryOffsets.size()); +  Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy +  Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets)); + +  Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(FILE_SOURCE_LOCATION_OFFSETS)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets +  unsigned SLocFileOffsetsAbbrev = Stream.EmitAbbrev(Abbrev); + +  Record.clear(); +  Record.push_back(FILE_SOURCE_LOCATION_OFFSETS); +  Record.push_back(SLocFileEntryOffsets.size()); +  Stream.EmitRecordWithBlob(SLocFileOffsetsAbbrev, Record, +                            data(SLocFileEntryOffsets)); + +  // Write the source location entry preloads array, telling the AST +  // reader which source locations entries it should load eagerly. +  Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs); + +  // Write the line table. It depends on remapping working, so it must come +  // after the source location offsets. +  if (SourceMgr.hasLineTable()) { +    LineTableInfo &LineTable = SourceMgr.getLineTable(); + +    Record.clear(); +    // 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) { +      // Only emit entries for local files. +      if (L->first < 0) +        continue; + +      // 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(SOURCE_MANAGER_LINE_TABLE, Record); +  } +} + +//===----------------------------------------------------------------------===// +// Preprocessor Serialization +//===----------------------------------------------------------------------===// + +static int compareMacroDefinitions(const void *XPtr, const void *YPtr) { +  const std::pair<const IdentifierInfo *, MacroInfo *> &X = +    *(const std::pair<const IdentifierInfo *, MacroInfo *>*)XPtr; +  const std::pair<const IdentifierInfo *, MacroInfo *> &Y = +    *(const std::pair<const IdentifierInfo *, MacroInfo *>*)YPtr; +  return X.first->getName().compare(Y.first->getName()); +} + +/// \brief Writes the block containing the serialized form of the +/// preprocessor. +/// +void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { +  PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); +  if (PPRec) +    WritePreprocessorDetail(*PPRec); + +  RecordData Record; + +  // If the preprocessor __COUNTER__ value has been bumped, remember it. +  if (PP.getCounterValue() != 0) { +    Record.push_back(PP.getCounterValue()); +    Stream.EmitRecord(PP_COUNTER_VALUE, Record); +    Record.clear(); +  } + +  // Enter the preprocessor block. +  Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3); + +  // If the AST 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. + +  // Construct the list of macro definitions that need to be serialized. +  SmallVector<std::pair<const IdentifierInfo *, MacroInfo *>, 2>  +    MacrosToEmit; +  llvm::SmallPtrSet<const IdentifierInfo*, 4> MacroDefinitionsSeen; +  for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0),  +                                    E = PP.macro_end(Chain == 0); +       I != E; ++I) { +    const IdentifierInfo *Name = I->first; +    if (!IsModule || I->second->isPublic()) { +      MacroDefinitionsSeen.insert(Name); +      MacrosToEmit.push_back(std::make_pair(I->first, I->second)); +    } +  } +   +  // Sort the set of macro definitions that need to be serialized by the +  // name of the macro, to provide a stable ordering. +  llvm::array_pod_sort(MacrosToEmit.begin(), MacrosToEmit.end(),  +                       &compareMacroDefinitions); +   +  // Resolve any identifiers that defined macros at the time they were +  // deserialized, adding them to the list of macros to emit (if appropriate). +  for (unsigned I = 0, N = DeserializedMacroNames.size(); I != N; ++I) { +    IdentifierInfo *Name +      = const_cast<IdentifierInfo *>(DeserializedMacroNames[I]); +    if (Name->hasMacroDefinition() && MacroDefinitionsSeen.insert(Name)) +      MacrosToEmit.push_back(std::make_pair(Name, PP.getMacroInfo(Name))); +  } +   +  for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) { +    const IdentifierInfo *Name = MacrosToEmit[I].first; +    MacroInfo *MI = MacrosToEmit[I].second; +    if (!MI) +      continue; +     +    // Don't emit builtin macros like __LINE__ to the AST file unless they have +    // been redefined by the header (in which case they are not isBuiltinMacro). +    // Also skip macros from a AST file if we're chaining. + +    // FIXME: There is a (probably minor) optimization we could do here, if +    // the macro comes from the original PCH but the identifier comes from a +    // chained PCH, by storing the offset into the original PCH rather than +    // writing the macro definition a second time. +    if (MI->isBuiltinMacro() || +        (Chain &&  +         Name->isFromAST() && !Name->hasChangedSinceDeserialization() &&  +         MI->isFromAST() && !MI->hasChangedAfterLoad())) +      continue; + +    AddIdentifierRef(Name, Record); +    MacroOffsets[Name] = Stream.GetCurrentBitNo(); +    Record.push_back(MI->getDefinitionLoc().getRawEncoding()); +    Record.push_back(MI->isUsed()); +    Record.push_back(MI->isPublic()); +    AddSourceLocation(MI->getVisibilityLocation(), Record); +    unsigned Code; +    if (MI->isObjectLike()) { +      Code = PP_MACRO_OBJECT_LIKE; +    } else { +      Code = 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(MacroDefinitions[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(PP_TOKEN, Record); +      Record.clear(); +    } +    ++NumMacros; +  } +  Stream.ExitBlock(); +} + +void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { +  if (PPRec.local_begin() == PPRec.local_end()) +    return; + +  SmallVector<PPEntityOffset, 64> PreprocessedEntityOffsets; + +  // Enter the preprocessor block. +  Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3); + +  // If the preprocessor has a preprocessing record, emit it. +  unsigned NumPreprocessingRecords = 0; +  using namespace llvm; +   +  // Set up the abbreviation for  +  unsigned InclusionAbbrev = 0; +  { +    BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +    Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE)); +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +    InclusionAbbrev = Stream.EmitAbbrev(Abbrev); +  } +   +  unsigned FirstPreprocessorEntityID  +    = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0)  +    + NUM_PREDEF_PP_ENTITY_IDS; +  unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID; +  RecordData Record; +  for (PreprocessingRecord::iterator E = PPRec.local_begin(), +                                  EEnd = PPRec.local_end(); +       E != EEnd;  +       (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) { +    Record.clear(); + +    PreprocessedEntityOffsets.push_back(PPEntityOffset((*E)->getSourceRange(), +                                                     Stream.GetCurrentBitNo())); + +    if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) { +      // Record this macro definition's ID. +      MacroDefinitions[MD] = NextPreprocessorEntityID; +       +      AddIdentifierRef(MD->getName(), Record); +      Stream.EmitRecord(PPD_MACRO_DEFINITION, Record); +      continue; +    } + +    if (MacroExpansion *ME = dyn_cast<MacroExpansion>(*E)) { +      Record.push_back(ME->isBuiltinMacro()); +      if (ME->isBuiltinMacro()) +        AddIdentifierRef(ME->getName(), Record); +      else +        Record.push_back(MacroDefinitions[ME->getDefinition()]); +      Stream.EmitRecord(PPD_MACRO_EXPANSION, Record); +      continue; +    } + +    if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) { +      Record.push_back(PPD_INCLUSION_DIRECTIVE); +      Record.push_back(ID->getFileName().size()); +      Record.push_back(ID->wasInQuotes()); +      Record.push_back(static_cast<unsigned>(ID->getKind())); +      SmallString<64> Buffer; +      Buffer += ID->getFileName(); +      // Check that the FileEntry is not null because it was not resolved and +      // we create a PCH even with compiler errors. +      if (ID->getFile()) +        Buffer += ID->getFile()->getName(); +      Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer); +      continue; +    } +     +    llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter"); +  } +  Stream.ExitBlock(); + +  // Write the offsets table for the preprocessing record. +  if (NumPreprocessingRecords > 0) { +    assert(PreprocessedEntityOffsets.size() == NumPreprocessingRecords); + +    // Write the offsets table for identifier IDs. +    using namespace llvm; +    BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +    Abbrev->Add(BitCodeAbbrevOp(PPD_ENTITIES_OFFSETS)); +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first pp entity +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +    unsigned PPEOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + +    Record.clear(); +    Record.push_back(PPD_ENTITIES_OFFSETS); +    Record.push_back(FirstPreprocessorEntityID - NUM_PREDEF_PP_ENTITY_IDS); +    Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record, +                              data(PreprocessedEntityOffsets)); +  } +} + +unsigned ASTWriter::getSubmoduleID(Module *Mod) { +  llvm::DenseMap<Module *, unsigned>::iterator Known = SubmoduleIDs.find(Mod); +  if (Known != SubmoduleIDs.end()) +    return Known->second; +   +  return SubmoduleIDs[Mod] = NextSubmoduleID++; +} + +/// \brief Compute the number of modules within the given tree (including the +/// given module). +static unsigned getNumberOfModules(Module *Mod) { +  unsigned ChildModules = 0; +  for (Module::submodule_iterator Sub = Mod->submodule_begin(), +                               SubEnd = Mod->submodule_end(); +       Sub != SubEnd; ++Sub) +    ChildModules += getNumberOfModules(*Sub); +   +  return ChildModules + 1; +} + +void ASTWriter::WriteSubmodules(Module *WritingModule) { +  // Determine the dependencies of our module and each of it's submodules. +  // FIXME: This feels like it belongs somewhere else, but there are no +  // other consumers of this information. +  SourceManager &SrcMgr = PP->getSourceManager(); +  ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap(); +  for (ASTContext::import_iterator I = Context->local_import_begin(), +                                IEnd = Context->local_import_end(); +       I != IEnd; ++I) { +    if (Module *ImportedFrom +          = ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(),  +                                                         SrcMgr))) { +      ImportedFrom->Imports.push_back(I->getImportedModule()); +    } +  } +   +  // Enter the submodule description block. +  Stream.EnterSubblock(SUBMODULE_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); +   +  // Write the abbreviations needed for the submodules block. +  using namespace llvm; +  BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem   +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules... +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit... +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild... +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name +  unsigned DefinitionAbbrev = Stream.EmitAbbrev(Abbrev); + +  Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_HEADER)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name +  unsigned UmbrellaAbbrev = Stream.EmitAbbrev(Abbrev); + +  Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_HEADER)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name +  unsigned HeaderAbbrev = Stream.EmitAbbrev(Abbrev); + +  Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_DIR)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name +  unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(Abbrev); + +  Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature +  unsigned RequiresAbbrev = Stream.EmitAbbrev(Abbrev); + +  // Write the submodule metadata block. +  RecordData Record; +  Record.push_back(getNumberOfModules(WritingModule)); +  Record.push_back(FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS); +  Stream.EmitRecord(SUBMODULE_METADATA, Record); +   +  // Write all of the submodules. +  std::queue<Module *> Q; +  Q.push(WritingModule); +  while (!Q.empty()) { +    Module *Mod = Q.front(); +    Q.pop(); +    unsigned ID = getSubmoduleID(Mod); +     +    // Emit the definition of the block. +    Record.clear(); +    Record.push_back(SUBMODULE_DEFINITION); +    Record.push_back(ID); +    if (Mod->Parent) { +      assert(SubmoduleIDs[Mod->Parent] && "Submodule parent not written?"); +      Record.push_back(SubmoduleIDs[Mod->Parent]); +    } else { +      Record.push_back(0); +    } +    Record.push_back(Mod->IsFramework); +    Record.push_back(Mod->IsExplicit); +    Record.push_back(Mod->IsSystem); +    Record.push_back(Mod->InferSubmodules); +    Record.push_back(Mod->InferExplicitSubmodules); +    Record.push_back(Mod->InferExportWildcard); +    Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name); +     +    // Emit the requirements. +    for (unsigned I = 0, N = Mod->Requires.size(); I != N; ++I) { +      Record.clear(); +      Record.push_back(SUBMODULE_REQUIRES); +      Stream.EmitRecordWithBlob(RequiresAbbrev, Record, +                                Mod->Requires[I].data(), +                                Mod->Requires[I].size()); +    } + +    // Emit the umbrella header, if there is one. +    if (const FileEntry *UmbrellaHeader = Mod->getUmbrellaHeader()) { +      Record.clear(); +      Record.push_back(SUBMODULE_UMBRELLA_HEADER); +      Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record,  +                                UmbrellaHeader->getName()); +    } else if (const DirectoryEntry *UmbrellaDir = Mod->getUmbrellaDir()) { +      Record.clear(); +      Record.push_back(SUBMODULE_UMBRELLA_DIR); +      Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record,  +                                UmbrellaDir->getName());       +    } +     +    // Emit the headers. +    for (unsigned I = 0, N = Mod->Headers.size(); I != N; ++I) { +      Record.clear(); +      Record.push_back(SUBMODULE_HEADER); +      Stream.EmitRecordWithBlob(HeaderAbbrev, Record,  +                                Mod->Headers[I]->getName()); +    } + +    // Emit the imports.  +    if (!Mod->Imports.empty()) { +      Record.clear(); +      for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) { +        unsigned ImportedID = getSubmoduleID(Mod->Imports[I]); +        assert(ImportedID && "Unknown submodule!");                                            +        Record.push_back(ImportedID); +      } +      Stream.EmitRecord(SUBMODULE_IMPORTS, Record); +    } + +    // Emit the exports.  +    if (!Mod->Exports.empty()) { +      Record.clear(); +      for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) { +        if (Module *Exported = Mod->Exports[I].getPointer()) { +          unsigned ExportedID = SubmoduleIDs[Exported]; +          assert(ExportedID > 0 && "Unknown submodule ID?"); +          Record.push_back(ExportedID); +        } else { +          Record.push_back(0); +        } +         +        Record.push_back(Mod->Exports[I].getInt()); +      } +      Stream.EmitRecord(SUBMODULE_EXPORTS, Record); +    } +     +    // Queue up the submodules of this module. +    for (Module::submodule_iterator Sub = Mod->submodule_begin(), +                                 SubEnd = Mod->submodule_end(); +         Sub != SubEnd; ++Sub) +      Q.push(*Sub); +  } +   +  Stream.ExitBlock(); +   +  assert((NextSubmoduleID - FirstSubmoduleID +            == getNumberOfModules(WritingModule)) && "Wrong # of submodules"); +} + +serialization::SubmoduleID  +ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) { +  if (Loc.isInvalid() || !WritingModule) +    return 0; // No submodule +     +  // Find the module that owns this location. +  ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap(); +  Module *OwningMod  +    = ModMap.inferModuleFromLocation(FullSourceLoc(Loc,PP->getSourceManager())); +  if (!OwningMod) +    return 0; +   +  // Check whether this submodule is part of our own module. +  if (WritingModule != OwningMod && !OwningMod->isSubModuleOf(WritingModule)) +    return 0; +   +  return getSubmoduleID(OwningMod); +} + +void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag) { +  RecordData Record; +  for (DiagnosticsEngine::DiagStatePointsTy::const_iterator +         I = Diag.DiagStatePoints.begin(), E = Diag.DiagStatePoints.end(); +         I != E; ++I) { +    const DiagnosticsEngine::DiagStatePoint &point = *I;  +    if (point.Loc.isInvalid()) +      continue; + +    Record.push_back(point.Loc.getRawEncoding()); +    for (DiagnosticsEngine::DiagState::const_iterator +           I = point.State->begin(), E = point.State->end(); I != E; ++I) { +      if (I->second.isPragma()) { +        Record.push_back(I->first); +        Record.push_back(I->second.getMapping()); +      } +    } +    Record.push_back(-1); // mark the end of the diag/map pairs for this +                          // location. +  } + +  if (!Record.empty()) +    Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record); +} + +void ASTWriter::WriteCXXBaseSpecifiersOffsets() { +  if (CXXBaseSpecifiersOffsets.empty()) +    return; + +  RecordData Record; + +  // Create a blob abbreviation for the C++ base specifiers offsets. +  using namespace llvm; +     +  BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(CXX_BASE_SPECIFIER_OFFSETS)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +  unsigned BaseSpecifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); +   +  // Write the base specifier offsets table. +  Record.clear(); +  Record.push_back(CXX_BASE_SPECIFIER_OFFSETS); +  Record.push_back(CXXBaseSpecifiersOffsets.size()); +  Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record, +                            data(CXXBaseSpecifiersOffsets)); +} + +//===----------------------------------------------------------------------===// +// Type Serialization +//===----------------------------------------------------------------------===// + +/// \brief Write the representation of a type to the AST stream. +void ASTWriter::WriteType(QualType T) { +  TypeIdx &Idx = TypeIdxs[T]; +  if (Idx.getIndex() == 0) // we haven't seen this type before. +    Idx = TypeIdx(NextTypeID++); + +  assert(Idx.getIndex() >= FirstTypeID && "Re-writing a type from a prior AST"); + +  // Record the offset for this type. +  unsigned Index = Idx.getIndex() - 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. +  ASTTypeWriter W(*this, Record); + +  if (T.hasLocalNonFastQualifiers()) { +    Qualifiers Qs = T.getLocalQualifiers(); +    AddTypeRef(T.getLocalUnqualifiedType(), Record); +    Record.push_back(Qs.getAsOpaqueValue()); +    W.Code = 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 ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, +                                                 DeclContext *DC) { +  if (DC->decls_empty()) +    return 0; + +  uint64_t Offset = Stream.GetCurrentBitNo(); +  RecordData Record; +  Record.push_back(DECL_CONTEXT_LEXICAL); +  SmallVector<KindDeclIDPair, 64> Decls; +  for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); +         D != DEnd; ++D) +    Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D))); + +  ++NumLexicalDeclContexts; +  Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls)); +  return Offset; +} + +void ASTWriter::WriteTypeDeclOffsets() { +  using namespace llvm; +  RecordData Record; + +  // Write the type offsets array +  BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base type index +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block +  unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev); +  Record.clear(); +  Record.push_back(TYPE_OFFSET); +  Record.push_back(TypeOffsets.size()); +  Record.push_back(FirstTypeID - NUM_PREDEF_TYPE_IDS); +  Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, data(TypeOffsets)); + +  // Write the declaration offsets array +  Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base decl ID +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block +  unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev); +  Record.clear(); +  Record.push_back(DECL_OFFSET); +  Record.push_back(DeclOffsets.size()); +  Record.push_back(FirstDeclID - NUM_PREDEF_DECL_IDS); +  Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets)); +} + +void ASTWriter::WriteFileDeclIDsMap() { +  using namespace llvm; +  RecordData Record; + +  // Join the vectors of DeclIDs from all files. +  SmallVector<DeclID, 256> FileSortedIDs; +  for (FileDeclIDsTy::iterator +         FI = FileDeclIDs.begin(), FE = FileDeclIDs.end(); FI != FE; ++FI) { +    DeclIDInFileInfo &Info = *FI->second; +    Info.FirstDeclIndex = FileSortedIDs.size(); +    for (LocDeclIDsTy::iterator +           DI = Info.DeclIDs.begin(), DE = Info.DeclIDs.end(); DI != DE; ++DI) +      FileSortedIDs.push_back(DI->second); +  } + +  BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +  unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); +  Record.push_back(FILE_SORTED_DECLS); +  Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs)); +} + +//===----------------------------------------------------------------------===// +// Global Method Pool and Selector Serialization +//===----------------------------------------------------------------------===// + +namespace { +// Trait used for the on-disk hash table used in the method pool. +class ASTMethodPoolTrait { +  ASTWriter &Writer; + +public: +  typedef Selector key_type; +  typedef key_type key_type_ref; + +  struct data_type { +    SelectorID ID; +    ObjCMethodList Instance, Factory; +  }; +  typedef const data_type& data_type_ref; + +  explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) { } + +  static unsigned ComputeHash(Selector Sel) { +    return serialization::ComputeHash(Sel); +  } + +  std::pair<unsigned,unsigned> +    EmitKeyDataLength(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(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(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 ASTWriter::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<ASTMethodPoolTrait> Generator; +    ASTMethodPoolTrait Trait(*this); + +    // 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, SelectorID>::iterator +             I = SelectorIDs.begin(), E = SelectorIDs.end(); +         I != E; ++I) { +      Selector S = I->first; +      Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S); +      ASTMethodPoolTrait::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 AST 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->isFromASTFile()) +            changed = true; +        } +        for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method; +             M = M->Next) { +          if (!M->Method->isFromASTFile()) +            changed = true; +        } +        if (!changed) +          continue; +      } else if (Data.Instance.Method || Data.Factory.Method) { +        // A new method pool entry. +        ++NumTableEntries; +      } +      Generator.insert(S, Data, Trait); +    } + +    // Create the on-disk hash table in a buffer. +    SmallString<4096> MethodPool; +    uint32_t BucketOffset; +    { +      ASTMethodPoolTrait 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(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(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(SELECTOR_OFFSETS)); +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +    unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + +    // Write the selector offsets table. +    Record.clear(); +    Record.push_back(SELECTOR_OFFSETS); +    Record.push_back(SelectorOffsets.size()); +    Record.push_back(FirstSelectorID - NUM_PREDEF_SELECTOR_IDS); +    Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, +                              data(SelectorOffsets)); +  } +} + +/// \brief Write the selectors referenced in @selector expression into AST file. +void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { +  using namespace llvm; +  if (SemaRef.ReferencedSelectors.empty()) +    return; + +  RecordData Record; + +  // Note: this writes out all references even for a dependent AST. 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(REFERENCED_SELECTOR_POOL, Record); +} + +//===----------------------------------------------------------------------===// +// Identifier Table Serialization +//===----------------------------------------------------------------------===// + +namespace { +class ASTIdentifierTableTrait { +  ASTWriter &Writer; +  Preprocessor &PP; +  IdentifierResolver &IdResolver; +  bool IsModule; +   +  /// \brief Determines whether this is an "interesting" identifier +  /// that needs a full IdentifierInfo structure written into the hash +  /// table. +  bool isInterestingIdentifier(IdentifierInfo *II, MacroInfo *&Macro) { +    if (II->isPoisoned() || +        II->isExtensionToken() || +        II->getObjCOrBuiltinID() || +        II->hasRevertedTokenIDToIdentifier() || +        II->getFETokenInfo<void>()) +      return true; + +    return hasMacroDefinition(II, Macro); +  } +   +  bool hasMacroDefinition(IdentifierInfo *II, MacroInfo *&Macro) { +    if (!II->hasMacroDefinition()) +      return false; +     +    if (Macro || (Macro = PP.getMacroInfo(II))) +      return !Macro->isBuiltinMacro() && (!IsModule || Macro->isPublic()); +     +    return false;     +  } + +public: +  typedef IdentifierInfo* key_type; +  typedef key_type  key_type_ref; + +  typedef IdentID data_type; +  typedef data_type data_type_ref; + +  ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,  +                          IdentifierResolver &IdResolver, bool IsModule) +    : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule) { } + +  static unsigned ComputeHash(const IdentifierInfo* II) { +    return llvm::HashString(II->getName()); +  } + +  std::pair<unsigned,unsigned> +  EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { +    unsigned KeyLen = II->getLength() + 1; +    unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 +    MacroInfo *Macro = 0; +    if (isInterestingIdentifier(II, Macro)) { +      DataLen += 2; // 2 bytes for builtin ID, flags +      if (hasMacroDefinition(II, Macro)) +        DataLen += 8; +       +      for (IdentifierResolver::iterator D = IdResolver.begin(II), +                                     DEnd = IdResolver.end(); +           D != DEnd; ++D) +        DataLen += sizeof(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(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(raw_ostream& Out, IdentifierInfo* II, +                IdentID ID, unsigned) { +    MacroInfo *Macro = 0; +    if (!isInterestingIdentifier(II, Macro)) { +      clang::io::Emit32(Out, ID << 1); +      return; +    } + +    clang::io::Emit32(Out, (ID << 1) | 0x01); +    uint32_t Bits = 0; +    bool HasMacroDefinition = hasMacroDefinition(II, Macro); +    Bits = (uint32_t)II->getObjCOrBuiltinID(); +    assert((Bits & 0x7ff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); +    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)); +      clang::io::Emit32(Out,  +        Writer.inferSubmoduleIDFromLocation(Macro->getDefinitionLoc())); +    } +     +    // 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 the ASTReader 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. +    SmallVector<Decl *, 16> Decls(IdResolver.begin(II), +                                  IdResolver.end()); +    for (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 AST 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 ASTWriter::WriteIdentifierTable(Preprocessor &PP,  +                                     IdentifierResolver &IdResolver, +                                     bool IsModule) { +  using namespace llvm; + +  // Create and write out the blob that contains the identifier +  // strings. +  { +    OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; +    ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); + +    // 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 AST +    // 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 *, IdentID>::iterator +           ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end(); +         ID != IDEnd; ++ID) { +      assert(ID->first && "NULL identifier in identifier table"); +      if (!Chain || !ID->first->isFromAST() ||  +          ID->first->hasChangedSinceDeserialization()) +        Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second,  +                         Trait); +    } + +    // Create the on-disk hash table in a buffer. +    SmallString<4096> IdentifierTable; +    uint32_t BucketOffset; +    { +      ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); +      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(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(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(IDENTIFIER_OFFSET)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +  unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + +  RecordData Record; +  Record.push_back(IDENTIFIER_OFFSET); +  Record.push_back(IdentifierOffsets.size()); +  Record.push_back(FirstIdentID - NUM_PREDEF_IDENT_IDS); +  Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, +                            data(IdentifierOffsets)); +} + +//===----------------------------------------------------------------------===// +// DeclContext's Name Lookup Table Serialization +//===----------------------------------------------------------------------===// + +namespace { +// Trait used for the on-disk hash table used in the method pool. +class ASTDeclContextNameLookupTrait { +  ASTWriter &Writer; + +public: +  typedef DeclarationName key_type; +  typedef key_type key_type_ref; + +  typedef DeclContext::lookup_result data_type; +  typedef const data_type& data_type_ref; + +  explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { } + +  unsigned ComputeHash(DeclarationName Name) { +    llvm::FoldingSetNodeID ID; +    ID.AddInteger(Name.getNameKind()); + +    switch (Name.getNameKind()) { +    case DeclarationName::Identifier: +      ID.AddString(Name.getAsIdentifierInfo()->getName()); +      break; +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +      ID.AddInteger(serialization::ComputeHash(Name.getObjCSelector())); +      break; +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +      break; +    case DeclarationName::CXXOperatorName: +      ID.AddInteger(Name.getCXXOverloadedOperator()); +      break; +    case DeclarationName::CXXLiteralOperatorName: +      ID.AddString(Name.getCXXLiteralIdentifier()->getName()); +    case DeclarationName::CXXUsingDirective: +      break; +    } + +    return ID.ComputeHash(); +  } + +  std::pair<unsigned,unsigned> +    EmitKeyDataLength(raw_ostream& Out, DeclarationName Name, +                      data_type_ref Lookup) { +    unsigned KeyLen = 1; +    switch (Name.getNameKind()) { +    case DeclarationName::Identifier: +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +    case DeclarationName::CXXLiteralOperatorName: +      KeyLen += 4; +      break; +    case DeclarationName::CXXOperatorName: +      KeyLen += 1; +      break; +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +    case DeclarationName::CXXUsingDirective: +      break; +    } +    clang::io::Emit16(Out, KeyLen); + +    // 2 bytes for num of decls and 4 for each DeclID. +    unsigned DataLen = 2 + 4 * (Lookup.second - Lookup.first); +    clang::io::Emit16(Out, DataLen); + +    return std::make_pair(KeyLen, DataLen); +  } + +  void EmitKey(raw_ostream& Out, DeclarationName Name, unsigned) { +    using namespace clang::io; + +    assert(Name.getNameKind() < 0x100 && "Invalid name kind ?"); +    Emit8(Out, Name.getNameKind()); +    switch (Name.getNameKind()) { +    case DeclarationName::Identifier: +      Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo())); +      break; +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +      Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector())); +      break; +    case DeclarationName::CXXOperatorName: +      assert(Name.getCXXOverloadedOperator() < 0x100 && "Invalid operator ?"); +      Emit8(Out, Name.getCXXOverloadedOperator()); +      break; +    case DeclarationName::CXXLiteralOperatorName: +      Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier())); +      break; +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +    case DeclarationName::CXXUsingDirective: +      break; +    } +  } + +  void EmitData(raw_ostream& Out, key_type_ref, +                data_type Lookup, unsigned DataLen) { +    uint64_t Start = Out.tell(); (void)Start; +    clang::io::Emit16(Out, Lookup.second - Lookup.first); +    for (; Lookup.first != Lookup.second; ++Lookup.first) +      clang::io::Emit32(Out, Writer.GetDeclRef(*Lookup.first)); + +    assert(Out.tell() - Start == DataLen && "Data length is wrong"); +  } +}; +} // end anonymous namespace + +/// \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 +/// bitstream, or 0 if no block was written. +uint64_t ASTWriter::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.getLangOpts().CPlusPlus) +    return 0; + +  // 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(); +  StoredDeclsMap *Map = DC->buildLookup(); +  if (!Map || Map->empty()) +    return 0; + +  OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator; +  ASTDeclContextNameLookupTrait Trait(*this); + +  // Create the on-disk hash table representation. +  DeclarationName ConversionName; +  llvm::SmallVector<NamedDecl *, 4> ConversionDecls; +  for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); +       D != DEnd; ++D) { +    DeclarationName Name = D->first; +    DeclContext::lookup_result Result = D->second.getLookupResult(); +    if (Result.first != Result.second) { +      if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { +        // Hash all conversion function names to the same name. The actual +        // type information in conversion function name is not used in the +        // key (since such type information is not stable across different +        // modules), so the intended effect is to coalesce all of the conversion +        // functions under a single key. +        if (!ConversionName) +          ConversionName = Name; +        ConversionDecls.append(Result.first, Result.second); +        continue; +      } +       +      Generator.insert(Name, Result, Trait); +    } +  } + +  // Add the conversion functions +  if (!ConversionDecls.empty()) { +    Generator.insert(ConversionName,  +                     DeclContext::lookup_result(ConversionDecls.begin(), +                                                ConversionDecls.end()), +                     Trait); +  } +   +  // Create the on-disk hash table in a buffer. +  SmallString<4096> LookupTable; +  uint32_t BucketOffset; +  { +    llvm::raw_svector_ostream Out(LookupTable); +    // Make sure that no bucket is at offset 0 +    clang::io::Emit32(Out, 0); +    BucketOffset = Generator.Emit(Out, Trait); +  } + +  // Write the lookup table +  RecordData Record; +  Record.push_back(DECL_CONTEXT_VISIBLE); +  Record.push_back(BucketOffset); +  Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record, +                            LookupTable.str()); + +  Stream.EmitRecord(DECL_CONTEXT_VISIBLE, Record); +  ++NumVisibleDeclContexts; +  return Offset; +} + +/// \brief Write an UPDATE_VISIBLE block for the given context. +/// +/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing +/// DeclContext in a dependent AST file. As such, they only exist for the TU +/// (in C++), for namespaces, and for classes with forward-declared unscoped +/// enumeration members (in C++11). +void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { +  StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr()); +  if (!Map || Map->empty()) +    return; + +  OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator; +  ASTDeclContextNameLookupTrait Trait(*this); + +  // Create the hash table. +  for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); +       D != DEnd; ++D) { +    DeclarationName Name = D->first; +    DeclContext::lookup_result Result = D->second.getLookupResult(); +    // For any name that appears in this table, the results are complete, i.e. +    // they overwrite results from previous PCHs. Merging is always a mess. +    if (Result.first != Result.second) +      Generator.insert(Name, Result, Trait); +  } + +  // Create the on-disk hash table in a buffer. +  SmallString<4096> LookupTable; +  uint32_t BucketOffset; +  { +    llvm::raw_svector_ostream Out(LookupTable); +    // Make sure that no bucket is at offset 0 +    clang::io::Emit32(Out, 0); +    BucketOffset = Generator.Emit(Out, Trait); +  } + +  // Write the lookup table +  RecordData Record; +  Record.push_back(UPDATE_VISIBLE); +  Record.push_back(getDeclID(cast<Decl>(DC))); +  Record.push_back(BucketOffset); +  Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable.str()); +} + +/// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions. +void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) { +  RecordData Record; +  Record.push_back(Opts.fp_contract); +  Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record); +} + +/// \brief Write an OPENCL_EXTENSIONS block for the given OpenCLOptions. +void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { +  if (!SemaRef.Context.getLangOpts().OpenCL) +    return; + +  const OpenCLOptions &Opts = SemaRef.getOpenCLOptions(); +  RecordData Record; +#define OPENCLEXT(nm)  Record.push_back(Opts.nm); +#include "clang/Basic/OpenCLExtensions.def" +  Stream.EmitRecord(OPENCL_EXTENSIONS, Record); +} + +void ASTWriter::WriteRedeclarations() { +  RecordData LocalRedeclChains; +  SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap; + +  for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) { +    Decl *First = Redeclarations[I]; +    assert(First->getPreviousDecl() == 0 && "Not the first declaration?"); +     +    Decl *MostRecent = First->getMostRecentDecl(); +     +    // If we only have a single declaration, there is no point in storing +    // a redeclaration chain. +    if (First == MostRecent) +      continue; +     +    unsigned Offset = LocalRedeclChains.size(); +    unsigned Size = 0; +    LocalRedeclChains.push_back(0); // Placeholder for the size. +     +    // Collect the set of local redeclarations of this declaration. +    for (Decl *Prev = MostRecent; Prev != First;  +         Prev = Prev->getPreviousDecl()) {  +      if (!Prev->isFromASTFile()) { +        AddDeclRef(Prev, LocalRedeclChains); +        ++Size; +      } +    } +    LocalRedeclChains[Offset] = Size; +     +    // Reverse the set of local redeclarations, so that we store them in +    // order (since we found them in reverse order). +    std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end()); +     +    // Add the mapping from the first ID to the set of local declarations. +    LocalRedeclarationsInfo Info = { getDeclID(First), Offset }; +    LocalRedeclsMap.push_back(Info); +     +    assert(N == Redeclarations.size() &&  +           "Deserialized a declaration we shouldn't have"); +  } +   +  if (LocalRedeclChains.empty()) +    return; +   +  // Sort the local redeclarations map by the first declaration ID, +  // since the reader will be performing binary searches on this information. +  llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end()); +   +  // Emit the local redeclarations map. +  using namespace llvm; +  llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(LOCAL_REDECLARATIONS_MAP)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +  unsigned AbbrevID = Stream.EmitAbbrev(Abbrev); +   +  RecordData Record; +  Record.push_back(LOCAL_REDECLARATIONS_MAP); +  Record.push_back(LocalRedeclsMap.size()); +  Stream.EmitRecordWithBlob(AbbrevID, Record,  +    reinterpret_cast<char*>(LocalRedeclsMap.data()), +    LocalRedeclsMap.size() * sizeof(LocalRedeclarationsInfo)); + +  // Emit the redeclaration chains. +  Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains); +} + +void ASTWriter::WriteObjCCategories() { +  llvm::SmallVector<ObjCCategoriesInfo, 2> CategoriesMap; +  RecordData Categories; +   +  for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) { +    unsigned Size = 0; +    unsigned StartIndex = Categories.size(); +     +    ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I]; +     +    // Allocate space for the size. +    Categories.push_back(0); +     +    // Add the categories. +    for (ObjCCategoryDecl *Cat = Class->getCategoryList(); +         Cat; Cat = Cat->getNextClassCategory(), ++Size) { +      assert(getDeclID(Cat) != 0 && "Bogus category"); +      AddDeclRef(Cat, Categories); +    } +     +    // Update the size. +    Categories[StartIndex] = Size; +     +    // Record this interface -> category map. +    ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex }; +    CategoriesMap.push_back(CatInfo); +  } + +  // Sort the categories map by the definition ID, since the reader will be +  // performing binary searches on this information. +  llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end()); + +  // Emit the categories map. +  using namespace llvm; +  llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +  Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP)); +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +  unsigned AbbrevID = Stream.EmitAbbrev(Abbrev); +   +  RecordData Record; +  Record.push_back(OBJC_CATEGORIES_MAP); +  Record.push_back(CategoriesMap.size()); +  Stream.EmitRecordWithBlob(AbbrevID, Record,  +                            reinterpret_cast<char*>(CategoriesMap.data()), +                            CategoriesMap.size() * sizeof(ObjCCategoriesInfo)); +   +  // Emit the category lists. +  Stream.EmitRecord(OBJC_CATEGORIES, Categories); +} + +void ASTWriter::WriteMergedDecls() { +  if (!Chain || Chain->MergedDecls.empty()) +    return; +   +  RecordData Record; +  for (ASTReader::MergedDeclsMap::iterator I = Chain->MergedDecls.begin(), +                                        IEnd = Chain->MergedDecls.end(); +       I != IEnd; ++I) { +    DeclID CanonID = I->first->isFromASTFile()? I->first->getGlobalID() +                                              : getDeclID(I->first); +    assert(CanonID && "Merged declaration not known?"); +     +    Record.push_back(CanonID); +    Record.push_back(I->second.size()); +    Record.append(I->second.begin(), I->second.end()); +  } +  Stream.EmitRecord(MERGED_DECLARATIONS, Record); +} + +//===----------------------------------------------------------------------===// +// General Serialization Routines +//===----------------------------------------------------------------------===// + +/// \brief Write a record containing the given attributes. +void ASTWriter::WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record) { +  Record.push_back(Attrs.size()); +  for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){ +    const Attr * A = *i; +    Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs +    AddSourceRange(A->getRange(), Record); + +#include "clang/Serialization/AttrPCHWrite.inc" + +  } +} + +void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { +  Record.push_back(Str.size()); +  Record.insert(Record.end(), Str.begin(), Str.end()); +} + +void ASTWriter::AddVersionTuple(const VersionTuple &Version, +                                RecordDataImpl &Record) { +  Record.push_back(Version.getMajor()); +  if (llvm::Optional<unsigned> Minor = Version.getMinor()) +    Record.push_back(*Minor + 1); +  else +    Record.push_back(0); +  if (llvm::Optional<unsigned> Subminor = Version.getSubminor()) +    Record.push_back(*Subminor + 1); +  else +    Record.push_back(0); +} + +/// \brief Note that the identifier II occurs at the given offset +/// within the identifier table. +void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { +  IdentID ID = IdentifierIDs[II]; +  // Only store offsets new to this AST 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 ASTWriter::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; +} + +ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) +  : Stream(Stream), Context(0), PP(0), Chain(0), WritingModule(0), +    WritingAST(false), ASTHasCompilerErrors(false), +    FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), +    FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), +    FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID),  +    FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS),  +    NextSubmoduleID(FirstSubmoduleID), +    FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), +    CollectedStmts(&StmtsToEmit), +    NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), +    NumVisibleDeclContexts(0), +    NextCXXBaseSpecifiersID(1), +    DeclParmVarAbbrev(0), DeclContextLexicalAbbrev(0), +    DeclContextVisibleLookupAbbrev(0), UpdateVisibleAbbrev(0), +    DeclRefExprAbbrev(0), CharacterLiteralAbbrev(0), +    DeclRecordAbbrev(0), IntegerLiteralAbbrev(0), +    DeclTypedefAbbrev(0), +    DeclVarAbbrev(0), DeclFieldAbbrev(0), +    DeclEnumAbbrev(0), DeclObjCIvarAbbrev(0) +{ +} + +ASTWriter::~ASTWriter() { +  for (FileDeclIDsTy::iterator +         I = FileDeclIDs.begin(), E = FileDeclIDs.end(); I != E; ++I) +    delete I->second; +} + +void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, +                         const std::string &OutputFile, +                         Module *WritingModule, StringRef isysroot, +                         bool hasErrors) { +  WritingAST = true; +   +  ASTHasCompilerErrors = hasErrors; +   +  // 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(); + +  Context = &SemaRef.Context; +  PP = &SemaRef.PP; +  this->WritingModule = WritingModule; +  WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, WritingModule); +  Context = 0; +  PP = 0; +  this->WritingModule = 0; +   +  WritingAST = false; +} + +template<typename Vector> +static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, +                               ASTWriter::RecordData &Record) { +  for (typename Vector::iterator I = Vec.begin(0, true), E = Vec.end(); +       I != E; ++I)  { +    Writer.AddDeclRef(*I, Record); +  } +} + +void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, +                             StringRef isysroot, +                             const std::string &OutputFile,  +                             Module *WritingModule) { +  using namespace llvm; + +  // Make sure that the AST reader knows to finalize itself. +  if (Chain) +    Chain->finalizeForWriting(); +   +  ASTContext &Context = SemaRef.Context; +  Preprocessor &PP = SemaRef.PP; + +  // Set up predefined declaration IDs. +  DeclIDs[Context.getTranslationUnitDecl()] = PREDEF_DECL_TRANSLATION_UNIT_ID; +  if (Context.ObjCIdDecl) +    DeclIDs[Context.ObjCIdDecl] = PREDEF_DECL_OBJC_ID_ID; +  if (Context.ObjCSelDecl) +    DeclIDs[Context.ObjCSelDecl] = PREDEF_DECL_OBJC_SEL_ID; +  if (Context.ObjCClassDecl) +    DeclIDs[Context.ObjCClassDecl] = PREDEF_DECL_OBJC_CLASS_ID; +  if (Context.ObjCProtocolClassDecl) +    DeclIDs[Context.ObjCProtocolClassDecl] = PREDEF_DECL_OBJC_PROTOCOL_ID; +  if (Context.Int128Decl) +    DeclIDs[Context.Int128Decl] = PREDEF_DECL_INT_128_ID; +  if (Context.UInt128Decl) +    DeclIDs[Context.UInt128Decl] = PREDEF_DECL_UNSIGNED_INT_128_ID; +  if (Context.ObjCInstanceTypeDecl) +    DeclIDs[Context.ObjCInstanceTypeDecl] = PREDEF_DECL_OBJC_INSTANCETYPE_ID; +   +  if (!Chain) { +    // Make sure that we emit IdentifierInfos (and any attached +    // declarations) for builtins. We don't need to do this when we're +    // emitting chained PCH files, because all of the builtins will be +    // in the original PCH file. +    // FIXME: Modules won't like this at all. +    IdentifierTable &Table = PP.getIdentifierTable(); +    SmallVector<const char *, 32> BuiltinNames; +    Context.BuiltinInfo.GetBuiltinNames(BuiltinNames, +                                        Context.getLangOpts().NoBuiltin); +    for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I) +      getIdentifierRef(&Table.get(BuiltinNames[I])); +  } + +  // If there are any out-of-date identifiers, bring them up to date. +  if (ExternalPreprocessorSource *ExtSource = PP.getExternalSource()) { +    for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), +                                IDEnd = PP.getIdentifierTable().end(); +         ID != IDEnd; ++ID) +      if (ID->second->isOutOfDate()) +        ExtSource->updateOutOfDateIdentifier(*ID->second); +  } + +  // 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; +  AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); +   +  // Build a record containing all of the file scoped decls in this file. +  RecordData UnusedFileScopedDecls; +  AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls,  +                     UnusedFileScopedDecls); + +  // Build a record containing all of the delegating constructors we still need +  // to resolve. +  RecordData DelegatingCtorDecls; +  AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); + +  // Write the set of weak, undeclared identifiers. We always write the +  // entire table, since later PCH files in a PCH chain are only interested in +  // the results at the end of the chain. +  RecordData WeakUndeclaredIdentifiers; +  if (!SemaRef.WeakUndeclaredIdentifiers.empty()) { +    for (llvm::DenseMap<IdentifierInfo*,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 AST 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->isFromASTFile()) +      AddDeclRef(TD->second, LocallyScopedExternalDecls); +  } +   +  // Build a record containing all of the ext_vector declarations. +  RecordData ExtVectorDecls; +  AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); + +  // Build a record containing all of the VTable uses information. +  RecordData VTableUses; +  if (!SemaRef.VTableUses.empty()) { +    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; +  AddLazyVectorDecls(*this, SemaRef.DynamicClasses, DynamicClasses); + +  // Build a record containing all of pending implicit instantiations. +  RecordData PendingInstantiations; +  for (std::deque<Sema::PendingImplicitInstantiation>::iterator +         I = SemaRef.PendingInstantiations.begin(), +         N = SemaRef.PendingInstantiations.end(); I != N; ++I) { +    AddDeclRef(I->first, PendingInstantiations); +    AddSourceLocation(I->second, PendingInstantiations); +  } +  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); +  } + +  RecordData CUDASpecialDeclRefs; +  if (Context.getcudaConfigureCallDecl()) { +    AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs); +  } + +  // Build a record containing all of the known namespaces. +  RecordData KnownNamespaces; +  for (llvm::DenseMap<NamespaceDecl*, bool>::iterator  +            I = SemaRef.KnownNamespaces.begin(), +         IEnd = SemaRef.KnownNamespaces.end(); +       I != IEnd; ++I) { +    if (!I->second) +      AddDeclRef(I->first, KnownNamespaces); +  } +   +  // Write the remaining AST contents. +  RecordData Record; +  Stream.EnterSubblock(AST_BLOCK_ID, 5); +  WriteMetadata(Context, isysroot, OutputFile); +  WriteLanguageOptions(Context.getLangOpts()); +  if (StatCalls && isysroot.empty()) +    WriteStatCache(*StatCalls); + +  // Create a lexical update block containing all of the declarations in the +  // translation unit that do not come from other AST files. +  const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); +  SmallVector<KindDeclIDPair, 64> NewGlobalDecls; +  for (DeclContext::decl_iterator I = TU->noload_decls_begin(), +                                  E = TU->noload_decls_end(); +       I != E; ++I) { +    if (!(*I)->isFromASTFile()) +      NewGlobalDecls.push_back(std::make_pair((*I)->getKind(), GetDeclRef(*I))); +  } +   +  llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev(); +  Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); +  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); +  unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(Abv); +  Record.clear(); +  Record.push_back(TU_UPDATE_LEXICAL); +  Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, +                            data(NewGlobalDecls)); +   +  // And a visible updates block for the translation unit. +  Abv = new llvm::BitCodeAbbrev(); +  Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); +  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); +  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, 32)); +  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); +  UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv); +  WriteDeclContextVisibleUpdate(TU); +   +  // If the translation unit has an anonymous namespace, and we don't already +  // have an update block for it, write it as an update block. +  if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { +    ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; +    if (Record.empty()) { +      Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); +      Record.push_back(reinterpret_cast<uint64_t>(NS)); +    } +  } +   +  // Resolve any declaration pointers within the declaration updates block. +  ResolveDeclUpdatesBlocks(); +   +  // Form the record of special types. +  RecordData SpecialTypes; +  AddTypeRef(Context.getBuiltinVaListType(), SpecialTypes); +  AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); +  AddTypeRef(Context.getFILEType(), SpecialTypes); +  AddTypeRef(Context.getjmp_bufType(), SpecialTypes); +  AddTypeRef(Context.getsigjmp_bufType(), SpecialTypes); +  AddTypeRef(Context.ObjCIdRedefinitionType, SpecialTypes); +  AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes); +  AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); +  AddTypeRef(Context.getucontext_tType(), SpecialTypes); + +  // Keep writing types and declarations until all types and +  // declarations have been written. +  Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); +  WriteDeclsBlockAbbrevs(); +  for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(),  +                                  E = DeclsToRewrite.end();  +       I != E; ++I) +    DeclTypesToEmit.push(const_cast<Decl*>(*I)); +  while (!DeclTypesToEmit.empty()) { +    DeclOrType DOT = DeclTypesToEmit.front(); +    DeclTypesToEmit.pop(); +    if (DOT.isType()) +      WriteType(DOT.getType()); +    else +      WriteDecl(Context, DOT.getDecl()); +  } +  Stream.ExitBlock(); + +  WriteFileDeclIDsMap(); +  WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); +   +  if (Chain) { +    // Write the mapping information describing our module dependencies and how +    // each of those modules were mapped into our own offset/ID space, so that +    // the reader can build the appropriate mapping to its own offset/ID space. +    // The map consists solely of a blob with the following format: +    // *(module-name-len:i16 module-name:len*i8 +    //   source-location-offset:i32 +    //   identifier-id:i32 +    //   preprocessed-entity-id:i32 +    //   macro-definition-id:i32 +    //   submodule-id:i32 +    //   selector-id:i32 +    //   declaration-id:i32 +    //   c++-base-specifiers-id:i32 +    //   type-id:i32) +    //  +    llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); +    Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP)); +    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +    unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(Abbrev); +    SmallString<2048> Buffer; +    { +      llvm::raw_svector_ostream Out(Buffer); +      for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(), +                                           MEnd = Chain->ModuleMgr.end(); +           M != MEnd; ++M) { +        StringRef FileName = (*M)->FileName; +        io::Emit16(Out, FileName.size()); +        Out.write(FileName.data(), FileName.size()); +        io::Emit32(Out, (*M)->SLocEntryBaseOffset); +        io::Emit32(Out, (*M)->BaseIdentifierID); +        io::Emit32(Out, (*M)->BasePreprocessedEntityID); +        io::Emit32(Out, (*M)->BaseSubmoduleID); +        io::Emit32(Out, (*M)->BaseSelectorID); +        io::Emit32(Out, (*M)->BaseDeclID); +        io::Emit32(Out, (*M)->BaseTypeIndex); +      } +    } +    Record.clear(); +    Record.push_back(MODULE_OFFSET_MAP); +    Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record, +                              Buffer.data(), Buffer.size()); +  } +  WritePreprocessor(PP, WritingModule != 0); +  WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); +  WriteSelectors(SemaRef); +  WriteReferencedSelectorsPool(SemaRef); +  WriteIdentifierTable(PP, SemaRef.IdResolver, WritingModule != 0); +  WriteFPPragmaOptions(SemaRef.getFPOptions()); +  WriteOpenCLExtensions(SemaRef); + +  WriteTypeDeclOffsets(); +  WritePragmaDiagnosticMappings(Context.getDiagnostics()); + +  WriteCXXBaseSpecifiersOffsets(); +   +  // If we're emitting a module, write out the submodule information.   +  if (WritingModule) +    WriteSubmodules(WritingModule); + +  Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); + +  // Write the record containing external, unnamed definitions. +  if (!ExternalDefinitions.empty()) +    Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions); + +  // Write the record containing tentative definitions. +  if (!TentativeDefinitions.empty()) +    Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); + +  // Write the record containing unused file scoped decls. +  if (!UnusedFileScopedDecls.empty()) +    Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); + +  // Write the record containing weak undeclared identifiers. +  if (!WeakUndeclaredIdentifiers.empty()) +    Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, +                      WeakUndeclaredIdentifiers); + +  // Write the record containing locally-scoped external definitions. +  if (!LocallyScopedExternalDecls.empty()) +    Stream.EmitRecord(LOCALLY_SCOPED_EXTERNAL_DECLS, +                      LocallyScopedExternalDecls); + +  // Write the record containing ext_vector type names. +  if (!ExtVectorDecls.empty()) +    Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); + +  // Write the record containing VTable uses information. +  if (!VTableUses.empty()) +    Stream.EmitRecord(VTABLE_USES, VTableUses); + +  // Write the record containing dynamic classes declarations. +  if (!DynamicClasses.empty()) +    Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses); + +  // Write the record containing pending implicit instantiations. +  if (!PendingInstantiations.empty()) +    Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); + +  // Write the record containing declaration references of Sema. +  if (!SemaDeclRefs.empty()) +    Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); + +  // Write the record containing CUDA-specific declaration references. +  if (!CUDASpecialDeclRefs.empty()) +    Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); +   +  // Write the delegating constructors. +  if (!DelegatingCtorDecls.empty()) +    Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); + +  // Write the known namespaces. +  if (!KnownNamespaces.empty()) +    Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); +   +  // Write the visible updates to DeclContexts. +  for (llvm::SmallPtrSet<const DeclContext *, 16>::iterator +       I = UpdatedDeclContexts.begin(), +       E = UpdatedDeclContexts.end(); +       I != E; ++I) +    WriteDeclContextVisibleUpdate(*I); + +  if (!WritingModule) { +    // Write the submodules that were imported, if any. +    RecordData ImportedModules; +    for (ASTContext::import_iterator I = Context.local_import_begin(), +                                  IEnd = Context.local_import_end(); +         I != IEnd; ++I) { +      assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end()); +      ImportedModules.push_back(SubmoduleIDs[I->getImportedModule()]); +    } +    if (!ImportedModules.empty()) { +      // Sort module IDs. +      llvm::array_pod_sort(ImportedModules.begin(), ImportedModules.end()); +       +      // Unique module IDs. +      ImportedModules.erase(std::unique(ImportedModules.begin(),  +                                        ImportedModules.end()), +                            ImportedModules.end()); +       +      Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); +    } +  } +   +  WriteDeclUpdatesBlocks(); +  WriteDeclReplacementsBlock(); +  WriteMergedDecls(); +  WriteRedeclarations(); +  WriteObjCCategories(); +   +  // Some simple statistics +  Record.clear(); +  Record.push_back(NumStatements); +  Record.push_back(NumMacros); +  Record.push_back(NumLexicalDeclContexts); +  Record.push_back(NumVisibleDeclContexts); +  Stream.EmitRecord(STATISTICS, Record); +  Stream.ExitBlock(); +} + +/// \brief Go through the declaration update blocks and resolve declaration +/// pointers into declaration IDs. +void ASTWriter::ResolveDeclUpdatesBlocks() { +  for (DeclUpdateMap::iterator +       I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) { +    const Decl *D = I->first; +    UpdateRecord &URec = I->second; +     +    if (isRewritten(D)) +      continue; // The decl will be written completely + +    unsigned Idx = 0, N = URec.size(); +    while (Idx < N) { +      switch ((DeclUpdateKind)URec[Idx++]) { +      case UPD_CXX_ADDED_IMPLICIT_MEMBER: +      case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: +      case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: +        URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx])); +        ++Idx; +        break; +           +      case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: +        ++Idx; +        break; +      } +    } +  } +} + +void ASTWriter::WriteDeclUpdatesBlocks() { +  if (DeclUpdates.empty()) +    return; + +  RecordData OffsetsRecord; +  Stream.EnterSubblock(DECL_UPDATES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); +  for (DeclUpdateMap::iterator +         I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) { +    const Decl *D = I->first; +    UpdateRecord &URec = I->second; + +    if (isRewritten(D)) +      continue; // The decl will be written completely,no need to store updates. + +    uint64_t Offset = Stream.GetCurrentBitNo(); +    Stream.EmitRecord(DECL_UPDATES, URec); + +    OffsetsRecord.push_back(GetDeclRef(D)); +    OffsetsRecord.push_back(Offset); +  } +  Stream.ExitBlock(); +  Stream.EmitRecord(DECL_UPDATE_OFFSETS, OffsetsRecord); +} + +void ASTWriter::WriteDeclReplacementsBlock() { +  if (ReplacedDecls.empty()) +    return; + +  RecordData Record; +  for (SmallVector<ReplacedDeclInfo, 16>::iterator +           I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) { +    Record.push_back(I->ID); +    Record.push_back(I->Offset); +    Record.push_back(I->Loc); +  } +  Stream.EmitRecord(DECL_REPLACEMENTS, Record); +} + +void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) { +  Record.push_back(Loc.getRawEncoding()); +} + +void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) { +  AddSourceLocation(Range.getBegin(), Record); +  AddSourceLocation(Range.getEnd(), Record); +} + +void ASTWriter::AddAPInt(const llvm::APInt &Value, RecordDataImpl &Record) { +  Record.push_back(Value.getBitWidth()); +  const uint64_t *Words = Value.getRawData(); +  Record.append(Words, Words + Value.getNumWords()); +} + +void ASTWriter::AddAPSInt(const llvm::APSInt &Value, RecordDataImpl &Record) { +  Record.push_back(Value.isUnsigned()); +  AddAPInt(Value, Record); +} + +void ASTWriter::AddAPFloat(const llvm::APFloat &Value, RecordDataImpl &Record) { +  AddAPInt(Value.bitcastToAPInt(), Record); +} + +void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) { +  Record.push_back(getIdentifierRef(II)); +} + +IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { +  if (II == 0) +    return 0; + +  IdentID &ID = IdentifierIDs[II]; +  if (ID == 0) +    ID = NextIdentID++; +  return ID; +} + +void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { +  Record.push_back(getSelectorRef(SelRef)); +} + +SelectorID ASTWriter::getSelectorRef(Selector Sel) { +  if (Sel.getAsOpaquePtr() == 0) { +    return 0; +  } + +  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 ASTWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record) { +  AddDeclRef(Temp->getDestructor(), Record); +} + +void ASTWriter::AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases, +                                      CXXBaseSpecifier const *BasesEnd, +                                        RecordDataImpl &Record) { +  assert(Bases != BasesEnd && "Empty base-specifier sets are not recorded"); +  CXXBaseSpecifiersToWrite.push_back( +                                QueuedCXXBaseSpecifiers(NextCXXBaseSpecifiersID, +                                                        Bases, BasesEnd)); +  Record.push_back(NextCXXBaseSpecifiersID++); +} + +void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, +                                           const TemplateArgumentLocInfo &Arg, +                                           RecordDataImpl &Record) { +  switch (Kind) { +  case TemplateArgument::Expression: +    AddStmt(Arg.getAsExpr()); +    break; +  case TemplateArgument::Type: +    AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record); +    break; +  case TemplateArgument::Template: +    AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc(), Record); +    AddSourceLocation(Arg.getTemplateNameLoc(), Record); +    break; +  case TemplateArgument::TemplateExpansion: +    AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc(), Record); +    AddSourceLocation(Arg.getTemplateNameLoc(), Record); +    AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record); +    break; +  case TemplateArgument::Null: +  case TemplateArgument::Integral: +  case TemplateArgument::Declaration: +  case TemplateArgument::Pack: +    break; +  } +} + +void ASTWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, +                                       RecordDataImpl &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 ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo,  +                                  RecordDataImpl &Record) { +  if (TInfo == 0) { +    AddTypeRef(QualType(), Record); +    return; +  } + +  AddTypeLoc(TInfo->getTypeLoc(), Record); +} + +void ASTWriter::AddTypeLoc(TypeLoc TL, RecordDataImpl &Record) { +  AddTypeRef(TL.getType(), Record); + +  TypeLocWriter TLW(*this, Record); +  for (; !TL.isNull(); TL = TL.getNextTypeLoc()) +    TLW.Visit(TL); +} + +void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) { +  Record.push_back(GetOrCreateTypeID(T)); +} + +TypeID ASTWriter::GetOrCreateTypeID( QualType T) { +  return MakeTypeID(*Context, T, +              std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this)); +} + +TypeID ASTWriter::getTypeID(QualType T) const { +  return MakeTypeID(*Context, T, +              std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this)); +} + +TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) { +  if (T.isNull()) +    return TypeIdx(); +  assert(!T.getLocalFastQualifiers()); + +  TypeIdx &Idx = TypeIdxs[T]; +  if (Idx.getIndex() == 0) { +    // We haven't seen this type before. Assign it a new ID and put it +    // into the queue of types to emit. +    Idx = TypeIdx(NextTypeID++); +    DeclTypesToEmit.push(T); +  } +  return Idx; +} + +TypeIdx ASTWriter::getTypeIdx(QualType T) const { +  if (T.isNull()) +    return TypeIdx(); +  assert(!T.getLocalFastQualifiers()); + +  TypeIdxMap::const_iterator I = TypeIdxs.find(T); +  assert(I != TypeIdxs.end() && "Type not emitted!"); +  return I->second; +} + +void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { +  Record.push_back(GetDeclRef(D)); +} + +DeclID ASTWriter::GetDeclRef(const Decl *D) { +  assert(WritingAST && "Cannot request a declaration ID before AST writing"); +   +  if (D == 0) { +    return 0; +  } +   +  // If D comes from an AST file, its declaration ID is already known and +  // fixed. +  if (D->isFromASTFile()) +    return D->getGlobalID(); +   +  assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer"); +  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)); +  } + +  return ID; +} + +DeclID ASTWriter::getDeclID(const Decl *D) { +  if (D == 0) +    return 0; + +  // If D comes from an AST file, its declaration ID is already known and +  // fixed. +  if (D->isFromASTFile()) +    return D->getGlobalID(); + +  assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!"); +  return DeclIDs[D]; +} + +static inline bool compLocDecl(std::pair<unsigned, serialization::DeclID> L, +                               std::pair<unsigned, serialization::DeclID> R) { +  return L.first < R.first; +} + +void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { +  assert(ID); +  assert(D); + +  SourceLocation Loc = D->getLocation(); +  if (Loc.isInvalid()) +    return; + +  // We only keep track of the file-level declarations of each file. +  if (!D->getLexicalDeclContext()->isFileContext()) +    return; +  // FIXME: ParmVarDecls that are part of a function type of a parameter of +  // a function/objc method, should not have TU as lexical context. +  if (isa<ParmVarDecl>(D)) +    return; + +  SourceManager &SM = Context->getSourceManager(); +  SourceLocation FileLoc = SM.getFileLoc(Loc); +  assert(SM.isLocalSourceLocation(FileLoc)); +  FileID FID; +  unsigned Offset; +  llvm::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); +  if (FID.isInvalid()) +    return; +  const SrcMgr::SLocEntry *Entry = &SM.getSLocEntry(FID); +  assert(Entry->isFile()); + +  DeclIDInFileInfo *&Info = FileDeclIDs[Entry]; +  if (!Info) +    Info = new DeclIDInFileInfo(); + +  std::pair<unsigned, serialization::DeclID> LocDecl(Offset, ID); +  LocDeclIDsTy &Decls = Info->DeclIDs; + +  if (Decls.empty() || Decls.back().first <= Offset) { +    Decls.push_back(LocDecl); +    return; +  } + +  LocDeclIDsTy::iterator +    I = std::upper_bound(Decls.begin(), Decls.end(), LocDecl, compLocDecl); + +  Decls.insert(I, LocDecl); +} + +void ASTWriter::AddDeclarationName(DeclarationName Name, RecordDataImpl &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 ASTWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc, +                                     DeclarationName Name, RecordDataImpl &Record) { +  switch (Name.getNameKind()) { +  case DeclarationName::CXXConstructorName: +  case DeclarationName::CXXDestructorName: +  case DeclarationName::CXXConversionFunctionName: +    AddTypeSourceInfo(DNLoc.NamedType.TInfo, Record); +    break; + +  case DeclarationName::CXXOperatorName: +    AddSourceLocation( +       SourceLocation::getFromRawEncoding(DNLoc.CXXOperatorName.BeginOpNameLoc), +       Record); +    AddSourceLocation( +        SourceLocation::getFromRawEncoding(DNLoc.CXXOperatorName.EndOpNameLoc), +        Record); +    break; + +  case DeclarationName::CXXLiteralOperatorName: +    AddSourceLocation( +     SourceLocation::getFromRawEncoding(DNLoc.CXXLiteralOperatorName.OpNameLoc), +     Record); +    break; + +  case DeclarationName::Identifier: +  case DeclarationName::ObjCZeroArgSelector: +  case DeclarationName::ObjCOneArgSelector: +  case DeclarationName::ObjCMultiArgSelector: +  case DeclarationName::CXXUsingDirective: +    break; +  } +} + +void ASTWriter::AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo, +                                       RecordDataImpl &Record) { +  AddDeclarationName(NameInfo.getName(), Record); +  AddSourceLocation(NameInfo.getLoc(), Record); +  AddDeclarationNameLoc(NameInfo.getInfo(), NameInfo.getName(), Record); +} + +void ASTWriter::AddQualifierInfo(const QualifierInfo &Info, +                                 RecordDataImpl &Record) { +  AddNestedNameSpecifierLoc(Info.QualifierLoc, Record); +  Record.push_back(Info.NumTemplParamLists); +  for (unsigned i=0, e=Info.NumTemplParamLists; i != e; ++i) +    AddTemplateParameterList(Info.TemplParamLists[i], Record); +} + +void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, +                                       RecordDataImpl &Record) { +  // Nested name specifiers usually aren't too long. I think that 8 would +  // typically accommodate the vast majority. +  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::NamespaceAlias: +      AddDeclRef(NNS->getAsNamespaceAlias(), 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 ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, +                                          RecordDataImpl &Record) { +  // Nested name specifiers usually aren't too long. I think that 8 would +  // typically accommodate the vast majority. +  SmallVector<NestedNameSpecifierLoc , 8> NestedNames; + +  // Push each of the nested-name-specifiers'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.getNestedNameSpecifier()->getKind(); +    Record.push_back(Kind); +    switch (Kind) { +    case NestedNameSpecifier::Identifier: +      AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier(), Record); +      AddSourceRange(NNS.getLocalSourceRange(), Record); +      break; + +    case NestedNameSpecifier::Namespace: +      AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace(), Record); +      AddSourceRange(NNS.getLocalSourceRange(), Record); +      break; + +    case NestedNameSpecifier::NamespaceAlias: +      AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), Record); +      AddSourceRange(NNS.getLocalSourceRange(), Record); +      break; + +    case NestedNameSpecifier::TypeSpec: +    case NestedNameSpecifier::TypeSpecWithTemplate: +      Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); +      AddTypeLoc(NNS.getTypeLoc(), Record); +      AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); +      break; + +    case NestedNameSpecifier::Global: +      AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); +      break; +    } +  } +} + +void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &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; +  } + +  case TemplateName::SubstTemplateTemplateParm: { +    SubstTemplateTemplateParmStorage *subst +      = Name.getAsSubstTemplateTemplateParm(); +    AddDeclRef(subst->getParameter(), Record); +    AddTemplateName(subst->getReplacement(), Record); +    break; +  } +       +  case TemplateName::SubstTemplateTemplateParmPack: { +    SubstTemplateTemplateParmPackStorage *SubstPack +      = Name.getAsSubstTemplateTemplateParmPack(); +    AddDeclRef(SubstPack->getParameterPack(), Record); +    AddTemplateArgument(SubstPack->getArgumentPack(), Record); +    break; +  } +  } +} + +void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg, +                                    RecordDataImpl &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.getAsTemplateOrTemplatePattern(), Record); +    break; +  case TemplateArgument::TemplateExpansion: +    AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record); +    if (llvm::Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions()) +      Record.push_back(*NumExpansions + 1); +    else +      Record.push_back(0); +    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 +ASTWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams, +                                    RecordDataImpl &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 +ASTWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs, +                                   RecordDataImpl &Record) { +  assert(TemplateArgs && "No TemplateArgs!"); +  Record.push_back(TemplateArgs->size()); +  for (int i=0, e = TemplateArgs->size(); i != e; ++i) +    AddTemplateArgument(TemplateArgs->get(i), Record); +} + + +void +ASTWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &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 ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, +                                    RecordDataImpl &Record) { +  Record.push_back(Base.isVirtual()); +  Record.push_back(Base.isBaseOfClass()); +  Record.push_back(Base.getAccessSpecifierAsWritten()); +  Record.push_back(Base.getInheritConstructors()); +  AddTypeSourceInfo(Base.getTypeSourceInfo(), Record); +  AddSourceRange(Base.getSourceRange(), Record); +  AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()  +                                          : SourceLocation(), +                    Record); +} + +void ASTWriter::FlushCXXBaseSpecifiers() { +  RecordData Record; +  for (unsigned I = 0, N = CXXBaseSpecifiersToWrite.size(); I != N; ++I) { +    Record.clear(); +     +    // Record the offset of this base-specifier set. +    unsigned Index = CXXBaseSpecifiersToWrite[I].ID - 1; +    if (Index == CXXBaseSpecifiersOffsets.size()) +      CXXBaseSpecifiersOffsets.push_back(Stream.GetCurrentBitNo()); +    else { +      if (Index > CXXBaseSpecifiersOffsets.size()) +        CXXBaseSpecifiersOffsets.resize(Index + 1); +      CXXBaseSpecifiersOffsets[Index] = Stream.GetCurrentBitNo(); +    } + +    const CXXBaseSpecifier *B = CXXBaseSpecifiersToWrite[I].Bases, +                        *BEnd = CXXBaseSpecifiersToWrite[I].BasesEnd; +    Record.push_back(BEnd - B); +    for (; B != BEnd; ++B) +      AddCXXBaseSpecifier(*B, Record); +    Stream.EmitRecord(serialization::DECL_CXX_BASE_SPECIFIERS, Record); +     +    // Flush any expressions that were written as part of the base specifiers. +    FlushStmts(); +  } + +  CXXBaseSpecifiersToWrite.clear(); +} + +void ASTWriter::AddCXXCtorInitializers( +                             const CXXCtorInitializer * const *CtorInitializers, +                             unsigned NumCtorInitializers, +                             RecordDataImpl &Record) { +  Record.push_back(NumCtorInitializers); +  for (unsigned i=0; i != NumCtorInitializers; ++i) { +    const CXXCtorInitializer *Init = CtorInitializers[i]; + +    if (Init->isBaseInitializer()) { +      Record.push_back(CTOR_INITIALIZER_BASE); +      AddTypeSourceInfo(Init->getTypeSourceInfo(), Record); +      Record.push_back(Init->isBaseVirtual()); +    } else if (Init->isDelegatingInitializer()) { +      Record.push_back(CTOR_INITIALIZER_DELEGATING); +      AddTypeSourceInfo(Init->getTypeSourceInfo(), Record); +    } else if (Init->isMemberInitializer()){ +      Record.push_back(CTOR_INITIALIZER_MEMBER); +      AddDeclRef(Init->getMember(), Record); +    } else { +      Record.push_back(CTOR_INITIALIZER_INDIRECT_MEMBER); +      AddDeclRef(Init->getIndirectMember(), Record); +    } + +    AddSourceLocation(Init->getMemberLocation(), Record); +    AddStmt(Init->getInit()); +    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 ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) { +  assert(D->DefinitionData); +  struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; +  Record.push_back(Data.IsLambda); +  Record.push_back(Data.UserDeclaredConstructor); +  Record.push_back(Data.UserDeclaredCopyConstructor); +  Record.push_back(Data.UserDeclaredMoveConstructor); +  Record.push_back(Data.UserDeclaredCopyAssignment); +  Record.push_back(Data.UserDeclaredMoveAssignment); +  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.IsStandardLayout); +  Record.push_back(Data.HasNoNonEmptyBases); +  Record.push_back(Data.HasPrivateFields); +  Record.push_back(Data.HasProtectedFields); +  Record.push_back(Data.HasPublicFields); +  Record.push_back(Data.HasMutableFields); +  Record.push_back(Data.HasOnlyCMembers); +  Record.push_back(Data.HasTrivialDefaultConstructor); +  Record.push_back(Data.HasConstexprNonCopyMoveConstructor); +  Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr); +  Record.push_back(Data.DefaultedCopyConstructorIsConstexpr); +  Record.push_back(Data.DefaultedMoveConstructorIsConstexpr); +  Record.push_back(Data.HasConstexprDefaultConstructor); +  Record.push_back(Data.HasConstexprCopyConstructor); +  Record.push_back(Data.HasConstexprMoveConstructor); +  Record.push_back(Data.HasTrivialCopyConstructor); +  Record.push_back(Data.HasTrivialMoveConstructor); +  Record.push_back(Data.HasTrivialCopyAssignment); +  Record.push_back(Data.HasTrivialMoveAssignment); +  Record.push_back(Data.HasTrivialDestructor); +  Record.push_back(Data.HasIrrelevantDestructor); +  Record.push_back(Data.HasNonLiteralTypeFieldsOrBases); +  Record.push_back(Data.ComputedVisibleConversions); +  Record.push_back(Data.UserProvidedDefaultConstructor); +  Record.push_back(Data.DeclaredDefaultConstructor); +  Record.push_back(Data.DeclaredCopyConstructor); +  Record.push_back(Data.DeclaredMoveConstructor); +  Record.push_back(Data.DeclaredCopyAssignment); +  Record.push_back(Data.DeclaredMoveAssignment); +  Record.push_back(Data.DeclaredDestructor); +  Record.push_back(Data.FailedImplicitMoveConstructor); +  Record.push_back(Data.FailedImplicitMoveAssignment); +  // IsLambda bit is already saved. + +  Record.push_back(Data.NumBases); +  if (Data.NumBases > 0) +    AddCXXBaseSpecifiersRef(Data.getBases(), Data.getBases() + Data.NumBases,  +                            Record); +   +  // FIXME: Make VBases lazily computed when needed to avoid storing them. +  Record.push_back(Data.NumVBases); +  if (Data.NumVBases > 0) +    AddCXXBaseSpecifiersRef(Data.getVBases(), Data.getVBases() + Data.NumVBases,  +                            Record); + +  AddUnresolvedSet(Data.Conversions, Record); +  AddUnresolvedSet(Data.VisibleConversions, Record); +  // Data.Definition is the owning decl, no need to write it.  +  AddDeclRef(Data.FirstFriend, Record); +   +  // Add lambda-specific data. +  if (Data.IsLambda) { +    CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData(); +    Record.push_back(Lambda.Dependent); +    Record.push_back(Lambda.NumCaptures); +    Record.push_back(Lambda.NumExplicitCaptures); +    Record.push_back(Lambda.ManglingNumber); +    AddDeclRef(Lambda.ContextDecl, Record); +    for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { +      LambdaExpr::Capture &Capture = Lambda.Captures[I]; +      AddSourceLocation(Capture.getLocation(), Record); +      Record.push_back(Capture.isImplicit()); +      Record.push_back(Capture.getCaptureKind()); // FIXME: stable! +      VarDecl *Var = Capture.capturesVariable()? Capture.getCapturedVar() : 0; +      AddDeclRef(Var, Record); +      AddSourceLocation(Capture.isPackExpansion()? Capture.getEllipsisLoc() +                                                 : SourceLocation(),  +                        Record); +    } +  } +} + +void ASTWriter::ReaderInitialized(ASTReader *Reader) { +  assert(Reader && "Cannot remove chain"); +  assert((!Chain || Chain == Reader) && "Cannot replace chain"); +  assert(FirstDeclID == NextDeclID && +         FirstTypeID == NextTypeID && +         FirstIdentID == NextIdentID && +         FirstSubmoduleID == NextSubmoduleID && +         FirstSelectorID == NextSelectorID && +         "Setting chain after writing has started."); + +  Chain = Reader; + +  FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); +  FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); +  FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); +  FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); +  FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); +  NextDeclID = FirstDeclID; +  NextTypeID = FirstTypeID; +  NextIdentID = FirstIdentID; +  NextSelectorID = FirstSelectorID; +  NextSubmoduleID = FirstSubmoduleID; +} + +void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { +  IdentifierIDs[II] = ID; +  if (II->hasMacroDefinition()) +    DeserializedMacroNames.push_back(II); +} + +void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { +  // Always take the highest-numbered type index. This copes with an interesting +  // case for chained AST writing where we schedule writing the type and then, +  // later, deserialize the type from another AST. In this case, we want to +  // keep the higher-numbered entry so that we can properly write it out to +  // the AST file. +  TypeIdx &StoredIdx = TypeIdxs[T]; +  if (Idx.getIndex() >= StoredIdx.getIndex()) +    StoredIdx = Idx; +} + +void ASTWriter::SelectorRead(SelectorID ID, Selector S) { +  SelectorIDs[S] = ID; +} + +void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, +                                    MacroDefinition *MD) { +  assert(MacroDefinitions.find(MD) == MacroDefinitions.end()); +  MacroDefinitions[MD] = ID; +} + +void ASTWriter::MacroVisible(IdentifierInfo *II) { +  DeserializedMacroNames.push_back(II); +} + +void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { +  assert(SubmoduleIDs.find(Mod) == SubmoduleIDs.end()); +  SubmoduleIDs[Mod] = ID; +} + +void ASTWriter::CompletedTagDefinition(const TagDecl *D) { +  assert(D->isCompleteDefinition()); +  assert(!WritingAST && "Already writing the AST!"); +  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { +    // We are interested when a PCH decl is modified. +    if (RD->isFromASTFile()) { +      // A forward reference was mutated into a definition. Rewrite it. +      // FIXME: This happens during template instantiation, should we +      // have created a new definition decl instead ? +      RewriteDecl(RD); +    } +  } +} +void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { +  assert(!WritingAST && "Already writing the AST!"); + +  // TU and namespaces are handled elsewhere. +  if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC)) +    return; + +  if (!(!D->isFromASTFile() && cast<Decl>(DC)->isFromASTFile())) +    return; // Not a source decl added to a DeclContext from PCH. + +  AddUpdatedDeclContext(DC); +} + +void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { +  assert(!WritingAST && "Already writing the AST!"); +  assert(D->isImplicit()); +  if (!(!D->isFromASTFile() && RD->isFromASTFile())) +    return; // Not a source member added to a class from PCH. +  if (!isa<CXXMethodDecl>(D)) +    return; // We are interested in lazily declared implicit methods. + +  // A decl coming from PCH was modified. +  assert(RD->isCompleteDefinition()); +  UpdateRecord &Record = DeclUpdates[RD]; +  Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER); +  Record.push_back(reinterpret_cast<uint64_t>(D)); +} + +void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, +                                     const ClassTemplateSpecializationDecl *D) { +  // The specializations set is kept in the canonical template. +  assert(!WritingAST && "Already writing the AST!"); +  TD = TD->getCanonicalDecl(); +  if (!(!D->isFromASTFile() && TD->isFromASTFile())) +    return; // Not a source specialization added to a template from PCH. + +  UpdateRecord &Record = DeclUpdates[TD]; +  Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION); +  Record.push_back(reinterpret_cast<uint64_t>(D)); +} + +void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, +                                               const FunctionDecl *D) { +  // The specializations set is kept in the canonical template. +  assert(!WritingAST && "Already writing the AST!"); +  TD = TD->getCanonicalDecl(); +  if (!(!D->isFromASTFile() && TD->isFromASTFile())) +    return; // Not a source specialization added to a template from PCH. + +  UpdateRecord &Record = DeclUpdates[TD]; +  Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION); +  Record.push_back(reinterpret_cast<uint64_t>(D)); +} + +void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { +  assert(!WritingAST && "Already writing the AST!"); +  if (!D->isFromASTFile()) +    return; // Declaration not imported from PCH. + +  // Implicit decl from a PCH was defined. +  // FIXME: Should implicit definition be a separate FunctionDecl? +  RewriteDecl(D); +} + +void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { +  assert(!WritingAST && "Already writing the AST!"); +  if (!D->isFromASTFile()) +    return; + +  // Since the actual instantiation is delayed, this really means that we need +  // to update the instantiation location. +  UpdateRecord &Record = DeclUpdates[D]; +  Record.push_back(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER); +  AddSourceLocation( +      D->getMemberSpecializationInfo()->getPointOfInstantiation(), Record); +} + +void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, +                                             const ObjCInterfaceDecl *IFD) { +  assert(!WritingAST && "Already writing the AST!"); +  if (!IFD->isFromASTFile()) +    return; // Declaration not imported from PCH. +   +  assert(IFD->getDefinition() && "Category on a class without a definition?"); +  ObjCClassesWithCategories.insert( +    const_cast<ObjCInterfaceDecl *>(IFD->getDefinition())); +} + + +void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, +                                          const ObjCPropertyDecl *OrigProp, +                                          const ObjCCategoryDecl *ClassExt) { +  const ObjCInterfaceDecl *D = ClassExt->getClassInterface(); +  if (!D) +    return; + +  assert(!WritingAST && "Already writing the AST!"); +  if (!D->isFromASTFile()) +    return; // Declaration not imported from PCH. + +  RewriteDecl(D); +} diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp new file mode 100644 index 0000000..1ee3ac4 --- /dev/null +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -0,0 +1,1728 @@ +//===--- ASTWriterDecl.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/ASTWriter.h" +#include "clang/Serialization/ASTReader.h" +#include "ASTCommon.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/DeclContextInternals.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Support/ErrorHandling.h" +using namespace clang; +using namespace serialization; + +//===----------------------------------------------------------------------===// +// Declaration serialization +//===----------------------------------------------------------------------===// + +namespace clang { +  class ASTDeclWriter : public DeclVisitor<ASTDeclWriter, void> { + +    ASTWriter &Writer; +    ASTContext &Context; +    typedef ASTWriter::RecordData RecordData; +    RecordData &Record; + +  public: +    serialization::DeclCode Code; +    unsigned AbbrevToUse; + +    ASTDeclWriter(ASTWriter &Writer, ASTContext &Context, 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 VisitLabelDecl(LabelDecl *LD); +    void VisitNamespaceDecl(NamespaceDecl *D); +    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); +    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); +    void VisitTypeDecl(TypeDecl *D); +    void VisitTypedefNameDecl(TypedefNameDecl *D); +    void VisitTypedefDecl(TypedefDecl *D); +    void VisitTypeAliasDecl(TypeAliasDecl *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 VisitClassScopeFunctionSpecializationDecl( +                                       ClassScopeFunctionSpecializationDecl *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 VisitIndirectFieldDecl(IndirectFieldDecl *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 VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); +    void VisitUsingDecl(UsingDecl *D); +    void VisitUsingShadowDecl(UsingShadowDecl *D); +    void VisitLinkageSpecDecl(LinkageSpecDecl *D); +    void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); +    void VisitImportDecl(ImportDecl *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 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 ASTDeclWriter::Visit(Decl *D) { +  DeclVisitor<ASTDeclWriter>::Visit(D); + +  // Source locations require array (variable-length) abbreviations.  The +  // abbreviation infrastructure requires that arrays are encoded last, so +  // we handle it here in the case of those classes derived from DeclaratorDecl +  if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)){ +    Writer.AddTypeSourceInfo(DD->getTypeSourceInfo(), Record); +  } + +  // 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 AST, we'll just lazily set the offset.  +  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +    Record.push_back(FD->doesThisDeclarationHaveABody()); +    if (FD->doesThisDeclarationHaveABody()) +      Writer.AddStmt(FD->getBody()); +  } +} + +void ASTDeclWriter::VisitDecl(Decl *D) { +  Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record); +  Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record); +  Record.push_back(D->isInvalidDecl()); +  Record.push_back(D->hasAttrs()); +  if (D->hasAttrs()) +    Writer.WriteAttributes(D->getAttrs(), Record); +  Record.push_back(D->isImplicit()); +  Record.push_back(D->isUsed(false)); +  Record.push_back(D->isReferenced()); +  Record.push_back(D->isTopLevelDeclInObjCContainer()); +  Record.push_back(D->getAccess()); +  Record.push_back(D->isModulePrivate()); +  Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation())); +} + +void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { +  llvm_unreachable("Translation units aren't directly serialized"); +} + +void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { +  VisitDecl(D); +  Writer.AddDeclarationName(D->getDeclName(), Record); +} + +void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { +  VisitNamedDecl(D); +  Writer.AddSourceLocation(D->getLocStart(), Record); +  Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); +} + +void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) { +  VisitRedeclarable(D); +  VisitTypeDecl(D); +  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);   +} + +void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { +  VisitTypedefNameDecl(D); +  if (!D->hasAttrs() && +      !D->isImplicit() && +      !D->isUsed(false) && +      D->getFirstDeclaration() == D->getMostRecentDecl() && +      !D->isInvalidDecl() && +      !D->isReferenced() && +      !D->isTopLevelDeclInObjCContainer() && +      D->getAccess() == AS_none && +      !D->isModulePrivate() && +      D->getDeclName().getNameKind() == DeclarationName::Identifier) +    AbbrevToUse = Writer.getDeclTypedefAbbrev(); + +  Code = serialization::DECL_TYPEDEF; +} + +void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { +  VisitTypedefNameDecl(D); +  Code = serialization::DECL_TYPEALIAS; +} + +void ASTDeclWriter::VisitTagDecl(TagDecl *D) { +  VisitRedeclarable(D); +  VisitTypeDecl(D); +  Record.push_back(D->getIdentifierNamespace()); +  Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding +  Record.push_back(D->isCompleteDefinition()); +  Record.push_back(D->isEmbeddedInDeclarator()); +  Record.push_back(D->isFreeStanding()); +  Writer.AddSourceLocation(D->getRBraceLoc(), Record); +  Record.push_back(D->hasExtInfo()); +  if (D->hasExtInfo()) +    Writer.AddQualifierInfo(*D->getExtInfo(), Record); +  else +    Writer.AddDeclRef(D->getTypedefNameForAnonDecl(), Record); +} + +void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { +  VisitTagDecl(D); +  Writer.AddTypeSourceInfo(D->getIntegerTypeSourceInfo(), Record); +  if (!D->getIntegerTypeSourceInfo()) +    Writer.AddTypeRef(D->getIntegerType(), Record); +  Writer.AddTypeRef(D->getPromotionType(), Record); +  Record.push_back(D->getNumPositiveBits()); +  Record.push_back(D->getNumNegativeBits()); +  Record.push_back(D->isScoped()); +  Record.push_back(D->isScopedUsingClassTag()); +  Record.push_back(D->isFixed()); +  if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) { +    Writer.AddDeclRef(MemberInfo->getInstantiatedFrom(), Record); +    Record.push_back(MemberInfo->getTemplateSpecializationKind()); +    Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record); +  } else { +    Writer.AddDeclRef(0, Record); +  } + +  if (!D->hasAttrs() && +      !D->isImplicit() && +      !D->isUsed(false) && +      !D->hasExtInfo() && +      D->getFirstDeclaration() == D->getMostRecentDecl() && +      !D->isInvalidDecl() && +      !D->isReferenced() && +      !D->isTopLevelDeclInObjCContainer() && +      D->getAccess() == AS_none && +      !D->isModulePrivate() && +      !CXXRecordDecl::classofKind(D->getKind()) && +      !D->getIntegerTypeSourceInfo() && +      D->getDeclName().getNameKind() == DeclarationName::Identifier) +    AbbrevToUse = Writer.getDeclEnumAbbrev(); + +  Code = serialization::DECL_ENUM; +} + +void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { +  VisitTagDecl(D); +  Record.push_back(D->hasFlexibleArrayMember()); +  Record.push_back(D->isAnonymousStructOrUnion()); +  Record.push_back(D->hasObjectMember()); + +  if (!D->hasAttrs() && +      !D->isImplicit() && +      !D->isUsed(false) && +      !D->hasExtInfo() && +      D->getFirstDeclaration() == D->getMostRecentDecl() && +      !D->isInvalidDecl() && +      !D->isReferenced() && +      !D->isTopLevelDeclInObjCContainer() && +      D->getAccess() == AS_none && +      !D->isModulePrivate() && +      !CXXRecordDecl::classofKind(D->getKind()) && +      D->getDeclName().getNameKind() == DeclarationName::Identifier) +    AbbrevToUse = Writer.getDeclRecordAbbrev(); + +  Code = serialization::DECL_RECORD; +} + +void ASTDeclWriter::VisitValueDecl(ValueDecl *D) { +  VisitNamedDecl(D); +  Writer.AddTypeRef(D->getType(), Record); +} + +void ASTDeclWriter::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 = serialization::DECL_ENUM_CONSTANT; +} + +void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { +  VisitValueDecl(D); +  Writer.AddSourceLocation(D->getInnerLocStart(), Record); +  Record.push_back(D->hasExtInfo()); +  if (D->hasExtInfo()) +    Writer.AddQualifierInfo(*D->getExtInfo(), Record); +} + +void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { +  VisitRedeclarable(D); +  VisitDeclaratorDecl(D); + +  Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); +  Record.push_back(D->getIdentifierNamespace()); +   +  // FunctionDecl's body is handled last at ASTWriterDecl::Visit, +  // after everything else is written. +   +  Record.push_back(D->getStorageClass()); // FIXME: stable encoding +  Record.push_back(D->getStorageClassAsWritten()); +  Record.push_back(D->IsInline); +  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->isDeletedAsWritten()); +  Record.push_back(D->isTrivial()); +  Record.push_back(D->isDefaulted()); +  Record.push_back(D->isExplicitlyDefaulted()); +  Record.push_back(D->hasImplicitReturnZero()); +  Record.push_back(D->isConstexpr()); +  Writer.AddSourceLocation(D->getLocEnd(), Record); + +  Record.push_back(D->getTemplatedKind()); +  switch (D->getTemplatedKind()) { +  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(); +    Writer.AddDeclRef(FTSInfo->getTemplate(), 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->NumTemplateArgs); +      for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs; +             i!=e; ++i) +        Writer.AddTemplateArgumentLoc((*FTSInfo->TemplateArgumentsAsWritten)[i], +                                      Record); +      Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->LAngleLoc, +                               Record); +      Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->RAngleLoc, +                               Record); +    } +     +    Writer.AddSourceLocation(FTSInfo->getPointOfInstantiation(), Record); + +    if (D->isCanonicalDecl()) { +      // Write the template that contains the specializations set. We will +      // add a FunctionTemplateSpecializationInfo to it when reading. +      Writer.AddDeclRef(FTSInfo->getTemplate()->getCanonicalDecl(), 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; +  } +  } + +  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 = serialization::DECL_FUNCTION; +} + +void ASTDeclWriter::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()); + +  Record.push_back(D->IsRedeclaration); +  Record.push_back(D->HasRedeclaration); +  if (D->HasRedeclaration) { +    assert(Context.getObjCMethodRedeclaration(D)); +    Writer.AddDeclRef(Context.getObjCMethodRedeclaration(D), Record); +  } + +  // 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->hasRelatedResultType()); +  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); + +  Record.push_back(D->SelLocsKind); +  unsigned NumStoredSelLocs = D->getNumStoredSelLocs(); +  SourceLocation *SelLocs = D->getStoredSelLocs(); +  Record.push_back(NumStoredSelLocs); +  for (unsigned i = 0; i != NumStoredSelLocs; ++i) +    Writer.AddSourceLocation(SelLocs[i], Record); + +  Code = serialization::DECL_OBJC_METHOD; +} + +void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { +  VisitNamedDecl(D); +  Writer.AddSourceLocation(D->getAtStartLoc(), Record); +  Writer.AddSourceRange(D->getAtEndRange(), Record); +  // Abstract class (no need to define a stable serialization::DECL code). +} + +void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { +  VisitRedeclarable(D); +  VisitObjCContainerDecl(D); +  Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); + +  Record.push_back(D->isThisDeclarationADefinition()); +  if (D->isThisDeclarationADefinition()) { +    // Write the DefinitionData +    ObjCInterfaceDecl::DefinitionData &Data = D->data(); +     +    Writer.AddDeclRef(D->getSuperClass(), Record); +    Writer.AddSourceLocation(D->getSuperClassLoc(), Record); +    Writer.AddSourceLocation(D->getEndOfDefinitionLoc(), Record); + +    // Write out the protocols that are directly referenced by the @interface. +    Record.push_back(Data.ReferencedProtocols.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); +     +    // Write out the protocols that are transitively referenced. +    Record.push_back(Data.AllReferencedProtocols.size()); +    for (ObjCList<ObjCProtocolDecl>::iterator +              P = Data.AllReferencedProtocols.begin(), +           PEnd = Data.AllReferencedProtocols.end(); +         P != PEnd; ++P) +      Writer.AddDeclRef(*P, Record); +     +    if (ObjCCategoryDecl *Cat = D->getCategoryList()) { +      // Ensure that we write out the set of categories for this class. +      Writer.ObjCClassesWithCategories.insert(D); +       +      // Make sure that the categories get serialized. +      for (; Cat; Cat = Cat->getNextClassCategory()) +        (void)Writer.GetDeclRef(Cat); +    } +  }   +   +  Code = serialization::DECL_OBJC_INTERFACE; +} + +void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { +  VisitFieldDecl(D); +  // FIXME: stable encoding for @public/@private/@protected/@package +  Record.push_back(D->getAccessControl()); +  Record.push_back(D->getSynthesize()); + +  if (!D->hasAttrs() && +      !D->isImplicit() && +      !D->isUsed(false) && +      !D->isInvalidDecl() && +      !D->isReferenced() && +      !D->isModulePrivate() && +      !D->getBitWidth() && +      !D->hasExtInfo() && +      D->getDeclName()) +    AbbrevToUse = Writer.getDeclObjCIvarAbbrev(); + +  Code = serialization::DECL_OBJC_IVAR; +} + +void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { +  VisitRedeclarable(D); +  VisitObjCContainerDecl(D); +   +  Record.push_back(D->isThisDeclarationADefinition()); +  if (D->isThisDeclarationADefinition()) { +    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 = serialization::DECL_OBJC_PROTOCOL; +} + +void ASTDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { +  VisitFieldDecl(D); +  Code = serialization::DECL_OBJC_AT_DEFS_FIELD; +} + +void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { +  VisitObjCContainerDecl(D); +  Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); +  Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record); +  Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); +  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); +  Record.push_back(D->hasSynthBitfield()); +  Code = serialization::DECL_OBJC_CATEGORY; +} + +void ASTDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) { +  VisitNamedDecl(D); +  Writer.AddDeclRef(D->getClassInterface(), Record); +  Code = serialization::DECL_OBJC_COMPATIBLE_ALIAS; +} + +void ASTDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { +  VisitNamedDecl(D); +  Writer.AddSourceLocation(D->getAtLoc(), Record); +  Writer.AddSourceLocation(D->getLParenLoc(), 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 = serialization::DECL_OBJC_PROPERTY; +} + +void ASTDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) { +  VisitObjCContainerDecl(D); +  Writer.AddDeclRef(D->getClassInterface(), Record); +  // Abstract class (no need to define a stable serialization::DECL code). +} + +void ASTDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { +  VisitObjCImplDecl(D); +  Writer.AddIdentifierRef(D->getIdentifier(), Record); +  Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); +  Code = serialization::DECL_OBJC_CATEGORY_IMPL; +} + +void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { +  VisitObjCImplDecl(D); +  Writer.AddDeclRef(D->getSuperClass(), Record); +  Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record); +  Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); +  Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers, +                                Record); +  Record.push_back(D->hasSynthBitfield()); +  Code = serialization::DECL_OBJC_IMPLEMENTATION; +} + +void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { +  VisitDecl(D); +  Writer.AddSourceLocation(D->getLocStart(), Record); +  Writer.AddDeclRef(D->getPropertyDecl(), Record); +  Writer.AddDeclRef(D->getPropertyIvarDecl(), Record); +  Writer.AddSourceLocation(D->getPropertyIvarDeclLoc(), Record); +  Writer.AddStmt(D->getGetterCXXConstructor()); +  Writer.AddStmt(D->getSetterCXXAssignment()); +  Code = serialization::DECL_OBJC_PROPERTY_IMPL; +} + +void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { +  VisitDeclaratorDecl(D); +  Record.push_back(D->isMutable()); +  Record.push_back(D->getBitWidth()? 1 : D->hasInClassInitializer() ? 2 : 0); +  if (D->getBitWidth()) +    Writer.AddStmt(D->getBitWidth()); +  else if (D->hasInClassInitializer()) +    Writer.AddStmt(D->getInClassInitializer()); +  if (!D->getDeclName()) +    Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record); + +  if (!D->hasAttrs() && +      !D->isImplicit() && +      !D->isUsed(false) && +      !D->isInvalidDecl() && +      !D->isReferenced() && +      !D->isTopLevelDeclInObjCContainer() && +      !D->isModulePrivate() && +      !D->getBitWidth() && +      !D->hasInClassInitializer() && +      !D->hasExtInfo() && +      !ObjCIvarDecl::classofKind(D->getKind()) && +      !ObjCAtDefsFieldDecl::classofKind(D->getKind()) && +      D->getDeclName()) +    AbbrevToUse = Writer.getDeclFieldAbbrev(); + +  Code = serialization::DECL_FIELD; +} + +void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { +  VisitValueDecl(D); +  Record.push_back(D->getChainingSize()); + +  for (IndirectFieldDecl::chain_iterator +       P = D->chain_begin(), +       PEnd = D->chain_end(); P != PEnd; ++P) +    Writer.AddDeclRef(*P, Record); +  Code = serialization::DECL_INDIRECTFIELD; +} + +void ASTDeclWriter::VisitVarDecl(VarDecl *D) { +  VisitRedeclarable(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->getInitStyle()); +  Record.push_back(D->isExceptionVariable()); +  Record.push_back(D->isNRVOVariable()); +  Record.push_back(D->isCXXForRangeDecl()); +  Record.push_back(D->isARCPseudoStrong()); +  if (D->getInit()) { +    Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2)); +    Writer.AddStmt(D->getInit()); +  } else { +    Record.push_back(0); +  } + +  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); +  } + +  if (!D->hasAttrs() && +      !D->isImplicit() && +      !D->isUsed(false) && +      !D->isInvalidDecl() && +      !D->isReferenced() && +      !D->isTopLevelDeclInObjCContainer() && +      D->getAccess() == AS_none && +      !D->isModulePrivate() && +      D->getDeclName().getNameKind() == DeclarationName::Identifier && +      !D->hasExtInfo() && +      D->getFirstDeclaration() == D->getMostRecentDecl() && +      D->getInitStyle() == VarDecl::CInit && +      D->getInit() == 0 && +      !isa<ParmVarDecl>(D) && +      !SpecInfo) +    AbbrevToUse = Writer.getDeclVarAbbrev(); + +  Code = serialization::DECL_VAR; +} + +void ASTDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { +  VisitVarDecl(D); +  Code = serialization::DECL_IMPLICIT_PARAM; +} + +void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { +  VisitVarDecl(D); +  Record.push_back(D->isObjCMethodParameter()); +  Record.push_back(D->getFunctionScopeDepth()); +  Record.push_back(D->getFunctionScopeIndex()); +  Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding +  Record.push_back(D->isKNRPromoted()); +  Record.push_back(D->hasInheritedDefaultArg()); +  Record.push_back(D->hasUninstantiatedDefaultArg()); +  if (D->hasUninstantiatedDefaultArg()) +    Writer.AddStmt(D->getUninstantiatedDefaultArg()); +  Code = serialization::DECL_PARM_VAR; + +  assert(!D->isARCPseudoStrong()); // can be true of ImplicitParamDecl + +  // 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->hasAttrs() && +      !D->hasExtInfo() && +      !D->isImplicit() && +      !D->isUsed(false) && +      !D->isInvalidDecl() && +      !D->isReferenced() && +      D->getAccess() == AS_none && +      !D->isModulePrivate() && +      D->getStorageClass() == 0 && +      D->getInitStyle() == VarDecl::CInit && // Can params have anything else? +      D->getFunctionScopeDepth() == 0 && +      D->getObjCDeclQualifier() == 0 && +      !D->isKNRPromoted() && +      !D->hasInheritedDefaultArg() && +      D->getInit() == 0 && +      !D->hasUninstantiatedDefaultArg())  // No default expr. +    AbbrevToUse = Writer.getDeclParmVarAbbrev(); + +  // Check things we know are true of *every* PARM_VAR_DECL, which is more than +  // just us assuming it. +  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->getPreviousDecl() == 0 && "PARM_VAR_DECL can't be redecl"); +  assert(!D->isStaticDataMember() && +         "PARM_VAR_DECL can't be static data member"); +} + +void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { +  VisitDecl(D); +  Writer.AddStmt(D->getAsmString()); +  Writer.AddSourceLocation(D->getRParenLoc(), Record); +  Code = serialization::DECL_FILE_SCOPE_ASM; +} + +void ASTDeclWriter::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); +  Record.push_back(D->isVariadic()); +  Record.push_back(D->blockMissingReturnType()); +  Record.push_back(D->isConversionFromLambda()); +  Record.push_back(D->capturesCXXThis()); +  Record.push_back(D->getNumCaptures()); +  for (BlockDecl::capture_iterator +         i = D->capture_begin(), e = D->capture_end(); i != e; ++i) { +    const BlockDecl::Capture &capture = *i; +    Writer.AddDeclRef(capture.getVariable(), Record); + +    unsigned flags = 0; +    if (capture.isByRef()) flags |= 1; +    if (capture.isNested()) flags |= 2; +    if (capture.hasCopyExpr()) flags |= 4; +    Record.push_back(flags); + +    if (capture.hasCopyExpr()) Writer.AddStmt(capture.getCopyExpr()); +  } + +  Code = serialization::DECL_BLOCK; +} + +void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { +  VisitDecl(D); +  Record.push_back(D->getLanguage()); +  Writer.AddSourceLocation(D->getExternLoc(), Record); +  Writer.AddSourceLocation(D->getRBraceLoc(), Record); +  Code = serialization::DECL_LINKAGE_SPEC; +} + +void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { +  VisitNamedDecl(D); +  Writer.AddSourceLocation(D->getLocStart(), Record); +  Code = serialization::DECL_LABEL; +} + + +void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { +  VisitRedeclarable(D); +  VisitNamedDecl(D); +  Record.push_back(D->isInline()); +  Writer.AddSourceLocation(D->getLocStart(), Record); +  Writer.AddSourceLocation(D->getRBraceLoc(), Record); + +  if (D->isOriginalNamespace()) +    Writer.AddDeclRef(D->getAnonymousNamespace(), Record); +  Code = serialization::DECL_NAMESPACE; + +  if (Writer.hasChain() && !D->isOriginalNamespace() && +      D->getOriginalNamespace()->isFromASTFile()) { +    NamespaceDecl *NS = D->getOriginalNamespace(); +    Writer.AddUpdatedDeclContext(NS); + +    // Make sure all visible decls are written. They will be recorded later. +    if (StoredDeclsMap *Map = NS->buildLookup()) { +      for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); +           D != DEnd; ++D) { +        DeclContext::lookup_result Result = D->second.getLookupResult(); +        while (Result.first != Result.second) { +          Writer.GetDeclRef(*Result.first); +          ++Result.first; +        } +      } +    } +  } + +  if (Writer.hasChain() && D->isAnonymousNamespace() &&  +      D == D->getMostRecentDecl()) { +    // This is a most recent reopening of the anonymous namespace. If its parent +    // is in a previous PCH (or is the TU), mark that parent for update, because +    // the original namespace always points to the latest re-opening of its +    // anonymous namespace. +    Decl *Parent = cast<Decl>( +        D->getParent()->getRedeclContext()->getPrimaryContext()); +    if (Parent->isFromASTFile() || isa<TranslationUnitDecl>(Parent)) { +      ASTWriter::UpdateRecord &Record = Writer.DeclUpdates[Parent]; +      Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); +      Writer.AddDeclRef(D, Record); +    } +  } +} + +void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { +  VisitNamedDecl(D); +  Writer.AddSourceLocation(D->getNamespaceLoc(), Record); +  Writer.AddSourceLocation(D->getTargetNameLoc(), Record); +  Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); +  Writer.AddDeclRef(D->getNamespace(), Record); +  Code = serialization::DECL_NAMESPACE_ALIAS; +} + +void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { +  VisitNamedDecl(D); +  Writer.AddSourceLocation(D->getUsingLocation(), Record); +  Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); +  Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); +  Writer.AddDeclRef(D->FirstUsingShadow.getPointer(), Record); +  Record.push_back(D->isTypeName()); +  Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record); +  Code = serialization::DECL_USING; +} + +void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { +  VisitNamedDecl(D); +  Writer.AddDeclRef(D->getTargetDecl(), Record); +  Writer.AddDeclRef(D->UsingOrNextShadow, Record); +  Writer.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D), Record); +  Code = serialization::DECL_USING_SHADOW; +} + +void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { +  VisitNamedDecl(D); +  Writer.AddSourceLocation(D->getUsingLoc(), Record); +  Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record); +  Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); +  Writer.AddDeclRef(D->getNominatedNamespace(), Record); +  Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record); +  Code = serialization::DECL_USING_DIRECTIVE; +} + +void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { +  VisitValueDecl(D); +  Writer.AddSourceLocation(D->getUsingLoc(), Record); +  Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); +  Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); +  Code = serialization::DECL_UNRESOLVED_USING_VALUE; +} + +void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( +                                               UnresolvedUsingTypenameDecl *D) { +  VisitTypeDecl(D); +  Writer.AddSourceLocation(D->getTypenameLoc(), Record); +  Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); +  Code = serialization::DECL_UNRESOLVED_USING_TYPENAME; +} + +void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { +  VisitRecordDecl(D); +  Record.push_back(D->isThisDeclarationADefinition()); +  if (D->isThisDeclarationADefinition()) +    Writer.AddCXXDefinitionData(D, 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); +  } + +  // Store the key function to avoid deserializing every method so we can +  // compute it. +  if (D->IsCompleteDefinition) +    Writer.AddDeclRef(Context.getKeyFunction(D), Record); + +  Code = serialization::DECL_CXX_RECORD; +} + +void ASTDeclWriter::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 = serialization::DECL_CXX_METHOD; +} + +void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { +  VisitCXXMethodDecl(D); + +  Record.push_back(D->IsExplicitSpecified); +  Record.push_back(D->ImplicitlyDefined); +  Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers, +                                Record); + +  Code = serialization::DECL_CXX_CONSTRUCTOR; +} + +void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { +  VisitCXXMethodDecl(D); + +  Record.push_back(D->ImplicitlyDefined); +  Writer.AddDeclRef(D->OperatorDelete, Record); + +  Code = serialization::DECL_CXX_DESTRUCTOR; +} + +void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { +  VisitCXXMethodDecl(D); +  Record.push_back(D->IsExplicitSpecified); +  Code = serialization::DECL_CXX_CONVERSION; +} + +void ASTDeclWriter::VisitImportDecl(ImportDecl *D) { +  VisitDecl(D); +  ArrayRef<SourceLocation> IdentifierLocs = D->getIdentifierLocs(); +  Record.push_back(!IdentifierLocs.empty()); +  if (IdentifierLocs.empty()) { +    Writer.AddSourceLocation(D->getLocEnd(), Record); +    Record.push_back(1); +  } else { +    for (unsigned I = 0, N = IdentifierLocs.size(); I != N; ++I) +      Writer.AddSourceLocation(IdentifierLocs[I], Record); +    Record.push_back(IdentifierLocs.size()); +  } +  // Note: the number of source locations must always be the last element in +  // the record. +  Code = serialization::DECL_IMPORT; +} + +void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) { +  VisitDecl(D); +  Writer.AddSourceLocation(D->getColonLoc(), Record); +  Code = serialization::DECL_ACCESS_SPEC; +} + +void ASTDeclWriter::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->getNextFriend(), Record); +  Record.push_back(D->UnsupportedFriend); +  Writer.AddSourceLocation(D->FriendLoc, Record); +  Code = serialization::DECL_FRIEND; +} + +void ASTDeclWriter::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 = serialization::DECL_FRIEND_TEMPLATE; +} + +void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) { +  VisitNamedDecl(D); + +  Writer.AddDeclRef(D->getTemplatedDecl(), Record); +  Writer.AddTemplateParameterList(D->getTemplateParameters(), Record); +} + +void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { +  VisitRedeclarable(D); + +  // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that +  // getCommonPtr() can be used while this is still initializing. +  if (D->isFirstDeclaration()) { +    // This declaration owns the 'common' pointer, so serialize that data now. +    Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); +    if (D->getInstantiatedFromMemberTemplate()) +      Record.push_back(D->isMemberSpecialization()); +  } +   +  VisitTemplateDecl(D); +  Record.push_back(D->getIdentifierNamespace()); +} + +void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { +  VisitRedeclarableTemplateDecl(D); + +  if (D->isFirstDeclaration()) { +    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 = serialization::DECL_CLASS_TEMPLATE; +} + +void ASTDeclWriter::VisitClassTemplateSpecializationDecl( +                                           ClassTemplateSpecializationDecl *D) { +  VisitCXXRecordDecl(D); + +  llvm::PointerUnion<ClassTemplateDecl *, +                     ClassTemplatePartialSpecializationDecl *> InstFrom +    = D->getSpecializedTemplateOrPartial(); +  if (Decl *InstFromD = InstFrom.dyn_cast<ClassTemplateDecl *>()) { +    Writer.AddDeclRef(InstFromD, 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 = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION; +} + +void ASTDeclWriter::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->getPreviousDecl() == 0) { +    Writer.AddDeclRef(D->getInstantiatedFromMember(), Record); +    Record.push_back(D->isMemberSpecialization()); +  } + +  Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; +} + +void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( +                                    ClassScopeFunctionSpecializationDecl *D) { +  VisitDecl(D); +  Writer.AddDeclRef(D->getSpecialization(), Record); +  Code = serialization::DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION; +} + + +void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { +  VisitRedeclarableTemplateDecl(D); + +  if (D->isFirstDeclaration()) { +    // 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 = serialization::DECL_FUNCTION_TEMPLATE; +} + +void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { +  VisitTypeDecl(D); + +  Record.push_back(D->wasDeclaredWithTypename()); +  Record.push_back(D->defaultArgumentWasInherited()); +  Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record); + +  Code = serialization::DECL_TEMPLATE_TYPE_PARM; +} + +void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { +  // For an expanded parameter pack, record the number of expansion types here +  // so that it's easier for  +  if (D->isExpandedParameterPack()) +    Record.push_back(D->getNumExpansionTypes()); +   +  VisitDeclaratorDecl(D); +  // TemplateParmPosition. +  Record.push_back(D->getDepth()); +  Record.push_back(D->getPosition()); +   +  if (D->isExpandedParameterPack()) { +    for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { +      Writer.AddTypeRef(D->getExpansionType(I), Record); +      Writer.AddTypeSourceInfo(D->getExpansionTypeSourceInfo(I), Record); +    } +       +    Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK; +  } else { +    // Rest of NonTypeTemplateParmDecl. +    Record.push_back(D->isParameterPack()); +    Record.push_back(D->getDefaultArgument() != 0); +    if (D->getDefaultArgument()) { +      Writer.AddStmt(D->getDefaultArgument()); +      Record.push_back(D->defaultArgumentWasInherited()); +    } +    Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; +  } +} + +void ASTDeclWriter::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()); +  Record.push_back(D->isParameterPack()); +  Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM; +} + +void ASTDeclWriter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { +  VisitRedeclarableTemplateDecl(D); +  Code = serialization::DECL_TYPE_ALIAS_TEMPLATE; +} + +void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) { +  VisitDecl(D); +  Writer.AddStmt(D->getAssertExpr()); +  Writer.AddStmt(D->getMessage()); +  Writer.AddSourceLocation(D->getRParenLoc(), Record); +  Code = serialization::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 ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, +                                     uint64_t VisibleOffset) { +  Record.push_back(LexicalOffset); +  Record.push_back(VisibleOffset); +} + +template <typename T> +void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { +  T *First = D->getFirstDeclaration(); +  if (First->getMostRecentDecl() != First) { +    // There is more than one declaration of this entity, so we will need to  +    // write a redeclaration chain. +    Writer.AddDeclRef(First, Record); +    Writer.Redeclarations.insert(First); + +    // Make sure that we serialize both the previous and the most-recent  +    // declarations, which (transitively) ensures that all declarations in the +    // chain get serialized. +    (void)Writer.GetDeclRef(D->getPreviousDecl()); +    (void)Writer.GetDeclRef(First->getMostRecentDecl()); +  } else { +    // We use the sentinel value 0 to indicate an only declaration. +    Record.push_back(0); +  } +   +} + +//===----------------------------------------------------------------------===// +// ASTWriter Implementation +//===----------------------------------------------------------------------===// + +void ASTWriter::WriteDeclsBlockAbbrevs() { +  using namespace llvm; + +  BitCodeAbbrev *Abv; + +  // Abbreviation for DECL_FIELD +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_FIELD)); +  // Decl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext +  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs +  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit +  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed +  Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced +  Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2));  // AccessSpecifier +  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID +  // 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(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc +  Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo +  // FieldDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable +  Abv->Add(BitCodeAbbrevOp(0));                       //getBitWidth +  // Type Source Info +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc +  DeclFieldAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for DECL_OBJC_IVAR +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_OBJC_IVAR)); +  // Decl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext +  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs +  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit +  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed +  Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced +  Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2));  // AccessSpecifier +  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID +  // 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(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc +  Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo +  // FieldDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable +  Abv->Add(BitCodeAbbrevOp(0));                       //getBitWidth +  // ObjC Ivar +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize +  // Type Source Info +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc +  DeclObjCIvarAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for DECL_ENUM +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM)); +  // Redeclarable +  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration +  // Decl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext +  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs +  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit +  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed +  Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced +  Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer +  Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier +  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID +  // NamedDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name +  // TypeDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref +  // TagDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IdentifierNamespace +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // getTagKind +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation +  Abv->Add(BitCodeAbbrevOp(0));                         // hasExtInfo +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // TypedefNameAnonDecl +  // EnumDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // AddTypeRef +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IntegerType +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // getPromotionType +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // getNumPositiveBits +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // getNumNegativeBits +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScoped +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScopedUsingClassTag +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isFixed +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // InstantiatedMembEnum +  // DC +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LexicalOffset +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // VisibleOffset +  DeclEnumAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for DECL_RECORD +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD)); +  // Redeclarable +  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration +  // Decl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext +  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs +  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit +  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed +  Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced +  Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer +  Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier +  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID +  // NamedDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name +  // TypeDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref +  // TagDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IdentifierNamespace +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // getTagKind +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation +  Abv->Add(BitCodeAbbrevOp(0));                         // hasExtInfo +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // TypedefNameAnonDecl +  // RecordDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // FlexibleArrayMember +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasObjectMember +  // DC +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LexicalOffset +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // VisibleOffset +  DeclRecordAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for DECL_PARM_VAR +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR)); +  // Redeclarable +  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration +  // Decl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext +  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs +  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit +  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed +  Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced +  Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer +  Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier +  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID +  // 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(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc +  Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo +  // 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));                       // isCXXForRangeDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // isARCPseudoStrong +  Abv->Add(BitCodeAbbrevOp(0));                       // HasInit +  Abv->Add(BitCodeAbbrevOp(0));                   // HasMemberSpecializationInfo +  // ParmVarDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsObjCMethodParameter +  Abv->Add(BitCodeAbbrevOp(0));                       // ScopeDepth +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ScopeIndex +  Abv->Add(BitCodeAbbrevOp(0));                       // ObjCDeclQualifier +  Abv->Add(BitCodeAbbrevOp(0));                       // KNRPromoted +  Abv->Add(BitCodeAbbrevOp(0));                       // HasInheritedDefaultArg +  Abv->Add(BitCodeAbbrevOp(0));                   // HasUninstantiatedDefaultArg +  // Type Source Info +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc +  DeclParmVarAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for DECL_TYPEDEF +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF)); +  // Redeclarable +  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration +  // Decl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext +  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs +  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit +  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed +  Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced +  Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer +  Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier +  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID +  // NamedDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name +  // TypeDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref +  // TypedefDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc +  DeclTypedefAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for DECL_VAR +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR)); +  // Redeclarable +  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration +  // Decl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext +  Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl +  Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs +  Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit +  Abv->Add(BitCodeAbbrevOp(0));                       // isUsed +  Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced +  Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer +  Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier +  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID +  // 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(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc +  Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo +  // VarDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClassAsWritten +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isThreadSpecified +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // CXXDirectInitializer +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasInit +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasMemberSpecInfo +  // Type Source Info +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc +  DeclVarAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for EXPR_DECL_REF +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF)); +  //Stmt +  //Expr +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind +  //DeclRefExpr +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HasQualifier +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //RefersToEnclosingLocal +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location +  DeclRefExprAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for EXPR_INTEGER_LITERAL +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_INTEGER_LITERAL)); +  //Stmt +  //Expr +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind +  //Integer Literal +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location +  Abv->Add(BitCodeAbbrevOp(32));                      // Bit Width +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Value +  IntegerLiteralAbbrev = Stream.EmitAbbrev(Abv); + +  // Abbreviation for EXPR_CHARACTER_LITERAL +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CHARACTER_LITERAL)); +  //Stmt +  //Expr +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind +  //Character Literal +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getValue +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //IsWide +  CharacterLiteralAbbrev = Stream.EmitAbbrev(Abv); + +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +  DeclContextLexicalAbbrev = Stream.EmitAbbrev(Abv); + +  Abv = new BitCodeAbbrev(); +  Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); +  DeclContextVisibleLookupAbbrev = 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 AST 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) { +  // An ObjCMethodDecl is never considered as "required" because its +  // implementation container always is. + +  // File scoped assembly or obj-c implementation must be seen. +  if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D)) +    return true; + +  return Context.DeclMustBeEmitted(D); +} + +void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { +  // Switch case IDs are per Decl. +  ClearSwitchCaseIDs(); + +  RecordData Record; +  ASTDeclWriter W(*this, Context, Record); + +  // Determine the ID for this declaration. +  serialization::DeclID ID; +  if (D->isFromASTFile()) +    ID = getDeclID(D); +  else { +    serialization::DeclID &IDR = DeclIDs[D]; +    if (IDR == 0) +      IDR = NextDeclID++; +     +    ID= IDR; +  } + +  bool isReplacingADecl = ID < FirstDeclID; + +  // 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) { +    if (isReplacingADecl) { +      // It is replacing a decl from a chained PCH; make sure that the +      // DeclContext is fully loaded. +      if (DC->hasExternalLexicalStorage()) +        DC->LoadLexicalDeclsFromExternalStorage(); +      if (DC->hasExternalVisibleStorage()) +        Chain->completeVisibleDeclsMap(DC); +    } +    LexicalOffset = WriteDeclContextLexicalBlock(Context, DC); +    VisibleOffset = WriteDeclContextVisibleBlock(Context, DC); +  } +   +  if (isReplacingADecl) { +    // We're replacing a decl in a previous file. +    ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(), +                                             D->getLocation())); +  } else { +    unsigned Index = ID - FirstDeclID; + +    // Record the offset for this declaration +    SourceLocation Loc = D->getLocation(); +    if (DeclOffsets.size() == Index) +      DeclOffsets.push_back(DeclOffset(Loc, Stream.GetCurrentBitNo())); +    else if (DeclOffsets.size() < Index) { +      DeclOffsets.resize(Index+1); +      DeclOffsets[Index].setLocation(Loc); +      DeclOffsets[Index].BitOffset = Stream.GetCurrentBitNo(); +    } +     +    SourceManager &SM = Context.getSourceManager(); +    if (Loc.isValid() && SM.isLocalSourceLocation(Loc)) +      associateDeclWithFile(D, ID); +  } + +  // Build and emit a record for this declaration +  Record.clear(); +  W.Code = (serialization::DeclCode)0; +  W.AbbrevToUse = 0; +  W.Visit(D); +  if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); + +  if (!W.Code) +    llvm::report_fatal_error(StringRef("unexpected declaration kind '") + +                            D->getDeclKindName() + "'"); +  Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); + +  // Flush any expressions that were written as part of this declaration. +  FlushStmts(); +   +  // Flush C++ base specifiers, if there are any. +  FlushCXXBaseSpecifiers(); +   +  // Note "external" declarations so that we can add them to a record in the +  // AST 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/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp new file mode 100644 index 0000000..1e31211 --- /dev/null +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -0,0 +1,1667 @@ +//===--- ASTWriterStmt.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/ASTWriter.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/StmtVisitor.h" +#include "llvm/Bitcode/BitstreamWriter.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +// Statement/expression serialization +//===----------------------------------------------------------------------===// + +namespace clang { +  class ASTStmtWriter : public StmtVisitor<ASTStmtWriter, void> { +    ASTWriter &Writer; +    ASTWriter::RecordData &Record; + +  public: +    serialization::StmtCode Code; +    unsigned AbbrevToUse; + +    ASTStmtWriter(ASTWriter &Writer, ASTWriter::RecordData &Record) +      : Writer(Writer), Record(Record) { } + +    void AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &Args); + +    void VisitStmt(Stmt *S); +#define STMT(Type, Base) \ +    void Visit##Type(Type *); +#include "clang/AST/StmtNodes.inc" +  }; +} + +void ASTStmtWriter:: +AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &Args) { +  Writer.AddSourceLocation(Args.getTemplateKeywordLoc(), Record); +  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 ASTStmtWriter::VisitStmt(Stmt *S) { +} + +void ASTStmtWriter::VisitNullStmt(NullStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getSemiLoc(), Record); +  Record.push_back(S->HasLeadingEmptyMacro); +  Code = serialization::STMT_NULL; +} + +void ASTStmtWriter::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 = serialization::STMT_COMPOUND; +} + +void ASTStmtWriter::VisitSwitchCase(SwitchCase *S) { +  VisitStmt(S); +  Record.push_back(Writer.getSwitchCaseID(S)); +} + +void ASTStmtWriter::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 = serialization::STMT_CASE; +} + +void ASTStmtWriter::VisitDefaultStmt(DefaultStmt *S) { +  VisitSwitchCase(S); +  Writer.AddStmt(S->getSubStmt()); +  Writer.AddSourceLocation(S->getDefaultLoc(), Record); +  Writer.AddSourceLocation(S->getColonLoc(), Record); +  Code = serialization::STMT_DEFAULT; +} + +void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) { +  VisitStmt(S); +  Writer.AddDeclRef(S->getDecl(), Record); +  Writer.AddStmt(S->getSubStmt()); +  Writer.AddSourceLocation(S->getIdentLoc(), Record); +  Code = serialization::STMT_LABEL; +} + +void ASTStmtWriter::VisitAttributedStmt(AttributedStmt *S) { +  VisitStmt(S); +  Writer.WriteAttributes(S->getAttrs(), Record); +  Writer.AddStmt(S->getSubStmt()); +  Writer.AddSourceLocation(S->getAttrLoc(), Record); +  Code = serialization::STMT_ATTRIBUTED; +} + +void ASTStmtWriter::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 = serialization::STMT_IF; +} + +void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) { +  VisitStmt(S); +  Writer.AddDeclRef(S->getConditionVariable(), Record); +  Writer.AddStmt(S->getCond()); +  Writer.AddStmt(S->getBody()); +  Writer.AddSourceLocation(S->getSwitchLoc(), Record); +  Record.push_back(S->isAllEnumCasesCovered()); +  for (SwitchCase *SC = S->getSwitchCaseList(); SC; +       SC = SC->getNextSwitchCase()) +    Record.push_back(Writer.RecordSwitchCaseID(SC)); +  Code = serialization::STMT_SWITCH; +} + +void ASTStmtWriter::VisitWhileStmt(WhileStmt *S) { +  VisitStmt(S); +  Writer.AddDeclRef(S->getConditionVariable(), Record); +  Writer.AddStmt(S->getCond()); +  Writer.AddStmt(S->getBody()); +  Writer.AddSourceLocation(S->getWhileLoc(), Record); +  Code = serialization::STMT_WHILE; +} + +void ASTStmtWriter::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 = serialization::STMT_DO; +} + +void ASTStmtWriter::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 = serialization::STMT_FOR; +} + +void ASTStmtWriter::VisitGotoStmt(GotoStmt *S) { +  VisitStmt(S); +  Writer.AddDeclRef(S->getLabel(), Record); +  Writer.AddSourceLocation(S->getGotoLoc(), Record); +  Writer.AddSourceLocation(S->getLabelLoc(), Record); +  Code = serialization::STMT_GOTO; +} + +void ASTStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getGotoLoc(), Record); +  Writer.AddSourceLocation(S->getStarLoc(), Record); +  Writer.AddStmt(S->getTarget()); +  Code = serialization::STMT_INDIRECT_GOTO; +} + +void ASTStmtWriter::VisitContinueStmt(ContinueStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getContinueLoc(), Record); +  Code = serialization::STMT_CONTINUE; +} + +void ASTStmtWriter::VisitBreakStmt(BreakStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getBreakLoc(), Record); +  Code = serialization::STMT_BREAK; +} + +void ASTStmtWriter::VisitReturnStmt(ReturnStmt *S) { +  VisitStmt(S); +  Writer.AddStmt(S->getRetValue()); +  Writer.AddSourceLocation(S->getReturnLoc(), Record); +  Writer.AddDeclRef(S->getNRVOCandidate(), Record); +  Code = serialization::STMT_RETURN; +} + +void ASTStmtWriter::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 = serialization::STMT_DECL; +} + +void ASTStmtWriter::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 = serialization::STMT_ASM; +} + +void ASTStmtWriter::VisitExpr(Expr *E) { +  VisitStmt(E); +  Writer.AddTypeRef(E->getType(), Record); +  Record.push_back(E->isTypeDependent()); +  Record.push_back(E->isValueDependent()); +  Record.push_back(E->isInstantiationDependent()); +  Record.push_back(E->containsUnexpandedParameterPack()); +  Record.push_back(E->getValueKind()); +  Record.push_back(E->getObjectKind()); +} + +void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Record.push_back(E->getIdentType()); // FIXME: stable encoding +  Code = serialization::EXPR_PREDEFINED; +} + +void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { +  VisitExpr(E); + +  Record.push_back(E->hasQualifier()); +  Record.push_back(E->getDecl() != E->getFoundDecl()); +  Record.push_back(E->hasTemplateKWAndArgsInfo()); +  Record.push_back(E->hadMultipleCandidates()); +  Record.push_back(E->refersToEnclosingLocal()); + +  if (E->hasTemplateKWAndArgsInfo()) { +    unsigned NumTemplateArgs = E->getNumTemplateArgs(); +    Record.push_back(NumTemplateArgs); +  } + +  DeclarationName::NameKind nk = (E->getDecl()->getDeclName().getNameKind()); + +  if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) && +      (E->getDecl() == E->getFoundDecl()) && +      nk == DeclarationName::Identifier) { +    AbbrevToUse = Writer.getDeclRefExprAbbrev(); +  } + +  if (E->hasQualifier()) +    Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); + +  if (E->getDecl() != E->getFoundDecl()) +    Writer.AddDeclRef(E->getFoundDecl(), Record); + +  if (E->hasTemplateKWAndArgsInfo()) +    AddTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo()); + +  Writer.AddDeclRef(E->getDecl(), Record); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Writer.AddDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName(), Record); +  Code = serialization::EXPR_DECL_REF; +} + +void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Writer.AddAPInt(E->getValue(), Record); + +  if (E->getValue().getBitWidth() == 32) { +    AbbrevToUse = Writer.getIntegerLiteralAbbrev(); +  } + +  Code = serialization::EXPR_INTEGER_LITERAL; +} + +void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) { +  VisitExpr(E); +  Writer.AddAPFloat(E->getValue(), Record); +  Record.push_back(E->isExact()); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Code = serialization::EXPR_FLOATING_LITERAL; +} + +void ASTStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getSubExpr()); +  Code = serialization::EXPR_IMAGINARY_LITERAL; +} + +void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) { +  VisitExpr(E); +  Record.push_back(E->getByteLength()); +  Record.push_back(E->getNumConcatenated()); +  Record.push_back(E->getKind()); +  Record.push_back(E->isPascal()); +  // 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 AST file during deserialization. +  Record.append(E->getBytes().begin(), E->getBytes().end()); +  for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) +    Writer.AddSourceLocation(E->getStrTokenLoc(I), Record); +  Code = serialization::EXPR_STRING_LITERAL; +} + +void ASTStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) { +  VisitExpr(E); +  Record.push_back(E->getValue()); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Record.push_back(E->getKind()); + +  AbbrevToUse = Writer.getCharacterLiteralAbbrev(); + +  Code = serialization::EXPR_CHARACTER_LITERAL; +} + +void ASTStmtWriter::VisitParenExpr(ParenExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getLParen(), Record); +  Writer.AddSourceLocation(E->getRParen(), Record); +  Writer.AddStmt(E->getSubExpr()); +  Code = serialization::EXPR_PAREN; +} + +void ASTStmtWriter::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 = serialization::EXPR_PAREN_LIST; +} + +void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getSubExpr()); +  Record.push_back(E->getOpcode()); // FIXME: stable encoding +  Writer.AddSourceLocation(E->getOperatorLoc(), Record); +  Code = serialization::EXPR_UNARY_OPERATOR; +} + +void ASTStmtWriter::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.getSourceRange().getBegin(), Record); +    Writer.AddSourceLocation(ON.getSourceRange().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 = serialization::EXPR_OFFSETOF; +} + +void ASTStmtWriter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getKind()); +  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 = serialization::EXPR_SIZEOF_ALIGN_OF; +} + +void ASTStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getLHS()); +  Writer.AddStmt(E->getRHS()); +  Writer.AddSourceLocation(E->getRBracketLoc(), Record); +  Code = serialization::EXPR_ARRAY_SUBSCRIPT; +} + +void ASTStmtWriter::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 = serialization::EXPR_CALL; +} + +void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { +  // Don't call VisitExpr, we'll write everything here. + +  Record.push_back(E->hasQualifier()); +  if (E->hasQualifier()) +    Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); + +  Record.push_back(E->HasTemplateKWAndArgsInfo); +  if (E->HasTemplateKWAndArgsInfo) { +    Writer.AddSourceLocation(E->getTemplateKeywordLoc(), Record); +    unsigned NumTemplateArgs = E->getNumTemplateArgs(); +    Record.push_back(NumTemplateArgs); +    Writer.AddSourceLocation(E->getLAngleLoc(), Record); +    Writer.AddSourceLocation(E->getRAngleLoc(), Record); +    for (unsigned i=0; i != NumTemplateArgs; ++i) +      Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record); +  } + +  Record.push_back(E->hadMultipleCandidates()); + +  DeclAccessPair FoundDecl = E->getFoundDecl(); +  Writer.AddDeclRef(FoundDecl.getDecl(), Record); +  Record.push_back(FoundDecl.getAccess()); + +  Writer.AddTypeRef(E->getType(), Record); +  Record.push_back(E->getValueKind()); +  Record.push_back(E->getObjectKind()); +  Writer.AddStmt(E->getBase()); +  Writer.AddDeclRef(E->getMemberDecl(), Record); +  Writer.AddSourceLocation(E->getMemberLoc(), Record); +  Record.push_back(E->isArrow()); +  Writer.AddDeclarationNameLoc(E->MemberDNLoc, +                               E->getMemberDecl()->getDeclName(), Record); +  Code = serialization::EXPR_MEMBER; +} + +void ASTStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getBase()); +  Writer.AddSourceLocation(E->getIsaMemberLoc(), Record); +  Record.push_back(E->isArrow()); +  Code = serialization::EXPR_OBJC_ISA; +} + +void ASTStmtWriter:: +VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getSubExpr()); +  Record.push_back(E->shouldCopy()); +  Code = serialization::EXPR_OBJC_INDIRECT_COPY_RESTORE; +} + +void ASTStmtWriter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { +  VisitExplicitCastExpr(E); +  Writer.AddSourceLocation(E->getLParenLoc(), Record); +  Writer.AddSourceLocation(E->getBridgeKeywordLoc(), Record); +  Record.push_back(E->getBridgeKind()); // FIXME: Stable encoding +  Code = serialization::EXPR_OBJC_BRIDGED_CAST; +} + +void ASTStmtWriter::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 ASTStmtWriter::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 = serialization::EXPR_BINARY_OPERATOR; +} + +void ASTStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { +  VisitBinaryOperator(E); +  Writer.AddTypeRef(E->getComputationLHSType(), Record); +  Writer.AddTypeRef(E->getComputationResultType(), Record); +  Code = serialization::EXPR_COMPOUND_ASSIGN_OPERATOR; +} + +void ASTStmtWriter::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 = serialization::EXPR_CONDITIONAL_OPERATOR; +} + +void +ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getOpaqueValue()); +  Writer.AddStmt(E->getCommon()); +  Writer.AddStmt(E->getCond()); +  Writer.AddStmt(E->getTrueExpr()); +  Writer.AddStmt(E->getFalseExpr()); +  Writer.AddSourceLocation(E->getQuestionLoc(), Record); +  Writer.AddSourceLocation(E->getColonLoc(), Record); +  Code = serialization::EXPR_BINARY_CONDITIONAL_OPERATOR; +} + +void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { +  VisitCastExpr(E); +  Code = serialization::EXPR_IMPLICIT_CAST; +} + +void ASTStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) { +  VisitCastExpr(E); +  Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record); +} + +void ASTStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) { +  VisitExplicitCastExpr(E); +  Writer.AddSourceLocation(E->getLParenLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_CSTYLE_CAST; +} + +void ASTStmtWriter::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 = serialization::EXPR_COMPOUND_LITERAL; +} + +void ASTStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getBase()); +  Writer.AddIdentifierRef(&E->getAccessor(), Record); +  Writer.AddSourceLocation(E->getAccessorLoc(), Record); +  Code = serialization::EXPR_EXT_VECTOR_ELEMENT; +} + +void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getSyntacticForm()); +  Writer.AddSourceLocation(E->getLBraceLoc(), Record); +  Writer.AddSourceLocation(E->getRBraceLoc(), Record); +  bool isArrayFiller = E->ArrayFillerOrUnionFieldInit.is<Expr*>(); +  Record.push_back(isArrayFiller); +  if (isArrayFiller) +    Writer.AddStmt(E->getArrayFiller()); +  else +    Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record); +  Record.push_back(E->hadArrayRangeDesignator()); +  Record.push_back(E->initializesStdInitializerList()); +  Record.push_back(E->getNumInits()); +  if (isArrayFiller) { +    // ArrayFiller may have filled "holes" due to designated initializer. +    // Replace them by 0 to indicate that the filler goes in that place. +    Expr *filler = E->getArrayFiller(); +    for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) +      Writer.AddStmt(E->getInit(I) != filler ? E->getInit(I) : 0); +  } else { +    for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) +      Writer.AddStmt(E->getInit(I)); +  } +  Code = serialization::EXPR_INIT_LIST; +} + +void ASTStmtWriter::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(serialization::DESIG_FIELD_DECL); +        Writer.AddDeclRef(Field, Record); +      } else { +        Record.push_back(serialization::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(serialization::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(serialization::DESIG_ARRAY_RANGE); +      Record.push_back(D->getFirstExprIndex()); +      Writer.AddSourceLocation(D->getLBracketLoc(), Record); +      Writer.AddSourceLocation(D->getEllipsisLoc(), Record); +      Writer.AddSourceLocation(D->getRBracketLoc(), Record); +    } +  } +  Code = serialization::EXPR_DESIGNATED_INIT; +} + +void ASTStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { +  VisitExpr(E); +  Code = serialization::EXPR_IMPLICIT_VALUE_INIT; +} + +void ASTStmtWriter::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 = serialization::EXPR_VA_ARG; +} + +void ASTStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getAmpAmpLoc(), Record); +  Writer.AddSourceLocation(E->getLabelLoc(), Record); +  Writer.AddDeclRef(E->getLabel(), Record); +  Code = serialization::EXPR_ADDR_LABEL; +} + +void ASTStmtWriter::VisitStmtExpr(StmtExpr *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getSubStmt()); +  Writer.AddSourceLocation(E->getLParenLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_STMT; +} + +void ASTStmtWriter::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 = serialization::EXPR_CHOOSE; +} + +void ASTStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getTokenLocation(), Record); +  Code = serialization::EXPR_GNU_NULL; +} + +void ASTStmtWriter::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 = serialization::EXPR_SHUFFLE_VECTOR; +} + +void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) { +  VisitExpr(E); +  Writer.AddDeclRef(E->getBlockDecl(), Record); +  Code = serialization::EXPR_BLOCK; +} + +void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getNumAssocs()); + +  Writer.AddStmt(E->getControllingExpr()); +  for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { +    Writer.AddTypeSourceInfo(E->getAssocTypeSourceInfo(I), Record); +    Writer.AddStmt(E->getAssocExpr(I)); +  } +  Record.push_back(E->isResultDependent() ? -1U : E->getResultIndex()); + +  Writer.AddSourceLocation(E->getGenericLoc(), Record); +  Writer.AddSourceLocation(E->getDefaultLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_GENERIC_SELECTION; +} + +void ASTStmtWriter::VisitPseudoObjectExpr(PseudoObjectExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getNumSemanticExprs()); + +  // Push the result index.  Currently, this needs to exactly match +  // the encoding used internally for ResultIndex. +  unsigned result = E->getResultExprIndex(); +  result = (result == PseudoObjectExpr::NoResult ? 0 : result + 1); +  Record.push_back(result); + +  Writer.AddStmt(E->getSyntacticForm()); +  for (PseudoObjectExpr::semantics_iterator +         i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { +    Writer.AddStmt(*i); +  } +  Code = serialization::EXPR_PSEUDO_OBJECT; +} + +void ASTStmtWriter::VisitAtomicExpr(AtomicExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getOp()); +  for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) +    Writer.AddStmt(E->getSubExprs()[I]); +  Writer.AddSourceLocation(E->getBuiltinLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_ATOMIC; +} + +//===----------------------------------------------------------------------===// +// Objective-C Expressions and Statements. +//===----------------------------------------------------------------------===// + +void ASTStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getString()); +  Writer.AddSourceLocation(E->getAtLoc(), Record); +  Code = serialization::EXPR_OBJC_STRING_LITERAL; +} + +void ASTStmtWriter::VisitObjCNumericLiteral(ObjCNumericLiteral *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getNumber()); +  Writer.AddDeclRef(E->getObjCNumericLiteralMethod(), Record); +  Writer.AddSourceLocation(E->getAtLoc(), Record); +  Code = serialization::EXPR_OBJC_NUMERIC_LITERAL; +} + +void ASTStmtWriter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { +  VisitExpr(E); +  Record.push_back(E->getNumElements()); +  for (unsigned i = 0; i < E->getNumElements(); i++) +    Writer.AddStmt(E->getElement(i)); +  Writer.AddDeclRef(E->getArrayWithObjectsMethod(), Record); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  Code = serialization::EXPR_OBJC_ARRAY_LITERAL; +} + +void ASTStmtWriter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { +  VisitExpr(E); +  Record.push_back(E->getNumElements()); +  Record.push_back(E->HasPackExpansions); +  for (unsigned i = 0; i < E->getNumElements(); i++) { +    ObjCDictionaryElement Element = E->getKeyValueElement(i); +    Writer.AddStmt(Element.Key); +    Writer.AddStmt(Element.Value); +    if (E->HasPackExpansions) { +      Writer.AddSourceLocation(Element.EllipsisLoc, Record); +      unsigned NumExpansions = 0; +      if (Element.NumExpansions) +        NumExpansions = *Element.NumExpansions + 1; +      Record.push_back(NumExpansions); +    } +  } +     +  Writer.AddDeclRef(E->getDictWithObjectsMethod(), Record); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  Code = serialization::EXPR_OBJC_DICTIONARY_LITERAL; +} + +void ASTStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { +  VisitExpr(E); +  Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record); +  Writer.AddSourceLocation(E->getAtLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_OBJC_ENCODE; +} + +void ASTStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { +  VisitExpr(E); +  Writer.AddSelectorRef(E->getSelector(), Record); +  Writer.AddSourceLocation(E->getAtLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_OBJC_SELECTOR_EXPR; +} + +void ASTStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { +  VisitExpr(E); +  Writer.AddDeclRef(E->getProtocol(), Record); +  Writer.AddSourceLocation(E->getAtLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_OBJC_PROTOCOL_EXPR; +} + +void ASTStmtWriter::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 = serialization::EXPR_OBJC_IVAR_REF_EXPR; +} + +void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { +  VisitExpr(E); +  Record.push_back(E->SetterAndMethodRefFlags.getInt()); +  Record.push_back(E->isImplicitProperty()); +  if (E->isImplicitProperty()) { +    Writer.AddDeclRef(E->getImplicitPropertyGetter(), Record); +    Writer.AddDeclRef(E->getImplicitPropertySetter(), Record); +  } else { +    Writer.AddDeclRef(E->getExplicitProperty(), Record); +  } +  Writer.AddSourceLocation(E->getLocation(), Record); +  Writer.AddSourceLocation(E->getReceiverLocation(), Record); +  if (E->isObjectReceiver()) { +    Record.push_back(0); +    Writer.AddStmt(E->getBase()); +  } else if (E->isSuperReceiver()) { +    Record.push_back(1); +    Writer.AddTypeRef(E->getSuperReceiverType(), Record); +  } else { +    Record.push_back(2); +    Writer.AddDeclRef(E->getClassReceiver(), Record); +  } +   +  Code = serialization::EXPR_OBJC_PROPERTY_REF_EXPR; +} + +void ASTStmtWriter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getRBracket(), Record); +  Writer.AddStmt(E->getBaseExpr()); +  Writer.AddStmt(E->getKeyExpr()); +  Writer.AddDeclRef(E->getAtIndexMethodDecl(), Record); +  Writer.AddDeclRef(E->setAtIndexMethodDecl(), Record); +   +  Code = serialization::EXPR_OBJC_SUBSCRIPT_REF_EXPR; +} + +void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getNumArgs()); +  Record.push_back(E->getNumStoredSelLocs()); +  Record.push_back(E->SelLocsKind); +  Record.push_back(E->isDelegateInitCall()); +  Record.push_back(E->IsImplicit); +  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); + +  SourceLocation *Locs = E->getStoredSelLocs(); +  for (unsigned i = 0, e = E->getNumStoredSelLocs(); i != e; ++i) +    Writer.AddSourceLocation(Locs[i], Record); + +  Code = serialization::EXPR_OBJC_MESSAGE_EXPR; +} + +void ASTStmtWriter::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 = serialization::STMT_OBJC_FOR_COLLECTION; +} + +void ASTStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { +  Writer.AddStmt(S->getCatchBody()); +  Writer.AddDeclRef(S->getCatchParamDecl(), Record); +  Writer.AddSourceLocation(S->getAtCatchLoc(), Record); +  Writer.AddSourceLocation(S->getRParenLoc(), Record); +  Code = serialization::STMT_OBJC_CATCH; +} + +void ASTStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { +  Writer.AddStmt(S->getFinallyBody()); +  Writer.AddSourceLocation(S->getAtFinallyLoc(), Record); +  Code = serialization::STMT_OBJC_FINALLY; +} + +void ASTStmtWriter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { +  Writer.AddStmt(S->getSubStmt()); +  Writer.AddSourceLocation(S->getAtLoc(), Record); +  Code = serialization::STMT_OBJC_AUTORELEASE_POOL; +} + +void ASTStmtWriter::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 = serialization::STMT_OBJC_AT_TRY; +} + +void ASTStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { +  Writer.AddStmt(S->getSynchExpr()); +  Writer.AddStmt(S->getSynchBody()); +  Writer.AddSourceLocation(S->getAtSynchronizedLoc(), Record); +  Code = serialization::STMT_OBJC_AT_SYNCHRONIZED; +} + +void ASTStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { +  Writer.AddStmt(S->getThrowExpr()); +  Writer.AddSourceLocation(S->getThrowLoc(), Record); +  Code = serialization::STMT_OBJC_AT_THROW; +} + +void ASTStmtWriter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getValue()); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Code = serialization::EXPR_OBJC_BOOL_LITERAL; +} + +//===----------------------------------------------------------------------===// +// C++ Expressions and Statements. +//===----------------------------------------------------------------------===// + +void ASTStmtWriter::VisitCXXCatchStmt(CXXCatchStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getCatchLoc(), Record); +  Writer.AddDeclRef(S->getExceptionDecl(), Record); +  Writer.AddStmt(S->getHandlerBlock()); +  Code = serialization::STMT_CXX_CATCH; +} + +void ASTStmtWriter::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 = serialization::STMT_CXX_TRY; +} + +void ASTStmtWriter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getForLoc(), Record); +  Writer.AddSourceLocation(S->getColonLoc(), Record); +  Writer.AddSourceLocation(S->getRParenLoc(), Record); +  Writer.AddStmt(S->getRangeStmt()); +  Writer.AddStmt(S->getBeginEndStmt()); +  Writer.AddStmt(S->getCond()); +  Writer.AddStmt(S->getInc()); +  Writer.AddStmt(S->getLoopVarStmt()); +  Writer.AddStmt(S->getBody()); +  Code = serialization::STMT_CXX_FOR_RANGE; +} + +void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getKeywordLoc(), Record); +  Record.push_back(S->isIfExists()); +  Writer.AddNestedNameSpecifierLoc(S->getQualifierLoc(), Record); +  Writer.AddDeclarationNameInfo(S->getNameInfo(), Record); +  Writer.AddStmt(S->getSubStmt()); +  Code = serialization::STMT_MS_DEPENDENT_EXISTS; +} + +void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { +  VisitCallExpr(E); +  Record.push_back(E->getOperator()); +  Code = serialization::EXPR_CXX_OPERATOR_CALL; +} + +void ASTStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { +  VisitCallExpr(E); +  Code = serialization::EXPR_CXX_MEMBER_CALL; +} + +void ASTStmtWriter::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->hadMultipleCandidates()); +  Record.push_back(E->requiresZeroInitialization()); +  Record.push_back(E->getConstructionKind()); // FIXME: stable encoding +  Writer.AddSourceRange(E->getParenRange(), Record); +  Code = serialization::EXPR_CXX_CONSTRUCT; +} + +void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { +  VisitCXXConstructExpr(E); +  Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); +  Code = serialization::EXPR_CXX_TEMPORARY_OBJECT; +} + +void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) { +  VisitExpr(E); +  Record.push_back(E->NumCaptures); +  unsigned NumArrayIndexVars = 0; +  if (E->HasArrayIndexVars) +    NumArrayIndexVars = E->getArrayIndexStarts()[E->NumCaptures]; +  Record.push_back(NumArrayIndexVars); +  Writer.AddSourceRange(E->IntroducerRange, Record); +  Record.push_back(E->CaptureDefault); // FIXME: stable encoding +  Record.push_back(E->ExplicitParams); +  Record.push_back(E->ExplicitResultType); +  Writer.AddSourceLocation(E->ClosingBrace, Record); +   +  // Add capture initializers. +  for (LambdaExpr::capture_init_iterator C = E->capture_init_begin(), +                                      CEnd = E->capture_init_end(); +       C != CEnd; ++C) { +    Writer.AddStmt(*C); +  } +   +  // Add array index variables, if any. +  if (NumArrayIndexVars) { +    Record.append(E->getArrayIndexStarts(),  +                  E->getArrayIndexStarts() + E->NumCaptures + 1); +    VarDecl **ArrayIndexVars = E->getArrayIndexVars(); +    for (unsigned I = 0; I != NumArrayIndexVars; ++I) +      Writer.AddDeclRef(ArrayIndexVars[I], Record); +  } +   +  Code = serialization::EXPR_LAMBDA; +} + +void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { +  VisitExplicitCastExpr(E); +  Writer.AddSourceRange(SourceRange(E->getOperatorLoc(), E->getRParenLoc()), +                        Record); +} + +void ASTStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { +  VisitCXXNamedCastExpr(E); +  Code = serialization::EXPR_CXX_STATIC_CAST; +} + +void ASTStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { +  VisitCXXNamedCastExpr(E); +  Code = serialization::EXPR_CXX_DYNAMIC_CAST; +} + +void ASTStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) { +  VisitCXXNamedCastExpr(E); +  Code = serialization::EXPR_CXX_REINTERPRET_CAST; +} + +void ASTStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) { +  VisitCXXNamedCastExpr(E); +  Code = serialization::EXPR_CXX_CONST_CAST; +} + +void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { +  VisitExplicitCastExpr(E); +  Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_CXX_FUNCTIONAL_CAST; +} + +void ASTStmtWriter::VisitUserDefinedLiteral(UserDefinedLiteral *E) { +  VisitCallExpr(E); +  Writer.AddSourceLocation(E->UDSuffixLoc, Record); +  Code = serialization::EXPR_USER_DEFINED_LITERAL; +} + +void ASTStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getValue()); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Code = serialization::EXPR_CXX_BOOL_LITERAL; +} + +void ASTStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Code = serialization::EXPR_CXX_NULL_PTR_LITERAL; +} + +void ASTStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { +  VisitExpr(E); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  if (E->isTypeOperand()) { +    Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record); +    Code = serialization::EXPR_CXX_TYPEID_TYPE; +  } else { +    Writer.AddStmt(E->getExprOperand()); +    Code = serialization::EXPR_CXX_TYPEID_EXPR; +  } +} + +void ASTStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Record.push_back(E->isImplicit()); +  Code = serialization::EXPR_CXX_THIS; +} + +void ASTStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getThrowLoc(), Record); +  Writer.AddStmt(E->getSubExpr()); +  Record.push_back(E->isThrownVariableInScope()); +  Code = serialization::EXPR_CXX_THROW; +} + +void ASTStmtWriter::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 = serialization::EXPR_CXX_DEFAULT_ARG; +} + +void ASTStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { +  VisitExpr(E); +  Writer.AddCXXTemporary(E->getTemporary(), Record); +  Writer.AddStmt(E->getSubExpr()); +  Code = serialization::EXPR_CXX_BIND_TEMPORARY; +} + +void ASTStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { +  VisitExpr(E); +  Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_CXX_SCALAR_VALUE_INIT; +} + +void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { +  VisitExpr(E); +  Record.push_back(E->isGlobalNew()); +  Record.push_back(E->isArray()); +  Record.push_back(E->doesUsualArrayDeleteWantSize()); +  Record.push_back(E->getNumPlacementArgs()); +  Record.push_back(E->StoredInitializationStyle); +  Writer.AddDeclRef(E->getOperatorNew(), Record); +  Writer.AddDeclRef(E->getOperatorDelete(), Record); +  Writer.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo(), Record); +  Writer.AddSourceRange(E->getTypeIdParens(), Record); +  Writer.AddSourceLocation(E->getStartLoc(), Record); +  Writer.AddSourceRange(E->getDirectInitRange(), Record); +  for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end(); +       I != e; ++I) +    Writer.AddStmt(*I); + +  Code = serialization::EXPR_CXX_NEW; +} + +void ASTStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { +  VisitExpr(E); +  Record.push_back(E->isGlobalDelete()); +  Record.push_back(E->isArrayForm()); +  Record.push_back(E->isArrayFormAsWritten()); +  Record.push_back(E->doesUsualArrayDeleteWantSize()); +  Writer.AddDeclRef(E->getOperatorDelete(), Record); +  Writer.AddStmt(E->getArgument()); +  Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record); +   +  Code = serialization::EXPR_CXX_DELETE; +} + +void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { +  VisitExpr(E); + +  Writer.AddStmt(E->getBase()); +  Record.push_back(E->isArrow()); +  Writer.AddSourceLocation(E->getOperatorLoc(), Record); +  Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), 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 = serialization::EXPR_CXX_PSEUDO_DESTRUCTOR; +} + +void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) { +  VisitExpr(E); +  Record.push_back(E->getNumObjects()); +  for (unsigned i = 0, e = E->getNumObjects(); i != e; ++i) +    Writer.AddDeclRef(E->getObject(i), Record); +   +  Writer.AddStmt(E->getSubExpr()); +  Code = serialization::EXPR_EXPR_WITH_CLEANUPS; +} + +void +ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ +  VisitExpr(E); + +  // Don't emit anything here, HasTemplateKWAndArgsInfo must be +  // emitted first. + +  Record.push_back(E->HasTemplateKWAndArgsInfo); +  if (E->HasTemplateKWAndArgsInfo) { +    const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo(); +    Record.push_back(Args.NumTemplateArgs); +    AddTemplateKWAndArgsInfo(Args); +  } + +  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.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); +  Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record); +  Writer.AddDeclarationNameInfo(E->MemberNameInfo, Record); +  Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER; +} + +void +ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { +  VisitExpr(E); + +  // Don't emit anything here, HasTemplateKWAndArgsInfo must be +  // emitted first. + +  Record.push_back(E->HasTemplateKWAndArgsInfo); +  if (E->HasTemplateKWAndArgsInfo) { +    const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo(); +    Record.push_back(Args.NumTemplateArgs); +    AddTemplateKWAndArgsInfo(Args); +  } + +  Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); +  Writer.AddDeclarationNameInfo(E->NameInfo, Record); +  Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF; +} + +void +ASTStmtWriter::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.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); +  Writer.AddSourceLocation(E->getLParenLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Code = serialization::EXPR_CXX_UNRESOLVED_CONSTRUCT; +} + +void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) { +  VisitExpr(E); + +  // Don't emit anything here, HasTemplateKWAndArgsInfo must be +  // emitted first. + +  Record.push_back(E->HasTemplateKWAndArgsInfo); +  if (E->HasTemplateKWAndArgsInfo) { +    const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo(); +    Record.push_back(Args.NumTemplateArgs); +    AddTemplateKWAndArgsInfo(Args); +  } + +  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()); +  } + +  Writer.AddDeclarationNameInfo(E->NameInfo, Record); +  Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); +} + +void ASTStmtWriter::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 = serialization::EXPR_CXX_UNRESOLVED_MEMBER; +} + +void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { +  VisitOverloadExpr(E); +  Record.push_back(E->requiresADL()); +  if (E->requiresADL()) +    Record.push_back(E->isStdAssociatedNamespace()); +  Record.push_back(E->isOverloaded()); +  Writer.AddDeclRef(E->getNamingClass(), Record); +  Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP; +} + +void ASTStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getTrait()); +  Record.push_back(E->getValue()); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(), Record); +  Code = serialization::EXPR_CXX_UNARY_TYPE_TRAIT; +} + +void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getTrait()); +  Record.push_back(E->getValue()); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  Writer.AddTypeSourceInfo(E->getLhsTypeSourceInfo(), Record); +  Writer.AddTypeSourceInfo(E->getRhsTypeSourceInfo(), Record); +  Code = serialization::EXPR_BINARY_TYPE_TRAIT; +} + +void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) { +  VisitExpr(E); +  Record.push_back(E->TypeTraitExprBits.NumArgs); +  Record.push_back(E->TypeTraitExprBits.Kind); // FIXME: Stable encoding +  Record.push_back(E->TypeTraitExprBits.Value); +  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) +    Writer.AddTypeSourceInfo(E->getArg(I), Record); +  Code = serialization::EXPR_TYPE_TRAIT; +} + +void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getTrait()); +  Record.push_back(E->getValue()); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(), Record); +  Code = serialization::EXPR_ARRAY_TYPE_TRAIT; +} + +void ASTStmtWriter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getTrait()); +  Record.push_back(E->getValue()); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  Writer.AddStmt(E->getQueriedExpression()); +  Code = serialization::EXPR_CXX_EXPRESSION_TRAIT; +} + +void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { +  VisitExpr(E); +  Record.push_back(E->getValue()); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  Writer.AddStmt(E->getOperand()); +  Code = serialization::EXPR_CXX_NOEXCEPT; +} + +void ASTStmtWriter::VisitPackExpansionExpr(PackExpansionExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getEllipsisLoc(), Record); +  Record.push_back(E->NumExpansions); +  Writer.AddStmt(E->getPattern()); +  Code = serialization::EXPR_PACK_EXPANSION; +} + +void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->OperatorLoc, Record); +  Writer.AddSourceLocation(E->PackLoc, Record); +  Writer.AddSourceLocation(E->RParenLoc, Record); +  Record.push_back(E->Length); +  Writer.AddDeclRef(E->Pack, Record); +  Code = serialization::EXPR_SIZEOF_PACK; +} + +void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr( +                                              SubstNonTypeTemplateParmExpr *E) { +  VisitExpr(E); +  Writer.AddDeclRef(E->getParameter(), Record); +  Writer.AddSourceLocation(E->getNameLoc(), Record); +  Writer.AddStmt(E->getReplacement()); +  Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM; +} + +void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr( +                                          SubstNonTypeTemplateParmPackExpr *E) { +  VisitExpr(E); +  Writer.AddDeclRef(E->getParameterPack(), Record); +  Writer.AddTemplateArgument(E->getArgumentPack(), Record); +  Writer.AddSourceLocation(E->getParameterPackLocation(), Record); +  Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK; +} + +void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { +  VisitExpr(E); +  Writer.AddStmt(E->Temporary); +  Code = serialization::EXPR_MATERIALIZE_TEMPORARY; +} + +void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { +  VisitExpr(E); +  Writer.AddStmt(E->getSourceExpr()); +  Writer.AddSourceLocation(E->getLocation(), Record); +  Code = serialization::EXPR_OPAQUE_VALUE; +} + +//===----------------------------------------------------------------------===// +// CUDA Expressions and Statements. +//===----------------------------------------------------------------------===// + +void ASTStmtWriter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) { +  VisitCallExpr(E); +  Writer.AddStmt(E->getConfig()); +  Code = serialization::EXPR_CUDA_KERNEL_CALL; +} + +//===----------------------------------------------------------------------===// +// OpenCL Expressions and Statements. +//===----------------------------------------------------------------------===// +void ASTStmtWriter::VisitAsTypeExpr(AsTypeExpr *E) { +  VisitExpr(E); +  Writer.AddSourceLocation(E->getBuiltinLoc(), Record); +  Writer.AddSourceLocation(E->getRParenLoc(), Record); +  Writer.AddStmt(E->getSrcExpr()); +  Code = serialization::EXPR_ASTYPE; +} + +//===----------------------------------------------------------------------===// +// Microsoft Expressions and Statements. +//===----------------------------------------------------------------------===// +void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) { +  VisitExpr(E); +  Writer.AddSourceRange(E->getSourceRange(), Record); +  if (E->isTypeOperand()) { +    Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record); +    Code = serialization::EXPR_CXX_UUIDOF_TYPE; +  } else { +    Writer.AddStmt(E->getExprOperand()); +    Code = serialization::EXPR_CXX_UUIDOF_EXPR; +  } +} + +void ASTStmtWriter::VisitSEHExceptStmt(SEHExceptStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getExceptLoc(), Record); +  Writer.AddStmt(S->getFilterExpr()); +  Writer.AddStmt(S->getBlock()); +  Code = serialization::STMT_SEH_EXCEPT; +} + +void ASTStmtWriter::VisitSEHFinallyStmt(SEHFinallyStmt *S) { +  VisitStmt(S); +  Writer.AddSourceLocation(S->getFinallyLoc(), Record); +  Writer.AddStmt(S->getBlock()); +  Code = serialization::STMT_SEH_FINALLY; +} + +void ASTStmtWriter::VisitSEHTryStmt(SEHTryStmt *S) { +  VisitStmt(S); +  Record.push_back(S->getIsCXXTry()); +  Writer.AddSourceLocation(S->getTryLoc(), Record); +  Writer.AddStmt(S->getTryBlock()); +  Writer.AddStmt(S->getHandler()); +  Code = serialization::STMT_SEH_TRY; +} + +//===----------------------------------------------------------------------===// +// ASTWriter Implementation +//===----------------------------------------------------------------------===// + +unsigned ASTWriter::RecordSwitchCaseID(SwitchCase *S) { +  assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && +         "SwitchCase recorded twice"); +  unsigned NextID = SwitchCaseIDs.size(); +  SwitchCaseIDs[S] = NextID; +  return NextID; +} + +unsigned ASTWriter::getSwitchCaseID(SwitchCase *S) { +  assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && +         "SwitchCase hasn't been seen yet"); +  return SwitchCaseIDs[S]; +} + +void ASTWriter::ClearSwitchCaseIDs() { +  SwitchCaseIDs.clear(); +} + +/// \brief Write the given substatement or subexpression to the +/// bitstream. +void ASTWriter::WriteSubStmt(Stmt *S, +                             llvm::DenseMap<Stmt *, uint64_t> &SubStmtEntries, +                             llvm::DenseSet<Stmt *> &ParentStmts) { +  RecordData Record; +  ASTStmtWriter Writer(*this, Record); +  ++NumStatements; +   +  if (!S) { +    Stream.EmitRecord(serialization::STMT_NULL_PTR, Record); +    return; +  } + +  llvm::DenseMap<Stmt *, uint64_t>::iterator I = SubStmtEntries.find(S); +  if (I != SubStmtEntries.end()) { +    Record.push_back(I->second); +    Stream.EmitRecord(serialization::STMT_REF_PTR, Record); +    return; +  } + +#ifndef NDEBUG +  assert(!ParentStmts.count(S) && "There is a Stmt cycle!"); + +  struct ParentStmtInserterRAII { +    Stmt *S; +    llvm::DenseSet<Stmt *> &ParentStmts; + +    ParentStmtInserterRAII(Stmt *S, llvm::DenseSet<Stmt *> &ParentStmts) +      : S(S), ParentStmts(ParentStmts) { +      ParentStmts.insert(S); +    } +    ~ParentStmtInserterRAII() { +      ParentStmts.erase(S); +    } +  }; + +  ParentStmtInserterRAII ParentStmtInserter(S, ParentStmts); +#endif + +  // Redirect ASTWriter::AddStmt to collect sub stmts. +  SmallVector<Stmt *, 16> SubStmts; +  CollectedStmts = &SubStmts; + +  Writer.Code = serialization::STMT_NULL_PTR; +  Writer.AbbrevToUse = 0; +  Writer.Visit(S); +   +#ifndef NDEBUG +  if (Writer.Code == serialization::STMT_NULL_PTR) { +    SourceManager &SrcMgr +      = DeclIDs.begin()->first->getASTContext().getSourceManager(); +    S->dump(SrcMgr); +    llvm_unreachable("Unhandled sub statement writing AST file"); +  } +#endif + +  // Revert ASTWriter::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(), SubStmtEntries, ParentStmts); +   +  Stream.EmitRecord(Writer.Code, Record, Writer.AbbrevToUse); +  +  SubStmtEntries[S] = Stream.GetCurrentBitNo(); +} + +/// \brief Flush all of the statements that have been added to the +/// queue via AddStmt(). +void ASTWriter::FlushStmts() { +  RecordData Record; + +  // We expect to be the only consumer of the two temporary statement maps, +  // assert that they are empty. +  assert(SubStmtEntries.empty() && "unexpected entries in sub stmt map"); +  assert(ParentStmts.empty() && "unexpected entries in parent stmt map"); + +  for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { +    WriteSubStmt(StmtsToEmit[I], SubStmtEntries, ParentStmts); +     +    assert(N == StmtsToEmit.size() && +           "Substatement written 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(serialization::STMT_STOP, Record); + +    SubStmtEntries.clear(); +    ParentStmts.clear(); +  } + +  StmtsToEmit.clear(); +} diff --git a/clang/lib/Serialization/CMakeLists.txt b/clang/lib/Serialization/CMakeLists.txt new file mode 100644 index 0000000..04c5382 --- /dev/null +++ b/clang/lib/Serialization/CMakeLists.txt @@ -0,0 +1,27 @@ +set(LLVM_USED_LIBS clangSema) + +add_clang_library(clangSerialization +  ASTCommon.h +  ASTReaderInternals.h +  ASTCommon.cpp +  ASTReader.cpp +  ASTReaderDecl.cpp +  ASTReaderStmt.cpp +  ASTWriter.cpp +  ASTWriterDecl.cpp +  ASTWriterStmt.cpp +  GeneratePCH.cpp +  Module.cpp +  ModuleManager.cpp +  ) + +add_dependencies(clangSerialization +  ClangAttrClasses +  ClangAttrList +  ClangAttrPCHRead +  ClangAttrPCHWrite +  ClangDiagnosticLex +  ClangDiagnosticSema +  ClangDiagnosticSerialization +  ClangDeclNodes +  ClangStmtNodes) diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp new file mode 100644 index 0000000..02aed10 --- /dev/null +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -0,0 +1,69 @@ +//===--- GeneratePCH.cpp - Sema 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 PCHGenerator, which as a SemaConsumer that generates +//  a PCH file. +// +//===----------------------------------------------------------------------===// + +#include "clang/Serialization/ASTWriter.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 "clang/Basic/FileSystemStatCache.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Support/raw_ostream.h" +#include <string> + +using namespace clang; + +PCHGenerator::PCHGenerator(const Preprocessor &PP, +                           StringRef OutputFile, +                           clang::Module *Module, +                           StringRef isysroot, +                           raw_ostream *OS) +  : PP(PP), OutputFile(OutputFile), Module(Module),  +    isysroot(isysroot.str()), 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(); +  PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/false); +} + +PCHGenerator::~PCHGenerator() { +} + +void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { +  if (PP.getDiagnostics().hasErrorOccurred()) +    return; +   +  // Emit the PCH file +  assert(SemaPtr && "No Sema?"); +  Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, Module, 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(); +} + +ASTMutationListener *PCHGenerator::GetASTMutationListener() { +  return &Writer; +} + +ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { +  return &Writer; +} diff --git a/clang/lib/Serialization/Makefile b/clang/lib/Serialization/Makefile new file mode 100644 index 0000000..e89ddc3 --- /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/Module.cpp b/clang/lib/Serialization/Module.cpp new file mode 100644 index 0000000..ff241d3 --- /dev/null +++ b/clang/lib/Serialization/Module.cpp @@ -0,0 +1,114 @@ +//===--- Module.cpp - Module description ------------------------*- 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 Module class, which describes a module that has +//  been loaded from an AST file. +// +//===----------------------------------------------------------------------===// +#include "clang/Serialization/Module.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/MemoryBuffer.h" +#include "ASTReaderInternals.h" + +using namespace clang; +using namespace serialization; +using namespace reader; + +ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) +  : Kind(Kind), DirectlyImported(false), Generation(Generation), SizeInBits(0),  +    LocalNumSLocEntries(0), SLocEntryBaseID(0), +    SLocEntryBaseOffset(0), SLocEntryOffsets(0), +    SLocFileOffsets(0), LocalNumIdentifiers(0),  +    IdentifierOffsets(0), BaseIdentifierID(0), IdentifierTableData(0), +    IdentifierLookupTable(0), BasePreprocessedEntityID(0), +    PreprocessedEntityOffsets(0), NumPreprocessedEntities(0), +    LocalNumHeaderFileInfos(0),  +    HeaderFileInfoTableData(0), HeaderFileInfoTable(0), +    HeaderFileFrameworkStrings(0), LocalNumSubmodules(0), BaseSubmoduleID(0), +    LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0), +    SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0), +    DeclOffsets(0), BaseDeclID(0), +    LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0), +    FileSortedDecls(0), RedeclarationsMap(0), LocalNumRedeclarationsInMap(0), +    ObjCCategoriesMap(0), LocalNumObjCCategoriesInMap(0), +    LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0) +{} + +ModuleFile::~ModuleFile() { +  for (DeclContextInfosMap::iterator I = DeclContextInfos.begin(), +       E = DeclContextInfos.end(); +       I != E; ++I) { +    if (I->second.NameLookupTableData) +      delete I->second.NameLookupTableData; +  } +   +  delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable); +  delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable); +  delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable); +} + +template<typename Key, typename Offset, unsigned InitialCapacity> +static void  +dumpLocalRemap(StringRef Name, +               const ContinuousRangeMap<Key, Offset, InitialCapacity> &Map) { +  if (Map.begin() == Map.end()) +    return; +   +  typedef ContinuousRangeMap<Key, Offset, InitialCapacity> MapType; +  llvm::errs() << "  " << Name << ":\n"; +  for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();  +       I != IEnd; ++I) { +    llvm::errs() << "    " << I->first << " -> " << I->second << "\n"; +  } +} + +void ModuleFile::dump() { +  llvm::errs() << "\nModule: " << FileName << "\n"; +  if (!Imports.empty()) { +    llvm::errs() << "  Imports: "; +    for (unsigned I = 0, N = Imports.size(); I != N; ++I) { +      if (I) +        llvm::errs() << ", "; +      llvm::errs() << Imports[I]->FileName; +    } +    llvm::errs() << "\n"; +  } +   +  // Remapping tables. +  llvm::errs() << "  Base source location offset: " << SLocEntryBaseOffset  +               << '\n'; +  dumpLocalRemap("Source location offset local -> global map", SLocRemap); +   +  llvm::errs() << "  Base identifier ID: " << BaseIdentifierID << '\n' +               << "  Number of identifiers: " << LocalNumIdentifiers << '\n'; +  dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap); + +  llvm::errs() << "  Base submodule ID: " << BaseSubmoduleID << '\n' +               << "  Number of submodules: " << LocalNumSubmodules << '\n'; +  dumpLocalRemap("Submodule ID local -> global map", SubmoduleRemap); + +  llvm::errs() << "  Base selector ID: " << BaseSelectorID << '\n' +               << "  Number of selectors: " << LocalNumSelectors << '\n'; +  dumpLocalRemap("Selector ID local -> global map", SelectorRemap); +   +  llvm::errs() << "  Base preprocessed entity ID: " << BasePreprocessedEntityID +               << '\n'   +               << "  Number of preprocessed entities: "  +               << NumPreprocessedEntities << '\n'; +  dumpLocalRemap("Preprocessed entity ID local -> global map",  +                 PreprocessedEntityRemap); +   +  llvm::errs() << "  Base type index: " << BaseTypeIndex << '\n' +               << "  Number of types: " << LocalNumTypes << '\n'; +  dumpLocalRemap("Type index local -> global map", TypeRemap); +   +  llvm::errs() << "  Base decl ID: " << BaseDeclID << '\n' +               << "  Number of decls: " << LocalNumDecls << '\n'; +  dumpLocalRemap("Decl ID local -> global map", DeclRemap); +} diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp new file mode 100644 index 0000000..ab364b7 --- /dev/null +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -0,0 +1,254 @@ +//===--- ModuleManager.cpp - Module Manager ---------------------*- 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 ModuleManager class, which manages a set of loaded +//  modules for the ASTReader. +// +//===----------------------------------------------------------------------===// +#include "clang/Serialization/ModuleManager.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" + +#ifndef NDEBUG +#include "llvm/Support/GraphWriter.h" +#endif + +using namespace clang; +using namespace serialization; + +ModuleFile *ModuleManager::lookup(StringRef Name) { +  const FileEntry *Entry = FileMgr.getFile(Name); +  return Modules[Entry]; +} + +llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { +  const FileEntry *Entry = FileMgr.getFile(Name); +  return InMemoryBuffers[Entry]; +} + +std::pair<ModuleFile *, bool> +ModuleManager::addModule(StringRef FileName, ModuleKind Type,  +                         ModuleFile *ImportedBy, unsigned Generation, +                         std::string &ErrorStr) { +  const FileEntry *Entry = FileMgr.getFile(FileName); +  if (!Entry && FileName != "-") { +    ErrorStr = "file not found"; +    return std::make_pair(static_cast<ModuleFile*>(0), false); +  } +   +  // Check whether we already loaded this module, before  +  ModuleFile *&ModuleEntry = Modules[Entry]; +  bool NewModule = false; +  if (!ModuleEntry) { +    // Allocate a new module. +    ModuleFile *New = new ModuleFile(Type, Generation); +    New->FileName = FileName.str(); +    Chain.push_back(New); +    NewModule = true; +    ModuleEntry = New; +     +    // Load the contents of the module +    if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { +      // The buffer was already provided for us. +      assert(Buffer && "Passed null buffer"); +      New->Buffer.reset(Buffer); +    } else { +      // Open the AST file. +      llvm::error_code ec; +      if (FileName == "-") { +        ec = llvm::MemoryBuffer::getSTDIN(New->Buffer); +        if (ec) +          ErrorStr = ec.message(); +      } else +        New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); +       +      if (!New->Buffer) +        return std::make_pair(static_cast<ModuleFile*>(0), false); +    } +     +    // Initialize the stream +    New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), +                         (const unsigned char *)New->Buffer->getBufferEnd());     } +   +  if (ImportedBy) { +    ModuleEntry->ImportedBy.insert(ImportedBy); +    ImportedBy->Imports.insert(ModuleEntry); +  } else { +    ModuleEntry->DirectlyImported = true; +  } +   +  return std::make_pair(ModuleEntry, NewModule); +} + +void ModuleManager::addInMemoryBuffer(StringRef FileName,  +                                      llvm::MemoryBuffer *Buffer) { +   +  const FileEntry *Entry = FileMgr.getVirtualFile(FileName,  +                                                  Buffer->getBufferSize(), 0); +  InMemoryBuffers[Entry] = Buffer; +} + +ModuleManager::ModuleManager(const FileSystemOptions &FSO) : FileMgr(FSO) { } + +ModuleManager::~ModuleManager() { +  for (unsigned i = 0, e = Chain.size(); i != e; ++i) +    delete Chain[e - i - 1]; +} + +void ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),  +                          void *UserData) { +  unsigned N = size(); +   +  // Record the number of incoming edges for each module. When we +  // encounter a module with no incoming edges, push it into the queue +  // to seed the queue. +  SmallVector<ModuleFile *, 4> Queue; +  Queue.reserve(N); +  llvm::DenseMap<ModuleFile *, unsigned> UnusedIncomingEdges;  +  for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { +    if (unsigned Size = (*M)->ImportedBy.size()) +      UnusedIncomingEdges[*M] = Size; +    else +      Queue.push_back(*M); +  } +   +  llvm::SmallPtrSet<ModuleFile *, 4> Skipped; +  unsigned QueueStart = 0; +  while (QueueStart < Queue.size()) { +    ModuleFile *CurrentModule = Queue[QueueStart++]; +     +    // Check whether this module should be skipped. +    if (Skipped.count(CurrentModule)) +      continue; +     +    if (Visitor(*CurrentModule, UserData)) { +      // The visitor has requested that cut off visitation of any +      // module that the current module depends on. To indicate this +      // behavior, we mark all of the reachable modules as having N +      // incoming edges (which is impossible otherwise). +      SmallVector<ModuleFile *, 4> Stack; +      Stack.push_back(CurrentModule); +      Skipped.insert(CurrentModule); +      while (!Stack.empty()) { +        ModuleFile *NextModule = Stack.back(); +        Stack.pop_back(); +         +        // For any module that this module depends on, push it on the +        // stack (if it hasn't already been marked as visited). +        for (llvm::SetVector<ModuleFile *>::iterator  +             M = NextModule->Imports.begin(), +             MEnd = NextModule->Imports.end(); +             M != MEnd; ++M) { +          if (Skipped.insert(*M)) +            Stack.push_back(*M); +        } +      } +      continue; +    } +     +    // For any module that this module depends on, push it on the +    // stack (if it hasn't already been marked as visited). +    for (llvm::SetVector<ModuleFile *>::iterator M = CurrentModule->Imports.begin(), +         MEnd = CurrentModule->Imports.end(); +         M != MEnd; ++M) { +       +      // Remove our current module as an impediment to visiting the +      // module we depend on. If we were the last unvisited module +      // that depends on this particular module, push it into the +      // queue to be visited. +      unsigned &NumUnusedEdges = UnusedIncomingEdges[*M]; +      if (NumUnusedEdges && (--NumUnusedEdges == 0)) +        Queue.push_back(*M); +    } +  } +} + +/// \brief Perform a depth-first visit of the current module. +static bool visitDepthFirst(ModuleFile &M,  +                            bool (*Visitor)(ModuleFile &M, bool Preorder,  +                                            void *UserData),  +                            void *UserData, +                            llvm::SmallPtrSet<ModuleFile *, 4> &Visited) { +  // Preorder visitation +  if (Visitor(M, /*Preorder=*/true, UserData)) +    return true; +   +  // Visit children +  for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(), +       IMEnd = M.Imports.end(); +       IM != IMEnd; ++IM) { +    if (!Visited.insert(*IM)) +      continue; +     +    if (visitDepthFirst(**IM, Visitor, UserData, Visited)) +      return true; +  }   +   +  // Postorder visitation +  return Visitor(M, /*Preorder=*/false, UserData); +} + +void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder,  +                                                    void *UserData),  +                                    void *UserData) { +  llvm::SmallPtrSet<ModuleFile *, 4> Visited; +  for (unsigned I = 0, N = Chain.size(); I != N; ++I) { +    if (!Visited.insert(Chain[I])) +      continue; +     +    if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited)) +      return; +  } +} + +#ifndef NDEBUG +namespace llvm { +  template<> +  struct GraphTraits<ModuleManager> { +    typedef ModuleFile NodeType; +    typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType; +    typedef ModuleManager::ModuleConstIterator nodes_iterator; +     +    static ChildIteratorType child_begin(NodeType *Node) { +      return Node->Imports.begin(); +    } + +    static ChildIteratorType child_end(NodeType *Node) { +      return Node->Imports.end(); +    } +     +    static nodes_iterator nodes_begin(const ModuleManager &Manager) { +      return Manager.begin(); +    } +     +    static nodes_iterator nodes_end(const ModuleManager &Manager) { +      return Manager.end(); +    } +  }; +   +  template<> +  struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits { +    explicit DOTGraphTraits(bool IsSimple = false) +      : DefaultDOTGraphTraits(IsSimple) { } +     +    static bool renderGraphFromBottomUp() { +      return true; +    } + +    std::string getNodeLabel(ModuleFile *M, const ModuleManager&) { +      return llvm::sys::path::stem(M->FileName); +    } +  }; +} + +void ModuleManager::viewGraph() { +  llvm::ViewGraph(*this, "Modules"); +} +#endif  | 
