diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp | 4300 |
1 files changed, 2247 insertions, 2053 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index a4ed5f4..fe1cc30 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -13,7 +13,9 @@ #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTDeserializationListener.h" +#include "clang/Serialization/ModuleManager.h" #include "ASTCommon.h" +#include "ASTReaderInternals.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" #include "clang/Sema/Sema.h" @@ -52,6 +54,7 @@ using namespace clang; using namespace clang::serialization; +using namespace clang::serialization::reader; //===----------------------------------------------------------------------===// // PCH validator implementation @@ -62,103 +65,36 @@ ASTReaderListener::~ASTReaderListener() {} bool PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { const LangOptions &PPLangOpts = PP.getLangOptions(); -#define PARSE_LANGOPT_BENIGN(Option) -#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \ - if (PPLangOpts.Option != LangOpts.Option) { \ - Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \ - return true; \ - } - - PARSE_LANGOPT_BENIGN(Trigraphs); - PARSE_LANGOPT_BENIGN(BCPLComment); - PARSE_LANGOPT_BENIGN(DollarIdents); - PARSE_LANGOPT_BENIGN(AsmPreprocessor); - PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions); - PARSE_LANGOPT_IMPORTANT(GNUKeywords, diag::warn_pch_gnu_keywords); - PARSE_LANGOPT_BENIGN(ImplicitInt); - PARSE_LANGOPT_BENIGN(Digraphs); - PARSE_LANGOPT_BENIGN(HexFloats); - PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99); - PARSE_LANGOPT_IMPORTANT(C1X, diag::warn_pch_c1x); - PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions); - PARSE_LANGOPT_BENIGN(MSCVersion); - PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus); - PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x); - PARSE_LANGOPT_BENIGN(CXXOperatorName); - PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c); - PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2); - PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi); - PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2); - PARSE_LANGOPT_IMPORTANT(AppleKext, diag::warn_pch_apple_kext); - PARSE_LANGOPT_IMPORTANT(ObjCDefaultSynthProperties, - diag::warn_pch_objc_auto_properties); - PARSE_LANGOPT_BENIGN(ObjCInferRelatedResultType) - PARSE_LANGOPT_IMPORTANT(NoConstantCFStrings, - diag::warn_pch_no_constant_cfstrings); - PARSE_LANGOPT_BENIGN(PascalStrings); - PARSE_LANGOPT_BENIGN(WritableStrings); - PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, - diag::warn_pch_lax_vector_conversions); - PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec); - PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions); - PARSE_LANGOPT_IMPORTANT(ObjCExceptions, diag::warn_pch_objc_exceptions); - PARSE_LANGOPT_IMPORTANT(CXXExceptions, diag::warn_pch_cxx_exceptions); - PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions); - PARSE_LANGOPT_IMPORTANT(MSBitfields, diag::warn_pch_ms_bitfields); - PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime); - PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding); - PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins); - PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics, - diag::warn_pch_thread_safe_statics); - PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads); - PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks); - PARSE_LANGOPT_BENIGN(EmitAllDecls); - PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno); - PARSE_LANGOPT_BENIGN(getSignedOverflowBehavior()); - PARSE_LANGOPT_IMPORTANT(HeinousExtensions, - diag::warn_pch_heinous_extensions); - // FIXME: Most of the options below are benign if the macro wasn't - // used. Unfortunately, this means that a PCH compiled without - // optimization can't be used with optimization turned on, even - // though the only thing that changes is whether __OPTIMIZE__ was - // defined... but if __OPTIMIZE__ never showed up in the header, it - // doesn't matter. We could consider making this some special kind - // of check. - PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize); - PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size); - PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static); - PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level); - PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline); - PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline); - PARSE_LANGOPT_IMPORTANT(Deprecated, diag::warn_pch_deprecated); - PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control); - PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed); - PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar); - PARSE_LANGOPT_IMPORTANT(ShortEnums, diag::warn_pch_short_enums); - if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) { - Reader.Diag(diag::warn_pch_gc_mode) - << LangOpts.getGCMode() << PPLangOpts.getGCMode(); - return true; + +#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; \ } - PARSE_LANGOPT_BENIGN(getVisibilityMode()); - PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(), - diag::warn_pch_stack_protector); - PARSE_LANGOPT_BENIGN(InstantiationDepth); - PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl); - PARSE_LANGOPT_IMPORTANT(CUDA, diag::warn_pch_cuda); - PARSE_LANGOPT_BENIGN(CatchUndefined); - PARSE_LANGOPT_BENIGN(DefaultFPContract); - PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors); - PARSE_LANGOPT_BENIGN(SpellChecking); - PARSE_LANGOPT_IMPORTANT(ObjCAutoRefCount, diag::warn_pch_auto_ref_count); - PARSE_LANGOPT_BENIGN(ObjCInferRelatedReturnType); -#undef PARSE_LANGOPT_IMPORTANT -#undef PARSE_LANGOPT_BENIGN +#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(llvm::StringRef Triple) { +bool PCHValidator::ReadTargetTriple(StringRef Triple) { if (Triple == PP.getTargetInfo().getTriple().str()) return false; @@ -169,14 +105,14 @@ bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) { namespace { struct EmptyStringRef { - bool operator ()(llvm::StringRef r) const { return r.empty(); } + bool operator ()(StringRef r) const { return r.empty(); } }; struct EmptyBlock { bool operator ()(const PCHPredefinesBlock &r) const {return r.Data.empty();} }; } -static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L, +static bool EqualConcatenations(SmallVector<StringRef, 2> L, PCHPredefinesBlocks R) { // First, sum up the lengths. unsigned LL = 0, RL = 0; @@ -196,7 +132,7 @@ static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L, R.erase(std::remove_if(R.begin(), R.end(), EmptyBlock()), R.end()); // Do it the hard way. At this point, both vectors must be non-empty. - llvm::StringRef LR = L[0], RR = R[0].Data; + StringRef LR = L[0], RR = R[0].Data; unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size(); (void) RN; for (;;) { @@ -236,12 +172,12 @@ static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L, } } -static std::pair<FileID, llvm::StringRef::size_type> -FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) { - std::pair<FileID, llvm::StringRef::size_type> Res; +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 != llvm::StringRef::npos) { + if (Res.second != StringRef::npos) { Res.first = Buffers[I].BufferID; break; } @@ -250,7 +186,7 @@ FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) { } bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - llvm::StringRef OriginalFileName, + StringRef OriginalFileName, std::string &SuggestedPredefines, FileManager &FileMgr) { // We are in the context of an implicit include, so the predefines buffer will @@ -261,9 +197,9 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, PCHInclude += "#include \""; PCHInclude += NormalizeDashIncludePath(OriginalFileName, FileMgr); PCHInclude += "\"\n"; - std::pair<llvm::StringRef,llvm::StringRef> Split = - llvm::StringRef(PP.getPredefines()).split(PCHInclude.str()); - llvm::StringRef Left = Split.first, Right = Split.second; + 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; @@ -271,7 +207,7 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, // If the concatenation of all the PCH buffers is equal to the adjusted // command line, we're done. - llvm::SmallVector<llvm::StringRef, 2> CommandLine; + SmallVector<StringRef, 2> CommandLine; CommandLine.push_back(Left); CommandLine.push_back(Right); if (EqualConcatenations(CommandLine, Buffers)) @@ -281,18 +217,18 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, // The predefines buffers are different. Determine what the differences are, // and whether they require us to reject the PCH file. - llvm::SmallVector<llvm::StringRef, 8> PCHLines; + SmallVector<StringRef, 8> PCHLines; for (unsigned I = 0, N = Buffers.size(); I != N; ++I) Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - llvm::SmallVector<llvm::StringRef, 8> CmdLineLines; + 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; - llvm::SmallVector<llvm::StringRef, 8> AfterPCHLines; + 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 ")) { @@ -325,7 +261,7 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, // Determine which predefines that were used to build the PCH file are missing // from the command line. - std::vector<llvm::StringRef> MissingPredefines; + std::vector<StringRef> MissingPredefines; std::set_difference(PCHLines.begin(), PCHLines.end(), CmdLineLines.begin(), CmdLineLines.end(), std::back_inserter(MissingPredefines)); @@ -333,7 +269,7 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, bool MissingDefines = false; bool ConflictingDefines = false; for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) { - llvm::StringRef Missing = MissingPredefines[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. @@ -351,13 +287,13 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, = Missing.find_first_of("( \n\r", StartOfMacroName); assert(EndOfMacroName != std::string::npos && "Couldn't find the end of the macro name"); - llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName); + StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName); // Determine whether this macro was given a different definition on the // command line. std::string MacroDefStart = "#define " + MacroName.str(); std::string::size_type MacroDefLen = MacroDefStart.size(); - llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos + SmallVector<StringRef, 8>::iterator ConflictPos = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(), MacroDefStart); for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) { @@ -382,12 +318,12 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, << MacroName; // Show the definition of this macro within the PCH file. - std::pair<FileID, llvm::StringRef::size_type> MacroLoc = + std::pair<FileID, StringRef::size_type> MacroLoc = FindMacro(Buffers, Missing); - assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!"); + assert(MacroLoc.second!=StringRef::npos && "Unable to find macro!"); SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(MacroLoc.first) - .getFileLocWithOffset(MacroLoc.second); + .getLocWithOffset(MacroLoc.second); Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName; ConflictingDefines = true; @@ -405,12 +341,12 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, } // Show the definition of this macro within the PCH file. - std::pair<FileID, llvm::StringRef::size_type> MacroLoc = + std::pair<FileID, StringRef::size_type> MacroLoc = FindMacro(Buffers, Missing); - assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!"); + assert(MacroLoc.second!=StringRef::npos && "Unable to find macro!"); SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(MacroLoc.first) - .getFileLocWithOffset(MacroLoc.second); + .getLocWithOffset(MacroLoc.second); Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch); } @@ -421,12 +357,12 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, // parameters that were not present when building the PCH // file. Extra #defines are okay, so long as the identifiers being // defined were not used within the precompiled header. - std::vector<llvm::StringRef> ExtraPredefines; + std::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) { - llvm::StringRef &Extra = ExtraPredefines[I]; + StringRef &Extra = ExtraPredefines[I]; if (!Extra.startswith("#define ")) { Reader.Diag(diag::warn_pch_compiler_options_mismatch); return true; @@ -439,7 +375,7 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, = Extra.find_first_of("( \n\r", StartOfMacroName); assert(EndOfMacroName != std::string::npos && "Couldn't find the end of the macro name"); - llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName); + 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 @@ -479,440 +415,321 @@ ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) { } -namespace { -class ASTSelectorLookupTrait { - ASTReader &Reader; -public: - struct data_type { - SelectorID ID; - ObjCMethodList Instance, Factory; - }; +unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) { + return serialization::ComputeHash(Sel); +} - typedef Selector external_key_type; - typedef external_key_type internal_key_type; - explicit ASTSelectorLookupTrait(ASTReader &Reader) : Reader(Reader) { } +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); +} - static bool EqualKey(const internal_key_type& a, - const internal_key_type& b) { - return a == b; - } +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); - static unsigned ComputeHash(Selector Sel) { - return serialization::ComputeHash(Sel); - } + SmallVector<IdentifierInfo *, 16> Args; + Args.push_back(FirstII); + for (unsigned I = 1; I != N; ++I) + Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d))); - // This hopefully will just get inlined and removed by the optimizer. - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } + return SelTable.getSelector(N, Args.data()); +} - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); - return std::make_pair(KeyLen, DataLen); - } +ASTSelectorLookupTrait::data_type +ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, + unsigned DataLen) { + using namespace clang::io; - internal_key_type ReadKey(const unsigned char* d, unsigned) { - using namespace clang::io; - SelectorTable &SelTable = Reader.getContext()->Selectors; - unsigned N = ReadUnalignedLE16(d); - IdentifierInfo *FirstII - = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)); - if (N == 0) - return SelTable.getNullarySelector(FirstII); - else if (N == 1) - return SelTable.getUnarySelector(FirstII); + data_type Result; - llvm::SmallVector<IdentifierInfo *, 16> Args; - Args.push_back(FirstII); - for (unsigned I = 1; I != N; ++I) - Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d))); + Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d)); + unsigned NumInstanceMethods = ReadUnalignedLE16(d); + unsigned NumFactoryMethods = ReadUnalignedLE16(d); - return SelTable.getSelector(N, Args.data()); + // Load instance methods + for (unsigned I = 0; I != NumInstanceMethods; ++I) { + if (ObjCMethodDecl *Method + = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d))) + Result.Instance.push_back(Method); } - data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; - - data_type Result; - - Result.ID = ReadUnalignedLE32(d); - unsigned NumInstanceMethods = ReadUnalignedLE16(d); - unsigned NumFactoryMethods = ReadUnalignedLE16(d); - - // Load instance methods - ObjCMethodList *Prev = 0; - for (unsigned I = 0; I != NumInstanceMethods; ++I) { - ObjCMethodDecl *Method - = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); - if (!Result.Instance.Method) { - // This is the first method, which is the easy case. - Result.Instance.Method = Method; - Prev = &Result.Instance; - continue; - } - - ObjCMethodList *Mem = - Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); - Prev->Next = new (Mem) ObjCMethodList(Method, 0); - Prev = Prev->Next; - } - - // Load factory methods - Prev = 0; - for (unsigned I = 0; I != NumFactoryMethods; ++I) { - ObjCMethodDecl *Method - = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); - if (!Result.Factory.Method) { - // This is the first method, which is the easy case. - Result.Factory.Method = Method; - Prev = &Result.Factory; - continue; - } - - ObjCMethodList *Mem = - Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); - Prev->Next = new (Mem) ObjCMethodList(Method, 0); - Prev = Prev->Next; - } - - return Result; + // Load factory methods + for (unsigned I = 0; I != NumFactoryMethods; ++I) { + if (ObjCMethodDecl *Method + = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d))) + Result.Factory.push_back(Method); } -}; - -} // end anonymous namespace - -/// \brief The on-disk hash table used for the global method pool. -typedef OnDiskChainedHashTable<ASTSelectorLookupTrait> - ASTSelectorLookupTable; - -namespace clang { -class ASTIdentifierLookupTrait { - ASTReader &Reader; - ASTReader::PerFileData &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, ASTReader::PerFileData &F, - IdentifierInfo *II = 0) - : Reader(Reader), F(F), KnownII(II) { } + return Result; +} - 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; - } +unsigned ASTIdentifierLookupTrait::ComputeHash(const internal_key_type& a) { + return llvm::HashString(StringRef(a.first, a.second)); +} - static unsigned ComputeHash(const internal_key_type& a) { - return llvm::HashString(llvm::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); +} - // This hopefully will just get inlined and removed by the optimizer. - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } +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); +} - // This hopefully will just get inlined and removed by the optimizer. - static const external_key_type& - GetExternalKey(const internal_key_type& x) { return x; } +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; - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned DataLen = ReadUnalignedLE16(d); - unsigned KeyLen = ReadUnalignedLE16(d); - return std::make_pair(KeyLen, DataLen); - } + // Wipe out the "is interesting" bit. + RawID = RawID >> 1; - static std::pair<const char*, unsigned> - ReadKey(const unsigned char* d, unsigned n) { - assert(n >= 2 && d[n-1] == '\0'); - return std::make_pair((const char*) d, n-1); - } - - IdentifierInfo *ReadData(const internal_key_type& k, - const unsigned char* d, - unsigned DataLen) { - using namespace clang::io; - IdentID ID = ReadUnalignedLE32(d); - bool IsInteresting = ID & 0x01; - - // Wipe out the "is interesting" bit. - ID = ID >> 1; - - if (!IsInteresting) { - // For uninteresting identifiers, just build the IdentifierInfo - // and associate it with the persistent ID. - IdentifierInfo *II = KnownII; - if (!II) - II = &Reader.getIdentifierTable().getOwn(llvm::StringRef(k.first, - k.second)); - Reader.SetIdentifierInfo(ID, II); - II->setIsFromAST(); - return II; - } - - unsigned Bits = ReadUnalignedLE16(d); - bool CPlusPlusOperatorKeyword = Bits & 0x01; - Bits >>= 1; - bool HasRevertedTokenIDToIdentifier = Bits & 0x01; - Bits >>= 1; - bool Poisoned = Bits & 0x01; - Bits >>= 1; - bool ExtensionToken = Bits & 0x01; - Bits >>= 1; - bool hasMacroDefinition = Bits & 0x01; - Bits >>= 1; - unsigned ObjCOrBuiltinID = Bits & 0x3FF; - Bits >>= 10; - - assert(Bits == 0 && "Extra bits in the identifier?"); - DataLen -= 6; - - // Build the IdentifierInfo itself and link the identifier ID with - // the new IdentifierInfo. + 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(llvm::StringRef(k.first, - k.second)); + II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second)); Reader.SetIdentifierInfo(ID, II); - - // Set or check the various bits in the IdentifierInfo structure. - // Token IDs are read-only. - if (HasRevertedTokenIDToIdentifier) - II->RevertTokenIDToIdentifier(); - II->setObjCOrBuiltinID(ObjCOrBuiltinID); - assert(II->isExtensionToken() == ExtensionToken && - "Incorrect extension token flag"); - (void)ExtensionToken; - II->setIsPoisoned(Poisoned); - assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword && - "Incorrect C++ operator keyword flag"); - (void)CPlusPlusOperatorKeyword; - - // If this identifier is a macro, deserialize the macro - // definition. - if (hasMacroDefinition) { - uint32_t Offset = ReadUnalignedLE32(d); - Reader.SetIdentifierIsMacro(II, F, Offset); - DataLen -= 4; - } - - // Read all of the declarations visible at global scope with this - // name. - if (Reader.getContext() == 0) return II; - if (DataLen > 0) { - llvm::SmallVector<uint32_t, 4> DeclIDs; - for (; DataLen > 0; DataLen -= 4) - DeclIDs.push_back(ReadUnalignedLE32(d)); - Reader.SetGloballyVisibleDecls(II, DeclIDs); - } - II->setIsFromAST(); return II; } -}; - -} // end anonymous namespace - -/// \brief The on-disk hash table used to contain information about -/// all of the identifiers in the program. -typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait> - ASTIdentifierLookupTable; - -namespace { -class ASTDeclContextNameLookupTrait { - ASTReader &Reader; - -public: - /// \brief Pair of begin/end iterators for DeclIDs. - typedef std::pair<DeclID *, DeclID *> 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) : Reader(Reader) { } - - 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 { - 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::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - ID.AddInteger((TypeID)Key.Data); - break; - case DeclarationName::CXXOperatorName: - ID.AddInteger((OverloadedOperatorKind)Key.Data); - break; - case DeclarationName::CXXUsingDirective: - break; - } - - return ID.ComputeHash(); + unsigned Bits = ReadUnalignedLE16(d); + bool CPlusPlusOperatorKeyword = Bits & 0x01; + Bits >>= 1; + bool HasRevertedTokenIDToIdentifier = Bits & 0x01; + Bits >>= 1; + bool Poisoned = Bits & 0x01; + Bits >>= 1; + bool ExtensionToken = Bits & 0x01; + Bits >>= 1; + bool hasMacroDefinition = Bits & 0x01; + Bits >>= 1; + unsigned ObjCOrBuiltinID = Bits & 0x3FF; + Bits >>= 10; + + assert(Bits == 0 && "Extra bits in the identifier?"); + DataLen -= 6; + + // Build the IdentifierInfo itself and link the identifier ID with + // the new IdentifierInfo. + IdentifierInfo *II = KnownII; + if (!II) + II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second)); + Reader.SetIdentifierInfo(ID, II); + + // Set or check the various bits in the IdentifierInfo structure. + // Token IDs are read-only. + if (HasRevertedTokenIDToIdentifier) + II->RevertTokenIDToIdentifier(); + II->setObjCOrBuiltinID(ObjCOrBuiltinID); + assert(II->isExtensionToken() == ExtensionToken && + "Incorrect extension token flag"); + (void)ExtensionToken; + 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); + Reader.SetIdentifierIsMacro(II, F, Offset); + DataLen -= 4; + } + + // 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); + } + + II->setIsFromAST(); + 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; } - internal_key_type 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::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - Key.Data = Reader.GetTypeID(Name.getCXXNameType()); - break; - case DeclarationName::CXXOperatorName: - Key.Data = Name.getCXXOverloadedOperator(); - break; - case DeclarationName::CXXLiteralOperatorName: - Key.Data = (uint64_t)Name.getCXXLiteralIdentifier(); - break; - case DeclarationName::CXXUsingDirective: - break; - } + return ID.ComputeHash(); +} - return Key; +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; } - external_key_type GetExternalKey(const internal_key_type& Key) const { - ASTContext *Context = Reader.getContext(); - switch (Key.Kind) { - case DeclarationName::Identifier: - return DeclarationName((IdentifierInfo*)Key.Data); - - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - return DeclarationName(Selector(Key.Data)); + return Key; +} - case DeclarationName::CXXConstructorName: - return Context->DeclarationNames.getCXXConstructorName( - Context->getCanonicalType(Reader.GetType(Key.Data))); +ASTDeclContextNameLookupTrait::external_key_type +ASTDeclContextNameLookupTrait::GetExternalKey( + const internal_key_type& Key) const { + ASTContext &Context = Reader.getContext(); + switch (Key.Kind) { + case DeclarationName::Identifier: + return DeclarationName((IdentifierInfo*)Key.Data); - case DeclarationName::CXXDestructorName: - return Context->DeclarationNames.getCXXDestructorName( - Context->getCanonicalType(Reader.GetType(Key.Data))); + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + return DeclarationName(Selector(Key.Data)); - case DeclarationName::CXXConversionFunctionName: - return Context->DeclarationNames.getCXXConversionFunctionName( - Context->getCanonicalType(Reader.GetType(Key.Data))); + case DeclarationName::CXXConstructorName: + return Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(Reader.getLocalType(F, Key.Data))); - case DeclarationName::CXXOperatorName: - return Context->DeclarationNames.getCXXOperatorName( - (OverloadedOperatorKind)Key.Data); + case DeclarationName::CXXDestructorName: + return Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(Reader.getLocalType(F, Key.Data))); - case DeclarationName::CXXLiteralOperatorName: - return Context->DeclarationNames.getCXXLiteralOperatorName( - (IdentifierInfo*)Key.Data); + case DeclarationName::CXXConversionFunctionName: + return Context.DeclarationNames.getCXXConversionFunctionName( + Context.getCanonicalType(Reader.getLocalType(F, Key.Data))); - case DeclarationName::CXXUsingDirective: - return DeclarationName::getUsingDirectiveName(); - } + case DeclarationName::CXXOperatorName: + return Context.DeclarationNames.getCXXOperatorName( + (OverloadedOperatorKind)Key.Data); - llvm_unreachable("Invalid Name Kind ?"); - } + case DeclarationName::CXXLiteralOperatorName: + return Context.DeclarationNames.getCXXLiteralOperatorName( + (IdentifierInfo*)Key.Data); - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); - return std::make_pair(KeyLen, DataLen); + case DeclarationName::CXXUsingDirective: + return DeclarationName::getUsingDirectiveName(); } - internal_key_type ReadKey(const unsigned char* d, unsigned) { - using namespace clang::io; + llvm_unreachable("Invalid Name Kind ?"); +} - DeclNameKey Key; - Key.Kind = (DeclarationName::NameKind)*d++; - switch (Key.Kind) { - case DeclarationName::Identifier: - Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)); - break; - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - Key.Data = - (uint64_t)Reader.DecodeSelector(ReadUnalignedLE32(d)).getAsOpaquePtr(); - break; - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - Key.Data = ReadUnalignedLE32(d); // TypeID - break; - case DeclarationName::CXXOperatorName: - Key.Data = *d++; // OverloadedOperatorKind - break; - case DeclarationName::CXXLiteralOperatorName: - Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)); - break; - case DeclarationName::CXXUsingDirective: - break; - } +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); +} - return Key; - } +ASTDeclContextNameLookupTrait::internal_key_type +ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) { + using namespace clang::io; - data_type ReadData(internal_key_type, const unsigned char* d, - unsigned DataLen) { - using namespace clang::io; - unsigned NumDecls = ReadUnalignedLE16(d); - DeclID *Start = (DeclID *)d; - return std::make_pair(Start, Start + NumDecls); + 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; } -}; -} // end anonymous namespace + return Key; +} -/// \brief The on-disk hash table used for the DeclContext's Name lookup table. -typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait> - ASTDeclContextNameLookupTable; +ASTDeclContextNameLookupTrait::data_type +ASTDeclContextNameLookupTrait::ReadData(internal_key_type, + const unsigned char* d, + unsigned DataLen) { + using namespace clang::io; + unsigned NumDecls = ReadUnalignedLE16(d); + DeclID *Start = (DeclID *)d; + return std::make_pair(Start, Start + NumDecls); +} -bool ASTReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, +bool ASTReader::ReadDeclContextStorage(Module &M, + llvm::BitstreamCursor &Cursor, const std::pair<uint64_t, uint64_t> &Offsets, DeclContextInfo &Info) { SavedStreamPosition SavedPosition(Cursor); @@ -932,9 +749,6 @@ bool ASTReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob); Info.NumLexicalDecls = BlobLen / sizeof(KindDeclIDPair); - } else { - Info.LexicalDecls = 0; - Info.NumLexicalDecls = 0; } // Now the lookup table. @@ -954,20 +768,18 @@ bool ASTReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, = ASTDeclContextNameLookupTable::Create( (const unsigned char *)Blob + Record[0], (const unsigned char *)Blob, - ASTDeclContextNameLookupTrait(*this)); - } else { - Info.NameLookupTableData = 0; + ASTDeclContextNameLookupTrait(*this, M)); } return false; } -void ASTReader::Error(llvm::StringRef Msg) { +void ASTReader::Error(StringRef Msg) { Error(diag::err_fe_pch_malformed, Msg); } void ASTReader::Error(unsigned DiagID, - llvm::StringRef Arg1, llvm::StringRef Arg2) { + StringRef Arg1, StringRef Arg2) { if (Diags.isDiagnosticInFlight()) Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2); else @@ -990,8 +802,8 @@ bool ASTReader::CheckPredefinesBuffers() { /// \brief Read the line table in the source manager block. /// \returns true if there was an error. -bool ASTReader::ParseLineTable(PerFileData &F, - llvm::SmallVectorImpl<uint64_t> &Record) { +bool ASTReader::ParseLineTable(Module &F, + SmallVectorImpl<uint64_t> &Record) { unsigned Idx = 0; LineTableInfo &LineTable = SourceMgr.getLineTable(); @@ -1010,6 +822,9 @@ bool ASTReader::ParseLineTable(PerFileData &F, 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++]; @@ -1131,7 +946,7 @@ public: /// \brief Read a source manager block -ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(PerFileData &F) { +ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(Module &F) { using namespace SrcMgr; llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor; @@ -1188,11 +1003,6 @@ ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(PerFileData &F) { default: // Default behavior: ignore. break; - case SM_LINE_TABLE: - if (ParseLineTable(F, Record)) - return Failure; - break; - case SM_SLOC_FILE_ENTRY: case SM_SLOC_BUFFER_ENTRY: case SM_SLOC_EXPANSION_ENTRY: @@ -1235,38 +1045,20 @@ resolveFileRelativeToOriginalDir(const std::string &Filename, return currPCHPath.str(); } -/// \brief Get a cursor that's correctly positioned for reading the source -/// location entry with the given ID. -ASTReader::PerFileData *ASTReader::SLocCursorForID(unsigned ID) { - assert(ID != 0 && ID <= TotalNumSLocEntries && - "SLocCursorForID should only be called for real IDs."); - - ID -= 1; - PerFileData *F = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - F = Chain[N - I - 1]; - if (ID < F->LocalNumSLocEntries) - break; - ID -= F->LocalNumSLocEntries; - } - assert(F && F->LocalNumSLocEntries > ID && "Chain corrupted"); - - F->SLocEntryCursor.JumpToBit(F->SLocOffsets[ID]); - return F; -} - /// \brief Read in the source location entry with the given ID. -ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) { +ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { if (ID == 0) return Success; - if (ID > TotalNumSLocEntries) { + if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) { Error("source location entry ID out-of-range for AST file"); return Failure; } - PerFileData *F = SLocCursorForID(ID); + Module *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(); @@ -1326,12 +1118,19 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) { return Failure; } - FileID FID = SourceMgr.createFileID(File, ReadSourceLocation(*F, Record[1]), + 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, Record[0]); + ID, BaseOffset + Record[0]); + SrcMgr::FileInfo &FileInfo = + const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()); + FileInfo.NumCreatedFIDs = Record[6]; if (Record[3]) - const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()) - .setHasLineDirectives(); + FileInfo.setHasLineDirectives(); break; } @@ -1350,14 +1149,15 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) { } llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(BlobStart, BlobLen - 1), + = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), Name); - FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset); + FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, + BaseOffset + Offset); if (strcmp(Name, "<built-in>") == 0) { PCHPredefinesBlock Block = { BufferID, - llvm::StringRef(BlobStart, BlobLen - 1) + StringRef(BlobStart, BlobLen - 1) }; PCHPredefinesBuffers.push_back(Block); } @@ -1367,12 +1167,12 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) { case SM_SLOC_EXPANSION_ENTRY: { SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]); - SourceMgr.createInstantiationLoc(SpellingLoc, + SourceMgr.createExpansionLoc(SpellingLoc, ReadSourceLocation(*F, Record[2]), ReadSourceLocation(*F, Record[3]), Record[4], ID, - Record[0]); + BaseOffset + Record[0]); break; } } @@ -1380,6 +1180,25 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) { return Success; } +/// \brief Find the location where the module F is imported. +SourceLocation ASTReader::getImportLocation(Module *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. @@ -1403,8 +1222,7 @@ bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, } } -PreprocessedEntity *ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) { - assert(PP && "Forgot to set Preprocessor ?"); +void ASTReader::ReadMacroRecord(Module &F, uint64_t Offset) { llvm::BitstreamCursor &Stream = F.MacroCursor; // Keep track of where we are in the stream, then jump back there @@ -1413,21 +1231,21 @@ PreprocessedEntity *ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) Stream.JumpToBit(Offset); RecordData Record; - llvm::SmallVector<IdentifierInfo*, 16> MacroArgs; + SmallVector<IdentifierInfo*, 16> MacroArgs; MacroInfo *Macro = 0; while (true) { unsigned Code = Stream.ReadCode(); switch (Code) { case llvm::bitc::END_BLOCK: - return 0; + 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 0; + return; } continue; @@ -1451,50 +1269,55 @@ PreprocessedEntity *ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) // of the definition of the macro we were looking for. We're // done. if (Macro) - return 0; + return; - IdentifierInfo *II = DecodeIdentifierInfo(Record[0]); + IdentifierInfo *II = getLocalIdentifier(F, Record[0]); if (II == 0) { Error("macro must have a name in AST file"); - return 0; + return; } SourceLocation Loc = ReadSourceLocation(F, Record[1]); bool isUsed = Record[2]; - MacroInfo *MI = PP->AllocateMacroInfo(Loc); + MacroInfo *MI = PP.AllocateMacroInfo(Loc); MI->setIsUsed(isUsed); MI->setIsFromAST(); unsigned NextIndex = 3; + MI->setExportLocation(ReadSourceLocation(F, Record, NextIndex)); + if (RecType == PP_MACRO_FUNCTION_LIKE) { // Decode function-like macro info. - bool isC99VarArgs = Record[3]; - bool isGNUVarArgs = Record[4]; + bool isC99VarArgs = Record[NextIndex++]; + bool isGNUVarArgs = Record[NextIndex++]; MacroArgs.clear(); - unsigned NumArgs = Record[5]; - NextIndex = 6 + NumArgs; + unsigned NumArgs = Record[NextIndex++]; for (unsigned i = 0; i != NumArgs; ++i) - MacroArgs.push_back(DecodeIdentifierInfo(Record[6+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()); + PP.getPreprocessorAllocator()); } // Finally, install the macro. - PP->setMacroInfo(II, MI); + PP.setMacroInfo(II, MI); // Remember that we saw this macro last so that we add the tokens that // form its body to it. Macro = MI; - if (NextIndex + 1 == Record.size() && PP->getPreprocessingRecord()) { - // We have a macro definition. Load it now. - PP->getPreprocessingRecord()->RegisterMacroDefinition(Macro, - getMacroDefinition(Record[NextIndex])); + 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; @@ -1510,7 +1333,7 @@ PreprocessedEntity *ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) Tok.startToken(); Tok.setLocation(ReadSourceLocation(F, Record[0])); Tok.setLength(Record[1]); - if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2])) + if (IdentifierInfo *II = getLocalIdentifier(F, Record[2])) Tok.setIdentifierInfo(II); Tok.setKind((tok::TokenKind)Record[3]); Tok.setFlag((Token::TokenFlags)Record[4]); @@ -1520,234 +1343,98 @@ PreprocessedEntity *ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) } } - return 0; + return; } -PreprocessedEntity *ASTReader::LoadPreprocessedEntity(PerFileData &F) { - assert(PP && "Forgot to set Preprocessor ?"); - unsigned Code = F.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. - PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - RecordData Record; - PreprocessorDetailRecordTypes RecType = - (PreprocessorDetailRecordTypes)F.PreprocessorDetailCursor.ReadRecord( - Code, Record, BlobStart, BlobLen); - switch (RecType) { - case PPD_MACRO_EXPANSION: { - if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) - return PE; - - MacroExpansion *ME = - new (PPRec) MacroExpansion(DecodeIdentifierInfo(Record[3]), - SourceRange(ReadSourceLocation(F, Record[1]), - ReadSourceLocation(F, Record[2])), - getMacroDefinition(Record[4])); - PPRec.SetPreallocatedEntity(Record[0], ME); - return ME; - } - - case PPD_MACRO_DEFINITION: { - if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) - return PE; - - if (Record[1] > MacroDefinitionsLoaded.size()) { - Error("out-of-bounds macro definition record"); - return 0; - } - - // Decode the identifier info and then check again; if the macro is - // still defined and associated with the identifier, - IdentifierInfo *II = DecodeIdentifierInfo(Record[4]); - if (!MacroDefinitionsLoaded[Record[1] - 1]) { - MacroDefinition *MD - = new (PPRec) MacroDefinition(II, - ReadSourceLocation(F, Record[5]), - SourceRange( - ReadSourceLocation(F, Record[2]), - ReadSourceLocation(F, Record[3]))); - - PPRec.SetPreallocatedEntity(Record[0], MD); - MacroDefinitionsLoaded[Record[1] - 1] = MD; - - if (DeserializationListener) - DeserializationListener->MacroDefinitionRead(Record[1], MD); - } - - return MacroDefinitionsLoaded[Record[1] - 1]; - } - - case PPD_INCLUSION_DIRECTIVE: { - if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) - return PE; - - const char *FullFileNameStart = BlobStart + Record[3]; - const FileEntry *File - = PP->getFileManager().getFile(llvm::StringRef(FullFileNameStart, - BlobLen - Record[3])); - - // FIXME: Stable encoding - InclusionDirective::InclusionKind Kind - = static_cast<InclusionDirective::InclusionKind>(Record[5]); - InclusionDirective *ID - = new (PPRec) InclusionDirective(PPRec, Kind, - llvm::StringRef(BlobStart, Record[3]), - Record[4], - File, - SourceRange(ReadSourceLocation(F, Record[1]), - ReadSourceLocation(F, Record[2]))); - PPRec.SetPreallocatedEntity(Record[0], ID); - return ID; - } - } +PreprocessedEntityID +ASTReader::getGlobalPreprocessedEntityID(Module &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"); - Error("invalid offset in preprocessor detail block"); - return 0; + return LocalID + I->second; } -namespace { - /// \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 { - 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(const char *SearchPath = 0) : SearchPath(SearchPath) { } - - static unsigned ComputeHash(const char *path) { - return llvm::HashString(llvm::sys::path::filename(path)); - } +unsigned HeaderFileInfoTrait::ComputeHash(const char *path) { + return llvm::HashString(llvm::sys::path::filename(path)); +} - static internal_key_type GetInternalKey(const char *path) { return path; } +HeaderFileInfoTrait::internal_key_type +HeaderFileInfoTrait::GetInternalKey(const char *path) { return path; } - bool 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; - - // The file names match, but the path names don't. stat() the files to - // see if they are the same. - struct stat StatBufA, StatBufB; - if (StatSimpleCache(a, &StatBufA) || StatSimpleCache(b, &StatBufB)) - return false; - - return StatBufA.st_ino == StatBufB.st_ino; - } - - 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); - } +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; + + // The file names match, but the path names don't. stat() the files to + // see if they are the same. + struct stat StatBufA, StatBufB; + if (StatSimpleCache(a, &StatBufA) || StatSimpleCache(b, &StatBufB)) + return false; + + return StatBufA.st_ino == StatBufB.st_ino; +} - static internal_key_type ReadKey(const unsigned char *d, unsigned) { - return (const char *)d; - } +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); +} - static data_type ReadData(const internal_key_type, const unsigned char *d, +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 >> 4) & 0x01; - HFI.isPragmaOnce = (Flags >> 3) & 0x01; - HFI.DirInfo = (Flags >> 1) & 0x03; - HFI.Resolved = Flags & 0x01; - HFI.NumIncludes = ReadUnalignedLE16(d); - HFI.ControllingMacroID = ReadUnalignedLE32(d); - assert(End == d && "Wrong data length in HeaderFileInfo deserialization"); - (void)End; - - // This HeaderFileInfo was externally loaded. - HFI.External = true; - return HFI; - } - }; + 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.getGlobalDeclID(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; } -/// \brief The on-disk hash table used for the global method pool. -typedef OnDiskChainedHashTable<HeaderFileInfoTrait> - HeaderFileInfoLookupTable; - -void ASTReader::SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F, - uint64_t Offset) { +void ASTReader::SetIdentifierIsMacro(IdentifierInfo *II, Module &F, + uint64_t LocalOffset) { // Note that this identifier has a macro definition. II->setHasMacroDefinition(true); - // Adjust the offset based on our position in the chain. - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - if (Chain[I] == &F) - break; - - Offset += Chain[I]->SizeInBits; - } - - UnreadMacroRecordOffsets[II] = Offset; + // Adjust the offset to a global offset. + UnreadMacroRecordOffsets[II] = F.GlobalBitOffset + LocalOffset; } void ASTReader::ReadDefinedMacros() { - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[N - I - 1]; - llvm::BitstreamCursor &MacroCursor = F.MacroCursor; + 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(F.MacroStartOffset); + Cursor.JumpToBit((*I)->MacroStartOffset); RecordData Record; while (true) { @@ -1780,7 +1467,7 @@ void ASTReader::ReadDefinedMacros() { case PP_MACRO_OBJECT_LIKE: case PP_MACRO_FUNCTION_LIKE: - DecodeIdentifierInfo(Record[0]); + getLocalIdentifier(**I, Record[0]); break; case PP_TOKEN: @@ -1798,24 +1485,11 @@ void ASTReader::ReadDefinedMacros() { void ASTReader::LoadMacroDefinition( llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) { assert(Pos != UnreadMacroRecordOffsets.end() && "Unknown macro definition"); - PerFileData *F = 0; uint64_t Offset = Pos->second; UnreadMacroRecordOffsets.erase(Pos); - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - if (Offset < Chain[I]->SizeInBits) { - F = Chain[I]; - break; - } - - Offset -= Chain[I]->SizeInBits; - } - if (!F) { - Error("Malformed macro record offset"); - return; - } - - ReadMacroRecord(*F, Offset); + RecordLocation Loc = getLocalBitOffset(Offset); + ReadMacroRecord(*Loc.F, Loc.Offset); } void ASTReader::LoadMacroDefinition(IdentifierInfo *II) { @@ -1824,29 +1498,7 @@ void ASTReader::LoadMacroDefinition(IdentifierInfo *II) { LoadMacroDefinition(Pos); } -MacroDefinition *ASTReader::getMacroDefinition(MacroID ID) { - if (ID == 0 || ID > MacroDefinitionsLoaded.size()) - return 0; - - if (!MacroDefinitionsLoaded[ID - 1]) { - unsigned Index = ID - 1; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[N - I - 1]; - if (Index < F.LocalNumMacroDefinitions) { - SavedStreamPosition SavedPosition(F.PreprocessorDetailCursor); - F.PreprocessorDetailCursor.JumpToBit(F.MacroDefinitionOffsets[Index]); - LoadPreprocessedEntity(F); - break; - } - Index -= F.LocalNumMacroDefinitions; - } - assert(MacroDefinitionsLoaded[ID - 1] && "Broken chain"); - } - - return MacroDefinitionsLoaded[ID - 1]; -} - -const FileEntry *ASTReader::getFileEntry(llvm::StringRef filenameStrRef) { +const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { std::string Filename = filenameStrRef; MaybeAddSystemRootToFilename(Filename); const FileEntry *File = FileMgr.getFile(Filename); @@ -1873,21 +1525,21 @@ void ASTReader::MaybeAddSystemRootToFilename(std::string &Filename) { if (Filename.empty() || llvm::sys::path::is_absolute(Filename)) return; - if (isysroot == 0) { + if (isysroot.empty()) { // If no system root was given, default to '/' Filename.insert(Filename.begin(), '/'); return; } - unsigned Length = strlen(isysroot); + unsigned Length = isysroot.size(); if (isysroot[Length - 1] != '/') Filename.insert(Filename.begin(), '/'); - Filename.insert(Filename.begin(), isysroot, isysroot + Length); + Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end()); } ASTReader::ASTReadResult -ASTReader::ReadASTBlock(PerFileData &F) { +ASTReader::ReadASTBlock(Module &F) { llvm::BitstreamCursor &Stream = F.Stream; if (Stream.EnterSubBlock(AST_BLOCK_ID)) { @@ -1897,7 +1549,6 @@ ASTReader::ReadASTBlock(PerFileData &F) { // Read all of the records and blocks for the ASt file. RecordData Record; - bool First = true; while (!Stream.AtEndOfStream()) { unsigned Code = Stream.ReadCode(); if (Code == llvm::bitc::END_BLOCK) { @@ -1934,8 +1585,8 @@ ASTReader::ReadASTBlock(PerFileData &F) { case PREPROCESSOR_BLOCK_ID: F.MacroCursor = Stream; - if (PP) - PP->setExternalSource(this); + if (!PP.getExternalSource()) + PP.setExternalSource(this); if (Stream.SkipBlock() || ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) { @@ -1955,6 +1606,11 @@ ASTReader::ReadASTBlock(PerFileData &F) { } F.PreprocessorDetailStartOffset = F.PreprocessorDetailCursor.GetCurrentBitNo(); + + if (!PP.getPreprocessingRecord()) + PP.createPreprocessingRecord(true); + if (!PP.getPreprocessingRecord()->getExternalSource()) + PP.getPreprocessingRecord()->SetExternalSource(*this); break; case SOURCE_MANAGER_BLOCK_ID: @@ -1971,7 +1627,6 @@ ASTReader::ReadASTBlock(PerFileData &F) { } break; } - First = false; continue; } @@ -2005,79 +1660,108 @@ ASTReader::ReadASTBlock(PerFileData &F) { break; } - case CHAINED_METADATA: { - if (!First) { - Error("CHAINED_METADATA is not first record in block"); - return Failure; - } - 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; - } - - // Load the chained file, which is always a PCH file. - switch(ReadASTCore(llvm::StringRef(BlobStart, BlobLen), PCH)) { - 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; + 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++]; + llvm::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: + 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.insert(std::make_pair(LocalBaseTypeIndex, + F.BaseTypeIndex - LocalBaseTypeIndex)); + + TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes); + } break; - - case DECL_OFFSET: + } + + case DECL_OFFSET: { if (F.LocalNumDecls != 0) { Error("duplicate DECL_OFFSET record in AST file"); return Failure; } F.DeclOffsets = (const uint32_t *)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.insert(std::make_pair(LocalBaseDeclID, + F.BaseDeclID - LocalBaseDeclID)); + + DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls); + } break; - + } + case TU_UPDATE_LEXICAL: { - DeclContextInfo Info = { - /* No visible information */ 0, - reinterpret_cast<const KindDeclIDPair *>(BlobStart), - BlobLen / sizeof(KindDeclIDPair) - }; - DeclContextOffsets[Context ? Context->getTranslationUnitDecl() : 0] - .push_back(Info); + 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: { - serialization::DeclID ID = Record[0]; + unsigned Idx = 0; + serialization::DeclID ID = ReadDeclID(F, Record, Idx); void *Table = ASTDeclContextNameLookupTable::Create( - (const unsigned char *)BlobStart + Record[1], + (const unsigned char *)BlobStart + Record[Idx++], (const unsigned char *)BlobStart, - ASTDeclContextNameLookupTrait(*this)); - if (ID == 1 && Context) { // Is it the TU? - DeclContextInfo Info = { - Table, /* No lexical inforamtion */ 0, 0 - }; - DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info); + 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(Table); + PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F)); break; } case REDECLS_UPDATE_LATEST: { assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs"); - for (unsigned i = 0, e = Record.size(); i < e; i += 2) { - DeclID First = Record[i], Latest = Record[i+1]; - assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() || - Latest > FirstLatestDeclIDs[First]) && - "The new latest is supposed to come after the previous latest"); + for (unsigned i = 0, e = Record.size(); i < e; /* in loop */) { + DeclID First = ReadDeclID(F, Record, i); + DeclID Latest = ReadDeclID(F, Record, i); FirstLatestDeclIDs[First] = Latest; } break; @@ -2096,35 +1780,47 @@ ASTReader::ReadASTBlock(PerFileData &F) { (const unsigned char *)F.IdentifierTableData + Record[0], (const unsigned char *)F.IdentifierTableData, ASTIdentifierLookupTrait(*this, F)); - if (PP) - PP->getIdentifierTable().setExternalIdentifierLookup(this); + + PP.getIdentifierTable().setExternalIdentifierLookup(this); } break; - case IDENTIFIER_OFFSET: + 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.insert( + std::make_pair(LocalBaseIdentifierID, + F.BaseIdentifierID - LocalBaseIdentifierID)); + + IdentifiersLoaded.resize(IdentifiersLoaded.size() + + F.LocalNumIdentifiers); + } break; - + } + case EXTERNAL_DEFINITIONS: - // Optimization for the first block. - if (ExternalDefinitions.empty()) - ExternalDefinitions.swap(Record); - else - ExternalDefinitions.insert(ExternalDefinitions.end(), - Record.begin(), Record.end()); + for (unsigned I = 0, N = Record.size(); I != N; ++I) + ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I])); break; case SPECIAL_TYPES: - // Optimization for the first block - if (SpecialTypes.empty()) - SpecialTypes.swap(Record); - else - SpecialTypes.insert(SpecialTypes.end(), Record.begin(), Record.end()); + for (unsigned I = 0, N = Record.size(); I != N; ++I) + SpecialTypes.push_back(getGlobalTypeID(F, Record[I])); break; case STATISTICS: @@ -2135,42 +1831,63 @@ ASTReader::ReadASTBlock(PerFileData &F) { break; case UNUSED_FILESCOPED_DECLS: - // Optimization for the first block. - if (UnusedFileScopedDecls.empty()) - UnusedFileScopedDecls.swap(Record); - else - UnusedFileScopedDecls.insert(UnusedFileScopedDecls.end(), - Record.begin(), Record.end()); + for (unsigned I = 0, N = Record.size(); I != N; ++I) + UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I])); break; case DELEGATING_CTORS: - // Optimization for the first block. - if (DelegatingCtorDecls.empty()) - DelegatingCtorDecls.swap(Record); - else - DelegatingCtorDecls.insert(DelegatingCtorDecls.end(), - Record.begin(), Record.end()); + for (unsigned I = 0, N = Record.size(); I != N; ++I) + DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I])); break; case WEAK_UNDECLARED_IDENTIFIERS: - // Later blocks overwrite earlier ones. - WeakUndeclaredIdentifiers.swap(Record); + 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: - // Optimization for the first block. - if (LocallyScopedExternalDecls.empty()) - LocallyScopedExternalDecls.swap(Record); - else - LocallyScopedExternalDecls.insert(LocallyScopedExternalDecls.end(), - Record.begin(), Record.end()); + for (unsigned I = 0, N = Record.size(); I != N; ++I) + LocallyScopedExternalDecls.push_back(getGlobalDeclID(F, Record[I])); break; - case SELECTOR_OFFSETS: + case SELECTOR_OFFSETS: { F.SelectorOffsets = (const uint32_t *)BlobStart; F.LocalNumSelectors = Record[0]; - break; + 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.insert(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]) @@ -2178,12 +1895,19 @@ ASTReader::ReadASTBlock(PerFileData &F) { = ASTSelectorLookupTable::Create( F.SelectorLookupTableData + Record[0], F.SelectorLookupTableData, - ASTSelectorLookupTrait(*this)); + ASTSelectorLookupTrait(*this, F)); TotalNumMethodPoolEntries += Record[1]; break; case REFERENCED_SELECTOR_POOL: - F.ReferencedSelectorsData.swap(Record); + 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: @@ -2191,10 +1915,94 @@ ASTReader::ReadASTBlock(PerFileData &F) { Listener->ReadCounter(Record[0]); break; - case SOURCE_LOCATION_OFFSETS: - F.SLocOffsets = (const uint32_t *)BlobStart; + case SOURCE_LOCATION_OFFSETS: { + F.SLocEntryOffsets = (const uint32_t *)BlobStart; F.LocalNumSLocEntries = Record[0]; - F.LocalSLocSize = Record[1]; + 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 + 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; + Module *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 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)); + 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)); + } + break; + } + + case SOURCE_MANAGER_LINE_TABLE: + if (ParseLineTable(F, Record)) + return Failure; break; case FILE_SOURCE_LOCATION_OFFSETS: @@ -2202,13 +2010,17 @@ ASTReader::ReadASTBlock(PerFileData &F) { F.LocalNumSLocFileEntries = Record[0]; break; - case SOURCE_LOCATION_PRELOADS: - if (PreloadSLocEntries.empty()) - PreloadSLocEntries.swap(Record); - else - PreloadSLocEntries.insert(PreloadSLocEntries.end(), - Record.begin(), Record.end()); + 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) { @@ -2223,35 +2035,56 @@ ASTReader::ReadASTBlock(PerFileData &F) { } case EXT_VECTOR_DECLS: - // Optimization for the first block. - if (ExtVectorDecls.empty()) - ExtVectorDecls.swap(Record); - else - ExtVectorDecls.insert(ExtVectorDecls.end(), - Record.begin(), Record.end()); + 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. - VTableUses.swap(Record); + // 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: - // Optimization for the first block. - if (DynamicClasses.empty()) - DynamicClasses.swap(Record); - else - DynamicClasses.insert(DynamicClasses.end(), - Record.begin(), Record.end()); + for (unsigned I = 0, N = Record.size(); I != N; ++I) + DynamicClasses.push_back(getGlobalDeclID(F, Record[I])); break; case PENDING_IMPLICIT_INSTANTIATIONS: - F.PendingInstantiations.swap(Record); + 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. - SemaDeclRefs.swap(Record); + // 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: @@ -2274,28 +2107,54 @@ ASTReader::ReadASTBlock(PerFileData &F) { case VERSION_CONTROL_BRANCH_REVISION: { const std::string &CurBranch = getClangFullRepositoryVersion(); - llvm::StringRef ASTBranch(BlobStart, BlobLen); - if (llvm::StringRef(CurBranch) != ASTBranch && !DisableValidation) { + StringRef ASTBranch(BlobStart, BlobLen); + if (StringRef(CurBranch) != ASTBranch && !DisableValidation) { Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch; return IgnorePCH; } break; } - case MACRO_DEFINITION_OFFSETS: - F.MacroDefinitionOffsets = (const uint32_t *)BlobStart; - F.NumPreallocatedPreprocessingEntities = Record[0]; - F.LocalNumMacroDefinitions = Record[1]; - 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(true); + 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.insert( + 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[static_cast<DeclID>(Record[I])] - .push_back(std::make_pair(&F, Record[I+1])); + DeclUpdateOffsets[getGlobalDeclID(F, Record[I])] + .push_back(std::make_pair(&F, Record[I+1])); break; } @@ -2305,8 +2164,22 @@ ASTReader::ReadASTBlock(PerFileData &F) { return Failure; } for (unsigned I = 0, N = Record.size(); I != N; I += 2) - ReplacedDecls[static_cast<DeclID>(Record[I])] = - std::make_pair(&F, Record[I+1]); + ReplacedDecls[getGlobalDeclID(F, Record[I])] + = std::make_pair(&F, Record[I+1]); + break; + } + + case OBJC_CHAINED_CATEGORIES: { + if (Record.size() % 3 != 0) { + Error("invalid OBJC_CHAINED_CATEGORIES block in AST file"); + return Failure; + } + for (unsigned I = 0, N = Record.size(); I != N; I += 3) { + serialization::GlobalDeclID GlobID = getGlobalDeclID(F, Record[I]); + F.ChainedObjCCategories[GlobID] = std::make_pair(Record[I+1], + Record[I+2]); + ObjCChainedCategoriesInterfaces.insert(GlobID); + } break; } @@ -2318,6 +2191,7 @@ ASTReader::ReadASTBlock(PerFileData &F) { F.LocalNumCXXBaseSpecifiers = Record[0]; F.CXXBaseSpecifiersOffsets = (const uint32_t *)BlobStart; + NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers; break; } @@ -2326,31 +2200,42 @@ ASTReader::ReadASTBlock(PerFileData &F) { Error("invalid DIAG_USER_MAPPINGS block in AST file"); return Failure; } - if (PragmaDiagMappings.empty()) - PragmaDiagMappings.swap(Record); + + if (F.PragmaDiagMappings.empty()) + F.PragmaDiagMappings.swap(Record); else - PragmaDiagMappings.insert(PragmaDiagMappings.end(), - Record.begin(), Record.end()); + F.PragmaDiagMappings.insert(F.PragmaDiagMappings.end(), + Record.begin(), Record.end()); break; case CUDA_SPECIAL_DECL_REFS: // Later tables overwrite earlier ones. - CUDASpecialDeclRefs.swap(Record); + // 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: + 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); - if (PP) - PP->getHeaderSearchInfo().SetExternalSource(this); + (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); @@ -2362,272 +2247,222 @@ ASTReader::ReadASTBlock(PerFileData &F) { break; case TENTATIVE_DEFINITIONS: - // Optimization for the first block. - if (TentativeDefinitions.empty()) - TentativeDefinitions.swap(Record); - else - TentativeDefinitions.insert(TentativeDefinitions.end(), - Record.begin(), Record.end()); + for (unsigned I = 0, N = Record.size(); I != N; ++I) + TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I])); break; case KNOWN_NAMESPACES: - // Optimization for the first block. - if (KnownNamespaces.empty()) - KnownNamespaces.swap(Record); - else - KnownNamespaces.insert(KnownNamespaces.end(), - Record.begin(), Record.end()); + for (unsigned I = 0, N = Record.size(); I != N; ++I) + KnownNamespaces.push_back(getGlobalDeclID(F, Record[I])); break; } - First = false; } Error("premature end of bitstream in AST file"); return Failure; } -ASTReader::ASTReadResult ASTReader::validateFileEntries() { - for (unsigned CI = 0, CN = Chain.size(); CI != CN; ++CI) { - PerFileData *F = Chain[CI]; - llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor; +ASTReader::ASTReadResult ASTReader::validateFileEntries(Module &M) { + llvm::BitstreamCursor &SLocEntryCursor = M.SLocEntryCursor; - for (unsigned i = 0, e = F->LocalNumSLocFileEntries; i != e; ++i) { - SLocEntryCursor.JumpToBit(F->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; + 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: { + 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; } - - RecordData Record; - const char *BlobStart; - unsigned BlobLen; - switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { - default: - Error("incorrectly-formatted source location entry in AST file"); + + if (Record.size() < 6) { + Error("source location entry is incorrect"); return Failure; - - case SM_SLOC_FILE_ENTRY: { - llvm::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() < 6) { - 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(); - } + // 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 (((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 + // 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; - } + )) { + Error(diag::err_fe_pch_file_modified, Filename); + return IgnorePCH; } + + break; + } } } return Success; } +namespace { + /// \brief Visitor class used to look up identifirs in an AST file. + class IdentifierLookupVisitor { + StringRef Name; + IdentifierInfo *Found; + public: + explicit IdentifierLookupVisitor(StringRef Name) : Name(Name), Found() { } + + static bool visit(Module &M, void *UserData) { + IdentifierLookupVisitor *This + = static_cast<IdentifierLookupVisitor *>(UserData); + + ASTIdentifierLookupTable *IdTable + = (ASTIdentifierLookupTable *)M.IdentifierLookupTable; + if (!IdTable) + return false; + + std::pair<const char*, unsigned> Key(This->Name.begin(), + This->Name.size()); + ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key); + 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; } + }; +} + + ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, - ASTFileType Type) { - switch(ReadASTCore(FileName, Type)) { + ModuleKind Type) { + 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. - - if (!DisableValidation) { - switch(validateFileEntries()) { - case Failure: return Failure; - case IgnorePCH: return IgnorePCH; - case Success: break; - } - } - - // Allocate space for loaded slocentries, identifiers, decls and types. - unsigned TotalNumIdentifiers = 0, TotalNumTypes = 0, TotalNumDecls = 0, - TotalNumPreallocatedPreprocessingEntities = 0, TotalNumMacroDefs = 0, - TotalNumSelectors = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - TotalNumSLocEntries += Chain[I]->LocalNumSLocEntries; - NextSLocOffset += Chain[I]->LocalSLocSize; - TotalNumIdentifiers += Chain[I]->LocalNumIdentifiers; - TotalNumTypes += Chain[I]->LocalNumTypes; - TotalNumDecls += Chain[I]->LocalNumDecls; - TotalNumPreallocatedPreprocessingEntities += - Chain[I]->NumPreallocatedPreprocessingEntities; - TotalNumMacroDefs += Chain[I]->LocalNumMacroDefinitions; - TotalNumSelectors += Chain[I]->LocalNumSelectors; - } - SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, NextSLocOffset); - IdentifiersLoaded.resize(TotalNumIdentifiers); - TypesLoaded.resize(TotalNumTypes); - DeclsLoaded.resize(TotalNumDecls); - MacroDefinitionsLoaded.resize(TotalNumMacroDefs); - if (PP) { - if (TotalNumIdentifiers > 0) - PP->getHeaderSearchInfo().SetExternalLookup(this); - if (TotalNumPreallocatedPreprocessingEntities > 0) { - if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(true); - PP->getPreprocessingRecord()->SetExternalSource(*this, - TotalNumPreallocatedPreprocessingEntities); - } - } - SelectorsLoaded.resize(TotalNumSelectors); - // Preload SLocEntries. - for (unsigned I = 0, N = PreloadSLocEntries.size(); I != N; ++I) { - ASTReadResult Result = ReadSLocEntryRecord(PreloadSLocEntries[I]); - if (Result != Success) - return Result; - } - + // Check the predefines buffers. - if (!DisableValidation && CheckPredefinesBuffers()) + if (!DisableValidation && Type != MK_Module && Type != MK_Preamble && + // 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; - if (PP) { - // Initialization of keywords and pragmas occurs before the - // AST file is read, so there may be some identifiers that were - // loaded into the IdentifierTable before we intercepted the - // creation of identifiers. Iterate through the list of known - // identifiers and determine whether we have to establish - // preprocessor definitions or top-level identifier declaration - // chains for those identifiers. - // - // We copy the IdentifierInfo pointers to a small vector first, - // since de-serializing declarations or macro definitions can add - // new entries into the identifier table, invalidating the - // iterators. - llvm::SmallVector<IdentifierInfo *, 128> Identifiers; - for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(), - IdEnd = PP->getIdentifierTable().end(); - Id != IdEnd; ++Id) - Identifiers.push_back(Id->second); - // We need to search the tables in all files. - for (unsigned J = 0, M = Chain.size(); J != M; ++J) { - ASTIdentifierLookupTable *IdTable - = (ASTIdentifierLookupTable *)Chain[J]->IdentifierLookupTable; - // Not all AST files necessarily have identifier tables, only the useful - // ones. - if (!IdTable) - continue; - for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) { - IdentifierInfo *II = Identifiers[I]; - // Look in the on-disk hash tables for an entry for this identifier - ASTIdentifierLookupTrait Info(*this, *Chain[J], II); - std::pair<const char*,unsigned> Key(II->getNameStart(),II->getLength()); - ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info); - if (Pos == IdTable->end()) - continue; - - // Dereferencing the iterator has the effect of populating the - // IdentifierInfo node with the various declarations it needs. - (void)*Pos; - } - } + // Initialization of keywords and pragmas occurs before the + // AST file is read, so there may be some identifiers that were + // loaded into the IdentifierTable before we intercepted the + // creation of identifiers. Iterate through the list of known + // identifiers and determine whether we have to establish + // preprocessor definitions or top-level identifier declaration + // chains for those identifiers. + // + // We copy the IdentifierInfo pointers to a small vector first, + // since de-serializing declarations or macro definitions can add + // new entries into the identifier table, invalidating the + // iterators. + // + // FIXME: We need a lazier way to load this information, e.g., by marking + // the identifier data as 'dirty', so that it will be looked up in the + // AST file(s) if it is uttered in the source. This could save us some + // module load time. + SmallVector<IdentifierInfo *, 128> Identifiers; + for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(), + IdEnd = PP.getIdentifierTable().end(); + Id != IdEnd; ++Id) + Identifiers.push_back(Id->second); + + for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) { + IdentifierLookupVisitor Visitor(Identifiers[I]->getName()); + ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); } - if (Context) - InitializeContext(*Context); + InitializeContext(); if (DeserializationListener) DeserializationListener->ReaderInitialized(this); - // If this AST file is a precompiled preamble, then set the main file ID of - // the source manager to the file source file from which the preamble was - // built. This is the only valid way to use a precompiled preamble. - if (Type == Preamble) { - if (OriginalFileID.isInvalid()) { - SourceLocation Loc - = SourceMgr.getLocation(FileMgr.getFile(getOriginalSourceFile()), 1, 1); - if (Loc.isValid()) - OriginalFileID = SourceMgr.getDecomposedLoc(Loc).first; + // 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) { + if (!OriginalFileID.isInvalid()) { + OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID + + OriginalFileID.getOpaqueValue() - 1); + SourceMgr.setPreambleFileID(OriginalFileID); } - - if (!OriginalFileID.isInvalid()) - SourceMgr.SetPreambleFileID(OriginalFileID); } return Success; } -ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName, - ASTFileType Type) { - PerFileData *Prev = Chain.empty() ? 0 : Chain.back(); - Chain.push_back(new PerFileData(Type)); - PerFileData &F = *Chain.back(); - if (Prev) - Prev->NextInSource = &F; - else - FirstInSource = &F; - F.Loaders.push_back(Prev); +ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, + ModuleKind Type, + Module *ImportedBy) { + Module *M; + bool NewModule; + std::string ErrorStr; + llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportedBy, + ErrorStr); + + if (!M) { + // We couldn't load the module. + std::string Msg = "Unable to load module \"" + FileName.str() + "\": " + + ErrorStr; + Error(Msg); + return Failure; + } - // Set the AST file name. - F.FileName = FileName; + 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 = "."; } - if (!ASTBuffers.empty()) { - F.Buffer.reset(ASTBuffers.back()); - ASTBuffers.pop_back(); - assert(F.Buffer && "Passed null buffer"); - } else { - // Open the AST file. - // - // FIXME: This shouldn't be here, we should just take a raw_ostream. - std::string ErrStr; - llvm::error_code ec; - if (FileName == "-") { - ec = llvm::MemoryBuffer::getSTDIN(F.Buffer); - if (ec) - ErrStr = ec.message(); - } else - F.Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrStr)); - if (!F.Buffer) { - Error(ErrStr.c_str()); - return IgnorePCH; - } - } - - // Initialize the stream - F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(), - (const unsigned char *)F.Buffer->getBufferEnd()); + Module &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' || @@ -2668,9 +2503,8 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName, // AST block, skipping subblocks, to see if there are other // AST blocks elsewhere. - // Clear out any preallocated source location entries, so that - // the source manager does not try to resolve them later. - SourceMgr.ClearPreallocatedSLocEntries(); + // FIXME: We can't clear loaded slocentries anymore. + //SourceMgr.ClearPreallocatedSLocEntries(); // Remove the stat cache. if (F.StatCache) @@ -2687,143 +2521,152 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName, break; } } + + // Once read, set the Module 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)); - return Success; -} + // 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); + } -void ASTReader::setPreprocessor(Preprocessor &pp) { - PP = &pp; - unsigned TotalNum = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) - TotalNum += Chain[I]->NumPreallocatedPreprocessingEntities; - if (TotalNum) { - if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(true); - PP->getPreprocessingRecord()->SetExternalSource(*this, TotalNum); - } + return Success; } -void ASTReader::InitializeContext(ASTContext &Ctx) { - Context = &Ctx; - assert(Context && "Passed null context!"); +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()); - assert(PP && "Forgot to set Preprocessor ?"); - PP->getIdentifierTable().setExternalIdentifierLookup(this); - PP->getHeaderSearchInfo().SetExternalLookup(this); - PP->setExternalSource(this); - PP->getHeaderSearchInfo().SetExternalSource(this); + // 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. - // If we have an update block for the TU waiting, we have to add it before - // deserializing the decl. - DeclContextOffsetsMap::iterator DCU = DeclContextOffsets.find(0); - if (DCU != DeclContextOffsets.end()) { - // Insertion could invalidate map, so grab vector. - DeclContextInfos T; - T.swap(DCU->second); - DeclContextOffsets.erase(DCU); - DeclContextOffsets[Ctx.getTranslationUnitDecl()].swap(T); - } - - // Load the translation unit declaration - GetTranslationUnitDecl(); - // Load the special types. - Context->setBuiltinVaListType( - GetType(SpecialTypes[SPECIAL_TYPE_BUILTIN_VA_LIST])); - if (unsigned Id = SpecialTypes[SPECIAL_TYPE_OBJC_ID]) - Context->setObjCIdType(GetType(Id)); - if (unsigned Sel = SpecialTypes[SPECIAL_TYPE_OBJC_SELECTOR]) - Context->setObjCSelType(GetType(Sel)); - if (unsigned Proto = SpecialTypes[SPECIAL_TYPE_OBJC_PROTOCOL]) - Context->setObjCProtoType(GetType(Proto)); - if (unsigned Class = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS]) - Context->setObjCClassType(GetType(Class)); - - if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) - Context->setCFConstantStringType(GetType(String)); - if (unsigned FastEnum - = SpecialTypes[SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE]) - Context->setObjCFastEnumerationStateType(GetType(FastEnum)); - if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) { - QualType FileType = GetType(File); - if (FileType.isNull()) { - Error("FILE type is NULL"); - return; + if (SpecialTypes.size() > NumSpecialTypeIDs) { + if (Context.getBuiltinVaListType().isNull()) { + Context.setBuiltinVaListType( + GetType(SpecialTypes[SPECIAL_TYPE_BUILTIN_VA_LIST])); } - 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"); + + if (unsigned Proto = SpecialTypes[SPECIAL_TYPE_OBJC_PROTOCOL]) { + if (Context.ObjCProtoType.isNull()) + Context.ObjCProtoType = GetType(Proto); + } + + 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; } - Context->setFILEDecl(Tag->getDecl()); + + 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_bug type is NULL"); - return; + + 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 (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"); + + 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; } - Context->setjmp_bufDecl(Tag->getDecl()); + + 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 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 (unsigned ObjCIdRedef + = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) { + if (Context.ObjCIdRedefinitionType.isNull()) + Context.ObjCIdRedefinitionType = GetType(ObjCIdRedef); } - 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 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 ObjCIdRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) - Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef); - if (unsigned ObjCClassRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) - Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); - if (unsigned String = SpecialTypes[SPECIAL_TYPE_BLOCK_DESCRIPTOR]) - Context->setBlockDescriptorType(GetType(String)); - if (unsigned String - = SpecialTypes[SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR]) - Context->setBlockDescriptorExtendedType(GetType(String)); - if (unsigned ObjCSelRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) - Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef); - if (unsigned String = SpecialTypes[SPECIAL_TYPE_NS_CONSTANT_STRING]) - Context->setNSConstantStringType(GetType(String)); - - if (SpecialTypes[SPECIAL_TYPE_INT128_INSTALLED]) - Context->setInt128Installed(); - - if (unsigned AutoDeduct = SpecialTypes[SPECIAL_TYPE_AUTO_DEDUCT]) - Context->AutoDeductTy = GetType(AutoDeduct); - if (unsigned AutoRRefDeduct = SpecialTypes[SPECIAL_TYPE_AUTO_RREF_DEDUCT]) - Context->AutoRRefDeductTy = GetType(AutoRRefDeduct); - - ReadPragmaDiagnosticMappings(Context->getDiagnostics()); + + 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( + Context.setcudaConfigureCallDecl( cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0]))); } } @@ -2833,7 +2676,7 @@ void ASTReader::InitializeContext(ASTContext &Ctx) { /// file. std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, FileManager &FileMgr, - Diagnostic &Diags) { + DiagnosticsEngine &Diags) { // Open the AST file. std::string ErrStr; llvm::OwningPtr<llvm::MemoryBuffer> Buffer; @@ -2917,181 +2760,349 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, /// /// \returns true if the listener deems the file unacceptable, false otherwise. bool ASTReader::ParseLanguageOptions( - const llvm::SmallVectorImpl<uint64_t> &Record) { + const SmallVectorImpl<uint64_t> &Record) { if (Listener) { LangOptions LangOpts; - - #define PARSE_LANGOPT(Option) \ - LangOpts.Option = Record[Idx]; \ - ++Idx - unsigned Idx = 0; - PARSE_LANGOPT(Trigraphs); - PARSE_LANGOPT(BCPLComment); - PARSE_LANGOPT(DollarIdents); - PARSE_LANGOPT(AsmPreprocessor); - PARSE_LANGOPT(GNUMode); - PARSE_LANGOPT(GNUKeywords); - PARSE_LANGOPT(ImplicitInt); - PARSE_LANGOPT(Digraphs); - PARSE_LANGOPT(HexFloats); - PARSE_LANGOPT(C99); - PARSE_LANGOPT(C1X); - PARSE_LANGOPT(Microsoft); - PARSE_LANGOPT(CPlusPlus); - PARSE_LANGOPT(CPlusPlus0x); - PARSE_LANGOPT(CXXOperatorNames); - PARSE_LANGOPT(ObjC1); - PARSE_LANGOPT(ObjC2); - PARSE_LANGOPT(ObjCNonFragileABI); - PARSE_LANGOPT(ObjCNonFragileABI2); - PARSE_LANGOPT(AppleKext); - PARSE_LANGOPT(ObjCDefaultSynthProperties); - PARSE_LANGOPT(ObjCInferRelatedResultType); - PARSE_LANGOPT(NoConstantCFStrings); - PARSE_LANGOPT(PascalStrings); - PARSE_LANGOPT(WritableStrings); - PARSE_LANGOPT(LaxVectorConversions); - PARSE_LANGOPT(AltiVec); - PARSE_LANGOPT(Exceptions); - PARSE_LANGOPT(ObjCExceptions); - PARSE_LANGOPT(CXXExceptions); - PARSE_LANGOPT(SjLjExceptions); - PARSE_LANGOPT(MSBitfields); - PARSE_LANGOPT(NeXTRuntime); - PARSE_LANGOPT(Freestanding); - PARSE_LANGOPT(NoBuiltin); - PARSE_LANGOPT(ThreadsafeStatics); - PARSE_LANGOPT(POSIXThreads); - PARSE_LANGOPT(Blocks); - PARSE_LANGOPT(EmitAllDecls); - PARSE_LANGOPT(MathErrno); - LangOpts.setSignedOverflowBehavior((LangOptions::SignedOverflowBehaviorTy) - Record[Idx++]); - PARSE_LANGOPT(HeinousExtensions); - PARSE_LANGOPT(Optimize); - PARSE_LANGOPT(OptimizeSize); - PARSE_LANGOPT(Static); - PARSE_LANGOPT(PICLevel); - PARSE_LANGOPT(GNUInline); - PARSE_LANGOPT(NoInline); - PARSE_LANGOPT(Deprecated); - PARSE_LANGOPT(AccessControl); - PARSE_LANGOPT(CharIsSigned); - PARSE_LANGOPT(ShortWChar); - PARSE_LANGOPT(ShortEnums); - LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]); - LangOpts.setVisibilityMode((Visibility)Record[Idx++]); - LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode) - Record[Idx++]); - PARSE_LANGOPT(InstantiationDepth); - PARSE_LANGOPT(OpenCL); - PARSE_LANGOPT(CUDA); - PARSE_LANGOPT(CatchUndefined); - PARSE_LANGOPT(DefaultFPContract); - PARSE_LANGOPT(ElideConstructors); - PARSE_LANGOPT(SpellChecking); - PARSE_LANGOPT(MRTD); - PARSE_LANGOPT(ObjCAutoRefCount); - #undef PARSE_LANGOPT - +#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" + return Listener->ReadLanguageOptions(LangOpts); } return false; } -void ASTReader::ReadPreprocessedEntities() { - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[I]; - if (!F.PreprocessorDetailCursor.getBitStreamReader()) - continue; +PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { + PreprocessedEntityID PPID = Index+1; + GlobalPreprocessedEntityMapType::iterator + I = GlobalPreprocessedEntityMap.find(Index); + assert(I != GlobalPreprocessedEntityMap.end() && + "Corrupted global preprocessed entity map"); + Module &M = *I->second; + unsigned LocalIndex = Index - M.BasePreprocessedEntityID; + const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; - SavedStreamPosition SavedPosition(F.PreprocessorDetailCursor); - F.PreprocessorDetailCursor.JumpToBit(F.PreprocessorDetailStartOffset); - while (LoadPreprocessedEntity(F)) { } + 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; } -} -PreprocessedEntity *ASTReader::ReadPreprocessedEntityAtOffset(uint64_t Offset) { - PerFileData *F = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - if (Offset < Chain[I]->SizeInBits) { - F = Chain[I]; - 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]; + const FileEntry *File + = PP.getFileManager().getFile(StringRef(FullFileNameStart, + BlobLen - Record[0])); - Offset -= Chain[I]->SizeInBits; + // 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; + } } - if (!F) { - Error("Malformed preprocessed entity offset"); - return 0; + Error("invalid offset in preprocessor detail block"); + return 0; +} + +/// \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) { + Module &M = *SLocMapI->second; + if (M.NumPreprocessedEntities) + return getGlobalPreprocessedEntityID(M, M.BasePreprocessedEntityID); } - // Keep track of where we are in the stream, then jump back there - // after reading this entity. - SavedStreamPosition SavedPosition(F->PreprocessorDetailCursor); - F->PreprocessorDetailCursor.JumpToBit(Offset); - return LoadPreprocessedEntity(*F); + return getTotalNumPreprocessedEntities(); } -HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { - HeaderFileInfoTrait Trait(FE->getName()); - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[I]; - HeaderFileInfoLookupTable *Table - = static_cast<HeaderFileInfoLookupTable *>(F.HeaderFileInfoTable); - if (!Table) - continue; +namespace { + +template <unsigned PPEntityOffset::*PPLoc> +struct PPEntityComp { + const ASTReader &Reader; + Module &M; + + PPEntityComp(const ASTReader &Reader, Module &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); + + Module &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); + + Module &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); +} + +namespace { + /// \brief Visitor used to search for information about a header file. + class HeaderFileInfoVisitor { + ASTReader &Reader; + const FileEntry *FE; - // Look in the on-disk hash table for an entry for this file name. - HeaderFileInfoLookupTable::iterator Pos = Table->find(FE->getName(), - &Trait); - if (Pos == Table->end()) - continue; + llvm::Optional<HeaderFileInfo> HFI; + + public: + HeaderFileInfoVisitor(ASTReader &Reader, const FileEntry *FE) + : Reader(Reader), FE(FE) { } + + static bool visit(Module &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; - HeaderFileInfo HFI = *Pos; - if (Listener) - Listener->ReadHeaderFileInfo(HFI, FE->getUID()); + // 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; } + }; +} - 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(Diagnostic &Diag) { - unsigned Idx = 0; - while (Idx < PragmaDiagMappings.size()) { - SourceLocation - Loc = SourceLocation::getFromRawEncoding(PragmaDiagMappings[Idx++]); - while (1) { - assert(Idx < PragmaDiagMappings.size() && - "Invalid data, didn't find '-1' marking end of diag/map pairs"); - if (Idx >= PragmaDiagMappings.size()) - break; // Something is messed up but at least avoid infinite loop in - // release build. - unsigned DiagID = PragmaDiagMappings[Idx++]; - if (DiagID == (unsigned)-1) - break; // no more diag/map pairs for this location. - diag::Mapping Map = (diag::Mapping)PragmaDiagMappings[Idx++]; - Diag.setDiagnosticMapping(DiagID, Map, Loc); +void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { + for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) { + Module &F = *(*I); + unsigned Idx = 0; + while (Idx < F.PragmaDiagMappings.size()) { + SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]); + 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++]; + // The user bit gets set by WritePragmaDiagnosticMappings. + Diag.setDiagnosticMapping(DiagID, Map, Loc); + } } } } /// \brief Get the correct cursor and offset for loading a type. ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { - PerFileData *F = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - F = Chain[N - I - 1]; - if (Index < F->LocalNumTypes) - break; - Index -= F->LocalNumTypes; - } - assert(F && F->LocalNumTypes > Index && "Broken chain"); - return RecordLocation(F, F->TypeOffsets[Index]); + GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index); + assert(I != GlobalTypeMap.end() && "Corrupted global type map"); + Module *M = I->second; + return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]); } /// \brief Read and return the type with the given index.. @@ -3100,7 +3111,7 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { /// 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) { +QualType ASTReader::readTypeRecord(unsigned Index) { RecordLocation Loc = TypeCursorForIndex(Index); llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; @@ -3113,6 +3124,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { // Note that we are loading a type record. Deserializing AType(this); + unsigned Idx = 0; DeclsCursor.JumpToBit(Loc.Offset); RecordData Record; unsigned Code = DeclsCursor.ReadCode(); @@ -3122,9 +3134,9 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("Incorrect encoding of extended qualifier type"); return QualType(); } - QualType Base = GetType(Record[0]); - Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]); - return Context->getQualifiedType(Base, Quals); + QualType Base = readType(*Loc.F, Record, Idx); + Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[Idx++]); + return Context.getQualifiedType(Base, Quals); } case TYPE_COMPLEX: { @@ -3132,8 +3144,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("Incorrect encoding of complex type"); return QualType(); } - QualType ElemType = GetType(Record[0]); - return Context->getComplexType(ElemType); + QualType ElemType = readType(*Loc.F, Record, Idx); + return Context.getComplexType(ElemType); } case TYPE_POINTER: { @@ -3141,8 +3153,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("Incorrect encoding of pointer type"); return QualType(); } - QualType PointeeType = GetType(Record[0]); - return Context->getPointerType(PointeeType); + QualType PointeeType = readType(*Loc.F, Record, Idx); + return Context.getPointerType(PointeeType); } case TYPE_BLOCK_POINTER: { @@ -3150,8 +3162,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("Incorrect encoding of block pointer type"); return QualType(); } - QualType PointeeType = GetType(Record[0]); - return Context->getBlockPointerType(PointeeType); + QualType PointeeType = readType(*Loc.F, Record, Idx); + return Context.getBlockPointerType(PointeeType); } case TYPE_LVALUE_REFERENCE: { @@ -3159,8 +3171,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("Incorrect encoding of lvalue reference type"); return QualType(); } - QualType PointeeType = GetType(Record[0]); - return Context->getLValueReferenceType(PointeeType, Record[1]); + QualType PointeeType = readType(*Loc.F, Record, Idx); + return Context.getLValueReferenceType(PointeeType, Record[1]); } case TYPE_RVALUE_REFERENCE: { @@ -3168,8 +3180,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("Incorrect encoding of rvalue reference type"); return QualType(); } - QualType PointeeType = GetType(Record[0]); - return Context->getRValueReferenceType(PointeeType); + QualType PointeeType = readType(*Loc.F, Record, Idx); + return Context.getRValueReferenceType(PointeeType); } case TYPE_MEMBER_POINTER: { @@ -3177,38 +3189,38 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("Incorrect encoding of member pointer type"); return QualType(); } - QualType PointeeType = GetType(Record[0]); - QualType ClassType = GetType(Record[1]); + 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()); + return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr()); } case TYPE_CONSTANT_ARRAY: { - QualType ElementType = GetType(Record[0]); + 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, + return Context.getConstantArrayType(ElementType, Size, ASM, IndexTypeQuals); } case TYPE_INCOMPLETE_ARRAY: { - QualType ElementType = GetType(Record[0]); + QualType ElementType = readType(*Loc.F, Record, Idx); ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; unsigned IndexTypeQuals = Record[2]; - return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals); + return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals); } case TYPE_VARIABLE_ARRAY: { - QualType ElementType = GetType(Record[0]); + 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), + return Context.getVariableArrayType(ElementType, ReadExpr(*Loc.F), ASM, IndexTypeQuals, SourceRange(LBLoc, RBLoc)); } @@ -3219,10 +3231,10 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { return QualType(); } - QualType ElementType = GetType(Record[0]); + QualType ElementType = readType(*Loc.F, Record, Idx); unsigned NumElements = Record[1]; unsigned VecKind = Record[2]; - return Context->getVectorType(ElementType, NumElements, + return Context.getVectorType(ElementType, NumElements, (VectorType::VectorKind)VecKind); } @@ -3232,9 +3244,9 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { return QualType(); } - QualType ElementType = GetType(Record[0]); + QualType ElementType = readType(*Loc.F, Record, Idx); unsigned NumElements = Record[1]; - return Context->getExtVectorType(ElementType, NumElements); + return Context.getExtVectorType(ElementType, NumElements); } case TYPE_FUNCTION_NO_PROTO: { @@ -3242,14 +3254,14 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("incorrect encoding of no-proto function type"); return QualType(); } - QualType ResultType = GetType(Record[0]); + 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); + return Context.getFunctionNoProtoType(ResultType, Info); } case TYPE_FUNCTION_PROTO: { - QualType ResultType = GetType(Record[0]); + QualType ResultType = readType(*Loc.F, Record, Idx); FunctionProtoType::ExtProtoInfo EPI; EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1], @@ -3260,9 +3272,9 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { unsigned Idx = 6; unsigned NumParams = Record[Idx++]; - llvm::SmallVector<QualType, 16> ParamTypes; + SmallVector<QualType, 16> ParamTypes; for (unsigned I = 0; I != NumParams; ++I) - ParamTypes.push_back(GetType(Record[Idx++])); + ParamTypes.push_back(readType(*Loc.F, Record, Idx)); EPI.Variadic = Record[Idx++]; EPI.TypeQuals = Record[Idx++]; @@ -3272,65 +3284,70 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { EPI.ExceptionSpecType = EST; if (EST == EST_Dynamic) { EPI.NumExceptions = Record[Idx++]; - llvm::SmallVector<QualType, 2> Exceptions; + SmallVector<QualType, 2> Exceptions; for (unsigned I = 0; I != EPI.NumExceptions; ++I) - Exceptions.push_back(GetType(Record[Idx++])); + Exceptions.push_back(readType(*Loc.F, Record, Idx)); EPI.Exceptions = Exceptions.data(); } else if (EST == EST_ComputedNoexcept) { EPI.NoexceptExpr = ReadExpr(*Loc.F); } - return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams, + return Context.getFunctionType(ResultType, ParamTypes.data(), NumParams, EPI); } - case TYPE_UNRESOLVED_USING: - return Context->getTypeDeclType( - cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0]))); - + 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(); } - TypedefNameDecl *Decl = cast<TypedefNameDecl>(GetDecl(Record[0])); - QualType Canonical = GetType(Record[1]); + 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); + Canonical = Context.getCanonicalType(Canonical); + return Context.getTypedefType(Decl, Canonical); } case TYPE_TYPEOF_EXPR: - return Context->getTypeOfExprType(ReadExpr(*Loc.F)); + 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 = GetType(Record[0]); - return Context->getTypeOfType(UnderlyingType); + QualType UnderlyingType = readType(*Loc.F, Record, Idx); + return Context.getTypeOfType(UnderlyingType); } case TYPE_DECLTYPE: - return Context->getDecltypeType(ReadExpr(*Loc.F)); + return Context.getDecltypeType(ReadExpr(*Loc.F)); case TYPE_UNARY_TRANSFORM: { - QualType BaseType = GetType(Record[0]); - QualType UnderlyingType = GetType(Record[1]); + 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); + return Context.getUnaryTransformType(BaseType, UnderlyingType, UKind); } case TYPE_AUTO: - return Context->getAutoType(GetType(Record[0])); + return Context.getAutoType(readType(*Loc.F, Record, Idx)); case TYPE_RECORD: { if (Record.size() != 2) { Error("incorrect encoding of record type"); return QualType(); } - bool IsDependent = Record[0]; - QualType T = Context->getRecordType(cast<RecordDecl>(GetDecl(Record[1]))); + unsigned Idx = 0; + bool IsDependent = Record[Idx++]; + QualType T + = Context.getRecordType(ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx)); const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); return T; } @@ -3340,8 +3357,10 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("incorrect encoding of enum type"); return QualType(); } - bool IsDependent = Record[0]; - QualType T = Context->getEnumType(cast<EnumDecl>(GetDecl(Record[1]))); + 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; } @@ -3351,10 +3370,10 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("incorrect encoding of attributed type"); return QualType(); } - QualType modifiedType = GetType(Record[0]); - QualType equivalentType = GetType(Record[1]); + 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); + return Context.getAttributedType(kind, modifiedType, equivalentType); } case TYPE_PAREN: { @@ -3362,8 +3381,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("incorrect encoding of paren type"); return QualType(); } - QualType InnerType = GetType(Record[0]); - return Context->getParenType(InnerType); + QualType InnerType = readType(*Loc.F, Record, Idx); + return Context.getParenType(InnerType); } case TYPE_PACK_EXPANSION: { @@ -3371,70 +3390,71 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("incorrect encoding of pack expansion type"); return QualType(); } - QualType Pattern = GetType(Record[0]); + 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); + return Context.getPackExpansionType(Pattern, NumExpansions); } case TYPE_ELABORATED: { unsigned Idx = 0; ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - QualType NamedType = GetType(Record[Idx++]); - return Context->getElaboratedType(Keyword, NNS, NamedType); + 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 = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++])); - return Context->getObjCInterfaceType(ItfD); + ObjCInterfaceDecl *ItfD + = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx); + return Context.getObjCInterfaceType(ItfD); } case TYPE_OBJC_OBJECT: { unsigned Idx = 0; - QualType Base = GetType(Record[Idx++]); + QualType Base = readType(*Loc.F, Record, Idx); unsigned NumProtos = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl*, 4> Protos; + SmallVector<ObjCProtocolDecl*, 4> Protos; for (unsigned I = 0; I != NumProtos; ++I) - Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); - return Context->getObjCObjectType(Base, Protos.data(), NumProtos); + 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 = GetType(Record[Idx++]); - return Context->getObjCObjectPointerType(Pointee); + QualType Pointee = readType(*Loc.F, Record, Idx); + return Context.getObjCObjectPointerType(Pointee); } case TYPE_SUBST_TEMPLATE_TYPE_PARM: { unsigned Idx = 0; - QualType Parm = GetType(Record[Idx++]); - QualType Replacement = GetType(Record[Idx++]); + QualType Parm = readType(*Loc.F, Record, Idx); + QualType Replacement = readType(*Loc.F, Record, Idx); return - Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), + Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), Replacement); } case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: { unsigned Idx = 0; - QualType Parm = GetType(Record[Idx++]); + QualType Parm = readType(*Loc.F, Record, Idx); TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx); - return Context->getSubstTemplateTypeParmPackType( + return Context.getSubstTemplateTypeParmPackType( cast<TemplateTypeParmType>(Parm), ArgPack); } case TYPE_INJECTED_CLASS_NAME: { - CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0])); - QualType TST = GetType(Record[1]); // probably derivable + 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); + QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0); } case TYPE_TEMPLATE_TYPE_PARM: { @@ -3442,33 +3462,33 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { unsigned Depth = Record[Idx++]; unsigned Index = Record[Idx++]; bool Pack = Record[Idx++]; - TemplateTypeParmDecl *D = - cast_or_null<TemplateTypeParmDecl>(GetDecl(Record[Idx++])); - return Context->getTemplateTypeParmType(Depth, Index, Pack, D); + 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(Record, Idx); - const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); - QualType Canon = GetType(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); + 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(Record, Idx); - const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); + NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx); + const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx); unsigned NumArgs = Record[Idx++]; - llvm::SmallVector<TemplateArgument, 8> Args; + SmallVector<TemplateArgument, 8> Args; Args.reserve(NumArgs); while (NumArgs--) Args.push_back(ReadTemplateArgument(*Loc.F, Record, Idx)); - return Context->getDependentTemplateSpecializationType(Keyword, NNS, Name, + return Context.getDependentTemplateSpecializationType(Keyword, NNS, Name, Args.size(), Args.data()); } @@ -3476,7 +3496,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { unsigned Idx = 0; // ArrayType - QualType ElementType = GetType(Record[Idx++]); + QualType ElementType = readType(*Loc.F, Record, Idx); ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[Idx++]; unsigned IndexTypeQuals = Record[Idx++]; @@ -3485,7 +3505,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Expr *NumElts = ReadExpr(*Loc.F); SourceRange Brackets = ReadSourceRange(*Loc.F, Record, Idx); - return Context->getDependentSizedArrayType(ElementType, NumElts, ASM, + return Context.getDependentSizedArrayType(ElementType, NumElts, ASM, IndexTypeQuals, Brackets); } @@ -3493,19 +3513,28 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { unsigned Idx = 0; bool IsDependent = Record[Idx++]; TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx); - llvm::SmallVector<TemplateArgument, 8> Args; + SmallVector<TemplateArgument, 8> Args; ReadTemplateArgumentList(Args, *Loc.F, Record, Idx); - QualType Underlying = GetType(Record[Idx++]); + QualType Underlying = readType(*Loc.F, Record, Idx); QualType T; if (Underlying.isNull()) - T = Context->getCanonicalTemplateSpecializationType(Name, Args.data(), + T = Context.getCanonicalTemplateSpecializationType(Name, Args.data(), Args.size()); else - T = Context->getTemplateSpecializationType(Name, Args.data(), + 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); + } } // Suppress a GCC warning return QualType(); @@ -3513,7 +3542,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> { ASTReader &Reader; - ASTReader::PerFileData &F; + Module &F; llvm::BitstreamCursor &DeclsCursor; const ASTReader::RecordData &Record; unsigned &Idx; @@ -3523,8 +3552,13 @@ class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> { 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, ASTReader::PerFileData &F, + TypeLocReader(ASTReader &Reader, Module &F, const ASTReader::RecordData &Record, unsigned &Idx) : Reader(Reader), F(F), DeclsCursor(F.DeclsCursor), Record(Record), Idx(Idx) { } @@ -3608,7 +3642,7 @@ void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx)); TL.setTrailingReturn(Record[Idx++]); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { - TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); + TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx)); } } void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { @@ -3735,15 +3769,20 @@ void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { 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(PerFileData &F, +TypeSourceInfo *ASTReader::GetTypeSourceInfo(Module &F, const RecordData &Record, unsigned &Idx) { - QualType InfoTy = GetType(Record[Idx++]); + QualType InfoTy = readType(F, Record, Idx); if (InfoTy.isNull()) return 0; - TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy); + TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy); TypeLocReader TLR(*this, F, Record, Idx); for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) TLR.Visit(TL); @@ -3758,41 +3797,47 @@ QualType ASTReader::GetType(TypeID ID) { 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_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; + 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_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_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_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_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; } assert(!T.isNull() && "Unknown predefined type"); @@ -3802,12 +3847,11 @@ QualType ASTReader::GetType(TypeID ID) { Index -= NUM_PREDEF_TYPE_IDS; assert(Index < TypesLoaded.size() && "Type index out-of-range"); if (TypesLoaded[Index].isNull()) { - TypesLoaded[Index] = ReadTypeRecord(Index); + TypesLoaded[Index] = readTypeRecord(Index); if (TypesLoaded[Index].isNull()) return QualType(); TypesLoaded[Index]->setFromAST(); - TypeIdxs[TypesLoaded[Index]] = TypeIdx::fromTypeID(ID); if (DeserializationListener) DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID), TypesLoaded[Index]); @@ -3816,37 +3860,28 @@ QualType ASTReader::GetType(TypeID ID) { return TypesLoaded[Index].withFastQualifiers(FastQuals); } -TypeID ASTReader::GetTypeID(QualType T) const { - return MakeTypeID(T, - std::bind1st(std::mem_fun(&ASTReader::GetTypeIdx), this)); +QualType ASTReader::getLocalType(Module &F, unsigned LocalID) { + return GetType(getGlobalTypeID(F, LocalID)); } -TypeIdx ASTReader::GetTypeIdx(QualType T) const { - if (T.isNull()) - return TypeIdx(); - assert(!T.getLocalFastQualifiers()); - - TypeIdxMap::const_iterator I = TypeIdxs.find(T); - // GetTypeIdx is mostly used for computing the hash of DeclarationNames and - // comparing keys of ASTDeclContextNameLookupTable. - // If the type didn't come from the AST file use a specially marked index - // so that any hash/key comparison fail since no such index is stored - // in a AST file. - if (I == TypeIdxs.end()) - return TypeIdx(-1); - return I->second; -} +serialization::TypeID +ASTReader::getGlobalTypeID(Module &F, unsigned LocalID) const { + unsigned FastQuals = LocalID & Qualifiers::FastMask; + unsigned LocalIndex = LocalID >> Qualifiers::FastWidth; + + if (LocalIndex < NUM_PREDEF_TYPE_IDS) + return LocalID; -unsigned ASTReader::getTotalNumCXXBaseSpecifiers() const { - unsigned Result = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) - Result += Chain[I]->LocalNumCXXBaseSpecifiers; + 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"); - return Result; + unsigned GlobalIndex = LocalIndex + I->second; + return (GlobalIndex << Qualifiers::FastWidth) | FastQuals; } TemplateArgumentLocInfo -ASTReader::GetTemplateArgumentLocInfo(PerFileData &F, +ASTReader::GetTemplateArgumentLocInfo(Module &F, TemplateArgument::ArgKind Kind, const RecordData &Record, unsigned &Index) { @@ -3881,7 +3916,7 @@ ASTReader::GetTemplateArgumentLocInfo(PerFileData &F, } TemplateArgumentLoc -ASTReader::ReadTemplateArgumentLoc(PerFileData &F, +ASTReader::ReadTemplateArgumentLoc(Module &F, const RecordData &Record, unsigned &Index) { TemplateArgument Arg = ReadTemplateArgument(F, Record, Index); @@ -3897,47 +3932,20 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) { return GetDecl(ID); } -uint64_t -ASTReader::GetCXXBaseSpecifiersOffset(serialization::CXXBaseSpecifiersID ID) { - if (ID == 0) +uint64_t ASTReader::readCXXBaseSpecifiers(Module &M, const RecordData &Record, + unsigned &Idx){ + if (Idx >= Record.size()) return 0; - --ID; - uint64_t Offset = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[N - I - 1]; - - if (ID < F.LocalNumCXXBaseSpecifiers) - return Offset + F.CXXBaseSpecifiersOffsets[ID]; - - ID -= F.LocalNumCXXBaseSpecifiers; - Offset += F.SizeInBits; - } - - assert(false && "CXXBaseSpecifiers not found"); - return 0; + unsigned LocalID = Record[Idx++]; + return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]); } CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { - // Figure out which AST file contains this offset. - PerFileData *F = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - if (Offset < Chain[N - I - 1]->SizeInBits) { - F = Chain[N - I - 1]; - break; - } - - Offset -= Chain[N - I - 1]->SizeInBits; - } - - if (!F) { - Error("Malformed AST file: C++ base specifiers at impossible offset"); - return 0; - } - - llvm::BitstreamCursor &Cursor = F->DeclsCursor; + RecordLocation Loc = getLocalBitOffset(Offset); + llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Offset); + Cursor.JumpToBit(Loc.Offset); ReadingKindTracker ReadingKind(Read_Decl, *this); RecordData Record; unsigned Code = Cursor.ReadCode(); @@ -3949,35 +3957,72 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { unsigned Idx = 0; unsigned NumBases = Record[Idx++]; - void *Mem = Context->Allocate(sizeof(CXXBaseSpecifier) * NumBases); + void *Mem = Context.Allocate(sizeof(CXXBaseSpecifier) * NumBases); CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases]; for (unsigned I = 0; I != NumBases; ++I) - Bases[I] = ReadCXXBaseSpecifier(*F, Record, Idx); + Bases[I] = ReadCXXBaseSpecifier(*Loc.F, Record, Idx); return Bases; } -TranslationUnitDecl *ASTReader::GetTranslationUnitDecl() { - if (!DeclsLoaded[0]) { - ReadDeclRecord(0, 1); - if (DeserializationListener) - DeserializationListener->DeclRead(1, DeclsLoaded[0]); - } +serialization::DeclID +ASTReader::getGlobalDeclID(Module &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; +} - return cast<TranslationUnitDecl>(DeclsLoaded[0]); +bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, + Module &M) const { + GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID); + assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); + return &M == I->second; } Decl *ASTReader::GetDecl(DeclID ID) { - if (ID == 0) + 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_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(); + } + return 0; + } + + unsigned Index = ID - NUM_PREDEF_DECL_IDS; - if (ID > DeclsLoaded.size()) { + if (Index > DeclsLoaded.size()) { Error("declaration ID out-of-range for AST file"); return 0; } - - unsigned Index = ID - 1; - if (!DeclsLoaded[Index]) { - ReadDeclRecord(Index, ID); + +if (!DeclsLoaded[Index]) { + ReadDeclRecord(ID); if (DeserializationListener) DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); } @@ -3985,6 +4030,17 @@ Decl *ASTReader::GetDecl(DeclID ID) { return DeclsLoaded[Index]; } +serialization::DeclID ASTReader::ReadDeclID(Module &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 @@ -3995,49 +4051,137 @@ Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) { ClearSwitchCaseIDs(); // Offset here is a global offset across the entire chain. - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[N - I - 1]; - if (Offset < F.SizeInBits) { - // Since we know that this statement is part of a decl, make sure to use - // the decl cursor to read it. - F.DeclsCursor.JumpToBit(Offset); - return ReadStmtFromStream(F); - } - Offset -= F.SizeInBits; - } - llvm_unreachable("Broken chain"); + RecordLocation Loc = getLocalBitOffset(Offset); + Loc.F->DeclsCursor.JumpToBit(Loc.Offset); + return ReadStmtFromStream(*Loc.F); } -ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - llvm::SmallVectorImpl<Decl*> &Decls) { - // There might be lexical decls in multiple parts of the chain, for the TU - // at least. - // DeclContextOffsets might reallocate as we load additional decls below, - // so make a copy of the vector. - DeclContextInfos Infos = DeclContextOffsets[DC]; - for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end(); - I != E; ++I) { - // IDs can be 0 if this context doesn't contain declarations. - if (!I->LexicalDecls) - continue; +namespace { + class FindExternalLexicalDeclsVisitor { + ASTReader &Reader; + const DeclContext *DC; + bool (*isKindWeWant)(Decl::Kind); + + SmallVectorImpl<Decl*> &Decls; + bool PredefsVisited[NUM_PREDEF_DECL_IDS]; - // Load all of the declaration IDs - for (const KindDeclIDPair *ID = I->LexicalDecls, - *IDE = ID + I->NumLexicalDecls; ID != IDE; ++ID) { - if (isKindWeWant && !isKindWeWant((Decl::Kind)ID->first)) - continue; + 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; + } - Decl *D = GetDecl(ID->second); - assert(D && "Null decl in lexical decls"); - Decls.push_back(D); + static bool visit(Module &M, bool Preorder, void *UserData) { + if (Preorder) + return false; + + FindExternalLexicalDeclsVisitor *This + = static_cast<FindExternalLexicalDeclsVisitor *>(UserData); + + Module::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 { + /// \brief Module visitor used to perform name lookup into a + /// declaration context. + class DeclContextNameLookupVisitor { + ASTReader &Reader; + const DeclContext *DC; + DeclarationName Name; + SmallVectorImpl<NamedDecl *> &Decls; + + public: + DeclContextNameLookupVisitor(ASTReader &Reader, + const DeclContext *DC, DeclarationName Name, + SmallVectorImpl<NamedDecl *> &Decls) + : Reader(Reader), DC(DC), Name(Name), Decls(Decls) { } + + static bool visit(Module &M, void *UserData) { + DeclContextNameLookupVisitor *This + = static_cast<DeclContextNameLookupVisitor *>(UserData); + + // Check whether we have any visible declaration information for + // this context in this module. + Module::DeclContextInfosMap::iterator Info + = M.DeclContextInfos.find(This->DC); + if (Info == M.DeclContextInfos.end() || !Info->second.NameLookupTableData) + return false; + + // Look for this name within this module. + ASTDeclContextNameLookupTable *LookupTable = + (ASTDeclContextNameLookupTable*)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) { @@ -4047,69 +4191,39 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, return DeclContext::lookup_result(DeclContext::lookup_iterator(0), DeclContext::lookup_iterator(0)); - llvm::SmallVector<NamedDecl *, 64> Decls; - // There might be visible decls in multiple parts of the chain, for the TU - // and namespaces. For any given name, the last available results replace - // all earlier ones. For this reason, we walk in reverse. - DeclContextInfos &Infos = DeclContextOffsets[DC]; - for (DeclContextInfos::reverse_iterator I = Infos.rbegin(), E = Infos.rend(); - I != E; ++I) { - if (!I->NameLookupTableData) - continue; - - ASTDeclContextNameLookupTable *LookupTable = - (ASTDeclContextNameLookupTable*)I->NameLookupTableData; - ASTDeclContextNameLookupTable::iterator Pos = LookupTable->find(Name); - if (Pos == LookupTable->end()) - continue; - - ASTDeclContextNameLookupTrait::data_type Data = *Pos; - for (; Data.first != Data.second; ++Data.first) - Decls.push_back(cast<NamedDecl>(GetDecl(*Data.first))); - break; - } - + SmallVector<NamedDecl *, 64> Decls; + DeclContextNameLookupVisitor Visitor(*this, DC, Name, Decls); + ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor); ++NumVisibleDeclContextsRead; - SetExternalVisibleDeclsForName(DC, Name, Decls); return const_cast<DeclContext*>(DC)->lookup(Name); } -void ASTReader::MaterializeVisibleDecls(const DeclContext *DC) { - assert(DC->hasExternalVisibleStorage() && - "DeclContext has no visible decls in storage"); +/// \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); - llvm::SmallVector<NamedDecl *, 64> Decls; - // There might be visible decls in multiple parts of the chain, for the TU - // and namespaces. - DeclContextInfos &Infos = DeclContextOffsets[DC]; - for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end(); - I != E; ++I) { - if (!I->NameLookupTableData) - continue; + for (ObjCImplDecl::method_iterator + I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I) + Consumer->HandleInterestingDecl(DeclGroupRef(*I)); - ASTDeclContextNameLookupTable *LookupTable = - (ASTDeclContextNameLookupTable*)I->NameLookupTableData; - for (ASTDeclContextNameLookupTable::item_iterator - ItemI = LookupTable->item_begin(), - ItemEnd = LookupTable->item_end() ; ItemI != ItemEnd; ++ItemI) { - ASTDeclContextNameLookupTable::item_iterator::value_type Val - = *ItemI; - ASTDeclContextNameLookupTrait::data_type Data = Val.second; - Decls.clear(); - for (; Data.first != Data.second; ++Data.first) - Decls.push_back(cast<NamedDecl>(GetDecl(*Data.first))); - MaterializeVisibleDeclsForName(DC, Val.first, Decls); - } - } + Consumer->HandleInterestingDecl(DeclGroupRef(ImplD)); } void ASTReader::PassInterestingDeclsToConsumer() { assert(Consumer); while (!InterestingDecls.empty()) { - DeclGroupRef DG(InterestingDecls.front()); + Decl *D = InterestingDecls.front(); InterestingDecls.pop_front(); - Consumer->HandleInterestingDecl(DG); + + if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) + PassObjCImplDeclToConsumer(ImplD, Consumer); + else + Consumer->HandleInterestingDecl(DeclGroupRef(D)); } } @@ -4124,6 +4238,7 @@ void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) { // passing to the consumer. GetDecl(ExternalDefinitions[I]); } + ExternalDefinitions.clear(); PassInterestingDeclsToConsumer(); } @@ -4148,7 +4263,7 @@ void ASTReader::PrintStats() { std::fprintf(stderr, " %u stat cache hits\n", NumStatHits); std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses); - if (TotalNumSLocEntries) + if (unsigned TotalNumSLocEntries = getTotalNumSLocs()) std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n", NumSLocEntriesRead, TotalNumSLocEntries, ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100)); @@ -4194,13 +4309,51 @@ void ASTReader::PrintStats() { std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses); } std::fprintf(stderr, "\n"); + dump(); + std::fprintf(stderr, "\n"); +} + +template<typename Key, typename Module, unsigned InitialCapacity> +static void +dumpModuleIDMap(StringRef Name, + const ContinuousRangeMap<Key, Module *, + InitialCapacity> &Map) { + if (Map.begin() == Map.end()) + return; + + typedef ContinuousRangeMap<Key, Module *, 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/Module 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 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 (unsigned i = 0, e = Chain.size(); i != e; ++i) - if (llvm::MemoryBuffer *buf = Chain[i]->Buffer.get()) { + 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: @@ -4211,6 +4364,7 @@ void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { break; } } + } } void ASTReader::InitializeSema(Sema &S) { @@ -4227,114 +4381,14 @@ void ASTReader::InitializeSema(Sema &S) { } PreloadedDecls.clear(); - // If there were any tentative definitions, deserialize them and add - // them to Sema's list of tentative definitions. - for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { - VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I])); - SemaObj->TentativeDefinitions.push_back(Var); - } - - // If there were any unused file scoped decls, deserialize them and add to - // Sema's list of unused file scoped decls. - for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) { - DeclaratorDecl *D = cast<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I])); - SemaObj->UnusedFileScopedDecls.push_back(D); - } - - // If there were any delegating constructors, add them to Sema's list - for (unsigned I = 0, N = DelegatingCtorDecls.size(); I != N; ++I) { - CXXConstructorDecl *D - = cast<CXXConstructorDecl>(GetDecl(DelegatingCtorDecls[I])); - SemaObj->DelegatingCtorDecls.push_back(D); - } - - // If there were any locally-scoped external declarations, - // deserialize them and add them to Sema's table of locally-scoped - // external declarations. - for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) { - NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I])); - SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D; - } - - // If there were any ext_vector type declarations, deserialize them - // and add them to Sema's vector of such declarations. - for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) - SemaObj->ExtVectorDecls.push_back( - cast<TypedefNameDecl>(GetDecl(ExtVectorDecls[I]))); - - // FIXME: Do VTable uses and dynamic classes deserialize too much ? - // Can we cut them down before writing them ? - - // If there were any dynamic classes declarations, deserialize them - // and add them to Sema's vector of such declarations. - for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) - SemaObj->DynamicClasses.push_back( - cast<CXXRecordDecl>(GetDecl(DynamicClasses[I]))); - // Load the offsets of the declarations that Sema references. // They will be lazily deserialized when needed. if (!SemaDeclRefs.empty()) { assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!"); - SemaObj->StdNamespace = SemaDeclRefs[0]; - SemaObj->StdBadAlloc = SemaDeclRefs[1]; - } - - for (PerFileData *F = FirstInSource; F; F = F->NextInSource) { - - // If there are @selector references added them to its pool. This is for - // implementation of -Wselector. - if (!F->ReferencedSelectorsData.empty()) { - unsigned int DataSize = F->ReferencedSelectorsData.size()-1; - unsigned I = 0; - while (I < DataSize) { - Selector Sel = DecodeSelector(F->ReferencedSelectorsData[I++]); - SourceLocation SelLoc = ReadSourceLocation( - *F, F->ReferencedSelectorsData, I); - SemaObj->ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); - } - } - } - - // The special data sets below always come from the most recent PCH, - // which is at the front of the chain. - PerFileData &F = *Chain.front(); - - // If there were any pending implicit instantiations, deserialize them - // and add them to Sema's queue of such instantiations. - assert(F.PendingInstantiations.size() % 2 == 0 && - "Expected pairs of entries"); - for (unsigned Idx = 0, N = F.PendingInstantiations.size(); Idx < N;) { - ValueDecl *D=cast<ValueDecl>(GetDecl(F.PendingInstantiations[Idx++])); - SourceLocation Loc = ReadSourceLocation(F, F.PendingInstantiations,Idx); - SemaObj->PendingInstantiations.push_back(std::make_pair(D, Loc)); - } - - // If there were any weak undeclared identifiers, deserialize them and add to - // Sema's list of weak undeclared identifiers. - if (!WeakUndeclaredIdentifiers.empty()) { - unsigned Idx = 0; - for (unsigned I = 0, N = WeakUndeclaredIdentifiers[Idx++]; I != N; ++I) { - IdentifierInfo *WeakId = GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx); - IdentifierInfo *AliasId= GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx); - SourceLocation Loc = ReadSourceLocation(F, WeakUndeclaredIdentifiers,Idx); - bool Used = WeakUndeclaredIdentifiers[Idx++]; - Sema::WeakInfo WI(AliasId, Loc); - WI.setUsed(Used); - SemaObj->WeakUndeclaredIdentifiers.insert(std::make_pair(WeakId, WI)); - } - } - - // If there were any VTable uses, deserialize the information and add it - // to Sema's vector and map of VTable uses. - if (!VTableUses.empty()) { - unsigned Idx = 0; - for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) { - CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++])); - SourceLocation Loc = ReadSourceLocation(F, VTableUses, Idx); - bool DefinitionRequired = VTableUses[Idx++]; - SemaObj->VTableUses.push_back(std::make_pair(Class, Loc)); - SemaObj->VTablesUsed[Class] = DefinitionRequired; - } + if (!SemaObj->StdNamespace) + SemaObj->StdNamespace = SemaDeclRefs[0]; + if (!SemaObj->StdBadAlloc) + SemaObj->StdBadAlloc = SemaDeclRefs[1]; } if (!FPPragmaOptions.empty()) { @@ -4352,24 +4406,9 @@ void ASTReader::InitializeSema(Sema &S) { } IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { - // Try to find this name within our on-disk hash tables. We start with the - // most recent one, since that one contains the most up-to-date info. - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - ASTIdentifierLookupTable *IdTable - = (ASTIdentifierLookupTable *)Chain[I]->IdentifierLookupTable; - if (!IdTable) - continue; - std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart); - ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key); - if (Pos == IdTable->end()) - continue; - - // Dereferencing the iterator has the effect of building the - // IdentifierInfo node and populating it with the various - // declarations it needs. - return *Pos; - } - return 0; + IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart)); + ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); + return Visitor.getIdentifierInfo(); } namespace clang { @@ -4394,27 +4433,28 @@ namespace clang { public: explicit ASTIdentifierIterator(const ASTReader &Reader); - virtual llvm::StringRef Next(); + virtual StringRef Next(); }; } ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader) - : Reader(Reader), Index(Reader.Chain.size() - 1) { + : Reader(Reader), Index(Reader.ModuleMgr.size() - 1) { ASTIdentifierLookupTable *IdTable - = (ASTIdentifierLookupTable *)Reader.Chain[Index]->IdentifierLookupTable; + = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].IdentifierLookupTable; Current = IdTable->key_begin(); End = IdTable->key_end(); } -llvm::StringRef ASTIdentifierIterator::Next() { +StringRef ASTIdentifierIterator::Next() { while (Current == End) { // If we have exhausted all of our AST files, we're done. if (Index == 0) - return llvm::StringRef(); + return StringRef(); --Index; ASTIdentifierLookupTable *IdTable - = (ASTIdentifierLookupTable *)Reader.Chain[Index]->IdentifierLookupTable; + = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index]. + IdentifierLookupTable; Current = IdTable->key_begin(); End = IdTable->key_end(); } @@ -4423,43 +4463,103 @@ llvm::StringRef ASTIdentifierIterator::Next() { // the next one. std::pair<const char*, unsigned> Key = *Current; ++Current; - return llvm::StringRef(Key.first, Key.second); + return StringRef(Key.first, Key.second); } IdentifierIterator *ASTReader::getIdentifiers() const { return new ASTIdentifierIterator(*this); } -std::pair<ObjCMethodList, ObjCMethodList> -ASTReader::ReadMethodPool(Selector Sel) { - // Find this selector in a hash table. We want to find the most recent entry. - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[I]; - if (!F.SelectorLookupTable) - continue; - - ASTSelectorLookupTable *PoolTable - = (ASTSelectorLookupTable*)F.SelectorLookupTable; - ASTSelectorLookupTable::iterator Pos = PoolTable->find(Sel); - if (Pos != PoolTable->end()) { - ++NumSelectorsRead; +namespace clang { namespace serialization { + class ReadMethodPoolVisitor { + ASTReader &Reader; + Selector Sel; + llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods; + llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods; + + /// \brief Build an ObjCMethodList from a vector of Objective-C method + /// declarations. + ObjCMethodList + buildObjCMethodList(const SmallVectorImpl<ObjCMethodDecl *> &Vec) const + { + ObjCMethodList List; + ObjCMethodList *Prev = 0; + for (unsigned I = 0, N = Vec.size(); I != N; ++I) { + if (!List.Method) { + // This is the first method, which is the easy case. + List.Method = Vec[I]; + Prev = &List; + continue; + } + + ObjCMethodList *Mem = + Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); + Prev->Next = new (Mem) ObjCMethodList(Vec[I], 0); + Prev = Prev->Next; + } + + return List; + } + + public: + ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel) + : Reader(Reader), Sel(Sel) { } + + static bool visit(Module &M, void *UserData) { + ReadMethodPoolVisitor *This + = static_cast<ReadMethodPoolVisitor *>(UserData); + + if (!M.SelectorLookupTable) + return false; + + 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? - ++NumMethodPoolEntriesRead; + ++This->Reader.NumMethodPoolEntriesRead; ASTSelectorLookupTrait::data_type Data = *Pos; - if (DeserializationListener) - DeserializationListener->SelectorRead(Data.ID, Sel); - return std::make_pair(Data.Instance, Data.Factory); + 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. + ObjCMethodList getInstanceMethods() const { + return buildObjCMethodList(InstanceMethods); } - } - ++NumMethodPoolMisses; - return std::pair<ObjCMethodList, ObjCMethodList>(); + /// \brief Retrieve the instance methods found by this visitor. + ObjCMethodList getFactoryMethods() const { + return buildObjCMethodList(FactoryMethods); + } + }; +} } // end namespace clang::serialization + +std::pair<ObjCMethodList, ObjCMethodList> +ASTReader::ReadMethodPool(Selector Sel) { + ReadMethodPoolVisitor Visitor(*this, Sel); + ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor); + std::pair<ObjCMethodList, ObjCMethodList> Result; + Result.first = Visitor.getInstanceMethods(); + Result.second = Visitor.getFactoryMethods(); + + if (!Result.first.Method && !Result.second.Method) + ++NumMethodPoolMisses; + return Result; } void ASTReader::ReadKnownNamespaces( - llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces) { + SmallVectorImpl<NamespaceDecl *> &Namespaces) { Namespaces.clear(); for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) { @@ -4469,12 +4569,136 @@ void ASTReader::ReadKnownNamespaces( } } +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(unsigned ID, IdentifierInfo *II) { +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; @@ -4500,7 +4724,7 @@ void ASTReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) { /// will not be placed onto the pending queue. void ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, - const llvm::SmallVectorImpl<uint32_t> &DeclIDs, + const SmallVectorImpl<uint32_t> &DeclIDs, bool Nonrecursive) { if (NumCurrentElementsDeserializing && !Nonrecursive) { PendingIdentifierInfos.push_back(PendingIdentifierInfo()); @@ -4529,7 +4753,7 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, } } -IdentifierInfo *ASTReader::DecodeIdentifierInfo(unsigned ID) { +IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { if (ID == 0) return 0; @@ -4538,21 +4762,13 @@ IdentifierInfo *ASTReader::DecodeIdentifierInfo(unsigned ID) { return 0; } - assert(PP && "Forgot to set Preprocessor ?"); ID -= 1; if (!IdentifiersLoaded[ID]) { - unsigned Index = ID; - const char *Str = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData *F = Chain[N - I - 1]; - if (Index < F->LocalNumIdentifiers) { - uint32_t Offset = F->IdentifierOffsets[Index]; - Str = F->IdentifierTableData + Offset; - break; - } - Index -= F->LocalNumIdentifiers; - } - assert(Str && "Broken Chain"); + GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1); + assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map"); + Module *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(). @@ -4563,7 +4779,7 @@ IdentifierInfo *ASTReader::DecodeIdentifierInfo(unsigned ID) { unsigned StrLen = (((unsigned) StrLenPtr[0]) | (((unsigned) StrLenPtr[1]) << 8)) - 1; IdentifiersLoaded[ID] - = &PP->getIdentifierTable().get(llvm::StringRef(Str, StrLen)); + = &PP.getIdentifierTable().get(StringRef(Str, StrLen)); if (DeserializationListener) DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]); } @@ -4571,11 +4787,31 @@ IdentifierInfo *ASTReader::DecodeIdentifierInfo(unsigned ID) { return IdentifiersLoaded[ID]; } -bool ASTReader::ReadSLocEntry(unsigned ID) { +IdentifierInfo *ASTReader::getLocalIdentifier(Module &M, unsigned LocalID) { + return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID)); +} + +IdentifierID ASTReader::getGlobalIdentifierID(Module &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; } -Selector ASTReader::DecodeSelector(unsigned ID) { +Selector ASTReader::getLocalSelector(Module &M, unsigned LocalID) { + return DecodeSelector(getGlobalSelectorID(M, LocalID)); +} + +Selector ASTReader::DecodeSelector(serialization::SelectorID ID) { if (ID == 0) return Selector(); @@ -4586,25 +4822,21 @@ Selector ASTReader::DecodeSelector(unsigned ID) { if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) { // Load this selector from the selector table. - unsigned Idx = ID - 1; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[N - I - 1]; - if (Idx < F.LocalNumSelectors) { - ASTSelectorLookupTrait Trait(*this); - SelectorsLoaded[ID - 1] = - Trait.ReadKey(F.SelectorLookupTableData + F.SelectorOffsets[Idx], 0); - if (DeserializationListener) - DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]); - break; - } - Idx -= F.LocalNumSelectors; - } + GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID); + assert(I != GlobalSelectorMap.end() && "Corrupted global selector map"); + Module &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(uint32_t ID) { +Selector ASTReader::GetExternalSelector(serialization::SelectorID ID) { return DecodeSelector(ID); } @@ -4613,37 +4845,51 @@ uint32_t ASTReader::GetNumExternalSelectors() { return getTotalNumSelectors() + 1; } +serialization::SelectorID +ASTReader::getGlobalSelectorID(Module &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(const RecordData &Record, unsigned &Idx) { +ASTReader::ReadDeclarationName(Module &F, + const RecordData &Record, unsigned &Idx) { DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; switch (Kind) { case DeclarationName::Identifier: - return DeclarationName(GetIdentifierInfo(Record, Idx)); + return DeclarationName(GetIdentifierInfo(F, Record, Idx)); case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - return DeclarationName(GetSelector(Record, Idx)); + return DeclarationName(ReadSelector(F, Record, Idx)); case DeclarationName::CXXConstructorName: - return Context->DeclarationNames.getCXXConstructorName( - Context->getCanonicalType(GetType(Record[Idx++]))); + return Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(readType(F, Record, Idx))); case DeclarationName::CXXDestructorName: - return Context->DeclarationNames.getCXXDestructorName( - Context->getCanonicalType(GetType(Record[Idx++]))); + return Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(readType(F, Record, Idx))); case DeclarationName::CXXConversionFunctionName: - return Context->DeclarationNames.getCXXConversionFunctionName( - Context->getCanonicalType(GetType(Record[Idx++]))); + return Context.DeclarationNames.getCXXConversionFunctionName( + Context.getCanonicalType(readType(F, Record, Idx))); case DeclarationName::CXXOperatorName: - return Context->DeclarationNames.getCXXOperatorName( + return Context.DeclarationNames.getCXXOperatorName( (OverloadedOperatorKind)Record[Idx++]); case DeclarationName::CXXLiteralOperatorName: - return Context->DeclarationNames.getCXXLiteralOperatorName( - GetIdentifierInfo(Record, Idx)); + return Context.DeclarationNames.getCXXLiteralOperatorName( + GetIdentifierInfo(F, Record, Idx)); case DeclarationName::CXXUsingDirective: return DeclarationName::getUsingDirectiveName(); @@ -4653,7 +4899,7 @@ ASTReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { return DeclarationName(); } -void ASTReader::ReadDeclarationNameLoc(PerFileData &F, +void ASTReader::ReadDeclarationNameLoc(Module &F, DeclarationNameLoc &DNLoc, DeclarationName Name, const RecordData &Record, unsigned &Idx) { @@ -4685,72 +4931,73 @@ void ASTReader::ReadDeclarationNameLoc(PerFileData &F, } } -void ASTReader::ReadDeclarationNameInfo(PerFileData &F, +void ASTReader::ReadDeclarationNameInfo(Module &F, DeclarationNameInfo &NameInfo, const RecordData &Record, unsigned &Idx) { - NameInfo.setName(ReadDeclarationName(Record, 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(PerFileData &F, QualifierInfo &Info, +void ASTReader::ReadQualifierInfo(Module &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]; + Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists]; for (unsigned i=0; i != NumTPLists; ++i) Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx); } } TemplateName -ASTReader::ReadTemplateName(PerFileData &F, const RecordData &Record, +ASTReader::ReadTemplateName(Module &F, const RecordData &Record, unsigned &Idx) { TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; switch (Kind) { case TemplateName::Template: - return TemplateName(cast_or_null<TemplateDecl>(GetDecl(Record[Idx++]))); + return TemplateName(ReadDeclAs<TemplateDecl>(F, Record, Idx)); case TemplateName::OverloadedTemplate: { unsigned size = Record[Idx++]; UnresolvedSet<8> Decls; while (size--) - Decls.addDecl(cast<NamedDecl>(GetDecl(Record[Idx++]))); + Decls.addDecl(ReadDeclAs<NamedDecl>(F, Record, Idx)); - return Context->getOverloadedTemplateName(Decls.begin(), Decls.end()); + return Context.getOverloadedTemplateName(Decls.begin(), Decls.end()); } case TemplateName::QualifiedTemplate: { - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); + NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx); bool hasTemplKeyword = Record[Idx++]; - TemplateDecl *Template = cast<TemplateDecl>(GetDecl(Record[Idx++])); - return Context->getQualifiedTemplateName(NNS, hasTemplKeyword, Template); + TemplateDecl *Template = ReadDeclAs<TemplateDecl>(F, Record, Idx); + return Context.getQualifiedTemplateName(NNS, hasTemplKeyword, Template); } case TemplateName::DependentTemplate: { - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); + NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx); if (Record[Idx++]) // isIdentifier - return Context->getDependentTemplateName(NNS, - GetIdentifierInfo(Record, Idx)); - return Context->getDependentTemplateName(NNS, + return Context.getDependentTemplateName(NNS, + GetIdentifierInfo(F, Record, + Idx)); + return Context.getDependentTemplateName(NNS, (OverloadedOperatorKind)Record[Idx++]); } case TemplateName::SubstTemplateTemplateParm: { TemplateTemplateParmDecl *param - = cast_or_null<TemplateTemplateParmDecl>(GetDecl(Record[Idx++])); + = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx); if (!param) return TemplateName(); TemplateName replacement = ReadTemplateName(F, Record, Idx); - return Context->getSubstTemplateTemplateParm(param, replacement); + return Context.getSubstTemplateTemplateParm(param, replacement); } case TemplateName::SubstTemplateTemplateParmPack: { TemplateTemplateParmDecl *Param - = cast_or_null<TemplateTemplateParmDecl>(GetDecl(Record[Idx++])); + = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx); if (!Param) return TemplateName(); @@ -4758,28 +5005,27 @@ ASTReader::ReadTemplateName(PerFileData &F, const RecordData &Record, if (ArgPack.getKind() != TemplateArgument::Pack) return TemplateName(); - return Context->getSubstTemplateTemplateParmPack(Param, ArgPack); + return Context.getSubstTemplateTemplateParmPack(Param, ArgPack); } } - assert(0 && "Unhandled template name kind!"); - return TemplateName(); + llvm_unreachable("Unhandled template name kind!"); } TemplateArgument -ASTReader::ReadTemplateArgument(PerFileData &F, +ASTReader::ReadTemplateArgument(Module &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(GetType(Record[Idx++])); + return TemplateArgument(readType(F, Record, Idx)); case TemplateArgument::Declaration: - return TemplateArgument(GetDecl(Record[Idx++])); + return TemplateArgument(ReadDecl(F, Record, Idx)); case TemplateArgument::Integral: { llvm::APSInt Value = ReadAPSInt(Record, Idx); - QualType T = GetType(Record[Idx++]); + QualType T = readType(F, Record, Idx); return TemplateArgument(Value, T); } case TemplateArgument::Template: @@ -4795,40 +5041,39 @@ ASTReader::ReadTemplateArgument(PerFileData &F, return TemplateArgument(ReadExpr(F)); case TemplateArgument::Pack: { unsigned NumArgs = Record[Idx++]; - TemplateArgument *Args = new (*Context) TemplateArgument[NumArgs]; + TemplateArgument *Args = new (Context) TemplateArgument[NumArgs]; for (unsigned I = 0; I != NumArgs; ++I) Args[I] = ReadTemplateArgument(F, Record, Idx); return TemplateArgument(Args, NumArgs); } } - assert(0 && "Unhandled template argument kind!"); - return TemplateArgument(); + llvm_unreachable("Unhandled template argument kind!"); } TemplateParameterList * -ASTReader::ReadTemplateParameterList(PerFileData &F, +ASTReader::ReadTemplateParameterList(Module &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++]; - llvm::SmallVector<NamedDecl *, 16> Params; + SmallVector<NamedDecl *, 16> Params; Params.reserve(NumParams); while (NumParams--) - Params.push_back(cast<NamedDecl>(GetDecl(Record[Idx++]))); + Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx)); TemplateParameterList* TemplateParams = - TemplateParameterList::Create(*Context, TemplateLoc, LAngleLoc, + TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, Params.data(), Params.size(), RAngleLoc); return TemplateParams; } void ASTReader:: -ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs, - PerFileData &F, const RecordData &Record, +ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs, + Module &F, const RecordData &Record, unsigned &Idx) { unsigned NumTemplateArgs = Record[Idx++]; TemplArgs.reserve(NumTemplateArgs); @@ -4837,18 +5082,18 @@ ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs, } /// \brief Read a UnresolvedSet structure. -void ASTReader::ReadUnresolvedSet(UnresolvedSetImpl &Set, +void ASTReader::ReadUnresolvedSet(Module &F, UnresolvedSetImpl &Set, const RecordData &Record, unsigned &Idx) { unsigned NumDecls = Record[Idx++]; while (NumDecls--) { - NamedDecl *D = cast<NamedDecl>(GetDecl(Record[Idx++])); + NamedDecl *D = ReadDeclAs<NamedDecl>(F, Record, Idx); AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; Set.addDecl(D, AS); } } CXXBaseSpecifier -ASTReader::ReadCXXBaseSpecifier(PerFileData &F, +ASTReader::ReadCXXBaseSpecifier(Module &F, const RecordData &Record, unsigned &Idx) { bool isVirtual = static_cast<bool>(Record[Idx++]); bool isBaseOfClass = static_cast<bool>(Record[Idx++]); @@ -4864,15 +5109,13 @@ ASTReader::ReadCXXBaseSpecifier(PerFileData &F, } std::pair<CXXCtorInitializer **, unsigned> -ASTReader::ReadCXXCtorInitializers(PerFileData &F, const RecordData &Record, +ASTReader::ReadCXXCtorInitializers(Module &F, const RecordData &Record, unsigned &Idx) { CXXCtorInitializer **CtorInitializers = 0; unsigned NumInitializers = Record[Idx++]; if (NumInitializers) { - ASTContext &C = *getContext(); - CtorInitializers - = new (C) CXXCtorInitializer*[NumInitializers]; + = new (Context) CXXCtorInitializer*[NumInitializers]; for (unsigned i=0; i != NumInitializers; ++i) { TypeSourceInfo *BaseClassInfo = 0; bool IsBaseVirtual = false; @@ -4888,15 +5131,15 @@ ASTReader::ReadCXXCtorInitializers(PerFileData &F, const RecordData &Record, break; case CTOR_INITIALIZER_DELEGATING: - Target = cast<CXXConstructorDecl>(GetDecl(Record[Idx++])); + Target = ReadDeclAs<CXXConstructorDecl>(F, Record, Idx); break; case CTOR_INITIALIZER_MEMBER: - Member = cast<FieldDecl>(GetDecl(Record[Idx++])); + Member = ReadDeclAs<FieldDecl>(F, Record, Idx); break; case CTOR_INITIALIZER_INDIRECT_MEMBER: - IndirectMember = cast<IndirectFieldDecl>(GetDecl(Record[Idx++])); + IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx); break; } @@ -4906,34 +5149,34 @@ ASTReader::ReadCXXCtorInitializers(PerFileData &F, const RecordData &Record, SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); bool IsWritten = Record[Idx++]; unsigned SourceOrderOrNumArrayIndices; - llvm::SmallVector<VarDecl *, 8> Indices; + SmallVector<VarDecl *, 8> Indices; if (IsWritten) { SourceOrderOrNumArrayIndices = Record[Idx++]; } else { SourceOrderOrNumArrayIndices = Record[Idx++]; Indices.reserve(SourceOrderOrNumArrayIndices); for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i) - Indices.push_back(cast<VarDecl>(GetDecl(Record[Idx++]))); + Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx)); } CXXCtorInitializer *BOMInit; if (Type == CTOR_INITIALIZER_BASE) { - BOMInit = new (C) CXXCtorInitializer(C, BaseClassInfo, IsBaseVirtual, + BOMInit = new (Context) CXXCtorInitializer(Context, BaseClassInfo, IsBaseVirtual, LParenLoc, Init, RParenLoc, MemberOrEllipsisLoc); } else if (Type == CTOR_INITIALIZER_DELEGATING) { - BOMInit = new (C) CXXCtorInitializer(C, MemberOrEllipsisLoc, LParenLoc, + BOMInit = new (Context) CXXCtorInitializer(Context, MemberOrEllipsisLoc, LParenLoc, Target, Init, RParenLoc); } else if (IsWritten) { if (Member) - BOMInit = new (C) CXXCtorInitializer(C, Member, MemberOrEllipsisLoc, + BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc); else - BOMInit = new (C) CXXCtorInitializer(C, IndirectMember, + BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc); } else { - BOMInit = CXXCtorInitializer::Create(C, Member, MemberOrEllipsisLoc, + BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc, Indices.data(), Indices.size()); } @@ -4948,7 +5191,8 @@ ASTReader::ReadCXXCtorInitializers(PerFileData &F, const RecordData &Record, } NestedNameSpecifier * -ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { +ASTReader::ReadNestedNameSpecifier(Module &F, + const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; NestedNameSpecifier *NNS = 0, *Prev = 0; for (unsigned I = 0; I != N; ++I) { @@ -4956,37 +5200,36 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; switch (Kind) { case NestedNameSpecifier::Identifier: { - IdentifierInfo *II = GetIdentifierInfo(Record, Idx); - NNS = NestedNameSpecifier::Create(*Context, Prev, II); + IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx); + NNS = NestedNameSpecifier::Create(Context, Prev, II); break; } case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++])); - NNS = NestedNameSpecifier::Create(*Context, Prev, NS); + NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx); + NNS = NestedNameSpecifier::Create(Context, Prev, NS); break; } case NestedNameSpecifier::NamespaceAlias: { - NamespaceAliasDecl *Alias - = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++])); - NNS = NestedNameSpecifier::Create(*Context, Prev, Alias); + NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx); + NNS = NestedNameSpecifier::Create(Context, Prev, Alias); break; } case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { - const Type *T = GetType(Record[Idx++]).getTypePtrOrNull(); + const Type *T = readType(F, Record, Idx).getTypePtrOrNull(); if (!T) return 0; bool Template = Record[Idx++]; - NNS = NestedNameSpecifier::Create(*Context, Prev, Template, T); + NNS = NestedNameSpecifier::Create(Context, Prev, Template, T); break; } case NestedNameSpecifier::Global: { - NNS = NestedNameSpecifier::GlobalSpecifier(*Context); + NNS = NestedNameSpecifier::GlobalSpecifier(Context); // No associated value, and there can't be a prefix. break; } @@ -4997,7 +5240,7 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { } NestedNameSpecifierLoc -ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record, +ASTReader::ReadNestedNameSpecifierLoc(Module &F, const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; NestedNameSpecifierLocBuilder Builder; @@ -5006,24 +5249,23 @@ ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record, = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; switch (Kind) { case NestedNameSpecifier::Identifier: { - IdentifierInfo *II = GetIdentifierInfo(Record, Idx); + IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx); SourceRange Range = ReadSourceRange(F, Record, Idx); - Builder.Extend(*Context, II, Range.getBegin(), Range.getEnd()); + Builder.Extend(Context, II, Range.getBegin(), Range.getEnd()); break; } case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++])); + NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx); SourceRange Range = ReadSourceRange(F, Record, Idx); - Builder.Extend(*Context, NS, Range.getBegin(), Range.getEnd()); + Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd()); break; } case NestedNameSpecifier::NamespaceAlias: { - NamespaceAliasDecl *Alias - = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++])); + NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx); SourceRange Range = ReadSourceRange(F, Record, Idx); - Builder.Extend(*Context, Alias, Range.getBegin(), Range.getEnd()); + Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd()); break; } @@ -5036,7 +5278,7 @@ ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record, SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); // FIXME: 'template' keyword location not saved anywhere, so we fake it. - Builder.Extend(*Context, + Builder.Extend(Context, Template? T->getTypeLoc().getBeginLoc() : SourceLocation(), T->getTypeLoc(), ColonColonLoc); break; @@ -5044,17 +5286,17 @@ ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record, case NestedNameSpecifier::Global: { SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); - Builder.MakeGlobal(*Context, ColonColonLoc); + Builder.MakeGlobal(Context, ColonColonLoc); break; } } } - return Builder.getWithLocInContext(*Context); + return Builder.getWithLocInContext(Context); } SourceRange -ASTReader::ReadSourceRange(PerFileData &F, const RecordData &Record, +ASTReader::ReadSourceRange(Module &F, const RecordData &Record, unsigned &Idx) { SourceLocation beg = ReadSourceLocation(F, Record, Idx); SourceLocation end = ReadSourceLocation(F, Record, Idx); @@ -5101,10 +5343,11 @@ VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, return VersionTuple(Major, Minor - 1, Subminor - 1); } -CXXTemporary *ASTReader::ReadCXXTemporary(const RecordData &Record, +CXXTemporary *ASTReader::ReadCXXTemporary(Module &F, + const RecordData &Record, unsigned &Idx) { - CXXDestructorDecl *Decl = cast<CXXDestructorDecl>(GetDecl(Record[Idx++])); - return CXXTemporary::Create(*Context, Decl); + CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx); + return CXXTemporary::Create(Context, Decl); } DiagnosticBuilder ASTReader::Diag(unsigned DiagID) { @@ -5118,8 +5361,7 @@ DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) { /// \brief Retrieve the identifier table associated with the /// preprocessor. IdentifierTable &ASTReader::getIdentifierTable() { - assert(PP && "Forgot to set Preprocessor ?"); - return PP->getIdentifierTable(); + return PP.getIdentifierTable(); } /// \brief Record that the given ID maps to the given switch-case @@ -5169,56 +5411,29 @@ void ASTReader::FinishedDeserializing() { --NumCurrentElementsDeserializing; } -ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context, - const char *isysroot, bool DisableValidation, +ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, + StringRef isysroot, bool DisableValidation, bool DisableStatCache) : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), - Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), - Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation), + Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context), + Consumer(0), ModuleMgr(FileMgr.getFileSystemOptions()), + RelocatablePCH(false), isysroot(isysroot), + DisableValidation(DisableValidation), DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0), - NumSLocEntriesRead(0), TotalNumSLocEntries(0), NextSLocOffset(0), + NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), - NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), - NumCurrentElementsDeserializing(0) + NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), + TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), + NumCXXBaseSpecifiersLoaded(0) { - RelocatablePCH = false; -} - -ASTReader::ASTReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags, const char *isysroot, - bool DisableValidation, bool DisableStatCache) - : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr), - Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0), - isysroot(isysroot), DisableValidation(DisableValidation), - DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0), - NumSLocEntriesRead(0), TotalNumSLocEntries(0), - NextSLocOffset(0), NumStatementsRead(0), TotalNumStatements(0), - NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0), - NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0), - TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0), - TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0), - TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) { - RelocatablePCH = false; + SourceMgr.setExternalSLocEntrySource(this); } ASTReader::~ASTReader() { - for (unsigned i = 0, e = Chain.size(); i != e; ++i) - delete Chain[e - i - 1]; - // Delete all visible decl lookup tables - for (DeclContextOffsetsMap::iterator I = DeclContextOffsets.begin(), - E = DeclContextOffsets.end(); - I != E; ++I) { - for (DeclContextInfos::iterator J = I->second.begin(), F = I->second.end(); - J != F; ++J) { - if (J->NameLookupTableData) - delete static_cast<ASTDeclContextNameLookupTable*>( - J->NameLookupTableData); - } - } for (DeclContextVisibleUpdatesPending::iterator I = PendingVisibleUpdates.begin(), E = PendingVisibleUpdates.end(); @@ -5226,27 +5441,6 @@ ASTReader::~ASTReader() { for (DeclContextVisibleUpdates::iterator J = I->second.begin(), F = I->second.end(); J != F; ++J) - delete static_cast<ASTDeclContextNameLookupTable*>(*J); - } -} - -ASTReader::PerFileData::PerFileData(ASTFileType Ty) - : Type(Ty), SizeInBits(0), LocalNumSLocEntries(0), SLocOffsets(0), - SLocFileOffsets(0), LocalSLocSize(0), - LocalNumIdentifiers(0), IdentifierOffsets(0), IdentifierTableData(0), - IdentifierLookupTable(0), LocalNumMacroDefinitions(0), - MacroDefinitionOffsets(0), - LocalNumHeaderFileInfos(0), HeaderFileInfoTableData(0), - HeaderFileInfoTable(0), - LocalNumSelectors(0), SelectorOffsets(0), - SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0), - DeclOffsets(0), LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0), - LocalNumTypes(0), TypeOffsets(0), StatCache(0), - NumPreallocatedPreprocessingEntities(0), NextInSource(0) -{} - -ASTReader::PerFileData::~PerFileData() { - delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable); - delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable); - delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable); + delete static_cast<ASTDeclContextNameLookupTable*>(J->first); + } } |