diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization')
13 files changed, 4293 insertions, 3287 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp index 782e5c6..445e750 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp @@ -43,6 +43,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::Long: ID = PREDEF_TYPE_LONG_ID; break; case BuiltinType::LongLong: ID = PREDEF_TYPE_LONGLONG_ID; break; case BuiltinType::Int128: ID = PREDEF_TYPE_INT128_ID; break; + case BuiltinType::Half: ID = PREDEF_TYPE_HALF_ID; break; case BuiltinType::Float: ID = PREDEF_TYPE_FLOAT_ID; break; case BuiltinType::Double: ID = PREDEF_TYPE_DOUBLE_ID; break; case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break; diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h index 838df13..367f57f 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H #include "clang/Serialization/ASTBitCodes.h" +#include "clang/AST/ASTContext.h" namespace clang { @@ -31,7 +32,7 @@ enum DeclUpdateKind { TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); template <typename IdxForTypeTy> -TypeID MakeTypeID(QualType T, IdxForTypeTy IdxForType) { +TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) { if (T.isNull()) return PREDEF_TYPE_NULL_ID; @@ -46,6 +47,11 @@ TypeID MakeTypeID(QualType T, IdxForTypeTy IdxForType) { if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); + if (T == Context.AutoDeductTy) + return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); + if (T == Context.AutoRRefDeductTy) + return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); + return IdxForType(T).asTypeID(FastQuals); } 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); + } } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp index 24ab544..6cc3f0a 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp @@ -14,6 +14,7 @@ #include "ASTCommon.h" #include "clang/Serialization/ASTReader.h" +#include "clang/Sema/SemaDiagnostic.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclVisitor.h" @@ -31,7 +32,7 @@ using namespace clang::serialization; namespace clang { class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> { ASTReader &Reader; - ASTReader::PerFileData &F; + Module &F; llvm::BitstreamCursor &Cursor; const DeclID ThisDeclID; typedef ASTReader::RecordData RecordData; @@ -43,23 +44,42 @@ namespace clang { DeclID LexicalDeclContextIDForTemplateParmDecl; uint64_t GetCurrentCursorOffset(); + SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) { return Reader.ReadSourceLocation(F, R, I); } + SourceRange ReadSourceRange(const RecordData &R, unsigned &I) { return Reader.ReadSourceRange(F, R, I); } + TypeSourceInfo *GetTypeSourceInfo(const RecordData &R, unsigned &I) { return Reader.GetTypeSourceInfo(F, R, I); } + + serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) { + return Reader.ReadDeclID(F, R, I); + } + + Decl *ReadDecl(const RecordData &R, unsigned &I) { + return Reader.ReadDecl(F, R, I); + } + + template<typename T> + T *ReadDeclAs(const RecordData &R, unsigned &I) { + return Reader.ReadDeclAs<T>(F, R, I); + } + void ReadQualifierInfo(QualifierInfo &Info, const RecordData &R, unsigned &I) { Reader.ReadQualifierInfo(F, Info, R, I); } + void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name, const RecordData &R, unsigned &I) { Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I); } + void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo, const RecordData &R, unsigned &I) { Reader.ReadDeclarationNameInfo(F, NameInfo, R, I); @@ -72,7 +92,7 @@ namespace clang { CXXRecordDecl *DefinitionDecl, const RecordData &Record, unsigned &Idx); public: - ASTDeclReader(ASTReader &Reader, ASTReader::PerFileData &F, + ASTDeclReader(ASTReader &Reader, Module &F, llvm::BitstreamCursor &Cursor, DeclID thisDeclID, const RecordData &Record, unsigned &Idx) : Reader(Reader), F(F), Cursor(Cursor), ThisDeclID(thisDeclID), @@ -82,9 +102,14 @@ namespace clang { void Visit(Decl *D); - void UpdateDecl(Decl *D, ASTReader::PerFileData &Module, + void UpdateDecl(Decl *D, Module &Module, const RecordData &Record); + static void setNextObjCCategory(ObjCCategoryDecl *Cat, + ObjCCategoryDecl *Next) { + Cat->NextClassCategory = Next; + } + void VisitDecl(Decl *D); void VisitTranslationUnitDecl(TranslationUnitDecl *TU); void VisitNamedDecl(NamedDecl *ND); @@ -104,6 +129,8 @@ namespace clang { ClassTemplateSpecializationDecl *D); void VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); + void VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *D); void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); void VisitValueDecl(ValueDecl *VD); void VisitEnumConstantDecl(EnumConstantDecl *ECD); @@ -159,16 +186,7 @@ namespace clang { } uint64_t ASTDeclReader::GetCurrentCursorOffset() { - uint64_t Off = 0; - for (unsigned I = 0, N = Reader.Chain.size(); I != N; ++I) { - ASTReader::PerFileData &F = *Reader.Chain[N - I - 1]; - if (&Cursor == &F.DeclsCursor) { - Off += F.DeclsCursor.GetCurrentBitNo(); - break; - } - Off += F.SizeInBits; - } - return Off; + return F.DeclsCursor.GetCurrentBitNo() + F.GlobalBitOffset; } void ASTDeclReader::Visit(Decl *D) { @@ -211,13 +229,12 @@ void ASTDeclReader::VisitDecl(Decl *D) { // parameter immediately, because the template parameter might be // used in the formulation of its DeclContext. Use the translation // unit DeclContext as a placeholder. - DeclContextIDForTemplateParmDecl = Record[Idx++]; - LexicalDeclContextIDForTemplateParmDecl = Record[Idx++]; - D->setDeclContext(Reader.getContext()->getTranslationUnitDecl()); + DeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx); + LexicalDeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx); + D->setDeclContext(Reader.getContext().getTranslationUnitDecl()); } else { - D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); - D->setLexicalDeclContext( - cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); + D->setDeclContext(ReadDeclAs<DeclContext>(Record, Idx)); + D->setLexicalDeclContext(ReadDeclAs<DeclContext>(Record, Idx)); } D->setLocation(ReadSourceLocation(Record, Idx)); D->setInvalidDecl(Record[Idx++]); @@ -230,25 +247,24 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->setUsed(Record[Idx++]); D->setReferenced(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); - D->setPCHLevel(Record[Idx++] + (F.Type <= ASTReader::PCH)); + D->FromASTFile = true; + D->ModulePrivate = Record[Idx++]; } void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { - VisitDecl(TU); - TU->setAnonymousNamespace( - cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++]))); + llvm_unreachable("Translation units are not serialized"); } void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) { VisitDecl(ND); - ND->setDeclName(Reader.ReadDeclarationName(Record, Idx)); + ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx)); } void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { VisitNamedDecl(TD); TD->setLocStart(ReadSourceLocation(Record, Idx)); // Delay type reading until after we have fully initialized the decl. - TypeIDForTypeDecl = Record[Idx++]; + TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); } void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { @@ -266,16 +282,16 @@ void ASTDeclReader::VisitTagDecl(TagDecl *TD) { VisitRedeclarable(TD); TD->IdentifierNamespace = Record[Idx++]; TD->setTagKind((TagDecl::TagKind)Record[Idx++]); - TD->setDefinition(Record[Idx++]); + TD->setCompleteDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); + TD->setFreeStanding(Record[Idx++]); TD->setRBraceLoc(ReadSourceLocation(Record, Idx)); if (Record[Idx++]) { // hasExtInfo - TagDecl::ExtInfo *Info = new (*Reader.getContext()) TagDecl::ExtInfo(); + TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); TD->TypedefNameDeclOrQualifier = Info; } else - TD->setTypedefNameForAnonDecl( - cast_or_null<TypedefNameDecl>(Reader.GetDecl(Record[Idx++]))); + TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx)); } void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -283,15 +299,14 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { if (TypeSourceInfo *TI = Reader.GetTypeSourceInfo(F, Record, Idx)) ED->setIntegerTypeSourceInfo(TI); else - ED->setIntegerType(Reader.GetType(Record[Idx++])); - ED->setPromotionType(Reader.GetType(Record[Idx++])); + ED->setIntegerType(Reader.readType(F, Record, Idx)); + ED->setPromotionType(Reader.readType(F, Record, Idx)); ED->setNumPositiveBits(Record[Idx++]); ED->setNumNegativeBits(Record[Idx++]); ED->IsScoped = Record[Idx++]; ED->IsScopedUsingClassTag = Record[Idx++]; ED->IsFixed = Record[Idx++]; - ED->setInstantiationOfMemberEnum( - cast_or_null<EnumDecl>(Reader.GetDecl(Record[Idx++]))); + ED->setInstantiationOfMemberEnum(ReadDeclAs<EnumDecl>(Record, Idx)); } void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { @@ -303,7 +318,7 @@ void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); - VD->setType(Reader.GetType(Record[Idx++])); + VD->setType(Reader.readType(F, Record, Idx)); } void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { @@ -318,7 +333,7 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { DD->setInnerLocStart(ReadSourceLocation(Record, Idx)); if (Record[Idx++]) { // hasExtInfo DeclaratorDecl::ExtInfo *Info - = new (*Reader.getContext()) DeclaratorDecl::ExtInfo(); + = new (Reader.getContext()) DeclaratorDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); DD->DeclInfo = Info; } @@ -331,35 +346,35 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx); FD->IdentifierNamespace = Record[Idx++]; switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { - default: assert(false && "Unhandled TemplatedKind!"); - break; + default: llvm_unreachable("Unhandled TemplatedKind!"); case FunctionDecl::TK_NonTemplate: break; case FunctionDecl::TK_FunctionTemplate: - FD->setDescribedFunctionTemplate( - cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]))); + FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record, + Idx)); break; case FunctionDecl::TK_MemberSpecialization: { - FunctionDecl *InstFD = cast<FunctionDecl>(Reader.GetDecl(Record[Idx++])); + FunctionDecl *InstFD = ReadDeclAs<FunctionDecl>(Record, Idx); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = ReadSourceLocation(Record, Idx); - FD->setInstantiationOfMemberFunction(*Reader.getContext(), InstFD, TSK); + FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); break; } case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateDecl *Template - = cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++])); + FunctionTemplateDecl *Template = ReadDeclAs<FunctionTemplateDecl>(Record, + Idx); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; // Template arguments. - llvm::SmallVector<TemplateArgument, 8> TemplArgs; + SmallVector<TemplateArgument, 8> TemplArgs; Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); // Template args as written. - llvm::SmallVector<TemplateArgumentLoc, 8> TemplArgLocs; + SmallVector<TemplateArgumentLoc, 8> TemplArgLocs; SourceLocation LAngleLoc, RAngleLoc; - if (Record[Idx++]) { // TemplateArgumentsAsWritten != 0 + bool HasTemplateArgumentsAsWritten = Record[Idx++]; + if (HasTemplateArgumentsAsWritten) { unsigned NumTemplateArgLocs = Record[Idx++]; TemplArgLocs.reserve(NumTemplateArgLocs); for (unsigned i=0; i != NumTemplateArgLocs; ++i) @@ -372,24 +387,24 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { SourceLocation POI = ReadSourceLocation(Record, Idx); - ASTContext &C = *Reader.getContext(); + ASTContext &C = Reader.getContext(); TemplateArgumentList *TemplArgList = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size()); - TemplateArgumentListInfo *TemplArgsInfo - = new (C) TemplateArgumentListInfo(LAngleLoc, RAngleLoc); + TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); for (unsigned i=0, e = TemplArgLocs.size(); i != e; ++i) - TemplArgsInfo->addArgument(TemplArgLocs[i]); + TemplArgsInfo.addArgument(TemplArgLocs[i]); FunctionTemplateSpecializationInfo *FTInfo = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK, TemplArgList, - TemplArgsInfo, POI); + HasTemplateArgumentsAsWritten ? &TemplArgsInfo : 0, + POI); FD->TemplateOrSpecialization = FTInfo; if (FD->isCanonicalDecl()) { // if canonical add to template's set. // The template that contains the specializations set. It's not safe to // use getCanonicalDecl on Template since it may still be initializing. FunctionTemplateDecl *CanonTemplate - = cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++])); + = ReadDeclAs<FunctionTemplateDecl>(Record, Idx); // Get the InsertPos by FindNodeOrInsertPos() instead of calling // InsertNode(FTInfo) directly to avoid the getASTContext() call in // FunctionTemplateSpecializationInfo's Profile(). @@ -410,7 +425,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { UnresolvedSet<8> TemplDecls; unsigned NumTemplates = Record[Idx++]; while (NumTemplates--) - TemplDecls.addDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); + TemplDecls.addDecl(ReadDeclAs<NamedDecl>(Record, Idx)); // Templates args. TemplateArgumentListInfo TemplArgs; @@ -420,7 +435,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { TemplArgs.setLAngleLoc(ReadSourceLocation(Record, Idx)); TemplArgs.setRAngleLoc(ReadSourceLocation(Record, Idx)); - FD->setDependentTemplateSpecialization(*Reader.getContext(), + FD->setDependentTemplateSpecialization(Reader.getContext(), TemplDecls, TemplArgs); break; } @@ -442,15 +457,16 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->IsDefaulted = Record[Idx++]; FD->IsExplicitlyDefaulted = Record[Idx++]; FD->HasImplicitReturnZero = Record[Idx++]; + FD->IsConstexpr = Record[Idx++]; FD->EndRangeLoc = ReadSourceLocation(Record, Idx); // Read in the parameters. unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; + SmallVector<ParmVarDecl *, 16> Params; Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - FD->setParams(*Reader.getContext(), Params.data(), NumParams); + Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx)); + FD->setParams(Reader.getContext(), Params); } void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { @@ -459,77 +475,87 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { // In practice, this won't be executed (since method definitions // don't occur in header files). MD->setBody(Reader.ReadStmt(F)); - MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++]))); - MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++]))); + MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>(Record, Idx)); + MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>(Record, Idx)); } MD->setInstanceMethod(Record[Idx++]); MD->setVariadic(Record[Idx++]); MD->setSynthesized(Record[Idx++]); MD->setDefined(Record[Idx++]); + + MD->IsRedeclaration = Record[Idx++]; + MD->HasRedeclaration = Record[Idx++]; + if (MD->HasRedeclaration) + Reader.getContext().setObjCMethodRedeclaration(MD, + ReadDeclAs<ObjCMethodDecl>(Record, Idx)); + MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); MD->SetRelatedResultType(Record[Idx++]); - MD->setNumSelectorArgs(unsigned(Record[Idx++])); - MD->setResultType(Reader.GetType(Record[Idx++])); + MD->setResultType(Reader.readType(F, Record, Idx)); MD->setResultTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); MD->setEndLoc(ReadSourceLocation(Record, Idx)); unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; + SmallVector<ParmVarDecl *, 16> Params; Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams, - NumParams); + Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx)); + + MD->SelLocsKind = Record[Idx++]; + unsigned NumStoredSelLocs = Record[Idx++]; + SmallVector<SourceLocation, 16> SelLocs; + SelLocs.reserve(NumStoredSelLocs); + for (unsigned i = 0; i != NumStoredSelLocs; ++i) + SelLocs.push_back(ReadSourceLocation(Record, Idx)); + + MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs); } void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { VisitNamedDecl(CD); - SourceLocation A = ReadSourceLocation(Record, Idx); - SourceLocation B = ReadSourceLocation(Record, Idx); - CD->setAtEndRange(SourceRange(A, B)); + CD->setAtStartLoc(ReadSourceLocation(Record, Idx)); + CD->setAtEndRange(ReadSourceRange(Record, Idx)); } void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { VisitObjCContainerDecl(ID); - ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtrOrNull()); - ID->setSuperClass(cast_or_null<ObjCInterfaceDecl> - (Reader.GetDecl(Record[Idx++]))); + ID->setTypeForDecl(Reader.readType(F, Record, Idx).getTypePtrOrNull()); + ID->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); // Read the directly referenced protocols and their SourceLocations. unsigned NumProtocols = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols; + SmallVector<ObjCProtocolDecl *, 16> Protocols; Protocols.reserve(NumProtocols); for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; ProtoLocs.reserve(NumProtocols); for (unsigned I = 0; I != NumProtocols; ++I) ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), - *Reader.getContext()); + Reader.getContext()); // Read the transitive closure of protocols referenced by this class. NumProtocols = Record[Idx++]; Protocols.clear(); Protocols.reserve(NumProtocols); for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); ID->AllReferencedProtocols.set(Protocols.data(), NumProtocols, - *Reader.getContext()); + Reader.getContext()); // Read the ivars. unsigned NumIvars = Record[Idx++]; - llvm::SmallVector<ObjCIvarDecl *, 16> IVars; + SmallVector<ObjCIvarDecl *, 16> IVars; IVars.reserve(NumIvars); for (unsigned I = 0; I != NumIvars; ++I) - IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); - ID->setCategoryList( - cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); + IVars.push_back(ReadDeclAs<ObjCIvarDecl>(Record, Idx)); + ID->setCategoryList(ReadDeclAs<ObjCCategoryDecl>(Record, Idx)); + // We will rebuild this list lazily. ID->setIvarList(0); ID->setForwardDecl(Record[Idx++]); ID->setImplicitInterfaceDecl(Record[Idx++]); - ID->setClassLoc(ReadSourceLocation(Record, Idx)); ID->setSuperClassLoc(ReadSourceLocation(Record, Idx)); ID->setLocEnd(ReadSourceLocation(Record, Idx)); } @@ -548,16 +574,16 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { PD->setForwardDecl(Record[Idx++]); PD->setLocEnd(ReadSourceLocation(Record, Idx)); unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; + SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; ProtoRefs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; + ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; ProtoLocs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); + Reader.getContext()); } void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { @@ -566,57 +592,48 @@ void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { void ASTDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) { VisitDecl(CD); - unsigned NumClassRefs = Record[Idx++]; - llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs; - ClassRefs.reserve(NumClassRefs); - for (unsigned I = 0; I != NumClassRefs; ++I) - ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> SLocs; - SLocs.reserve(NumClassRefs); - for (unsigned I = 0; I != NumClassRefs; ++I) - SLocs.push_back(ReadSourceLocation(Record, Idx)); - CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(), - NumClassRefs); + ObjCInterfaceDecl *ClassRef = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); + SourceLocation SLoc = ReadSourceLocation(Record, Idx); + CD->setClass(Reader.getContext(), ClassRef, SLoc); } void ASTDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) { VisitDecl(FPD); unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; + SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; ProtoRefs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; + ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; ProtoLocs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); + Reader.getContext()); } void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { VisitObjCContainerDecl(CD); - CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); + CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; + SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; ProtoRefs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; + ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; ProtoLocs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); - CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); + Reader.getContext()); + CD->NextClassCategory = ReadDeclAs<ObjCCategoryDecl>(Record, Idx); CD->setHasSynthBitfield(Record[Idx++]); - CD->setAtLoc(ReadSourceLocation(Record, Idx)); CD->setCategoryNameLoc(ReadSourceLocation(Record, Idx)); } void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { VisitNamedDecl(CAD); - CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); + CAD->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); } void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { @@ -631,31 +648,26 @@ void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // FIXME: stable encoding D->setPropertyImplementation( (ObjCPropertyDecl::PropertyControl)Record[Idx++]); - D->setGetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector()); - D->setSetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector()); - D->setGetterMethodDecl( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - D->setSetterMethodDecl( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - D->setPropertyIvarDecl( - cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); + D->setGetterName(Reader.ReadDeclarationName(F,Record, Idx).getObjCSelector()); + D->setSetterName(Reader.ReadDeclarationName(F,Record, Idx).getObjCSelector()); + D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx)); + D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx)); + D->setPropertyIvarDecl(ReadDeclAs<ObjCIvarDecl>(Record, Idx)); } void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { VisitObjCContainerDecl(D); - D->setClassInterface( - cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); + D->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); } void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { VisitObjCImplDecl(D); - D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx)); + D->setIdentifier(Reader.GetIdentifierInfo(F, Record, Idx)); } void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); - D->setSuperClass( - cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); + D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); llvm::tie(D->IvarInitializers, D->NumIvarInitializers) = Reader.ReadCXXCtorInitializers(F, Record, Idx); D->setHasSynthBitfield(Record[Idx++]); @@ -665,10 +677,8 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { VisitDecl(D); D->setAtLoc(ReadSourceLocation(Record, Idx)); - D->setPropertyDecl( - cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++]))); - D->PropertyIvarDecl = - cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])); + D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>(Record, Idx)); + D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>(Record, Idx); D->IvarLoc = ReadSourceLocation(Record, Idx); D->setGetterCXXConstructor(Reader.ReadExpr(F)); D->setSetterCXXAssignment(Reader.ReadExpr(F)); @@ -683,9 +693,8 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { else if (BitWidthOrInitializer == 2) FD->setInClassInitializer(Reader.ReadExpr(F)); if (!FD->getDeclName()) { - FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])); - if (Tmpl) - Reader.getContext()->setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); + if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx)) + Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); } } @@ -694,10 +703,10 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { FD->ChainingSize = Record[Idx++]; assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2"); - FD->Chaining = new (*Reader.getContext())NamedDecl*[FD->ChainingSize]; + FD->Chaining = new (Reader.getContext())NamedDecl*[FD->ChainingSize]; for (unsigned I = 0; I != FD->ChainingSize; ++I) - FD->Chaining[I] = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); + FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx); } void ASTDeclReader::VisitVarDecl(VarDecl *VD) { @@ -715,10 +724,10 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) { VD->setInit(Reader.ReadExpr(F)); if (Record[Idx++]) { // HasMemberSpecializationInfo. - VarDecl *Tmpl = cast<VarDecl>(Reader.GetDecl(Record[Idx++])); + VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = ReadSourceLocation(Record, Idx); - Reader.getContext()->setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); + Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); } } @@ -756,18 +765,18 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(F))); BD->setSignatureAsWritten(GetTypeSourceInfo(Record, Idx)); unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; + SmallVector<ParmVarDecl *, 16> Params; Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - BD->setParams(Params.data(), NumParams); + Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx)); + BD->setParams(Params); bool capturesCXXThis = Record[Idx++]; unsigned numCaptures = Record[Idx++]; - llvm::SmallVector<BlockDecl::Capture, 16> captures; + SmallVector<BlockDecl::Capture, 16> captures; captures.reserve(numCaptures); for (unsigned i = 0; i != numCaptures; ++i) { - VarDecl *decl = cast<VarDecl>(Reader.GetDecl(Record[Idx++])); + VarDecl *decl = ReadDeclAs<VarDecl>(Record, Idx); unsigned flags = Record[Idx++]; bool byRef = (flags & 1); bool nested = (flags & 2); @@ -775,7 +784,7 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr)); } - BD->setCaptures(*Reader.getContext(), captures.begin(), + BD->setCaptures(Reader.getContext(), captures.begin(), captures.end(), capturesCXXThis); } @@ -800,9 +809,10 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { D->NextNamespace = Record[Idx++]; bool IsOriginal = Record[Idx++]; + // FIXME: Modules will likely have trouble with pointing directly at + // the original namespace. D->OrigOrAnonNamespace.setInt(IsOriginal); - D->OrigOrAnonNamespace.setPointer( - cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++]))); + D->OrigOrAnonNamespace.setPointer(ReadDeclAs<NamespaceDecl>(Record, Idx)); } void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { @@ -810,7 +820,7 @@ void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { D->NamespaceLoc = ReadSourceLocation(Record, Idx); D->IdentLoc = ReadSourceLocation(Record, Idx); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); - D->Namespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); + D->Namespace = ReadDeclAs<NamedDecl>(Record, Idx); } void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { @@ -818,21 +828,19 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { D->setUsingLocation(ReadSourceLocation(Record, Idx)); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); - D->FirstUsingShadow = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])); + D->FirstUsingShadow = ReadDeclAs<UsingShadowDecl>(Record, Idx); D->setTypeName(Record[Idx++]); - NamedDecl *Pattern = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); - if (Pattern) - Reader.getContext()->setInstantiatedFromUsingDecl(D, Pattern); + if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx)) + Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern); } void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { VisitNamedDecl(D); - D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - D->UsingOrNextShadow = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); - UsingShadowDecl *Pattern - = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])); + D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx)); + D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx); + UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx); if (Pattern) - Reader.getContext()->setInstantiatedFromUsingShadowDecl(D, Pattern); + Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern); } void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { @@ -840,8 +848,8 @@ void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { D->UsingLoc = ReadSourceLocation(Record, Idx); D->NamespaceLoc = ReadSourceLocation(Record, Idx); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); - D->NominatedNamespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); - D->CommonAncestor = cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])); + D->NominatedNamespace = ReadDeclAs<NamedDecl>(Record, Idx); + D->CommonAncestor = ReadDeclAs<DeclContext>(Record, Idx); } void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { @@ -863,7 +871,9 @@ void ASTDeclReader::ReadCXXDefinitionData( const RecordData &Record, unsigned &Idx) { Data.UserDeclaredConstructor = Record[Idx++]; Data.UserDeclaredCopyConstructor = Record[Idx++]; + Data.UserDeclaredMoveConstructor = Record[Idx++]; Data.UserDeclaredCopyAssignment = Record[Idx++]; + Data.UserDeclaredMoveAssignment = Record[Idx++]; Data.UserDeclaredDestructor = Record[Idx++]; Data.Aggregate = Record[Idx++]; Data.PlainOldData = Record[Idx++]; @@ -877,7 +887,7 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.HasPublicFields = Record[Idx++]; Data.HasMutableFields = Record[Idx++]; Data.HasTrivialDefaultConstructor = Record[Idx++]; - Data.HasConstExprNonCopyMoveConstructor = Record[Idx++]; + Data.HasConstexprNonCopyMoveConstructor = Record[Idx++]; Data.HasTrivialCopyConstructor = Record[Idx++]; Data.HasTrivialMoveConstructor = Record[Idx++]; Data.HasTrivialCopyAssignment = Record[Idx++]; @@ -888,28 +898,31 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.UserProvidedDefaultConstructor = Record[Idx++]; Data.DeclaredDefaultConstructor = Record[Idx++]; Data.DeclaredCopyConstructor = Record[Idx++]; + Data.DeclaredMoveConstructor = Record[Idx++]; Data.DeclaredCopyAssignment = Record[Idx++]; + Data.DeclaredMoveAssignment = Record[Idx++]; Data.DeclaredDestructor = Record[Idx++]; + Data.FailedImplicitMoveConstructor = Record[Idx++]; + Data.FailedImplicitMoveAssignment = Record[Idx++]; Data.NumBases = Record[Idx++]; if (Data.NumBases) - Data.Bases = Reader.GetCXXBaseSpecifiersOffset(Record[Idx++]); + Data.Bases = Reader.readCXXBaseSpecifiers(F, Record, Idx); Data.NumVBases = Record[Idx++]; if (Data.NumVBases) - Data.VBases = Reader.GetCXXBaseSpecifiersOffset(Record[Idx++]); + Data.VBases = Reader.readCXXBaseSpecifiers(F, Record, Idx); - Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx); - Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx); + Reader.ReadUnresolvedSet(F, Data.Conversions, Record, Idx); + Reader.ReadUnresolvedSet(F, Data.VisibleConversions, Record, Idx); assert(Data.Definition && "Data.Definition should be already set!"); - Data.FirstFriend - = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++])); + Data.FirstFriend = ReadDeclAs<FriendDecl>(Record, Idx); } void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D, CXXRecordDecl *DefinitionDecl, const RecordData &Record, unsigned &Idx) { - ASTContext &C = *Reader.getContext(); + ASTContext &C = Reader.getContext(); if (D == DefinitionDecl) { D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); @@ -942,26 +955,24 @@ void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D, void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { VisitRecordDecl(D); - CXXRecordDecl *DefinitionDecl - = cast_or_null<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])); + CXXRecordDecl *DefinitionDecl = ReadDeclAs<CXXRecordDecl>(Record, Idx); InitializeCXXDefinitionData(D, DefinitionDecl, Record, Idx); - ASTContext &C = *Reader.getContext(); + ASTContext &C = Reader.getContext(); enum CXXRecKind { CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization }; switch ((CXXRecKind)Record[Idx++]) { default: - assert(false && "Out of sync with ASTDeclWriter::VisitCXXRecordDecl?"); + llvm_unreachable("Out of sync with ASTDeclWriter::VisitCXXRecordDecl?"); case CXXRecNotTemplate: break; case CXXRecTemplate: - D->TemplateOrInstantiation - = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])); + D->TemplateOrInstantiation = ReadDeclAs<ClassTemplateDecl>(Record, Idx); break; case CXXRecMemberSpecialization: { - CXXRecordDecl *RD = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])); + CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(Record, Idx); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = ReadSourceLocation(Record, Idx); MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK); @@ -973,10 +984,8 @@ void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { // Load the key function to avoid deserializing every method so we can // compute it. - if (D->IsDefinition) { - CXXMethodDecl *Key - = cast_or_null<CXXMethodDecl>(Reader.GetDecl(Record[Idx++])); - if (Key) + if (D->IsCompleteDefinition) { + if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx)) C.KeyFunctions[D] = Key; } } @@ -985,10 +994,10 @@ void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { VisitFunctionDecl(D); unsigned NumOverridenMethods = Record[Idx++]; while (NumOverridenMethods--) { - CXXMethodDecl *MD = cast<CXXMethodDecl>(Reader.GetDecl(Record[Idx++])); // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod, // MD may be initializing. - Reader.getContext()->addOverriddenMethod(D, MD); + if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx)) + Reader.getContext().addOverriddenMethod(D, MD); } } @@ -1005,7 +1014,7 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { VisitCXXMethodDecl(D); D->ImplicitlyDefined = Record[Idx++]; - D->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])); + D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx); } void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { @@ -1023,7 +1032,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { if (Record[Idx++]) D->Friend = GetTypeSourceInfo(Record, Idx); else - D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); + D->Friend = ReadDeclAs<NamedDecl>(Record, Idx); D->NextFriend = Record[Idx++]; D->UnsupportedFriend = (Record[Idx++] != 0); D->FriendLoc = ReadSourceLocation(Record, Idx); @@ -1037,7 +1046,7 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { for (unsigned i = 0; i != NumParams; ++i) D->Params[i] = Reader.ReadTemplateParameterList(F, Record, Idx); if (Record[Idx++]) // HasFriendDecl - D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); + D->Friend = ReadDeclAs<NamedDecl>(Record, Idx); else D->Friend = GetTypeSourceInfo(Record, Idx); D->FriendLoc = ReadSourceLocation(Record, Idx); @@ -1046,8 +1055,7 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { VisitNamedDecl(D); - NamedDecl *TemplatedDecl - = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); + NamedDecl *TemplatedDecl = ReadDeclAs<NamedDecl>(Record, Idx); TemplateParameterList* TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); D->init(TemplatedDecl, TemplateParams); @@ -1058,8 +1066,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { // can be used while this is still initializing. assert(D->CommonOrPrev.isNull() && "getCommonPtr was called earlier on this"); - DeclID PreviousDeclID = Record[Idx++]; - DeclID FirstDeclID = PreviousDeclID ? Record[Idx++] : 0; + DeclID PreviousDeclID = ReadDeclID(Record, Idx); + DeclID FirstDeclID = PreviousDeclID ? ReadDeclID(Record, Idx) : 0; // We delay loading of the redeclaration chain to avoid deeply nested calls. // We temporarily set the first (canonical) declaration as the previous one // which is the one that matters and mark the real previous DeclID to be @@ -1074,9 +1082,9 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { if (PreviousDeclID != FirstDeclID) Reader.PendingPreviousDecls.push_back(std::make_pair(D, PreviousDeclID)); } else { - D->CommonOrPrev = D->newCommon(*Reader.getContext()); + D->CommonOrPrev = D->newCommon(Reader.getContext()); if (RedeclarableTemplateDecl *RTD - = cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]))) { + = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) { assert(RTD->getKind() == D->getKind() && "InstantiatedFromMemberTemplate kind mismatch"); D->setInstantiatedFromMemberTemplateImpl(RTD); @@ -1084,8 +1092,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { D->setMemberSpecialization(); } - RedeclarableTemplateDecl *LatestDecl = - cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++])); + RedeclarableTemplateDecl *LatestDecl + = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx); // This decl is a first one and the latest declaration that it points to is // in the same AST file. However, if this actually needs to point to a @@ -1095,14 +1103,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { ASTReader::FirstLatestDeclIDMap::iterator I = Reader.FirstLatestDeclIDs.find(ThisDeclID); if (I != Reader.FirstLatestDeclIDs.end()) { - Decl *NewLatest = Reader.GetDecl(I->second); - assert((LatestDecl->getLocation().isInvalid() || - NewLatest->getLocation().isInvalid() || - !Reader.SourceMgr.isBeforeInTranslationUnit( - NewLatest->getLocation(), - LatestDecl->getLocation())) && - "The new latest is supposed to come after the previous latest"); - LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest); + if (Decl *NewLatest = Reader.GetDecl(I->second)) + LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest); } assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch"); @@ -1119,27 +1121,27 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (D->getPreviousDeclaration() == 0) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - llvm::SmallVector<serialization::DeclID, 2> SpecIDs; + SmallVector<serialization::DeclID, 2> SpecIDs; SpecIDs.push_back(0); // Specializations. unsigned Size = Record[Idx++]; SpecIDs[0] += Size; - SpecIDs.append(Record.begin() + Idx, Record.begin() + Idx + Size); - Idx += Size; + for (unsigned I = 0; I != Size; ++I) + SpecIDs.push_back(ReadDeclID(Record, Idx)); // Partial specializations. Size = Record[Idx++]; SpecIDs[0] += Size; - SpecIDs.append(Record.begin() + Idx, Record.begin() + Idx + Size); - Idx += Size; + for (unsigned I = 0; I != Size; ++I) + SpecIDs.push_back(ReadDeclID(Record, Idx)); if (SpecIDs[0]) { typedef serialization::DeclID DeclID; ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr(); CommonPtr->LazySpecializations - = new (*Reader.getContext()) DeclID [SpecIDs.size()]; + = new (Reader.getContext()) DeclID [SpecIDs.size()]; memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), SpecIDs.size() * sizeof(DeclID)); } @@ -1152,12 +1154,12 @@ void ASTDeclReader::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { VisitCXXRecordDecl(D); - ASTContext &C = *Reader.getContext(); - if (Decl *InstD = Reader.GetDecl(Record[Idx++])) { + ASTContext &C = Reader.getContext(); + if (Decl *InstD = ReadDecl(Record, Idx)) { if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) { D->SpecializedTemplate = CTD; } else { - llvm::SmallVector<TemplateArgument, 8> TemplArgs; + SmallVector<TemplateArgument, 8> TemplArgs; Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), @@ -1182,7 +1184,7 @@ void ASTDeclReader::VisitClassTemplateSpecializationDecl( D->ExplicitInfo = ExplicitInfo; } - llvm::SmallVector<TemplateArgument, 8> TemplArgs; + SmallVector<TemplateArgument, 8> TemplArgs; Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size()); @@ -1190,8 +1192,7 @@ void ASTDeclReader::VisitClassTemplateSpecializationDecl( D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++]; if (D->isCanonicalDecl()) { // It's kept in the folding set. - ClassTemplateDecl *CanonPattern - = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])); + ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(Record,Idx); if (ClassTemplatePartialSpecializationDecl *Partial = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { CanonPattern->getCommonPtr()->PartialSpecializations.InsertNode(Partial); @@ -1205,7 +1206,7 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { VisitClassTemplateSpecializationDecl(D); - ASTContext &C = *Reader.getContext(); + ASTContext &C = Reader.getContext(); D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); unsigned NumArgs = Record[Idx++]; @@ -1221,12 +1222,17 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( // These are read/set from/to the first declaration. if (D->getPreviousDeclaration() == 0) { D->InstantiatedFromMember.setPointer( - cast_or_null<ClassTemplatePartialSpecializationDecl>( - Reader.GetDecl(Record[Idx++]))); + ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx)); D->InstantiatedFromMember.setInt(Record[Idx++]); } } +void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *D) { + VisitDecl(D); + D->Specialization = ReadDeclAs<CXXMethodDecl>(Record, Idx); +} + void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); @@ -1238,7 +1244,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // when reading the specialized FunctionDecl. unsigned NumSpecs = Record[Idx++]; while (NumSpecs--) - Reader.GetDecl(Record[Idx++]); + (void)ReadDecl(Record, Idx); } } @@ -1260,7 +1266,7 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { if (D->isExpandedParameterPack()) { void **Data = reinterpret_cast<void **>(D + 1); for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { - Data[2*I] = Reader.GetType(Record[Idx++]).getAsOpaquePtr(); + Data[2*I] = Reader.readType(F, Record, Idx).getAsOpaquePtr(); Data[2*I + 1] = GetTypeSourceInfo(Record, Idx); } } else { @@ -1310,13 +1316,13 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { RedeclKind Kind = (RedeclKind)Record[Idx++]; switch (Kind) { default: - assert(0 && "Out of sync with ASTDeclWriter::VisitRedeclarable or messed up" - " reading"); + llvm_unreachable("Out of sync with ASTDeclWriter::VisitRedeclarable or" + " messed up reading"); case NoRedeclaration: break; case PointsToPrevious: { - DeclID PreviousDeclID = Record[Idx++]; - DeclID FirstDeclID = Record[Idx++]; + DeclID PreviousDeclID = ReadDeclID(Record, Idx); + DeclID FirstDeclID = ReadDeclID(Record, Idx); // We delay loading of the redeclaration chain to avoid deeply nested calls. // We temporarily set the first (canonical) declaration as the previous one // which is the one that matters and mark the real previous DeclID to be @@ -1330,7 +1336,7 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { } case PointsToLatest: D->RedeclLink = typename Redeclarable<T>::LatestDeclLink( - cast_or_null<T>(Reader.GetDecl(Record[Idx++]))); + ReadDeclAs<T>(Record, Idx)); break; } @@ -1361,12 +1367,12 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { //===----------------------------------------------------------------------===// /// \brief Reads attributes from the current stream position. -void ASTReader::ReadAttributes(PerFileData &F, AttrVec &Attrs, +void ASTReader::ReadAttributes(Module &F, AttrVec &Attrs, const RecordData &Record, unsigned &Idx) { for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) { Attr *New = 0; attr::Kind Kind = (attr::Kind)Record[Idx++]; - SourceLocation Loc = ReadSourceLocation(F, Record, Idx); + SourceRange Range = ReadSourceRange(F, Record, Idx); #include "clang/Serialization/AttrPCHRead.inc" @@ -1398,33 +1404,47 @@ inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) { /// code generation, e.g., inline function definitions, Objective-C /// declarations with metadata, etc. static bool isConsumerInterestedIn(Decl *D) { - if (isa<FileScopeAsmDecl>(D)) + // An ObjCMethodDecl is never considered as "interesting" because its + // implementation container always is. + + if (isa<FileScopeAsmDecl>(D) || + isa<ObjCProtocolDecl>(D) || + isa<ObjCImplDecl>(D)) return true; if (VarDecl *Var = dyn_cast<VarDecl>(D)) return Var->isFileVarDecl() && Var->isThisDeclarationADefinition() == VarDecl::Definition; if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) return Func->doesThisDeclarationHaveABody(); - return isa<ObjCProtocolDecl>(D) || isa<ObjCImplementationDecl>(D); + + return false; } -/// \brief Get the correct cursor and offset for loading a type. +/// \brief Get the correct cursor and offset for loading a declaration. ASTReader::RecordLocation -ASTReader::DeclCursorForIndex(unsigned Index, DeclID ID) { +ASTReader::DeclCursorForID(DeclID ID) { // See if there's an override. DeclReplacementMap::iterator It = ReplacedDecls.find(ID); if (It != ReplacedDecls.end()) return RecordLocation(It->second.first, It->second.second); - PerFileData *F = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - F = Chain[N - I - 1]; - if (Index < F->LocalNumDecls) - break; - Index -= F->LocalNumDecls; - } - assert(F && F->LocalNumDecls > Index && "Broken chain"); - return RecordLocation(F, F->DeclOffsets[Index]); + GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); + assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); + Module *M = I->second; + return RecordLocation(M, + M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS]); +} + +ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) { + ContinuousRangeMap<uint64_t, Module*, 4>::iterator I + = GlobalBitOffsetsMap.find(GlobalOffset); + + assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map"); + return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset); +} + +uint64_t ASTReader::getGlobalBitOffset(Module &M, uint32_t LocalOffset) { + return LocalOffset + M.GlobalBitOffset; } void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { @@ -1447,8 +1467,9 @@ void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) { } /// \brief Read the declaration at the given offset from the AST file. -Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { - RecordLocation Loc = DeclCursorForIndex(Index, ID); +Decl *ASTReader::ReadDeclRecord(DeclID ID) { + unsigned Index = ID - NUM_PREDEF_DECL_IDS; + RecordLocation Loc = DeclCursorForID(ID); llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; // Keep track of where we are in the stream, then jump back there // after reading this declaration. @@ -1469,215 +1490,216 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { switch ((DeclCode)DeclsCursor.ReadRecord(Code, Record)) { case DECL_CONTEXT_LEXICAL: case DECL_CONTEXT_VISIBLE: - assert(false && "Record cannot be de-serialized with ReadDeclRecord"); - break; - case DECL_TRANSLATION_UNIT: - assert(Index == 0 && "Translation unit must be at index 0"); - D = Context->getTranslationUnitDecl(); - break; + llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord"); case DECL_TYPEDEF: - D = TypedefDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + D = TypedefDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, 0); break; case DECL_TYPEALIAS: - D = TypeAliasDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + D = TypeAliasDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, 0); break; case DECL_ENUM: - D = EnumDecl::Create(*Context, Decl::EmptyShell()); + D = EnumDecl::Create(Context, Decl::EmptyShell()); break; case DECL_RECORD: - D = RecordDecl::Create(*Context, Decl::EmptyShell()); + D = RecordDecl::Create(Context, Decl::EmptyShell()); break; case DECL_ENUM_CONSTANT: - D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), + D = EnumConstantDecl::Create(Context, 0, SourceLocation(), 0, QualType(), 0, llvm::APSInt()); break; case DECL_FUNCTION: - D = FunctionDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + D = FunctionDecl::Create(Context, 0, SourceLocation(), SourceLocation(), DeclarationName(), QualType(), 0); break; case DECL_LINKAGE_SPEC: - D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + D = LinkageSpecDecl::Create(Context, 0, SourceLocation(), SourceLocation(), (LinkageSpecDecl::LanguageIDs)0, SourceLocation()); break; case DECL_LABEL: - D = LabelDecl::Create(*Context, 0, SourceLocation(), 0); + D = LabelDecl::Create(Context, 0, SourceLocation(), 0); break; case DECL_NAMESPACE: - D = NamespaceDecl::Create(*Context, 0, SourceLocation(), + D = NamespaceDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0); break; case DECL_NAMESPACE_ALIAS: - D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(), + D = NamespaceAliasDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, NestedNameSpecifierLoc(), SourceLocation(), 0); break; case DECL_USING: - D = UsingDecl::Create(*Context, 0, SourceLocation(), + D = UsingDecl::Create(Context, 0, SourceLocation(), NestedNameSpecifierLoc(), DeclarationNameInfo(), false); break; case DECL_USING_SHADOW: - D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0); + D = UsingShadowDecl::Create(Context, 0, SourceLocation(), 0, 0); break; case DECL_USING_DIRECTIVE: - D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(), + D = UsingDirectiveDecl::Create(Context, 0, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), 0, 0); break; case DECL_UNRESOLVED_USING_VALUE: - D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(), + D = UnresolvedUsingValueDecl::Create(Context, 0, SourceLocation(), NestedNameSpecifierLoc(), DeclarationNameInfo()); break; case DECL_UNRESOLVED_USING_TYPENAME: - D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(), + D = UnresolvedUsingTypenameDecl::Create(Context, 0, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), DeclarationName()); break; case DECL_CXX_RECORD: - D = CXXRecordDecl::Create(*Context, Decl::EmptyShell()); + D = CXXRecordDecl::Create(Context, Decl::EmptyShell()); break; case DECL_CXX_METHOD: - D = CXXMethodDecl::Create(*Context, 0, SourceLocation(), + D = CXXMethodDecl::Create(Context, 0, SourceLocation(), DeclarationNameInfo(), QualType(), 0, - false, SC_None, false, SourceLocation()); + false, SC_None, false, false, SourceLocation()); break; case DECL_CXX_CONSTRUCTOR: - D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell()); + D = CXXConstructorDecl::Create(Context, Decl::EmptyShell()); break; case DECL_CXX_DESTRUCTOR: - D = CXXDestructorDecl::Create(*Context, Decl::EmptyShell()); + D = CXXDestructorDecl::Create(Context, Decl::EmptyShell()); break; case DECL_CXX_CONVERSION: - D = CXXConversionDecl::Create(*Context, Decl::EmptyShell()); + D = CXXConversionDecl::Create(Context, Decl::EmptyShell()); break; case DECL_ACCESS_SPEC: - D = AccessSpecDecl::Create(*Context, Decl::EmptyShell()); + D = AccessSpecDecl::Create(Context, Decl::EmptyShell()); break; case DECL_FRIEND: - D = FriendDecl::Create(*Context, Decl::EmptyShell()); + D = FriendDecl::Create(Context, Decl::EmptyShell()); break; case DECL_FRIEND_TEMPLATE: - D = FriendTemplateDecl::Create(*Context, Decl::EmptyShell()); + D = FriendTemplateDecl::Create(Context, Decl::EmptyShell()); break; case DECL_CLASS_TEMPLATE: - D = ClassTemplateDecl::Create(*Context, Decl::EmptyShell()); + D = ClassTemplateDecl::Create(Context, Decl::EmptyShell()); break; case DECL_CLASS_TEMPLATE_SPECIALIZATION: - D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell()); + D = ClassTemplateSpecializationDecl::Create(Context, Decl::EmptyShell()); break; case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: - D = ClassTemplatePartialSpecializationDecl::Create(*Context, + D = ClassTemplatePartialSpecializationDecl::Create(Context, Decl::EmptyShell()); break; + case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION: + D = ClassScopeFunctionSpecializationDecl::Create(Context, + Decl::EmptyShell()); + break; case DECL_FUNCTION_TEMPLATE: - D = FunctionTemplateDecl::Create(*Context, Decl::EmptyShell()); + D = FunctionTemplateDecl::Create(Context, Decl::EmptyShell()); break; case DECL_TEMPLATE_TYPE_PARM: - D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell()); + D = TemplateTypeParmDecl::Create(Context, Decl::EmptyShell()); break; case DECL_NON_TYPE_TEMPLATE_PARM: - D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), + D = NonTypeTemplateParmDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, 0, 0, QualType(), false, 0); break; case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: - D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), + D = NonTypeTemplateParmDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, 0, 0, QualType(), 0, 0, Record[Idx++], 0); break; case DECL_TEMPLATE_TEMPLATE_PARM: - D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0, + D = TemplateTemplateParmDecl::Create(Context, 0, SourceLocation(), 0, 0, false, 0, 0); break; case DECL_TYPE_ALIAS_TEMPLATE: - D = TypeAliasTemplateDecl::Create(*Context, Decl::EmptyShell()); + D = TypeAliasTemplateDecl::Create(Context, Decl::EmptyShell()); break; case DECL_STATIC_ASSERT: - D = StaticAssertDecl::Create(*Context, 0, SourceLocation(), 0, 0, + D = StaticAssertDecl::Create(Context, 0, SourceLocation(), 0, 0, SourceLocation()); break; case DECL_OBJC_METHOD: - D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(), + D = ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(), Selector(), QualType(), 0, 0); break; case DECL_OBJC_INTERFACE: - D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0); + D = ObjCInterfaceDecl::Create(Context, 0, SourceLocation(), 0); break; case DECL_OBJC_IVAR: - D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + D = ObjCIvarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0, ObjCIvarDecl::None); break; case DECL_OBJC_PROTOCOL: - D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0); + D = ObjCProtocolDecl::Create(Context, 0, 0, SourceLocation(), + SourceLocation()); break; case DECL_OBJC_AT_DEFS_FIELD: - D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), + D = ObjCAtDefsFieldDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0); break; case DECL_OBJC_CLASS: - D = ObjCClassDecl::Create(*Context, 0, SourceLocation()); + D = ObjCClassDecl::Create(Context, 0, SourceLocation()); break; case DECL_OBJC_FORWARD_PROTOCOL: - D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation()); + D = ObjCForwardProtocolDecl::Create(Context, 0, SourceLocation()); break; case DECL_OBJC_CATEGORY: - D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceLocation(), 0); + D = ObjCCategoryDecl::Create(Context, Decl::EmptyShell()); break; case DECL_OBJC_CATEGORY_IMPL: - D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0); + D = ObjCCategoryImplDecl::Create(Context, 0, 0, 0, SourceLocation(), + SourceLocation()); break; case DECL_OBJC_IMPLEMENTATION: - D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0); + D = ObjCImplementationDecl::Create(Context, 0, 0, 0, SourceLocation(), + SourceLocation()); break; case DECL_OBJC_COMPATIBLE_ALIAS: - D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0); + D = ObjCCompatibleAliasDecl::Create(Context, 0, SourceLocation(), 0, 0); break; case DECL_OBJC_PROPERTY: - D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(), + D = ObjCPropertyDecl::Create(Context, 0, SourceLocation(), 0, SourceLocation(), 0); break; case DECL_OBJC_PROPERTY_IMPL: - D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(), + D = ObjCPropertyImplDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, ObjCPropertyImplDecl::Dynamic, 0, SourceLocation()); break; case DECL_FIELD: - D = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, + D = FieldDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0, 0, false, false); break; case DECL_INDIRECTFIELD: - D = IndirectFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), + D = IndirectFieldDecl::Create(Context, 0, SourceLocation(), 0, QualType(), 0, 0); break; case DECL_VAR: - D = VarDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, + D = VarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0, SC_None, SC_None); break; case DECL_IMPLICIT_PARAM: - D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType()); + D = ImplicitParamDecl::Create(Context, 0, SourceLocation(), 0, QualType()); break; case DECL_PARM_VAR: - D = ParmVarDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, + D = ParmVarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0, SC_None, SC_None, 0); break; case DECL_FILE_SCOPE_ASM: - D = FileScopeAsmDecl::Create(*Context, 0, 0, SourceLocation(), + D = FileScopeAsmDecl::Create(Context, 0, 0, SourceLocation(), SourceLocation()); break; case DECL_BLOCK: - D = BlockDecl::Create(*Context, 0, SourceLocation()); + D = BlockDecl::Create(Context, 0, SourceLocation()); break; case DECL_CXX_BASE_SPECIFIERS: Error("attempt to read a C++ base-specifier record as a declaration"); @@ -1693,16 +1715,13 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { if (DeclContext *DC = dyn_cast<DeclContext>(D)) { std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); if (Offsets.first || Offsets.second) { - DC->setHasExternalLexicalStorage(Offsets.first != 0); - DC->setHasExternalVisibleStorage(Offsets.second != 0); - DeclContextInfo Info; - if (ReadDeclContextStorage(DeclsCursor, Offsets, Info)) + if (Offsets.first != 0) + DC->setHasExternalLexicalStorage(true); + if (Offsets.second != 0) + DC->setHasExternalVisibleStorage(true); + if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets, + Loc.F->DeclContextInfos[DC])) return 0; - DeclContextInfos &Infos = DeclContextOffsets[DC]; - // Reading the TU will happen after reading its lexical update blocks, - // so we need to make sure we insert in front. For all other contexts, - // the vector is empty here anyway, so there's no loss in efficiency. - Infos.insert(Infos.begin(), Info); } // Now add the pending visible updates for this decl context, if it has any. @@ -1713,20 +1732,32 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { // storage, even if the original stored version didn't. DC->setHasExternalVisibleStorage(true); DeclContextVisibleUpdates &U = I->second; - DeclContextInfos &Infos = DeclContextOffsets[DC]; - DeclContextInfo Info; - Info.LexicalDecls = 0; - Info.NumLexicalDecls = 0; for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end(); UI != UE; ++UI) { - Info.NameLookupTableData = *UI; - Infos.push_back(Info); + UI->second->DeclContextInfos[DC].NameLookupTableData = UI->first; } PendingVisibleUpdates.erase(I); } } assert(Idx == Record.size()); + // Load any relevant update records. + loadDeclUpdateRecords(ID, D); + + if (ObjCChainedCategoriesInterfaces.count(ID)) + loadObjCChainedCategories(ID, cast<ObjCInterfaceDecl>(D)); + + // If we have deserialized a declaration that has a definition the + // AST consumer might need to know about, queue it. + // We don't pass it to the consumer immediately because we may be in recursive + // loading, and some declarations may still be initializing. + if (isConsumerInterestedIn(D)) + InterestingDecls.push_back(D); + + return D; +} + +void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { // The declaration may have been modified by files later in the chain. // If this is the case, read the record containing the updates from each file // and pass it to ASTDeclReader to make the modifications. @@ -1734,8 +1765,8 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { if (UpdI != DeclUpdateOffsets.end()) { FileOffsetsTy &UpdateOffsets = UpdI->second; for (FileOffsetsTy::iterator - I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { - PerFileData *F = I->first; + I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) { + Module *F = I->first; uint64_t Offset = I->second; llvm::BitstreamCursor &Cursor = F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); @@ -1745,45 +1776,166 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { unsigned RecCode = Cursor.ReadRecord(Code, Record); (void)RecCode; assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); + + unsigned Idx = 0; + ASTDeclReader Reader(*this, *F, Cursor, ID, Record, Idx); Reader.UpdateDecl(D, *F, Record); } } +} - // If we have deserialized a declaration that has a definition the - // AST consumer might need to know about, queue it. - // We don't pass it to the consumer immediately because we may be in recursive - // loading, and some declarations may still be initializing. - if (isConsumerInterestedIn(D)) - InterestingDecls.push_back(D); +namespace { + /// \brief Given an ObjC interface, goes through the modules and links to the + /// interface all the categories for it. + class ObjCChainedCategoriesVisitor { + ASTReader &Reader; + serialization::GlobalDeclID InterfaceID; + ObjCInterfaceDecl *Interface; + ObjCCategoryDecl *GlobHeadCat, *GlobTailCat; + llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; - return D; + public: + ObjCChainedCategoriesVisitor(ASTReader &Reader, + serialization::GlobalDeclID InterfaceID, + ObjCInterfaceDecl *Interface) + : Reader(Reader), InterfaceID(InterfaceID), Interface(Interface), + GlobHeadCat(0), GlobTailCat(0) { } + + static bool visit(Module &M, void *UserData) { + return static_cast<ObjCChainedCategoriesVisitor *>(UserData)->visit(M); + } + + bool visit(Module &M) { + if (Reader.isDeclIDFromModule(InterfaceID, M)) + return true; // We reached the module where the interface originated + // from. Stop traversing the imported modules. + + Module::ChainedObjCCategoriesMap::iterator + I = M.ChainedObjCCategories.find(InterfaceID); + if (I == M.ChainedObjCCategories.end()) + return false; + + ObjCCategoryDecl * + HeadCat = Reader.GetLocalDeclAs<ObjCCategoryDecl>(M, I->second.first); + ObjCCategoryDecl * + TailCat = Reader.GetLocalDeclAs<ObjCCategoryDecl>(M, I->second.second); + + addCategories(HeadCat, TailCat); + return false; + } + + void addCategories(ObjCCategoryDecl *HeadCat, + ObjCCategoryDecl *TailCat = 0) { + if (!HeadCat) { + assert(!TailCat); + return; + } + + if (!TailCat) { + TailCat = HeadCat; + while (TailCat->getNextClassCategory()) + TailCat = TailCat->getNextClassCategory(); + } + + if (!GlobHeadCat) { + GlobHeadCat = HeadCat; + GlobTailCat = TailCat; + } else { + ASTDeclReader::setNextObjCCategory(GlobTailCat, HeadCat); + GlobTailCat = TailCat; + } + + llvm::DenseSet<DeclarationName> Checked; + for (ObjCCategoryDecl *Cat = HeadCat, + *CatEnd = TailCat->getNextClassCategory(); + Cat != CatEnd; Cat = Cat->getNextClassCategory()) { + if (Checked.count(Cat->getDeclName())) + continue; + Checked.insert(Cat->getDeclName()); + checkForDuplicate(Cat); + } + } + + /// \brief Warns for duplicate categories that come from different modules. + void checkForDuplicate(ObjCCategoryDecl *Cat) { + DeclarationName Name = Cat->getDeclName(); + // Find the top category with the same name. We do not want to warn for + // duplicates along the established chain because there were already + // warnings for them when the module was created. We only want to warn for + // duplicates between non-dependent modules: + // + // MT // + // / \ // + // ML MR // + // + // We want to warn for duplicates between ML and MR,not between ML and MT. + // + // FIXME: We should not warn for duplicates in diamond: + // + // MT // + // / \ // + // ML MR // + // \ / // + // MB // + // + // If there are duplicates in ML/MR, there will be warning when creating + // MB *and* when importing MB. We should not warn when importing. + for (ObjCCategoryDecl *Next = Cat->getNextClassCategory(); Next; + Next = Next->getNextClassCategory()) { + if (Next->getDeclName() == Name) + Cat = Next; + } + + ObjCCategoryDecl *&PrevCat = NameCategoryMap[Name]; + if (!PrevCat) + PrevCat = Cat; + + if (PrevCat != Cat) { + Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) + << Interface->getDeclName() << Name; + Reader.Diag(PrevCat->getLocation(), diag::note_previous_definition); + } + } + + ObjCCategoryDecl *getHeadCategory() const { return GlobHeadCat; } + }; +} + +void ASTReader::loadObjCChainedCategories(serialization::GlobalDeclID ID, + ObjCInterfaceDecl *D) { + ObjCChainedCategoriesVisitor Visitor(*this, ID, D); + ModuleMgr.visit(ObjCChainedCategoriesVisitor::visit, &Visitor); + // Also add the categories that the interface already links to. + Visitor.addCategories(D->getCategoryList()); + D->setCategoryList(Visitor.getHeadCategory()); } -void ASTDeclReader::UpdateDecl(Decl *D, ASTReader::PerFileData &Module, +void ASTDeclReader::UpdateDecl(Decl *D, Module &Module, const RecordData &Record) { unsigned Idx = 0; while (Idx < Record.size()) { switch ((DeclUpdateKind)Record[Idx++]) { case UPD_CXX_SET_DEFINITIONDATA: { CXXRecordDecl *RD = cast<CXXRecordDecl>(D); - CXXRecordDecl * - DefinitionDecl = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])); + CXXRecordDecl *DefinitionDecl + = Reader.ReadDeclAs<CXXRecordDecl>(Module, Record, Idx); assert(!RD->DefinitionData && "DefinitionData is already set!"); InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx); break; } case UPD_CXX_ADDED_IMPLICIT_MEMBER: - cast<CXXRecordDecl>(D)->addedMember(Reader.GetDecl(Record[Idx++])); + cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(Module, Record, Idx)); break; case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: // It will be added to the template's specializations set when loaded. - Reader.GetDecl(Record[Idx++]); + (void)Reader.ReadDecl(Module, Record, Idx); break; case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { - NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(Record[Idx++])); + NamespaceDecl *Anon + = Reader.ReadDeclAs<NamespaceDecl>(Module, Record, Idx); // Guard against these being loaded out of original order. Don't use // getNextNamespace(), since it tries to access the context and can't in // the middle of deserialization. diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h new file mode 100644 index 0000000..99e8be5 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h @@ -0,0 +1,243 @@ +//===--- ASTReaderInternals.h - AST Reader Internals ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides internal definitions used in the AST reader. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H +#define LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H + +#include "clang/Basic/OnDiskHashTable.h" +#include "clang/AST/DeclarationName.h" +#include <utility> +#include <sys/stat.h> + +namespace clang { + +class ASTReader; +class HeaderSearch; +struct HeaderFileInfo; + +namespace serialization { + +class Module; + +namespace reader { + +/// \brief Class that performs name lookup into a DeclContext stored +/// in an AST file. +class ASTDeclContextNameLookupTrait { + ASTReader &Reader; + Module &F; + +public: + /// \brief Pair of begin/end iterators for DeclIDs. + /// + /// Note that these declaration IDs are local to the module that contains this + /// particular lookup t + typedef 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, + Module &F) + : Reader(Reader), F(F) { } + + static bool EqualKey(const internal_key_type& a, + const internal_key_type& b) { + return a.Kind == b.Kind && a.Data == b.Data; + } + + unsigned ComputeHash(const DeclNameKey &Key) const; + internal_key_type GetInternalKey(const external_key_type& Name) const; + external_key_type GetExternalKey(const internal_key_type& Key) const; + + static std::pair<unsigned, unsigned> + ReadKeyDataLength(const unsigned char*& d); + + internal_key_type ReadKey(const unsigned char* d, unsigned); + + data_type ReadData(internal_key_type, const unsigned char* d, + unsigned DataLen); +}; + +/// \brief The on-disk hash table used for the DeclContext's Name lookup table. +typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait> + ASTDeclContextNameLookupTable; + +/// \brief Class that performs lookup for an identifier stored in an AST file. +class ASTIdentifierLookupTrait { + ASTReader &Reader; + Module &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, Module &F, + IdentifierInfo *II = 0) + : Reader(Reader), F(F), KnownII(II) { } + + static bool EqualKey(const internal_key_type& a, + const internal_key_type& b) { + return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0 + : false; + } + + static unsigned ComputeHash(const internal_key_type& a); + + // This hopefully will just get inlined and removed by the optimizer. + static const internal_key_type& + GetInternalKey(const external_key_type& x) { return x; } + + // This hopefully will just get inlined and removed by the optimizer. + static const external_key_type& + GetExternalKey(const internal_key_type& x) { return x; } + + static std::pair<unsigned, unsigned> + ReadKeyDataLength(const unsigned char*& d); + + static std::pair<const char*, unsigned> + ReadKey(const unsigned char* d, unsigned n); + + IdentifierInfo *ReadData(const internal_key_type& k, + const unsigned char* d, + unsigned DataLen); +}; + +/// \brief The on-disk hash table used to contain information about +/// all of the identifiers in the program. +typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait> + ASTIdentifierLookupTable; + +/// \brief Class that performs lookup for a selector's entries in the global +/// method pool stored in an AST file. +class ASTSelectorLookupTrait { + ASTReader &Reader; + Module &F; + +public: + struct data_type { + SelectorID ID; + llvm::SmallVector<ObjCMethodDecl *, 2> Instance; + llvm::SmallVector<ObjCMethodDecl *, 2> Factory; + }; + + typedef Selector external_key_type; + typedef external_key_type internal_key_type; + + ASTSelectorLookupTrait(ASTReader &Reader, Module &F) + : Reader(Reader), F(F) { } + + static bool EqualKey(const internal_key_type& a, + const internal_key_type& b) { + return a == b; + } + + static unsigned ComputeHash(Selector Sel); + + static const internal_key_type& + GetInternalKey(const external_key_type& x) { return x; } + + static std::pair<unsigned, unsigned> + ReadKeyDataLength(const unsigned char*& d); + + internal_key_type ReadKey(const unsigned char* d, unsigned); + data_type ReadData(Selector, const unsigned char* d, unsigned DataLen); +}; + +/// \brief The on-disk hash table used for the global method pool. +typedef OnDiskChainedHashTable<ASTSelectorLookupTrait> + ASTSelectorLookupTable; + +/// \brief Trait class used to search the on-disk hash table containing all of +/// the header search information. +/// +/// The on-disk hash table contains a mapping from each header path to +/// information about that header (how many times it has been included, its +/// controlling macro, etc.). Note that we actually hash based on the +/// filename, and support "deep" comparisons of file names based on current +/// inode numbers, so that the search can cope with non-normalized path names +/// and symlinks. +class HeaderFileInfoTrait { + ASTReader &Reader; + Module &M; + HeaderSearch *HS; + const char *FrameworkStrings; + const char *SearchPath; + struct stat SearchPathStatBuf; + llvm::Optional<int> SearchPathStatResult; + + int StatSimpleCache(const char *Path, struct stat *StatBuf) { + if (Path == SearchPath) { + if (!SearchPathStatResult) + SearchPathStatResult = stat(Path, &SearchPathStatBuf); + + *StatBuf = SearchPathStatBuf; + return *SearchPathStatResult; + } + + return stat(Path, StatBuf); + } + +public: + typedef const char *external_key_type; + typedef const char *internal_key_type; + + typedef HeaderFileInfo data_type; + + HeaderFileInfoTrait(ASTReader &Reader, Module &M, HeaderSearch *HS, + const char *FrameworkStrings, + const char *SearchPath = 0) + : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings), + SearchPath(SearchPath) { } + + static unsigned ComputeHash(const char *path); + static internal_key_type GetInternalKey(const char *path); + bool EqualKey(internal_key_type a, internal_key_type b); + + static std::pair<unsigned, unsigned> + ReadKeyDataLength(const unsigned char*& d); + + static internal_key_type ReadKey(const unsigned char *d, unsigned) { + return (const char *)d; + } + + data_type ReadData(const internal_key_type, const unsigned char *d, + unsigned DataLen); +}; + +/// \brief The on-disk hash table used for known header files. +typedef OnDiskChainedHashTable<HeaderFileInfoTrait> + HeaderFileInfoLookupTable; + +} // end namespace clang::serialization::reader +} // end namespace clang::serialization +} // end namespace clang + + +#endif diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp index 14927b9..ab07b85 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp @@ -22,34 +22,51 @@ using namespace clang::serialization; namespace clang { class ASTStmtReader : public StmtVisitor<ASTStmtReader> { + typedef ASTReader::RecordData RecordData; + ASTReader &Reader; - ASTReader::PerFileData &F; + Module &F; llvm::BitstreamCursor &DeclsCursor; const ASTReader::RecordData &Record; unsigned &Idx; - SourceLocation ReadSourceLocation(const ASTReader::RecordData &R, - unsigned &I) { + SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) { return Reader.ReadSourceLocation(F, R, I); } - SourceRange ReadSourceRange(const ASTReader::RecordData &R, unsigned &I) { + + SourceRange ReadSourceRange(const RecordData &R, unsigned &I) { return Reader.ReadSourceRange(F, R, I); } - TypeSourceInfo *GetTypeSourceInfo(const ASTReader::RecordData &R, - unsigned &I) { + + TypeSourceInfo *GetTypeSourceInfo(const RecordData &R, unsigned &I) { return Reader.GetTypeSourceInfo(F, R, I); } + + serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) { + return Reader.ReadDeclID(F, R, I); + } + + Decl *ReadDecl(const RecordData &R, unsigned &I) { + return Reader.ReadDecl(F, R, I); + } + + template<typename T> + T *ReadDeclAs(const RecordData &R, unsigned &I) { + return Reader.ReadDeclAs<T>(F, R, I); + } + void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name, const ASTReader::RecordData &R, unsigned &I) { Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I); } + void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo, const ASTReader::RecordData &R, unsigned &I) { Reader.ReadDeclarationNameInfo(F, NameInfo, R, I); } public: - ASTStmtReader(ASTReader &Reader, ASTReader::PerFileData &F, + ASTStmtReader(ASTReader &Reader, Module &F, llvm::BitstreamCursor &Cursor, const ASTReader::RecordData &Record, unsigned &Idx) : Reader(Reader), F(F), DeclsCursor(Cursor), Record(Record), Idx(Idx) { } @@ -63,7 +80,7 @@ namespace clang { static const unsigned NumExprFields = NumStmtFields + 7; /// \brief Read and initialize a ExplicitTemplateArgumentList structure. - void ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList, + void ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList, unsigned NumTemplateArgs); void VisitStmt(Stmt *S); @@ -74,7 +91,7 @@ namespace clang { } void ASTStmtReader:: -ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList, +ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList, unsigned NumTemplateArgs) { TemplateArgumentListInfo ArgInfo; ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx)); @@ -92,16 +109,16 @@ void ASTStmtReader::VisitStmt(Stmt *S) { void ASTStmtReader::VisitNullStmt(NullStmt *S) { VisitStmt(S); S->setSemiLoc(ReadSourceLocation(Record, Idx)); - S->LeadingEmptyMacro = ReadSourceLocation(Record, Idx); + S->HasLeadingEmptyMacro = Record[Idx++]; } void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) { VisitStmt(S); - llvm::SmallVector<Stmt *, 16> Stmts; + SmallVector<Stmt *, 16> Stmts; unsigned NumStmts = Record[Idx++]; while (NumStmts--) Stmts.push_back(Reader.ReadSubStmt()); - S->setStmts(*Reader.getContext(), Stmts.data(), Stmts.size()); + S->setStmts(Reader.getContext(), Stmts.data(), Stmts.size()); S->setLBracLoc(ReadSourceLocation(Record, Idx)); S->setRBracLoc(ReadSourceLocation(Record, Idx)); } @@ -130,7 +147,7 @@ void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) { void ASTStmtReader::VisitLabelStmt(LabelStmt *S) { VisitStmt(S); - LabelDecl *LD = cast<LabelDecl>(Reader.GetDecl(Record[Idx++])); + LabelDecl *LD = ReadDeclAs<LabelDecl>(Record, Idx); LD->setStmt(S); S->setDecl(LD); S->setSubStmt(Reader.ReadSubStmt()); @@ -139,8 +156,8 @@ void ASTStmtReader::VisitLabelStmt(LabelStmt *S) { void ASTStmtReader::VisitIfStmt(IfStmt *S) { VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); + S->setConditionVariable(Reader.getContext(), + ReadDeclAs<VarDecl>(Record, Idx)); S->setCond(Reader.ReadSubExpr()); S->setThen(Reader.ReadSubStmt()); S->setElse(Reader.ReadSubStmt()); @@ -150,8 +167,8 @@ void ASTStmtReader::VisitIfStmt(IfStmt *S) { void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) { VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); + S->setConditionVariable(Reader.getContext(), + ReadDeclAs<VarDecl>(Record, Idx)); S->setCond(Reader.ReadSubExpr()); S->setBody(Reader.ReadSubStmt()); S->setSwitchLoc(ReadSourceLocation(Record, Idx)); @@ -172,8 +189,9 @@ void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) { void ASTStmtReader::VisitWhileStmt(WhileStmt *S) { VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); + S->setConditionVariable(Reader.getContext(), + ReadDeclAs<VarDecl>(Record, Idx)); + S->setCond(Reader.ReadSubExpr()); S->setBody(Reader.ReadSubStmt()); S->setWhileLoc(ReadSourceLocation(Record, Idx)); @@ -192,8 +210,8 @@ void ASTStmtReader::VisitForStmt(ForStmt *S) { VisitStmt(S); S->setInit(Reader.ReadSubStmt()); S->setCond(Reader.ReadSubExpr()); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); + S->setConditionVariable(Reader.getContext(), + ReadDeclAs<VarDecl>(Record, Idx)); S->setInc(Reader.ReadSubExpr()); S->setBody(Reader.ReadSubStmt()); S->setForLoc(ReadSourceLocation(Record, Idx)); @@ -203,7 +221,7 @@ void ASTStmtReader::VisitForStmt(ForStmt *S) { void ASTStmtReader::VisitGotoStmt(GotoStmt *S) { VisitStmt(S); - S->setLabel(cast<LabelDecl>(Reader.GetDecl(Record[Idx++]))); + S->setLabel(ReadDeclAs<LabelDecl>(Record, Idx)); S->setGotoLoc(ReadSourceLocation(Record, Idx)); S->setLabelLoc(ReadSourceLocation(Record, Idx)); } @@ -229,7 +247,7 @@ void ASTStmtReader::VisitReturnStmt(ReturnStmt *S) { VisitStmt(S); S->setRetValue(Reader.ReadSubExpr()); S->setReturnLoc(ReadSourceLocation(Record, Idx)); - S->setNRVOCandidate(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); + S->setNRVOCandidate(ReadDeclAs<VarDecl>(Record, Idx)); } void ASTStmtReader::VisitDeclStmt(DeclStmt *S) { @@ -239,13 +257,13 @@ void ASTStmtReader::VisitDeclStmt(DeclStmt *S) { if (Idx + 1 == Record.size()) { // Single declaration - S->setDeclGroup(DeclGroupRef(Reader.GetDecl(Record[Idx++]))); + S->setDeclGroup(DeclGroupRef(ReadDecl(Record, Idx))); } else { - llvm::SmallVector<Decl *, 16> Decls; - Decls.reserve(Record.size() - Idx); - for (unsigned N = Record.size(); Idx != N; ++Idx) - Decls.push_back(Reader.GetDecl(Record[Idx])); - S->setDeclGroup(DeclGroupRef(DeclGroup::Create(*Reader.getContext(), + SmallVector<Decl *, 16> Decls; + Decls.reserve(Record.size() - Idx); + for (unsigned N = Record.size(); Idx != N; ) + Decls.push_back(ReadDecl(Record, Idx)); + S->setDeclGroup(DeclGroupRef(DeclGroup::Create(Reader.getContext(), Decls.data(), Decls.size()))); } @@ -265,21 +283,21 @@ void ASTStmtReader::VisitAsmStmt(AsmStmt *S) { S->setAsmString(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); // Outputs and inputs - llvm::SmallVector<IdentifierInfo *, 16> Names; - llvm::SmallVector<StringLiteral*, 16> Constraints; - llvm::SmallVector<Stmt*, 16> Exprs; + SmallVector<IdentifierInfo *, 16> Names; + SmallVector<StringLiteral*, 16> Constraints; + SmallVector<Stmt*, 16> Exprs; for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) { - Names.push_back(Reader.GetIdentifierInfo(Record, Idx)); + Names.push_back(Reader.GetIdentifierInfo(F, Record, Idx)); Constraints.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); Exprs.push_back(Reader.ReadSubStmt()); } // Constraints - llvm::SmallVector<StringLiteral*, 16> Clobbers; + SmallVector<StringLiteral*, 16> Clobbers; for (unsigned I = 0; I != NumClobbers; ++I) Clobbers.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); - S->setOutputsAndInputsAndClobbers(*Reader.getContext(), + S->setOutputsAndInputsAndClobbers(Reader.getContext(), Names.data(), Constraints.data(), Exprs.data(), NumOutputs, NumInputs, Clobbers.data(), NumClobbers); @@ -287,7 +305,7 @@ void ASTStmtReader::VisitAsmStmt(AsmStmt *S) { void ASTStmtReader::VisitExpr(Expr *E) { VisitStmt(E); - E->setType(Reader.GetType(Record[Idx++])); + E->setType(Reader.readType(F, Record, Idx)); E->setTypeDependent(Record[Idx++]); E->setValueDependent(Record[Idx++]); E->setInstantiationDependent(Record[Idx++]); @@ -309,6 +327,7 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { E->DeclRefExprBits.HasQualifier = Record[Idx++]; E->DeclRefExprBits.HasFoundDecl = Record[Idx++]; E->DeclRefExprBits.HasExplicitTemplateArgs = Record[Idx++]; + E->DeclRefExprBits.HadMultipleCandidates = Record[Idx++]; unsigned NumTemplateArgs = 0; if (E->hasExplicitTemplateArgs()) NumTemplateArgs = Record[Idx++]; @@ -318,13 +337,13 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); if (E->hasFoundDecl()) - E->getInternalFoundDecl() = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); + E->getInternalFoundDecl() = ReadDeclAs<NamedDecl>(Record, Idx); if (E->hasExplicitTemplateArgs()) ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), NumTemplateArgs); - E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++]))); + E->setDecl(ReadDeclAs<ValueDecl>(Record, Idx)); E->setLocation(ReadSourceLocation(Record, Idx)); ReadDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName(), Record, Idx); } @@ -332,12 +351,12 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) { VisitExpr(E); E->setLocation(ReadSourceLocation(Record, Idx)); - E->setValue(*Reader.getContext(), Reader.ReadAPInt(Record, Idx)); + E->setValue(Reader.getContext(), Reader.ReadAPInt(Record, Idx)); } void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) { VisitExpr(E); - E->setValue(*Reader.getContext(), Reader.ReadAPFloat(Record, Idx)); + E->setValue(Reader.getContext(), Reader.ReadAPFloat(Record, Idx)); E->setExact(Record[Idx++]); E->setLocation(ReadSourceLocation(Record, Idx)); } @@ -353,12 +372,12 @@ void ASTStmtReader::VisitStringLiteral(StringLiteral *E) { assert(Record[Idx] == E->getNumConcatenated() && "Wrong number of concatenated tokens!"); ++Idx; - E->IsWide = Record[Idx++]; + E->Kind = static_cast<StringLiteral::StringKind>(Record[Idx++]); E->IsPascal = Record[Idx++]; // Read string data llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); - E->setString(*Reader.getContext(), Str.str()); + E->setString(Reader.getContext(), Str.str()); Idx += Len; // Read source locations @@ -370,7 +389,7 @@ void ASTStmtReader::VisitCharacterLiteral(CharacterLiteral *E) { VisitExpr(E); E->setValue(Record[Idx++]); E->setLocation(ReadSourceLocation(Record, Idx)); - E->setWide(Record[Idx++]); + E->setKind(static_cast<CharacterLiteral::CharacterKind>(Record[Idx++])); } void ASTStmtReader::VisitParenExpr(ParenExpr *E) { @@ -383,7 +402,7 @@ void ASTStmtReader::VisitParenExpr(ParenExpr *E) { void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) { VisitExpr(E); unsigned NumExprs = Record[Idx++]; - E->Exprs = new (*Reader.getContext()) Stmt*[NumExprs]; + E->Exprs = new (Reader.getContext()) Stmt*[NumExprs]; for (unsigned i = 0; i != NumExprs; ++i) E->Exprs[i] = Reader.ReadSubStmt(); E->NumExprs = NumExprs; @@ -418,18 +437,18 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { break; case Node::Field: - E->setComponent(I, - Node(Start, - dyn_cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])), - End)); + E->setComponent(I, Node(Start, ReadDeclAs<FieldDecl>(Record, Idx), End)); break; case Node::Identifier: - E->setComponent(I, Node(Start, Reader.GetIdentifier(Record[Idx++]), End)); + E->setComponent(I, + Node(Start, + Reader.GetIdentifierInfo(F, Record, Idx), + End)); break; case Node::Base: { - CXXBaseSpecifier *Base = new (*Reader.getContext()) CXXBaseSpecifier(); + CXXBaseSpecifier *Base = new (Reader.getContext()) CXXBaseSpecifier(); *Base = Reader.ReadCXXBaseSpecifier(F, Record, Idx); E->setComponent(I, Node(Base)); break; @@ -463,7 +482,7 @@ void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { void ASTStmtReader::VisitCallExpr(CallExpr *E) { VisitExpr(E); - E->setNumArgs(*Reader.getContext(), Record[Idx++]); + E->setNumArgs(Reader.getContext(), Record[Idx++]); E->setRParenLoc(ReadSourceLocation(Record, Idx)); E->setCallee(Reader.ReadSubExpr()); for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) @@ -509,7 +528,7 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { E->setCastKind((CastExpr::CastKind)Record[Idx++]); CastExpr::path_iterator BaseI = E->path_begin(); while (NumBaseSpecs--) { - CXXBaseSpecifier *BaseSpec = new (*Reader.getContext()) CXXBaseSpecifier; + CXXBaseSpecifier *BaseSpec = new (Reader.getContext()) CXXBaseSpecifier; *BaseSpec = Reader.ReadCXXBaseSpecifier(F, Record, Idx); *BaseI++ = BaseSpec; } @@ -525,8 +544,8 @@ void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { VisitBinaryOperator(E); - E->setComputationLHSType(Reader.GetType(Record[Idx++])); - E->setComputationResultType(Reader.GetType(Record[Idx++])); + E->setComputationLHSType(Reader.readType(F, Record, Idx)); + E->setComputationResultType(Reader.readType(F, Record, Idx)); } void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) { @@ -578,7 +597,7 @@ void ASTStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { VisitExpr(E); E->setBase(Reader.ReadSubExpr()); - E->setAccessor(Reader.GetIdentifierInfo(Record, Idx)); + E->setAccessor(Reader.GetIdentifierInfo(F, Record, Idx)); E->setAccessorLoc(ReadSourceLocation(Record, Idx)); } @@ -593,19 +612,18 @@ void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { filler = Reader.ReadSubExpr(); E->ArrayFillerOrUnionFieldInit = filler; } else - E->ArrayFillerOrUnionFieldInit - = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])); + E->ArrayFillerOrUnionFieldInit = ReadDeclAs<FieldDecl>(Record, Idx); E->sawArrayRangeDesignator(Record[Idx++]); unsigned NumInits = Record[Idx++]; - E->reserveInits(*Reader.getContext(), NumInits); + E->reserveInits(Reader.getContext(), NumInits); if (isArrayFiller) { for (unsigned I = 0; I != NumInits; ++I) { Expr *init = Reader.ReadSubExpr(); - E->updateInit(*Reader.getContext(), I, init ? init : filler); + E->updateInit(Reader.getContext(), I, init ? init : filler); } } else { for (unsigned I = 0; I != NumInits; ++I) - E->updateInit(*Reader.getContext(), I, Reader.ReadSubExpr()); + E->updateInit(Reader.getContext(), I, Reader.ReadSubExpr()); } } @@ -620,11 +638,11 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { E->setEqualOrColonLoc(ReadSourceLocation(Record, Idx)); E->setGNUSyntax(Record[Idx++]); - llvm::SmallVector<Designator, 4> Designators; + SmallVector<Designator, 4> Designators; while (Idx < Record.size()) { switch ((DesignatorTypes)Record[Idx++]) { case DESIG_FIELD_DECL: { - FieldDecl *Field = cast<FieldDecl>(Reader.GetDecl(Record[Idx++])); + FieldDecl *Field = ReadDeclAs<FieldDecl>(Record, Idx); SourceLocation DotLoc = ReadSourceLocation(Record, Idx); SourceLocation FieldLoc @@ -636,7 +654,7 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { } case DESIG_FIELD_NAME: { - const IdentifierInfo *Name = Reader.GetIdentifierInfo(Record, Idx); + const IdentifierInfo *Name = Reader.GetIdentifierInfo(F, Record, Idx); SourceLocation DotLoc = ReadSourceLocation(Record, Idx); SourceLocation FieldLoc @@ -669,7 +687,7 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { } } } - E->setDesignators(*Reader.getContext(), + E->setDesignators(Reader.getContext(), Designators.data(), Designators.size()); } @@ -689,7 +707,7 @@ void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) { VisitExpr(E); E->setAmpAmpLoc(ReadSourceLocation(Record, Idx)); E->setLabelLoc(ReadSourceLocation(Record, Idx)); - E->setLabel(cast<LabelDecl>(Reader.GetDecl(Record[Idx++]))); + E->setLabel(ReadDeclAs<LabelDecl>(Record, Idx)); } void ASTStmtReader::VisitStmtExpr(StmtExpr *E) { @@ -715,23 +733,23 @@ void ASTStmtReader::VisitGNUNullExpr(GNUNullExpr *E) { void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { VisitExpr(E); - llvm::SmallVector<Expr *, 16> Exprs; + SmallVector<Expr *, 16> Exprs; unsigned NumExprs = Record[Idx++]; while (NumExprs--) Exprs.push_back(Reader.ReadSubExpr()); - E->setExprs(*Reader.getContext(), Exprs.data(), Exprs.size()); + E->setExprs(Reader.getContext(), Exprs.data(), Exprs.size()); E->setBuiltinLoc(ReadSourceLocation(Record, Idx)); E->setRParenLoc(ReadSourceLocation(Record, Idx)); } void ASTStmtReader::VisitBlockExpr(BlockExpr *E) { VisitExpr(E); - E->setBlockDecl(cast_or_null<BlockDecl>(Reader.GetDecl(Record[Idx++]))); + E->setBlockDecl(ReadDeclAs<BlockDecl>(Record, Idx)); } void ASTStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { VisitExpr(E); - E->setDecl(cast<VarDecl>(Reader.GetDecl(Record[Idx++]))); + E->setDecl(ReadDeclAs<VarDecl>(Record, Idx)); E->setLocation(ReadSourceLocation(Record, Idx)); E->setByRef(Record[Idx++]); E->setConstQualAdded(Record[Idx++]); @@ -740,9 +758,9 @@ void ASTStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { VisitExpr(E); E->NumAssocs = Record[Idx++]; - E->AssocTypes = new (*Reader.getContext()) TypeSourceInfo*[E->NumAssocs]; + E->AssocTypes = new (Reader.getContext()) TypeSourceInfo*[E->NumAssocs]; E->SubExprs = - new(*Reader.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs]; + new(Reader.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs]; E->SubExprs[GenericSelectionExpr::CONTROLLING] = Reader.ReadSubExpr(); for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { @@ -756,6 +774,25 @@ void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { E->RParenLoc = ReadSourceLocation(Record, Idx); } +void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) { + VisitExpr(E); + E->setOp(AtomicExpr::AtomicOp(Record[Idx++])); + E->setPtr(Reader.ReadSubExpr()); + E->setOrder(Reader.ReadSubExpr()); + E->setNumSubExprs(2); + if (E->getOp() != AtomicExpr::Load) { + E->setVal1(Reader.ReadSubExpr()); + E->setNumSubExprs(3); + } + if (E->isCmpXChg()) { + E->setOrderFail(Reader.ReadSubExpr()); + E->setVal2(Reader.ReadSubExpr()); + E->setNumSubExprs(5); + } + E->setBuiltinLoc(ReadSourceLocation(Record, Idx)); + E->setRParenLoc(ReadSourceLocation(Record, Idx)); +} + //===----------------------------------------------------------------------===// // Objective-C Expressions and Statements @@ -774,21 +811,21 @@ void ASTStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { void ASTStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { VisitExpr(E); - E->setSelector(Reader.GetSelector(Record, Idx)); + E->setSelector(Reader.ReadSelector(F, Record, Idx)); E->setAtLoc(ReadSourceLocation(Record, Idx)); E->setRParenLoc(ReadSourceLocation(Record, Idx)); } void ASTStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { VisitExpr(E); - E->setProtocol(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); + E->setProtocol(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); E->setAtLoc(ReadSourceLocation(Record, Idx)); E->setRParenLoc(ReadSourceLocation(Record, Idx)); } void ASTStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { VisitExpr(E); - E->setDecl(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); + E->setDecl(ReadDeclAs<ObjCIvarDecl>(Record, Idx)); E->setLocation(ReadSourceLocation(Record, Idx)); E->setBase(Reader.ReadSubExpr()); E->setIsArrow(Record[Idx++]); @@ -799,14 +836,11 @@ void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { VisitExpr(E); bool Implicit = Record[Idx++] != 0; if (Implicit) { - ObjCMethodDecl *Getter = - cast<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])); - ObjCMethodDecl *Setter = - cast<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])); + ObjCMethodDecl *Getter = ReadDeclAs<ObjCMethodDecl>(Record, Idx); + ObjCMethodDecl *Setter = ReadDeclAs<ObjCMethodDecl>(Record, Idx); E->setImplicitProperty(Getter, Setter); } else { - E->setExplicitProperty( - cast<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++]))); + E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(Record, Idx)); } E->setLocation(ReadSourceLocation(Record, Idx)); E->setReceiverLocation(ReadSourceLocation(Record, Idx)); @@ -815,11 +849,10 @@ void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { E->setBase(Reader.ReadSubExpr()); break; case 1: - E->setSuperReceiver(Reader.GetType(Record[Idx++])); + E->setSuperReceiver(Reader.readType(F, Record, Idx)); break; case 2: - E->setClassReceiver( - cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); + E->setClassReceiver(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); break; } } @@ -828,6 +861,8 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { VisitExpr(E); assert(Record[Idx] == E->getNumArgs()); ++Idx; + unsigned NumStoredSelLocs = Record[Idx++]; + E->SelLocsKind = Record[Idx++]; E->setDelegateInitCall(Record[Idx++]); ObjCMessageExpr::ReceiverKind Kind = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]); @@ -842,7 +877,7 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { case ObjCMessageExpr::SuperClass: case ObjCMessageExpr::SuperInstance: { - QualType T = Reader.GetType(Record[Idx++]); + QualType T = Reader.readType(F, Record, Idx); SourceLocation SuperLoc = ReadSourceLocation(Record, Idx); E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance); break; @@ -852,16 +887,19 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { assert(Kind == E->getReceiverKind()); if (Record[Idx++]) - E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); + E->setMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx)); else - E->setSelector(Reader.GetSelector(Record, Idx)); + E->setSelector(Reader.ReadSelector(F, Record, Idx)); E->LBracLoc = ReadSourceLocation(Record, Idx); E->RBracLoc = ReadSourceLocation(Record, Idx); - E->SelectorLoc = ReadSourceLocation(Record, Idx); for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) E->setArg(I, Reader.ReadSubExpr()); + + SourceLocation *Locs = E->getStoredSelLocs(); + for (unsigned I = 0; I != NumStoredSelLocs; ++I) + Locs[I] = ReadSourceLocation(Record, Idx); } void ASTStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { @@ -876,7 +914,7 @@ void ASTStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { void ASTStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { VisitStmt(S); S->setCatchBody(Reader.ReadSubStmt()); - S->setCatchParamDecl(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); + S->setCatchParamDecl(ReadDeclAs<VarDecl>(Record, Idx)); S->setAtCatchLoc(ReadSourceLocation(Record, Idx)); S->setRParenLoc(ReadSourceLocation(Record, Idx)); } @@ -927,7 +965,7 @@ void ASTStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { void ASTStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) { VisitStmt(S); S->CatchLoc = ReadSourceLocation(Record, Idx); - S->ExceptionDecl = cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])); + S->ExceptionDecl = ReadDeclAs<VarDecl>(Record, Idx); S->HandlerBlock = Reader.ReadSubStmt(); } @@ -963,12 +1001,13 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { VisitExpr(E); E->NumArgs = Record[Idx++]; if (E->NumArgs) - E->Args = new (*Reader.getContext()) Stmt*[E->NumArgs]; + E->Args = new (Reader.getContext()) Stmt*[E->NumArgs]; for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) E->setArg(I, Reader.ReadSubExpr()); - E->setConstructor(cast<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++]))); + E->setConstructor(ReadDeclAs<CXXConstructorDecl>(Record, Idx)); E->setLocation(ReadSourceLocation(Record, Idx)); - E->setElidable(Record[Idx++]); + E->setElidable(Record[Idx++]); + E->setHadMultipleCandidates(Record[Idx++]); E->setRequiresZeroInitialization(Record[Idx++]); E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); E->ParenRange = ReadSourceRange(Record, Idx); @@ -1048,15 +1087,15 @@ void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) { void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { VisitExpr(E); - assert(Record[Idx] == E->Param.getInt() && "We messed up at creation ?"); + assert((bool)Record[Idx] == E->Param.getInt() && "We messed up at creation ?"); ++Idx; // HasOtherExprStored and SubExpr was handled during creation. - E->Param.setPointer(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); + E->Param.setPointer(ReadDeclAs<ParmVarDecl>(Record, Idx)); E->Loc = ReadSourceLocation(Record, Idx); } void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { VisitExpr(E); - E->setTemporary(Reader.ReadCXXTemporary(Record, Idx)); + E->setTemporary(Reader.ReadCXXTemporary(F, Record, Idx)); E->setSubExpr(Reader.ReadSubExpr()); } @@ -1072,13 +1111,12 @@ void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { E->Initializer = Record[Idx++]; E->UsualArrayDeleteWantsSize = Record[Idx++]; bool isArray = Record[Idx++]; + E->setHadMultipleCandidates(Record[Idx++]); unsigned NumPlacementArgs = Record[Idx++]; unsigned NumCtorArgs = Record[Idx++]; - E->setOperatorNew(cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - E->setOperatorDelete( - cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - E->setConstructor( - cast_or_null<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++]))); + E->setOperatorNew(ReadDeclAs<FunctionDecl>(Record, Idx)); + E->setOperatorDelete(ReadDeclAs<FunctionDecl>(Record, Idx)); + E->setConstructor(ReadDeclAs<CXXConstructorDecl>(Record, Idx)); E->AllocatedTypeInfo = GetTypeSourceInfo(Record, Idx); SourceRange TypeIdParens; TypeIdParens.setBegin(ReadSourceLocation(Record, Idx)); @@ -1089,7 +1127,7 @@ void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { E->ConstructorLParen = ReadSourceLocation(Record, Idx); E->ConstructorRParen = ReadSourceLocation(Record, Idx); - E->AllocateArgsArray(*Reader.getContext(), isArray, NumPlacementArgs, + E->AllocateArgsArray(Reader.getContext(), isArray, NumPlacementArgs, NumCtorArgs); // Install all the subexpressions. @@ -1104,7 +1142,7 @@ void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { E->ArrayForm = Record[Idx++]; E->ArrayFormAsWritten = Record[Idx++]; E->UsualArrayDeleteWantsSize = Record[Idx++]; - E->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])); + E->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx); E->Argument = Reader.ReadSubExpr(); E->Loc = ReadSourceLocation(Record, Idx); } @@ -1120,7 +1158,7 @@ void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { E->ColonColonLoc = ReadSourceLocation(Record, Idx); E->TildeLoc = ReadSourceLocation(Record, Idx); - IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx); + IdentifierInfo *II = Reader.GetIdentifierInfo(F, Record, Idx); if (II) E->setDestroyedType(II, ReadSourceLocation(Record, Idx)); else @@ -1131,9 +1169,9 @@ void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) { VisitExpr(E); unsigned NumTemps = Record[Idx++]; if (NumTemps) { - E->setNumTemporaries(*Reader.getContext(), NumTemps); + E->setNumTemporaries(Reader.getContext(), NumTemps); for (unsigned i = 0; i != NumTemps; ++i) - E->setTemporary(i, Reader.ReadCXXTemporary(Record, Idx)); + E->setTemporary(i, Reader.ReadCXXTemporary(F, Record, Idx)); } E->setSubExpr(Reader.ReadSubExpr()); } @@ -1147,12 +1185,11 @@ ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ Record[Idx++]); E->Base = Reader.ReadSubExpr(); - E->BaseType = Reader.GetType(Record[Idx++]); + E->BaseType = Reader.readType(F, Record, Idx); E->IsArrow = Record[Idx++]; E->OperatorLoc = ReadSourceLocation(Record, Idx); E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); - E->FirstQualifierFoundInScope - = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); + E->FirstQualifierFoundInScope = ReadDeclAs<NamedDecl>(Record, Idx); ReadDeclarationNameInfo(E->MemberNameInfo, Record, Idx); } @@ -1191,11 +1228,11 @@ void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { unsigned NumDecls = Record[Idx++]; UnresolvedSet<8> Decls; for (unsigned i = 0; i != NumDecls; ++i) { - NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); + NamedDecl *D = ReadDeclAs<NamedDecl>(Record, Idx); AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; Decls.addDecl(D, AS); } - E->initializeResults(*Reader.getContext(), Decls.begin(), Decls.end()); + E->initializeResults(Reader.getContext(), Decls.begin(), Decls.end()); ReadDeclarationNameInfo(E->NameInfo, Record, Idx); E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); @@ -1206,7 +1243,7 @@ void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { E->IsArrow = Record[Idx++]; E->HasUnresolvedUsing = Record[Idx++]; E->Base = Reader.ReadSubExpr(); - E->BaseType = Reader.GetType(Record[Idx++]); + E->BaseType = Reader.readType(F, Record, Idx); E->OperatorLoc = ReadSourceLocation(Record, Idx); } @@ -1216,7 +1253,7 @@ void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { if (E->RequiresADL) E->StdIsAssociatedNamespace = Record[Idx++]; E->Overloaded = Record[Idx++]; - E->NamingClass = cast_or_null<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])); + E->NamingClass = ReadDeclAs<CXXRecordDecl>(Record, Idx); } void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { @@ -1280,14 +1317,13 @@ void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) { E->PackLoc = ReadSourceLocation(Record, Idx); E->RParenLoc = ReadSourceLocation(Record, Idx); E->Length = Record[Idx++]; - E->Pack = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); + E->Pack = ReadDeclAs<NamedDecl>(Record, Idx); } void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); - E->Param - = cast_or_null<NonTypeTemplateParmDecl>(Reader.GetDecl(Record[Idx++])); + E->Param = ReadDeclAs<NonTypeTemplateParmDecl>(Record, Idx); E->NameLoc = ReadSourceLocation(Record, Idx); E->Replacement = Reader.ReadSubExpr(); } @@ -1295,8 +1331,7 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E) { VisitExpr(E); - E->Param - = cast_or_null<NonTypeTemplateParmDecl>(Reader.GetDecl(Record[Idx++])); + E->Param = ReadDeclAs<NonTypeTemplateParmDecl>(Record, Idx); TemplateArgument ArgPack = Reader.ReadTemplateArgument(F, Record, Idx); if (ArgPack.getKind() != TemplateArgument::Pack) return; @@ -1377,7 +1412,7 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) { // ASTReader Implementation //===----------------------------------------------------------------------===// -Stmt *ASTReader::ReadStmt(PerFileData &F) { +Stmt *ASTReader::ReadStmt(Module &F) { switch (ReadingKind) { case Read_Decl: case Read_Type: @@ -1390,7 +1425,7 @@ Stmt *ASTReader::ReadStmt(PerFileData &F) { return 0; } -Expr *ASTReader::ReadExpr(PerFileData &F) { +Expr *ASTReader::ReadExpr(Module &F) { return cast_or_null<Expr>(ReadStmt(F)); } @@ -1405,7 +1440,7 @@ Expr *ASTReader::ReadSubExpr() { // the stack, with expressions having operands removing those operands from the // stack. Evaluation terminates when we see a STMT_STOP record, and // the single remaining expression on the stack is our result. -Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { +Stmt *ASTReader::ReadStmtFromStream(Module &F) { ReadingKindTracker ReadingKind(Read_Stmt, *this); llvm::BitstreamCursor &Cursor = F.DeclsCursor; @@ -1531,20 +1566,20 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { case EXPR_DECL_REF: S = DeclRefExpr::CreateEmpty( - *Context, + Context, /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ? - Record[ASTStmtReader::NumExprFields + 3] : 0); + Record[ASTStmtReader::NumExprFields + 4] : 0); break; case EXPR_INTEGER_LITERAL: - S = IntegerLiteral::Create(*Context, Empty); + S = IntegerLiteral::Create(Context, Empty); break; case EXPR_FLOATING_LITERAL: - S = FloatingLiteral::Create(*Context, Empty); + S = FloatingLiteral::Create(Context, Empty); break; case EXPR_IMAGINARY_LITERAL: @@ -1552,7 +1587,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_STRING_LITERAL: - S = StringLiteral::CreateEmpty(*Context, + S = StringLiteral::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields + 1]); break; @@ -1573,7 +1608,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_OFFSETOF: - S = OffsetOfExpr::CreateEmpty(*Context, + S = OffsetOfExpr::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields], Record[ASTStmtReader::NumExprFields + 1]); break; @@ -1587,7 +1622,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_CALL: - S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty); + S = new (Context) CallExpr(Context, Stmt::CallExprClass, Empty); break; case EXPR_MEMBER: { @@ -1610,25 +1645,29 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { for (unsigned i = 0; i != NumTemplateArgs; ++i) ArgInfo.addArgument(ReadTemplateArgumentLoc(F, Record, Idx)); } - - NamedDecl *FoundD = cast_or_null<NamedDecl>(GetDecl(Record[Idx++])); + + bool HadMultipleCandidates = Record[Idx++]; + + NamedDecl *FoundD = ReadDeclAs<NamedDecl>(F, Record, Idx); AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS); - QualType T = GetType(Record[Idx++]); + QualType T = readType(F, Record, Idx); ExprValueKind VK = static_cast<ExprValueKind>(Record[Idx++]); ExprObjectKind OK = static_cast<ExprObjectKind>(Record[Idx++]); Expr *Base = ReadSubExpr(); - ValueDecl *MemberD = cast<ValueDecl>(GetDecl(Record[Idx++])); + ValueDecl *MemberD = ReadDeclAs<ValueDecl>(F, Record, Idx); SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx); DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc); bool IsArrow = Record[Idx++]; - S = MemberExpr::Create(*Context, Base, IsArrow, QualifierLoc, + S = MemberExpr::Create(Context, Base, IsArrow, QualifierLoc, MemberD, FoundDecl, MemberNameInfo, HasExplicitTemplateArgs ? &ArgInfo : 0, T, VK, OK); ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc, MemberD->getDeclName(), Record, Idx); + if (HadMultipleCandidates) + cast<MemberExpr>(S)->setHadMultipleCandidates(true); break; } @@ -1649,12 +1688,12 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_IMPLICIT_CAST: - S = ImplicitCastExpr::CreateEmpty(*Context, + S = ImplicitCastExpr::CreateEmpty(Context, /*PathSize*/ Record[ASTStmtReader::NumExprFields]); break; case EXPR_CSTYLE_CAST: - S = CStyleCastExpr::CreateEmpty(*Context, + S = CStyleCastExpr::CreateEmpty(Context, /*PathSize*/ Record[ASTStmtReader::NumExprFields]); break; @@ -1667,11 +1706,11 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_INIT_LIST: - S = new (Context) InitListExpr(*getContext(), Empty); + S = new (Context) InitListExpr(getContext(), Empty); break; case EXPR_DESIGNATED_INIT: - S = DesignatedInitExpr::CreateEmpty(*Context, + S = DesignatedInitExpr::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields] - 1); break; @@ -1738,8 +1777,9 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { llvm_unreachable("mismatching AST file"); break; case EXPR_OBJC_MESSAGE_EXPR: - S = ObjCMessageExpr::CreateEmpty(*Context, - Record[ASTStmtReader::NumExprFields]); + S = ObjCMessageExpr::CreateEmpty(Context, + Record[ASTStmtReader::NumExprFields], + Record[ASTStmtReader::NumExprFields + 1]); break; case EXPR_OBJC_ISA: S = new (Context) ObjCIsaExpr(Empty); @@ -1760,7 +1800,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { S = new (Context) ObjCAtFinallyStmt(Empty); break; case STMT_OBJC_AT_TRY: - S = ObjCAtTryStmt::CreateEmpty(*Context, + S = ObjCAtTryStmt::CreateEmpty(Context, Record[ASTStmtReader::NumStmtFields], Record[ASTStmtReader::NumStmtFields + 1]); break; @@ -1787,7 +1827,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case STMT_CXX_TRY: - S = CXXTryStmt::Create(*Context, Empty, + S = CXXTryStmt::Create(Context, Empty, /*NumHandlers=*/Record[ASTStmtReader::NumStmtFields]); break; @@ -1796,11 +1836,11 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_CXX_OPERATOR_CALL: - S = new (Context) CXXOperatorCallExpr(*Context, Empty); + S = new (Context) CXXOperatorCallExpr(Context, Empty); break; case EXPR_CXX_MEMBER_CALL: - S = new (Context) CXXMemberCallExpr(*Context, Empty); + S = new (Context) CXXMemberCallExpr(Context, Empty); break; case EXPR_CXX_CONSTRUCT: @@ -1812,26 +1852,26 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_CXX_STATIC_CAST: - S = CXXStaticCastExpr::CreateEmpty(*Context, + S = CXXStaticCastExpr::CreateEmpty(Context, /*PathSize*/ Record[ASTStmtReader::NumExprFields]); break; case EXPR_CXX_DYNAMIC_CAST: - S = CXXDynamicCastExpr::CreateEmpty(*Context, + S = CXXDynamicCastExpr::CreateEmpty(Context, /*PathSize*/ Record[ASTStmtReader::NumExprFields]); break; case EXPR_CXX_REINTERPRET_CAST: - S = CXXReinterpretCastExpr::CreateEmpty(*Context, + S = CXXReinterpretCastExpr::CreateEmpty(Context, /*PathSize*/ Record[ASTStmtReader::NumExprFields]); break; case EXPR_CXX_CONST_CAST: - S = CXXConstCastExpr::CreateEmpty(*Context); + S = CXXConstCastExpr::CreateEmpty(Context); break; case EXPR_CXX_FUNCTIONAL_CAST: - S = CXXFunctionalCastExpr::CreateEmpty(*Context, + S = CXXFunctionalCastExpr::CreateEmpty(Context, /*PathSize*/ Record[ASTStmtReader::NumExprFields]); break; @@ -1864,7 +1904,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { bool HasOtherExprStored = Record[ASTStmtReader::NumExprFields]; if (HasOtherExprStored) { Expr *SubExpr = ReadSubExpr(); - S = CXXDefaultArgExpr::Create(*Context, SourceLocation(), 0, SubExpr); + S = CXXDefaultArgExpr::Create(Context, SourceLocation(), 0, SubExpr); } else S = new (Context) CXXDefaultArgExpr(Empty); break; @@ -1891,7 +1931,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: - S = CXXDependentScopeMemberExpr::CreateEmpty(*Context, + S = CXXDependentScopeMemberExpr::CreateEmpty(Context, /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] ? Record[ASTStmtReader::NumExprFields + 1] @@ -1899,7 +1939,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: - S = DependentScopeDeclRefExpr::CreateEmpty(*Context, + S = DependentScopeDeclRefExpr::CreateEmpty(Context, /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] ? Record[ASTStmtReader::NumExprFields + 1] @@ -1907,12 +1947,12 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_CXX_UNRESOLVED_CONSTRUCT: - S = CXXUnresolvedConstructExpr::CreateEmpty(*Context, + S = CXXUnresolvedConstructExpr::CreateEmpty(Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields]); break; case EXPR_CXX_UNRESOLVED_MEMBER: - S = UnresolvedMemberExpr::CreateEmpty(*Context, + S = UnresolvedMemberExpr::CreateEmpty(Context, /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] ? Record[ASTStmtReader::NumExprFields + 1] @@ -1920,7 +1960,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_CXX_UNRESOLVED_LOOKUP: - S = UnresolvedLookupExpr::CreateEmpty(*Context, + S = UnresolvedLookupExpr::CreateEmpty(Context, /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] ? Record[ASTStmtReader::NumExprFields + 1] @@ -1983,12 +2023,16 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { } case EXPR_CUDA_KERNEL_CALL: - S = new (Context) CUDAKernelCallExpr(*Context, Empty); + S = new (Context) CUDAKernelCallExpr(Context, Empty); break; case EXPR_ASTYPE: S = new (Context) AsTypeExpr(Empty); break; + + case EXPR_ATOMIC: + S = new (Context) AtomicExpr(Empty); + break; } // We hit a STMT_STOP, so we're done with this expression. diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index 39f2fbd..b31262d 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/Serialization/ASTWriter.h" -#include "clang/Serialization/ASTSerializationListener.h" #include "ASTCommon.h" #include "clang/Sema/Sema.h" #include "clang/Sema/IdentifierResolver.h" @@ -45,21 +44,23 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include <algorithm> #include <cstdio> #include <string.h> +#include <utility> using namespace clang; using namespace clang::serialization; template <typename T, typename Allocator> -static llvm::StringRef data(const std::vector<T, Allocator> &v) { - if (v.empty()) return llvm::StringRef(); - return llvm::StringRef(reinterpret_cast<const char*>(&v[0]), +static StringRef data(const std::vector<T, Allocator> &v) { + if (v.empty()) return StringRef(); + return StringRef(reinterpret_cast<const char*>(&v[0]), sizeof(T) * v.size()); } template <typename T> -static llvm::StringRef data(const llvm::SmallVectorImpl<T> &v) { - return llvm::StringRef(reinterpret_cast<const char*>(v.data()), +static StringRef data(const SmallVectorImpl<T> &v) { + return StringRef(reinterpret_cast<const char*>(v.data()), sizeof(T) * v.size()); } @@ -90,7 +91,7 @@ namespace { } void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) { - assert(false && "Built-in types are never serialized"); + llvm_unreachable("Built-in types are never serialized"); } void ASTTypeWriter::VisitComplexType(const ComplexType *T) { @@ -304,7 +305,7 @@ void ASTTypeWriter::VisitDependentSizedExtVectorType( const DependentSizedExtVectorType *T) { // FIXME: Serialize this type (C++ only) - assert(false && "Cannot serialize dependent sized extended vector types"); + llvm_unreachable("Cannot serialize dependent sized extended vector types"); } void @@ -387,6 +388,12 @@ ASTTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { Code = TYPE_OBJC_OBJECT_POINTER; } +void +ASTTypeWriter::VisitAtomicType(const AtomicType *T) { + Writer.AddTypeRef(T->getValueType(), Record); + Code = TYPE_ATOMIC; +} + namespace { class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { @@ -595,6 +602,11 @@ void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { Writer.AddSourceLocation(TL.getStarLoc(), Record); } +void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) { + Writer.AddSourceLocation(TL.getKWLoc(), Record); + Writer.AddSourceLocation(TL.getLParenLoc(), Record); + Writer.AddSourceLocation(TL.getRParenLoc(), Record); +} //===----------------------------------------------------------------------===// // ASTWriter Implementation @@ -762,8 +774,8 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(STAT_CACHE); RECORD(EXT_VECTOR_DECLS); RECORD(VERSION_CONTROL_BRANCH_REVISION); - RECORD(MACRO_DEFINITION_OFFSETS); - RECORD(CHAINED_METADATA); + RECORD(PPD_ENTITIES_OFFSETS); + RECORD(IMPORTS); RECORD(REFERENCED_SELECTOR_POOL); RECORD(TU_UPDATE_LEXICAL); RECORD(REDECLS_UPDATE_LATEST); @@ -778,11 +790,14 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DIAG_PRAGMA_MAPPINGS); RECORD(CUDA_SPECIAL_DECL_REFS); RECORD(HEADER_SEARCH_TABLE); + RECORD(ORIGINAL_PCH_DIR); RECORD(FP_PRAGMA_OPTIONS); RECORD(OPENCL_EXTENSIONS); RECORD(DELEGATING_CTORS); RECORD(FILE_SOURCE_LOCATION_OFFSETS); RECORD(KNOWN_NAMESPACES); + RECORD(MODULE_OFFSET_MAP); + RECORD(SOURCE_MANAGER_LINE_TABLE); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -790,7 +805,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(SM_SLOC_BUFFER_ENTRY); RECORD(SM_SLOC_BUFFER_BLOB); RECORD(SM_SLOC_EXPANSION_ENTRY); - RECORD(SM_LINE_TABLE); // Preprocessor Block. BLOCK(PREPROCESSOR_BLOCK); @@ -837,7 +851,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TYPE_PACK_EXPANSION); RECORD(TYPE_ATTRIBUTED); RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK); - RECORD(DECL_TRANSLATION_UNIT); + RECORD(TYPE_ATOMIC); RECORD(DECL_TYPEDEF); RECORD(DECL_ENUM); RECORD(DECL_RECORD); @@ -916,15 +930,15 @@ void ASTWriter::WriteBlockInfoBlock() { /// \returns either the original filename (if it needs no adjustment) or the /// adjusted filename (which points into the @p Filename parameter). static const char * -adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) { +adjustFilenameForRelocatablePCH(const char *Filename, StringRef isysroot) { assert(Filename && "No file name to adjust?"); - if (!isysroot) + if (isysroot.empty()) return Filename; // Verify that the filename and the system root have the same prefix. unsigned Pos = 0; - for (; Filename[Pos] && isysroot[Pos]; ++Pos) + for (; Filename[Pos] && Pos < isysroot.size(); ++Pos) if (Filename[Pos] != isysroot[Pos]) return Filename; // Prefixes don't match. @@ -942,34 +956,52 @@ adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) { } /// \brief Write the AST metadata (e.g., i686-apple-darwin9). -void ASTWriter::WriteMetadata(ASTContext &Context, const char *isysroot, +void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, const std::string &OutputFile) { using namespace llvm; // Metadata - const TargetInfo &Target = Context.Target; + const TargetInfo &Target = Context.getTargetInfo(); BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev(); - MetaAbbrev->Add(BitCodeAbbrevOp( - Chain ? CHAINED_METADATA : METADATA)); + MetaAbbrev->Add(BitCodeAbbrevOp(METADATA)); MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST major MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST minor MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable - // Target triple or chained PCH name - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); RecordData Record; - Record.push_back(Chain ? CHAINED_METADATA : METADATA); + Record.push_back(METADATA); Record.push_back(VERSION_MAJOR); Record.push_back(VERSION_MINOR); Record.push_back(CLANG_VERSION_MAJOR); Record.push_back(CLANG_VERSION_MINOR); - Record.push_back(isysroot != 0); - // FIXME: This writes the absolute path for chained headers. - const std::string &BlobStr = Chain ? Chain->getFileName() : Target.getTriple().getTriple(); - Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, BlobStr); + Record.push_back(!isysroot.empty()); + const std::string &Triple = Target.getTriple().getTriple(); + Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple); + + if (Chain) { + serialization::ModuleManager &Mgr = Chain->getModuleManager(); + llvm::SmallVector<char, 128> ModulePaths; + Record.clear(); + + for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end(); + M != MEnd; ++M) { + // Skip modules that weren't directly imported. + if (!(*M)->isDirectlyImported()) + continue; + + Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding + // FIXME: Write import location, once it matters. + // FIXME: This writes the absolute path for AST files we depend on. + const std::string &FileName = (*M)->FileName; + Record.push_back(FileName.size()); + Record.append(FileName.begin(), FileName.end()); + } + Stream.EmitRecord(IMPORTS, Record); + } // Original file name and file ID SourceManager &SM = Context.getSourceManager(); @@ -1026,94 +1058,11 @@ void ASTWriter::WriteMetadata(ASTContext &Context, const char *isysroot, /// \brief Write the LangOptions structure. void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { RecordData Record; - Record.push_back(LangOpts.Trigraphs); - Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments. - Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers. - Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode. - Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc) - Record.push_back(LangOpts.GNUKeywords); // Allow GNU-extension keywords - Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'. - Record.push_back(LangOpts.Digraphs); // C94, C99 and C++ - Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants. - Record.push_back(LangOpts.C99); // C99 Support - Record.push_back(LangOpts.C1X); // C1X Support - Record.push_back(LangOpts.Microsoft); // Microsoft extensions. - // LangOpts.MSCVersion is ignored because all it does it set a macro, which is - // already saved elsewhere. - Record.push_back(LangOpts.CPlusPlus); // C++ Support - Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support - Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords. - - Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled. - Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled. - Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C - // modern abi enabled. - Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced - // modern abi enabled. - Record.push_back(LangOpts.AppleKext); // Apple's kernel extensions ABI - Record.push_back(LangOpts.ObjCDefaultSynthProperties); // Objective-C auto-synthesized - // properties enabled. - Record.push_back(LangOpts.ObjCInferRelatedResultType); - Record.push_back(LangOpts.NoConstantCFStrings); // non cfstring generation enabled.. - - Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings - Record.push_back(LangOpts.WritableStrings); // Allow writable strings - Record.push_back(LangOpts.LaxVectorConversions); - Record.push_back(LangOpts.AltiVec); - Record.push_back(LangOpts.Exceptions); // Support exception handling. - Record.push_back(LangOpts.ObjCExceptions); - Record.push_back(LangOpts.CXXExceptions); - Record.push_back(LangOpts.SjLjExceptions); - - Record.push_back(LangOpts.MSBitfields); // MS-compatible structure layout - Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime. - Record.push_back(LangOpts.Freestanding); // Freestanding implementation - Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin) - - // Whether static initializers are protected by locks. - Record.push_back(LangOpts.ThreadsafeStatics); - Record.push_back(LangOpts.POSIXThreads); - Record.push_back(LangOpts.Blocks); // block extension to C - Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if - // they are unused. - Record.push_back(LangOpts.MathErrno); // Math functions must respect errno - // (modulo the platform support). - - Record.push_back(LangOpts.getSignedOverflowBehavior()); - Record.push_back(LangOpts.HeinousExtensions); - - Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined. - Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be - // defined. - Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as - // opposed to __DYNAMIC__). - Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero. - - Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be - // used (instead of C99 semantics). - Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined. - Record.push_back(LangOpts.Deprecated); // Should __DEPRECATED be defined. - Record.push_back(LangOpts.AccessControl); // Whether C++ access control should - // be enabled. - Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or - // unsigned type - Record.push_back(LangOpts.ShortWChar); // force wchar_t to be unsigned short - Record.push_back(LangOpts.ShortEnums); // Should the enum type be equivalent - // to the smallest integer type with - // enough room. - Record.push_back(LangOpts.getGCMode()); - Record.push_back(LangOpts.getVisibilityMode()); - Record.push_back(LangOpts.getStackProtectorMode()); - Record.push_back(LangOpts.InstantiationDepth); - Record.push_back(LangOpts.OpenCL); - Record.push_back(LangOpts.CUDA); - Record.push_back(LangOpts.CatchUndefined); - Record.push_back(LangOpts.DefaultFPContract); - Record.push_back(LangOpts.ElideConstructors); - Record.push_back(LangOpts.SpellChecking); - Record.push_back(LangOpts.MRTD); - Record.push_back(LangOpts.ObjCAutoRefCount); - Record.push_back(LangOpts.ObjCInferRelatedReturnType); +#define LANGOPT(Name, Bits, Default, Description) \ + Record.push_back(LangOpts.Name); +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + Record.push_back(static_cast<unsigned>(LangOpts.get##Name())); +#include "clang/Basic/LangOptions.def" Stream.EmitRecord(LANGUAGE_OPTIONS, Record); } @@ -1136,7 +1085,7 @@ public: } std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const char *path, + EmitKeyDataLength(raw_ostream& Out, const char *path, data_type_ref Data) { unsigned StrLen = strlen(path); clang::io::Emit16(Out, StrLen); @@ -1145,11 +1094,11 @@ public: return std::make_pair(StrLen + 1, DataLen); } - void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) { + void EmitKey(raw_ostream& Out, const char *path, unsigned KeyLen) { Out.write(path, KeyLen); } - void EmitData(llvm::raw_ostream &Out, key_type_ref, + void EmitData(raw_ostream &Out, key_type_ref, data_type_ref Data, unsigned DataLen) { using namespace clang::io; uint64_t Start = Out.tell(); (void)Start; @@ -1174,7 +1123,7 @@ void ASTWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), StatEnd = StatCalls.end(); Stat != StatEnd; ++Stat, ++NumStatEntries) { - llvm::StringRef Filename = Stat->first(); + StringRef Filename = Stat->first(); Generator.insert(Filename.data(), Stat->second); } @@ -1222,6 +1171,7 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { // FileEntry fields. Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name return Stream.EmitAbbrev(Abbrev); } @@ -1270,6 +1220,10 @@ namespace { ASTWriter &Writer; HeaderSearch &HS; + // Keep track of the framework names we've used during serialization. + SmallVector<char, 128> FrameworkStringData; + llvm::StringMap<unsigned> FrameworkNameOffset; + public: HeaderFileInfoTrait(ASTWriter &Writer, HeaderSearch &HS) : Writer(Writer), HS(HS) { } @@ -1289,28 +1243,29 @@ namespace { } std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const char *path, + EmitKeyDataLength(raw_ostream& Out, const char *path, data_type_ref Data) { unsigned StrLen = strlen(path); clang::io::Emit16(Out, StrLen); - unsigned DataLen = 1 + 2 + 4; + unsigned DataLen = 1 + 2 + 4 + 4; clang::io::Emit8(Out, DataLen); return std::make_pair(StrLen + 1, DataLen); } - void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) { + void EmitKey(raw_ostream& Out, const char *path, unsigned KeyLen) { Out.write(path, KeyLen); } - void EmitData(llvm::raw_ostream &Out, key_type_ref, + void EmitData(raw_ostream &Out, key_type_ref, data_type_ref Data, unsigned DataLen) { using namespace clang::io; uint64_t Start = Out.tell(); (void)Start; - unsigned char Flags = (Data.isImport << 4) - | (Data.isPragmaOnce << 3) - | (Data.DirInfo << 1) - | Data.Resolved; + unsigned char Flags = (Data.isImport << 5) + | (Data.isPragmaOnce << 4) + | (Data.DirInfo << 2) + | (Data.Resolved << 1) + | Data.IndexHeaderMapHeader; Emit8(Out, (uint8_t)Flags); Emit16(Out, (uint16_t) Data.NumIncludes); @@ -1318,8 +1273,29 @@ namespace { Emit32(Out, (uint32_t)Data.ControllingMacroID); else Emit32(Out, (uint32_t)Writer.getIdentifierRef(Data.ControllingMacro)); + + unsigned Offset = 0; + if (!Data.Framework.empty()) { + // If this header refers into a framework, save the framework name. + llvm::StringMap<unsigned>::iterator Pos + = FrameworkNameOffset.find(Data.Framework); + if (Pos == FrameworkNameOffset.end()) { + Offset = FrameworkStringData.size() + 1; + FrameworkStringData.append(Data.Framework.begin(), + Data.Framework.end()); + FrameworkStringData.push_back(0); + + FrameworkNameOffset[Data.Framework] = Offset; + } else + Offset = Pos->second; + } + Emit32(Out, Offset); + assert(Out.tell() - Start == DataLen && "Wrong data length"); } + + const char *strings_begin() const { return FrameworkStringData.begin(); } + const char *strings_end() const { return FrameworkStringData.end(); } }; } // end anonymous namespace @@ -1328,8 +1304,8 @@ namespace { /// \param HS The header search structure to save. /// /// \param Chain Whether we're creating a chained AST file. -void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, const char* isysroot) { - llvm::SmallVector<const FileEntry *, 16> FilesByUID; +void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, StringRef isysroot) { + SmallVector<const FileEntry *, 16> FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); if (FilesByUID.size() > HS.header_file_size()) @@ -1337,7 +1313,7 @@ void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, const char* isysroot) { HeaderFileInfoTrait GeneratorTrait(*this, HS); OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator; - llvm::SmallVector<const char *, 4> SavedStrings; + SmallVector<const char *, 4> SavedStrings; unsigned NumHeaderSearchEntries = 0; for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { const FileEntry *File = FilesByUID[UID]; @@ -1379,14 +1355,17 @@ void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, const char* isysroot) { Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned TableAbbrev = Stream.EmitAbbrev(Abbrev); - // Write the stat cache + // Write the header search table RecordData Record; Record.push_back(HEADER_SEARCH_TABLE); Record.push_back(BucketOffset); Record.push_back(NumHeaderSearchEntries); + Record.push_back(TableData.size()); + TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end()); Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData.str()); // Free all of the strings we had to duplicate. @@ -1404,7 +1383,7 @@ void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, const char* isysroot) { /// the files in the AST. void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP, - const char *isysroot) { + StringRef isysroot) { RecordData Record; // Enter the source manager block. @@ -1416,43 +1395,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream); unsigned SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream); - // Write the line table. - if (SourceMgr.hasLineTable()) { - LineTableInfo &LineTable = SourceMgr.getLineTable(); - - // Emit the file names - Record.push_back(LineTable.getNumFilenames()); - for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { - // Emit the file name - const char *Filename = LineTable.getFilename(I); - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - unsigned FilenameLen = Filename? strlen(Filename) : 0; - Record.push_back(FilenameLen); - if (FilenameLen) - Record.insert(Record.end(), Filename, Filename + FilenameLen); - } - - // Emit the line entries - for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); - L != LEnd; ++L) { - // Emit the file ID - Record.push_back(L->first); - - // Emit the line entries - Record.push_back(L->second.size()); - for (std::vector<LineEntry>::iterator LE = L->second.begin(), - LEEnd = L->second.end(); - LE != LEEnd; ++LE) { - Record.push_back(LE->FileOffset); - Record.push_back(LE->LineNo); - Record.push_back(LE->FilenameID); - Record.push_back((unsigned)LE->FileKind); - Record.push_back(LE->IncludeOffset); - } - } - Stream.EmitRecord(SM_LINE_TABLE, Record); - } - // Write out the source location entry table. We skip the first // entry, which is always the same dummy entry. std::vector<uint32_t> SLocEntryOffsets; @@ -1460,12 +1402,11 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // We will go through them in ASTReader::validateFileEntries(). std::vector<uint32_t> SLocFileEntryOffsets; RecordData PreloadSLocs; - unsigned BaseSLocID = Chain ? Chain->getTotalNumSLocs() : 0; - SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1 - BaseSLocID); - for (unsigned I = BaseSLocID + 1, N = SourceMgr.sloc_entry_size(); + SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1); + for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { // Get this source location entry. - const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I); + const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); // Record the offset of this source-location entry. SLocEntryOffsets.push_back(Stream.GetCurrentBitNo()); @@ -1483,7 +1424,8 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.clear(); Record.push_back(Code); - Record.push_back(SLoc->getOffset()); + // Starting offset of this entry within this module, so skip the dummy. + Record.push_back(SLoc->getOffset() - 2); if (SLoc->isFile()) { const SrcMgr::FileInfo &File = SLoc->getFile(); Record.push_back(File.getIncludeLoc().getRawEncoding()); @@ -1502,6 +1444,8 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.push_back(Content->OrigEntry->getSize()); Record.push_back(Content->OrigEntry->getModificationTime()); + Record.push_back(File.NumCreatedFIDs); + // Turn the file name into an absolute path, if it isn't already. const char *Filename = Content->OrigEntry->getName(); llvm::SmallString<128> FilePath(Filename); @@ -1528,27 +1472,29 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); const char *Name = Buffer->getBufferIdentifier(); Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, - llvm::StringRef(Name, strlen(Name) + 1)); + StringRef(Name, strlen(Name) + 1)); Record.clear(); Record.push_back(SM_SLOC_BUFFER_BLOB); Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, - llvm::StringRef(Buffer->getBufferStart(), + StringRef(Buffer->getBufferStart(), Buffer->getBufferSize() + 1)); - if (strcmp(Name, "<built-in>") == 0) - PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size()); + if (strcmp(Name, "<built-in>") == 0) { + PreloadSLocs.push_back(SLocEntryOffsets.size()); + } } } else { // The source location entry is a macro expansion. - const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation(); - Record.push_back(Inst.getSpellingLoc().getRawEncoding()); - Record.push_back(Inst.getInstantiationLocStart().getRawEncoding()); - Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding()); + const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion(); + Record.push_back(Expansion.getSpellingLoc().getRawEncoding()); + Record.push_back(Expansion.getExpansionLocStart().getRawEncoding()); + Record.push_back(Expansion.isMacroArgExpansion() ? 0 + : Expansion.getExpansionLocEnd().getRawEncoding()); // Compute the token length for this macro expansion. - unsigned NextOffset = SourceMgr.getNextOffset(); + unsigned NextOffset = SourceMgr.getNextLocalOffset(); if (I + 1 != N) - NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset(); + NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset(); Record.push_back(NextOffset - SLoc->getOffset() - 1); Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record); } @@ -1565,15 +1511,14 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev); Record.clear(); Record.push_back(SOURCE_LOCATION_OFFSETS); Record.push_back(SLocEntryOffsets.size()); - unsigned BaseOffset = Chain ? Chain->getNextSLocOffset() : 0; - Record.push_back(SourceMgr.getNextOffset() - BaseOffset); + Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets)); Abbrev = new BitCodeAbbrev(); @@ -1591,6 +1536,49 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Write the source location entry preloads array, telling the AST // reader which source locations entries it should load eagerly. Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs); + + // Write the line table. It depends on remapping working, so it must come + // after the source location offsets. + if (SourceMgr.hasLineTable()) { + LineTableInfo &LineTable = SourceMgr.getLineTable(); + + Record.clear(); + // Emit the file names + Record.push_back(LineTable.getNumFilenames()); + for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { + // Emit the file name + const char *Filename = LineTable.getFilename(I); + Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); + unsigned FilenameLen = Filename? strlen(Filename) : 0; + Record.push_back(FilenameLen); + if (FilenameLen) + Record.insert(Record.end(), Filename, Filename + FilenameLen); + } + + // Emit the line entries + for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); + L != LEnd; ++L) { + // Only emit entries for local files. + if (L->first < 0) + continue; + + // Emit the file ID + Record.push_back(L->first); + + // Emit the line entries + Record.push_back(L->second.size()); + for (std::vector<LineEntry>::iterator LE = L->second.begin(), + LEEnd = L->second.end(); + LE != LEEnd; ++LE) { + Record.push_back(LE->FileOffset); + Record.push_back(LE->LineNo); + Record.push_back(LE->FilenameID); + Record.push_back((unsigned)LE->FileKind); + Record.push_back(LE->IncludeOffset); + } + } + Stream.EmitRecord(SOURCE_MANAGER_LINE_TABLE, Record); + } } //===----------------------------------------------------------------------===// @@ -1608,7 +1596,11 @@ static int compareMacroDefinitions(const void *XPtr, const void *YPtr) { /// \brief Writes the block containing the serialized form of the /// preprocessor. /// -void ASTWriter::WritePreprocessor(const Preprocessor &PP) { +void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { + PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); + if (PPRec) + WritePreprocessorDetail(*PPRec); + RecordData Record; // If the preprocessor __COUNTER__ value has been bumped, remember it. @@ -1629,17 +1621,18 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { // Loop over all the macro definitions that are live at the end of the file, // emitting each to the PP section. - PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); // Construct the list of macro definitions that need to be serialized. - llvm::SmallVector<std::pair<const IdentifierInfo *, MacroInfo *>, 2> + SmallVector<std::pair<const IdentifierInfo *, MacroInfo *>, 2> MacrosToEmit; llvm::SmallPtrSet<const IdentifierInfo*, 4> MacroDefinitionsSeen; for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0), E = PP.macro_end(Chain == 0); I != E; ++I) { - MacroDefinitionsSeen.insert(I->first); - MacrosToEmit.push_back(std::make_pair(I->first, I->second)); + if (!IsModule || I->second->isExported()) { + MacroDefinitionsSeen.insert(I->first); + MacrosToEmit.push_back(std::make_pair(I->first, I->second)); + } } // Sort the set of macro definitions that need to be serialized by the @@ -1671,14 +1664,15 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { // chained PCH, by storing the offset into the original PCH rather than // writing the macro definition a second time. if (MI->isBuiltinMacro() || - (Chain && Name->isFromAST() && MI->isFromAST())) + (Chain && Name->isFromAST() && MI->isFromAST() && + !MI->hasChangedAfterLoad())) continue; AddIdentifierRef(Name, Record); MacroOffsets[Name] = Stream.GetCurrentBitNo(); Record.push_back(MI->getDefinitionLoc().getRawEncoding()); Record.push_back(MI->isUsed()); - + AddSourceLocation(MI->getExportLocation(), Record); unsigned Code; if (MI->isObjectLike()) { Code = PP_MACRO_OBJECT_LIKE; @@ -1696,7 +1690,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { // If we have a detailed preprocessing record, record the macro definition // ID that corresponds to this macro. if (PPRec) - Record.push_back(getMacroDefinitionID(PPRec->findMacroDefinition(MI))); + Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); Stream.EmitRecord(Code, Record); Record.clear(); @@ -1725,15 +1719,14 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { ++NumMacros; } Stream.ExitBlock(); - - if (PPRec) - WritePreprocessorDetail(*PPRec); } void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { - if (PPRec.begin(Chain) == PPRec.end(Chain)) + if (PPRec.local_begin() == PPRec.local_end()) return; - + + SmallVector<PPEntityOffset, 64> PreprocessedEntityOffsets; + // Enter the preprocessor block. Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3); @@ -1746,9 +1739,6 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { { BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // start location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // end location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind @@ -1756,65 +1746,41 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { InclusionAbbrev = Stream.EmitAbbrev(Abbrev); } - unsigned IndexBase = Chain ? PPRec.getNumPreallocatedEntities() : 0; + unsigned FirstPreprocessorEntityID + = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0) + + NUM_PREDEF_PP_ENTITY_IDS; + unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID; RecordData Record; - for (PreprocessingRecord::iterator E = PPRec.begin(Chain), - EEnd = PPRec.end(Chain); - E != EEnd; ++E) { + for (PreprocessingRecord::iterator E = PPRec.local_begin(), + EEnd = PPRec.local_end(); + E != EEnd; + (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) { Record.clear(); + PreprocessedEntityOffsets.push_back(PPEntityOffset((*E)->getSourceRange(), + Stream.GetCurrentBitNo())); + if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) { - // Record this macro definition's location. - MacroID ID = getMacroDefinitionID(MD); - - // Don't write the macro definition if it is from another AST file. - if (ID < FirstMacroID) - continue; + // Record this macro definition's ID. + MacroDefinitions[MD] = NextPreprocessorEntityID; - // Notify the serialization listener that we're serializing this entity. - if (SerializationListener) - SerializationListener->SerializedPreprocessedEntity(*E, - Stream.GetCurrentBitNo()); - - unsigned Position = ID - FirstMacroID; - if (Position != MacroDefinitionOffsets.size()) { - if (Position > MacroDefinitionOffsets.size()) - MacroDefinitionOffsets.resize(Position + 1); - - MacroDefinitionOffsets[Position] = Stream.GetCurrentBitNo(); - } else - MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo()); - - Record.push_back(IndexBase + NumPreprocessingRecords++); - Record.push_back(ID); - AddSourceLocation(MD->getSourceRange().getBegin(), Record); - AddSourceLocation(MD->getSourceRange().getEnd(), Record); AddIdentifierRef(MD->getName(), Record); - AddSourceLocation(MD->getLocation(), Record); Stream.EmitRecord(PPD_MACRO_DEFINITION, Record); continue; } - // Notify the serialization listener that we're serializing this entity. - if (SerializationListener) - SerializationListener->SerializedPreprocessedEntity(*E, - Stream.GetCurrentBitNo()); - if (MacroExpansion *ME = dyn_cast<MacroExpansion>(*E)) { - Record.push_back(IndexBase + NumPreprocessingRecords++); - AddSourceLocation(ME->getSourceRange().getBegin(), Record); - AddSourceLocation(ME->getSourceRange().getEnd(), Record); - AddIdentifierRef(ME->getName(), Record); - Record.push_back(getMacroDefinitionID(ME->getDefinition())); + Record.push_back(ME->isBuiltinMacro()); + if (ME->isBuiltinMacro()) + AddIdentifierRef(ME->getName(), Record); + else + Record.push_back(MacroDefinitions[ME->getDefinition()]); Stream.EmitRecord(PPD_MACRO_EXPANSION, Record); continue; } if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) { Record.push_back(PPD_INCLUSION_DIRECTIVE); - Record.push_back(IndexBase + NumPreprocessingRecords++); - AddSourceLocation(ID->getSourceRange().getBegin(), Record); - AddSourceLocation(ID->getSourceRange().getEnd(), Record); Record.push_back(ID->getFileName().size()); Record.push_back(ID->wasInQuotes()); Record.push_back(static_cast<unsigned>(ID->getKind())); @@ -1831,40 +1797,39 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { // Write the offsets table for the preprocessing record. if (NumPreprocessingRecords > 0) { + assert(PreprocessedEntityOffsets.size() == NumPreprocessingRecords); + // Write the offsets table for identifier IDs. using namespace llvm; BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(MACRO_DEFINITION_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of records - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macro defs + Abbrev->Add(BitCodeAbbrevOp(PPD_ENTITIES_OFFSETS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first pp entity Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MacroDefOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + unsigned PPEOffsetAbbrev = Stream.EmitAbbrev(Abbrev); Record.clear(); - Record.push_back(MACRO_DEFINITION_OFFSETS); - Record.push_back(NumPreprocessingRecords); - Record.push_back(MacroDefinitionOffsets.size()); - Stream.EmitRecordWithBlob(MacroDefOffsetAbbrev, Record, - data(MacroDefinitionOffsets)); + Record.push_back(PPD_ENTITIES_OFFSETS); + Record.push_back(FirstPreprocessorEntityID - NUM_PREDEF_PP_ENTITY_IDS); + Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record, + data(PreprocessedEntityOffsets)); } } -void ASTWriter::WritePragmaDiagnosticMappings(const Diagnostic &Diag) { +void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag) { RecordData Record; - for (Diagnostic::DiagStatePointsTy::const_iterator + for (DiagnosticsEngine::DiagStatePointsTy::const_iterator I = Diag.DiagStatePoints.begin(), E = Diag.DiagStatePoints.end(); I != E; ++I) { - const Diagnostic::DiagStatePoint &point = *I; + const DiagnosticsEngine::DiagStatePoint &point = *I; if (point.Loc.isInvalid()) continue; Record.push_back(point.Loc.getRawEncoding()); - for (Diagnostic::DiagState::iterator + for (DiagnosticsEngine::DiagState::const_iterator I = point.State->begin(), E = point.State->end(); I != E; ++I) { - unsigned diag = I->first, map = I->second; - if (map & 0x10) { // mapping from a diagnostic pragma. - Record.push_back(diag); - Record.push_back(map & 0x7); + if (I->second.isPragma()) { + Record.push_back(I->first); + Record.push_back(I->second.getMapping()); } } Record.push_back(-1); // mark the end of the diag/map pairs for this @@ -1890,7 +1855,7 @@ void ASTWriter::WriteCXXBaseSpecifiersOffsets() { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned BaseSpecifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - // Write the selector offsets table. + // Write the base specifier offsets table. Record.clear(); Record.push_back(CXX_BASE_SPECIFIER_OFFSETS); Record.push_back(CXXBaseSpecifiersOffsets.size()); @@ -1964,7 +1929,7 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, uint64_t Offset = Stream.GetCurrentBitNo(); RecordData Record; Record.push_back(DECL_CONTEXT_LEXICAL); - llvm::SmallVector<KindDeclIDPair, 64> Decls; + SmallVector<KindDeclIDPair, 64> Decls; for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); D != DEnd; ++D) Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D))); @@ -1982,22 +1947,26 @@ void ASTWriter::WriteTypeDeclOffsets() { BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base type index Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev); Record.clear(); Record.push_back(TYPE_OFFSET); Record.push_back(TypeOffsets.size()); + Record.push_back(FirstTypeID - NUM_PREDEF_TYPE_IDS); Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, data(TypeOffsets)); // Write the declaration offsets array Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base decl ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev); Record.clear(); Record.push_back(DECL_OFFSET); Record.push_back(DeclOffsets.size()); + Record.push_back(FirstDeclID - NUM_PREDEF_DECL_IDS); Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets)); } @@ -2027,7 +1996,7 @@ public: } std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, Selector Sel, + EmitKeyDataLength(raw_ostream& Out, Selector Sel, data_type_ref Methods) { unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); clang::io::Emit16(Out, KeyLen); @@ -2044,7 +2013,7 @@ public: return std::make_pair(KeyLen, DataLen); } - void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) { + void EmitKey(raw_ostream& Out, Selector Sel, unsigned) { uint64_t Start = Out.tell(); assert((Start >> 32) == 0 && "Selector key offset too large"); Writer.SetSelectorOffset(Sel, Start); @@ -2057,7 +2026,7 @@ public: Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); } - void EmitData(llvm::raw_ostream& Out, key_type_ref, + void EmitData(raw_ostream& Out, key_type_ref, data_type_ref Methods, unsigned DataLen) { uint64_t Start = Out.tell(); (void)Start; clang::io::Emit32(Out, Methods.ID); @@ -2130,12 +2099,12 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { bool changed = false; for (ObjCMethodList *M = &Data.Instance; !changed && M && M->Method; M = M->Next) { - if (M->Method->getPCHLevel() == 0) + if (!M->Method->isFromASTFile()) changed = true; } for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method; M = M->Next) { - if (M->Method->getPCHLevel() == 0) + if (!M->Method->isFromASTFile()) changed = true; } if (!changed) @@ -2177,6 +2146,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev); @@ -2184,6 +2154,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { Record.clear(); Record.push_back(SELECTOR_OFFSETS); Record.push_back(SelectorOffsets.size()); + Record.push_back(FirstSelectorID - NUM_PREDEF_SELECTOR_IDS); Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, data(SelectorOffsets)); } @@ -2219,41 +2190,53 @@ namespace { class ASTIdentifierTableTrait { ASTWriter &Writer; Preprocessor &PP; - + bool IsModule; + /// \brief Determines whether this is an "interesting" identifier /// that needs a full IdentifierInfo structure written into the hash /// table. - static bool isInterestingIdentifier(const IdentifierInfo *II) { - return II->isPoisoned() || - II->isExtensionToken() || - II->hasMacroDefinition() || - II->getObjCOrBuiltinID() || - II->getFETokenInfo<void>(); + bool isInterestingIdentifier(IdentifierInfo *II, MacroInfo *&Macro) { + if (II->isPoisoned() || + II->isExtensionToken() || + II->getObjCOrBuiltinID() || + II->getFETokenInfo<void>()) + return true; + + return hasMacroDefinition(II, Macro); + } + + bool hasMacroDefinition(IdentifierInfo *II, MacroInfo *&Macro) { + if (!II->hasMacroDefinition()) + return false; + + if (Macro || (Macro = PP.getMacroInfo(II))) + return !Macro->isBuiltinMacro() && (!IsModule || Macro->isExported()); + + return false; } public: - typedef const IdentifierInfo* key_type; + typedef IdentifierInfo* key_type; typedef key_type key_type_ref; typedef IdentID data_type; typedef data_type data_type_ref; - ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP) - : Writer(Writer), PP(PP) { } + ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, bool IsModule) + : Writer(Writer), PP(PP), IsModule(IsModule) { } static unsigned ComputeHash(const IdentifierInfo* II) { return llvm::HashString(II->getName()); } std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II, - IdentID ID) { + EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { unsigned KeyLen = II->getLength() + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 - if (isInterestingIdentifier(II)) { + MacroInfo *Macro = 0; + if (isInterestingIdentifier(II, Macro)) { DataLen += 2; // 2 bytes for builtin ID, flags - if (II->hasMacroDefinition() && - !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro()) + if (hasMacroDefinition(II, Macro)) DataLen += 4; for (IdentifierResolver::iterator D = IdentifierResolver::begin(II), DEnd = IdentifierResolver::end(); @@ -2268,7 +2251,7 @@ public: return std::make_pair(KeyLen, DataLen); } - void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II, + void EmitKey(raw_ostream& Out, const IdentifierInfo* II, unsigned KeyLen) { // Record the location of the key data. This is used when generating // the mapping from persistent IDs to strings. @@ -2276,27 +2259,26 @@ public: Out.write(II->getNameStart(), KeyLen); } - void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II, + void EmitData(raw_ostream& Out, IdentifierInfo* II, IdentID ID, unsigned) { - if (!isInterestingIdentifier(II)) { + MacroInfo *Macro = 0; + if (!isInterestingIdentifier(II, Macro)) { clang::io::Emit32(Out, ID << 1); return; } clang::io::Emit32(Out, (ID << 1) | 0x01); uint32_t Bits = 0; - bool hasMacroDefinition = - II->hasMacroDefinition() && - !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro(); + bool HasMacroDefinition = hasMacroDefinition(II, Macro); Bits = (uint32_t)II->getObjCOrBuiltinID(); - Bits = (Bits << 1) | unsigned(hasMacroDefinition); + Bits = (Bits << 1) | unsigned(HasMacroDefinition); Bits = (Bits << 1) | unsigned(II->isExtensionToken()); Bits = (Bits << 1) | unsigned(II->isPoisoned()); Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); clang::io::Emit16(Out, Bits); - if (hasMacroDefinition) + if (HasMacroDefinition) clang::io::Emit32(Out, Writer.getMacroOffset(II)); // Emit the declaration IDs in reverse order, because the @@ -2306,9 +2288,9 @@ public: // adds declarations to the end of the list (so we need to see the // struct "status" before the function "status"). // Only emit declarations that aren't from a chained PCH, though. - llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II), + SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II), IdentifierResolver::end()); - for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(), + for (SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(), DEnd = Decls.rend(); D != DEnd; ++D) clang::io::Emit32(Out, Writer.getDeclID(*D)); @@ -2321,14 +2303,14 @@ public: /// The identifier table consists of a blob containing string data /// (the actual identifiers themselves) and a separate "offsets" index /// that maps identifier IDs to locations within the blob. -void ASTWriter::WriteIdentifierTable(Preprocessor &PP) { +void ASTWriter::WriteIdentifierTable(Preprocessor &PP, bool IsModule) { using namespace llvm; // Create and write out the blob that contains the identifier // strings. { OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; - ASTIdentifierTableTrait Trait(*this, PP); + ASTIdentifierTableTrait Trait(*this, PP, IsModule); // Look for any identifiers that were named while processing the // headers, but are otherwise not needed. We add these to the hash @@ -2348,14 +2330,15 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) { ID != IDEnd; ++ID) { assert(ID->first && "NULL identifier in identifier table"); if (!Chain || !ID->first->isFromAST()) - Generator.insert(ID->first, ID->second, Trait); + Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second, + Trait); } // Create the on-disk hash table in a buffer. llvm::SmallString<4096> IdentifierTable; uint32_t BucketOffset; { - ASTIdentifierTableTrait Trait(*this, PP); + ASTIdentifierTableTrait Trait(*this, PP, IsModule); llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 clang::io::Emit32(Out, 0); @@ -2380,12 +2363,14 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) { BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); RecordData Record; Record.push_back(IDENTIFIER_OFFSET); Record.push_back(IdentifierOffsets.size()); + Record.push_back(FirstIdentID - NUM_PREDEF_IDENT_IDS); Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, data(IdentifierOffsets)); } @@ -2424,7 +2409,6 @@ public: case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: - ID.AddInteger(Writer.GetOrCreateTypeID(Name.getCXXNameType())); break; case DeclarationName::CXXOperatorName: ID.AddInteger(Name.getCXXOverloadedOperator()); @@ -2439,7 +2423,7 @@ public: } std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, DeclarationName Name, + EmitKeyDataLength(raw_ostream& Out, DeclarationName Name, data_type_ref Lookup) { unsigned KeyLen = 1; switch (Name.getNameKind()) { @@ -2447,15 +2431,15 @@ public: case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXLiteralOperatorName: KeyLen += 4; break; case DeclarationName::CXXOperatorName: KeyLen += 1; break; + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXUsingDirective: break; } @@ -2468,7 +2452,7 @@ public: return std::make_pair(KeyLen, DataLen); } - void EmitKey(llvm::raw_ostream& Out, DeclarationName Name, unsigned) { + void EmitKey(raw_ostream& Out, DeclarationName Name, unsigned) { using namespace clang::io; assert(Name.getNameKind() < 0x100 && "Invalid name kind ?"); @@ -2482,11 +2466,6 @@ public: case DeclarationName::ObjCMultiArgSelector: Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector())); break; - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - Emit32(Out, Writer.getTypeID(Name.getCXXNameType())); - break; case DeclarationName::CXXOperatorName: assert(Name.getCXXOverloadedOperator() < 0x100 && "Invalid operator ?"); Emit8(Out, Name.getCXXOverloadedOperator()); @@ -2494,12 +2473,15 @@ public: case DeclarationName::CXXLiteralOperatorName: Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier())); break; + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXUsingDirective: break; } } - void EmitData(llvm::raw_ostream& Out, key_type_ref, + void EmitData(raw_ostream& Out, key_type_ref, data_type Lookup, unsigned DataLen) { uint64_t Start = Out.tell(); (void)Start; clang::io::Emit16(Out, Lookup.second - Lookup.first); @@ -2534,9 +2516,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, return 0; // Force the DeclContext to build a its name-lookup table. - if (DC->hasExternalVisibleStorage()) - DC->MaterializeVisibleDeclsFromExternalStorage(); - else + if (!DC->hasExternalVisibleStorage()) DC->lookup(DeclarationName()); // Serialize the contents of the mapping used for lookup. Note that, @@ -2553,13 +2533,37 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, ASTDeclContextNameLookupTrait Trait(*this); // Create the on-disk hash table representation. + DeclarationName ConversionName; + llvm::SmallVector<NamedDecl *, 4> ConversionDecls; for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); D != DEnd; ++D) { DeclarationName Name = D->first; DeclContext::lookup_result Result = D->second.getLookupResult(); - Generator.insert(Name, Result, Trait); + if (Result.first != Result.second) { + if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + // Hash all conversion function names to the same name. The actual + // type information in conversion function name is not used in the + // key (since such type information is not stable across different + // modules), so the intended effect is to coalesce all of the conversion + // functions under a single key. + if (!ConversionName) + ConversionName = Name; + ConversionDecls.append(Result.first, Result.second); + continue; + } + + Generator.insert(Name, Result, Trait); + } } + // Add the conversion functions + if (!ConversionDecls.empty()) { + Generator.insert(ConversionName, + DeclContext::lookup_result(ConversionDecls.begin(), + ConversionDecls.end()), + Trait); + } + // Create the on-disk hash table in a buffer. llvm::SmallString<4096> LookupTable; uint32_t BucketOffset; @@ -2602,7 +2606,8 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { DeclContext::lookup_result Result = D->second.getLookupResult(); // For any name that appears in this table, the results are complete, i.e. // they overwrite results from previous PCHs. Merging is always a mess. - Generator.insert(Name, Result, Trait); + if (Result.first != Result.second) + Generator.insert(Name, Result, Trait); } // Create the on-disk hash table in a buffer. @@ -2652,14 +2657,14 @@ void ASTWriter::WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record) { for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){ const Attr * A = *i; Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs - AddSourceLocation(A->getLocation(), Record); + AddSourceRange(A->getRange(), Record); #include "clang/Serialization/AttrPCHWrite.inc" } } -void ASTWriter::AddString(llvm::StringRef Str, RecordDataImpl &Record) { +void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { Record.push_back(Str.size()); Record.insert(Record.end(), Str.begin(), Str.end()); } @@ -2700,15 +2705,15 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { } ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) - : Stream(Stream), Chain(0), SerializationListener(0), - FirstDeclID(1), NextDeclID(FirstDeclID), + : Stream(Stream), Context(0), Chain(0), WritingAST(false), + FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), - FirstIdentID(1), NextIdentID(FirstIdentID), FirstSelectorID(1), - NextSelectorID(FirstSelectorID), FirstMacroID(1), NextMacroID(FirstMacroID), + FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), NumVisibleDeclContexts(0), - FirstCXXBaseSpecifiersID(1), NextCXXBaseSpecifiersID(1), + NextCXXBaseSpecifiersID(1), DeclParmVarAbbrev(0), DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0), UpdateVisibleAbbrev(0), DeclRefExprAbbrev(0), CharacterLiteralAbbrev(0), @@ -2721,7 +2726,9 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, const std::string &OutputFile, - const char *isysroot) { + bool IsModule, StringRef isysroot) { + WritingAST = true; + // Emit the file header. Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'P', 8); @@ -2730,30 +2737,53 @@ void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, WriteBlockInfoBlock(); - if (Chain) - WriteASTChain(SemaRef, StatCalls, isysroot); - else - WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile); + Context = &SemaRef.Context; + WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, IsModule); + Context = 0; + + WritingAST = false; +} + +template<typename Vector> +static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, + ASTWriter::RecordData &Record) { + for (typename Vector::iterator I = Vec.begin(0, true), E = Vec.end(); + I != E; ++I) { + Writer.AddDeclRef(*I, Record); + } } void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot, - const std::string &OutputFile) { + StringRef isysroot, + const std::string &OutputFile, bool IsModule) { using namespace llvm; ASTContext &Context = SemaRef.Context; Preprocessor &PP = SemaRef.PP; - // The translation unit is the first declaration we'll emit. - DeclIDs[Context.getTranslationUnitDecl()] = 1; - ++NextDeclID; - DeclTypesToEmit.push(Context.getTranslationUnitDecl()); - - // Make sure that we emit IdentifierInfos (and any attached - // declarations) for builtins. - { + // Set up predefined declaration IDs. + DeclIDs[Context.getTranslationUnitDecl()] = PREDEF_DECL_TRANSLATION_UNIT_ID; + if (Context.ObjCIdDecl) + DeclIDs[Context.ObjCIdDecl] = PREDEF_DECL_OBJC_ID_ID; + if (Context.ObjCSelDecl) + DeclIDs[Context.ObjCSelDecl] = PREDEF_DECL_OBJC_SEL_ID; + if (Context.ObjCClassDecl) + DeclIDs[Context.ObjCClassDecl] = PREDEF_DECL_OBJC_CLASS_ID; + if (Context.Int128Decl) + DeclIDs[Context.Int128Decl] = PREDEF_DECL_INT_128_ID; + if (Context.UInt128Decl) + DeclIDs[Context.UInt128Decl] = PREDEF_DECL_UNSIGNED_INT_128_ID; + if (Context.ObjCInstanceTypeDecl) + DeclIDs[Context.ObjCInstanceTypeDecl] = PREDEF_DECL_OBJC_INSTANCETYPE_ID; + + if (!Chain) { + // Make sure that we emit IdentifierInfos (and any attached + // declarations) for builtins. We don't need to do this when we're + // emitting chained PCH files, because all of the builtins will be + // in the original PCH file. + // FIXME: Modules won't like this at all. IdentifierTable &Table = PP.getIdentifierTable(); - llvm::SmallVector<const char *, 32> BuiltinNames; + SmallVector<const char *, 32> BuiltinNames; Context.BuiltinInfo.GetBuiltinNames(BuiltinNames, Context.getLangOptions().NoBuiltin); for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I) @@ -2764,24 +2794,24 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, // TentativeDefinitions order. Generally, this record will be empty for // headers. RecordData TentativeDefinitions; - for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) { - AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions); - } - + AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); + // Build a record containing all of the file scoped decls in this file. RecordData UnusedFileScopedDecls; - for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i) - AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls); + AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, + UnusedFileScopedDecls); + // Build a record containing all of the delegating constructors we still need + // to resolve. RecordData DelegatingCtorDecls; - for (unsigned i=0, e = SemaRef.DelegatingCtorDecls.size(); i != e; ++i) - AddDeclRef(SemaRef.DelegatingCtorDecls[i], DelegatingCtorDecls); + AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); + // Write the set of weak, undeclared identifiers. We always write the + // entire table, since later PCH files in a PCH chain are only interested in + // the results at the end of the chain. RecordData WeakUndeclaredIdentifiers; if (!SemaRef.WeakUndeclaredIdentifiers.empty()) { - WeakUndeclaredIdentifiers.push_back( - SemaRef.WeakUndeclaredIdentifiers.size()); - for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator + for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I = SemaRef.WeakUndeclaredIdentifiers.begin(), E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) { AddIdentifierRef(I->first, WeakUndeclaredIdentifiers); @@ -2800,18 +2830,18 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator TD = SemaRef.LocallyScopedExternalDecls.begin(), TDEnd = SemaRef.LocallyScopedExternalDecls.end(); - TD != TDEnd; ++TD) - AddDeclRef(TD->second, LocallyScopedExternalDecls); - + TD != TDEnd; ++TD) { + if (!TD->second->isFromASTFile()) + AddDeclRef(TD->second, LocallyScopedExternalDecls); + } + // Build a record containing all of the ext_vector declarations. RecordData ExtVectorDecls; - for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) - AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls); + AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); // Build a record containing all of the VTable uses information. RecordData VTableUses; if (!SemaRef.VTableUses.empty()) { - VTableUses.push_back(SemaRef.VTableUses.size()); for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); @@ -2821,8 +2851,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, // Build a record containing all of dynamic classes declarations. RecordData DynamicClasses; - for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I) - AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses); + AddLazyVectorDecls(*this, SemaRef.DynamicClasses, DynamicClasses); // Build a record containing all of pending implicit instantiations. RecordData PendingInstantiations; @@ -2862,155 +2891,65 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Stream.EnterSubblock(AST_BLOCK_ID, 5); WriteMetadata(Context, isysroot, OutputFile); WriteLanguageOptions(Context.getLangOptions()); - if (StatCalls && !isysroot) + if (StatCalls && isysroot.empty()) WriteStatCache(*StatCalls); WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); - // Write the record of special types. - Record.clear(); - - AddTypeRef(Context.getBuiltinVaListType(), Record); - AddTypeRef(Context.getObjCIdType(), Record); - AddTypeRef(Context.getObjCSelType(), Record); - AddTypeRef(Context.getObjCProtoType(), Record); - AddTypeRef(Context.getObjCClassType(), Record); - AddTypeRef(Context.getRawCFConstantStringType(), Record); - AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record); - AddTypeRef(Context.getFILEType(), Record); - AddTypeRef(Context.getjmp_bufType(), Record); - AddTypeRef(Context.getsigjmp_bufType(), Record); - AddTypeRef(Context.ObjCIdRedefinitionType, Record); - AddTypeRef(Context.ObjCClassRedefinitionType, Record); - AddTypeRef(Context.getRawBlockdescriptorType(), Record); - AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record); - AddTypeRef(Context.ObjCSelRedefinitionType, Record); - AddTypeRef(Context.getRawNSConstantStringType(), Record); - Record.push_back(Context.isInt128Installed()); - AddTypeRef(Context.AutoDeductTy, Record); - AddTypeRef(Context.AutoRRefDeductTy, Record); - Stream.EmitRecord(SPECIAL_TYPES, Record); - - // Keep writing types and declarations until all types and - // declarations have been written. - Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); - WriteDeclsBlockAbbrevs(); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - Stream.ExitBlock(); - - WritePreprocessor(PP); - WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); - WriteSelectors(SemaRef); - WriteReferencedSelectorsPool(SemaRef); - WriteIdentifierTable(PP); - WriteFPPragmaOptions(SemaRef.getFPOptions()); - WriteOpenCLExtensions(SemaRef); - - WriteTypeDeclOffsets(); - WritePragmaDiagnosticMappings(Context.getDiagnostics()); - - WriteCXXBaseSpecifiersOffsets(); - - // Write the record containing external, unnamed definitions. - if (!ExternalDefinitions.empty()) - Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions); - - // Write the record containing tentative definitions. - if (!TentativeDefinitions.empty()) - Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); - - // Write the record containing unused file scoped decls. - if (!UnusedFileScopedDecls.empty()) - Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); - - // Write the record containing weak undeclared identifiers. - if (!WeakUndeclaredIdentifiers.empty()) - Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, - WeakUndeclaredIdentifiers); - - // Write the record containing locally-scoped external definitions. - if (!LocallyScopedExternalDecls.empty()) - Stream.EmitRecord(LOCALLY_SCOPED_EXTERNAL_DECLS, - LocallyScopedExternalDecls); - - // Write the record containing ext_vector type names. - if (!ExtVectorDecls.empty()) - Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); - - // Write the record containing VTable uses information. - if (!VTableUses.empty()) - Stream.EmitRecord(VTABLE_USES, VTableUses); - - // Write the record containing dynamic classes declarations. - if (!DynamicClasses.empty()) - Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses); - - // Write the record containing pending implicit instantiations. - if (!PendingInstantiations.empty()) - Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); - - // Write the record containing declaration references of Sema. - if (!SemaDeclRefs.empty()) - Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); - - // Write the record containing CUDA-specific declaration references. - if (!CUDASpecialDeclRefs.empty()) - Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); - // Write the delegating constructors. - if (!DelegatingCtorDecls.empty()) - Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); - - // Write the known namespaces. - if (!KnownNamespaces.empty()) - Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); - - // Some simple statistics - Record.clear(); - Record.push_back(NumStatements); - Record.push_back(NumMacros); - Record.push_back(NumLexicalDeclContexts); - Record.push_back(NumVisibleDeclContexts); - Stream.EmitRecord(STATISTICS, Record); - Stream.ExitBlock(); -} - -void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot) { - using namespace llvm; - - ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - - RecordData Record; - Stream.EnterSubblock(AST_BLOCK_ID, 5); - WriteMetadata(Context, isysroot, ""); - if (StatCalls && !isysroot) - WriteStatCache(*StatCalls); - // FIXME: Source manager block should only write new stuff, which could be - // done by tracking the largest ID in the chain - WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); - - // The special types are in the chained PCH. + if (Chain) { + // Write the mapping information describing our module dependencies and how + // each of those modules were mapped into our own offset/ID space, so that + // the reader can build the appropriate mapping to its own offset/ID space. + // The map consists solely of a blob with the following format: + // *(module-name-len:i16 module-name:len*i8 + // source-location-offset:i32 + // identifier-id:i32 + // preprocessed-entity-id:i32 + // macro-definition-id:i32 + // selector-id:i32 + // declaration-id:i32 + // c++-base-specifiers-id:i32 + // type-id:i32) + // + llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(Abbrev); + llvm::SmallString<2048> Buffer; + { + llvm::raw_svector_ostream Out(Buffer); + for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(), + MEnd = Chain->ModuleMgr.end(); + M != MEnd; ++M) { + StringRef FileName = (*M)->FileName; + io::Emit16(Out, FileName.size()); + Out.write(FileName.data(), FileName.size()); + io::Emit32(Out, (*M)->SLocEntryBaseOffset); + io::Emit32(Out, (*M)->BaseIdentifierID); + io::Emit32(Out, (*M)->BasePreprocessedEntityID); + io::Emit32(Out, (*M)->BaseSelectorID); + io::Emit32(Out, (*M)->BaseDeclID); + io::Emit32(Out, (*M)->BaseTypeIndex); + } + } + Record.clear(); + Record.push_back(MODULE_OFFSET_MAP); + Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record, + Buffer.data(), Buffer.size()); + } - // We don't start with the translation unit, but with its decls that - // don't come from the chained PCH. + // Create a lexical update block containing all of the declarations in the + // translation unit that do not come from other AST files. const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - llvm::SmallVector<KindDeclIDPair, 64> NewGlobalDecls; + SmallVector<KindDeclIDPair, 64> NewGlobalDecls; for (DeclContext::decl_iterator I = TU->noload_decls_begin(), E = TU->noload_decls_end(); I != E; ++I) { - if ((*I)->getPCHLevel() == 0) + if (!(*I)->isFromASTFile()) NewGlobalDecls.push_back(std::make_pair((*I)->getKind(), GetDeclRef(*I))); else if ((*I)->isChangedSinceDeserialization()) (void)GetDeclRef(*I); // Make sure it's written, but don't record it. } - // We also need to write a lexical updates block for the TU. + llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev(); Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); @@ -3019,7 +2958,8 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, Record.push_back(TU_UPDATE_LEXICAL); Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, data(NewGlobalDecls)); - // And a visible updates block for the DeclContexts. + + // And a visible updates block for the translation unit. Abv = new llvm::BitCodeAbbrev(); Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); @@ -3027,108 +2967,41 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv); WriteDeclContextVisibleUpdate(TU); - - // Build a record containing all of the new tentative definitions in this - // file, in TentativeDefinitions order. - RecordData TentativeDefinitions; - for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) { - if (SemaRef.TentativeDefinitions[i]->getPCHLevel() == 0) - AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions); - } - - // Build a record containing all of the file scoped decls in this file. - RecordData UnusedFileScopedDecls; - for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i) { - if (SemaRef.UnusedFileScopedDecls[i]->getPCHLevel() == 0) - AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls); - } - - // Build a record containing all of the delegating constructor decls in this - // file. - RecordData DelegatingCtorDecls; - for (unsigned i=0, e = SemaRef.DelegatingCtorDecls.size(); i != e; ++i) { - if (SemaRef.DelegatingCtorDecls[i]->getPCHLevel() == 0) - AddDeclRef(SemaRef.DelegatingCtorDecls[i], DelegatingCtorDecls); - } - - // We write the entire table, overwriting the tables from the chain. - RecordData WeakUndeclaredIdentifiers; - if (!SemaRef.WeakUndeclaredIdentifiers.empty()) { - WeakUndeclaredIdentifiers.push_back( - SemaRef.WeakUndeclaredIdentifiers.size()); - for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator - I = SemaRef.WeakUndeclaredIdentifiers.begin(), - E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) { - AddIdentifierRef(I->first, WeakUndeclaredIdentifiers); - AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers); - AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers); - WeakUndeclaredIdentifiers.push_back(I->second.getUsed()); - } - } - - // Build a record containing all of the locally-scoped external - // declarations in this header file. Generally, this record will be - // empty. - RecordData LocallyScopedExternalDecls; - // FIXME: This is filling in the AST file in densemap order which is - // nondeterminstic! - for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator - TD = SemaRef.LocallyScopedExternalDecls.begin(), - TDEnd = SemaRef.LocallyScopedExternalDecls.end(); - TD != TDEnd; ++TD) { - if (TD->second->getPCHLevel() == 0) - AddDeclRef(TD->second, LocallyScopedExternalDecls); - } - - // Build a record containing all of the ext_vector declarations. - RecordData ExtVectorDecls; - for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) { - if (SemaRef.ExtVectorDecls[I]->getPCHLevel() == 0) - AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls); - } - - // Build a record containing all of the VTable uses information. - // We write everything here, because it's too hard to determine whether - // a use is new to this part. - RecordData VTableUses; - if (!SemaRef.VTableUses.empty()) { - VTableUses.push_back(SemaRef.VTableUses.size()); - for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { - AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); - AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); - VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); + + // If the translation unit has an anonymous namespace, and we don't already + // have an update block for it, write it as an update block. + if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { + ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; + if (Record.empty()) { + Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); + Record.push_back(reinterpret_cast<uint64_t>(NS)); } } - - // Build a record containing all of dynamic classes declarations. - RecordData DynamicClasses; - for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I) - if (SemaRef.DynamicClasses[I]->getPCHLevel() == 0) - AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses); - - // Build a record containing all of pending implicit instantiations. - RecordData PendingInstantiations; - for (std::deque<Sema::PendingImplicitInstantiation>::iterator - I = SemaRef.PendingInstantiations.begin(), - N = SemaRef.PendingInstantiations.end(); I != N; ++I) { - AddDeclRef(I->first, PendingInstantiations); - AddSourceLocation(I->second, PendingInstantiations); - } - assert(SemaRef.PendingLocalImplicitInstantiations.empty() && - "There are local ones at end of translation unit!"); - - // Build a record containing some declaration references. - // It's not worth the effort to avoid duplication here. - RecordData SemaDeclRefs; - if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) { - AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs); - } - + + // Resolve any declaration pointers within the declaration updates block and + // chained Objective-C categories block to declaration IDs. + ResolveDeclUpdatesBlocks(); + ResolveChainedObjCCategories(); + + // Form the record of special types. + RecordData SpecialTypes; + AddTypeRef(Context.getBuiltinVaListType(), SpecialTypes); + AddTypeRef(Context.ObjCProtoType, SpecialTypes); + AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); + AddTypeRef(Context.getFILEType(), SpecialTypes); + AddTypeRef(Context.getjmp_bufType(), SpecialTypes); + AddTypeRef(Context.getsigjmp_bufType(), SpecialTypes); + AddTypeRef(Context.ObjCIdRedefinitionType, SpecialTypes); + AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes); + AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); + + // Keep writing types and declarations until all types and + // declarations have been written. Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE); WriteDeclsBlockAbbrevs(); - for (DeclsToRewriteTy::iterator - I = DeclsToRewrite.begin(), E = DeclsToRewrite.end(); I != E; ++I) + for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(), + E = DeclsToRewrite.end(); + I != E; ++I) DeclTypesToEmit.push(const_cast<Decl*>(*I)); while (!DeclTypesToEmit.empty()) { DeclOrType DOT = DeclTypesToEmit.front(); @@ -3140,30 +3013,31 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, } Stream.ExitBlock(); - WritePreprocessor(PP); + WritePreprocessor(PP, IsModule); + WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); WriteSelectors(SemaRef); WriteReferencedSelectorsPool(SemaRef); - WriteIdentifierTable(PP); + WriteIdentifierTable(PP, IsModule); WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteOpenCLExtensions(SemaRef); WriteTypeDeclOffsets(); - // FIXME: For chained PCH only write the new mappings (we currently - // write all of them again). WritePragmaDiagnosticMappings(Context.getDiagnostics()); WriteCXXBaseSpecifiersOffsets(); + + Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); /// Build a record containing first declarations from a chained PCH and the /// most recent declarations in this AST that they point to. RecordData FirstLatestDeclIDs; - for (FirstLatestDeclMap::iterator - I = FirstLatestDecls.begin(), E = FirstLatestDecls.end(); I != E; ++I) { - assert(I->first->getPCHLevel() > I->second->getPCHLevel() && - "Expected first & second to be in different PCHs"); + for (FirstLatestDeclMap::iterator I = FirstLatestDecls.begin(), + E = FirstLatestDecls.end(); + I != E; ++I) { AddDeclRef(I->first, FirstLatestDeclIDs); AddDeclRef(I->second, FirstLatestDeclIDs); } + if (!FirstLatestDeclIDs.empty()) Stream.EmitRecord(REDECLS_UPDATE_LATEST, FirstLatestDeclIDs); @@ -3208,30 +3082,70 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, // Write the record containing declaration references of Sema. if (!SemaDeclRefs.empty()) Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); + + // Write the record containing CUDA-specific declaration references. + if (!CUDASpecialDeclRefs.empty()) + Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); // Write the delegating constructors. if (!DelegatingCtorDecls.empty()) Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); - // Write the updates to DeclContexts. + // Write the known namespaces. + if (!KnownNamespaces.empty()) + Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); + + // Write the visible updates to DeclContexts. for (llvm::SmallPtrSet<const DeclContext *, 16>::iterator - I = UpdatedDeclContexts.begin(), - E = UpdatedDeclContexts.end(); - I != E; ++I) + I = UpdatedDeclContexts.begin(), + E = UpdatedDeclContexts.end(); + I != E; ++I) WriteDeclContextVisibleUpdate(*I); WriteDeclUpdatesBlocks(); + WriteDeclReplacementsBlock(); + WriteChainedObjCCategories(); + // Some simple statistics Record.clear(); Record.push_back(NumStatements); Record.push_back(NumMacros); Record.push_back(NumLexicalDeclContexts); Record.push_back(NumVisibleDeclContexts); - WriteDeclReplacementsBlock(); Stream.EmitRecord(STATISTICS, Record); Stream.ExitBlock(); } +/// \brief Go through the declaration update blocks and resolve declaration +/// pointers into declaration IDs. +void ASTWriter::ResolveDeclUpdatesBlocks() { + for (DeclUpdateMap::iterator + I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) { + const Decl *D = I->first; + UpdateRecord &URec = I->second; + + if (DeclsToRewrite.count(D)) + continue; // The decl will be written completely + + unsigned Idx = 0, N = URec.size(); + while (Idx < N) { + switch ((DeclUpdateKind)URec[Idx++]) { + case UPD_CXX_SET_DEFINITIONDATA: + case UPD_CXX_ADDED_IMPLICIT_MEMBER: + case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: + case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: + URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx])); + ++Idx; + break; + + case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: + ++Idx; + break; + } + } + } +} + void ASTWriter::WriteDeclUpdatesBlocks() { if (DeclUpdates.empty()) return; @@ -3261,7 +3175,7 @@ void ASTWriter::WriteDeclReplacementsBlock() { return; RecordData Record; - for (llvm::SmallVector<std::pair<DeclID, uint64_t>, 16>::iterator + for (SmallVector<std::pair<DeclID, uint64_t>, 16>::iterator I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) { Record.push_back(I->first); Record.push_back(I->second); @@ -3269,6 +3183,37 @@ void ASTWriter::WriteDeclReplacementsBlock() { Stream.EmitRecord(DECL_REPLACEMENTS, Record); } +void ASTWriter::ResolveChainedObjCCategories() { + for (SmallVector<ChainedObjCCategoriesData, 16>::iterator + I = LocalChainedObjCCategories.begin(), + E = LocalChainedObjCCategories.end(); I != E; ++I) { + ChainedObjCCategoriesData &Data = *I; + Data.InterfaceID = GetDeclRef(Data.Interface); + Data.TailCategoryID = GetDeclRef(Data.TailCategory); + } + +} + +void ASTWriter::WriteChainedObjCCategories() { + if (LocalChainedObjCCategories.empty()) + return; + + RecordData Record; + for (SmallVector<ChainedObjCCategoriesData, 16>::iterator + I = LocalChainedObjCCategories.begin(), + E = LocalChainedObjCCategories.end(); I != E; ++I) { + ChainedObjCCategoriesData &Data = *I; + serialization::DeclID + HeadCatID = getDeclID(Data.Interface->getCategoryList()); + assert(HeadCatID != 0 && "Category not written ?"); + + Record.push_back(Data.InterfaceID); + Record.push_back(HeadCatID); + Record.push_back(Data.TailCategoryID); + } + Stream.EmitRecord(OBJC_CHAINED_CATEGORIES, Record); +} + void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) { Record.push_back(Loc.getRawEncoding()); } @@ -3307,16 +3252,6 @@ IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { return ID; } -MacroID ASTWriter::getMacroDefinitionID(MacroDefinition *MD) { - if (MD == 0) - return 0; - - MacroID &ID = MacroDefinitions[MD]; - if (ID == 0) - ID = NextMacroID++; - return ID; -} - void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { Record.push_back(getSelectorRef(SelRef)); } @@ -3416,13 +3351,13 @@ void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) { Record.push_back(GetOrCreateTypeID(T)); } -TypeID ASTWriter::GetOrCreateTypeID(QualType T) { - return MakeTypeID(T, +TypeID ASTWriter::GetOrCreateTypeID( QualType T) { + return MakeTypeID(*Context, T, std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this)); } TypeID ASTWriter::getTypeID(QualType T) const { - return MakeTypeID(T, + return MakeTypeID(*Context, T, std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this)); } @@ -3456,6 +3391,8 @@ void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { } DeclID ASTWriter::GetDeclRef(const Decl *D) { + assert(WritingAST && "Cannot request a declaration ID before AST writing"); + if (D == 0) { return 0; } @@ -3571,7 +3508,7 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record) { // Nested name specifiers usually aren't too long. I think that 8 would // typically accommodate the vast majority. - llvm::SmallVector<NestedNameSpecifier *, 8> NestedNames; + SmallVector<NestedNameSpecifier *, 8> NestedNames; // Push each of the NNS's onto a stack for serialization in reverse order. while (NNS) { @@ -3614,7 +3551,7 @@ void ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, RecordDataImpl &Record) { // Nested name specifiers usually aren't too long. I think that 8 would // typically accommodate the vast majority. - llvm::SmallVector<NestedNameSpecifierLoc , 8> NestedNames; + SmallVector<NestedNameSpecifierLoc , 8> NestedNames; // Push each of the nested-name-specifiers's onto a stack for // serialization in reverse order. @@ -3805,7 +3742,7 @@ void ASTWriter::FlushCXXBaseSpecifiers() { Record.clear(); // Record the offset of this base-specifier set. - unsigned Index = CXXBaseSpecifiersToWrite[I].ID - FirstCXXBaseSpecifiersID; + unsigned Index = CXXBaseSpecifiersToWrite[I].ID - 1; if (Index == CXXBaseSpecifiersOffsets.size()) CXXBaseSpecifiersOffsets.push_back(Stream.GetCurrentBitNo()); else { @@ -3871,7 +3808,9 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; Record.push_back(Data.UserDeclaredConstructor); Record.push_back(Data.UserDeclaredCopyConstructor); + Record.push_back(Data.UserDeclaredMoveConstructor); Record.push_back(Data.UserDeclaredCopyAssignment); + Record.push_back(Data.UserDeclaredMoveAssignment); Record.push_back(Data.UserDeclaredDestructor); Record.push_back(Data.Aggregate); Record.push_back(Data.PlainOldData); @@ -3885,7 +3824,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.HasPublicFields); Record.push_back(Data.HasMutableFields); Record.push_back(Data.HasTrivialDefaultConstructor); - Record.push_back(Data.HasConstExprNonCopyMoveConstructor); + Record.push_back(Data.HasConstexprNonCopyMoveConstructor); Record.push_back(Data.HasTrivialCopyConstructor); Record.push_back(Data.HasTrivialMoveConstructor); Record.push_back(Data.HasTrivialCopyAssignment); @@ -3896,8 +3835,12 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.UserProvidedDefaultConstructor); Record.push_back(Data.DeclaredDefaultConstructor); Record.push_back(Data.DeclaredCopyConstructor); + Record.push_back(Data.DeclaredMoveConstructor); Record.push_back(Data.DeclaredCopyAssignment); + Record.push_back(Data.DeclaredMoveAssignment); Record.push_back(Data.DeclaredDestructor); + Record.push_back(Data.FailedImplicitMoveConstructor); + Record.push_back(Data.FailedImplicitMoveAssignment); Record.push_back(Data.NumBases); if (Data.NumBases > 0) @@ -3918,28 +3861,23 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec void ASTWriter::ReaderInitialized(ASTReader *Reader) { assert(Reader && "Cannot remove chain"); - assert(!Chain && "Cannot replace chain"); + assert((!Chain || Chain == Reader) && "Cannot replace chain"); assert(FirstDeclID == NextDeclID && FirstTypeID == NextTypeID && FirstIdentID == NextIdentID && FirstSelectorID == NextSelectorID && - FirstMacroID == NextMacroID && - FirstCXXBaseSpecifiersID == NextCXXBaseSpecifiersID && "Setting chain after writing has started."); + Chain = Reader; - FirstDeclID += Chain->getTotalNumDecls(); - FirstTypeID += Chain->getTotalNumTypes(); - FirstIdentID += Chain->getTotalNumIdentifiers(); - FirstSelectorID += Chain->getTotalNumSelectors(); - FirstMacroID += Chain->getTotalNumMacroDefinitions(); - FirstCXXBaseSpecifiersID += Chain->getTotalNumCXXBaseSpecifiers(); + FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); + FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); + FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); + FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; NextSelectorID = FirstSelectorID; - NextMacroID = FirstMacroID; - NextCXXBaseSpecifiersID = FirstCXXBaseSpecifiersID; } void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { @@ -3967,16 +3905,18 @@ void ASTWriter::SelectorRead(SelectorID ID, Selector S) { SelectorIDs[S] = ID; } -void ASTWriter::MacroDefinitionRead(serialization::MacroID ID, +void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, MacroDefinition *MD) { + assert(MacroDefinitions.find(MD) == MacroDefinitions.end()); MacroDefinitions[MD] = ID; } void ASTWriter::CompletedTagDefinition(const TagDecl *D) { - assert(D->isDefinition()); + assert(D->isCompleteDefinition()); + assert(!WritingAST && "Already writing the AST!"); if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { // We are interested when a PCH decl is modified. - if (RD->getPCHLevel() > 0) { + if (RD->isFromASTFile()) { // A forward reference was mutated into a definition. Rewrite it. // FIXME: This happens during template instantiation, should we // have created a new definition decl instead ? @@ -3990,67 +3930,73 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { continue; // We are interested when a PCH decl is modified. - if (Redecl->getPCHLevel() > 0) { + if (Redecl->isFromASTFile()) { UpdateRecord &Record = DeclUpdates[Redecl]; Record.push_back(UPD_CXX_SET_DEFINITIONDATA); assert(Redecl->DefinitionData); assert(Redecl->DefinitionData->Definition == D); - AddDeclRef(D, Record); // the DefinitionDecl + Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl } } } } void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { + assert(!WritingAST && "Already writing the AST!"); + // TU and namespaces are handled elsewhere. if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC)) return; - if (!(D->getPCHLevel() == 0 && cast<Decl>(DC)->getPCHLevel() > 0)) + if (!(!D->isFromASTFile() && cast<Decl>(DC)->isFromASTFile())) return; // Not a source decl added to a DeclContext from PCH. AddUpdatedDeclContext(DC); } void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { + assert(!WritingAST && "Already writing the AST!"); assert(D->isImplicit()); - if (!(D->getPCHLevel() == 0 && RD->getPCHLevel() > 0)) + if (!(!D->isFromASTFile() && RD->isFromASTFile())) return; // Not a source member added to a class from PCH. if (!isa<CXXMethodDecl>(D)) return; // We are interested in lazily declared implicit methods. // A decl coming from PCH was modified. - assert(RD->isDefinition()); + assert(RD->isCompleteDefinition()); UpdateRecord &Record = DeclUpdates[RD]; Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER); - AddDeclRef(D, Record); + Record.push_back(reinterpret_cast<uint64_t>(D)); } void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) { // The specializations set is kept in the canonical template. + assert(!WritingAST && "Already writing the AST!"); TD = TD->getCanonicalDecl(); - if (!(D->getPCHLevel() == 0 && TD->getPCHLevel() > 0)) + if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. UpdateRecord &Record = DeclUpdates[TD]; Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION); - AddDeclRef(D, Record); + Record.push_back(reinterpret_cast<uint64_t>(D)); } void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, const FunctionDecl *D) { // The specializations set is kept in the canonical template. + assert(!WritingAST && "Already writing the AST!"); TD = TD->getCanonicalDecl(); - if (!(D->getPCHLevel() == 0 && TD->getPCHLevel() > 0)) + if (!(!D->isFromASTFile() && TD->isFromASTFile())) return; // Not a source specialization added to a template from PCH. UpdateRecord &Record = DeclUpdates[TD]; Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION); - AddDeclRef(D, Record); + Record.push_back(reinterpret_cast<uint64_t>(D)); } void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { - if (D->getPCHLevel() == 0) + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) return; // Declaration not imported from PCH. // Implicit decl from a PCH was defined. @@ -4059,7 +4005,8 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { } void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { - if (D->getPCHLevel() == 0) + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) return; // Since the actual instantiation is delayed, this really means that we need @@ -4070,4 +4017,16 @@ void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { D->getMemberSpecializationInfo()->getPointOfInstantiation(), Record); } -ASTSerializationListener::~ASTSerializationListener() { } +void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, + const ObjCInterfaceDecl *IFD) { + assert(!WritingAST && "Already writing the AST!"); + if (!IFD->isFromASTFile()) + return; // Declaration not imported from PCH. + if (CatD->getNextClassCategory() && + !CatD->getNextClassCategory()->isFromASTFile()) + return; // We already recorded that the tail of a category chain should be + // attached to an interface. + + ChainedObjCCategoriesData Data = { IFD, CatD, 0, 0 }; + LocalChainedObjCCategories.push_back(Data); +} diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp index 2b83494..a8243e5 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp @@ -65,6 +65,8 @@ namespace clang { ClassTemplateSpecializationDecl *D); void VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); + void VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *D); void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); void VisitValueDecl(ValueDecl *D); void VisitEnumConstantDecl(EnumConstantDecl *D); @@ -153,13 +155,11 @@ void ASTDeclWriter::VisitDecl(Decl *D) { Record.push_back(D->isUsed(false)); Record.push_back(D->isReferenced()); Record.push_back(D->getAccess()); - Record.push_back(D->getPCHLevel()); + Record.push_back(D->ModulePrivate); } void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { - VisitDecl(D); - Writer.AddDeclRef(D->getAnonymousNamespace(), Record); - Code = serialization::DECL_TRANSLATION_UNIT; + llvm_unreachable("Translation units aren't directly serialized"); } void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { @@ -180,11 +180,11 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { if (!D->hasAttrs() && !D->isImplicit() && !D->isUsed(false) && - D->getPCHLevel() == 0 && D->RedeclLink.getNext() == D && !D->isInvalidDecl() && !D->isReferenced() && D->getAccess() == AS_none && + !D->isModulePrivate() && D->getDeclName().getNameKind() == DeclarationName::Identifier) AbbrevToUse = Writer.getDeclTypedefAbbrev(); @@ -202,8 +202,9 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) { VisitRedeclarable(D); Record.push_back(D->getIdentifierNamespace()); Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding - Record.push_back(D->isDefinition()); + Record.push_back(D->isCompleteDefinition()); Record.push_back(D->isEmbeddedInDeclarator()); + Record.push_back(D->isFreeStanding()); Writer.AddSourceLocation(D->getRBraceLoc(), Record); Record.push_back(D->hasExtInfo()); if (D->hasExtInfo()) @@ -228,12 +229,12 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { if (!D->hasAttrs() && !D->isImplicit() && !D->isUsed(false) && - D->getPCHLevel() == 0 && !D->hasExtInfo() && D->RedeclLink.getNext() == D && !D->isInvalidDecl() && !D->isReferenced() && D->getAccess() == AS_none && + !D->isModulePrivate() && !CXXRecordDecl::classofKind(D->getKind()) && !D->getIntegerTypeSourceInfo() && D->getDeclName().getNameKind() == DeclarationName::Identifier) @@ -251,12 +252,12 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { if (!D->hasAttrs() && !D->isImplicit() && !D->isUsed(false) && - D->getPCHLevel() == 0 && !D->hasExtInfo() && D->RedeclLink.getNext() == D && !D->isInvalidDecl() && !D->isReferenced() && D->getAccess() == AS_none && + !D->isModulePrivate() && !CXXRecordDecl::classofKind(D->getKind()) && D->getDeclName().getNameKind() == DeclarationName::Identifier) AbbrevToUse = Writer.getDeclRecordAbbrev(); @@ -295,8 +296,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->getIdentifierNamespace()); Record.push_back(D->getTemplatedKind()); switch (D->getTemplatedKind()) { - default: assert(false && "Unhandled TemplatedKind!"); - break; + default: llvm_unreachable("Unhandled TemplatedKind!"); case FunctionDecl::TK_NonTemplate: break; case FunctionDecl::TK_FunctionTemplate: @@ -321,13 +321,14 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { // Template args as written. Record.push_back(FTSInfo->TemplateArgumentsAsWritten != 0); if (FTSInfo->TemplateArgumentsAsWritten) { - Record.push_back(FTSInfo->TemplateArgumentsAsWritten->size()); - for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->size(); i!=e; ++i) + Record.push_back(FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs); + for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs; + i!=e; ++i) Writer.AddTemplateArgumentLoc((*FTSInfo->TemplateArgumentsAsWritten)[i], Record); - Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getLAngleLoc(), + Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->LAngleLoc, Record); - Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getRAngleLoc(), + Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->RAngleLoc, Record); } @@ -375,6 +376,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->isDefaulted()); Record.push_back(D->isExplicitlyDefaulted()); Record.push_back(D->hasImplicitReturnZero()); + Record.push_back(D->isConstexpr()); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->param_size()); @@ -400,12 +402,19 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Record.push_back(D->isVariadic()); Record.push_back(D->isSynthesized()); Record.push_back(D->isDefined()); + + Record.push_back(D->IsRedeclaration); + Record.push_back(D->HasRedeclaration); + if (D->HasRedeclaration) { + assert(Context.getObjCMethodRedeclaration(D)); + Writer.AddDeclRef(Context.getObjCMethodRedeclaration(D), Record); + } + // FIXME: stable encoding for @required/@optional Record.push_back(D->getImplementationControl()); // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway Record.push_back(D->getObjCDeclQualifier()); Record.push_back(D->hasRelatedResultType()); - Record.push_back(D->getNumSelectorArgs()); Writer.AddTypeRef(D->getResultType(), Record); Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record); Writer.AddSourceLocation(D->getLocEnd(), Record); @@ -413,11 +422,20 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { for (ObjCMethodDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); P != PEnd; ++P) Writer.AddDeclRef(*P, Record); + + Record.push_back(D->SelLocsKind); + unsigned NumStoredSelLocs = D->getNumStoredSelLocs(); + SourceLocation *SelLocs = D->getStoredSelLocs(); + Record.push_back(NumStoredSelLocs); + for (unsigned i = 0; i != NumStoredSelLocs; ++i) + Writer.AddSourceLocation(SelLocs[i], Record); + Code = serialization::DECL_OBJC_METHOD; } void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { VisitNamedDecl(D); + Writer.AddSourceLocation(D->getAtStartLoc(), Record); Writer.AddSourceRange(D->getAtEndRange(), Record); // Abstract class (no need to define a stable serialization::DECL code). } @@ -454,7 +472,6 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Writer.AddDeclRef(D->getCategoryList(), Record); Record.push_back(D->isForwardDecl()); Record.push_back(D->isImplicitInterfaceDecl()); - Writer.AddSourceLocation(D->getClassLoc(), Record); Writer.AddSourceLocation(D->getSuperClassLoc(), Record); Writer.AddSourceLocation(D->getLocEnd(), Record); Code = serialization::DECL_OBJC_INTERFACE; @@ -471,7 +488,7 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { !D->isUsed(false) && !D->isInvalidDecl() && !D->isReferenced() && - D->getPCHLevel() == 0 && + !D->isModulePrivate() && !D->getBitWidth() && !D->hasExtInfo() && D->getDeclName()) @@ -502,11 +519,8 @@ void ASTDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { void ASTDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) { VisitDecl(D); - Record.push_back(D->size()); - for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I) - Writer.AddDeclRef(I->getInterface(), Record); - for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I) - Writer.AddSourceLocation(I->getLocation(), Record); + Writer.AddDeclRef(D->getForwardInterfaceDecl(), Record); + Writer.AddSourceLocation(D->getForwardDecl()->getLocation(), Record); Code = serialization::DECL_OBJC_CLASS; } @@ -536,7 +550,6 @@ void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { Writer.AddSourceLocation(*PL, Record); Writer.AddDeclRef(D->getNextClassCategory(), Record); Record.push_back(D->hasSynthBitfield()); - Writer.AddSourceLocation(D->getAtLoc(), Record); Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); Code = serialization::DECL_OBJC_CATEGORY; } @@ -612,7 +625,7 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { !D->isUsed(false) && !D->isInvalidDecl() && !D->isReferenced() && - D->getPCHLevel() == 0 && + !D->isModulePrivate() && !D->getBitWidth() && !D->hasInClassInitializer() && !D->hasExtInfo() && @@ -665,7 +678,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->isInvalidDecl() && !D->isReferenced() && D->getAccess() == AS_none && - D->getPCHLevel() == 0 && + !D->isModulePrivate() && D->getDeclName().getNameKind() == DeclarationName::Identifier && !D->hasExtInfo() && D->RedeclLink.getNext() == D && @@ -706,7 +719,7 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { !D->isImplicit() && !D->isUsed(false) && D->getAccess() == AS_none && - D->getPCHLevel() == 0 && + !D->isModulePrivate() && D->getStorageClass() == 0 && !D->hasCXXDirectInitializer() && // Can params have this ever? D->getFunctionScopeDepth() == 0 && @@ -793,7 +806,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { Code = serialization::DECL_NAMESPACE; if (Writer.hasChain() && !D->isOriginalNamespace() && - D->getOriginalNamespace()->getPCHLevel() > 0) { + D->getOriginalNamespace()->isFromASTFile()) { NamespaceDecl *NS = D->getOriginalNamespace(); Writer.AddUpdatedDeclContext(NS); @@ -819,7 +832,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { // anonymous namespace. Decl *Parent = cast<Decl>( D->getParent()->getRedeclContext()->getPrimaryContext()); - if (Parent->getPCHLevel() > 0) { + if (Parent->isFromASTFile() || isa<TranslationUnitDecl>(Parent)) { ASTWriter::UpdateRecord &Record = Writer.DeclUpdates[Parent]; Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); Writer.AddDeclRef(D, Record); @@ -909,7 +922,7 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { // Store the key function to avoid deserializing every method so we can // compute it. - if (D->IsDefinition) + if (D->IsCompleteDefinition) Writer.AddDeclRef(Context.getKeyFunction(D), Record); Code = serialization::DECL_CXX_RECORD; @@ -1015,7 +1028,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { // in a chained PCH, keep track of the association with the map so we can // update the first decl during AST reading. if (First->getMostRecentDeclaration() == D && - First->getPCHLevel() > D->getPCHLevel()) { + First->isFromASTFile() && !D->isFromASTFile()) { assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end() && "The latest is already set"); Writer.FirstLatestDecls[First] = D; @@ -1058,16 +1071,12 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> InstFrom = D->getSpecializedTemplateOrPartial(); - Decl *InstFromD; - if (InstFrom.is<ClassTemplateDecl *>()) { - InstFromD = InstFrom.get<ClassTemplateDecl *>(); + if (Decl *InstFromD = InstFrom.dyn_cast<ClassTemplateDecl *>()) { Writer.AddDeclRef(InstFromD, Record); } else { - InstFromD = InstFrom.get<ClassTemplatePartialSpecializationDecl *>(); - Writer.AddDeclRef(InstFromD, Record); + Writer.AddDeclRef(InstFrom.get<ClassTemplatePartialSpecializationDecl *>(), + Record); Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record); - InstFromD = cast<ClassTemplatePartialSpecializationDecl>(InstFromD)-> - getSpecializedTemplate(); } // Explicit info. @@ -1110,6 +1119,14 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; } +void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *D) { + VisitDecl(D); + Writer.AddDeclRef(D->getSpecialization(), Record); + Code = serialization::DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION; +} + + void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); @@ -1233,7 +1250,7 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { // in a chained PCH, keep track of the association with the map so we can // update the first decl during AST reading. if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl && - First->getPCHLevel() > ThisDecl->getPCHLevel()) { + First->isFromASTFile() && !ThisDecl->isFromASTFile()) { assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end() && "The latest is already set"); Writer.FirstLatestDecls[First] = ThisDecl; @@ -1262,7 +1279,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1293,7 +1310,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1327,7 +1344,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1339,8 +1356,9 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // TagDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isDefinition + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypedefNameAnonDecl @@ -1372,7 +1390,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1384,8 +1402,9 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // TagDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isDefinition + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypedefNameAnonDecl @@ -1411,7 +1430,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1459,7 +1478,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1484,7 +1503,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name @@ -1527,6 +1546,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HasQualifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location DeclRefExprAbbrev = Stream.EmitAbbrev(Abv); @@ -1592,8 +1612,11 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { /// relatively painless since they would presumably only do it for top-level /// decls. static bool isRequiredDecl(const Decl *D, ASTContext &Context) { + // An ObjCMethodDecl is never considered as "required" because its + // implementation container always is. + // File scoped assembly or obj-c implementation must be seen. - if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplementationDecl>(D)) + if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D)) return true; return Context.DeclMustBeEmitted(D); @@ -1648,7 +1671,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); if (!W.Code) - llvm::report_fatal_error(llvm::StringRef("unexpected declaration kind '") + + llvm::report_fatal_error(StringRef("unexpected declaration kind '") + D->getDeclKindName() + "'"); Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp index 1d73ed4..7e2d45c 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp @@ -36,7 +36,7 @@ namespace clang { : Writer(Writer), Record(Record) { } void - AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args); + AddExplicitTemplateArgumentList(const ASTTemplateArgumentListInfo &Args); void VisitStmt(Stmt *S); #define STMT(Type, Base) \ @@ -46,7 +46,7 @@ namespace clang { } void ASTStmtWriter:: -AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args) { +AddExplicitTemplateArgumentList(const ASTTemplateArgumentListInfo &Args) { Writer.AddSourceLocation(Args.LAngleLoc, Record); Writer.AddSourceLocation(Args.RAngleLoc, Record); for (unsigned i=0; i != Args.NumTemplateArgs; ++i) @@ -59,7 +59,7 @@ void ASTStmtWriter::VisitStmt(Stmt *S) { void ASTStmtWriter::VisitNullStmt(NullStmt *S) { VisitStmt(S); Writer.AddSourceLocation(S->getSemiLoc(), Record); - Writer.AddSourceLocation(S->LeadingEmptyMacro, Record); + Record.push_back(S->HasLeadingEmptyMacro); Code = serialization::STMT_NULL; } @@ -265,6 +265,7 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { Record.push_back(E->hasQualifier()); Record.push_back(E->getDecl() != E->getFoundDecl()); Record.push_back(E->hasExplicitTemplateArgs()); + Record.push_back(E->hadMultipleCandidates()); if (E->hasExplicitTemplateArgs()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -324,7 +325,7 @@ void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) { VisitExpr(E); Record.push_back(E->getByteLength()); Record.push_back(E->getNumConcatenated()); - Record.push_back(E->isWide()); + Record.push_back(E->getKind()); Record.push_back(E->isPascal()); // FIXME: String data should be stored as a blob at the end of the // StringLiteral. However, we can't do so now because we have no @@ -340,7 +341,7 @@ void ASTStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) { VisitExpr(E); Record.push_back(E->getValue()); Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isWide()); + Record.push_back(E->getKind()); AbbrevToUse = Writer.getCharacterLiteralAbbrev(); @@ -457,7 +458,9 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { for (unsigned i=0; i != NumTemplateArgs; ++i) Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record); } - + + Record.push_back(E->hadMultipleCandidates()); + DeclAccessPair FoundDecl = E->getFoundDecl(); Writer.AddDeclRef(FoundDecl.getDecl(), Record); Record.push_back(FoundDecl.getAccess()); @@ -733,6 +736,21 @@ void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { Code = serialization::EXPR_GENERIC_SELECTION; } +void ASTStmtWriter::VisitAtomicExpr(AtomicExpr *E) { + VisitExpr(E); + Record.push_back(E->getOp()); + Writer.AddStmt(E->getPtr()); + Writer.AddStmt(E->getOrder()); + if (E->getOp() != AtomicExpr::Load) + Writer.AddStmt(E->getVal1()); + if (E->isCmpXChg()) { + Writer.AddStmt(E->getOrderFail()); + Writer.AddStmt(E->getVal2()); + } + Writer.AddSourceLocation(E->getBuiltinLoc(), Record); + Writer.AddSourceLocation(E->getRParenLoc(), Record); +} + //===----------------------------------------------------------------------===// // Objective-C Expressions and Statements. //===----------------------------------------------------------------------===// @@ -806,6 +824,8 @@ void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { VisitExpr(E); Record.push_back(E->getNumArgs()); + Record.push_back(E->getNumStoredSelLocs()); + Record.push_back(E->SelLocsKind); Record.push_back(E->isDelegateInitCall()); Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding switch (E->getReceiverKind()) { @@ -834,11 +854,15 @@ void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { Writer.AddSourceLocation(E->getLeftLoc(), Record); Writer.AddSourceLocation(E->getRightLoc(), Record); - Writer.AddSourceLocation(E->getSelectorLoc(), Record); for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); Arg != ArgEnd; ++Arg) Writer.AddStmt(*Arg); + + SourceLocation *Locs = E->getStoredSelLocs(); + for (unsigned i = 0, e = E->getNumStoredSelLocs(); i != e; ++i) + Writer.AddSourceLocation(Locs[i], Record); + Code = serialization::EXPR_OBJC_MESSAGE_EXPR; } @@ -952,6 +976,7 @@ void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { Writer.AddDeclRef(E->getConstructor(), Record); Writer.AddSourceLocation(E->getLocation(), Record); Record.push_back(E->isElidable()); + Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->requiresZeroInitialization()); Record.push_back(E->getConstructionKind()); // FIXME: stable encoding Writer.AddSourceRange(E->getParenRange(), Record); @@ -1071,6 +1096,7 @@ void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { Record.push_back(E->hasInitializer()); Record.push_back(E->doesUsualArrayDeleteWantSize()); Record.push_back(E->isArray()); + Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->getNumPlacementArgs()); Record.push_back(E->getNumConstructorArgs()); Writer.AddDeclRef(E->getOperatorNew(), Record); @@ -1142,7 +1168,7 @@ ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ Record.push_back(E->hasExplicitTemplateArgs()); if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs(); + const ASTTemplateArgumentListInfo &Args = E->getExplicitTemplateArgs(); Record.push_back(Args.NumTemplateArgs); AddExplicitTemplateArgumentList(Args); } @@ -1168,7 +1194,7 @@ ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { // emitted first. Record.push_back(E->hasExplicitTemplateArgs()); if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs(); + const ASTTemplateArgumentListInfo &Args = E->getExplicitTemplateArgs(); Record.push_back(Args.NumTemplateArgs); AddExplicitTemplateArgumentList(Args); } @@ -1197,7 +1223,7 @@ void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) { // Don't emit anything here, hasExplicitTemplateArgs() must be emitted first. Record.push_back(E->hasExplicitTemplateArgs()); if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs(); + const ASTTemplateArgumentListInfo &Args = E->getExplicitTemplateArgs(); Record.push_back(Args.NumTemplateArgs); AddExplicitTemplateArgumentList(Args); } @@ -1428,7 +1454,7 @@ void ASTWriter::WriteSubStmt(Stmt *S) { } // Redirect ASTWriter::AddStmt to collect sub stmts. - llvm::SmallVector<Stmt *, 16> SubStmts; + SmallVector<Stmt *, 16> SubStmts; CollectedStmts = &SubStmts; Writer.Code = serialization::STMT_NULL_PTR; @@ -1440,7 +1466,7 @@ void ASTWriter::WriteSubStmt(Stmt *S) { SourceManager &SrcMgr = DeclIDs.begin()->first->getASTContext().getSourceManager(); S->dump(SrcMgr); - assert(0 && "Unhandled sub statement writing AST file"); + llvm_unreachable("Unhandled sub statement writing AST file"); } #endif diff --git a/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp b/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp index 3b7cd23..5fcf11a 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp @@ -26,17 +26,20 @@ using namespace clang; static ASTReader *createASTReader(CompilerInstance &CI, - llvm::StringRef pchFile, - llvm::MemoryBuffer **memBufs, - unsigned numBufs, + StringRef pchFile, + SmallVector<llvm::MemoryBuffer *, 4> &memBufs, + SmallVector<std::string, 4> &bufNames, ASTDeserializationListener *deserialListener = 0) { Preprocessor &PP = CI.getPreprocessor(); llvm::OwningPtr<ASTReader> Reader; - Reader.reset(new ASTReader(PP, &CI.getASTContext(), /*isysroot=*/0, + Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"", /*DisableValidation=*/true)); - Reader->setASTMemoryBuffers(memBufs, numBufs); + for (unsigned ti = 0; ti < bufNames.size(); ++ti) { + StringRef sr(bufNames[ti]); + Reader->addInMemoryBuffer(sr, memBufs[ti]); + } Reader->setDeserializationListener(deserialListener); - switch (Reader->ReadAST(pchFile, ASTReader::PCH)) { + switch (Reader->ReadAST(pchFile, serialization::MK_PCH)) { case ASTReader::Success: // Set the predefines buffer as suggested by the PCH reader. PP.setPredefines(Reader->getSuggestedPredefines()); @@ -62,7 +65,8 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { llvm::OwningPtr<ChainedIncludesSource> source(new ChainedIncludesSource()); InputKind IK = CI.getFrontendOpts().Inputs[0].first; - llvm::SmallVector<llvm::MemoryBuffer *, 4> serialBufs; + SmallVector<llvm::MemoryBuffer *, 4> serialBufs; + SmallVector<std::string, 4> serialBufNames; for (unsigned i = 0, e = includes.size(); i != e; ++i) { bool firstInclude = (i == 0); @@ -83,8 +87,8 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID, - DiagClient)); + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags( + new DiagnosticsEngine(DiagID, DiagClient)); llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance()); Clang->setInvocation(CInvok.take()); @@ -98,16 +102,15 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { &Clang->getPreprocessor()); Clang->createASTContext(); - llvm::SmallVector<char, 256> serialAST; + SmallVector<char, 256> serialAST; llvm::raw_svector_ostream OS(serialAST); llvm::OwningPtr<ASTConsumer> consumer; consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", - /*Chaining=*/!firstInclude, - /*isysroot=*/0, &OS)); + /*IsModule=*/false, /*isysroot=*/"", &OS)); Clang->getASTContext().setASTMutationListener( consumer->GetASTMutationListener()); Clang->setASTConsumer(consumer.take()); - Clang->createSema(/*CompleteTranslationUnit=*/false, 0); + Clang->createSema(TU_Prefix, 0); if (firstInclude) { Preprocessor &PP = Clang->getPreprocessor(); @@ -115,19 +118,23 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { PP.getLangOptions()); } else { assert(!serialBufs.empty()); - llvm::SmallVector<llvm::MemoryBuffer *, 4> bufs; + SmallVector<llvm::MemoryBuffer *, 4> bufs; for (unsigned si = 0, se = serialBufs.size(); si != se; ++si) { bufs.push_back(llvm::MemoryBuffer::getMemBufferCopy( - llvm::StringRef(serialBufs[si]->getBufferStart(), + StringRef(serialBufs[si]->getBufferStart(), serialBufs[si]->getBufferSize()))); } std::string pchName = includes[i-1]; llvm::raw_string_ostream os(pchName); os << ".pch" << i-1; os.flush(); + + serialBufNames.push_back(pchName); + llvm::OwningPtr<ExternalASTSource> Reader; - Reader.reset(createASTReader(*Clang, pchName, bufs.data(), bufs.size(), - Clang->getASTConsumer().GetASTDeserializationListener())); + + Reader.reset(createASTReader(*Clang, pchName, bufs, serialBufNames, + Clang->getASTConsumer().GetASTDeserializationListener())); if (!Reader) return 0; Clang->getASTContext().setExternalSource(Reader); @@ -140,16 +147,16 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { OS.flush(); Clang->getDiagnosticClient().EndSourceFile(); serialBufs.push_back( - llvm::MemoryBuffer::getMemBufferCopy(llvm::StringRef(serialAST.data(), + llvm::MemoryBuffer::getMemBufferCopy(StringRef(serialAST.data(), serialAST.size()))); source->CIs.push_back(Clang.take()); } assert(!serialBufs.empty()); std::string pchName = includes.back() + ".pch-final"; + serialBufNames.push_back(pchName); llvm::OwningPtr<ASTReader> Reader; - Reader.reset(createASTReader(CI, pchName, - serialBufs.data(), serialBufs.size())); + Reader.reset(createASTReader(CI, pchName, serialBufs, serialBufNames)); if (!Reader) return 0; @@ -182,13 +189,10 @@ ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { return getFinalReader().FindExternalVisibleDeclsByName(DC, Name); } -void ChainedIncludesSource::MaterializeVisibleDecls(const DeclContext *DC) { - return getFinalReader().MaterializeVisibleDecls(DC); -} ExternalLoadResult ChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), - llvm::SmallVectorImpl<Decl*> &Result) { + SmallVectorImpl<Decl*> &Result) { return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result); } void ChainedIncludesSource::CompleteType(TagDecl *Tag) { diff --git a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp index b8833ce..a2534db 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp @@ -27,31 +27,29 @@ using namespace clang; PCHGenerator::PCHGenerator(const Preprocessor &PP, - const std::string &OutputFile, - bool Chaining, - const char *isysroot, - llvm::raw_ostream *OS) - : PP(PP), OutputFile(OutputFile), isysroot(isysroot), Out(OS), SemaPtr(0), - StatCalls(0), Stream(Buffer), Writer(Stream), Chaining(Chaining) { + StringRef OutputFile, + bool IsModule, + StringRef isysroot, + raw_ostream *OS) + : PP(PP), OutputFile(OutputFile), IsModule(IsModule), + isysroot(isysroot.str()), Out(OS), + SemaPtr(0), StatCalls(0), Stream(Buffer), Writer(Stream) { // Install a stat() listener to keep track of all of the stat() // calls. StatCalls = new MemorizeStatCalls(); - // If we have a chain, we want new stat calls only, so install the memorizer - // *after* the already installed ASTReader's stat cache. - PP.getFileManager().addStatCache(StatCalls, - /*AtBeginning=*/!Chaining); + PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/false); +} + +PCHGenerator::~PCHGenerator() { } void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { if (PP.getDiagnostics().hasErrorOccurred()) return; - - // Set up the serialization listener. - Writer.SetSerializationListener(GetASTSerializationListener()); // Emit the PCH file assert(SemaPtr && "No Sema?"); - Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, isysroot); + Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, IsModule, isysroot); // Write the generated bitstream to "Out". Out->write((char *)&Buffer.front(), Buffer.size()); @@ -64,13 +62,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { } ASTMutationListener *PCHGenerator::GetASTMutationListener() { - if (Chaining) - return &Writer; - return 0; -} - -ASTSerializationListener *PCHGenerator::GetASTSerializationListener() { - return 0; + return &Writer; } ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { diff --git a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp new file mode 100644 index 0000000..0a721c4 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp @@ -0,0 +1,109 @@ +//===--- Module.cpp - Module description ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Module class, which describes a module that has +// been loaded from an AST file. +// +//===----------------------------------------------------------------------===// +#include "clang/Serialization/Module.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/MemoryBuffer.h" +#include "ASTReaderInternals.h" + +using namespace clang; +using namespace serialization; +using namespace reader; + +Module::Module(ModuleKind Kind) + : Kind(Kind), DirectlyImported(false), SizeInBits(0), + LocalNumSLocEntries(0), SLocEntryBaseID(0), + SLocEntryBaseOffset(0), SLocEntryOffsets(0), + SLocFileOffsets(0), LocalNumIdentifiers(0), + IdentifierOffsets(0), BaseIdentifierID(0), IdentifierTableData(0), + IdentifierLookupTable(0), BasePreprocessedEntityID(0), + PreprocessedEntityOffsets(0), NumPreprocessedEntities(0), + LocalNumHeaderFileInfos(0), + HeaderFileInfoTableData(0), HeaderFileInfoTable(0), + HeaderFileFrameworkStrings(0), + LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0), + SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0), + DeclOffsets(0), BaseDeclID(0), + LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0), + LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0) +{} + +Module::~Module() { + for (DeclContextInfosMap::iterator I = DeclContextInfos.begin(), + E = DeclContextInfos.end(); + I != E; ++I) { + if (I->second.NameLookupTableData) + delete static_cast<ASTDeclContextNameLookupTable*>( + I->second.NameLookupTableData); + } + + delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable); + delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable); + delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable); +} + +template<typename Key, typename Offset, unsigned InitialCapacity> +static void +dumpLocalRemap(StringRef Name, + const ContinuousRangeMap<Key, Offset, InitialCapacity> &Map) { + if (Map.begin() == Map.end()) + return; + + typedef ContinuousRangeMap<Key, Offset, InitialCapacity> MapType; + llvm::errs() << " " << Name << ":\n"; + for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); + I != IEnd; ++I) { + llvm::errs() << " " << I->first << " -> " << I->second << "\n"; + } +} + +void Module::dump() { + llvm::errs() << "\nModule: " << FileName << "\n"; + if (!Imports.empty()) { + llvm::errs() << " Imports: "; + for (unsigned I = 0, N = Imports.size(); I != N; ++I) { + if (I) + llvm::errs() << ", "; + llvm::errs() << Imports[I]->FileName; + } + llvm::errs() << "\n"; + } + + // Remapping tables. + llvm::errs() << " Base source location offset: " << SLocEntryBaseOffset + << '\n'; + dumpLocalRemap("Source location offset local -> global map", SLocRemap); + + llvm::errs() << " Base identifier ID: " << BaseIdentifierID << '\n' + << " Number of identifiers: " << LocalNumIdentifiers << '\n'; + dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap); + + llvm::errs() << " Base selector ID: " << BaseSelectorID << '\n' + << " Number of selectors: " << LocalNumSelectors << '\n'; + dumpLocalRemap("Selector ID local -> global map", SelectorRemap); + + llvm::errs() << " Base preprocessed entity ID: " << BasePreprocessedEntityID + << '\n' + << " Number of preprocessed entities: " + << NumPreprocessedEntities << '\n'; + dumpLocalRemap("Preprocessed entity ID local -> global map", + PreprocessedEntityRemap); + + llvm::errs() << " Base type index: " << BaseTypeIndex << '\n' + << " Number of types: " << LocalNumTypes << '\n'; + dumpLocalRemap("Type index local -> global map", TypeRemap); + + llvm::errs() << " Base decl ID: " << BaseDeclID << '\n' + << " Number of decls: " << LocalNumDecls << '\n'; + dumpLocalRemap("Decl ID local -> global map", DeclRemap); +} diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp new file mode 100644 index 0000000..c4b1f71 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp @@ -0,0 +1,253 @@ +//===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ModuleManager class, which manages a set of loaded +// modules for the ASTReader. +// +//===----------------------------------------------------------------------===// +#include "clang/Serialization/ModuleManager.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" + +#ifndef NDEBUG +#include "llvm/Support/GraphWriter.h" +#endif + +using namespace clang; +using namespace serialization; + +Module *ModuleManager::lookup(StringRef Name) { + const FileEntry *Entry = FileMgr.getFile(Name); + return Modules[Entry]; +} + +llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { + const FileEntry *Entry = FileMgr.getFile(Name); + return InMemoryBuffers[Entry]; +} + +std::pair<Module *, bool> +ModuleManager::addModule(StringRef FileName, ModuleKind Type, + Module *ImportedBy, std::string &ErrorStr) { + const FileEntry *Entry = FileMgr.getFile(FileName); + if (!Entry && FileName != "-") { + ErrorStr = "file not found"; + return std::make_pair(static_cast<Module*>(0), false); + } + + // Check whether we already loaded this module, before + Module *&ModuleEntry = Modules[Entry]; + bool NewModule = false; + if (!ModuleEntry) { + // Allocate a new module. + Module *New = new Module(Type); + New->FileName = FileName.str(); + Chain.push_back(New); + NewModule = true; + ModuleEntry = New; + + // Load the contents of the module + if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { + // The buffer was already provided for us. + assert(Buffer && "Passed null buffer"); + New->Buffer.reset(Buffer); + } else { + // Open the AST file. + llvm::error_code ec; + if (FileName == "-") { + ec = llvm::MemoryBuffer::getSTDIN(New->Buffer); + if (ec) + ErrorStr = ec.message(); + } else + New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); + + if (!New->Buffer) + return std::make_pair(static_cast<Module*>(0), false); + } + + // Initialize the stream + New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), + (const unsigned char *)New->Buffer->getBufferEnd()); } + + if (ImportedBy) { + ModuleEntry->ImportedBy.insert(ImportedBy); + ImportedBy->Imports.insert(ModuleEntry); + } else { + ModuleEntry->DirectlyImported = true; + } + + return std::make_pair(ModuleEntry, NewModule); +} + +void ModuleManager::addInMemoryBuffer(StringRef FileName, + llvm::MemoryBuffer *Buffer) { + + const FileEntry *Entry = FileMgr.getVirtualFile(FileName, + Buffer->getBufferSize(), 0); + InMemoryBuffers[Entry] = Buffer; +} + +ModuleManager::ModuleManager(const FileSystemOptions &FSO) : FileMgr(FSO) { } + +ModuleManager::~ModuleManager() { + for (unsigned i = 0, e = Chain.size(); i != e; ++i) + delete Chain[e - i - 1]; +} + +void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), + void *UserData) { + unsigned N = size(); + + // Record the number of incoming edges for each module. When we + // encounter a module with no incoming edges, push it into the queue + // to seed the queue. + SmallVector<Module *, 4> Queue; + Queue.reserve(N); + llvm::DenseMap<Module *, unsigned> UnusedIncomingEdges; + for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { + if (unsigned Size = (*M)->ImportedBy.size()) + UnusedIncomingEdges[*M] = Size; + else + Queue.push_back(*M); + } + + llvm::SmallPtrSet<Module *, 4> Skipped; + unsigned QueueStart = 0; + while (QueueStart < Queue.size()) { + Module *CurrentModule = Queue[QueueStart++]; + + // Check whether this module should be skipped. + if (Skipped.count(CurrentModule)) + continue; + + if (Visitor(*CurrentModule, UserData)) { + // The visitor has requested that cut off visitation of any + // module that the current module depends on. To indicate this + // behavior, we mark all of the reachable modules as having N + // incoming edges (which is impossible otherwise). + SmallVector<Module *, 4> Stack; + Stack.push_back(CurrentModule); + Skipped.insert(CurrentModule); + while (!Stack.empty()) { + Module *NextModule = Stack.back(); + Stack.pop_back(); + + // For any module that this module depends on, push it on the + // stack (if it hasn't already been marked as visited). + for (llvm::SetVector<Module *>::iterator + M = NextModule->Imports.begin(), + MEnd = NextModule->Imports.end(); + M != MEnd; ++M) { + if (Skipped.insert(*M)) + Stack.push_back(*M); + } + } + continue; + } + + // For any module that this module depends on, push it on the + // stack (if it hasn't already been marked as visited). + for (llvm::SetVector<Module *>::iterator M = CurrentModule->Imports.begin(), + MEnd = CurrentModule->Imports.end(); + M != MEnd; ++M) { + + // Remove our current module as an impediment to visiting the + // module we depend on. If we were the last unvisited module + // that depends on this particular module, push it into the + // queue to be visited. + unsigned &NumUnusedEdges = UnusedIncomingEdges[*M]; + if (NumUnusedEdges && (--NumUnusedEdges == 0)) + Queue.push_back(*M); + } + } +} + +/// \brief Perform a depth-first visit of the current module. +static bool visitDepthFirst(Module &M, + bool (*Visitor)(Module &M, bool Preorder, + void *UserData), + void *UserData, + llvm::SmallPtrSet<Module *, 4> &Visited) { + // Preorder visitation + if (Visitor(M, /*Preorder=*/true, UserData)) + return true; + + // Visit children + for (llvm::SetVector<Module *>::iterator IM = M.Imports.begin(), + IMEnd = M.Imports.end(); + IM != IMEnd; ++IM) { + if (!Visited.insert(*IM)) + continue; + + if (visitDepthFirst(**IM, Visitor, UserData, Visited)) + return true; + } + + // Postorder visitation + return Visitor(M, /*Preorder=*/false, UserData); +} + +void ModuleManager::visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, + void *UserData), + void *UserData) { + llvm::SmallPtrSet<Module *, 4> Visited; + for (unsigned I = 0, N = Chain.size(); I != N; ++I) { + if (!Visited.insert(Chain[I])) + continue; + + if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited)) + return; + } +} + +#ifndef NDEBUG +namespace llvm { + template<> + struct GraphTraits<ModuleManager> { + typedef Module NodeType; + typedef llvm::SetVector<Module *>::const_iterator ChildIteratorType; + typedef ModuleManager::ModuleConstIterator nodes_iterator; + + static ChildIteratorType child_begin(NodeType *Node) { + return Node->Imports.begin(); + } + + static ChildIteratorType child_end(NodeType *Node) { + return Node->Imports.end(); + } + + static nodes_iterator nodes_begin(const ModuleManager &Manager) { + return Manager.begin(); + } + + static nodes_iterator nodes_end(const ModuleManager &Manager) { + return Manager.end(); + } + }; + + template<> + struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits { + explicit DOTGraphTraits(bool IsSimple = false) + : DefaultDOTGraphTraits(IsSimple) { } + + static bool renderGraphFromBottomUp() { + return true; + } + + std::string getNodeLabel(Module *M, const ModuleManager&) { + return llvm::sys::path::stem(M->FileName); + } + }; +} + +void ModuleManager::viewGraph() { + llvm::ViewGraph(*this, "Modules"); +} +#endif |