diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization')
11 files changed, 2046 insertions, 1915 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp index 1339322..85c574c 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp @@ -94,6 +94,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) { switch (DC->getDeclKind()) { // These entities may have multiple definitions. case Decl::TranslationUnit: + case Decl::ExternCContext: case Decl::Namespace: case Decl::LinkageSpec: return nullptr; @@ -149,7 +150,11 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) { bool serialization::isRedeclarableDeclKind(unsigned Kind) { switch (static_cast<Decl::Kind>(Kind)) { - case Decl::TranslationUnit: // Special case of a "merged" declaration. + case Decl::TranslationUnit: + case Decl::ExternCContext: + // Special case of a "merged" declaration. + return true; + case Decl::Namespace: case Decl::NamespaceAlias: case Decl::Typedef: @@ -223,6 +228,24 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { } bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { + // Friend declarations in dependent contexts aren't anonymous in the usual + // sense, but they cannot be found by name lookup in their semantic context + // (or indeed in any context), so we treat them as anonymous. + // + // This doesn't apply to friend tag decls; Sema makes those available to name + // lookup in the surrounding context. + if (D->getFriendObjectKind() && + D->getLexicalDeclContext()->isDependentContext() && !isa<TagDecl>(D)) { + // For function templates and class templates, the template is numbered and + // not its pattern. + if (auto *FD = dyn_cast<FunctionDecl>(D)) + return !FD->getDescribedFunctionTemplate(); + if (auto *RD = dyn_cast<CXXRecordDecl>(D)) + return !RD->getDescribedClassTemplate(); + return true; + } + + // Otherwise, we only care about anonymous class members. if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext())) return false; return isa<TagDecl>(D) || isa<FieldDecl>(D); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h index 38a0ff5..79d1817 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_LIB_SERIALIZATION_ASTCOMMON_H #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclFriend.h" #include "clang/Serialization/ASTBitCodes.h" namespace clang { @@ -28,12 +29,14 @@ enum DeclUpdateKind { UPD_CXX_ADDED_FUNCTION_DEFINITION, UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, UPD_CXX_INSTANTIATED_CLASS_DEFINITION, + UPD_CXX_RESOLVED_DTOR_DELETE, UPD_CXX_RESOLVED_EXCEPTION_SPEC, UPD_CXX_DEDUCED_RETURN_TYPE, UPD_DECL_MARKED_USED, UPD_MANGLING_NUMBER, UPD_STATIC_LOCAL_NUMBER, - UPD_DECL_MARKED_OPENMP_THREADPRIVATE + UPD_DECL_MARKED_OPENMP_THREADPRIVATE, + UPD_DECL_EXPORTED }; TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); @@ -85,6 +88,24 @@ bool isRedeclarableDeclKind(unsigned Kind); /// declaration number. bool needsAnonymousDeclarationNumber(const NamedDecl *D); +/// \brief Visit each declaration within \c DC that needs an anonymous +/// declaration number and call \p Visit with the declaration and its number. +template<typename Fn> void numberAnonymousDeclsWithin(const DeclContext *DC, + Fn Visit) { + unsigned Index = 0; + for (Decl *LexicalD : DC->decls()) { + // For a friend decl, we care about the declaration within it, if any. + if (auto *FD = dyn_cast<FriendDecl>(LexicalD)) + LexicalD = FD->getFriendDecl(); + + auto *ND = dyn_cast_or_null<NamedDecl>(LexicalD); + if (!ND || !needsAnonymousDeclarationNumber(ND)) + continue; + + Visit(ND, Index++); + } +} + } // namespace serialization } // namespace clang diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index 416164e..609c25d 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -1,4 +1,4 @@ -//===--- ASTReader.cpp - AST File Reader ----------------------------------===// +//===-- ASTReader.cpp - AST File Reader ----------------------------------===// // // The LLVM Compiler Infrastructure // @@ -89,11 +89,13 @@ ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts, Second->ReadLanguageOptions(LangOpts, Complain, AllowCompatibleDifferences); } -bool -ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts, - bool Complain) { - return First->ReadTargetOptions(TargetOpts, Complain) || - Second->ReadTargetOptions(TargetOpts, Complain); +bool ChainedASTReaderListener::ReadTargetOptions( + const TargetOptions &TargetOpts, bool Complain, + bool AllowCompatibleDifferences) { + return First->ReadTargetOptions(TargetOpts, Complain, + AllowCompatibleDifferences) || + Second->ReadTargetOptions(TargetOpts, Complain, + AllowCompatibleDifferences); } bool ChainedASTReaderListener::ReadDiagnosticOptions( IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { @@ -108,9 +110,12 @@ ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts, } bool ChainedASTReaderListener::ReadHeaderSearchOptions( - const HeaderSearchOptions &HSOpts, bool Complain) { - return First->ReadHeaderSearchOptions(HSOpts, Complain) || - Second->ReadHeaderSearchOptions(HSOpts, Complain); + const HeaderSearchOptions &HSOpts, StringRef SpecificModuleCachePath, + bool Complain) { + return First->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath, + Complain) || + Second->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath, + Complain); } bool ChainedASTReaderListener::ReadPreprocessorOptions( const PreprocessorOptions &PPOpts, bool Complain, @@ -229,7 +234,8 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, /// \returns true if the target options mis-match, false otherwise. static bool checkTargetOptions(const TargetOptions &TargetOpts, const TargetOptions &ExistingTargetOpts, - DiagnosticsEngine *Diags) { + DiagnosticsEngine *Diags, + bool AllowCompatibleDifferences = true) { #define CHECK_TARGET_OPT(Field, Name) \ if (TargetOpts.Field != ExistingTargetOpts.Field) { \ if (Diags) \ @@ -238,9 +244,16 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts, return true; \ } + // The triple and ABI must match exactly. CHECK_TARGET_OPT(Triple, "target"); - CHECK_TARGET_OPT(CPU, "target CPU"); CHECK_TARGET_OPT(ABI, "target ABI"); + + // We can tolerate different CPUs in many cases, notably when one CPU + // supports a strict superset of another. When allowing compatible + // differences skip this check. + if (!AllowCompatibleDifferences) + CHECK_TARGET_OPT(CPU, "target CPU"); + #undef CHECK_TARGET_OPT // Compare feature sets. @@ -252,43 +265,31 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts, std::sort(ExistingFeatures.begin(), ExistingFeatures.end()); std::sort(ReadFeatures.begin(), ReadFeatures.end()); - unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size(); - unsigned ReadIdx = 0, ReadN = ReadFeatures.size(); - while (ExistingIdx < ExistingN && ReadIdx < ReadN) { - if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) { - ++ExistingIdx; - ++ReadIdx; - continue; - } - - if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) { - if (Diags) - Diags->Report(diag::err_pch_targetopt_feature_mismatch) - << false << ReadFeatures[ReadIdx]; - return true; - } - - if (Diags) - Diags->Report(diag::err_pch_targetopt_feature_mismatch) - << true << ExistingFeatures[ExistingIdx]; - return true; - } + // We compute the set difference in both directions explicitly so that we can + // diagnose the differences differently. + SmallVector<StringRef, 4> UnmatchedExistingFeatures, UnmatchedReadFeatures; + std::set_difference( + ExistingFeatures.begin(), ExistingFeatures.end(), ReadFeatures.begin(), + ReadFeatures.end(), std::back_inserter(UnmatchedExistingFeatures)); + std::set_difference(ReadFeatures.begin(), ReadFeatures.end(), + ExistingFeatures.begin(), ExistingFeatures.end(), + std::back_inserter(UnmatchedReadFeatures)); + + // If we are allowing compatible differences and the read feature set is + // a strict subset of the existing feature set, there is nothing to diagnose. + if (AllowCompatibleDifferences && UnmatchedReadFeatures.empty()) + return false; - if (ExistingIdx < ExistingN) { - if (Diags) + if (Diags) { + for (StringRef Feature : UnmatchedReadFeatures) Diags->Report(diag::err_pch_targetopt_feature_mismatch) - << true << ExistingFeatures[ExistingIdx]; - return true; - } - - if (ReadIdx < ReadN) { - if (Diags) + << /* is-existing-feature */ false << Feature; + for (StringRef Feature : UnmatchedExistingFeatures) Diags->Report(diag::err_pch_targetopt_feature_mismatch) - << false << ReadFeatures[ReadIdx]; - return true; + << /* is-existing-feature */ true << Feature; } - return false; + return !UnmatchedReadFeatures.empty() || !UnmatchedExistingFeatures.empty(); } bool @@ -302,10 +303,12 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts, } bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts, - bool Complain) { + bool Complain, + bool AllowCompatibleDifferences) { const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts(); return checkTargetOptions(TargetOpts, ExistingTargetOpts, - Complain? &Reader.Diags : nullptr); + Complain ? &Reader.Diags : nullptr, + AllowCompatibleDifferences); } namespace { @@ -464,7 +467,7 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts, Macros[MacroName] = std::make_pair(MacroBody, false); } } - + /// \brief Check the preprocessor options deserialized from the control block /// against the preprocessor options in an existing preprocessor. /// @@ -591,6 +594,36 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, PP.getLangOpts()); } +/// Check the header search options deserialized from the control block +/// against the header search options in an existing preprocessor. +/// +/// \param Diags If non-null, produce diagnostics for any mismatches incurred. +static bool checkHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + StringRef SpecificModuleCachePath, + StringRef ExistingModuleCachePath, + DiagnosticsEngine *Diags, + const LangOptions &LangOpts) { + if (LangOpts.Modules) { + if (SpecificModuleCachePath != ExistingModuleCachePath) { + if (Diags) + Diags->Report(diag::err_pch_modulecache_mismatch) + << SpecificModuleCachePath << ExistingModuleCachePath; + return true; + } + } + + return false; +} + +bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + StringRef SpecificModuleCachePath, + bool Complain) { + return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath, + PP.getHeaderSearchInfo().getModuleCachePath(), + Complain ? &Reader.Diags : nullptr, + PP.getLangOpts()); +} + void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) { PP.setCounterValue(Value); } @@ -744,8 +777,6 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, Bits >>= 1; bool ExtensionToken = Bits & 0x01; Bits >>= 1; - bool hasSubmoduleMacros = Bits & 0x01; - Bits >>= 1; bool hadMacroDefinition = Bits & 0x01; Bits >>= 1; @@ -787,49 +818,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, uint32_t MacroDirectivesOffset = endian::readNext<uint32_t, little, unaligned>(d); DataLen -= 4; - SmallVector<uint32_t, 8> LocalMacroIDs; - if (hasSubmoduleMacros) { - while (true) { - uint32_t LocalMacroID = - endian::readNext<uint32_t, little, unaligned>(d); - DataLen -= 4; - if (LocalMacroID == 0xdeadbeef) break; - LocalMacroIDs.push_back(LocalMacroID); - } - } - - if (F.Kind == MK_ImplicitModule || F.Kind == MK_ExplicitModule) { - // Macro definitions are stored from newest to oldest, so reverse them - // before registering them. - llvm::SmallVector<unsigned, 8> MacroSizes; - for (SmallVectorImpl<uint32_t>::iterator - I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; /**/) { - unsigned Size = 1; - - static const uint32_t HasOverridesFlag = 0x80000000U; - if (I + 1 != E && (I[1] & HasOverridesFlag)) - Size += 1 + (I[1] & ~HasOverridesFlag); - MacroSizes.push_back(Size); - I += Size; - } - - SmallVectorImpl<uint32_t>::iterator I = LocalMacroIDs.end(); - for (SmallVectorImpl<unsigned>::reverse_iterator SI = MacroSizes.rbegin(), - SE = MacroSizes.rend(); - SI != SE; ++SI) { - I -= *SI; - - uint32_t LocalMacroID = *I; - ArrayRef<uint32_t> Overrides; - if (*SI != 1) - Overrides = llvm::makeArrayRef(&I[2], *SI - 2); - Reader.addPendingMacroFromModule(II, &F, LocalMacroID, Overrides); - } - assert(I == LocalMacroIDs.begin()); - } else { - Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset); - } + Reader.addPendingMacro(II, &F, MacroDirectivesOffset); } Reader.SetIdentifierInfo(ID, II); @@ -1393,6 +1383,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { PreprocessorRecordTypes RecType = (PreprocessorRecordTypes)Stream.readRecord(Entry.ID, Record); switch (RecType) { + case PP_MODULE_MACRO: case PP_MACRO_DIRECTIVE_HISTORY: return Macro; @@ -1441,10 +1432,10 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) { PreprocessedEntityID GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]); PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); - PreprocessingRecord::PPEntityID - PPID = PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true); - MacroDefinition *PPDef = - cast_or_null<MacroDefinition>(PPRec.getPreprocessedEntity(PPID)); + PreprocessingRecord::PPEntityID PPID = + PPRec.getPPEntityID(GlobalID - 1, /*isLoaded=*/true); + MacroDefinitionRecord *PPDef = cast_or_null<MacroDefinitionRecord>( + PPRec.getPreprocessedEntity(PPID)); if (PPDef) PPRec.RegisterMacroDefinition(Macro, PPDef); } @@ -1586,24 +1577,9 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, return HFI; } -void -ASTReader::addPendingMacroFromModule(IdentifierInfo *II, ModuleFile *M, - GlobalMacroID GMacID, - ArrayRef<SubmoduleID> Overrides) { - assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard"); - SubmoduleID *OverrideData = nullptr; - if (!Overrides.empty()) { - OverrideData = new (Context) SubmoduleID[Overrides.size() + 1]; - OverrideData[0] = Overrides.size(); - for (unsigned I = 0; I != Overrides.size(); ++I) - OverrideData[I + 1] = getGlobalSubmoduleID(*M, Overrides[I]); - } - PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, OverrideData)); -} - -void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II, - ModuleFile *M, - uint64_t MacroDirectivesOffset) { +void ASTReader::addPendingMacro(IdentifierInfo *II, + ModuleFile *M, + uint64_t MacroDirectivesOffset) { assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard"); PendingMacroIDs[II].push_back(PendingMacroInfo(M, MacroDirectivesOffset)); } @@ -1747,110 +1723,81 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { IdentifierGeneration[II] = getGeneration(); } -struct ASTReader::ModuleMacroInfo { - SubmoduleID SubModID; - MacroInfo *MI; - SubmoduleID *Overrides; - // FIXME: Remove this. - ModuleFile *F; - - bool isDefine() const { return MI; } - - SubmoduleID getSubmoduleID() const { return SubModID; } - - ArrayRef<SubmoduleID> getOverriddenSubmodules() const { - if (!Overrides) - return None; - return llvm::makeArrayRef(Overrides + 1, *Overrides); - } - - MacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const { - if (!MI) - return PP.AllocateUndefMacroDirective(ImportLoc, SubModID, - getOverriddenSubmodules()); - return PP.AllocateDefMacroDirective(MI, ImportLoc, SubModID, - getOverriddenSubmodules()); - } -}; - -ASTReader::ModuleMacroInfo * -ASTReader::getModuleMacro(const PendingMacroInfo &PMInfo) { - ModuleMacroInfo Info; - - uint32_t ID = PMInfo.ModuleMacroData.MacID; - if (ID & 1) { - // Macro undefinition. - Info.SubModID = getGlobalSubmoduleID(*PMInfo.M, ID >> 1); - Info.MI = nullptr; - } else { - // Macro definition. - GlobalMacroID GMacID = getGlobalMacroID(*PMInfo.M, ID >> 1); - assert(GMacID); - - // If this macro has already been loaded, don't do so again. - // FIXME: This is highly dubious. Multiple macro definitions can have the - // same MacroInfo (and hence the same GMacID) due to #pragma push_macro etc. - if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS]) - return nullptr; +void ASTReader::resolvePendingMacro(IdentifierInfo *II, + const PendingMacroInfo &PMInfo) { + ModuleFile &M = *PMInfo.M; - Info.MI = getMacro(GMacID); - Info.SubModID = Info.MI->getOwningModuleID(); - } - Info.Overrides = PMInfo.ModuleMacroData.Overrides; - Info.F = PMInfo.M; + BitstreamCursor &Cursor = M.MacroCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(PMInfo.MacroDirectivesOffset); - return new (Context) ModuleMacroInfo(Info); -} + struct ModuleMacroRecord { + SubmoduleID SubModID; + MacroInfo *MI; + SmallVector<SubmoduleID, 8> Overrides; + }; + llvm::SmallVector<ModuleMacroRecord, 8> ModuleMacros; -void ASTReader::resolvePendingMacro(IdentifierInfo *II, - const PendingMacroInfo &PMInfo) { - assert(II); + // We expect to see a sequence of PP_MODULE_MACRO records listing exported + // macros, followed by a PP_MACRO_DIRECTIVE_HISTORY record with the complete + // macro histroy. + RecordData Record; + while (true) { + llvm::BitstreamEntry Entry = + Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); + if (Entry.Kind != llvm::BitstreamEntry::Record) { + Error("malformed block record in AST file"); + return; + } - if (PMInfo.M->Kind != MK_ImplicitModule && - PMInfo.M->Kind != MK_ExplicitModule) { - installPCHMacroDirectives(II, *PMInfo.M, - PMInfo.PCHMacroData.MacroDirectivesOffset); - return; - } + Record.clear(); + switch ((PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record)) { + case PP_MACRO_DIRECTIVE_HISTORY: + break; - // Module Macro. + case PP_MODULE_MACRO: { + ModuleMacros.push_back(ModuleMacroRecord()); + auto &Info = ModuleMacros.back(); + Info.SubModID = getGlobalSubmoduleID(M, Record[0]); + Info.MI = getMacro(getGlobalMacroID(M, Record[1])); + for (int I = 2, N = Record.size(); I != N; ++I) + Info.Overrides.push_back(getGlobalSubmoduleID(M, Record[I])); + continue; + } - ModuleMacroInfo *MMI = getModuleMacro(PMInfo); - if (!MMI) - return; + default: + Error("malformed block record in AST file"); + return; + } - Module *Owner = getSubmodule(MMI->getSubmoduleID()); - if (Owner && Owner->NameVisibility == Module::Hidden) { - // Macros in the owning module are hidden. Just remember this macro to - // install if we make this module visible. - HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI)); - } else { - installImportedMacro(II, MMI, Owner); + // We found the macro directive history; that's the last record + // for this macro. + break; } -} - -void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, - ModuleFile &M, uint64_t Offset) { - assert(M.Kind != MK_ImplicitModule && M.Kind != MK_ExplicitModule); - BitstreamCursor &Cursor = M.MacroCursor; - SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Offset); + // Module macros are listed in reverse dependency order. + { + std::reverse(ModuleMacros.begin(), ModuleMacros.end()); + llvm::SmallVector<ModuleMacro*, 8> Overrides; + for (auto &MMR : ModuleMacros) { + Overrides.clear(); + for (unsigned ModID : MMR.Overrides) { + Module *Mod = getSubmodule(ModID); + auto *Macro = PP.getModuleMacro(Mod, II); + assert(Macro && "missing definition for overridden macro"); + Overrides.push_back(Macro); + } - llvm::BitstreamEntry Entry = - Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); - if (Entry.Kind != llvm::BitstreamEntry::Record) { - Error("malformed block record in AST file"); - return; + bool Inserted = false; + Module *Owner = getSubmodule(MMR.SubModID); + PP.addModuleMacro(Owner, II, MMR.MI, Overrides, Inserted); + } } - RecordData Record; - PreprocessorRecordTypes RecType = - (PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record); - if (RecType != PP_MACRO_DIRECTIVE_HISTORY) { - Error("malformed block record in AST file"); + // Don't read the directive history for a module; we don't have anywhere + // to put it. + if (M.Kind == MK_ImplicitModule || M.Kind == MK_ExplicitModule) return; - } // Deserialize the macro directives history in reverse source-order. MacroDirective *Latest = nullptr, *Earliest = nullptr; @@ -1861,31 +1808,12 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++]; switch (K) { case MacroDirective::MD_Define: { - GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]); - MacroInfo *MI = getMacro(GMacID); - SubmoduleID ImportedFrom = Record[Idx++]; - bool IsAmbiguous = Record[Idx++]; - llvm::SmallVector<unsigned, 4> Overrides; - if (ImportedFrom) { - Overrides.insert(Overrides.end(), - &Record[Idx] + 1, &Record[Idx] + 1 + Record[Idx]); - Idx += Overrides.size() + 1; - } - DefMacroDirective *DefMD = - PP.AllocateDefMacroDirective(MI, Loc, ImportedFrom, Overrides); - DefMD->setAmbiguous(IsAmbiguous); - MD = DefMD; + MacroInfo *MI = getMacro(getGlobalMacroID(M, Record[Idx++])); + MD = PP.AllocateDefMacroDirective(MI, Loc); break; } case MacroDirective::MD_Undefine: { - SubmoduleID ImportedFrom = Record[Idx++]; - llvm::SmallVector<unsigned, 4> Overrides; - if (ImportedFrom) { - Overrides.insert(Overrides.end(), - &Record[Idx] + 1, &Record[Idx] + 1 + Record[Idx]); - Idx += Overrides.size() + 1; - } - MD = PP.AllocateUndefMacroDirective(Loc, ImportedFrom, Overrides); + MD = PP.AllocateUndefMacroDirective(Loc); break; } case MacroDirective::MD_Visibility: @@ -1901,177 +1829,8 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, Earliest = MD; } - PP.setLoadedMacroDirective(II, Latest); -} - -/// \brief For the given macro definitions, check if they are both in system -/// modules. -static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI, - Module *NewOwner, ASTReader &Reader) { - assert(PrevMI && NewMI); - Module *PrevOwner = nullptr; - if (SubmoduleID PrevModID = PrevMI->getOwningModuleID()) - PrevOwner = Reader.getSubmodule(PrevModID); - SourceManager &SrcMgr = Reader.getSourceManager(); - bool PrevInSystem - = PrevOwner? PrevOwner->IsSystem - : SrcMgr.isInSystemHeader(PrevMI->getDefinitionLoc()); - bool NewInSystem - = NewOwner? NewOwner->IsSystem - : SrcMgr.isInSystemHeader(NewMI->getDefinitionLoc()); - if (PrevOwner && PrevOwner == NewOwner) - return false; - return PrevInSystem && NewInSystem; -} - -void ASTReader::removeOverriddenMacros(IdentifierInfo *II, - SourceLocation ImportLoc, - AmbiguousMacros &Ambig, - ArrayRef<SubmoduleID> Overrides) { - for (unsigned OI = 0, ON = Overrides.size(); OI != ON; ++OI) { - SubmoduleID OwnerID = Overrides[OI]; - - // If this macro is not yet visible, remove it from the hidden names list. - // It won't be there if we're in the middle of making the owner visible. - Module *Owner = getSubmodule(OwnerID); - auto HiddenIt = HiddenNamesMap.find(Owner); - if (HiddenIt != HiddenNamesMap.end()) { - HiddenNames &Hidden = HiddenIt->second; - HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II); - if (HI != Hidden.HiddenMacros.end()) { - // Register the macro now so we don't lose it when we re-export. - PP.appendMacroDirective(II, HI->second->import(PP, ImportLoc)); - - auto SubOverrides = HI->second->getOverriddenSubmodules(); - Hidden.HiddenMacros.erase(HI); - removeOverriddenMacros(II, ImportLoc, Ambig, SubOverrides); - } - } - - // If this macro is already in our list of conflicts, remove it from there. - Ambig.erase( - std::remove_if(Ambig.begin(), Ambig.end(), [&](DefMacroDirective *MD) { - return MD->getInfo()->getOwningModuleID() == OwnerID; - }), - Ambig.end()); - } -} - -ASTReader::AmbiguousMacros * -ASTReader::removeOverriddenMacros(IdentifierInfo *II, - SourceLocation ImportLoc, - ArrayRef<SubmoduleID> Overrides) { - MacroDirective *Prev = PP.getMacroDirective(II); - if (!Prev && Overrides.empty()) - return nullptr; - - DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective() - : nullptr; - if (PrevDef && PrevDef->isAmbiguous()) { - // We had a prior ambiguity. Check whether we resolve it (or make it worse). - AmbiguousMacros &Ambig = AmbiguousMacroDefs[II]; - Ambig.push_back(PrevDef); - - removeOverriddenMacros(II, ImportLoc, Ambig, Overrides); - - if (!Ambig.empty()) - return &Ambig; - - AmbiguousMacroDefs.erase(II); - } else { - // There's no ambiguity yet. Maybe we're introducing one. - AmbiguousMacros Ambig; - if (PrevDef) - Ambig.push_back(PrevDef); - - removeOverriddenMacros(II, ImportLoc, Ambig, Overrides); - - if (!Ambig.empty()) { - AmbiguousMacros &Result = AmbiguousMacroDefs[II]; - std::swap(Result, Ambig); - return &Result; - } - } - - // We ended up with no ambiguity. - return nullptr; -} - -void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI, - Module *Owner) { - assert(II && Owner); - - SourceLocation ImportLoc = Owner->MacroVisibilityLoc; - if (ImportLoc.isInvalid()) { - // FIXME: If we made macros from this module visible but didn't provide a - // source location for the import, we don't have a location for the macro. - // Use the location at which the containing module file was first imported - // for now. - ImportLoc = MMI->F->DirectImportLoc; - assert(ImportLoc.isValid() && "no import location for a visible macro?"); - } - - AmbiguousMacros *Prev = - removeOverriddenMacros(II, ImportLoc, MMI->getOverriddenSubmodules()); - - // Create a synthetic macro definition corresponding to the import (or null - // if this was an undefinition of the macro). - MacroDirective *Imported = MMI->import(PP, ImportLoc); - DefMacroDirective *MD = dyn_cast<DefMacroDirective>(Imported); - - // If there's no ambiguity, just install the macro. - if (!Prev) { - PP.appendMacroDirective(II, Imported); - return; - } - assert(!Prev->empty()); - - if (!MD) { - // We imported a #undef that didn't remove all prior definitions. The most - // recent prior definition remains, and we install it in the place of the - // imported directive, as if by a local #pragma pop_macro. - MacroInfo *NewMI = Prev->back()->getInfo(); - Prev->pop_back(); - MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc); - - // Install our #undef first so that we don't lose track of it. We'll replace - // this with whichever macro definition ends up winning. - PP.appendMacroDirective(II, Imported); - } - - // We're introducing a macro definition that creates or adds to an ambiguity. - // We can resolve that ambiguity if this macro is token-for-token identical to - // all of the existing definitions. - MacroInfo *NewMI = MD->getInfo(); - assert(NewMI && "macro definition with no MacroInfo?"); - while (!Prev->empty()) { - MacroInfo *PrevMI = Prev->back()->getInfo(); - assert(PrevMI && "macro definition with no MacroInfo?"); - - // Before marking the macros as ambiguous, check if this is a case where - // both macros are in system headers. If so, we trust that the system - // did not get it wrong. This also handles cases where Clang's own - // headers have a different spelling of certain system macros: - // #define LONG_MAX __LONG_MAX__ (clang's limits.h) - // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h) - // - // FIXME: Remove the defined-in-system-headers check. clang's limits.h - // overrides the system limits.h's macros, so there's no conflict here. - if (NewMI != PrevMI && - !PrevMI->isIdenticalTo(*NewMI, PP, /*Syntactically=*/true) && - !areDefinedInSystemModules(PrevMI, NewMI, Owner, *this)) - break; - - // The previous definition is the same as this one (or both are defined in - // system modules so we can assume they're equivalent); we don't need to - // track it any more. - Prev->pop_back(); - } - - if (!Prev->empty()) - MD->setAmbiguous(true); - - PP.appendMacroDirective(II, MD); + if (Latest) + PP.setLoadedMacroDirective(II, Latest); } ASTReader::InputFileInfo @@ -2426,6 +2185,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, break; } + case KNOWN_MODULE_FILES: + break; + case LANGUAGE_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; // FIXME: The &F == *ModuleMgr.begin() check is wrong for modules. @@ -2440,7 +2202,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, case TARGET_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; if (Listener && &F == *ModuleMgr.begin() && - ParseTargetOptions(Record, Complain, *Listener) && + ParseTargetOptions(Record, Complain, *Listener, + AllowCompatibleConfigurationMismatch) && !DisableValidation && !AllowConfigurationMismatch) return ConfigurationMismatch; break; @@ -2543,7 +2306,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, case INPUT_FILE_OFFSETS: NumInputs = Record[0]; NumUserInputs = Record[1]; - F.InputFileOffsets = (const uint32_t *)Blob.data(); + F.InputFileOffsets = (const uint64_t *)Blob.data(); F.InputFilesLoaded.resize(NumInputs); break; } @@ -2795,6 +2558,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case EAGERLY_DESERIALIZED_DECLS: + // FIXME: Skip reading this record if our ASTConsumer doesn't care + // about "interesting" decls (for instance, if we're building a module). for (unsigned I = 0, N = Record.size(); I != N; ++I) EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); break; @@ -2859,11 +2624,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } break; - case LOCALLY_SCOPED_EXTERN_C_DECLS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - LocallyScopedExternCDecls.push_back(getGlobalDeclID(F, Record[I])); - break; - case SELECTOR_OFFSETS: { F.SelectorOffsets = (const uint32_t *)Blob.data(); F.LocalNumSelectors = Record[0]; @@ -3066,11 +2826,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } break; - case DYNAMIC_CLASSES: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - DynamicClasses.push_back(getGlobalDeclID(F, Record[I])); - break; - case PENDING_IMPLICIT_INSTANTIATIONS: if (PendingInstantiations.size() % 2 != 0) { Error("Invalid existing PendingInstantiations"); @@ -3172,16 +2927,26 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { case OBJC_CATEGORIES: F.ObjCCategories.swap(Record); break; - + case CXX_BASE_SPECIFIER_OFFSETS: { if (F.LocalNumCXXBaseSpecifiers != 0) { Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file"); return Failure; } - + F.LocalNumCXXBaseSpecifiers = Record[0]; F.CXXBaseSpecifiersOffsets = (const uint32_t *)Blob.data(); - NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers; + break; + } + + case CXX_CTOR_INITIALIZERS_OFFSETS: { + if (F.LocalNumCXXCtorInitializers != 0) { + Error("duplicate CXX_CTOR_INITIALIZERS_OFFSETS record in AST file"); + return Failure; + } + + F.LocalNumCXXCtorInitializers = Record[0]; + F.CXXCtorInitializersOffsets = (const uint32_t *)Blob.data(); break; } @@ -3256,6 +3021,18 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { ReadSourceLocation(F, Record, I).getRawEncoding()); } break; + case DELETE_EXPRS_TO_ANALYZE: + for (unsigned I = 0, N = Record.size(); I != N;) { + DelayedDeleteExprs.push_back(getGlobalDeclID(F, Record[I++])); + const uint64_t Count = Record[I++]; + DelayedDeleteExprs.push_back(Count); + for (uint64_t C = 0; C < Count; ++C) { + DelayedDeleteExprs.push_back(ReadSourceLocation(F, Record, I).getRawEncoding()); + bool IsArrayForm = Record[I++] == 1; + DelayedDeleteExprs.push_back(IsArrayForm); + } + } + break; case IMPORTED_MODULES: { if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) { @@ -3288,16 +3065,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; } - case MERGED_DECLARATIONS: { - for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) { - GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]); - SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID]; - for (unsigned N = Record[Idx++]; N > 0; --N) - Decls.push_back(getGlobalDeclID(F, Record[Idx++])); - } - break; - } - case MACRO_OFFSET: { if (F.LocalNumMacros != 0) { Error("duplicate MACRO_OFFSET record in AST file"); @@ -3322,11 +3089,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; } - case MACRO_TABLE: { - // FIXME: Not used yet. - break; - } - case LATE_PARSED_TEMPLATE: { LateParsedTemplates.append(Record.begin(), Record.end()); break; @@ -3472,10 +3234,9 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { } } -void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner, - bool FromFinalization) { - // FIXME: Only do this if Owner->NameVisibility == AllVisible. - for (Decl *D : Names.HiddenDecls) { +void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) { + assert(Owner->NameVisibility != Module::Hidden && "nothing to make visible?"); + for (Decl *D : Names) { bool wasHidden = D->Hidden; D->Hidden = false; @@ -3485,22 +3246,11 @@ void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner, } } } - - assert((FromFinalization || Owner->NameVisibility >= Module::MacrosVisible) && - "nothing to make visible?"); - for (const auto &Macro : Names.HiddenMacros) { - if (FromFinalization) - PP.appendMacroDirective(Macro.first, - Macro.second->import(PP, SourceLocation())); - else - installImportedMacro(Macro.first, Macro.second, Owner); - } } void ASTReader::makeModuleVisible(Module *Mod, Module::NameVisibilityKind NameVisibility, - SourceLocation ImportLoc, - bool Complain) { + SourceLocation ImportLoc) { llvm::SmallPtrSet<Module *, 4> Visited; SmallVector<Module *, 4> Stack; Stack.push_back(Mod); @@ -3519,9 +3269,6 @@ void ASTReader::makeModuleVisible(Module *Mod, } // Update the module's name visibility. - if (NameVisibility >= Module::MacrosVisible && - Mod->NameVisibility < Module::MacrosVisible) - Mod->MacroVisibilityLoc = ImportLoc; Mod->NameVisibility = NameVisibility; // If we've already deserialized any names from this module, @@ -3530,8 +3277,7 @@ void ASTReader::makeModuleVisible(Module *Mod, if (Hidden != HiddenNamesMap.end()) { auto HiddenNames = std::move(*Hidden); HiddenNamesMap.erase(Hidden); - makeNamesVisible(HiddenNames.second, HiddenNames.first, - /*FromFinalization*/false); + makeNamesVisible(HiddenNames.second, HiddenNames.first); assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() && "making names visible added hidden names"); } @@ -3545,20 +3291,6 @@ void ASTReader::makeModuleVisible(Module *Mod, if (Visited.insert(Exported).second) Stack.push_back(Exported); } - - // Detect any conflicts. - if (Complain) { - assert(ImportLoc.isValid() && "Missing import location"); - for (unsigned I = 0, N = Mod->Conflicts.size(); I != N; ++I) { - if (Mod->Conflicts[I].Other->NameVisibility >= NameVisibility) { - Diag(ImportLoc, diag::warn_module_conflict) - << Mod->getFullModuleName() - << Mod->Conflicts[I].Other->getFullModuleName() - << Mod->Conflicts[I].Message; - // FIXME: Need note where the other module was imported. - } - } - } } } @@ -3717,7 +3449,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, case UnresolvedModuleRef::Import: if (ResolvedMod) - Unresolved.Mod->Imports.push_back(ResolvedMod); + Unresolved.Mod->Imports.insert(ResolvedMod); continue; case UnresolvedModuleRef::Export: @@ -3785,6 +3517,14 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile); +/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'. +static bool startsWithASTFileMagic(BitstreamCursor &Stream) { + return Stream.Read(8) == 'C' && + Stream.Read(8) == 'P' && + Stream.Read(8) == 'C' && + Stream.Read(8) == 'H'; +} + ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, ModuleKind Type, @@ -3854,10 +3594,7 @@ ASTReader::ReadASTCore(StringRef FileName, F.SizeInBits = F.Buffer->getBufferSize() * 8; // Sniff for the signature. - if (Stream.Read(8) != 'C' || - Stream.Read(8) != 'P' || - Stream.Read(8) != 'C' || - Stream.Read(8) != 'H') { + if (!startsWithASTFileMagic(Stream)) { Diag(diag::err_not_a_pch_file) << FileName; return Failure; } @@ -3924,7 +3661,7 @@ ASTReader::ReadASTCore(StringRef FileName, return Success; } -void ASTReader::InitializeContext() { +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, @@ -4047,24 +3784,19 @@ void ASTReader::InitializeContext() { } // Re-export any modules that were imported by a non-module AST file. - // FIXME: This does not make macro-only imports visible again. It also doesn't - // make #includes mapped to module imports visible. + // FIXME: This does not make macro-only imports visible again. for (auto &Import : ImportedModules) { - if (Module *Imported = getSubmodule(Import.ID)) + if (Module *Imported = getSubmodule(Import.ID)) { makeModuleVisible(Imported, Module::AllVisible, - /*ImportLoc=*/Import.ImportLoc, - /*Complain=*/false); + /*ImportLoc=*/Import.ImportLoc); + PP.makeModuleVisible(Imported, Import.ImportLoc); + } } ImportedModules.clear(); } void ASTReader::finalizeForWriting() { - while (!HiddenNamesMap.empty()) { - auto HiddenNames = std::move(*HiddenNamesMap.begin()); - HiddenNamesMap.erase(HiddenNamesMap.begin()); - makeNamesVisible(HiddenNames.second, HiddenNames.first, - /*FromFinalization*/true); - } + // Nothing to do for now. } /// \brief Given a cursor at the start of an AST file, scan ahead and drop the @@ -4097,14 +3829,12 @@ static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) { } } +/// \brief Reads and return the signature record from \p StreamFile's control +/// block, or else returns 0. static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){ BitstreamCursor Stream(StreamFile); - if (Stream.Read(8) != 'C' || - Stream.Read(8) != 'P' || - Stream.Read(8) != 'C' || - Stream.Read(8) != 'H') { + if (!startsWithASTFileMagic(Stream)) return 0; - } // Scan for the CONTROL_BLOCK_ID block. if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID)) @@ -4146,10 +3876,7 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, BitstreamCursor Stream(StreamFile); // Sniff for the signature. - if (Stream.Read(8) != 'C' || - Stream.Read(8) != 'P' || - Stream.Read(8) != 'C' || - Stream.Read(8) != 'H') { + if (!startsWithASTFileMagic(Stream)) { Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName; return std::string(); } @@ -4184,16 +3911,19 @@ namespace { const LangOptions &ExistingLangOpts; const TargetOptions &ExistingTargetOpts; const PreprocessorOptions &ExistingPPOpts; + std::string ExistingModuleCachePath; FileManager &FileMgr; - + public: SimplePCHValidator(const LangOptions &ExistingLangOpts, const TargetOptions &ExistingTargetOpts, const PreprocessorOptions &ExistingPPOpts, + StringRef ExistingModuleCachePath, FileManager &FileMgr) : ExistingLangOpts(ExistingLangOpts), ExistingTargetOpts(ExistingTargetOpts), ExistingPPOpts(ExistingPPOpts), + ExistingModuleCachePath(ExistingModuleCachePath), FileMgr(FileMgr) { } @@ -4203,9 +3933,17 @@ namespace { return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr, AllowCompatibleDifferences); } - bool ReadTargetOptions(const TargetOptions &TargetOpts, - bool Complain) override { - return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr); + bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain, + bool AllowCompatibleDifferences) override { + return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr, + AllowCompatibleDifferences); + } + bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + StringRef SpecificModuleCachePath, + bool Complain) override { + return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath, + ExistingModuleCachePath, + nullptr, ExistingLangOpts); } bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, @@ -4220,6 +3958,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, ASTReaderListener &Listener) { // Open the AST file. + // FIXME: This allows use of the VFS; we do not allow use of the + // VFS when actually loading a module. auto Buffer = FileMgr.getBufferForFile(Filename); if (!Buffer) { return true; @@ -4232,12 +3972,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, BitstreamCursor Stream(StreamFile); // Sniff for the signature. - if (Stream.Read(8) != 'C' || - Stream.Read(8) != 'P' || - Stream.Read(8) != 'C' || - Stream.Read(8) != 'H') { + if (!startsWithASTFileMagic(Stream)) return true; - } // Scan for the CONTROL_BLOCK_ID block. if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID)) @@ -4310,7 +4046,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, break; case TARGET_OPTIONS: - if (ParseTargetOptions(Record, false, Listener)) + if (ParseTargetOptions(Record, false, Listener, + /*AllowCompatibleConfigurationMismatch*/ false)) return true; break; @@ -4343,7 +4080,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, unsigned NumInputFiles = Record[0]; unsigned NumUserFiles = Record[1]; - const uint32_t *InputFileOffs = (const uint32_t *)Blob.data(); + const uint64_t *InputFileOffs = (const uint64_t *)Blob.data(); for (unsigned I = 0; I != NumInputFiles; ++I) { // Go find this input file. bool isSystemFile = I >= NumUserFiles; @@ -4389,6 +4126,20 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, break; } + case KNOWN_MODULE_FILES: { + // Known-but-not-technically-used module files are treated as imports. + if (!NeedsImports) + break; + + unsigned Idx = 0, N = Record.size(); + while (Idx < N) { + std::string Filename = ReadString(Record, Idx); + ResolveImportedPath(Filename, ModuleDir); + Listener.visitImport(Filename); + } + break; + } + default: // No other validation to perform. break; @@ -4401,8 +4152,10 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, const LangOptions &LangOpts, const TargetOptions &TargetOpts, - const PreprocessorOptions &PPOpts) { - SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr); + const PreprocessorOptions &PPOpts, + std::string ExistingModuleCachePath) { + SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, + ExistingModuleCachePath, FileMgr); return !readASTFileControlBlock(Filename, FileMgr, validator); } @@ -4529,13 +4282,19 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case SUBMODULE_UMBRELLA_HEADER: { - if (const FileEntry *Umbrella = PP.getFileManager().getFile(Blob)) { + std::string Filename = Blob; + ResolveImportedPath(F, Filename); + if (auto *Umbrella = PP.getFileManager().getFile(Filename)) { if (!CurrentModule->getUmbrellaHeader()) - ModMap.setUmbrellaHeader(CurrentModule, Umbrella); - else if (CurrentModule->getUmbrellaHeader() != Umbrella) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Error("mismatched umbrella headers in submodule"); - return OutOfDate; + ModMap.setUmbrellaHeader(CurrentModule, Umbrella, Blob); + else if (CurrentModule->getUmbrellaHeader().Entry != Umbrella) { + // This can be a spurious difference caused by changing the VFS to + // point to a different copy of the file, and it is too late to + // to rebuild safely. + // FIXME: If we wrote the virtual paths instead of the 'real' paths, + // after input file validation only real problems would remain and we + // could just error. For now, assume it's okay. + break; } } break; @@ -4561,11 +4320,12 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case SUBMODULE_UMBRELLA_DIR: { - if (const DirectoryEntry *Umbrella - = PP.getFileManager().getDirectory(Blob)) { + std::string Dirname = Blob; + ResolveImportedPath(F, Dirname); + if (auto *Umbrella = PP.getFileManager().getDirectory(Dirname)) { if (!CurrentModule->getUmbrellaDir()) - ModMap.setUmbrellaDir(CurrentModule, Umbrella); - else if (CurrentModule->getUmbrellaDir() != Umbrella) { + ModMap.setUmbrellaDir(CurrentModule, Umbrella, Blob); + else if (CurrentModule->getUmbrellaDir().Entry != Umbrella) { if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) Error("mismatched umbrella directories in submodule"); return OutOfDate; @@ -4696,9 +4456,9 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record, AllowCompatibleDifferences); } -bool ASTReader::ParseTargetOptions(const RecordData &Record, - bool Complain, - ASTReaderListener &Listener) { +bool ASTReader::ParseTargetOptions(const RecordData &Record, bool Complain, + ASTReaderListener &Listener, + bool AllowCompatibleDifferences) { unsigned Idx = 0; TargetOptions TargetOpts; TargetOpts.Triple = ReadString(Record, Idx); @@ -4711,7 +4471,8 @@ bool ASTReader::ParseTargetOptions(const RecordData &Record, TargetOpts.Features.push_back(ReadString(Record, Idx)); } - return Listener.ReadTargetOptions(TargetOpts, Complain); + return Listener.ReadTargetOptions(TargetOpts, Complain, + AllowCompatibleDifferences); } bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain, @@ -4753,16 +4514,15 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, = static_cast<frontend::IncludeDirGroup>(Record[Idx++]); bool IsFramework = Record[Idx++]; bool IgnoreSysRoot = Record[Idx++]; - HSOpts.UserEntries.push_back( - HeaderSearchOptions::Entry(Path, Group, IsFramework, IgnoreSysRoot)); + HSOpts.UserEntries.emplace_back(std::move(Path), Group, IsFramework, + IgnoreSysRoot); } // System header prefixes. for (unsigned N = Record[Idx++]; N; --N) { std::string Prefix = ReadString(Record, Idx); bool IsSystemHeader = Record[Idx++]; - HSOpts.SystemHeaderPrefixes.push_back( - HeaderSearchOptions::SystemHeaderPrefix(Prefix, IsSystemHeader)); + HSOpts.SystemHeaderPrefixes.emplace_back(std::move(Prefix), IsSystemHeader); } HSOpts.ResourceDir = ReadString(Record, Idx); @@ -4773,8 +4533,10 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, HSOpts.UseStandardSystemIncludes = Record[Idx++]; HSOpts.UseStandardCXXIncludes = Record[Idx++]; HSOpts.UseLibcxx = Record[Idx++]; + std::string SpecificModuleCachePath = ReadString(Record, Idx); - return Listener.ReadHeaderSearchOptions(HSOpts, Complain); + return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath, + Complain); } bool ASTReader::ParsePreprocessorOptions(const RecordData &Record, @@ -4823,21 +4585,22 @@ ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) { return std::make_pair(M, LocalIndex); } -std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> +llvm::iterator_range<PreprocessingRecord::iterator> ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const { if (PreprocessingRecord *PPRec = PP.getPreprocessingRecord()) return PPRec->getIteratorsForLoadedRange(Mod.BasePreprocessedEntityID, Mod.NumPreprocessedEntities); - return std::make_pair(PreprocessingRecord::iterator(), - PreprocessingRecord::iterator()); + return llvm::make_range(PreprocessingRecord::iterator(), + PreprocessingRecord::iterator()); } -std::pair<ASTReader::ModuleDeclIterator, ASTReader::ModuleDeclIterator> +llvm::iterator_range<ASTReader::ModuleDeclIterator> ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) { - return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls), - ModuleDeclIterator(this, &Mod, - Mod.FileSortedDecls + Mod.NumFileSortedDecls)); + return llvm::make_range( + ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls), + ModuleDeclIterator(this, &Mod, + Mod.FileSortedDecls + Mod.NumFileSortedDecls)); } PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { @@ -4873,13 +4636,14 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { case PPD_MACRO_EXPANSION: { bool isBuiltin = Record[0]; IdentifierInfo *Name = nullptr; - MacroDefinition *Def = nullptr; + MacroDefinitionRecord *Def = nullptr; if (isBuiltin) Name = getLocalIdentifier(M, Record[1]); else { - PreprocessedEntityID - GlobalID = getGlobalPreprocessedEntityID(M, Record[1]); - Def =cast<MacroDefinition>(PPRec.getLoadedPreprocessedEntity(GlobalID-1)); + PreprocessedEntityID GlobalID = + getGlobalPreprocessedEntityID(M, Record[1]); + Def = cast<MacroDefinitionRecord>( + PPRec.getLoadedPreprocessedEntity(GlobalID - 1)); } MacroExpansion *ME; @@ -4895,8 +4659,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { // 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); + MacroDefinitionRecord *MD = new (PPRec) MacroDefinitionRecord(II, Range); if (DeserializationListener) DeserializationListener->MacroDefinitionRead(PPID, MD); @@ -6081,6 +5844,12 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) { return GetDecl(ID); } +template<typename TemplateSpecializationDecl> +static void completeRedeclChainForTemplateSpecialization(Decl *D) { + if (auto *TSD = dyn_cast<TemplateSpecializationDecl>(D)) + TSD->getSpecializedTemplate()->LoadLazySpecializations(); +} + void ASTReader::CompleteRedeclChain(const Decl *D) { if (NumCurrentElementsDeserializing) { // We arrange to not care about the complete redeclaration chain while we're @@ -6114,6 +5883,47 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { D->getDeclContext()->decls_begin(); } } + + if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) + CTSD->getSpecializedTemplate()->LoadLazySpecializations(); + if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) + VTSD->getSpecializedTemplate()->LoadLazySpecializations(); + if (auto *FD = dyn_cast<FunctionDecl>(D)) { + if (auto *Template = FD->getPrimaryTemplate()) + Template->LoadLazySpecializations(); + } +} + +uint64_t ASTReader::ReadCXXCtorInitializersRef(ModuleFile &M, + const RecordData &Record, + unsigned &Idx) { + if (Idx >= Record.size() || Record[Idx] > M.LocalNumCXXCtorInitializers) { + Error("malformed AST file: missing C++ ctor initializers"); + return 0; + } + + unsigned LocalID = Record[Idx++]; + return getGlobalBitOffset(M, M.CXXCtorInitializersOffsets[LocalID - 1]); +} + +CXXCtorInitializer ** +ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) { + RecordLocation Loc = getLocalBitOffset(Offset); + BitstreamCursor &Cursor = Loc.F->DeclsCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(Loc.Offset); + ReadingKindTracker ReadingKind(Read_Decl, *this); + + RecordData Record; + unsigned Code = Cursor.ReadCode(); + unsigned RecCode = Cursor.readRecord(Code, Record); + if (RecCode != DECL_CXX_CTOR_INITIALIZERS) { + Error("malformed AST file: missing C++ ctor initializers"); + return nullptr; + } + + unsigned Idx = 0; + return ReadCXXCtorInitializers(*Loc.F, Record, Idx); } uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, @@ -6165,6 +5975,10 @@ ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const { bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const { + // Predefined decls aren't from any module. + if (ID < NUM_PREDEF_DECL_IDS) + return false; + GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID); assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); return &M == I->second; @@ -6197,39 +6011,55 @@ SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { return ReadSourceLocation(*Rec.F, RawLocation); } -Decl *ASTReader::GetExistingDecl(DeclID ID) { - if (ID < NUM_PREDEF_DECL_IDS) { - switch ((PredefinedDeclIDs)ID) { - case PREDEF_DECL_NULL_ID: - return nullptr; +static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) { + switch (ID) { + case PREDEF_DECL_NULL_ID: + return nullptr; + + case PREDEF_DECL_TRANSLATION_UNIT_ID: + return Context.getTranslationUnitDecl(); - case PREDEF_DECL_TRANSLATION_UNIT_ID: - return Context.getTranslationUnitDecl(); + case PREDEF_DECL_OBJC_ID_ID: + return Context.getObjCIdDecl(); - case PREDEF_DECL_OBJC_ID_ID: - return Context.getObjCIdDecl(); + case PREDEF_DECL_OBJC_SEL_ID: + return Context.getObjCSelDecl(); - case PREDEF_DECL_OBJC_SEL_ID: - return Context.getObjCSelDecl(); + case PREDEF_DECL_OBJC_CLASS_ID: + return Context.getObjCClassDecl(); - case PREDEF_DECL_OBJC_CLASS_ID: - return Context.getObjCClassDecl(); + case PREDEF_DECL_OBJC_PROTOCOL_ID: + return Context.getObjCProtocolDecl(); - case PREDEF_DECL_OBJC_PROTOCOL_ID: - return Context.getObjCProtocolDecl(); + case PREDEF_DECL_INT_128_ID: + return Context.getInt128Decl(); - case PREDEF_DECL_INT_128_ID: - return Context.getInt128Decl(); + case PREDEF_DECL_UNSIGNED_INT_128_ID: + return Context.getUInt128Decl(); - case PREDEF_DECL_UNSIGNED_INT_128_ID: - return Context.getUInt128Decl(); + case PREDEF_DECL_OBJC_INSTANCETYPE_ID: + return Context.getObjCInstanceTypeDecl(); - case PREDEF_DECL_OBJC_INSTANCETYPE_ID: - return Context.getObjCInstanceTypeDecl(); + case PREDEF_DECL_BUILTIN_VA_LIST_ID: + return Context.getBuiltinVaListDecl(); - case PREDEF_DECL_BUILTIN_VA_LIST_ID: - return Context.getBuiltinVaListDecl(); + case PREDEF_DECL_EXTERN_C_CONTEXT_ID: + return Context.getExternCContextDecl(); + } + llvm_unreachable("PredefinedDeclIDs unknown enum value"); +} + +Decl *ASTReader::GetExistingDecl(DeclID ID) { + if (ID < NUM_PREDEF_DECL_IDS) { + Decl *D = getPredefinedDecl(Context, (PredefinedDeclIDs)ID); + if (D) { + // Track that we have merged the declaration with ID \p ID into the + // pre-existing predefined declaration \p D. + auto &Merged = MergedDecls[D->getCanonicalDecl()]; + if (Merged.empty()) + Merged.push_back(ID); } + return D; } unsigned Index = ID - NUM_PREDEF_DECL_IDS; @@ -6326,10 +6156,7 @@ namespace { PredefsVisited[I] = false; } - static bool visit(ModuleFile &M, bool Preorder, void *UserData) { - if (Preorder) - return false; - + static bool visitPostorder(ModuleFile &M, void *UserData) { FindExternalLexicalDeclsVisitor *This = static_cast<FindExternalLexicalDeclsVisitor *>(UserData); @@ -6371,7 +6198,8 @@ ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC, // 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); + ModuleMgr.visitDepthFirst( + nullptr, &FindExternalLexicalDeclsVisitor::visitPostorder, &Visitor); ++NumLexicalDeclContextsRead; return ELR_Success; } @@ -6460,13 +6288,16 @@ namespace { ArrayRef<const DeclContext *> Contexts; DeclarationName Name; SmallVectorImpl<NamedDecl *> &Decls; + llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet; public: DeclContextNameLookupVisitor(ASTReader &Reader, ArrayRef<const DeclContext *> Contexts, DeclarationName Name, - SmallVectorImpl<NamedDecl *> &Decls) - : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { } + SmallVectorImpl<NamedDecl *> &Decls, + llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet) + : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls), + DeclSet(DeclSet) { } static bool visit(ModuleFile &M, void *UserData) { DeclContextNameLookupVisitor *This @@ -6515,7 +6346,8 @@ namespace { // Record this declaration. FoundAnything = true; - This->Decls.push_back(ND); + if (This->DeclSet.insert(ND).second) + This->Decls.push_back(ND); } return FoundAnything; @@ -6555,6 +6387,7 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, Deserializing LookupResults(this); SmallVector<NamedDecl *, 64> Decls; + llvm::SmallPtrSet<NamedDecl*, 64> DeclSet; // Compute the declaration contexts we need to look into. Multiple such // declaration contexts occur when two declaration contexts from disjoint @@ -6572,7 +6405,7 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, } auto LookUpInContexts = [&](ArrayRef<const DeclContext*> Contexts) { - DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls); + DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls, DeclSet); // If we can definitively determine which module file to look into, // only look there. Otherwise, look in all module files. @@ -6592,19 +6425,14 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, // individually, because finding an entity in one of them doesn't imply that // we can't find a different entity in another one. if (isa<CXXRecordDecl>(DC)) { - auto Kind = Name.getNameKind(); - if (Kind == DeclarationName::CXXConstructorName || - Kind == DeclarationName::CXXDestructorName || - (Kind == DeclarationName::CXXOperatorName && - Name.getCXXOverloadedOperator() == OO_Equal)) { - auto Merged = MergedLookups.find(DC); - if (Merged != MergedLookups.end()) { - for (unsigned I = 0; I != Merged->second.size(); ++I) { - LookUpInContexts(Merged->second[I]); - // We might have just added some more merged lookups. If so, our - // iterator is now invalid, so grab a fresh one before continuing. - Merged = MergedLookups.find(DC); - } + auto Merged = MergedLookups.find(DC); + if (Merged != MergedLookups.end()) { + for (unsigned I = 0; I != Merged->second.size(); ++I) { + const DeclContext *Context = Merged->second[I]; + LookUpInContexts(Context); + // We might have just added some more merged lookups. If so, our + // iterator is now invalid, so grab a fresh one before continuing. + Merged = MergedLookups.find(DC); } } } @@ -6621,6 +6449,7 @@ namespace { ASTReader &Reader; SmallVectorImpl<const DeclContext *> &Contexts; DeclsMap &Decls; + llvm::SmallPtrSet<NamedDecl *, 256> DeclSet; bool VisitAll; public: @@ -6665,7 +6494,8 @@ namespace { // Record this declaration. FoundAnything = true; - This->Decls[ND->getDeclName()].push_back(ND); + if (This->DeclSet.insert(ND).second) + This->Decls[ND->getDeclName()].push_back(ND); } } @@ -6731,6 +6561,12 @@ void ASTReader::PassInterestingDeclsToConsumer() { SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, true); + // Ensure that we've loaded all potentially-interesting declarations + // that need to be eagerly loaded. + for (auto ID : EagerlyDeserializedDecls) + GetDecl(ID); + EagerlyDeserializedDecls.clear(); + while (!InterestingDecls.empty()) { Decl *D = InterestingDecls.front(); InterestingDecls.pop_front(); @@ -6749,17 +6585,11 @@ void ASTReader::PassInterestingDeclToConsumer(Decl *D) { void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) { this->Consumer = Consumer; - if (!Consumer) - return; + if (Consumer) + PassInterestingDeclsToConsumer(); - for (unsigned I = 0, N = EagerlyDeserializedDecls.size(); I != N; ++I) { - // Force deserialization of this decl, which will cause it to be queued for - // passing to the consumer. - GetDecl(EagerlyDeserializedDecls[I]); - } - EagerlyDeserializedDecls.clear(); - - PassInterestingDeclsToConsumer(); + if (DeserializationListener) + DeserializationListener->ReaderInitialized(this); } void ASTReader::PrintStats() { @@ -7195,6 +7025,21 @@ void ASTReader::ReadUndefinedButUsed( } } +void ASTReader::ReadMismatchingDeleteExpressions(llvm::MapVector< + FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> & + Exprs) { + for (unsigned Idx = 0, N = DelayedDeleteExprs.size(); Idx != N;) { + FieldDecl *FD = cast<FieldDecl>(GetDecl(DelayedDeleteExprs[Idx++])); + uint64_t Count = DelayedDeleteExprs[Idx++]; + for (uint64_t C = 0; C < Count; ++C) { + SourceLocation DeleteLoc = + SourceLocation::getFromRawEncoding(DelayedDeleteExprs[Idx++]); + const bool IsArrayForm = DelayedDeleteExprs[Idx++]; + Exprs[FD].push_back(std::make_pair(DeleteLoc, IsArrayForm)); + } + } +} + void ASTReader::ReadTentativeDefinitions( SmallVectorImpl<VarDecl *> &TentativeDefs) { for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { @@ -7237,16 +7082,6 @@ void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) { 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::ReadUnusedLocalTypedefNameCandidates( llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) { for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N; @@ -7259,17 +7094,6 @@ void ASTReader::ReadUnusedLocalTypedefNameCandidates( UnusedLocalTypedefNameCandidates.clear(); } -void -ASTReader::ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl *> &Decls) { - for (unsigned I = 0, N = LocallyScopedExternCDecls.size(); I != N; ++I) { - NamedDecl *D - = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternCDecls[I])); - if (D) - Decls.push_back(D); - } - LocallyScopedExternCDecls.clear(); -} - void ASTReader::ReadReferencedSelectors( SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) { if (ReferencedSelectorsData.empty()) @@ -7333,7 +7157,7 @@ void ASTReader::ReadPendingInstantiations( } void ASTReader::ReadLateParsedTemplates( - llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) { + llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) { for (unsigned Idx = 0, N = LateParsedTemplates.size(); Idx < N; /* In loop */) { FunctionDecl *FD = cast<FunctionDecl>(GetDecl(LateParsedTemplates[Idx++])); @@ -7349,7 +7173,7 @@ void ASTReader::ReadLateParsedTemplates( for (unsigned T = 0; T < TokN; ++T) LT->Toks.push_back(ReadToken(*F, LateParsedTemplates, Idx)); - LPTMap[FD] = LT; + LPTMap.insert(std::make_pair(FD, LT)); } LateParsedTemplates.clear(); @@ -7840,92 +7664,89 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F, return Result; } -std::pair<CXXCtorInitializer **, unsigned> +CXXCtorInitializer ** ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx) { - CXXCtorInitializer **CtorInitializers = nullptr; unsigned NumInitializers = Record[Idx++]; - if (NumInitializers) { - CtorInitializers - = new (Context) CXXCtorInitializer*[NumInitializers]; - for (unsigned i=0; i != NumInitializers; ++i) { - TypeSourceInfo *TInfo = nullptr; - bool IsBaseVirtual = false; - FieldDecl *Member = nullptr; - IndirectFieldDecl *IndirectMember = nullptr; - - CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; - switch (Type) { - case CTOR_INITIALIZER_BASE: - TInfo = GetTypeSourceInfo(F, Record, Idx); - IsBaseVirtual = Record[Idx++]; - break; - - case CTOR_INITIALIZER_DELEGATING: - TInfo = GetTypeSourceInfo(F, Record, Idx); - break; + assert(NumInitializers && "wrote ctor initializers but have no inits"); + auto **CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; + for (unsigned i = 0; i != NumInitializers; ++i) { + TypeSourceInfo *TInfo = nullptr; + bool IsBaseVirtual = false; + FieldDecl *Member = nullptr; + IndirectFieldDecl *IndirectMember = nullptr; - case CTOR_INITIALIZER_MEMBER: - Member = ReadDeclAs<FieldDecl>(F, Record, Idx); - break; + CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; + switch (Type) { + case CTOR_INITIALIZER_BASE: + TInfo = GetTypeSourceInfo(F, Record, Idx); + IsBaseVirtual = Record[Idx++]; + break; - case CTOR_INITIALIZER_INDIRECT_MEMBER: - IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx); - break; - } + case CTOR_INITIALIZER_DELEGATING: + TInfo = GetTypeSourceInfo(F, Record, Idx); + break; - SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx); - Expr *Init = ReadExpr(F); - SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); - SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); - bool IsWritten = Record[Idx++]; - unsigned SourceOrderOrNumArrayIndices; - SmallVector<VarDecl *, 8> Indices; - if (IsWritten) { - SourceOrderOrNumArrayIndices = Record[Idx++]; - } else { - SourceOrderOrNumArrayIndices = Record[Idx++]; - Indices.reserve(SourceOrderOrNumArrayIndices); - for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i) - Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx)); - } + case CTOR_INITIALIZER_MEMBER: + Member = ReadDeclAs<FieldDecl>(F, Record, Idx); + break; - CXXCtorInitializer *BOMInit; - if (Type == CTOR_INITIALIZER_BASE) { - BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual, - LParenLoc, Init, RParenLoc, - MemberOrEllipsisLoc); - } else if (Type == CTOR_INITIALIZER_DELEGATING) { - BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc, - Init, RParenLoc); - } else if (IsWritten) { - if (Member) - BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, - LParenLoc, Init, RParenLoc); - else - BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember, - MemberOrEllipsisLoc, LParenLoc, - Init, RParenLoc); + case CTOR_INITIALIZER_INDIRECT_MEMBER: + IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx); + break; + } + + SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx); + Expr *Init = ReadExpr(F); + SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); + SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); + bool IsWritten = Record[Idx++]; + unsigned SourceOrderOrNumArrayIndices; + SmallVector<VarDecl *, 8> Indices; + if (IsWritten) { + SourceOrderOrNumArrayIndices = Record[Idx++]; + } else { + SourceOrderOrNumArrayIndices = Record[Idx++]; + Indices.reserve(SourceOrderOrNumArrayIndices); + for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i) + Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx)); + } + + CXXCtorInitializer *BOMInit; + if (Type == CTOR_INITIALIZER_BASE) { + BOMInit = new (Context) + CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init, + RParenLoc, MemberOrEllipsisLoc); + } else if (Type == CTOR_INITIALIZER_DELEGATING) { + BOMInit = new (Context) + CXXCtorInitializer(Context, TInfo, LParenLoc, Init, RParenLoc); + } else if (IsWritten) { + if (Member) + BOMInit = new (Context) CXXCtorInitializer( + Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc); + else + BOMInit = new (Context) + CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, + LParenLoc, Init, RParenLoc); + } else { + if (IndirectMember) { + assert(Indices.empty() && "Indirect field improperly initialized"); + BOMInit = new (Context) + CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, + LParenLoc, Init, RParenLoc); } else { - if (IndirectMember) { - assert(Indices.empty() && "Indirect field improperly initialized"); - BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember, - MemberOrEllipsisLoc, LParenLoc, - Init, RParenLoc); - } else { - BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc, - LParenLoc, Init, RParenLoc, - Indices.data(), Indices.size()); - } + BOMInit = CXXCtorInitializer::Create( + Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc, + Indices.data(), Indices.size()); } - - if (IsWritten) - BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices); - CtorInitializers[i] = BOMInit; } + + if (IsWritten) + BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices); + CtorInitializers[i] = BOMInit; } - return std::make_pair(CtorInitializers, NumInitializers); + return CtorInitializers; } NestedNameSpecifier * @@ -8203,7 +8024,7 @@ void ASTReader::getInputFiles(ModuleFile &F, std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { // If we know the owning module, use it. - if (Module *M = D->getOwningModule()) + if (Module *M = D->getImportedOwningModule()) return M->getFullModuleName(); // Otherwise, use the name of the top-level module the decl is within. @@ -8243,9 +8064,10 @@ void ASTReader::finishPendingActions() { // Load pending declaration chains. for (unsigned I = 0; I != PendingDeclChains.size(); ++I) { - loadPendingDeclChain(PendingDeclChains[I]); PendingDeclChainsKnown.erase(PendingDeclChains[I]); + loadPendingDeclChain(PendingDeclChains[I]); } + assert(PendingDeclChainsKnown.empty()); PendingDeclChains.clear(); // Make the most recent of the top-level declarations visible. @@ -8298,7 +8120,12 @@ void ASTReader::finishPendingActions() { loadDeclUpdateRecords(Update.first, Update.second); } } - + + // At this point, all update records for loaded decls are in place, so any + // fake class definitions should have become real. + assert(PendingFakeDefinitionData.empty() && + "faked up a class definition but never saw the real one"); + // If we deserialized any C++ or Objective-C class definitions, any // Objective-C protocol definitions, or any redeclarable templates, make sure // that all redeclarations point to the definitions. Note that this can only @@ -8309,10 +8136,12 @@ void ASTReader::finishPendingActions() { // Make sure that the TagType points at the definition. const_cast<TagType*>(TagT)->decl = TD; } - + if (auto RD = dyn_cast<CXXRecordDecl>(D)) { - for (auto R : RD->redecls()) { - assert((R == D) == R->isThisDeclarationADefinition() && + for (auto *R = getMostRecentExistingDecl(RD); R; + R = R->getPreviousDecl()) { + assert((R == D) == + cast<CXXRecordDecl>(R)->isThisDeclarationADefinition() && "declaration thinks it's the definition but it isn't"); cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData; } @@ -8320,34 +8149,36 @@ void ASTReader::finishPendingActions() { continue; } - + if (auto ID = dyn_cast<ObjCInterfaceDecl>(D)) { // Make sure that the ObjCInterfaceType points at the definition. const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl)) ->Decl = ID; - - for (auto R : ID->redecls()) - R->Data = ID->Data; - + + for (auto *R = getMostRecentExistingDecl(ID); R; R = R->getPreviousDecl()) + cast<ObjCInterfaceDecl>(R)->Data = ID->Data; + continue; } - + if (auto PD = dyn_cast<ObjCProtocolDecl>(D)) { - for (auto R : PD->redecls()) - R->Data = PD->Data; - + for (auto *R = getMostRecentExistingDecl(PD); R; R = R->getPreviousDecl()) + cast<ObjCProtocolDecl>(R)->Data = PD->Data; + continue; } - + auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl(); - for (auto R : RTD->redecls()) - R->Common = RTD->Common; + for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl()) + cast<RedeclarableTemplateDecl>(R)->Common = RTD->Common; } PendingDefinitions.clear(); // Load the bodies of any functions or methods we've encountered. We do // this now (delayed) so that we can be sure that the declaration chains // have been fully wired up. + // FIXME: There seems to be no point in delaying this, it does not depend + // on the redecl chains having been wired up. for (PendingBodiesMap::iterator PB = PendingBodies.begin(), PBEnd = PendingBodies.end(); PB != PBEnd; ++PB) { @@ -8364,6 +8195,11 @@ void ASTReader::finishPendingActions() { MD->setLazyBody(PB->second); } PendingBodies.clear(); + + // Do some cleanup. + for (auto *ND : PendingMergedDefinitionsToDeduplicate) + getContext().deduplicateMergedDefinitonsFor(ND); + PendingMergedDefinitionsToDeduplicate.clear(); } void ASTReader::diagnoseOdrViolations() { @@ -8440,6 +8276,10 @@ void ASTReader::diagnoseOdrViolations() { // completed. We only really need to mark FieldDecls as invalid here. if (!isa<TagDecl>(D)) D->setInvalidDecl(); + + // Ensure we don't accidentally recursively enter deserialization while + // we're producing our diagnostic. + Deserializing RecursionGuard(this); std::string CanonDefModule = getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef)); @@ -8461,6 +8301,13 @@ void ASTReader::diagnoseOdrViolations() { } } + if (OdrMergeFailures.empty()) + return; + + // Ensure we don't accidentally recursively enter deserialization while + // we're producing our diagnostics. + Deserializing RecursionGuard(this); + // Issue any pending ODR-failure diagnostics. for (auto &Merge : OdrMergeFailures) { // If we've already pointed out a specific problem with this class, don't @@ -8514,6 +8361,17 @@ void ASTReader::FinishedDeserializing() { --NumCurrentElementsDeserializing; if (NumCurrentElementsDeserializing == 0) { + // Propagate exception specification updates along redeclaration chains. + while (!PendingExceptionSpecUpdates.empty()) { + auto Updates = std::move(PendingExceptionSpecUpdates); + PendingExceptionSpecUpdates.clear(); + for (auto Update : Updates) { + auto *FPT = Update.second->getType()->castAs<FunctionProtoType>(); + SemaObj->UpdateExceptionSpec(Update.second, + FPT->getExtProtoInfo().ExceptionSpec); + } + } + diagnoseOdrViolations(); // We are not in recursive loading, so it's safe to pass the "interesting" @@ -8524,7 +8382,18 @@ void ASTReader::FinishedDeserializing() { } void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { - D = D->getMostRecentDecl(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) { + // Remove any fake results before adding any real ones. + auto It = PendingFakeLookupResults.find(II); + if (It != PendingFakeLookupResults.end()) { + for (auto *ND : PendingFakeLookupResults[II]) + SemaObj->IdResolver.RemoveDecl(ND); + // FIXME: this works around module+PCH performance issue. + // Rather than erase the result from the map, which is O(n), just clear + // the vector of NamedDecls. + It->second.clear(); + } + } if (SemaObj->IdResolver.tryAddTopLevelDecl(D, Name) && SemaObj->TUScope) { SemaObj->TUScope->AddDecl(D); @@ -8562,8 +8431,7 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot, NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), - PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0), - ReadingKind(Read_None) { + PassingDeclsToConsumer(false), ReadingKind(Read_None) { SourceMgr.setExternalSLocEntrySource(this); } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp index a783183..02273ed 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp @@ -66,7 +66,12 @@ namespace clang { serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) { return Reader.ReadDeclID(F, R, I); } - + + void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) { + for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I) + IDs.push_back(ReadDeclID(Record, Idx)); + } + Decl *ReadDecl(const RecordData &R, unsigned &I) { return Reader.ReadDecl(F, R, I); } @@ -103,11 +108,11 @@ namespace clang { return Reader.getSubmodule(readSubmoduleID(R, I)); } - void ReadCXXRecordDefinition(CXXRecordDecl *D); + void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update); void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, const RecordData &R, unsigned &I); void MergeDefinitionData(CXXRecordDecl *D, - struct CXXRecordDecl::DefinitionData &NewDD); + struct CXXRecordDecl::DefinitionData &&NewDD); static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, @@ -118,43 +123,42 @@ namespace clang { /// \brief RAII class used to capture the first ID within a redeclaration /// chain and to introduce it into the list of pending redeclaration chains /// on destruction. - /// - /// The caller can choose not to introduce this ID into the list of pending - /// redeclaration chains by calling \c suppress(). class RedeclarableResult { ASTReader &Reader; GlobalDeclID FirstID; + Decl *MergeWith; mutable bool Owning; Decl::Kind DeclKind; - - void operator=(RedeclarableResult &) LLVM_DELETED_FUNCTION; - + + void operator=(RedeclarableResult &) = delete; + public: RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID, - Decl::Kind DeclKind) - : Reader(Reader), FirstID(FirstID), Owning(true), DeclKind(DeclKind) { } - - RedeclarableResult(const RedeclarableResult &Other) - : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) , - DeclKind(Other.DeclKind) - { + Decl *MergeWith, Decl::Kind DeclKind) + : Reader(Reader), FirstID(FirstID), MergeWith(MergeWith), + Owning(true), DeclKind(DeclKind) {} + + RedeclarableResult(RedeclarableResult &&Other) + : Reader(Other.Reader), FirstID(Other.FirstID), + MergeWith(Other.MergeWith), Owning(Other.Owning), + DeclKind(Other.DeclKind) { Other.Owning = false; } ~RedeclarableResult() { - if (FirstID && Owning && isRedeclarableDeclKind(DeclKind) && - Reader.PendingDeclChainsKnown.insert(FirstID).second) - Reader.PendingDeclChains.push_back(FirstID); + if (FirstID && Owning && isRedeclarableDeclKind(DeclKind)) { + auto Canon = Reader.GetDecl(FirstID)->getCanonicalDecl(); + if (Reader.PendingDeclChainsKnown.insert(Canon).second) + Reader.PendingDeclChains.push_back(Canon); + } } - + /// \brief Retrieve the first ID. GlobalDeclID getFirstID() const { return FirstID; } - - /// \brief Do not introduce this declaration ID into the set of pending - /// declaration chains. - void suppress() { - Owning = false; - } + + /// \brief Get a known declaration that this should be merged with, if + /// any. + Decl *getKnownMergeTarget() const { return MergeWith; } }; /// \brief Class used to capture the result of searching for an existing @@ -171,7 +175,7 @@ namespace clang { unsigned AnonymousDeclNumber; IdentifierInfo *TypedefNameForLinkage; - void operator=(FindExistingResult&) LLVM_DELETED_FUNCTION; + void operator=(FindExistingResult&) = delete; public: FindExistingResult(ASTReader &Reader) @@ -205,6 +209,8 @@ namespace clang { operator T*() const { return dyn_cast_or_null<T>(Existing); } }; + static DeclContext *getPrimaryContextForMerging(ASTReader &Reader, + DeclContext *DC); FindExistingResult findExisting(NamedDecl *D); public: @@ -216,10 +222,17 @@ namespace clang { TypedefNameForLinkage(nullptr), HasPendingBody(false) {} template <typename DeclT> + static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D); + static Decl *getMostRecentDeclImpl(...); + static Decl *getMostRecentDecl(Decl *D); + + template <typename DeclT> static void attachPreviousDeclImpl(ASTReader &Reader, - Redeclarable<DeclT> *D, Decl *Previous); + Redeclarable<DeclT> *D, Decl *Previous, + Decl *Canon); static void attachPreviousDeclImpl(ASTReader &Reader, ...); - static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous); + static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous, + Decl *Canon); template <typename DeclT> static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest); @@ -390,9 +403,14 @@ void ASTDeclReader::Visit(Decl *D) { // FunctionDecl's body was written last after all other Stmts/Exprs. // We only read it if FD doesn't already have a body (e.g., from another // module). - // FIXME: Also consider = default and = delete. // FIXME: Can we diagnose ODR violations somehow? if (Record[Idx++]) { + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { + CD->NumCtorInitializers = Record[Idx++]; + if (CD->NumCtorInitializers) + CD->CtorInitializers = + Reader.ReadCXXCtorInitializersRef(F, Record, Idx); + } Reader.PendingBodies[FD] = GetCurrentCursorOffset(); HasPendingBody = true; } @@ -440,24 +458,28 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->FromASTFile = true; D->setModulePrivate(Record[Idx++]); D->Hidden = D->isModulePrivate(); - + // Determine whether this declaration is part of a (sub)module. If so, it // may not yet be visible. if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) { // Store the owning submodule ID in the declaration. D->setOwningModuleID(SubmoduleID); - - // Module-private declarations are never visible, so there is no work to do. - if (!D->isModulePrivate()) { - if (Module *Owner = Reader.getSubmodule(SubmoduleID)) { - if (Owner->NameVisibility != Module::AllVisible) { - // The owning module is not visible. Mark this declaration as hidden. - D->Hidden = true; - - // Note that this declaration was hidden because its owning module is - // not yet visible. - Reader.HiddenNamesMap[Owner].HiddenDecls.push_back(D); - } + + if (D->Hidden) { + // Module-private declarations are never visible, so there is no work to do. + } else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) { + // If local visibility is being tracked, this declaration will become + // hidden and visible as the owning module does. Inform Sema that this + // declaration might not be visible. + D->Hidden = true; + } else if (Module *Owner = Reader.getSubmodule(SubmoduleID)) { + if (Owner->NameVisibility != Module::AllVisible) { + // The owning module is not visible. Mark this declaration as hidden. + D->Hidden = true; + + // Note that this declaration was hidden because its owning module is + // not yet visible. + Reader.HiddenNamesMap[Owner].push_back(D); } } } @@ -470,8 +492,7 @@ void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) { VisitDecl(ND); ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx)); - if (needsAnonymousDeclarationNumber(ND)) - AnonymousDeclNumber = Record[Idx++]; + AnonymousDeclNumber = Record[Idx++]; } void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { @@ -981,8 +1002,9 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); D->setHasNonZeroConstructors(Record[Idx++]); D->setHasDestructors(Record[Idx++]); - std::tie(D->IvarInitializers, D->NumIvarInitializers) = - Reader.ReadCXXCtorInitializers(F, Record, Idx); + D->NumIvarInitializers = Record[Idx++]; + if (D->NumIvarInitializers) + D->IvarInitializers = Reader.ReadCXXCtorInitializersRef(F, Record, Idx); } @@ -1041,13 +1063,15 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->VarDeclBits.SClass = (StorageClass)Record[Idx++]; VD->VarDeclBits.TSCSpec = Record[Idx++]; VD->VarDeclBits.InitStyle = Record[Idx++]; - VD->VarDeclBits.ExceptionVar = Record[Idx++]; - VD->VarDeclBits.NRVOVariable = Record[Idx++]; - VD->VarDeclBits.CXXForRangeDecl = Record[Idx++]; - VD->VarDeclBits.ARCPseudoStrong = Record[Idx++]; - VD->VarDeclBits.IsConstexpr = Record[Idx++]; - VD->VarDeclBits.IsInitCapture = Record[Idx++]; - VD->VarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++]; + if (!isa<ParmVarDecl>(VD)) { + VD->NonParmVarDeclBits.ExceptionVar = Record[Idx++]; + VD->NonParmVarDeclBits.NRVOVariable = Record[Idx++]; + VD->NonParmVarDeclBits.CXXForRangeDecl = Record[Idx++]; + VD->NonParmVarDeclBits.ARCPseudoStrong = Record[Idx++]; + VD->NonParmVarDeclBits.IsConstexpr = Record[Idx++]; + VD->NonParmVarDeclBits.IsInitCapture = Record[Idx++]; + VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++]; + } Linkage VarLinkage = Linkage(Record[Idx++]); VD->setCachedLinkage(VarLinkage); @@ -1189,13 +1213,13 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { D->LocStart = ReadSourceLocation(Record, Idx); D->RBraceLoc = ReadSourceLocation(Record, Idx); + // Defer loading the anonymous namespace until we've finished merging + // this namespace; loading it might load a later declaration of the + // same namespace, and we have an invariant that older declarations + // get merged before newer ones try to merge. + GlobalDeclID AnonNamespace = 0; if (Redecl.getFirstID() == ThisDeclID) { - // Each module has its own anonymous namespace, which is disjoint from - // any other module's anonymous namespaces, so don't attach the anonymous - // namespace at all. - NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx); - if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) - D->setAnonymousNamespace(Anon); + AnonNamespace = ReadDeclID(Record, Idx); } else { // Link this namespace back to the first declaration, which has already // been deserialized. @@ -1203,6 +1227,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { } mergeRedeclarable(D, Redecl); + + if (AnonNamespace) { + // Each module has its own anonymous namespace, which is disjoint from + // any other module's anonymous namespaces, so don't attach the anonymous + // namespace at all. + NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace)); + if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) + D->setAnonymousNamespace(Anon); + } } void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { @@ -1353,7 +1386,7 @@ void ASTDeclReader::ReadCXXDefinitionData( } void ASTDeclReader::MergeDefinitionData( - CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &MergeDD) { + CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&MergeDD) { assert(D->DefinitionData.getNotUpdated() && "merging class definition into non-definition"); auto &DD = *D->DefinitionData.getNotUpdated(); @@ -1364,14 +1397,45 @@ void ASTDeclReader::MergeDefinitionData( // FIXME: We only need to do this if the merged definition declares members // that this definition did not declare, or if it defines members that this // definition did not define. - if (MergeDD.DeclaredSpecialMembers && DD.Definition != MergeDD.Definition) { + if (DD.Definition != MergeDD.Definition) { Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition); DD.Definition->setHasExternalVisibleStorage(); + + if (DD.Definition->isHidden()) { + // If MergeDD is visible or becomes visible, make the definition visible. + if (!MergeDD.Definition->isHidden()) + DD.Definition->Hidden = false; + else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) { + Reader.getContext().mergeDefinitionIntoModule( + DD.Definition, MergeDD.Definition->getImportedOwningModule(), + /*NotifyListeners*/ false); + Reader.PendingMergedDefinitionsToDeduplicate.insert(DD.Definition); + } else { + auto SubmoduleID = MergeDD.Definition->getOwningModuleID(); + assert(SubmoduleID && "hidden definition in no module"); + Reader.HiddenNamesMap[Reader.getSubmodule(SubmoduleID)].push_back( + DD.Definition); + } + } + } + + auto PFDI = Reader.PendingFakeDefinitionData.find(&DD); + if (PFDI != Reader.PendingFakeDefinitionData.end() && + PFDI->second == ASTReader::PendingFakeDefinitionKind::Fake) { + // We faked up this definition data because we found a class for which we'd + // not yet loaded the definition. Replace it with the real thing now. + assert(!DD.IsLambda && !MergeDD.IsLambda && "faked up lambda definition?"); + PFDI->second = ASTReader::PendingFakeDefinitionKind::FakeLoaded; + + // Don't change which declaration is the definition; that is required + // to be invariant once we select it. + auto *Def = DD.Definition; + DD = std::move(MergeDD); + DD.Definition = Def; + return; } // FIXME: Move this out into a .def file? - // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than - // asserting; this can happen in the case of an ODR violation. bool DetectedOdrViolation = false; #define OR_FIELD(Field) DD.Field |= MergeDD.Field; #define MATCH_FIELD(Field) \ @@ -1442,7 +1506,7 @@ void ASTDeclReader::MergeDefinitionData( Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition); } -void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) { +void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { struct CXXRecordDecl::DefinitionData *DD; ASTContext &C = Reader.getContext(); @@ -1457,19 +1521,29 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) { ReadCXXDefinitionData(*DD, Record, Idx); - // If we're reading an update record, we might already have a definition for - // this record. If so, just merge into it. - if (D->DefinitionData.getNotUpdated()) { - MergeDefinitionData(D, *DD); + // We might already have a definition for this record. This can happen either + // because we're reading an update record, or because we've already done some + // merging. Either way, just merge into it. + CXXRecordDecl *Canon = D->getCanonicalDecl(); + if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) { + if (CanonDD->Definition != DD->Definition) + Reader.MergedDeclContexts.insert( + std::make_pair(DD->Definition, CanonDD->Definition)); + MergeDefinitionData(Canon, std::move(*DD)); + D->DefinitionData = Canon->DefinitionData; return; } // Propagate the DefinitionData pointer to the canonical declaration, so // that all other deserialized declarations will see it. - CXXRecordDecl *Canon = D->getCanonicalDecl(); if (Canon == D) { D->DefinitionData = DD; D->IsCompleteDefinition = true; + + // If this is an update record, we can have redeclarations already. Make a + // note that we need to propagate the DefinitionData pointer onto them. + if (Update) + Reader.PendingDefinitions.insert(D); } else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) { // We have already deserialized a definition of this record. This // definition is no longer really a definition. Note that the pre-existing @@ -1478,7 +1552,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) { std::make_pair(D, CanonDD->Definition)); D->DefinitionData = Canon->DefinitionData; D->IsCompleteDefinition = false; - MergeDefinitionData(D, *DD); + MergeDefinitionData(D, std::move(*DD)); } else { Canon->DefinitionData = DD; D->DefinitionData = Canon->DefinitionData; @@ -1535,7 +1609,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { bool WasDefinition = Record[Idx++]; if (WasDefinition) - ReadCXXRecordDefinition(D); + ReadCXXRecordDefinition(D, /*Update*/false); else // Propagate DefinitionData pointer from the canonical declaration. D->DefinitionData = D->getCanonicalDecl()->DefinitionData; @@ -1576,17 +1650,20 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { VisitCXXMethodDecl(D); if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx)) - D->setInheritedConstructor(CD); + if (D->isCanonicalDecl()) + D->setInheritedConstructor(CD->getCanonicalDecl()); D->IsExplicitSpecified = Record[Idx++]; - // FIXME: We should defer loading this until we need the constructor's body. - std::tie(D->CtorInitializers, D->NumCtorInitializers) = - Reader.ReadCXXCtorInitializers(F, Record, Idx); } void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { VisitCXXMethodDecl(D); - D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx); + if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx)) { + auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl()); + // FIXME: Check consistency if we have an old and new operator delete. + if (!Canon->OperatorDelete) + Canon->OperatorDelete = OperatorDelete; + } } void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { @@ -1690,36 +1767,34 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { return Redecl; } +static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old, + SmallVectorImpl<DeclID> &IDs) { + assert(!IDs.empty() && "no IDs to add to list"); + if (Old) { + IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); + std::sort(IDs.begin(), IDs.end()); + IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); + } + + auto *Result = new (Context) DeclID[1 + IDs.size()]; + *Result = IDs.size(); + std::copy(IDs.begin(), IDs.end(), Result + 1); + return Result; +} + void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); if (ThisDeclID == Redecl.getFirstID()) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector<serialization::DeclID, 2> SpecIDs; - SpecIDs.push_back(0); - - // Specializations. - unsigned Size = Record[Idx++]; - SpecIDs[0] += Size; - for (unsigned I = 0; I != Size; ++I) - SpecIDs.push_back(ReadDeclID(Record, Idx)); - - // Partial specializations. - Size = Record[Idx++]; - SpecIDs[0] += Size; - for (unsigned I = 0; I != Size; ++I) - SpecIDs.push_back(ReadDeclID(Record, Idx)); - - ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr(); - if (SpecIDs[0]) { - typedef serialization::DeclID DeclID; - - // FIXME: Append specializations! - CommonPtr->LazySpecializations - = new (Reader.getContext()) DeclID [SpecIDs.size()]; - memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), - SpecIDs.size() * sizeof(DeclID)); + SmallVector<serialization::DeclID, 32> SpecIDs; + ReadDeclIDList(SpecIDs); + + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); } } @@ -1741,30 +1816,13 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector<serialization::DeclID, 2> SpecIDs; - SpecIDs.push_back(0); - - // Specializations. - unsigned Size = Record[Idx++]; - SpecIDs[0] += Size; - for (unsigned I = 0; I != Size; ++I) - SpecIDs.push_back(ReadDeclID(Record, Idx)); - - // Partial specializations. - Size = Record[Idx++]; - SpecIDs[0] += Size; - for (unsigned I = 0; I != Size; ++I) - SpecIDs.push_back(ReadDeclID(Record, Idx)); - - VarTemplateDecl::Common *CommonPtr = D->getCommonPtr(); - if (SpecIDs[0]) { - typedef serialization::DeclID DeclID; + SmallVector<serialization::DeclID, 32> SpecIDs; + ReadDeclIDList(SpecIDs); - // FIXME: Append specializations! - CommonPtr->LazySpecializations = - new (Reader.getContext()) DeclID[SpecIDs.size()]; - memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), - SpecIDs.size() * sizeof(DeclID)); + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); } } } @@ -1823,7 +1881,7 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( // definition. if (auto *DDD = D->DefinitionData.getNotUpdated()) { if (auto *CanonDD = CanonSpec->DefinitionData.getNotUpdated()) { - MergeDefinitionData(CanonSpec, *DDD); + MergeDefinitionData(CanonSpec, std::move(*DDD)); Reader.PendingDefinitions.erase(D); Reader.MergedDeclContexts.insert( std::make_pair(D, CanonDD->Definition)); @@ -1876,17 +1934,13 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This FunctionTemplateDecl owns a CommonPtr; read it. + SmallVector<serialization::DeclID, 32> SpecIDs; + ReadDeclIDList(SpecIDs); - // Read the function specialization declaration IDs. The specializations - // themselves will be loaded if they're needed. - if (unsigned NumSpecs = Record[Idx++]) { - // FIXME: Append specializations! - FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = new (Reader.getContext()) - serialization::DeclID[NumSpecs + 1]; - CommonPtr->LazySpecializations[0] = NumSpecs; - for (unsigned I = 0; I != NumSpecs; ++I) - CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx); + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); } } } @@ -2049,15 +2103,25 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) { } template <typename T> -ASTDeclReader::RedeclarableResult +ASTDeclReader::RedeclarableResult ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { DeclID FirstDeclID = ReadDeclID(Record, Idx); - + Decl *MergeWith = nullptr; + // 0 indicates that this declaration was the only declaration of its entity, // and is used for space optimization. if (FirstDeclID == 0) FirstDeclID = ThisDeclID; - + else if (unsigned N = Record[Idx++]) { + // We have some declarations that must be before us in our redeclaration + // chain. Read them now, and remember that we ought to merge with one of + // them. + // FIXME: Provide a known merge target to the second and subsequent such + // declaration. + for (unsigned I = 0; I != N; ++I) + MergeWith = ReadDecl(Record, Idx/*, MergeWith*/); + } + T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID)); if (FirstDecl != D) { // We delay loading of the redeclaration chain to avoid deeply nested calls. @@ -2065,6 +2129,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { // which is the one that matters and mark the real previous DeclID to be // loaded & attached later on. D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl); + D->First = FirstDecl->getCanonicalDecl(); } // Note that this declaration has been deserialized. @@ -2072,7 +2137,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { // The result structure takes care to note that we need to load the // other declaration chains for this ID. - return RedeclarableResult(Reader, FirstDeclID, + return RedeclarableResult(Reader, FirstDeclID, MergeWith, static_cast<T *>(D)->getKind()); } @@ -2083,23 +2148,19 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, RedeclarableResult &Redecl, DeclID TemplatePatternID) { T *D = static_cast<T*>(DBase); - T *DCanon = D->getCanonicalDecl(); - if (D != DCanon && - // IDs < NUM_PREDEF_DECL_IDS are not loaded from an AST file. - Redecl.getFirstID() >= NUM_PREDEF_DECL_IDS && - (!Reader.getContext().getLangOpts().Modules || - Reader.getOwningModuleFile(DCanon) == Reader.getOwningModuleFile(D))) { - // All redeclarations between this declaration and its originally-canonical - // declaration get pulled in when we load DCanon; we don't need to - // perform any more merging now. - Redecl.suppress(); - } // If modules are not available, there is no reason to perform this merge. if (!Reader.getContext().getLangOpts().Modules) return; - if (FindExistingResult ExistingRes = findExisting(D)) + // If we're not the canonical declaration, we don't need to merge. + if (!DBase->isFirstDecl()) + return; + + if (auto *Existing = Redecl.getKnownMergeTarget()) + // We already know of an existing declaration we should merge with. + mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID); + else if (FindExistingResult ExistingRes = findExisting(D)) if (T *Existing = ExistingRes) mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); } @@ -2120,7 +2181,8 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, auto *DPattern = D->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl(); RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(), - DPattern->getKind()); + /*MergeWith*/ExistingPattern, DPattern->getKind()); + if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) { // Merge with any existing definition. // FIXME: This is duplicated in several places. Refactor. @@ -2128,13 +2190,14 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl(); if (auto *DDD = DClass->DefinitionData.getNotUpdated()) { if (auto *ExistingDD = ExistingClass->DefinitionData.getNotUpdated()) { - MergeDefinitionData(ExistingClass, *DDD); + MergeDefinitionData(ExistingClass, std::move(*DDD)); Reader.PendingDefinitions.erase(DClass); Reader.MergedDeclContexts.insert( std::make_pair(DClass, ExistingDD->Definition)); DClass->IsCompleteDefinition = false; } else { ExistingClass->DefinitionData = DClass->DefinitionData; + Reader.PendingDefinitions.insert(DClass); } } DClass->DefinitionData = ExistingClass->DefinitionData; @@ -2163,14 +2226,18 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, T *ExistingCanon = Existing->getCanonicalDecl(); T *DCanon = D->getCanonicalDecl(); if (ExistingCanon != DCanon) { - assert(DCanon->getGlobalID() == Redecl.getFirstID()); + assert(DCanon->getGlobalID() == Redecl.getFirstID() && + "already merged this declaration"); // Have our redeclaration link point back at the canonical declaration // of the existing declaration, so that this declaration has the // appropriate canonical declaration. D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon); + D->First = ExistingCanon; // When we merge a namespace, update its pointer to the first namespace. + // We cannot have loaded any redeclarations of this declaration yet, so + // there's nothing else that needs to be updated. if (auto *Namespace = dyn_cast<NamespaceDecl>(D)) Namespace->AnonOrFirstNamespaceAndInline.setPointer( assert_cast<NamespaceDecl*>(ExistingCanon)); @@ -2181,14 +2248,11 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon), TemplatePatternID); - // If this declaration was the canonical declaration, make a note of - // that. We accept the linear algorithm here because the number of - // unique canonical declarations of an entity should always be tiny. + // If this declaration was the canonical declaration, make a note of that. if (DCanon == D) { - SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon]; - if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID()) - == Merged.end()) - Merged.push_back(Redecl.getFirstID()); + Reader.MergedDecls[ExistingCanon].push_back(Redecl.getFirstID()); + if (Reader.PendingDeclChainsKnown.insert(ExistingCanon).second) + Reader.PendingDeclChains.push_back(ExistingCanon); } } } @@ -2529,42 +2593,71 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { /// Find the context in which we should search for previous declarations when /// looking for declarations to merge. -static DeclContext *getPrimaryContextForMerging(DeclContext *DC) { +DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, + DeclContext *DC) { if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC)) return ND->getOriginalNamespace(); - // There is one tricky case here: if DC is a class with no definition, then - // we're merging a declaration whose definition is added by an update record, - // but we've not yet loaded that update record. In this case, we use the - // canonical declaration for merging until we get a real definition. - // FIXME: When we add a definition, we may need to move the partial lookup - // information from the canonical declaration onto the chosen definition. - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) - return RD->getPrimaryContext(); + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { + // Try to dig out the definition. + auto *DD = RD->DefinitionData.getNotUpdated(); + if (!DD) + DD = RD->getCanonicalDecl()->DefinitionData.getNotUpdated(); + + // If there's no definition yet, then DC's definition is added by an update + // record, but we've not yet loaded that update record. In this case, we + // commit to DC being the canonical definition now, and will fix this when + // we load the update record. + if (!DD) { + DD = new (Reader.Context) struct CXXRecordDecl::DefinitionData(RD); + RD->IsCompleteDefinition = true; + RD->DefinitionData = DD; + RD->getCanonicalDecl()->DefinitionData = DD; + + // Track that we did this horrible thing so that we can fix it later. + Reader.PendingFakeDefinitionData.insert( + std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake)); + } + + return DD->Definition; + } if (EnumDecl *ED = dyn_cast<EnumDecl>(DC)) return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() : nullptr; + // We can see the TU here only if we have no Sema object. In that case, + // there's no TU scope to look in, so using the DC alone is sufficient. + if (auto *TU = dyn_cast<TranslationUnitDecl>(DC)) + return TU; + return nullptr; } ASTDeclReader::FindExistingResult::~FindExistingResult() { + // Record that we had a typedef name for linkage whether or not we merge + // with that declaration. + if (TypedefNameForLinkage) { + DeclContext *DC = New->getDeclContext()->getRedeclContext(); + Reader.ImportedTypedefNamesForLinkage.insert( + std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New)); + return; + } + if (!AddResult || Existing) return; DeclarationName Name = New->getDeclName(); DeclContext *DC = New->getDeclContext()->getRedeclContext(); - if (TypedefNameForLinkage) { - Reader.ImportedTypedefNamesForLinkage.insert( - std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New)); - } else if (!Name) { - assert(needsAnonymousDeclarationNumber(New)); + if (needsAnonymousDeclarationNumber(New)) { setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(), AnonymousDeclNumber, New); - } else if (DC->isTranslationUnit() && Reader.SemaObj) { - Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name); - } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) { + } else if (DC->isTranslationUnit() && Reader.SemaObj && + !Reader.getContext().getLangOpts().CPlusPlus) { + if (Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name)) + Reader.PendingFakeLookupResults[Name.getAsIdentifierInfo()] + .push_back(New); + } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) { // Add the declaration to its redeclaration context so later merging // lookups will find it. MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true); @@ -2582,12 +2675,11 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found, // If we found a typedef declaration that gives a name to some other // declaration, then we want that inner declaration. Declarations from // AST files are handled via ImportedTypedefNamesForLinkage. - if (Found->isFromASTFile()) return 0; - if (auto *TND = dyn_cast<TypedefNameDecl>(Found)) { - if (auto *TT = TND->getTypeSourceInfo()->getType()->getAs<TagType>()) - if (TT->getDecl()->getTypedefNameForAnonDecl() == TND) - return TT->getDecl(); - } + if (Found->isFromASTFile()) + return 0; + + if (auto *TND = dyn_cast<TypedefNameDecl>(Found)) + return TND->getAnonDeclWithTypedefName(); return 0; } @@ -2608,17 +2700,12 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, // If this is the first time, but we have parsed a declaration of the context, // build the anonymous declaration list from the parsed declaration. if (!cast<Decl>(DC)->isFromASTFile()) { - unsigned Index = 0; - for (Decl *LexicalD : DC->decls()) { - auto *ND = dyn_cast<NamedDecl>(LexicalD); - if (!ND || !needsAnonymousDeclarationNumber(ND)) - continue; - if (Previous.size() == Index) + numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) { + if (Previous.size() == Number) Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl())); else - Previous[Index] = cast<NamedDecl>(ND->getCanonicalDecl()); - ++Index; - } + Previous[Number] = cast<NamedDecl>(ND->getCanonicalDecl()); + }); } return Index < Previous.size() ? Previous[Index] : nullptr; @@ -2646,8 +2733,6 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // unmergeable contexts. FindExistingResult Result(Reader, D, /*Existing=*/nullptr, AnonymousDeclNumber, TypedefNameForLinkage); - // FIXME: We may still need to pull in the redeclaration chain; there can - // be redeclarations via 'decltype'. Result.suppress(); return Result; } @@ -2667,16 +2752,16 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // was not imported. } - if (!Name) { + if (needsAnonymousDeclarationNumber(D)) { // This is an anonymous declaration that we may need to merge. Look it up // in its context by number. - assert(needsAnonymousDeclarationNumber(D)); if (auto *Existing = getAnonymousDeclForMerging( Reader, D->getLexicalDeclContext(), AnonymousDeclNumber)) if (isSameEntity(Existing, D)) return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, TypedefNameForLinkage); - } else if (DC->isTranslationUnit() && Reader.SemaObj) { + } else if (DC->isTranslationUnit() && Reader.SemaObj && + !Reader.getContext().getLangOpts().CPlusPlus) { IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver; // Temporarily consider the identifier to be up-to-date. We don't want to @@ -2710,7 +2795,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, TypedefNameForLinkage); } - } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) { + } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) { DeclContext::lookup_result R = MergeDC->noload_lookup(Name); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage)) @@ -2738,20 +2823,47 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { } template<typename DeclT> +Decl *ASTDeclReader::getMostRecentDeclImpl(Redeclarable<DeclT> *D) { + return D->RedeclLink.getLatestNotUpdated(); +} +Decl *ASTDeclReader::getMostRecentDeclImpl(...) { + llvm_unreachable("getMostRecentDecl on non-redeclarable declaration"); +} + +Decl *ASTDeclReader::getMostRecentDecl(Decl *D) { + assert(D); + + switch (D->getKind()) { +#define ABSTRACT_DECL(TYPE) +#define DECL(TYPE, BASE) \ + case Decl::TYPE: \ + return getMostRecentDeclImpl(cast<TYPE##Decl>(D)); +#include "clang/AST/DeclNodes.inc" + } + llvm_unreachable("unknown decl kind"); +} + +Decl *ASTReader::getMostRecentExistingDecl(Decl *D) { + return ASTDeclReader::getMostRecentDecl(D->getCanonicalDecl()); +} + +template<typename DeclT> void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, Redeclarable<DeclT> *D, - Decl *Previous) { + Decl *Previous, Decl *Canon) { D->RedeclLink.setPrevious(cast<DeclT>(Previous)); + D->First = cast<DeclT>(Previous)->First; } namespace clang { template<> void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, Redeclarable<FunctionDecl> *D, - Decl *Previous) { + Decl *Previous, Decl *Canon) { FunctionDecl *FD = static_cast<FunctionDecl*>(D); FunctionDecl *PrevFD = cast<FunctionDecl>(Previous); FD->RedeclLink.setPrevious(PrevFD); + FD->First = PrevFD->First; // If the previous declaration is an inline function declaration, then this // declaration is too. @@ -2774,16 +2886,17 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, FD->IsInline = true; } - // If this declaration has an unresolved exception specification but the - // previous declaration had a resolved one, resolve the exception - // specification now. + // If we need to propagate an exception specification along the redecl + // chain, make a note of that so that we can do so later. auto *FPT = FD->getType()->getAs<FunctionProtoType>(); auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>(); - if (FPT && PrevFPT && - isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) && - !isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType())) { - Reader.Context.adjustExceptionSpec( - FD, PrevFPT->getExtProtoInfo().ExceptionSpec); + if (FPT && PrevFPT) { + bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType()); + bool WasUnresolved = + isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType()); + if (IsUnresolved != WasUnresolved) + Reader.PendingExceptionSpecUpdates.insert( + std::make_pair(Canon, IsUnresolved ? PrevFD : FD)); } } } @@ -2792,14 +2905,14 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) { } void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, - Decl *Previous) { + Decl *Previous, Decl *Canon) { assert(D && Previous); switch (D->getKind()) { #define ABSTRACT_DECL(TYPE) -#define DECL(TYPE, BASE) \ - case Decl::TYPE: \ - attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous); \ +#define DECL(TYPE, BASE) \ + case Decl::TYPE: \ + attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous, Canon); \ break; #include "clang/AST/DeclNodes.inc" } @@ -2859,29 +2972,6 @@ void ASTReader::markIncompleteDeclChain(Decl *D) { } } -ASTReader::MergedDeclsMap::iterator -ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) { - // If we don't have any stored merged declarations, just look in the - // merged declarations set. - StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID); - if (StoredPos == StoredMergedDecls.end()) - return MergedDecls.find(Canon); - - // Append the stored merged declarations to the merged declarations set. - MergedDeclsMap::iterator Pos = MergedDecls.find(Canon); - if (Pos == MergedDecls.end()) - Pos = MergedDecls.insert(std::make_pair(Canon, - SmallVector<DeclID, 2>())).first; - Pos->second.append(StoredPos->second.begin(), StoredPos->second.end()); - StoredMergedDecls.erase(StoredPos); - - // Sort and uniquify the set of merged declarations. - llvm::array_pod_sort(Pos->second.begin(), Pos->second.end()); - Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()), - Pos->second.end()); - return Pos; -} - /// \brief Read the declaration at the given offset from the AST file. Decl *ASTReader::ReadDeclRecord(DeclID ID) { unsigned Index = ID - NUM_PREDEF_DECL_IDS; @@ -3086,6 +3176,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_CXX_BASE_SPECIFIERS: Error("attempt to read a C++ base-specifier record as a declaration"); return nullptr; + case DECL_CXX_CTOR_INITIALIZERS: + Error("attempt to read a C++ ctor initializer record as a declaration"); + return nullptr; case DECL_IMPORT: // Note: last entry of the ImportDecl record is the number of stored source // locations. @@ -3199,47 +3292,55 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { } namespace { - /// \brief Module visitor class that finds all of the redeclarations of a - /// + /// \brief Module visitor class that finds all of the redeclarations of a + /// redeclarable declaration. class RedeclChainVisitor { ASTReader &Reader; SmallVectorImpl<DeclID> &SearchDecls; llvm::SmallPtrSetImpl<Decl *> &Deserialized; GlobalDeclID CanonID; SmallVector<Decl *, 4> Chain; - + public: RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls, llvm::SmallPtrSetImpl<Decl *> &Deserialized, GlobalDeclID CanonID) : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized), - CanonID(CanonID) { - for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) - addToChain(Reader.GetDecl(SearchDecls[I])); + CanonID(CanonID) { + // Ensure that the canonical ID goes at the start of the chain. + addToChain(Reader.GetDecl(CanonID)); } - - static bool visit(ModuleFile &M, bool Preorder, void *UserData) { - if (Preorder) - return false; - - return static_cast<RedeclChainVisitor *>(UserData)->visit(M); + + static ModuleManager::DFSPreorderControl + visitPreorder(ModuleFile &M, void *UserData) { + return static_cast<RedeclChainVisitor *>(UserData)->visitPreorder(M); } - + + static bool visitPostorder(ModuleFile &M, void *UserData) { + return static_cast<RedeclChainVisitor *>(UserData)->visitPostorder(M); + } + void addToChain(Decl *D) { if (!D) return; - + if (Deserialized.erase(D)) Chain.push_back(D); } - + void searchForID(ModuleFile &M, GlobalDeclID GlobalID) { // Map global ID of the first declaration down to the local ID // used in this module file. DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID); if (!ID) return; - + + // If the search decl was from this module, add it to the chain before any + // of its redeclarations in this module or users of it, and after any from + // imported modules. + if (CanonID != GlobalID && Reader.isDeclIDFromModule(GlobalID, M)) + addToChain(Reader.GetDecl(GlobalID)); + // Perform a binary search to find the local redeclarations for this // declaration (if any). const LocalRedeclarationsInfo Compare = { ID, 0 }; @@ -3269,8 +3370,36 @@ namespace { for (unsigned I = 0; I != N; ++I) addToChain(Reader.GetLocalDecl(M, M.RedeclarationChains[Offset++])); } - - bool visit(ModuleFile &M) { + + bool needsToVisitImports(ModuleFile &M, GlobalDeclID GlobalID) { + DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID); + if (!ID) + return false; + + const LocalRedeclarationsInfo Compare = {ID, 0}; + const LocalRedeclarationsInfo *Result = std::lower_bound( + M.RedeclarationsMap, + M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, Compare); + if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap || + Result->FirstID != ID) { + return true; + } + unsigned Offset = Result->Offset; + unsigned N = M.RedeclarationChains[Offset]; + // We don't need to visit a module or any of its imports if we've already + // deserialized the redecls from this module. + return N != 0; + } + + ModuleManager::DFSPreorderControl visitPreorder(ModuleFile &M) { + for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) { + if (needsToVisitImports(M, SearchDecls[I])) + return ModuleManager::Continue; + } + return ModuleManager::SkipImports; + } + + bool visitPostorder(ModuleFile &M) { // Visit each of the declarations. for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) searchForID(M, SearchDecls[I]); @@ -3285,41 +3414,46 @@ namespace { }; } -void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) { - Decl *D = GetDecl(ID); - Decl *CanonDecl = D->getCanonicalDecl(); - +void ASTReader::loadPendingDeclChain(Decl *CanonDecl) { + // The decl might have been merged into something else after being added to + // our list. If it was, just skip it. + if (!CanonDecl->isCanonicalDecl()) + return; + // Determine the set of declaration IDs we'll be searching for. - SmallVector<DeclID, 1> SearchDecls; - GlobalDeclID CanonID = 0; - if (D == CanonDecl) { - SearchDecls.push_back(ID); // Always first. - CanonID = ID; - } - MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID); + SmallVector<DeclID, 16> SearchDecls; + GlobalDeclID CanonID = CanonDecl->getGlobalID(); + if (CanonID) + SearchDecls.push_back(CanonDecl->getGlobalID()); // Always first. + MergedDeclsMap::iterator MergedPos = MergedDecls.find(CanonDecl); if (MergedPos != MergedDecls.end()) SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end()); - + // Build up the list of redeclarations. RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID); - ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visit, &Visitor); - + ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visitPreorder, + &RedeclChainVisitor::visitPostorder, &Visitor); + // Retrieve the chains. ArrayRef<Decl *> Chain = Visitor.getChain(); - if (Chain.empty()) + if (Chain.empty() || (Chain.size() == 1 && Chain[0] == CanonDecl)) return; - + // Hook up the chains. - Decl *MostRecent = CanonDecl->getMostRecentDecl(); + // + // FIXME: We have three different dispatches on decl kind here; maybe + // we should instead generate one loop per kind and dispatch up-front? + Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl); + if (!MostRecent) + MostRecent = CanonDecl; for (unsigned I = 0, N = Chain.size(); I != N; ++I) { if (Chain[I] == CanonDecl) continue; - ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent); + ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent, CanonDecl); MostRecent = Chain[I]; } - - ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent); + ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent); } namespace { @@ -3513,13 +3647,25 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, while (Idx < Record.size()) { switch ((DeclUpdateKind)Record[Idx++]) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { + auto *RD = cast<CXXRecordDecl>(D); // FIXME: If we also have an update record for instantiating the // definition of D, we need that to happen before we get here. Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx); assert(MD && "couldn't read decl from update record"); // FIXME: We should call addHiddenDecl instead, to add the member // to its DeclContext. - cast<CXXRecordDecl>(D)->addedMember(MD); + RD->addedMember(MD); + + // If we've added a new special member to a class definition that is not + // the canonical definition, then we need special member lookups in the + // canonical definition to also look into our class. + auto *DD = RD->DefinitionData.getNotUpdated(); + if (DD && DD->Definition != RD) { + auto &Merged = Reader.MergedLookups[DD->Definition]; + // FIXME: Avoid the linear-time scan here. + if (std::find(Merged.begin(), Merged.end(), RD) == Merged.end()) + Merged.push_back(RD); + } break; } @@ -3567,13 +3713,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, }); } FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx)); - if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) - std::tie(CD->CtorInitializers, CD->NumCtorInitializers) = - Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx); - if (auto *DD = dyn_cast<CXXDestructorDecl>(FD)) - // FIXME: Check consistency. - DD->setOperatorDelete(Reader.ReadDeclAs<FunctionDecl>(ModuleFile, - Record, Idx)); + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { + CD->NumCtorInitializers = Record[Idx++]; + if (CD->NumCtorInitializers) + CD->CtorInitializers = + Reader.ReadCXXCtorInitializersRef(F, Record, Idx); + } // Store the offset of the body so we can lazily load it later. Reader.PendingBodies[FD] = GetCurrentCursorOffset(); HasPendingBody = true; @@ -3583,16 +3728,20 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { auto *RD = cast<CXXRecordDecl>(D); - bool HadDefinition = RD->getDefinition(); - ReadCXXRecordDefinition(RD); + auto *OldDD = RD->DefinitionData.getNotUpdated(); + bool HadRealDefinition = + OldDD && (OldDD->Definition != RD || + !Reader.PendingFakeDefinitionData.count(OldDD)); + ReadCXXRecordDefinition(RD, /*Update*/true); + // Visible update is handled separately. uint64_t LexicalOffset = Record[Idx++]; - if (!HadDefinition && LexicalOffset) { + if (!HadRealDefinition && LexicalOffset) { RD->setHasExternalLexicalStorage(true); Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor, - std::make_pair(LexicalOffset, 0), - ModuleFile.DeclContextInfos[RD]); - Reader.PendingDefinitions.insert(RD); + std::make_pair(LexicalOffset, 0), + ModuleFile.DeclContextInfos[RD]); + Reader.PendingFakeDefinitionData.erase(OldDD); } auto TSK = (TemplateSpecializationKind)Record[Idx++]; @@ -3636,24 +3785,36 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, break; } + case UPD_CXX_RESOLVED_DTOR_DELETE: { + // Set the 'operator delete' directly to avoid emitting another update + // record. + auto *Del = Reader.ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx); + auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl()); + // FIXME: Check consistency if we have an old and new operator delete. + if (!First->OperatorDelete) + First->OperatorDelete = Del; + break; + } + case UPD_CXX_RESOLVED_EXCEPTION_SPEC: { - // FIXME: This doesn't send the right notifications if there are - // ASTMutationListeners other than an ASTWriter. FunctionProtoType::ExceptionSpecInfo ESI; SmallVector<QualType, 8> ExceptionStorage; Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx); - for (auto *Redecl : merged_redecls(D)) { - auto *FD = cast<FunctionDecl>(Redecl); - auto *FPT = FD->getType()->castAs<FunctionProtoType>(); - if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) { - // AST invariant: if any exception spec in the redecl chain is - // resolved, all are resolved. We don't need to go any further. - // FIXME: If the exception spec is resolved, check that it matches. - break; - } + + // Update this declaration's exception specification, if needed. + auto *FD = cast<FunctionDecl>(D); + auto *FPT = FD->getType()->castAs<FunctionProtoType>(); + // FIXME: If the exception specification is already present, check that it + // matches. + if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) { FD->setType(Reader.Context.getFunctionType( FPT->getReturnType(), FPT->getParamTypes(), FPT->getExtProtoInfo().withExceptionSpec(ESI))); + + // When we get to the end of deserializing, see if there are other decls + // that we need to propagate this exception specification onto. + Reader.PendingExceptionSpecUpdates.insert( + std::make_pair(FD->getCanonicalDecl(), FD)); } break; } @@ -3685,10 +3846,30 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, case UPD_STATIC_LOCAL_NUMBER: Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]); break; + case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( Reader.Context, ReadSourceRange(Record, Idx))); break; + + case UPD_DECL_EXPORTED: + unsigned SubmoduleID = readSubmoduleID(Record, Idx); + Module *Owner = SubmoduleID ? Reader.getSubmodule(SubmoduleID) : nullptr; + if (Reader.getContext().getLangOpts().ModulesLocalVisibility) { + // FIXME: This doesn't send the right notifications if there are + // ASTMutationListeners other than an ASTWriter. + Reader.getContext().mergeDefinitionIntoModule(cast<NamedDecl>(D), Owner, + /*NotifyListeners*/false); + Reader.PendingMergedDefinitionsToDeduplicate.insert(cast<NamedDecl>(D)); + } else if (Owner && Owner->NameVisibility != Module::AllVisible) { + // If Owner is made visible at some later point, make this declaration + // visible too. + Reader.HiddenNamesMap[Owner].push_back(D); + } else { + // The declaration is now visible. + D->Hidden = false; + } + break; } } } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp index 4ef2e73..d1ecd46 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp @@ -486,7 +486,7 @@ void ASTStmtReader::VisitStringLiteral(StringLiteral *E) { // Read string data SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); - E->setString(Reader.getContext(), Str.str(), kind, isPascal); + E->setString(Reader.getContext(), Str, kind, isPascal); Idx += Len; // Read source locations @@ -1826,6 +1826,7 @@ void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) { C->setScheduleKind( static_cast<OpenMPScheduleClauseKind>(Record[Idx++])); C->setChunkSize(Reader->Reader.ReadSubExpr()); + C->setHelperChunkSize(Reader->Reader.ReadSubExpr()); C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); C->setScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx)); C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx)); @@ -1889,6 +1890,22 @@ void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) { for (unsigned i = 0; i != NumVars; ++i) Vars.push_back(Reader->Reader.ReadSubExpr()); C->setVarRefs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setPrivateCopies(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setSourceExprs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setDestinationExprs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setAssignmentOps(Vars); } void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) { @@ -1917,6 +1934,18 @@ void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) { for (unsigned i = 0; i != NumVars; ++i) Vars.push_back(Reader->Reader.ReadSubExpr()); C->setVarRefs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setLHSExprs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setRHSExprs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setReductionOps(Vars); } void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) { @@ -1928,7 +1957,20 @@ void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) { for (unsigned i = 0; i != NumVars; ++i) Vars.push_back(Reader->Reader.ReadSubExpr()); C->setVarRefs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setInits(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setUpdates(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setFinals(Vars); C->setStep(Reader->Reader.ReadSubExpr()); + C->setCalcStep(Reader->Reader.ReadSubExpr()); } void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) { @@ -1946,21 +1988,45 @@ void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) { void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); + SmallVector<Expr *, 16> Exprs; + Exprs.reserve(NumVars); for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Reader->Reader.ReadSubExpr()); - C->setVarRefs(Vars); + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setSourceExprs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setDestinationExprs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setAssignmentOps(Exprs); } void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); + SmallVector<Expr *, 16> Exprs; + Exprs.reserve(NumVars); for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Reader->Reader.ReadSubExpr()); - C->setVarRefs(Vars); + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setSourceExprs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setDestinationExprs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setAssignmentOps(Exprs); } void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) { @@ -2135,6 +2201,9 @@ void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) { D->setX(Reader.ReadSubExpr()); D->setV(Reader.ReadSubExpr()); D->setExpr(Reader.ReadSubExpr()); + D->setUpdateExpr(Reader.ReadSubExpr()); + D->IsXLHSInRHSPart = Record[Idx++] != 0; + D->IsPostfixUpdate = Record[Idx++] != 0; } void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) { @@ -2423,11 +2492,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx); DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc); bool IsArrow = Record[Idx++]; + SourceLocation OperatorLoc = ReadSourceLocation(F, Record, Idx); - S = MemberExpr::Create(Context, Base, IsArrow, QualifierLoc, + S = MemberExpr::Create(Context, Base, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo, - HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, - T, VK, OK); + HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T, + VK, OK); ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc, MemberD->getDeclName(), Record, Idx); if (HadMultipleCandidates) diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index 6c60d45..e689234 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -60,14 +60,14 @@ using namespace clang; using namespace clang::serialization; template <typename T, typename Allocator> -static StringRef data(const std::vector<T, Allocator> &v) { +static StringRef bytes(const std::vector<T, Allocator> &v) { if (v.empty()) return StringRef(); return StringRef(reinterpret_cast<const char*>(&v[0]), sizeof(T) * v.size()); } template <typename T> -static StringRef data(const SmallVectorImpl<T> &v) { +static StringRef bytes(const SmallVectorImpl<T> &v) { return StringRef(reinterpret_cast<const char*>(v.data()), sizeof(T) * v.size()); } @@ -867,6 +867,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MODULE_NAME); RECORD(MODULE_MAP_FILE); RECORD(IMPORTS); + RECORD(KNOWN_MODULE_FILES); RECORD(LANGUAGE_OPTIONS); RECORD(TARGET_OPTIONS); RECORD(ORIGINAL_FILE); @@ -892,7 +893,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(STATISTICS); RECORD(TENTATIVE_DEFINITIONS); RECORD(UNUSED_FILESCOPED_DECLS); - RECORD(LOCALLY_SCOPED_EXTERN_C_DECLS); RECORD(SELECTOR_OFFSETS); RECORD(METHOD_POOL); RECORD(PP_COUNTER_VALUE); @@ -924,11 +924,9 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(OBJC_CATEGORIES_MAP); RECORD(FILE_SORTED_DECLS); RECORD(IMPORTED_MODULES); - RECORD(MERGED_DECLARATIONS); RECORD(LOCAL_REDECLARATIONS); RECORD(OBJC_CATEGORIES); RECORD(MACRO_OFFSET); - RECORD(MACRO_TABLE); RECORD(LATE_PARSED_TEMPLATE); RECORD(OPTIMIZE_PRAGMA_OPTIONS); @@ -941,10 +939,12 @@ void ASTWriter::WriteBlockInfoBlock() { // Preprocessor Block. BLOCK(PREPROCESSOR_BLOCK); - RECORD(PP_MACRO_OBJECT_LIKE); + RECORD(PP_MACRO_DIRECTIVE_HISTORY); RECORD(PP_MACRO_FUNCTION_LIKE); + RECORD(PP_MACRO_OBJECT_LIKE); + RECORD(PP_MODULE_MACRO); RECORD(PP_TOKEN); - + // Decls and Types block. BLOCK(DECLTYPES_BLOCK); RECORD(TYPE_EXT_QUAL); @@ -1062,7 +1062,8 @@ void ASTWriter::WriteBlockInfoBlock() { /// to an absolute path and removing nested './'s. /// /// \return \c true if the path was changed. -bool cleanPathForOutput(FileManager &FileMgr, SmallVectorImpl<char> &Path) { +static bool cleanPathForOutput(FileManager &FileMgr, + SmallVectorImpl<char> &Path) { bool Changed = false; if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) { @@ -1159,12 +1160,17 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); - // Signature - Record.clear(); - Record.push_back(getSignature()); - Stream.EmitRecord(SIGNATURE, Record); - if (WritingModule) { + // For implicit modules we output a signature that we can use to ensure + // duplicate module builds don't collide in the cache as their output order + // is non-deterministic. + // FIXME: Remove this when output is deterministic. + if (Context.getLangOpts().ImplicitModules) { + Record.clear(); + Record.push_back(getSignature()); + Stream.EmitRecord(SIGNATURE, Record); + } + // Module name BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME)); @@ -1222,20 +1228,28 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, serialization::ModuleManager &Mgr = Chain->getModuleManager(); Record.clear(); - for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end(); - M != MEnd; ++M) { + for (auto *M : Mgr) { // Skip modules that weren't directly imported. - if (!(*M)->isDirectlyImported()) + if (!M->isDirectlyImported()) continue; - Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding - AddSourceLocation((*M)->ImportLoc, Record); - Record.push_back((*M)->File->getSize()); - Record.push_back((*M)->File->getModificationTime()); - Record.push_back((*M)->Signature); - AddPath((*M)->FileName, Record); + Record.push_back((unsigned)M->Kind); // FIXME: Stable encoding + AddSourceLocation(M->ImportLoc, Record); + Record.push_back(M->File->getSize()); + Record.push_back(M->File->getModificationTime()); + Record.push_back(M->Signature); + AddPath(M->FileName, Record); } Stream.EmitRecord(IMPORTS, Record); + + // Also emit a list of known module files that were not imported, + // but are made available by this module. + // FIXME: Should we also include a signature here? + Record.clear(); + for (auto *E : Mgr.getAdditionalKnownModuleFiles()) + AddPath(E->getName(), Record); + if (!Record.empty()) + Stream.EmitRecord(KNOWN_MODULE_FILES, Record); } // Language options. @@ -1341,6 +1355,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.push_back(HSOpts.UseStandardSystemIncludes); Record.push_back(HSOpts.UseStandardCXXIncludes); Record.push_back(HSOpts.UseLibcxx); + // Write out the specific module cache path that contains the module files. + AddString(PP.getHeaderSearchInfo().getModuleCachePath(), Record); Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record); // Preprocessor options. @@ -1467,7 +1483,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, unsigned UserFilesNum = 0; // Write out all of the input files. - std::vector<uint32_t> InputFileOffsets; + std::vector<uint64_t> InputFileOffsets; for (std::deque<InputFileEntry>::iterator I = SortedFiles.begin(), E = SortedFiles.end(); I != E; ++I) { const InputFileEntry &Entry = *I; @@ -1514,7 +1530,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, Record.push_back(INPUT_FILE_OFFSETS); Record.push_back(InputFileOffsets.size()); Record.push_back(UserFilesNum); - Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, data(InputFileOffsets)); + Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets)); } //===----------------------------------------------------------------------===// @@ -1756,7 +1772,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { Record.push_back(NumHeaderSearchEntries); Record.push_back(TableData.size()); TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end()); - Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData.str()); + Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData); // Free all of the strings we had to duplicate. for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I) @@ -1909,7 +1925,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.push_back(SOURCE_LOCATION_OFFSETS); Record.push_back(SLocEntryOffsets.size()); Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy - Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets)); + Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, bytes(SLocEntryOffsets)); // Write the source location entry preloads array, telling the AST // reader which source locations entries it should load eagerly. @@ -1956,52 +1972,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Preprocessor Serialization //===----------------------------------------------------------------------===// -namespace { -class ASTMacroTableTrait { -public: - typedef IdentID key_type; - typedef key_type key_type_ref; - - struct Data { - uint32_t MacroDirectivesOffset; - }; - - typedef Data data_type; - typedef const data_type &data_type_ref; - typedef unsigned hash_value_type; - typedef unsigned offset_type; - - static hash_value_type ComputeHash(IdentID IdID) { - return llvm::hash_value(IdID); - } - - std::pair<unsigned,unsigned> - static EmitKeyDataLength(raw_ostream& Out, - key_type_ref Key, data_type_ref Data) { - unsigned KeyLen = 4; // IdentID. - unsigned DataLen = 4; // MacroDirectivesOffset. - return std::make_pair(KeyLen, DataLen); - } - - static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { - using namespace llvm::support; - endian::Writer<little>(Out).write<uint32_t>(Key); - } - - static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, - unsigned) { - using namespace llvm::support; - endian::Writer<little>(Out).write<uint32_t>(Data.MacroDirectivesOffset); - } -}; -} // end anonymous namespace - -static int compareMacroDirectives( - const std::pair<const IdentifierInfo *, MacroDirective *> *X, - const std::pair<const IdentifierInfo *, MacroDirective *> *Y) { - return X->first->getName().compare(Y->first->getName()); -} - static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, const Preprocessor &PP) { if (MacroInfo *MI = MD->getMacroInfo()) @@ -2009,10 +1979,6 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, return true; if (IsModule) { - // Re-export any imported directives. - if (MD->isImported()) - return false; - SourceLocation Loc = MD->getLocation(); if (Loc.isInvalid()) return true; @@ -2032,6 +1998,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { WritePreprocessorDetail(*PPRec); RecordData Record; + RecordData ModuleMacroRecord; // If the preprocessor __COUNTER__ value has been bumped, remember it. if (PP.getCounterValue() != 0) { @@ -2052,75 +2019,75 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { // Loop over all the macro directives that are live at the end of the file, // emitting each to the PP section. - // Construct the list of macro directives that need to be serialized. - SmallVector<std::pair<const IdentifierInfo *, MacroDirective *>, 2> - MacroDirectives; - for (Preprocessor::macro_iterator - I = PP.macro_begin(/*IncludeExternalMacros=*/false), - E = PP.macro_end(/*IncludeExternalMacros=*/false); - I != E; ++I) { - MacroDirectives.push_back(std::make_pair(I->first, I->second)); - } - + // Construct the list of identifiers with macro directives that need to be + // serialized. + SmallVector<const IdentifierInfo *, 128> MacroIdentifiers; + for (auto &Id : PP.getIdentifierTable()) + if (Id.second->hadMacroDefinition() && + (!Id.second->isFromAST() || + Id.second->hasChangedSinceDeserialization())) + MacroIdentifiers.push_back(Id.second); // Sort the set of macro definitions that need to be serialized by the // name of the macro, to provide a stable ordering. - llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(), - &compareMacroDirectives); - - llvm::OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator; + std::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(), + llvm::less_ptr<IdentifierInfo>()); // Emit the macro directives as a list and associate the offset with the // identifier they belong to. - for (unsigned I = 0, N = MacroDirectives.size(); I != N; ++I) { - const IdentifierInfo *Name = MacroDirectives[I].first; - uint64_t MacroDirectiveOffset = Stream.GetCurrentBitNo(); - MacroDirective *MD = MacroDirectives[I].second; - - // If the macro or identifier need no updates, don't write the macro history - // for this one. - // FIXME: Chain the macro history instead of re-writing it. - if (MD->isFromPCH() && - Name->isFromAST() && !Name->hasChangedSinceDeserialization()) - continue; + for (const IdentifierInfo *Name : MacroIdentifiers) { + MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name); + auto StartOffset = Stream.GetCurrentBitNo(); // Emit the macro directives in reverse source order. for (; MD; MD = MD->getPrevious()) { + // Once we hit an ignored macro, we're done: the rest of the chain + // will all be ignored macros. if (shouldIgnoreMacro(MD, IsModule, PP)) - continue; + break; AddSourceLocation(MD->getLocation(), Record); Record.push_back(MD->getKind()); if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) { - MacroID InfoID = getMacroRef(DefMD->getInfo(), Name); - Record.push_back(InfoID); - Record.push_back(DefMD->getOwningModuleID()); - Record.push_back(DefMD->isAmbiguous()); - } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) { - Record.push_back(UndefMD->getOwningModuleID()); - } else { - auto *VisMD = cast<VisibilityMacroDirective>(MD); + Record.push_back(getMacroRef(DefMD->getInfo(), Name)); + } else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { Record.push_back(VisMD->isPublic()); } + } - if (MD->isImported()) { - auto Overrides = MD->getOverriddenModules(); - Record.push_back(Overrides.size()); - for (auto Override : Overrides) - Record.push_back(Override); + // Write out any exported module macros. + bool EmittedModuleMacros = false; + if (IsModule) { + auto Leafs = PP.getLeafModuleMacros(Name); + SmallVector<ModuleMacro*, 8> Worklist(Leafs.begin(), Leafs.end()); + llvm::DenseMap<ModuleMacro*, unsigned> Visits; + while (!Worklist.empty()) { + auto *Macro = Worklist.pop_back_val(); + + // Emit a record indicating this submodule exports this macro. + ModuleMacroRecord.push_back( + getSubmoduleID(Macro->getOwningModule())); + ModuleMacroRecord.push_back(getMacroRef(Macro->getMacroInfo(), Name)); + for (auto *M : Macro->overrides()) + ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule())); + + Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord); + ModuleMacroRecord.clear(); + + // Enqueue overridden macros once we've visited all their ancestors. + for (auto *M : Macro->overrides()) + if (++Visits[M] == M->getNumOverridingMacros()) + Worklist.push_back(M); + + EmittedModuleMacros = true; } } - if (Record.empty()) + + if (Record.empty() && !EmittedModuleMacros) continue; + IdentMacroDirectivesOffsetMap[Name] = StartOffset; Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record); Record.clear(); - - IdentMacroDirectivesOffsetMap[Name] = MacroDirectiveOffset; - - IdentID NameID = getIdentifierRef(Name); - ASTMacroTableTrait::Data data; - data.MacroDirectivesOffset = MacroDirectiveOffset; - Generator.insert(NameID, data); } /// \brief Offsets of each of the macros into the bitstream, indexed by @@ -2168,9 +2135,8 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { Record.push_back(MI->isGNUVarargs()); Record.push_back(MI->hasCommaPasting()); Record.push_back(MI->getNumArgs()); - for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); - I != E; ++I) - AddIdentifierRef(*I, Record); + for (const IdentifierInfo *Arg : MI->args()) + AddIdentifierRef(Arg, Record); } // If we have a detailed preprocessing record, record the macro definition @@ -2196,33 +2162,9 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { Stream.ExitBlock(); - // Create the on-disk hash table in a buffer. - SmallString<4096> MacroTable; - uint32_t BucketOffset; - { - using namespace llvm::support; - llvm::raw_svector_ostream Out(MacroTable); - // Make sure that no bucket is at offset 0 - endian::Writer<little>(Out).write<uint32_t>(0); - BucketOffset = Generator.Emit(Out); - } - - // Write the macro table - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(MACRO_TABLE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MacroTableAbbrev = Stream.EmitAbbrev(Abbrev); - - Record.push_back(MACRO_TABLE); - Record.push_back(BucketOffset); - Stream.EmitRecordWithBlob(MacroTableAbbrev, Record, MacroTable.str()); - Record.clear(); - // Write the offsets table for macro IDs. using namespace llvm; - Abbrev = new BitCodeAbbrev(); + auto *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID @@ -2234,7 +2176,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { Record.push_back(MacroOffsets.size()); Record.push_back(FirstMacroID - NUM_PREDEF_MACRO_IDS); Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, - data(MacroOffsets)); + bytes(MacroOffsets)); } void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { @@ -2274,13 +2216,13 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) { Record.clear(); - PreprocessedEntityOffsets.push_back(PPEntityOffset((*E)->getSourceRange(), - Stream.GetCurrentBitNo())); + PreprocessedEntityOffsets.push_back( + PPEntityOffset((*E)->getSourceRange(), Stream.GetCurrentBitNo())); - if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) { + if (MacroDefinitionRecord *MD = dyn_cast<MacroDefinitionRecord>(*E)) { // Record this macro definition's ID. MacroDefinitions[MD] = NextPreprocessorEntityID; - + AddIdentifierRef(MD->getName(), Record); Stream.EmitRecord(PPD_MACRO_DEFINITION, Record); continue; @@ -2332,7 +2274,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { Record.push_back(PPD_ENTITIES_OFFSETS); Record.push_back(FirstPreprocessorEntityID - NUM_PREDEF_PP_ENTITY_IDS); Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record, - data(PreprocessedEntityOffsets)); + bytes(PreprocessedEntityOffsets)); } } @@ -2369,19 +2311,6 @@ static unsigned getNumberOfModules(Module *Mod) { } void ASTWriter::WriteSubmodules(Module *WritingModule) { - // Determine the dependencies of our module and each of it's submodules. - // FIXME: This feels like it belongs somewhere else, but there are no - // other consumers of this information. - SourceManager &SrcMgr = PP->getSourceManager(); - ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap(); - for (const auto *I : Context->local_imports()) { - if (Module *ImportedFrom - = ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(), - SrcMgr))) { - ImportedFrom->Imports.push_back(I->getImportedModule()); - } - } - // Enter the submodule description block. Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5); @@ -2509,16 +2438,16 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { } // Emit the umbrella header, if there is one. - if (const FileEntry *UmbrellaHeader = Mod->getUmbrellaHeader()) { + if (auto UmbrellaHeader = Mod->getUmbrellaHeader()) { Record.clear(); Record.push_back(SUBMODULE_UMBRELLA_HEADER); - Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, - UmbrellaHeader->getName()); - } else if (const DirectoryEntry *UmbrellaDir = Mod->getUmbrellaDir()) { + Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, + UmbrellaHeader.NameAsWritten); + } else if (auto UmbrellaDir = Mod->getUmbrellaDir()) { Record.clear(); Record.push_back(SUBMODULE_UMBRELLA_DIR); Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record, - UmbrellaDir->getName()); + UmbrellaDir.NameAsWritten); } // Emit the headers. @@ -2566,8 +2495,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Record.clear(); for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) { if (Module *Exported = Mod->Exports[I].getPointer()) { - unsigned ExportedID = SubmoduleIDs[Exported]; - assert(ExportedID > 0 && "Unknown submodule ID?"); + unsigned ExportedID = getSubmoduleID(Exported); Record.push_back(ExportedID); } else { Record.push_back(0); @@ -2618,9 +2546,14 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { } Stream.ExitBlock(); - - assert((NextSubmoduleID - FirstSubmoduleID - == getNumberOfModules(WritingModule)) && "Wrong # of submodules"); + + // FIXME: This can easily happen, if we have a reference to a submodule that + // did not result in us loading a module file for that submodule. For + // instance, a cross-top-level-module 'conflict' declaration will hit this. + assert((NextSubmoduleID - FirstSubmoduleID == + getNumberOfModules(WritingModule)) && + "Wrong # of submodules; found a reference to a non-local, " + "non-imported submodule?"); } serialization::SubmoduleID @@ -2684,6 +2617,29 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record); } +void ASTWriter::WriteCXXCtorInitializersOffsets() { + if (CXXCtorInitializersOffsets.empty()) + return; + + RecordData Record; + + // Create a blob abbreviation for the C++ ctor initializer offsets. + using namespace llvm; + + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(CXX_CTOR_INITIALIZERS_OFFSETS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned CtorInitializersOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + + // Write the base specifier offsets table. + Record.clear(); + Record.push_back(CXX_CTOR_INITIALIZERS_OFFSETS); + Record.push_back(CXXCtorInitializersOffsets.size()); + Stream.EmitRecordWithBlob(CtorInitializersOffsetAbbrev, Record, + bytes(CXXCtorInitializersOffsets)); +} + void ASTWriter::WriteCXXBaseSpecifiersOffsets() { if (CXXBaseSpecifiersOffsets.empty()) return; @@ -2704,7 +2660,7 @@ void ASTWriter::WriteCXXBaseSpecifiersOffsets() { Record.push_back(CXX_BASE_SPECIFIER_OFFSETS); Record.push_back(CXXBaseSpecifiersOffsets.size()); Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record, - data(CXXBaseSpecifiersOffsets)); + bytes(CXXBaseSpecifiersOffsets)); } //===----------------------------------------------------------------------===// @@ -2780,7 +2736,7 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, Decls.push_back(std::make_pair(D->getKind(), GetDeclRef(D))); ++NumLexicalDeclContexts; - Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls)); + Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, bytes(Decls)); return Offset; } @@ -2799,7 +2755,7 @@ void ASTWriter::WriteTypeDeclOffsets() { Record.push_back(TYPE_OFFSET); Record.push_back(TypeOffsets.size()); Record.push_back(FirstTypeID - NUM_PREDEF_TYPE_IDS); - Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, data(TypeOffsets)); + Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets)); // Write the declaration offsets array Abbrev = new BitCodeAbbrev(); @@ -2812,22 +2768,25 @@ void ASTWriter::WriteTypeDeclOffsets() { Record.push_back(DECL_OFFSET); Record.push_back(DeclOffsets.size()); Record.push_back(FirstDeclID - NUM_PREDEF_DECL_IDS); - Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets)); + Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets)); } void ASTWriter::WriteFileDeclIDsMap() { using namespace llvm; RecordData Record; + SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs( + FileDeclIDs.begin(), FileDeclIDs.end()); + std::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(), + llvm::less_first()); + // Join the vectors of DeclIDs from all files. - SmallVector<DeclID, 256> FileSortedIDs; - for (FileDeclIDsTy::iterator - FI = FileDeclIDs.begin(), FE = FileDeclIDs.end(); FI != FE; ++FI) { - DeclIDInFileInfo &Info = *FI->second; - Info.FirstDeclIndex = FileSortedIDs.size(); - for (LocDeclIDsTy::iterator - DI = Info.DeclIDs.begin(), DE = Info.DeclIDs.end(); DI != DE; ++DI) - FileSortedIDs.push_back(DI->second); + SmallVector<DeclID, 256> FileGroupedDeclIDs; + for (auto &FileDeclEntry : SortedFileDeclIDs) { + DeclIDInFileInfo &Info = *FileDeclEntry.second; + Info.FirstDeclIndex = FileGroupedDeclIDs.size(); + for (auto &LocDeclEntry : Info.DeclIDs) + FileGroupedDeclIDs.push_back(LocDeclEntry.second); } BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); @@ -2836,8 +2795,8 @@ void ASTWriter::WriteFileDeclIDsMap() { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); Record.push_back(FILE_SORTED_DECLS); - Record.push_back(FileSortedIDs.size()); - Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs)); + Record.push_back(FileGroupedDeclIDs.size()); + Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileGroupedDeclIDs)); } void ASTWriter::WriteComments() { @@ -2988,13 +2947,12 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { // Create the on-disk hash table representation. We walk through every // selector we've seen and look it up in the method pool. SelectorOffsets.resize(NextSelectorID - FirstSelectorID); - for (llvm::DenseMap<Selector, SelectorID>::iterator - I = SelectorIDs.begin(), E = SelectorIDs.end(); - I != E; ++I) { - Selector S = I->first; + for (auto &SelectorAndID : SelectorIDs) { + Selector S = SelectorAndID.first; + SelectorID ID = SelectorAndID.second; Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S); ASTMethodPoolTrait::data_type Data = { - I->second, + ID, ObjCMethodList(), ObjCMethodList() }; @@ -3004,7 +2962,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { } // Only write this selector if it's not in an existing AST or something // changed. - if (Chain && I->second < FirstSelectorID) { + if (Chain && ID < FirstSelectorID) { // Selector already exists. Did it change? bool changed = false; for (ObjCMethodList *M = &Data.Instance; @@ -3051,7 +3009,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { Record.push_back(METHOD_POOL); Record.push_back(BucketOffset); Record.push_back(NumTableEntries); - Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str()); + Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool); // Create a blob abbreviation for the selector table offsets. Abbrev = new BitCodeAbbrev(); @@ -3067,7 +3025,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { Record.push_back(SelectorOffsets.size()); Record.push_back(FirstSelectorID - NUM_PREDEF_SELECTOR_IDS); Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, - data(SelectorOffsets)); + bytes(SelectorOffsets)); } } @@ -3082,11 +3040,9 @@ void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { // Note: this writes out all references even for a dependent AST. But it is // very tricky to fix, and given that @selector shouldn't really appear in // headers, probably not worth it. It's not a correctness issue. - for (DenseMap<Selector, SourceLocation>::iterator S = - SemaRef.ReferencedSelectors.begin(), - E = SemaRef.ReferencedSelectors.end(); S != E; ++S) { - Selector Sel = (*S).first; - SourceLocation Loc = (*S).second; + for (auto &SelectorAndLocation : SemaRef.ReferencedSelectors) { + Selector Sel = SelectorAndLocation.first; + SourceLocation Loc = SelectorAndLocation.second; AddSelectorRef(Sel, Record); AddSourceLocation(Loc, Record); } @@ -3097,174 +3053,59 @@ void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { // Identifier Table Serialization //===----------------------------------------------------------------------===// +/// Determine the declaration that should be put into the name lookup table to +/// represent the given declaration in this module. This is usually D itself, +/// but if D was imported and merged into a local declaration, we want the most +/// recent local declaration instead. The chosen declaration will be the most +/// recent declaration in any module that imports this one. +static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts, + NamedDecl *D) { + if (!LangOpts.Modules || !D->isFromASTFile()) + return D; + + if (Decl *Redecl = D->getPreviousDecl()) { + // For Redeclarable decls, a prior declaration might be local. + for (; Redecl; Redecl = Redecl->getPreviousDecl()) { + if (!Redecl->isFromASTFile()) + return cast<NamedDecl>(Redecl); + // If we find a decl from a (chained-)PCH stop since we won't find a + // local one. + if (D->getOwningModuleID() == 0) + break; + } + } else if (Decl *First = D->getCanonicalDecl()) { + // For Mergeable decls, the first decl might be local. + if (!First->isFromASTFile()) + return cast<NamedDecl>(First); + } + + // All declarations are imported. Our most recent declaration will also be + // the most recent one in anyone who imports us. + return D; +} + namespace { class ASTIdentifierTableTrait { ASTWriter &Writer; Preprocessor &PP; IdentifierResolver &IdResolver; - bool IsModule; - /// \brief Determines whether this is an "interesting" identifier - /// that needs a full IdentifierInfo structure written into the hash - /// table. - bool isInterestingIdentifier(IdentifierInfo *II, MacroDirective *&Macro) { - if (II->isPoisoned() || + /// \brief Determines whether this is an "interesting" identifier that needs a + /// full IdentifierInfo structure written into the hash table. Notably, this + /// doesn't check whether the name has macros defined; use PublicMacroIterator + /// to check that. + bool isInterestingIdentifier(IdentifierInfo *II, uint64_t MacroOffset) { + if (MacroOffset || + II->isPoisoned() || II->isExtensionToken() || II->getObjCOrBuiltinID() || II->hasRevertedTokenIDToIdentifier() || II->getFETokenInfo<void>()) return true; - return hadMacroDefinition(II, Macro); - } - - bool hadMacroDefinition(IdentifierInfo *II, MacroDirective *&Macro) { - if (!II->hadMacroDefinition()) - return false; - - if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) { - if (!IsModule) - return !shouldIgnoreMacro(Macro, IsModule, PP); - - MacroState State; - if (getFirstPublicSubmoduleMacro(Macro, State)) - return true; - } - return false; } - enum class SubmoduleMacroState { - /// We've seen nothing about this macro. - None, - /// We've seen a public visibility directive. - Public, - /// We've either exported a macro for this module or found that the - /// module's definition of this macro is private. - Done - }; - typedef llvm::DenseMap<SubmoduleID, SubmoduleMacroState> MacroState; - - MacroDirective * - getFirstPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) { - if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, State)) - return NextMD; - return nullptr; - } - - MacroDirective * - getNextPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) { - if (MacroDirective *NextMD = - getPublicSubmoduleMacro(MD->getPrevious(), State)) - return NextMD; - return nullptr; - } - - /// \brief Traverses the macro directives history and returns the next - /// public macro definition or undefinition that has not been found so far. - /// - /// A macro that is defined in submodule A and undefined in submodule B - /// will still be considered as defined/exported from submodule A. - MacroDirective *getPublicSubmoduleMacro(MacroDirective *MD, - MacroState &State) { - if (!MD) - return nullptr; - - Optional<bool> IsPublic; - for (; MD; MD = MD->getPrevious()) { - // Once we hit an ignored macro, we're done: the rest of the chain - // will all be ignored macros. - if (shouldIgnoreMacro(MD, IsModule, PP)) - break; - - // If this macro was imported, re-export it. - if (MD->isImported()) - return MD; - - SubmoduleID ModID = getSubmoduleID(MD); - auto &S = State[ModID]; - assert(ModID && "found macro in no submodule"); - - if (S == SubmoduleMacroState::Done) - continue; - - if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { - // The latest visibility directive for a name in a submodule affects all - // the directives that come before it. - if (S == SubmoduleMacroState::None) - S = VisMD->isPublic() ? SubmoduleMacroState::Public - : SubmoduleMacroState::Done; - } else { - S = SubmoduleMacroState::Done; - return MD; - } - } - - return nullptr; - } - - ArrayRef<SubmoduleID> - getOverriddenSubmodules(MacroDirective *MD, - SmallVectorImpl<SubmoduleID> &ScratchSpace) { - assert(!isa<VisibilityMacroDirective>(MD) && - "only #define and #undef can override"); - if (MD->isImported()) - return MD->getOverriddenModules(); - - ScratchSpace.clear(); - SubmoduleID ModID = getSubmoduleID(MD); - for (MD = MD->getPrevious(); MD; MD = MD->getPrevious()) { - if (shouldIgnoreMacro(MD, IsModule, PP)) - break; - - // If this is a definition from a submodule import, that submodule's - // definition is overridden by the definition or undefinition that we - // started with. - if (MD->isImported()) { - if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) { - SubmoduleID DefModuleID = DefMD->getInfo()->getOwningModuleID(); - assert(DefModuleID && "imported macro has no owning module"); - ScratchSpace.push_back(DefModuleID); - } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) { - // If we override a #undef, we override anything that #undef overrides. - // We don't need to override it, since an active #undef doesn't affect - // the meaning of a macro. - auto Overrides = UndefMD->getOverriddenModules(); - ScratchSpace.insert(ScratchSpace.end(), - Overrides.begin(), Overrides.end()); - } - } - - // Stop once we leave the original macro's submodule. - // - // Either this submodule #included another submodule of the same - // module or it just happened to be built after the other module. - // In the former case, we override the submodule's macro. - // - // FIXME: In the latter case, we shouldn't do so, but we can't tell - // these cases apart. - // - // FIXME: We can leave this submodule and re-enter it if it #includes a - // header within a different submodule of the same module. In such cases - // the overrides list will be incomplete. - SubmoduleID DirectiveModuleID = getSubmoduleID(MD); - if (DirectiveModuleID != ModID) { - if (DirectiveModuleID && !MD->isImported()) - ScratchSpace.push_back(DirectiveModuleID); - break; - } - } - - std::sort(ScratchSpace.begin(), ScratchSpace.end()); - ScratchSpace.erase(std::unique(ScratchSpace.begin(), ScratchSpace.end()), - ScratchSpace.end()); - return ScratchSpace; - } - - SubmoduleID getSubmoduleID(MacroDirective *MD) { - return Writer.inferSubmoduleIDFromLocation(MD->getLocation()); - } - public: typedef IdentifierInfo* key_type; typedef key_type key_type_ref; @@ -3275,9 +3116,9 @@ public: typedef unsigned hash_value_type; typedef unsigned offset_type; - ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, - IdentifierResolver &IdResolver, bool IsModule) - : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule) { } + ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, + IdentifierResolver &IdResolver) + : Writer(Writer), PP(PP), IdResolver(IdResolver) {} static hash_value_type ComputeHash(const IdentifierInfo* II) { return llvm::HashString(II->getName()); @@ -3287,25 +3128,12 @@ public: EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { unsigned KeyLen = II->getLength() + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 - MacroDirective *Macro = nullptr; - if (isInterestingIdentifier(II, Macro)) { + auto MacroOffset = Writer.getMacroDirectivesOffset(II); + if (isInterestingIdentifier(II, MacroOffset)) { DataLen += 2; // 2 bytes for builtin ID DataLen += 2; // 2 bytes for flags - if (hadMacroDefinition(II, Macro)) { + if (MacroOffset) DataLen += 4; // MacroDirectives offset. - if (IsModule) { - MacroState State; - SmallVector<SubmoduleID, 16> Scratch; - for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State); - MD; MD = getNextPublicSubmoduleMacro(MD, State)) { - DataLen += 4; // MacroInfo ID or ModuleID. - if (unsigned NumOverrides = - getOverriddenSubmodules(MD, Scratch).size()) - DataLen += 4 * (1 + NumOverrides); - } - DataLen += 4; // 0 terminator. - } - } for (IdentifierResolver::iterator D = IdResolver.begin(II), DEnd = IdResolver.end(); @@ -3315,6 +3143,7 @@ public: using namespace llvm::support; endian::Writer<little> LE(Out); + assert((uint16_t)DataLen == DataLen && (uint16_t)KeyLen == KeyLen); LE.write<uint16_t>(DataLen); // We emit the key length after the data length so that every // string is preceded by a 16-bit length. This matches the PTH @@ -3331,25 +3160,13 @@ public: Out.write(II->getNameStart(), KeyLen); } - static void emitMacroOverrides(raw_ostream &Out, - ArrayRef<SubmoduleID> Overridden) { - if (!Overridden.empty()) { - using namespace llvm::support; - endian::Writer<little> LE(Out); - LE.write<uint32_t>(Overridden.size() | 0x80000000U); - for (unsigned I = 0, N = Overridden.size(); I != N; ++I) { - assert(Overridden[I] && "zero module ID for override"); - LE.write<uint32_t>(Overridden[I]); - } - } - } - void EmitData(raw_ostream& Out, IdentifierInfo* II, IdentID ID, unsigned) { using namespace llvm::support; endian::Writer<little> LE(Out); - MacroDirective *Macro = nullptr; - if (!isInterestingIdentifier(II, Macro)) { + + auto MacroOffset = Writer.getMacroDirectivesOffset(II); + if (!isInterestingIdentifier(II, MacroOffset)) { LE.write<uint32_t>(ID << 1); return; } @@ -3359,77 +3176,29 @@ public: assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); LE.write<uint16_t>(Bits); Bits = 0; - bool HadMacroDefinition = hadMacroDefinition(II, Macro); + bool HadMacroDefinition = MacroOffset != 0; Bits = (Bits << 1) | unsigned(HadMacroDefinition); - Bits = (Bits << 1) | unsigned(IsModule); Bits = (Bits << 1) | unsigned(II->isExtensionToken()); Bits = (Bits << 1) | unsigned(II->isPoisoned()); Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); LE.write<uint16_t>(Bits); - if (HadMacroDefinition) { - LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II)); - if (IsModule) { - // Write the IDs of macros coming from different submodules. - MacroState State; - SmallVector<SubmoduleID, 16> Scratch; - for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State); - MD; MD = getNextPublicSubmoduleMacro(MD, State)) { - if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { - // FIXME: If this macro directive was created by #pragma pop_macros, - // or if it was created implicitly by resolving conflicting macros, - // it may be for a different submodule from the one in the MacroInfo - // object. If so, we should write out its owning ModuleID. - MacroID InfoID = Writer.getMacroID(DefMD->getInfo()); - assert(InfoID); - LE.write<uint32_t>(InfoID << 1); - } else { - auto *UndefMD = cast<UndefMacroDirective>(MD); - SubmoduleID Mod = UndefMD->isImported() - ? UndefMD->getOwningModuleID() - : getSubmoduleID(UndefMD); - LE.write<uint32_t>((Mod << 1) | 1); - } - emitMacroOverrides(Out, getOverriddenSubmodules(MD, Scratch)); - } - LE.write<uint32_t>(0xdeadbeef); - } - } + if (HadMacroDefinition) + LE.write<uint32_t>(MacroOffset); // Emit the declaration IDs in reverse order, because the // IdentifierResolver provides the declarations as they would be // visible (e.g., the function "stat" would come before the struct - // "stat"), but the ASTReader adds declarations to the end of the list - // (so we need to see the struct "status" before the function "status"). + // "stat"), but the ASTReader adds declarations to the end of the list + // (so we need to see the struct "stat" before the function "stat"). // Only emit declarations that aren't from a chained PCH, though. - SmallVector<Decl *, 16> Decls(IdResolver.begin(II), - IdResolver.end()); - for (SmallVectorImpl<Decl *>::reverse_iterator D = Decls.rbegin(), - DEnd = Decls.rend(); + SmallVector<NamedDecl *, 16> Decls(IdResolver.begin(II), IdResolver.end()); + for (SmallVectorImpl<NamedDecl *>::reverse_iterator D = Decls.rbegin(), + DEnd = Decls.rend(); D != DEnd; ++D) - LE.write<uint32_t>(Writer.getDeclID(getMostRecentLocalDecl(*D))); - } - - /// \brief Returns the most recent local decl or the given decl if there are - /// no local ones. The given decl is assumed to be the most recent one. - Decl *getMostRecentLocalDecl(Decl *Orig) { - // The only way a "from AST file" decl would be more recent from a local one - // is if it came from a module. - if (!PP.getLangOpts().Modules) - return Orig; - - // Look for a local in the decl chain. - for (Decl *D = Orig; D; D = D->getPreviousDecl()) { - if (!D->isFromASTFile()) - return D; - // If we come up a decl from a (chained-)PCH stop since we won't find a - // local one. - if (D->getOwningModuleID() == 0) - break; - } - - return Orig; + LE.write<uint32_t>( + Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), *D))); } }; } // end anonymous namespace @@ -3448,29 +3217,33 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, // strings. { llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; - ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); + ASTIdentifierTableTrait Trait(*this, PP, IdResolver); // Look for any identifiers that were named while processing the // headers, but are otherwise not needed. We add these to the hash // table to enable checking of the predefines buffer in the case // where the user adds new macro definitions when building the AST // file. + SmallVector<const IdentifierInfo *, 128> IIs; for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), IDEnd = PP.getIdentifierTable().end(); ID != IDEnd; ++ID) - getIdentifierRef(ID->second); + IIs.push_back(ID->second); + // Sort the identifiers lexicographically before getting them references so + // that their order is stable. + std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>()); + for (const IdentifierInfo *II : IIs) + getIdentifierRef(II); // Create the on-disk hash table representation. We only store offsets // for identifiers that appear here for the first time. IdentifierOffsets.resize(NextIdentID - FirstIdentID); - for (llvm::DenseMap<const IdentifierInfo *, IdentID>::iterator - ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end(); - ID != IDEnd; ++ID) { - assert(ID->first && "NULL identifier in identifier table"); - if (!Chain || !ID->first->isFromAST() || - ID->first->hasChangedSinceDeserialization()) - Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second, - Trait); + for (auto IdentIDPair : IdentifierIDs) { + IdentifierInfo *II = const_cast<IdentifierInfo *>(IdentIDPair.first); + IdentID ID = IdentIDPair.second; + assert(II && "NULL identifier in identifier table"); + if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) + Generator.insert(II, ID, Trait); } // Create the on-disk hash table in a buffer. @@ -3478,7 +3251,6 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, uint32_t BucketOffset; { using namespace llvm::support; - ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 endian::Writer<little>(Out).write<uint32_t>(0); @@ -3496,7 +3268,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, RecordData Record; Record.push_back(IDENTIFIER_TABLE); Record.push_back(BucketOffset); - Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); + Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable); } // Write the offsets table for identifier IDs. @@ -3517,38 +3289,13 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, Record.push_back(IdentifierOffsets.size()); Record.push_back(FirstIdentID - NUM_PREDEF_IDENT_IDS); Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, - data(IdentifierOffsets)); + bytes(IdentifierOffsets)); } //===----------------------------------------------------------------------===// // DeclContext's Name Lookup Table Serialization //===----------------------------------------------------------------------===// -/// Determine the declaration that should be put into the name lookup table to -/// represent the given declaration in this module. This is usually D itself, -/// but if D was imported and merged into a local declaration, we want the most -/// recent local declaration instead. The chosen declaration will be the most -/// recent declaration in any module that imports this one. -static NamedDecl *getDeclForLocalLookup(NamedDecl *D) { - if (!D->isFromASTFile()) - return D; - - if (Decl *Redecl = D->getPreviousDecl()) { - // For Redeclarable decls, a prior declaration might be local. - for (; Redecl; Redecl = Redecl->getPreviousDecl()) - if (!Redecl->isFromASTFile()) - return cast<NamedDecl>(Redecl); - } else if (Decl *First = D->getCanonicalDecl()) { - // For Mergeable decls, the first decl might be local. - if (!First->isFromASTFile()) - return cast<NamedDecl>(First); - } - - // All declarations are imported. Our most recent declaration will also be - // the most recent one in anyone who imports us. - return D; -} - namespace { // Trait used for the on-disk hash table used in the method pool. class ASTDeclContextNameLookupTrait { @@ -3666,119 +3413,198 @@ public: LE.write<uint16_t>(Lookup.size()); for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end(); I != E; ++I) - LE.write<uint32_t>(Writer.GetDeclRef(getDeclForLocalLookup(*I))); + LE.write<uint32_t>( + Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), *I))); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } }; } // end anonymous namespace -template<typename Visitor> -static void visitLocalLookupResults(const DeclContext *ConstDC, - bool NeedToReconcileExternalVisibleStorage, - Visitor AddLookupResult) { +bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result, + DeclContext *DC) { + return Result.hasExternalDecls() && DC->NeedToReconcileExternalVisibleStorage; +} + +bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result, + DeclContext *DC) { + for (auto *D : Result.getLookupResult()) + if (!getDeclForLocalLookup(getLangOpts(), D)->isFromASTFile()) + return false; + + return true; +} + +uint32_t +ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, + llvm::SmallVectorImpl<char> &LookupTable) { + assert(!ConstDC->HasLazyLocalLexicalLookups && + !ConstDC->HasLazyExternalLexicalLookups && + "must call buildLookups first"); + // FIXME: We need to build the lookups table, which is logically const. DeclContext *DC = const_cast<DeclContext*>(ConstDC); assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table"); - SmallVector<DeclarationName, 16> ExternalNames; + // Create the on-disk hash table representation. + llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> + Generator; + ASTDeclContextNameLookupTrait Trait(*this); + + // The first step is to collect the declaration names which we need to + // serialize into the name lookup table, and to collect them in a stable + // order. + SmallVector<DeclarationName, 16> Names; + + // We also build up small sets of the constructor and conversion function + // names which are visible. + llvm::SmallSet<DeclarationName, 8> ConstructorNameSet, ConversionNameSet; + for (auto &Lookup : *DC->buildLookup()) { - if (Lookup.second.hasExternalDecls() || - NeedToReconcileExternalVisibleStorage) { - // We don't know for sure what declarations are found by this name, - // because the external source might have a different set from the set - // that are in the lookup map, and we can't update it now without - // risking invalidating our lookup iterator. So add it to a queue to - // deal with later. - ExternalNames.push_back(Lookup.first); + auto &Name = Lookup.first; + auto &Result = Lookup.second; + + // If there are no local declarations in our lookup result, we don't + // need to write an entry for the name at all unless we're rewriting + // the decl context. If we can't write out a lookup set without + // performing more deserialization, just skip this entry. + if (isLookupResultExternal(Result, DC) && !isRewritten(cast<Decl>(DC)) && + isLookupResultEntirelyExternal(Result, DC)) continue; - } - AddLookupResult(Lookup.first, Lookup.second.getLookupResult()); - } + // We also skip empty results. If any of the results could be external and + // the currently available results are empty, then all of the results are + // external and we skip it above. So the only way we get here with an empty + // results is when no results could have been external *and* we have + // external results. + // + // FIXME: While we might want to start emitting on-disk entries for negative + // lookups into a decl context as an optimization, today we *have* to skip + // them because there are names with empty lookup results in decl contexts + // which we can't emit in any stable ordering: we lookup constructors and + // conversion functions in the enclosing namespace scope creating empty + // results for them. This in almost certainly a bug in Clang's name lookup, + // but that is likely to be hard or impossible to fix and so we tolerate it + // here by omitting lookups with empty results. + if (Lookup.second.getLookupResult().empty()) + continue; - // Add the names we needed to defer. Note, this shouldn't add any new decls - // to the list we need to serialize: any new declarations we find here should - // be imported from an external source. - // FIXME: What if the external source isn't an ASTReader? - for (const auto &Name : ExternalNames) - AddLookupResult(Name, DC->lookup(Name)); -} - -void ASTWriter::AddUpdatedDeclContext(const DeclContext *DC) { - if (UpdatedDeclContexts.insert(DC).second && WritingAST) { - // Ensure we emit all the visible declarations. - visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage, - [&](DeclarationName Name, - DeclContext::lookup_const_result Result) { - for (auto *Decl : Result) - GetDeclRef(getDeclForLocalLookup(Decl)); - }); + switch (Lookup.first.getNameKind()) { + default: + Names.push_back(Lookup.first); + break; + + case DeclarationName::CXXConstructorName: + assert(isa<CXXRecordDecl>(DC) && + "Cannot have a constructor name outside of a class!"); + ConstructorNameSet.insert(Name); + break; + + case DeclarationName::CXXConversionFunctionName: + assert(isa<CXXRecordDecl>(DC) && + "Cannot have a conversion function name outside of a class!"); + ConversionNameSet.insert(Name); + break; + } } -} -uint32_t -ASTWriter::GenerateNameLookupTable(const DeclContext *DC, - llvm::SmallVectorImpl<char> &LookupTable) { - assert(!DC->LookupPtr.getInt() && "must call buildLookups first"); + // Sort the names into a stable order. + std::sort(Names.begin(), Names.end()); + + if (auto *D = dyn_cast<CXXRecordDecl>(DC)) { + // We need to establish an ordering of constructor and conversion function + // names, and they don't have an intrinsic ordering. + + // First we try the easy case by forming the current context's constructor + // name and adding that name first. This is a very useful optimization to + // avoid walking the lexical declarations in many cases, and it also + // handles the only case where a constructor name can come from some other + // lexical context -- when that name is an implicit constructor merged from + // another declaration in the redecl chain. Any non-implicit constructor or + // conversion function which doesn't occur in all the lexical contexts + // would be an ODR violation. + auto ImplicitCtorName = Context->DeclarationNames.getCXXConstructorName( + Context->getCanonicalType(Context->getRecordType(D))); + if (ConstructorNameSet.erase(ImplicitCtorName)) + Names.push_back(ImplicitCtorName); + + // If we still have constructors or conversion functions, we walk all the + // names in the decl and add the constructors and conversion functions + // which are visible in the order they lexically occur within the context. + if (!ConstructorNameSet.empty() || !ConversionNameSet.empty()) + for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls()) + if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) { + auto Name = ChildND->getDeclName(); + switch (Name.getNameKind()) { + default: + continue; + + case DeclarationName::CXXConstructorName: + if (ConstructorNameSet.erase(Name)) + Names.push_back(Name); + break; + + case DeclarationName::CXXConversionFunctionName: + if (ConversionNameSet.erase(Name)) + Names.push_back(Name); + break; + } - llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> - Generator; - ASTDeclContextNameLookupTrait Trait(*this); + if (ConstructorNameSet.empty() && ConversionNameSet.empty()) + break; + } - // Create the on-disk hash table representation. - DeclarationName ConstructorName; - DeclarationName ConversionName; + assert(ConstructorNameSet.empty() && "Failed to find all of the visible " + "constructors by walking all the " + "lexical members of the context."); + assert(ConversionNameSet.empty() && "Failed to find all of the visible " + "conversion functions by walking all " + "the lexical members of the context."); + } + + // Next we need to do a lookup with each name into this decl context to fully + // populate any results from external sources. We don't actually use the + // results of these lookups because we only want to use the results after all + // results have been loaded and the pointers into them will be stable. + for (auto &Name : Names) + DC->lookup(Name); + + // Now we need to insert the results for each name into the hash table. For + // constructor names and conversion function names, we actually need to merge + // all of the results for them into one list of results each and insert + // those. SmallVector<NamedDecl *, 8> ConstructorDecls; - SmallVector<NamedDecl *, 4> ConversionDecls; + SmallVector<NamedDecl *, 8> ConversionDecls; - visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage, - [&](DeclarationName Name, - DeclContext::lookup_result Result) { - if (Result.empty()) - return; + // Now loop over the names, either inserting them or appending for the two + // special cases. + for (auto &Name : Names) { + DeclContext::lookup_result Result = DC->noload_lookup(Name); - // Different DeclarationName values of certain kinds are mapped to - // identical serialized keys, because we don't want to use type - // identifiers in the keys (since type ids are local to the module). switch (Name.getNameKind()) { + default: + Generator.insert(Name, Result, Trait); + break; + case DeclarationName::CXXConstructorName: - // There may be different CXXConstructorName DeclarationName values - // in a DeclContext because a UsingDecl that inherits constructors - // has the DeclarationName of the inherited constructors. - if (!ConstructorName) - ConstructorName = Name; ConstructorDecls.append(Result.begin(), Result.end()); - return; + break; case DeclarationName::CXXConversionFunctionName: - if (!ConversionName) - ConversionName = Name; ConversionDecls.append(Result.begin(), Result.end()); - return; - - default: break; } - - Generator.insert(Name, Result, Trait); - }); - - // Add the constructors. - if (!ConstructorDecls.empty()) { - Generator.insert(ConstructorName, - DeclContext::lookup_result(ConstructorDecls.begin(), - ConstructorDecls.end()), - Trait); } - // Add the conversion functions. - if (!ConversionDecls.empty()) { - Generator.insert(ConversionName, - DeclContext::lookup_result(ConversionDecls.begin(), - ConversionDecls.end()), - Trait); - } + // Handle our two special cases if we ended up having any. We arbitrarily use + // the first declaration's name here because the name itself isn't part of + // the key, only the kind of name is used. + if (!ConstructorDecls.empty()) + Generator.insert(ConstructorDecls.front()->getDeclName(), + DeclContext::lookup_result(ConstructorDecls), Trait); + if (!ConversionDecls.empty()) + Generator.insert(ConversionDecls.front()->getDeclName(), + DeclContext::lookup_result(ConversionDecls), Trait); // Create the on-disk hash table in a buffer. llvm::raw_svector_ostream Out(LookupTable); @@ -3798,9 +3624,8 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, if (DC->getPrimaryContext() != DC) return 0; - // Since there is no name lookup into functions or methods, don't bother to - // build a visible-declarations table for these entities. - if (DC->isFunctionOrMethod()) + // Skip contexts which don't support name lookup. + if (!DC->isLookupContext()) return 0; // If not in C++, we perform name lookup for the translation unit via the @@ -3827,7 +3652,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, Record.push_back(DECL_CONTEXT_VISIBLE); Record.push_back(BucketOffset); Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record, - LookupTable.str()); + LookupTable); ++NumVisibleDeclContexts; return Offset; } @@ -3852,7 +3677,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { Record.push_back(UPDATE_VISIBLE); Record.push_back(getDeclID(cast<Decl>(DC))); Record.push_back(BucketOffset); - Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable.str()); + Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable); } /// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions. @@ -3902,18 +3727,6 @@ void ASTWriter::WriteRedeclarations() { } } - if (!First->isFromASTFile() && Chain) { - Decl *FirstFromAST = MostRecent; - for (Decl *Prev = MostRecent; Prev; Prev = Prev->getPreviousDecl()) { - if (Prev->isFromASTFile()) - FirstFromAST = Prev; - } - - // FIXME: Do we need to do this for the first declaration from each - // redeclaration chain that was merged into this one? - Chain->MergedDecls[FirstFromAST].push_back(getDeclID(First)); - } - LocalRedeclChains[Offset] = Size; // Reverse the set of local redeclarations, so that we store them in @@ -4008,25 +3821,6 @@ void ASTWriter::WriteObjCCategories() { Stream.EmitRecord(OBJC_CATEGORIES, Categories); } -void ASTWriter::WriteMergedDecls() { - if (!Chain || Chain->MergedDecls.empty()) - return; - - RecordData Record; - for (ASTReader::MergedDeclsMap::iterator I = Chain->MergedDecls.begin(), - IEnd = Chain->MergedDecls.end(); - I != IEnd; ++I) { - DeclID CanonID = I->first->isFromASTFile()? I->first->getGlobalID() - : GetDeclRef(I->first); - assert(CanonID && "Merged declaration not known?"); - - Record.push_back(CanonID); - Record.push_back(I->second.size()); - Record.append(I->second.begin(), I->second.end()); - } - Stream.EmitRecord(MERGED_DECLARATIONS, Record); -} - void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) { Sema::LateParsedTemplateMapT &LPTMap = SemaRef.LateParsedTemplateMap; @@ -4034,11 +3828,10 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) { return; RecordData Record; - for (Sema::LateParsedTemplateMapT::iterator It = LPTMap.begin(), - ItEnd = LPTMap.end(); - It != ItEnd; ++It) { - LateParsedTemplate *LPT = It->second; - AddDeclRef(It->first, Record); + for (auto LPTMapEntry : LPTMap) { + const FunctionDecl *FD = LPTMapEntry.first; + LateParsedTemplate *LPT = LPTMapEntry.second; + AddDeclRef(FD, Record); AddDeclRef(LPT->D, Record); Record.push_back(LPT->Toks.size()); @@ -4175,7 +3968,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), NumVisibleDeclContexts(0), - NextCXXBaseSpecifiersID(1), TypeExtQualAbbrev(0), + NextCXXBaseSpecifiersID(1), NextCXXCtorInitializersID(1), + TypeExtQualAbbrev(0), TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0), DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0), UpdateVisibleAbbrev(0), DeclRecordAbbrev(0), DeclTypedefAbbrev(0), @@ -4188,6 +3982,11 @@ ASTWriter::~ASTWriter() { llvm::DeleteContainerSeconds(FileDeclIDs); } +const LangOptions &ASTWriter::getLangOpts() const { + assert(WritingAST && "can't determine lang opts when not writing AST"); + return Context->getLangOpts(); +} + void ASTWriter::WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, @@ -4258,47 +4057,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, DeclIDs[Context.ObjCInstanceTypeDecl] = PREDEF_DECL_OBJC_INSTANCETYPE_ID; if (Context.BuiltinVaListDecl) DeclIDs[Context.getBuiltinVaListDecl()] = PREDEF_DECL_BUILTIN_VA_LIST_ID; - - if (!Chain) { - // Make sure that we emit IdentifierInfos (and any attached - // declarations) for builtins. We don't need to do this when we're - // emitting chained PCH files, because all of the builtins will be - // in the original PCH file. - // FIXME: Modules won't like this at all. - IdentifierTable &Table = PP.getIdentifierTable(); - SmallVector<const char *, 32> BuiltinNames; - if (!Context.getLangOpts().NoBuiltin) { - Context.BuiltinInfo.GetBuiltinNames(BuiltinNames); - } - for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I) - getIdentifierRef(&Table.get(BuiltinNames[I])); - } - - // If there are any out-of-date identifiers, bring them up to date. - if (ExternalPreprocessorSource *ExtSource = PP.getExternalSource()) { - // Find out-of-date identifiers. - SmallVector<IdentifierInfo *, 4> OutOfDate; - for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), - IDEnd = PP.getIdentifierTable().end(); - ID != IDEnd; ++ID) { - if (ID->second->isOutOfDate()) - OutOfDate.push_back(ID->second); - } - - // Update the out-of-date identifiers. - for (unsigned I = 0, N = OutOfDate.size(); I != N; ++I) { - ExtSource->updateOutOfDateIdentifier(*OutOfDate[I]); - } - } - - // If we saw any DeclContext updates before we started writing the AST file, - // make sure all visible decls in those DeclContexts are written out. - if (!UpdatedDeclContexts.empty()) { - auto OldUpdatedDeclContexts = std::move(UpdatedDeclContexts); - UpdatedDeclContexts.clear(); - for (auto *DC : OldUpdatedDeclContexts) - AddUpdatedDeclContext(DC); - } + if (Context.ExternCContext) + DeclIDs[Context.ExternCContext] = PREDEF_DECL_EXTERN_C_CONTEXT_ID; // Build a record containing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for @@ -4322,31 +4082,15 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // entire table, since later PCH files in a PCH chain are only interested in // the results at the end of the chain. RecordData WeakUndeclaredIdentifiers; - if (!SemaRef.WeakUndeclaredIdentifiers.empty()) { - for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator - I = SemaRef.WeakUndeclaredIdentifiers.begin(), - E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) { - AddIdentifierRef(I->first, WeakUndeclaredIdentifiers); - AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers); - AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers); - WeakUndeclaredIdentifiers.push_back(I->second.getUsed()); - } + for (auto &WeakUndeclaredIdentifier : SemaRef.WeakUndeclaredIdentifiers) { + IdentifierInfo *II = WeakUndeclaredIdentifier.first; + WeakInfo &WI = WeakUndeclaredIdentifier.second; + AddIdentifierRef(II, WeakUndeclaredIdentifiers); + AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); + AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); + WeakUndeclaredIdentifiers.push_back(WI.getUsed()); } - // Build a record containing all of the locally-scoped extern "C" - // declarations in this header file. Generally, this record will be - // empty. - RecordData LocallyScopedExternCDecls; - // FIXME: This is filling in the AST file in densemap order which is - // nondeterminstic! - for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator - TD = SemaRef.LocallyScopedExternCDecls.begin(), - TDEnd = SemaRef.LocallyScopedExternCDecls.end(); - TD != TDEnd; ++TD) { - if (!TD->second->isFromASTFile()) - AddDeclRef(TD->second, LocallyScopedExternCDecls); - } - // Build a record containing all of the ext_vector declarations. RecordData ExtVectorDecls; AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); @@ -4366,10 +4110,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) AddDeclRef(TD, UnusedLocalTypedefNameCandidates); - // Build a record containing all of dynamic classes declarations. - RecordData DynamicClasses; - AddLazyVectorDecls(*this, SemaRef.DynamicClasses, DynamicClasses); - // Build a record containing all of pending implicit instantiations. RecordData PendingInstantiations; for (std::deque<Sema::PendingImplicitInstantiation>::iterator @@ -4414,6 +4154,20 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, AddSourceLocation(I->second, UndefinedButUsed); } + // Build a record containing all delete-expressions that we would like to + // analyze later in AST. + RecordData DeleteExprsToAnalyze; + + for (const auto &DeleteExprsInfo : + SemaRef.getMismatchingDeleteExpressions()) { + AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); + DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); + for (const auto &DeleteLoc : DeleteExprsInfo.second) { + AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze); + DeleteExprsToAnalyze.push_back(DeleteLoc.second); + } + } + // Write the control block WriteControlBlock(PP, Context, isysroot, OutputFile); @@ -4443,7 +4197,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Record.clear(); Record.push_back(TU_UPDATE_LEXICAL); Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, - data(NewGlobalDecls)); + bytes(NewGlobalDecls)); // And a visible updates block for the translation unit. Abv = new llvm::BitCodeAbbrev(); @@ -4453,6 +4207,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv); WriteDeclContextVisibleUpdate(TU); + + // If we have any extern "C" names, write out a visible update for them. + if (Context.ExternCContext) + WriteDeclContextVisibleUpdate(Context.ExternCContext); // 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. @@ -4485,16 +4243,21 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // Make sure all decls associated with an identifier are registered for // serialization. + llvm::SmallVector<const IdentifierInfo*, 256> IIs; for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), IDEnd = PP.getIdentifierTable().end(); ID != IDEnd; ++ID) { const IdentifierInfo *II = ID->second; - if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) { - for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II), - DEnd = SemaRef.IdResolver.end(); - D != DEnd; ++D) { - GetDeclRef(*D); - } + if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) + IIs.push_back(II); + } + // Sort the identifiers to visit based on their name. + std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>()); + for (const IdentifierInfo *II : IIs) { + for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II), + DEnd = SemaRef.IdResolver.end(); + D != DEnd; ++D) { + GetDeclRef(*D); } } @@ -4601,6 +4364,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, if (!DeclUpdatesOffsetsRecord.empty()) Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); WriteCXXBaseSpecifiersOffsets(); + WriteCXXCtorInitializersOffsets(); WriteFileDeclIDsMap(); WriteSourceManagerBlock(Context.getSourceManager(), PP); @@ -4637,11 +4401,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, WeakUndeclaredIdentifiers); - // Write the record containing locally-scoped extern "C" definitions. - if (!LocallyScopedExternCDecls.empty()) - Stream.EmitRecord(LOCALLY_SCOPED_EXTERN_C_DECLS, - LocallyScopedExternCDecls); - // Write the record containing ext_vector type names. if (!ExtVectorDecls.empty()) Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); @@ -4650,10 +4409,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, 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 potentially unused local typedefs. if (!UnusedLocalTypedefNameCandidates.empty()) Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, @@ -4682,7 +4437,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // Write the undefined internal functions and variables, and inline functions. if (!UndefinedButUsed.empty()) Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); - + + if (!DeleteExprsToAnalyze.empty()) + Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); + // Write the visible updates to DeclContexts. for (auto *DC : UpdatedDeclContexts) WriteDeclContextVisibleUpdate(DC); @@ -4720,7 +4478,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // FIXME: If the module has macros imported then later has declarations // imported, this location won't be the right one as a location for the // declaration imports. - AddSourceLocation(Import.M->MacroVisibilityLoc, ImportedModules); + AddSourceLocation(PP.getModuleImportLoc(Import.M), ImportedModules); } Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); @@ -4729,7 +4487,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, WriteDeclReplacementsBlock(); WriteRedeclarations(); - WriteMergedDecls(); WriteObjCCategories(); WriteLateParsedTemplates(SemaRef); if(!WritingModule) @@ -4784,7 +4541,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { auto *RD = cast<CXXRecordDecl>(D); - AddUpdatedDeclContext(RD->getPrimaryContext()); + UpdatedDeclContexts.insert(RD->getPrimaryContext()); AddCXXDefinitionData(RD, Record); Record.push_back(WriteDeclContextLexicalBlock( *Context, const_cast<CXXRecordDecl *>(RD))); @@ -4828,6 +4585,10 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { break; } + case UPD_CXX_RESOLVED_DTOR_DELETE: + AddDeclRef(Update.getDecl(), Record); + break; + case UPD_CXX_RESOLVED_EXCEPTION_SPEC: addExceptionSpec( *this, @@ -4846,10 +4607,15 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { case UPD_STATIC_LOCAL_NUMBER: Record.push_back(Update.getNumber()); break; + case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: AddSourceRange(D->getAttr<OMPThreadPrivateDeclAttr>()->getRange(), Record); break; + + case UPD_DECL_EXPORTED: + Record.push_back(getSubmoduleID(Update.getModule())); + break; } } @@ -4859,8 +4625,6 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { Record.push_back(Def->isInlined()); AddSourceLocation(Def->getInnerLocStart(), Record); AddFunctionDefinition(Def, Record); - if (auto *DD = dyn_cast<CXXDestructorDecl>(Def)) - Record.push_back(GetDeclRef(DD->getOperatorDelete())); } OffsetsRecord.push_back(GetDeclRef(D)); @@ -4868,11 +4632,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { Stream.EmitRecord(DECL_UPDATES, Record); - // Flush any statements that were written as part of this update record. - FlushStmts(); - - // Flush C++ base specifiers, if there are any. - FlushCXXBaseSpecifiers(); + FlushPendingAfterDecl(); } } @@ -4953,8 +4713,7 @@ MacroID ASTWriter::getMacroID(MacroInfo *MI) { } uint64_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) { - assert(IdentMacroDirectivesOffsetMap[Name] && "not set!"); - return IdentMacroDirectivesOffsetMap[Name]; + return IdentMacroDirectivesOffsetMap.lookup(Name); } void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { @@ -4984,8 +4743,16 @@ void ASTWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record AddDeclRef(Temp->getDestructor(), Record); } +void ASTWriter::AddCXXCtorInitializersRef(ArrayRef<CXXCtorInitializer *> Inits, + RecordDataImpl &Record) { + assert(!Inits.empty() && "Empty ctor initializer sets are not recorded"); + CXXCtorInitializersToWrite.push_back( + QueuedCXXCtorInitializers(NextCXXCtorInitializersID, Inits)); + Record.push_back(NextCXXCtorInitializersID++); +} + void ASTWriter::AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases, - CXXBaseSpecifier const *BasesEnd, + CXXBaseSpecifier const *BasesEnd, RecordDataImpl &Record) { assert(Bases != BasesEnd && "Empty base-specifier sets are not recorded"); CXXBaseSpecifiersToWrite.push_back( @@ -5060,46 +4827,40 @@ void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) { Record.push_back(GetOrCreateTypeID(T)); } -TypeID ASTWriter::GetOrCreateTypeID( QualType T) { - assert(Context); - return MakeTypeID(*Context, T, - std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this)); -} - -TypeID ASTWriter::getTypeID(QualType T) const { +TypeID ASTWriter::GetOrCreateTypeID(QualType T) { assert(Context); - return MakeTypeID(*Context, T, - std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this)); -} + return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { + if (T.isNull()) + return TypeIdx(); + assert(!T.getLocalFastQualifiers()); -TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) { - if (T.isNull()) - return TypeIdx(); - assert(!T.getLocalFastQualifiers()); + TypeIdx &Idx = TypeIdxs[T]; + if (Idx.getIndex() == 0) { + if (DoneWritingDeclsAndTypes) { + assert(0 && "New type seen after serializing all the types to emit!"); + return TypeIdx(); + } - TypeIdx &Idx = TypeIdxs[T]; - if (Idx.getIndex() == 0) { - if (DoneWritingDeclsAndTypes) { - assert(0 && "New type seen after serializing all the types to emit!"); - return TypeIdx(); + // We haven't seen this type before. Assign it a new ID and put it + // into the queue of types to emit. + Idx = TypeIdx(NextTypeID++); + DeclTypesToEmit.push(T); } - - // We haven't seen this type before. Assign it a new ID and put it - // into the queue of types to emit. - Idx = TypeIdx(NextTypeID++); - DeclTypesToEmit.push(T); - } - return Idx; + return Idx; + }); } -TypeIdx ASTWriter::getTypeIdx(QualType T) const { - if (T.isNull()) - return TypeIdx(); - assert(!T.getLocalFastQualifiers()); +TypeID ASTWriter::getTypeID(QualType T) const { + assert(Context); + return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { + if (T.isNull()) + return TypeIdx(); + assert(!T.getLocalFastQualifiers()); - TypeIdxMap::const_iterator I = TypeIdxs.find(T); - assert(I != TypeIdxs.end() && "Type not emitted!"); - return I->second; + TypeIdxMap::const_iterator I = TypeIdxs.find(T); + assert(I != TypeIdxs.end() && "Type not emitted!"); + return I->second; + }); } void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { @@ -5234,13 +4995,10 @@ unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) { // already done so. auto It = AnonymousDeclarationNumbers.find(D); if (It == AnonymousDeclarationNumbers.end()) { - unsigned Index = 0; - for (Decl *LexicalD : D->getLexicalDeclContext()->decls()) { - auto *ND = dyn_cast<NamedDecl>(LexicalD); - if (!ND || !needsAnonymousDeclarationNumber(ND)) - continue; - AnonymousDeclarationNumbers[ND] = Index++; - } + auto *DC = D->getLexicalDeclContext(); + numberAnonymousDeclsWithin(DC, [&](const NamedDecl *ND, unsigned Number) { + AnonymousDeclarationNumbers[ND] = Number; + }); It = AnonymousDeclarationNumbers.find(D); assert(It != AnonymousDeclarationNumbers.end() && @@ -5555,7 +5313,8 @@ void ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, void ASTWriter::FlushCXXBaseSpecifiers() { RecordData Record; - for (unsigned I = 0, N = CXXBaseSpecifiersToWrite.size(); I != N; ++I) { + unsigned N = CXXBaseSpecifiersToWrite.size(); + for (unsigned I = 0; I != N; ++I) { Record.clear(); // Record the offset of this base-specifier set. @@ -5579,6 +5338,8 @@ void ASTWriter::FlushCXXBaseSpecifiers() { FlushStmts(); } + assert(N == CXXBaseSpecifiersToWrite.size() && + "added more base specifiers while writing base specifiers"); CXXBaseSpecifiersToWrite.clear(); } @@ -5620,6 +5381,36 @@ void ASTWriter::AddCXXCtorInitializers( } } +void ASTWriter::FlushCXXCtorInitializers() { + RecordData Record; + + unsigned N = CXXCtorInitializersToWrite.size(); + (void)N; // Silence unused warning in non-assert builds. + for (auto &Init : CXXCtorInitializersToWrite) { + Record.clear(); + + // Record the offset of this mem-initializer list. + unsigned Index = Init.ID - 1; + if (Index == CXXCtorInitializersOffsets.size()) + CXXCtorInitializersOffsets.push_back(Stream.GetCurrentBitNo()); + else { + if (Index > CXXCtorInitializersOffsets.size()) + CXXCtorInitializersOffsets.resize(Index + 1); + CXXCtorInitializersOffsets[Index] = Stream.GetCurrentBitNo(); + } + + AddCXXCtorInitializers(Init.Inits.data(), Init.Inits.size(), Record); + Stream.EmitRecord(serialization::DECL_CXX_CTOR_INITIALIZERS, Record); + + // Flush any expressions that were written as part of the initializers. + FlushStmts(); + } + + assert(N == CXXCtorInitializersToWrite.size() && + "added more ctor initializers while writing ctor initializers"); + CXXCtorInitializersToWrite.clear(); +} + void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) { auto &Data = D->data(); Record.push_back(Data.IsLambda); @@ -5725,6 +5516,8 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { Chain = Reader; + // Note, this will get called multiple times, once one the reader starts up + // and again each time it's done reading a PCH or module. FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); @@ -5772,7 +5565,7 @@ void ASTWriter::SelectorRead(SelectorID ID, Selector S) { } void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, - MacroDefinition *MD) { + MacroDefinitionRecord *MD) { assert(MacroDefinitions.find(MD) == MacroDefinitions.end()); MacroDefinitions[MD] = ID; } @@ -5809,7 +5602,7 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!"); assert(!WritingAST && "Already writing the AST!"); - AddUpdatedDeclContext(DC); + UpdatedDeclContexts.insert(DC); UpdatingVisibleDecls.push_back(D); } @@ -5863,21 +5656,36 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, } void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) { - assert(!WritingAST && "Already writing the AST!"); - FD = FD->getCanonicalDecl(); - if (!FD->isFromASTFile()) - return; // Not a function declared in PCH and defined outside. - - DeclUpdates[FD].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC); + assert(!DoneWritingDeclsAndTypes && "Already done writing updates!"); + if (!Chain) return; + Chain->forEachFormerlyCanonicalImportedDecl(FD, [&](const Decl *D) { + // If we don't already know the exception specification for this redecl + // chain, add an update record for it. + if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D) + ->getType() + ->castAs<FunctionProtoType>() + ->getExceptionSpecType())) + DeclUpdates[D].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC); + }); } void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) { assert(!WritingAST && "Already writing the AST!"); - FD = FD->getCanonicalDecl(); - if (!FD->isFromASTFile()) - return; // Not a function declared in PCH and defined outside. + if (!Chain) return; + Chain->forEachFormerlyCanonicalImportedDecl(FD, [&](const Decl *D) { + DeclUpdates[D].push_back( + DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType)); + }); +} - DeclUpdates[FD].push_back(DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType)); +void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD, + const FunctionDecl *Delete) { + assert(!WritingAST && "Already writing the AST!"); + assert(Delete && "Not given an operator delete"); + if (!Chain) return; + Chain->forEachFormerlyCanonicalImportedDecl(DD, [&](const Decl *D) { + DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete)); + }); } void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { @@ -5894,8 +5702,7 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) { if (!D->isFromASTFile()) return; - DeclUpdates[D].push_back( - DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); + DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { @@ -5951,3 +5758,12 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) { DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE)); } + +void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) { + assert(!WritingAST && "Already writing the AST!"); + assert(D->isHidden() && "expected a hidden declaration"); + if (!D->isFromASTFile()) + return; + + DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_EXPORTED, M)); +} diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp index c97c2d8..0fa4f93 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp @@ -133,11 +133,66 @@ namespace clang { void AddFunctionDefinition(const FunctionDecl *FD) { assert(FD->doesThisDeclarationHaveABody()); - if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) - Writer.AddCXXCtorInitializers(CD->CtorInitializers, - CD->NumCtorInitializers, Record); + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { + Record.push_back(CD->NumCtorInitializers); + if (CD->NumCtorInitializers) + Writer.AddCXXCtorInitializersRef( + llvm::makeArrayRef(CD->init_begin(), CD->init_end()), Record); + } Writer.AddStmt(FD->getBody()); } + + /// Get the specialization decl from an entry in the specialization list. + template <typename EntryType> + typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * + getSpecializationDecl(EntryType &T) { + return RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::getDecl(&T); + } + + /// Get the list of partial specializations from a template's common ptr. + template<typename T> + decltype(T::PartialSpecializations) &getPartialSpecializations(T *Common) { + return Common->PartialSpecializations; + } + ArrayRef<Decl> getPartialSpecializations(FunctionTemplateDecl::Common *) { + return None; + } + + template<typename Decl> + void AddTemplateSpecializations(Decl *D) { + auto *Common = D->getCommonPtr(); + + // If we have any lazy specializations, and the external AST source is + // our chained AST reader, we can just write out the DeclIDs. Otherwise, + // we need to resolve them to actual declarations. + if (Writer.Chain != Writer.Context->getExternalSource() && + Common->LazySpecializations) { + D->LoadLazySpecializations(); + assert(!Common->LazySpecializations); + } + + auto &Specializations = Common->Specializations; + auto &&PartialSpecializations = getPartialSpecializations(Common); + ArrayRef<DeclID> LazySpecializations; + if (auto *LS = Common->LazySpecializations) + LazySpecializations = ArrayRef<DeclID>(LS + 1, LS + 1 + LS[0]); + + Record.push_back(Specializations.size() + + PartialSpecializations.size() + + LazySpecializations.size()); + for (auto &Entry : Specializations) { + auto *D = getSpecializationDecl(Entry); + assert(D->isCanonicalDecl() && "non-canonical decl in set"); + Writer.AddDeclRef(D, Record); + } + for (auto &Entry : PartialSpecializations) { + auto *D = getSpecializationDecl(Entry); + assert(D->isCanonicalDecl() && "non-canonical decl in set"); + Writer.AddDeclRef(D, Record); + } + for (DeclID ID : LazySpecializations) + Record.push_back(ID); + } }; } @@ -157,7 +212,7 @@ void ASTDeclWriter::Visit(Decl *D) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { Record.push_back(FD->doesThisDeclarationHaveABody()); if (FD->doesThisDeclarationHaveABody()) - Writer.AddStmt(FD->getBody()); + AddFunctionDefinition(FD); } } @@ -188,7 +243,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) { while (auto *NS = dyn_cast<NamespaceDecl>(DC->getRedeclContext())) { if (!NS->isFromASTFile()) break; - Writer.AddUpdatedDeclContext(NS->getPrimaryContext()); + Writer.UpdatedDeclContexts.insert(NS->getPrimaryContext()); if (!NS->isInlineNamespace()) break; DC = NS->getParent(); @@ -203,8 +258,9 @@ void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { VisitDecl(D); Writer.AddDeclarationName(D->getDeclName(), Record); - if (needsAnonymousDeclarationNumber(D)) - Record.push_back(Writer.getAnonymousDeclarationNumber(D)); + Record.push_back(needsAnonymousDeclarationNumber(D) + ? Writer.getAnonymousDeclarationNumber(D) + : 0); } void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { @@ -658,8 +714,10 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); Record.push_back(D->hasNonZeroConstructors()); Record.push_back(D->hasDestructors()); - Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers, - Record); + Record.push_back(D->NumIvarInitializers); + if (D->NumIvarInitializers) + Writer.AddCXXCtorInitializersRef( + llvm::makeArrayRef(D->init_begin(), D->init_end()), Record); Code = serialization::DECL_OBJC_IMPLEMENTATION; } @@ -732,13 +790,15 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(D->getStorageClass()); Record.push_back(D->getTSCSpec()); Record.push_back(D->getInitStyle()); - Record.push_back(D->isExceptionVariable()); - Record.push_back(D->isNRVOVariable()); - Record.push_back(D->isCXXForRangeDecl()); - Record.push_back(D->isARCPseudoStrong()); - Record.push_back(D->isConstexpr()); - Record.push_back(D->isInitCapture()); - Record.push_back(D->isPreviousDeclInSameBlockScope()); + if (!isa<ParmVarDecl>(D)) { + Record.push_back(D->isExceptionVariable()); + Record.push_back(D->isNRVOVariable()); + Record.push_back(D->isCXXForRangeDecl()); + Record.push_back(D->isARCPseudoStrong()); + Record.push_back(D->isConstexpr()); + Record.push_back(D->isInitCapture()); + Record.push_back(D->isPreviousDeclInSameBlockScope()); + } Record.push_back(D->getLinkageInternal()); if (D->getInit()) { @@ -920,17 +980,34 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { if (Writer.hasChain() && !D->isOriginalNamespace() && D->getOriginalNamespace()->isFromASTFile()) { NamespaceDecl *NS = D->getOriginalNamespace(); - Writer.AddUpdatedDeclContext(NS); - - // Make sure all visible decls are written. They will be recorded later. - if (StoredDeclsMap *Map = NS->buildLookup()) { - for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); - D != DEnd; ++D) { - DeclContext::lookup_result R = D->second.getLookupResult(); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; - ++I) - Writer.GetDeclRef(*I); + Writer.UpdatedDeclContexts.insert(NS); + + // Make sure all visible decls are written. They will be recorded later. We + // do this using a side data structure so we can sort the names into + // a deterministic order. + StoredDeclsMap *Map = NS->buildLookup(); + SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16> + LookupResults; + LookupResults.reserve(Map->size()); + for (auto &Entry : *Map) + LookupResults.push_back( + std::make_pair(Entry.first, Entry.second.getLookupResult())); + + std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first()); + for (auto &NameAndResult : LookupResults) { + DeclarationName Name = NameAndResult.first; + DeclContext::lookup_result Result = NameAndResult.second; + if (Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + // We have to work around a name lookup bug here where negative lookup + // results for these names get cached in namespace lookup tables. + assert(Result.empty() && "Cannot have a constructor or conversion " + "function name in a namespace!"); + continue; } + + for (NamedDecl *ND : Result) + Writer.GetDeclRef(ND); } } @@ -1067,8 +1144,6 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { Writer.AddDeclRef(D->getInheritedConstructor(), Record); Record.push_back(D->IsExplicitSpecified); - Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers, - Record); Code = serialization::DECL_CXX_CONSTRUCTOR; } @@ -1076,7 +1151,7 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { VisitCXXMethodDecl(D); - Writer.AddDeclRef(D->OperatorDelete, Record); + Writer.AddDeclRef(D->getOperatorDelete(), Record); Code = serialization::DECL_CXX_DESTRUCTOR; } @@ -1171,24 +1246,8 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->isFirstDecl()) { - typedef llvm::FoldingSetVector<ClassTemplateSpecializationDecl> CTSDSetTy; - CTSDSetTy &CTSDSet = D->getSpecializations(); - Record.push_back(CTSDSet.size()); - for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - - typedef llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> - CTPSDSetTy; - CTPSDSetTy &CTPSDSet = D->getPartialSpecializations(); - Record.push_back(CTPSDSet.size()); - for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - } + if (D->isFirstDecl()) + AddTemplateSpecializations(D); Code = serialization::DECL_CLASS_TEMPLATE; } @@ -1246,26 +1305,8 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->isFirstDecl()) { - typedef llvm::FoldingSetVector<VarTemplateSpecializationDecl> VTSDSetTy; - VTSDSetTy &VTSDSet = D->getSpecializations(); - Record.push_back(VTSDSet.size()); - for (VTSDSetTy::iterator I = VTSDSet.begin(), E = VTSDSet.end(); I != E; - ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - - typedef llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> - VTPSDSetTy; - VTPSDSetTy &VTPSDSet = D->getPartialSpecializations(); - Record.push_back(VTPSDSet.size()); - for (VTPSDSetTy::iterator I = VTPSDSet.begin(), E = VTPSDSet.end(); I != E; - ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - } + if (D->isFirstDecl()) + AddTemplateSpecializations(D); Code = serialization::DECL_VAR_TEMPLATE; } @@ -1330,19 +1371,8 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->isFirstDecl()) { - // This FunctionTemplateDecl owns the CommonPtr; write it. - - // Write the function specialization declarations. - Record.push_back(D->getSpecializations().size()); - for (llvm::FoldingSetVector<FunctionTemplateSpecializationInfo>::iterator - I = D->getSpecializations().begin(), - E = D->getSpecializations().end() ; I != E; ++I) { - assert(I->Function->isCanonicalDecl() && - "Expected only canonical decls in set"); - Writer.AddDeclRef(I->Function, Record); - } - } + if (D->isFirstDecl()) + AddTemplateSpecializations(D); Code = serialization::DECL_FUNCTION_TEMPLATE; } @@ -1448,25 +1478,59 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, template <typename T> void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { T *First = D->getFirstDecl(); - if (First->getMostRecentDecl() != First) { + T *MostRecent = First->getMostRecentDecl(); + if (MostRecent != First) { assert(isRedeclarableDeclKind(static_cast<T *>(D)->getKind()) && "Not considered redeclarable?"); - + // There is more than one declaration of this entity, so we will need to // write a redeclaration chain. Writer.AddDeclRef(First, Record); Writer.Redeclarations.insert(First); + auto *Previous = D->getPreviousDecl(); + + // In a modules build, we can have imported declarations after a local + // canonical declaration. If this is the first local declaration, emit + // a list of all such imported declarations so that we can ensure they + // are loaded before we are. This allows us to rebuild the redecl chain + // in the right order on reload (all declarations imported by a module + // should be before all declarations provided by that module). + bool EmitImportedMergedCanonicalDecls = false; + if (Context.getLangOpts().Modules && Writer.Chain) { + auto *PreviousLocal = Previous; + while (PreviousLocal && PreviousLocal->isFromASTFile()) + PreviousLocal = PreviousLocal->getPreviousDecl(); + if (!PreviousLocal) + EmitImportedMergedCanonicalDecls = true; + } + if (EmitImportedMergedCanonicalDecls) { + llvm::SmallMapVector<ModuleFile*, Decl*, 16> FirstInModule; + for (auto *Redecl = MostRecent; Redecl; + Redecl = Redecl->getPreviousDecl()) + if (Redecl->isFromASTFile()) + FirstInModule[Writer.Chain->getOwningModuleFile(Redecl)] = Redecl; + // FIXME: If FirstInModule has entries for modules A and B, and B imports + // A (directly or indirectly), we don't need to write the entry for A. + Record.push_back(FirstInModule.size()); + for (auto I = FirstInModule.rbegin(), E = FirstInModule.rend(); + I != E; ++I) + Writer.AddDeclRef(I->second, Record); + } else + Record.push_back(0); + // Make sure that we serialize both the previous and the most-recent // declarations, which (transitively) ensures that all declarations in the // chain get serialized. - (void)Writer.GetDeclRef(D->getPreviousDecl()); - (void)Writer.GetDeclRef(First->getMostRecentDecl()); + // + // FIXME: This is not correct; when we reach an imported declaration we + // won't emit its previous declaration. + (void)Writer.GetDeclRef(Previous); + (void)Writer.GetDeclRef(MostRecent); } else { // We use the sentinel value 0 to indicate an only declaration. Record.push_back(0); } - } void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { @@ -1504,6 +1568,7 @@ void ASTWriter::WriteDeclAbbrevs() { // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // ValueDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl @@ -1536,6 +1601,7 @@ void ASTWriter::WriteDeclAbbrevs() { // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // ValueDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl @@ -1573,6 +1639,7 @@ void ASTWriter::WriteDeclAbbrevs() { // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // TypeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref @@ -1620,6 +1687,7 @@ void ASTWriter::WriteDeclAbbrevs() { // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // TypeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref @@ -1662,6 +1730,7 @@ void ASTWriter::WriteDeclAbbrevs() { // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // ValueDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl @@ -1671,13 +1740,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // StorageClass Abv->Add(BitCodeAbbrevOp(0)); // getTSCSpec Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer - Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable - Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable - Abv->Add(BitCodeAbbrevOp(0)); // isCXXForRangeDecl - Abv->Add(BitCodeAbbrevOp(0)); // isARCPseudoStrong - Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr - Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture - Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope Abv->Add(BitCodeAbbrevOp(0)); // Linkage Abv->Add(BitCodeAbbrevOp(0)); // HasInit Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo @@ -1715,6 +1777,7 @@ void ASTWriter::WriteDeclAbbrevs() { // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // TypeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref @@ -1743,6 +1806,7 @@ void ASTWriter::WriteDeclAbbrevs() { // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // ValueDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl @@ -1788,6 +1852,7 @@ void ASTWriter::WriteDeclAbbrevs() { // NamedDecl Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // ValueDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl @@ -1948,9 +2013,10 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { // Determine the ID for this declaration. serialization::DeclID ID; - if (D->isFromASTFile()) + if (D->isFromASTFile()) { + assert(isRewritten(D) && "should not be emitting imported decl"); ID = getDeclID(D); - else { + } else { serialization::DeclID &IDR = DeclIDs[D]; if (IDR == 0) IDR = NextDeclID++; @@ -2015,12 +2081,10 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { D->getDeclKindName() + "'"); Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); - // Flush any expressions that were written as part of this declaration. - FlushStmts(); - - // Flush C++ base specifiers, if there are any. - FlushCXXBaseSpecifiers(); - + // Flush any expressions, base specifiers, and ctor initializers that + // were written as part of this declaration. + FlushPendingAfterDecl(); + // Note declarations that should be deserialized eagerly so that we can add // them to a record in the AST file later. if (isRequiredDecl(D, Context)) diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp index e980ce7..ec822f0 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp @@ -553,6 +553,7 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { Writer.AddDeclRef(E->getMemberDecl(), Record); Writer.AddSourceLocation(E->getMemberLoc(), Record); Record.push_back(E->isArrow()); + Writer.AddSourceLocation(E->getOperatorLoc(), Record); Writer.AddDeclarationNameLoc(E->MemberDNLoc, E->getMemberDecl()->getDeclName(), Record); Code = serialization::EXPR_MEMBER; @@ -1744,6 +1745,7 @@ void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) { void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) { Record.push_back(C->getScheduleKind()); Writer->Writer.AddStmt(C->getChunkSize()); + Writer->Writer.AddStmt(C->getHelperChunkSize()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); Writer->Writer.AddSourceLocation(C->getScheduleKindLoc(), Record); Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record); @@ -1797,6 +1799,14 @@ void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) { Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); for (auto *VE : C->varlists()) Writer->Writer.AddStmt(VE); + for (auto *E : C->private_copies()) + Writer->Writer.AddStmt(E); + for (auto *E : C->source_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->destination_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->assignment_ops()) + Writer->Writer.AddStmt(E); } void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) { @@ -1814,15 +1824,32 @@ void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) { Writer->Writer.AddDeclarationNameInfo(C->getNameInfo(), Record); for (auto *VE : C->varlists()) Writer->Writer.AddStmt(VE); + for (auto *E : C->lhs_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->rhs_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->reduction_ops()) + Writer->Writer.AddStmt(E); } void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); Writer->Writer.AddSourceLocation(C->getColonLoc(), Record); - for (auto *VE : C->varlists()) + for (auto *VE : C->varlists()) { + Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->inits()) { Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->updates()) { + Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->finals()) { + Writer->Writer.AddStmt(VE); + } Writer->Writer.AddStmt(C->getStep()); + Writer->Writer.AddStmt(C->getCalcStep()); } void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) { @@ -1839,6 +1866,12 @@ void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) { Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); for (auto *VE : C->varlists()) Writer->Writer.AddStmt(VE); + for (auto *E : C->source_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->destination_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->assignment_ops()) + Writer->Writer.AddStmt(E); } void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { @@ -1846,6 +1879,12 @@ void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); for (auto *VE : C->varlists()) Writer->Writer.AddStmt(VE); + for (auto *E : C->source_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->destination_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->assignment_ops()) + Writer->Writer.AddStmt(E); } void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) { @@ -1990,6 +2029,9 @@ void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) { Writer.AddStmt(D->getX()); Writer.AddStmt(D->getV()); Writer.AddStmt(D->getExpr()); + Writer.AddStmt(D->getUpdateExpr()); + Record.push_back(D->isXLHSInRHSPart() ? 1 : 0); + Record.push_back(D->isPostfixUpdate() ? 1 : 0); Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE; } diff --git a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp index 4791388..1b52b44 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -757,7 +757,7 @@ void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { Record.clear(); Record.push_back(IDENTIFIER_INDEX); Record.push_back(BucketOffset); - Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); + Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable); } Stream.ExitBlock(); @@ -841,12 +841,12 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { return EC_IOError; // Remove the old index file. It isn't relevant any more. - llvm::sys::fs::remove(IndexPath.str()); + llvm::sys::fs::remove(IndexPath); // Rename the newly-written index file to the proper name. - if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) { + if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) { // Rename failed; just remove the - llvm::sys::fs::remove(IndexTmpPath.str()); + llvm::sys::fs::remove(IndexTmpPath); return EC_IOError; } diff --git a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp index 6c48a41..3b237d5 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp @@ -38,6 +38,7 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) SelectorLookupTableData(nullptr), SelectorLookupTable(nullptr), LocalNumDecls(0), DeclOffsets(nullptr), BaseDeclID(0), LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr), + LocalNumCXXCtorInitializers(0), CXXCtorInitializersOffsets(nullptr), FileSortedDecls(nullptr), NumFileSortedDecls(0), RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0), ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0), diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp index ac98ca0..30d9c89 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp @@ -58,8 +58,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, unsigned Generation, off_t ExpectedSize, time_t ExpectedModTime, ASTFileSignature ExpectedSignature, - std::function<ASTFileSignature(llvm::BitstreamReader &)> - ReadSignature, + ASTFileSignatureReader ReadSignature, ModuleFile *&Module, std::string &ErrorStr) { Module = nullptr; @@ -95,6 +94,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, New->File = Entry; New->ImportLoc = ImportLoc; Chain.push_back(New); + if (!ImportedBy) + Roots.push_back(New); NewModule = true; ModuleEntry = New; @@ -156,7 +157,12 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, // invalidate the file cache for Entry, and that is not safe if this // module is *itself* up to date, but has an out-of-date importer. Modules.erase(Entry); + assert(Chain.back() == ModuleEntry); Chain.pop_back(); + if (Roots.back() == ModuleEntry) + Roots.pop_back(); + else + assert(ImportedBy); delete ModuleEntry; } return OutOfDate; @@ -187,12 +193,15 @@ void ModuleManager::removeModules( // Collect the set of module file pointers that we'll be removing. llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last); + auto IsVictim = [&](ModuleFile *MF) { + return victimSet.count(MF); + }; // Remove any references to the now-destroyed modules. for (unsigned i = 0, n = Chain.size(); i != n; ++i) { - Chain[i]->ImportedBy.remove_if([&](ModuleFile *MF) { - return victimSet.count(MF); - }); + Chain[i]->ImportedBy.remove_if(IsVictim); } + Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim), + Roots.end()); // Delete the modules and erase them from the various structures. for (ModuleIterator victim = first; victim != last; ++victim) { @@ -227,6 +236,15 @@ ModuleManager::addInMemoryBuffer(StringRef FileName, InMemoryBuffers[Entry] = std::move(Buffer); } +bool ModuleManager::addKnownModuleFile(StringRef FileName) { + const FileEntry *File; + if (lookupModuleFile(FileName, 0, 0, File)) + return true; + if (!Modules.count(File)) + AdditionalKnownModuleFiles.insert(File); + return false; +} + ModuleManager::VisitState *ModuleManager::allocateVisitState() { // Fast path: if we have a cached state, use it. if (FirstVisitState) { @@ -263,6 +281,8 @@ void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) { } void ModuleManager::moduleFileAccepted(ModuleFile *MF) { + AdditionalKnownModuleFiles.remove(MF->File); + if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF)) return; @@ -388,16 +408,38 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), returnVisitState(State); } +static void markVisitedDepthFirst(ModuleFile &M, + SmallVectorImpl<bool> &Visited) { + for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(), + IMEnd = M.Imports.end(); + IM != IMEnd; ++IM) { + if (Visited[(*IM)->Index]) + continue; + Visited[(*IM)->Index] = true; + if (!M.DirectlyImported) + markVisitedDepthFirst(**IM, Visited); + } +} + /// \brief Perform a depth-first visit of the current module. -static bool visitDepthFirst(ModuleFile &M, - bool (*Visitor)(ModuleFile &M, bool Preorder, - void *UserData), - void *UserData, - SmallVectorImpl<bool> &Visited) { - // Preorder visitation - if (Visitor(M, /*Preorder=*/true, UserData)) - return true; - +static bool visitDepthFirst( + ModuleFile &M, + ModuleManager::DFSPreorderControl (*PreorderVisitor)(ModuleFile &M, + void *UserData), + bool (*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData, + SmallVectorImpl<bool> &Visited) { + if (PreorderVisitor) { + switch (PreorderVisitor(M, UserData)) { + case ModuleManager::Abort: + return true; + case ModuleManager::SkipImports: + markVisitedDepthFirst(M, Visited); + return false; + case ModuleManager::Continue: + break; + } + } + // Visit children for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(), IMEnd = M.Imports.end(); @@ -406,24 +448,27 @@ static bool visitDepthFirst(ModuleFile &M, continue; Visited[(*IM)->Index] = true; - if (visitDepthFirst(**IM, Visitor, UserData, Visited)) + if (visitDepthFirst(**IM, PreorderVisitor, PostorderVisitor, UserData, Visited)) return true; } - // Postorder visitation - return Visitor(M, /*Preorder=*/false, UserData); + if (PostorderVisitor) + return PostorderVisitor(M, UserData); + + return false; } -void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder, - void *UserData), - void *UserData) { +void ModuleManager::visitDepthFirst( + ModuleManager::DFSPreorderControl (*PreorderVisitor)(ModuleFile &M, + void *UserData), + bool (*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData) { SmallVector<bool, 16> Visited(size(), false); - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - if (Visited[Chain[I]->Index]) + for (unsigned I = 0, N = Roots.size(); I != N; ++I) { + if (Visited[Roots[I]->Index]) continue; - Visited[Chain[I]->Index] = true; + Visited[Roots[I]->Index] = true; - if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited)) + if (::visitDepthFirst(*Roots[I], PreorderVisitor, PostorderVisitor, UserData, Visited)) return; } } |