diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp | 1350 |
1 files changed, 583 insertions, 767 deletions
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)); +} |