diff options
Diffstat (limited to 'clang/lib/Serialization')
-rw-r--r-- | clang/lib/Serialization/ASTCommon.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 371 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 270 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderInternals.h | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 58 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 311 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 166 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Serialization/GlobalModuleIndex.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Serialization/ModuleManager.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Serialization/PCHContainerOperations.cpp | 5 |
11 files changed, 797 insertions, 455 deletions
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index 96bc47dcdb4e..72e582107480 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -250,6 +250,11 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { ID = PREDEF_TYPE_##Id##_ID; \ break; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + ID = PREDEF_TYPE_##Id##_ID; \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::BuiltinFn: ID = PREDEF_TYPE_BUILTIN_FN; break; @@ -479,8 +484,7 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { } // Otherwise, we only care about anonymous class members / block-scope decls. - // FIXME: We need to handle lambdas and blocks within inline / templated - // variables too. + // FIXME: We need to handle blocks within inline / templated variables too. if (D->getDeclName()) return false; if (!isa<RecordDecl, ObjCInterfaceDecl>(D->getLexicalDeclContext())) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 4d72596b7439..5f756961c6e1 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -105,7 +105,6 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Support/Casting.h" @@ -124,6 +123,7 @@ #include "llvm/Support/Timer.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Triple.h" #include <algorithm> #include <cassert> #include <cstddef> @@ -277,12 +277,17 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, const LangOptions &ExistingLangOpts, DiagnosticsEngine *Diags, bool AllowCompatibleDifferences = true) { -#define LANGOPT(Name, Bits, Default, Description) \ - if (ExistingLangOpts.Name != LangOpts.Name) { \ - if (Diags) \ - Diags->Report(diag::err_pch_langopt_mismatch) \ - << Description << LangOpts.Name << ExistingLangOpts.Name; \ - return true; \ +#define LANGOPT(Name, Bits, Default, Description) \ + if (ExistingLangOpts.Name != LangOpts.Name) { \ + if (Diags) { \ + if (Bits == 1) \ + Diags->Report(diag::err_pch_langopt_mismatch) \ + << Description << LangOpts.Name << ExistingLangOpts.Name; \ + else \ + Diags->Report(diag::err_pch_langopt_value_mismatch) \ + << Description; \ + } \ + return true; \ } #define VALUE_LANGOPT(Name, Bits, Default, Description) \ @@ -654,6 +659,10 @@ static bool checkPreprocessorOptions( SmallVector<StringRef, 4> ExistingMacroNames; collectMacroDefinitions(ExistingPPOpts, ExistingMacros, &ExistingMacroNames); + // Use a line marker to enter the <command line> file, as the defines and + // undefines here will have come from the command line. + SuggestedPredefines += "# 1 \"<command line>\" 1\n"; + for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) { // Dig out the macro definition in the existing preprocessor options. StringRef MacroName = ExistingMacroNames[I]; @@ -713,6 +722,10 @@ static bool checkPreprocessorOptions( } return true; } + + // Leave the <command line> file and return to <built-in>. + SuggestedPredefines += "# 1 \"<built-in>\" 2\n"; + if (Validation == OptionValidateStrictMatches) { // If strict matches are requested, don't tolerate any extra defines in // the AST file that are missing on the command line. @@ -1579,8 +1592,13 @@ bool ASTReader::ReadSLocEntry(int ID) { auto Buffer = ReadBuffer(SLocEntryCursor, Name); if (!Buffer) return true; - SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID, - BaseOffset + Offset, IncludeLoc); + FileID FID = SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID, + BaseOffset + Offset, IncludeLoc); + if (Record[3]) { + auto &FileInfo = + const_cast<SrcMgr::FileInfo &>(SourceMgr.getSLocEntry(FID).getFile()); + FileInfo.setHasLineDirectives(); + } break; } @@ -1687,6 +1705,16 @@ Token ASTReader::ReadToken(ModuleFile &F, const RecordDataImpl &Record, Tok.setAnnotationValue(static_cast<void *>(Info)); break; } + case tok::annot_pragma_pack: { + auto *Info = new (PP.getPreprocessorAllocator()) Sema::PragmaPackInfo; + Info->Action = static_cast<Sema::PragmaMsStackAction>(Record[Idx++]); + auto SlotLabel = ReadString(Record, Idx); + Info->SlotLabel = + llvm::StringRef(SlotLabel).copy(PP.getPreprocessorAllocator()); + Info->Alignment = ReadToken(F, Record, Idx); + Tok.setAnnotationValue(static_cast<void *>(Info)); + break; + } // Some annotation tokens do not use the PtrData field. case tok::annot_pragma_openmp: case tok::annot_pragma_openmp_end: @@ -1847,6 +1875,21 @@ ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, return LocalID + I->second; } +const FileEntry *HeaderFileInfoTrait::getFile(const internal_key_type &Key) { + FileManager &FileMgr = Reader.getFileManager(); + if (!Key.Imported) { + if (auto File = FileMgr.getFile(Key.Filename)) + return *File; + return nullptr; + } + + std::string Resolved = std::string(Key.Filename); + Reader.ResolveImportedPath(M, Resolved); + if (auto File = FileMgr.getFile(Resolved)) + return *File; + return nullptr; +} + unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) { return llvm::hash_combine(ikey.Size, ikey.ModTime); } @@ -1867,23 +1910,8 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) { return true; // Determine whether the actual files are equivalent. - FileManager &FileMgr = Reader.getFileManager(); - auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* { - if (!Key.Imported) { - if (auto File = FileMgr.getFile(Key.Filename)) - return *File; - return nullptr; - } - - std::string Resolved = std::string(Key.Filename); - Reader.ResolveImportedPath(M, Resolved); - if (auto File = FileMgr.getFile(Resolved)) - return *File; - return nullptr; - }; - - const FileEntry *FEA = GetFile(a); - const FileEntry *FEB = GetFile(b); + const FileEntry *FEA = getFile(a); + const FileEntry *FEB = getFile(b); return FEA && FEA == FEB; } @@ -1912,6 +1940,14 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, const unsigned char *End = d + DataLen; HeaderFileInfo HFI; unsigned Flags = *d++; + + bool Included = (Flags >> 6) & 0x01; + if (Included) + if (const FileEntry *FE = getFile(key)) + // Not using \c Preprocessor::markIncluded(), since that would attempt to + // deserialize this header file info again. + Reader.getPreprocessor().getIncludedFiles().insert(FE); + // FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp. HFI.isImport |= (Flags >> 5) & 0x01; HFI.isPragmaOnce |= (Flags >> 4) & 0x01; @@ -1945,10 +1981,11 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, std::string Filename = std::string(key.Filename); if (key.Imported) Reader.ResolveImportedPath(M, Filename); - // FIXME: NameAsWritten - Module::Header H = {std::string(key.Filename), "", - FileMgr.getOptionalFileRef(Filename)}; - ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true); + if (auto FE = FileMgr.getOptionalFileRef(Filename)) { + // FIXME: NameAsWritten + Module::Header H = {std::string(key.Filename), "", *FE}; + ModMap.addHeader(Mod, H, HeaderRole, /*Imported=*/true); + } HFI.isModuleHeader |= ModuleMap::isModular(HeaderRole); } @@ -2361,12 +2398,15 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { StringRef Filename = FI.Filename; uint64_t StoredContentHash = FI.ContentHash; + // For standard C++ modules, we don't need to check the inputs. + bool SkipChecks = F.StandardCXXModule; + OptionalFileEntryRefDegradesToFileEntryPtr File = OptionalFileEntryRef( expectedToOptional(FileMgr.getFileRef(Filename, /*OpenFile=*/false))); // For an overridden file, create a virtual file with the stored // size/timestamp. - if ((Overridden || Transient) && !File) + if ((Overridden || Transient || SkipChecks) && !File) File = FileMgr.getVirtualFileRef(Filename, StoredSize, StoredTime); if (!File) { @@ -2389,7 +2429,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { // PCH. SourceManager &SM = getSourceManager(); // FIXME: Reject if the overrides are different. - if ((!Overridden && !Transient) && SM.isFileOverridden(File)) { + if ((!Overridden && !Transient) && !SkipChecks && SM.isFileOverridden(File)) { if (Complain) Error(diag::err_fe_pch_file_overridden, Filename); @@ -2448,7 +2488,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { }; bool IsOutOfDate = false; - auto FileChange = HasInputFileChanged(); + auto FileChange = SkipChecks ? Change{Change::None} : HasInputFileChanged(); // For an overridden file, there is nothing to validate. if (!Overridden && FileChange.Kind != Change::None) { if (Complain && !Diags.isDiagnosticInFlight()) { @@ -2500,7 +2540,8 @@ void ASTReader::ResolveImportedPath(ModuleFile &M, std::string &Filename) { } void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) { - if (Filename.empty() || llvm::sys::path::is_absolute(Filename)) + if (Filename.empty() || llvm::sys::path::is_absolute(Filename) || + Filename == "<built-in>" || Filename == "<command line>") return; SmallString<128> Buffer; @@ -2792,7 +2833,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, return VersionMismatch; } - bool hasErrors = Record[6]; + bool hasErrors = Record[7]; if (hasErrors && !DisableValidation) { // If requested by the caller and the module hasn't already been read // or compiled, mark modules on error as out-of-date. @@ -2816,7 +2857,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, if (F.RelocatablePCH) F.BaseDirectory = isysroot.empty() ? "/" : isysroot; - F.HasTimestamps = Record[5]; + F.StandardCXXModule = Record[5]; + + F.HasTimestamps = Record[6]; const std::string &CurBranch = getClangFullRepositoryVersion(); StringRef ASTBranch = Blob; @@ -2840,6 +2883,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, while (Idx < N) { // Read information about the AST file. ModuleKind ImportedKind = (ModuleKind)Record[Idx++]; + // Whether we're importing a standard c++ module. + bool IsImportingStdCXXModule = Record[Idx++]; // The import location will be the local one for now; we will adjust // all import locations of module imports after the global source // location info are setup, in ReadAST. @@ -2857,18 +2902,25 @@ ASTReader::ReadControlBlock(ModuleFile &F, // For prebuilt and explicit modules first consult the file map for // an override. Note that here we don't search prebuilt module - // directories, only the explicit name to file mappings. Also, we will - // still verify the size/signature making sure it is essentially the - // same file but perhaps in a different location. + // directories if we're not importing standard c++ module, only the + // explicit name to file mappings. Also, we will still verify the + // size/signature making sure it is essentially the same file but + // perhaps in a different location. if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule) ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName( - ImportedName, /*FileMapOnly*/ true); + ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule); + + if (ImportedFile.empty()) { + // It is deprecated for C++20 Named modules to use the implicitly + // paths. + if (IsImportingStdCXXModule) + Diag(clang::diag::warn_reading_std_cxx_module_by_implicit_paths) + << ImportedName; - if (ImportedFile.empty()) // Use BaseDirectoryAsWritten to ensure we use the same path in the // ModuleCache as when writing. ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx); - else + } else SkipPath(Record, Idx); // If our client can't cope with us being out of date, we can't cope with @@ -2938,6 +2990,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, BaseDirectoryAsWritten = Blob; assert(!F.ModuleName.empty() && "MODULE_DIRECTORY found before MODULE_NAME"); + F.BaseDirectory = std::string(Blob); + if (!PP.getPreprocessorOpts().ModulesCheckRelocated) + break; // If we've already loaded a module map file covering this module, we may // have a better path for it (relative to the current build). Module *M = PP.getHeaderSearchInfo().lookupModule( @@ -2959,8 +3014,6 @@ ASTReader::ReadControlBlock(ModuleFile &F, } } F.BaseDirectory = std::string(M->Directory->getName()); - } else { - F.BaseDirectory = std::string(Blob); } break; } @@ -2984,22 +3037,6 @@ ASTReader::ReadControlBlock(ModuleFile &F, } } -void ASTReader::readIncludedFiles(ModuleFile &F, StringRef Blob, - Preprocessor &PP) { - using namespace llvm::support; - - const unsigned char *D = (const unsigned char *)Blob.data(); - unsigned FileCount = endian::readNext<uint32_t, little, unaligned>(D); - - for (unsigned I = 0; I < FileCount; ++I) { - size_t ID = endian::readNext<uint32_t, little, unaligned>(D); - InputFileInfo IFI = getInputFileInfo(F, ID); - if (llvm::ErrorOr<const FileEntry *> File = - PP.getFileManager().getFile(IFI.Filename)) - PP.getIncludedFiles().insert(*File); - } -} - llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { BitstreamCursor &Stream = F.Stream; @@ -3718,7 +3755,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, unsigned GlobalID = getGlobalSubmoduleID(F, Record[I++]); SourceLocation Loc = ReadSourceLocation(F, Record, I); if (GlobalID) { - ImportedModules.push_back(ImportedSubmodule(GlobalID, Loc)); + PendingImportedModules.push_back(ImportedSubmodule(GlobalID, Loc)); if (DeserializationListener) DeserializationListener->ModuleImportRead(GlobalID, Loc); } @@ -3751,10 +3788,6 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; } - case PP_INCLUDED_FILES: - readIncludedFiles(F, Blob, PP); - break; - case LATE_PARSED_TEMPLATE: LateParsedTemplates.emplace_back( std::piecewise_construct, std::forward_as_tuple(&F), @@ -3958,7 +3991,8 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, // usable header search context. assert(!F.ModuleName.empty() && "MODULE_NAME should come before MODULE_MAP_FILE"); - if (F.Kind == MK_ImplicitModule && ModuleMgr.begin()->Kind != MK_MainFile) { + if (PP.getPreprocessorOpts().ModulesCheckRelocated && + F.Kind == MK_ImplicitModule && ModuleMgr.begin()->Kind != MK_MainFile) { // An implicitly-loaded module file should have its module listed in some // module map file that we've already loaded. Module *M = @@ -4124,7 +4158,7 @@ void ASTReader::makeModuleVisible(Module *Mod, auto HiddenNames = std::move(*Hidden); HiddenNamesMap.erase(Hidden); makeNamesVisible(HiddenNames.second, HiddenNames.first); - assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() && + assert(!HiddenNamesMap.contains(Mod) && "making names visible added hidden names"); } @@ -4342,27 +4376,56 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, if (F.OriginalSourceFileID.isValid()) F.OriginalSourceFileID = TranslateFileID(F, F.OriginalSourceFileID); - // Preload all the pending interesting identifiers by marking them out of - // date. for (auto Offset : F.PreloadIdentifierOffsets) { const unsigned char *Data = F.IdentifierTableData + Offset; ASTIdentifierLookupTrait Trait(*this, F); auto KeyDataLen = Trait.ReadKeyDataLength(Data); auto Key = Trait.ReadKey(Data, KeyDataLen.first); - auto &II = PP.getIdentifierTable().getOwn(Key); - II.setOutOfDate(true); + + IdentifierInfo *II; + if (!PP.getLangOpts().CPlusPlus) { + // Identifiers present in both the module file and the importing + // instance are marked out-of-date so that they can be deserialized + // on next use via ASTReader::updateOutOfDateIdentifier(). + // Identifiers present in the module file but not in the importing + // instance are ignored for now, preventing growth of the identifier + // table. They will be deserialized on first use via ASTReader::get(). + auto It = PP.getIdentifierTable().find(Key); + if (It == PP.getIdentifierTable().end()) + continue; + II = It->second; + } else { + // With C++ modules, not many identifiers are considered interesting. + // All identifiers in the module file can be placed into the identifier + // table of the importing instance and marked as out-of-date. This makes + // ASTReader::get() a no-op, and deserialization will take place on + // first/next use via ASTReader::updateOutOfDateIdentifier(). + II = &PP.getIdentifierTable().getOwn(Key); + } + + II->setOutOfDate(true); // Mark this identifier as being from an AST file so that we can track // whether we need to serialize it. - markIdentifierFromAST(*this, II); + markIdentifierFromAST(*this, *II); // Associate the ID with the identifier so that the writer can reuse it. auto ID = Trait.ReadIdentifierID(Data + KeyDataLen.first); - SetIdentifierInfo(ID, &II); + SetIdentifierInfo(ID, II); } } + // Builtins and library builtins have already been initialized. Mark all + // identifiers as out-of-date, so that they are deserialized on first use. + if (Type == MK_PCH || Type == MK_Preamble || Type == MK_MainFile) + for (auto &Id : PP.getIdentifierTable()) + Id.second->setOutOfDate(true); + + // Mark selectors as out of date. + for (const auto &Sel : SelectorGeneration) + SelectorOutOfDate[Sel.first] = true; + // Setup the import locations and notify the module manager that we've // committed to these module files. for (ImportedModule &M : Loaded) { @@ -4380,25 +4443,6 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, F.ImportLoc = TranslateSourceLocation(*M.ImportedBy, M.ImportLoc); } - if (!PP.getLangOpts().CPlusPlus || - (Type != MK_ImplicitModule && Type != MK_ExplicitModule && - Type != MK_PrebuiltModule)) { - // Mark all of the identifiers in the identifier table as being out of date, - // so that various accessors know to check the loaded modules when the - // identifier is used. - // - // For C++ modules, we don't need information on many identifiers (just - // those that provide macros or are poisoned), so we mark all of - // the interesting ones via PreloadIdentifierOffsets. - for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(), - IdEnd = PP.getIdentifierTable().end(); - Id != IdEnd; ++Id) - Id->second->setOutOfDate(true); - } - // Mark selectors as out of date. - for (auto Sel : SelectorGeneration) - SelectorOutOfDate[Sel.first] = true; - // Resolve any unresolved module exports. for (unsigned I = 0, N = UnresolvedModuleRefs.size(); I != N; ++I) { UnresolvedModuleRef &Unresolved = UnresolvedModuleRefs[I]; @@ -4435,8 +4479,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, UnresolvedModuleRefs.clear(); if (Imported) - Imported->append(ImportedModules.begin(), - ImportedModules.end()); + Imported->append(PendingImportedModules.begin(), + PendingImportedModules.end()); // FIXME: How do we load the 'use'd modules? They may not be submodules. // Might be unnecessary as use declarations are only used to build the @@ -4473,18 +4517,16 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, } } - if (PP.getHeaderSearchInfo() - .getHeaderSearchOpts() - .ModulesValidateOncePerBuildSession) { + HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); + if (HSOpts.ModulesValidateOncePerBuildSession) { // Now we are certain that the module and all modules it depends on are - // up to date. Create or update timestamp files for modules that are - // located in the module cache (not for PCH files that could be anywhere - // in the filesystem). + // up-to-date. For implicitly-built module files, ensure the corresponding + // timestamp files are up-to-date in this build session. for (unsigned I = 0, N = Loaded.size(); I != N; ++I) { ImportedModule &M = Loaded[I]; - if (M.Mod->Kind == MK_ImplicitModule) { + if (M.Mod->Kind == MK_ImplicitModule && + M.Mod->InputFilesValidationTimestamp < HSOpts.BuildSessionTimestamp) updateModuleTimestamp(*M.Mod); - } } } @@ -5040,7 +5082,7 @@ 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. - for (auto &Import : ImportedModules) { + for (auto &Import : PendingImportedModules) { if (Module *Imported = getSubmodule(Import.ID)) { makeModuleVisible(Imported, Module::AllVisible, /*ImportLoc=*/Import.ImportLoc); @@ -5050,6 +5092,10 @@ void ASTReader::InitializeContext() { // nullptr here, we do the same later, in UpdateSema(). } } + + // Hand off these modules to Sema. + PendingImportedModulesSema.append(PendingImportedModules); + PendingImportedModules.clear(); } void ASTReader::finalizeForWriting() { @@ -5409,9 +5455,9 @@ bool ASTReader::readASTFileControlBlock( unsigned Idx = 0, N = Record.size(); while (Idx < N) { // Read information about the AST file. - Idx += - 1 + 1 + 1 + 1 + - ASTFileSignature::size; // Kind, ImportLoc, Size, ModTime, Signature + + // Kind, StandardCXXModule, ImportLoc, Size, ModTime, Signature + Idx += 1 + 1 + 1 + 1 + 1 + ASTFileSignature::size; std::string ModuleName = ReadString(Record, Idx); std::string Filename = ReadString(Record, Idx); ResolveImportedPath(Filename, ModuleDir); @@ -5563,7 +5609,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, break; case SUBMODULE_DEFINITION: { - if (Record.size() < 12) + if (Record.size() < 13) return llvm::createStringError(std::errc::illegal_byte_sequence, "malformed module definition"); @@ -5572,6 +5618,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]); SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]); Module::ModuleKind Kind = (Module::ModuleKind)Record[Idx++]; + SourceLocation DefinitionLoc = ReadSourceLocation(F, Record[Idx++]); bool IsFramework = Record[Idx++]; bool IsExplicit = Record[Idx++]; bool IsSystem = Record[Idx++]; @@ -5592,8 +5639,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit) .first; - // FIXME: set the definition loc for CurrentModule, or call - // ModMap.setInferredModuleAllowedBy() + // FIXME: Call ModMap.setInferredModuleAllowedBy() SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; if (GlobalIndex >= SubmodulesLoaded.size() || @@ -5622,6 +5668,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, } CurrentModule->Kind = Kind; + CurrentModule->DefinitionLoc = DefinitionLoc; CurrentModule->Signature = F.Signature; CurrentModule->IsFromModuleFile = true; CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; @@ -5634,6 +5681,12 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, if (DeserializationListener) DeserializationListener->ModuleRead(GlobalID, CurrentModule); + // If we're loading a module before we initialize the sema, it implies + // we're performing eagerly loading. + if (!getSema() && CurrentModule->isModulePurview() && + !getContext().getLangOpts().isCompilingModule()) + Diag(clang::diag::warn_eagerly_load_for_standard_cplusplus_modules); + SubmodulesLoaded[GlobalIndex] = CurrentModule; // Clear out data that will be replaced by what is in the module file. @@ -5662,9 +5715,9 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, std::string Filename = std::string(Blob); ResolveImportedPath(F, Filename); if (auto Umbrella = PP.getFileManager().getOptionalFileRef(Filename)) { - if (!CurrentModule->getUmbrellaHeader()) { + if (!CurrentModule->getUmbrellaHeaderAsWritten()) { // FIXME: NameAsWritten - ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob, ""); + ModMap.setUmbrellaHeaderAsWritten(CurrentModule, *Umbrella, Blob, ""); } // Note that it's too late at this point to return out of date if the // name from the PCM doesn't match up with the one in the module map, @@ -5699,10 +5752,11 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, // See comments in SUBMODULE_UMBRELLA_HEADER std::string Dirname = std::string(Blob); ResolveImportedPath(F, Dirname); - if (auto Umbrella = PP.getFileManager().getDirectory(Dirname)) { - if (!CurrentModule->getUmbrellaDir()) { + if (auto Umbrella = + PP.getFileManager().getOptionalDirectoryRef(Dirname)) { + if (!CurrentModule->getUmbrellaDirAsWritten()) { // FIXME: NameAsWritten - ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob, ""); + ModMap.setUmbrellaDirAsWritten(CurrentModule, *Umbrella, Blob, ""); } } break; @@ -6930,6 +6984,10 @@ QualType ASTReader::GetType(TypeID ID) { if (Index < NUM_PREDEF_TYPE_IDS) { QualType T; switch ((PredefinedTypeIDs)Index) { + case PREDEF_TYPE_LAST_ID: + // We should never use this one. + llvm_unreachable("Invalid predefined type"); + break; case PREDEF_TYPE_NULL_ID: return QualType(); case PREDEF_TYPE_VOID_ID: @@ -7178,6 +7236,11 @@ QualType ASTReader::GetType(TypeID ID) { T = Context.SingletonId; \ break; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case PREDEF_TYPE_##Id##_ID: \ + T = Context.SingletonId; \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" } assert(!T.isNull() && "Unknown predefined type"); @@ -7346,6 +7409,7 @@ ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) { return nullptr; } ReadingKindTracker ReadingKind(Read_Decl, *this); + Deserializing D(this); Expected<unsigned> MaybeCode = Cursor.ReadCode(); if (!MaybeCode) { @@ -7380,6 +7444,7 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { return nullptr; } ReadingKindTracker ReadingKind(Read_Decl, *this); + Deserializing D(this); Expected<unsigned> MaybeCode = Cursor.ReadCode(); if (!MaybeCode) { @@ -7647,7 +7712,7 @@ void ASTReader::FindExternalLexicalDecls( }; if (isa<TranslationUnitDecl>(DC)) { - for (auto Lexical : TULexicalDecls) + for (const auto &Lexical : TULexicalDecls) Visit(Lexical.first, Lexical.second); } else { auto I = LexicalDecls.find(DC); @@ -8082,13 +8147,14 @@ void ASTReader::UpdateSema() { } // For non-modular AST files, restore visiblity of modules. - for (auto &Import : ImportedModules) { + for (auto &Import : PendingImportedModulesSema) { if (Import.ImportLoc.isInvalid()) continue; if (Module *Imported = getSubmodule(Import.ID)) { SemaObj->makeModuleVisible(Imported, Import.ImportLoc); } } + PendingImportedModulesSema.clear(); } IdentifierInfo *ASTReader::get(StringRef Name) { @@ -8531,6 +8597,7 @@ void ASTReader::ReadLateParsedTemplates( auto LT = std::make_unique<LateParsedTemplate>(); LT->D = GetLocalDecl(*FMod, LateParsed[Idx++]); + LT->FPO = FPOptions::getFromOpaqueInt(LateParsed[Idx++]); ModuleFile *F = getOwningModuleFile(LT->D); assert(F && "No module"); @@ -8547,6 +8614,17 @@ void ASTReader::ReadLateParsedTemplates( LateParsedTemplates.clear(); } +void ASTReader::AssignedLambdaNumbering(const CXXRecordDecl *Lambda) { + if (Lambda->getLambdaContextDecl()) { + // Keep track of this lambda so it can be merged with another lambda that + // is loaded later. + LambdaDeclarationsForMerging.insert( + {{Lambda->getLambdaContextDecl()->getCanonicalDecl(), + Lambda->getLambdaIndexInContext()}, + const_cast<CXXRecordDecl *>(Lambda)}); + } +} + void ASTReader::LoadSelector(Selector Sel) { // It would be complicated to avoid reading the methods anyway. So don't. ReadMethodPool(Sel); @@ -9084,7 +9162,7 @@ llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) { } // Read a string -std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) { +std::string ASTReader::ReadString(const RecordDataImpl &Record, unsigned &Idx) { unsigned Len = Record[Idx++]; std::string Result(Record.data() + Idx, Record.data() + Idx + Len); Idx += Len; @@ -9257,11 +9335,12 @@ void ASTReader::visitTopLevelModuleMaps( } void ASTReader::finishPendingActions() { - while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() || - !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || - !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || - !PendingUpdateRecords.empty() || - !PendingObjCExtensionIvarRedeclarations.empty()) { + while ( + !PendingIdentifierInfos.empty() || !PendingDeducedFunctionTypes.empty() || + !PendingDeducedVarTypes.empty() || !PendingIncompleteDeclChains.empty() || + !PendingDeclChains.empty() || !PendingMacroIDs.empty() || + !PendingDeclContextInfos.empty() || !PendingUpdateRecords.empty() || + !PendingObjCExtensionIvarRedeclarations.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. using TopLevelDeclsMap = @@ -9279,9 +9358,9 @@ void ASTReader::finishPendingActions() { // Load each function type that we deferred loading because it was a // deduced type that might refer to a local type declared within itself. - for (unsigned I = 0; I != PendingFunctionTypes.size(); ++I) { - auto *FD = PendingFunctionTypes[I].first; - FD->setType(GetType(PendingFunctionTypes[I].second)); + for (unsigned I = 0; I != PendingDeducedFunctionTypes.size(); ++I) { + auto *FD = PendingDeducedFunctionTypes[I].first; + FD->setType(GetType(PendingDeducedFunctionTypes[I].second)); // If we gave a function a deduced return type, remember that we need to // propagate that along the redeclaration chain. @@ -9290,7 +9369,15 @@ void ASTReader::finishPendingActions() { PendingDeducedTypeUpdates.insert( {FD->getCanonicalDecl(), FD->getReturnType()}); } - PendingFunctionTypes.clear(); + PendingDeducedFunctionTypes.clear(); + + // Load each variable type that we deferred loading because it was a + // deduced type that might refer to a local type declared within itself. + for (unsigned I = 0; I != PendingDeducedVarTypes.size(); ++I) { + auto *VD = PendingDeducedVarTypes[I].first; + VD->setType(GetType(PendingDeducedVarTypes[I].second)); + } + PendingDeducedVarTypes.clear(); // For each decl chain that we wanted to complete while deserializing, mark // it as "still needs to be completed". @@ -9466,7 +9553,6 @@ void ASTReader::finishPendingActions() { continue; // FIXME: Check for =delete/=default? - // FIXME: Complain about ODR violations here? const FunctionDecl *Defn = nullptr; if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) { FD->setLazyBody(PB->second); @@ -9497,6 +9583,12 @@ void ASTReader::finishPendingActions() { } PendingBodies.clear(); + // Inform any classes that had members added that they now have more members. + for (auto [RD, MD] : PendingAddedClassMembers) { + RD->addedMember(MD); + } + PendingAddedClassMembers.clear(); + // Do some cleanup. for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); @@ -9673,9 +9765,6 @@ void ASTReader::diagnoseOdrViolations() { ObjCProtocolOdrMergeFailures.empty()) return; - // Ensure we don't accidentally recursively enter deserialization while - // we're producing our diagnostics. - Deserializing RecursionGuard(this); ODRDiagsEmitter DiagsEmitter(Diags, getContext(), getPreprocessor().getLangOpts()); @@ -10275,6 +10364,12 @@ OMPClause *OMPClauseReader::readClause() { case llvm::omp::OMPC_ompx_dyn_cgroup_mem: C = new (Context) OMPXDynCGroupMemClause(); break; + case llvm::omp::OMPC_doacross: { + unsigned NumVars = Record.readInt(); + unsigned NumLoops = Record.readInt(); + C = OMPDoacrossClause::CreateEmpty(Context, NumVars, NumLoops); + break; + } #define OMP_CLAUSE_NO_CLASS(Enum, Str) \ case llvm::omp::Enum: \ break; @@ -11351,6 +11446,22 @@ void OMPClauseReader::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) { C->setLParenLoc(Record.readSourceLocation()); } +void OMPClauseReader::VisitOMPDoacrossClause(OMPDoacrossClause *C) { + C->setLParenLoc(Record.readSourceLocation()); + C->setDependenceType( + static_cast<OpenMPDoacrossClauseModifier>(Record.readInt())); + C->setDependenceLoc(Record.readSourceLocation()); + C->setColonLoc(Record.readSourceLocation()); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned I = 0; I != NumVars; ++I) + Vars.push_back(Record.readSubExpr()); + C->setVarRefs(Vars); + for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) + C->setLoopData(I, Record.readSubExpr()); +} + OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() { OMPTraitInfo &TI = getContext().getNewOMPTraitInfo(); TI.Sets.resize(readUInt32()); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 8cb513eff13e..10c92f8d2149 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -14,6 +14,7 @@ #include "ASTCommon.h" #include "ASTReaderInternals.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/Attr.h" #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" @@ -88,7 +89,7 @@ namespace clang { using RecordData = ASTReader::RecordData; TypeID DeferredTypeID = 0; - unsigned AnonymousDeclNumber; + unsigned AnonymousDeclNumber = 0; GlobalDeclID NamedDeclForTagDecl = 0; IdentifierInfo *TypedefNameForLinkage = nullptr; @@ -157,9 +158,12 @@ namespace clang { return Record.getSubmodule(readSubmoduleID()); } - void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update); + void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update, + Decl *LambdaContext = nullptr, + unsigned IndexInLambdaContext = 0); void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, - const CXXRecordDecl *D); + const CXXRecordDecl *D, Decl *LambdaContext, + unsigned IndexInLambdaContext); void MergeDefinitionData(CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&NewDD); void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data); @@ -376,6 +380,7 @@ namespace clang { void VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D); void VisitIndirectFieldDecl(IndirectFieldDecl *FD); RedeclarableResult VisitVarDeclImpl(VarDecl *D); + void ReadVarDeclInit(VarDecl *VD); void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); } void VisitImplicitParamDecl(ImplicitParamDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD); @@ -421,6 +426,9 @@ namespace clang { template <typename T> void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl); + void mergeLambda(CXXRecordDecl *D, RedeclarableResult &Redecl, + Decl *Context, unsigned Number); + void mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, RedeclarableResult &Redecl); @@ -468,9 +476,8 @@ namespace { /// Iterator over the redeclarations of a declaration that have already /// been merged into the same redeclaration chain. -template<typename DeclT> -class MergedRedeclIterator { - DeclT *Start; +template <typename DeclT> class MergedRedeclIterator { + DeclT *Start = nullptr; DeclT *Canonical = nullptr; DeclT *Current = nullptr; @@ -558,11 +565,14 @@ void ASTDeclReader::Visit(Decl *D) { ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull(); } else if (auto *FD = dyn_cast<FunctionDecl>(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: Can we diagnose ODR violations somehow? if (Record.readInt()) ReadFunctionDefinition(FD); + } else if (auto *VD = dyn_cast<VarDecl>(D)) { + ReadVarDeclInit(VD); + } else if (auto *FD = dyn_cast<FieldDecl>(D)) { + if (FD->hasInClassInitializer() && Record.readInt()) { + FD->setLazyInClassInitializer(LazyDeclStmtPtr(GetCurrentCursorOffset())); + } } } @@ -860,10 +870,10 @@ void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); - // For function declarations, defer reading the type in case the function has - // a deduced return type that references an entity declared within the - // function. - if (isa<FunctionDecl>(VD)) + // For function or variable declarations, defer reading the type in case the + // declaration has a deduced type that references an entity declared within + // the function definition or variable initializer. + if (isa<FunctionDecl, VarDecl>(VD)) DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); else VD->setType(Record.readType()); @@ -1025,7 +1035,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { // We'll set up the real type in Visit, once we've finished loading the // function. FD->setType(FD->getTypeSourceInfo()->getType()); - Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID}); + Reader.PendingDeducedFunctionTypes.push_back({FD, DeferredTypeID}); } else { FD->setType(Reader.GetType(DeferredTypeID)); } @@ -1491,15 +1501,13 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { VisitDeclaratorDecl(FD); FD->Mutable = Record.readInt(); - if (auto ISK = static_cast<FieldDecl::InitStorageKind>(Record.readInt())) { - FD->InitStorage.setInt(ISK); - FD->InitStorage.setPointer(ISK == FieldDecl::ISK_CapturedVLAType - ? Record.readType().getAsOpaquePtr() - : Record.readExpr()); - } - - if (auto *BW = Record.readExpr()) - FD->setBitWidth(BW); + unsigned Bits = Record.readInt(); + FD->StorageKind = Bits >> 1; + if (FD->StorageKind == FieldDecl::ISK_CapturedVLAType) + FD->CapturedVLAType = + cast<VariableArrayType>(Record.readType().getTypePtr()); + else if (Bits & 1) + FD->setBitWidth(Record.readExpr()); if (!FD->getDeclName()) { if (auto *Tmpl = readDeclAs<FieldDecl>()) @@ -1570,6 +1578,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->VarDeclBits.TSCSpec = Record.readInt(); VD->VarDeclBits.InitStyle = Record.readInt(); VD->VarDeclBits.ARCPseudoStrong = Record.readInt(); + bool HasDeducedType = false; if (!isa<ParmVarDecl>(VD)) { VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = Record.readInt(); @@ -1584,7 +1593,18 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt(); VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt(); VD->NonParmVarDeclBits.EscapingByref = Record.readInt(); + HasDeducedType = Record.readInt(); } + + // If this variable has a deduced type, defer reading that type until we are + // done deserializing this variable, because the type might refer back to the + // variable. + if (HasDeducedType) + Reader.PendingDeducedVarTypes.push_back({VD, DeferredTypeID}); + else + VD->setType(Reader.GetType(DeferredTypeID)); + DeferredTypeID = 0; + auto VarLinkage = Linkage(Record.readInt()); VD->setCachedLinkage(VarLinkage); @@ -1593,22 +1613,13 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->getLexicalDeclContext()->isFunctionOrMethod()) VD->setLocalExternDecl(); - if (uint64_t Val = Record.readInt()) { - VD->setInit(Record.readExpr()); - if (Val != 1) { - EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); - Eval->HasConstantInitialization = (Val & 2) != 0; - Eval->HasConstantDestruction = (Val & 4) != 0; - } - } - - if (VD->hasAttr<BlocksAttr>() && VD->getType()->getAsCXXRecordDecl()) { + if (VD->hasAttr<BlocksAttr>()) { Expr *CopyExpr = Record.readExpr(); if (CopyExpr) Reader.getContext().setBlockVarCopyInit(VD, CopyExpr, Record.readInt()); } - if (VD->getStorageDuration() == SD_Static && Record.readInt()) { + if (Record.readInt()) { Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile || Reader.getContext().getLangOpts().BuildingPCHWithObjectFile; @@ -1642,6 +1653,25 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { return Redecl; } +void ASTDeclReader::ReadVarDeclInit(VarDecl *VD) { + if (uint64_t Val = Record.readInt()) { + EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); + Eval->HasConstantInitialization = (Val & 2) != 0; + Eval->HasConstantDestruction = (Val & 4) != 0; + Eval->WasEvaluated = (Val & 8) != 0; + if (Eval->WasEvaluated) { + Eval->Evaluated = Record.readAPValue(); + if (Eval->Evaluated.needsCleanup()) + Reader.getContext().addDestruction(&Eval->Evaluated); + } + + // Store the offset of the initializer. Don't deserialize it yet: it might + // not be needed, and might refer back to the variable, for example if it + // contains a lambda. + Eval->Value = GetCurrentCursorOffset(); + } +} + void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { VisitVarDecl(PD); } @@ -1893,10 +1923,10 @@ void ASTDeclReader::VisitUnresolvedUsingIfExistsDecl( } void ASTDeclReader::ReadCXXDefinitionData( - struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) { - #define FIELD(Name, Width, Merge) \ - Data.Name = Record.readInt(); - #include "clang/AST/CXXRecordDeclDefinitionBits.def" + struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D, + Decl *LambdaContext, unsigned IndexInLambdaContext) { +#define FIELD(Name, Width, Merge) Data.Name = Record.readInt(); +#include "clang/AST/CXXRecordDeclDefinitionBits.def" // Note: the caller has deserialized the IsLambda bit already. Data.ODRHash = Record.readInt(); @@ -1908,21 +1938,26 @@ void ASTDeclReader::ReadCXXDefinitionData( Reader.getContext().getLangOpts().BuildingPCHWithObjectFile; } - Data.NumBases = Record.readInt(); - if (Data.NumBases) - Data.Bases = ReadGlobalOffset(); - Data.NumVBases = Record.readInt(); - if (Data.NumVBases) - Data.VBases = ReadGlobalOffset(); - Record.readUnresolvedSet(Data.Conversions); Data.ComputedVisibleConversions = Record.readInt(); if (Data.ComputedVisibleConversions) Record.readUnresolvedSet(Data.VisibleConversions); assert(Data.Definition && "Data.Definition should be already set!"); - Data.FirstFriend = readDeclID(); - if (Data.IsLambda) { + if (!Data.IsLambda) { + assert(!LambdaContext && !IndexInLambdaContext && + "given lambda context for non-lambda"); + + Data.NumBases = Record.readInt(); + if (Data.NumBases) + Data.Bases = ReadGlobalOffset(); + + Data.NumVBases = Record.readInt(); + if (Data.NumVBases) + Data.VBases = ReadGlobalOffset(); + + Data.FirstFriend = readDeclID(); + } else { using Capture = LambdaCapture; auto &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); @@ -1933,8 +1968,10 @@ void ASTDeclReader::ReadCXXDefinitionData( Lambda.NumExplicitCaptures = Record.readInt(); Lambda.HasKnownInternalLinkage = Record.readInt(); Lambda.ManglingNumber = Record.readInt(); - D->setDeviceLambdaManglingNumber(Record.readInt()); - Lambda.ContextDecl = readDeclID(); + if (unsigned DeviceManglingNumber = Record.readInt()) + Reader.getContext().DeviceLambdaManglingNumbers[D] = DeviceManglingNumber; + Lambda.IndexInContext = IndexInLambdaContext; + Lambda.ContextDecl = LambdaContext; Capture *ToCapture = nullptr; if (Lambda.NumCaptures) { ToCapture = (Capture *)Reader.getContext().Allocate(sizeof(Capture) * @@ -1976,7 +2013,7 @@ void ASTDeclReader::MergeDefinitionData( Reader.PendingDefinitions.erase(MergeDD.Definition); MergeDD.Definition->setCompleteDefinition(false); Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition); - assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() && + assert(!Reader.Lookups.contains(MergeDD.Definition) && "already loaded pending lookups for merged definition"); } @@ -2055,13 +2092,17 @@ void ASTDeclReader::MergeDefinitionData( {MergeDD.Definition, &MergeDD}); } -void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { +void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update, + Decl *LambdaContext, + unsigned IndexInLambdaContext) { struct CXXRecordDecl::DefinitionData *DD; ASTContext &C = Reader.getContext(); // Determine whether this is a lambda closure type, so that we can // allocate the appropriate DefinitionData structure. bool IsLambda = Record.readInt(); + assert(!(IsLambda && Update) && + "lambda definition should not be added by update record"); if (IsLambda) DD = new (C) CXXRecordDecl::LambdaDefinitionData( D, nullptr, CXXRecordDecl::LDK_Unknown, false, LCD_None); @@ -2075,7 +2116,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { if (!Canon->DefinitionData) Canon->DefinitionData = DD; D->DefinitionData = Canon->DefinitionData; - ReadCXXDefinitionData(*DD, D); + ReadCXXDefinitionData(*DD, D, LambdaContext, IndexInLambdaContext); // We might already have a different definition for this record. This can // happen either because we're reading an update record, or because we've @@ -2102,8 +2143,15 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { ASTContext &C = Reader.getContext(); enum CXXRecKind { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization + CXXRecNotTemplate = 0, + CXXRecTemplate, + CXXRecMemberSpecialization, + CXXLambda }; + + Decl *LambdaContext = nullptr; + unsigned IndexInLambdaContext = 0; + switch ((CXXRecKind)Record.readInt()) { case CXXRecNotTemplate: // Merged when we merge the folding set entry in the primary template. @@ -2135,11 +2183,19 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { mergeRedeclarable(D, Redecl); break; } + case CXXLambda: { + LambdaContext = readDecl(); + if (LambdaContext) + IndexInLambdaContext = Record.readInt(); + mergeLambda(D, Redecl, LambdaContext, IndexInLambdaContext); + break; + } } bool WasDefinition = Record.readInt(); if (WasDefinition) - ReadCXXRecordDefinition(D, /*Update*/false); + ReadCXXRecordDefinition(D, /*Update=*/false, LambdaContext, + IndexInLambdaContext); else // Propagate DefinitionData pointer from the canonical declaration. D->DefinitionData = D->getCanonicalDecl()->DefinitionData; @@ -2162,7 +2218,8 @@ void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { D->setExplicitSpecifier(Record.readExplicitSpec()); D->Ctor = readDeclAs<CXXConstructorDecl>(); VisitFunctionDecl(D); - D->setIsCopyDeductionCandidate(Record.readInt()); + D->setDeductionCandidateKind( + static_cast<DeductionCandidate>(Record.readInt())); } void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { @@ -2741,6 +2798,41 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, mergeRedeclarable(D, Existing, Redecl); } +/// Attempt to merge D with a previous declaration of the same lambda, which is +/// found by its index within its context declaration, if it has one. +/// +/// We can't look up lambdas in their enclosing lexical or semantic context in +/// general, because for lambdas in variables, both of those might be a +/// namespace or the translation unit. +void ASTDeclReader::mergeLambda(CXXRecordDecl *D, RedeclarableResult &Redecl, + Decl *Context, unsigned IndexInContext) { + // If we don't have a mangling context, treat this like any other + // declaration. + if (!Context) + return mergeRedeclarable(D, Redecl); + + // If modules are not available, there is no reason to perform this merge. + if (!Reader.getContext().getLangOpts().Modules) + return; + + // If we're not the canonical declaration, we don't need to merge. + if (!D->isFirstDecl()) + return; + + if (auto *Existing = Redecl.getKnownMergeTarget()) + // We already know of an existing declaration we should merge with. + mergeRedeclarable(D, cast<TagDecl>(Existing), Redecl); + + // Look up this lambda to see if we've seen it before. If so, merge with the + // one we already loaded. + NamedDecl *&Slot = Reader.LambdaDeclarationsForMerging[{ + Context->getCanonicalDecl(), IndexInContext}]; + if (Slot) + mergeRedeclarable(D, cast<TagDecl>(Slot), Redecl); + else + Slot = D; +} + void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, RedeclarableResult &Redecl) { mergeRedeclarable(D, Redecl); @@ -3006,10 +3098,15 @@ Attr *ASTRecordReader::readAttr() { unsigned ParsedKind = Record.readInt(); unsigned Syntax = Record.readInt(); unsigned SpellingIndex = Record.readInt(); + bool IsAlignas = (ParsedKind == AttributeCommonInfo::AT_Aligned && + Syntax == AttributeCommonInfo::AS_Keyword && + SpellingIndex == AlignedAttr::Keyword_alignas); + bool IsRegularKeywordAttribute = Record.readBool(); AttributeCommonInfo Info(AttrName, ScopeName, AttrRange, ScopeLoc, AttributeCommonInfo::Kind(ParsedKind), - AttributeCommonInfo::Syntax(Syntax), SpellingIndex); + {AttributeCommonInfo::Syntax(Syntax), SpellingIndex, + IsAlignas, IsRegularKeywordAttribute}); #include "clang/Serialization/AttrPCHRead.inc" @@ -4181,23 +4278,22 @@ namespace { // Check for duplicate categories. if (Cat->getDeclName()) { ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()]; - if (Existing && - Reader.getOwningModuleFile(Existing) - != Reader.getOwningModuleFile(Cat)) { - // FIXME: We should not warn for duplicates in diamond: - // - // MT // - // / \ // - // ML MR // - // \ / // - // MB // - // - // If there are duplicates in ML/MR, there will be warning when - // creating MB *and* when importing MB. We should not warn when - // importing. - Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) - << Interface->getDeclName() << Cat->getDeclName(); - Reader.Diag(Existing->getLocation(), diag::note_previous_definition); + if (Existing && Reader.getOwningModuleFile(Existing) != + Reader.getOwningModuleFile(Cat)) { + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; + StructuralEquivalenceContext Ctx( + Cat->getASTContext(), Existing->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, + /*StrictTypeSpelling =*/false, + /*Complain =*/false, + /*ErrorOnTagTypeMismatch =*/true); + if (!Ctx.IsEquivalent(Cat, Existing)) { + // Warn only if the categories with the same name are different. + Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) + << Interface->getDeclName() << Cat->getDeclName(); + Reader.Diag(Existing->getLocation(), + diag::note_previous_definition); + } } else if (!Existing) { // Record this category. Existing = Cat; @@ -4306,13 +4402,9 @@ void ASTDeclReader::UpdateDecl(Decl *D, switch ((DeclUpdateKind)Record.readInt()) { 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 = Record.readDecl(); assert(MD && "couldn't read decl from update record"); - // FIXME: We should call addHiddenDecl instead, to add the member - // to its DeclContext. - RD->addedMember(MD); + Reader.PendingAddedClassMembers.push_back({RD, MD}); break; } @@ -4340,15 +4432,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, auto *VD = cast<VarDecl>(D); VD->NonParmVarDeclBits.IsInline = Record.readInt(); VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt(); - uint64_t Val = Record.readInt(); - if (Val && !VD->getInit()) { - VD->setInit(Record.readExpr()); - if (Val != 1) { - EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); - Eval->HasConstantInitialization = (Val & 2) != 0; - Eval->HasConstantDestruction = (Val & 4) != 0; - } - } + ReadVarDeclInit(VD); break; } @@ -4391,7 +4475,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, // Only apply the update if the field still has an uninstantiated // default member initializer. - if (FD->hasInClassInitializer() && !FD->getInClassInitializer()) { + if (FD->hasInClassInitializer() && !FD->hasNonNullInClassInitializer()) { if (DefaultInit) FD->setInClassInitializer(DefaultInit); else @@ -4545,9 +4629,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, break; case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: - D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( - Reader.getContext(), readSourceRange(), - AttributeCommonInfo::AS_Pragma)); + D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(), + readSourceRange())); break; case UPD_DECL_MARKED_OPENMP_ALLOCATE: { @@ -4557,8 +4640,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, Expr *Alignment = Record.readExpr(); SourceRange SR = readSourceRange(); D->addAttr(OMPAllocateDeclAttr::CreateImplicit( - Reader.getContext(), AllocatorKind, Allocator, Alignment, SR, - AttributeCommonInfo::AS_Pragma)); + Reader.getContext(), AllocatorKind, Allocator, Alignment, SR)); break; } @@ -4579,7 +4661,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, unsigned Level = Record.readInt(); D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit( Reader.getContext(), MapType, DevType, IndirectE, Indirect, Level, - readSourceRange(), AttributeCommonInfo::AS_Pragma)); + readSourceRange())); break; } diff --git a/clang/lib/Serialization/ASTReaderInternals.h b/clang/lib/Serialization/ASTReaderInternals.h index 4a4cfcce156d..b906cc6c58a2 100644 --- a/clang/lib/Serialization/ASTReaderInternals.h +++ b/clang/lib/Serialization/ASTReaderInternals.h @@ -276,6 +276,9 @@ public: static internal_key_type ReadKey(const unsigned char *d, unsigned); data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen); + +private: + const FileEntry *getFile(const internal_key_type &Key); }; /// The on-disk hash table used for known header files. diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 46d653c7f940..96307c35ad32 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -115,10 +115,6 @@ namespace clang { TemplateArgumentLoc *ArgsLocArray, unsigned NumTemplateArgs); - /// Read and initialize a ExplicitTemplateArgumentList structure. - void ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList, - unsigned NumTemplateArgs); - void VisitStmt(Stmt *S); #define STMT(Type, Base) \ void Visit##Type(Type *); @@ -228,7 +224,7 @@ void ASTStmtReader::VisitIfStmt(IfStmt *S) { if (HasElse) S->setElse(Record.readSubStmt()); if (HasVar) - S->setConditionVariable(Record.getContext(), readDeclAs<VarDecl>()); + S->setConditionVariableDeclStmt(cast<DeclStmt>(Record.readSubStmt())); if (HasInit) S->setInit(Record.readSubStmt()); @@ -253,7 +249,7 @@ void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) { if (HasInit) S->setInit(Record.readSubStmt()); if (HasVar) - S->setConditionVariable(Record.getContext(), readDeclAs<VarDecl>()); + S->setConditionVariableDeclStmt(cast<DeclStmt>(Record.readSubStmt())); S->setSwitchLoc(readSourceLocation()); S->setLParenLoc(readSourceLocation()); @@ -279,7 +275,7 @@ void ASTStmtReader::VisitWhileStmt(WhileStmt *S) { S->setCond(Record.readSubExpr()); S->setBody(Record.readSubStmt()); if (HasVar) - S->setConditionVariable(Record.getContext(), readDeclAs<VarDecl>()); + S->setConditionVariableDeclStmt(cast<DeclStmt>(Record.readSubStmt())); S->setWhileLoc(readSourceLocation()); S->setLParenLoc(readSourceLocation()); @@ -299,7 +295,7 @@ void ASTStmtReader::VisitForStmt(ForStmt *S) { VisitStmt(S); S->setInit(Record.readSubStmt()); S->setCond(Record.readSubExpr()); - S->setConditionVariable(Record.getContext(), readDeclAs<VarDecl>()); + S->setConditionVariableDeclStmt(cast_or_null<DeclStmt>(Record.readSubStmt())); S->setInc(Record.readSubExpr()); S->setBody(Record.readSubStmt()); S->setForLoc(readSourceLocation()); @@ -400,8 +396,10 @@ void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) { Clobbers.push_back(cast_or_null<StringLiteral>(Record.readSubStmt())); // Labels - for (unsigned I = 0, N = NumLabels; I != N; ++I) + for (unsigned I = 0, N = NumLabels; I != N; ++I) { + Names.push_back(Record.readIdentifier()); Exprs.push_back(Record.readSubStmt()); + } S->setOutputsAndInputsAndClobbers(Record.getContext(), Names.data(), Constraints.data(), @@ -582,6 +580,7 @@ void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { bool HasFunctionName = Record.readInt(); E->PredefinedExprBits.HasFunctionName = HasFunctionName; E->PredefinedExprBits.Kind = Record.readInt(); + E->PredefinedExprBits.IsTransparent = Record.readInt(); E->setLocation(readSourceLocation()); if (HasFunctionName) E->setFunctionName(cast<StringLiteral>(Record.readSubExpr())); @@ -596,6 +595,7 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { E->DeclRefExprBits.HadMultipleCandidates = Record.readInt(); E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt(); E->DeclRefExprBits.NonOdrUseReason = Record.readInt(); + E->DeclRefExprBits.IsImmediateEscalating = Record.readInt(); unsigned NumTemplateArgs = 0; if (E->hasTemplateKWAndArgsInfo()) NumTemplateArgs = Record.readInt(); @@ -1216,9 +1216,9 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { auto *Field = readDeclAs<FieldDecl>(); SourceLocation DotLoc = readSourceLocation(); SourceLocation FieldLoc = readSourceLocation(); - Designators.push_back(Designator(Field->getIdentifier(), DotLoc, - FieldLoc)); - Designators.back().setField(Field); + Designators.push_back(Designator::CreateFieldDesignator( + Field->getIdentifier(), DotLoc, FieldLoc)); + Designators.back().setFieldDecl(Field); break; } @@ -1226,7 +1226,8 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { const IdentifierInfo *Name = Record.readIdentifier(); SourceLocation DotLoc = readSourceLocation(); SourceLocation FieldLoc = readSourceLocation(); - Designators.push_back(Designator(Name, DotLoc, FieldLoc)); + Designators.push_back(Designator::CreateFieldDesignator(Name, DotLoc, + FieldLoc)); break; } @@ -1234,7 +1235,9 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { unsigned Index = Record.readInt(); SourceLocation LBracketLoc = readSourceLocation(); SourceLocation RBracketLoc = readSourceLocation(); - Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc)); + Designators.push_back(Designator::CreateArrayDesignator(Index, + LBracketLoc, + RBracketLoc)); break; } @@ -1243,8 +1246,8 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { SourceLocation LBracketLoc = readSourceLocation(); SourceLocation EllipsisLoc = readSourceLocation(); SourceLocation RBracketLoc = readSourceLocation(); - Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc, - RBracketLoc)); + Designators.push_back(Designator::CreateArrayRangeDesignator( + Index, LBracketLoc, EllipsisLoc, RBracketLoc)); break; } } @@ -1354,6 +1357,7 @@ void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { unsigned NumAssocs = Record.readInt(); assert(NumAssocs == E->getNumAssocs() && "Wrong NumAssocs!"); + E->IsExprPredicate = Record.readInt(); E->ResultIndex = Record.readInt(); E->GenericSelectionExprBits.GenericLoc = readSourceLocation(); E->DefaultLoc = readSourceLocation(); @@ -1700,6 +1704,7 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { E->CXXConstructExprBits.StdInitListInitialization = Record.readInt(); E->CXXConstructExprBits.ZeroInitialization = Record.readInt(); E->CXXConstructExprBits.ConstructionKind = Record.readInt(); + E->CXXConstructExprBits.IsImmediateEscalating = Record.readInt(); E->CXXConstructExprBits.Loc = readSourceLocation(); E->Constructor = readDeclAs<CXXConstructorDecl>(); E->ParenOrBraceRange = readSourceRange(); @@ -2003,9 +2008,10 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { Record.skipInts(1); for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) E->setArg(I, Record.readSubExpr()); - E->TSI = readTypeSourceInfo(); + E->TypeAndInitForm.setPointer(readTypeSourceInfo()); E->setLParenLoc(readSourceLocation()); E->setRParenLoc(readSourceLocation()); + E->TypeAndInitForm.setInt(Record.readInt()); } void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { @@ -2805,7 +2811,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case STMT_REF_PTR: IsStmtReference = true; - assert(StmtEntries.find(Record[0]) != StmtEntries.end() && + assert(StmtEntries.contains(Record[0]) && "No stmt was recorded for this offset reference!"); S = StmtEntries[Record.readInt()]; break; @@ -2929,12 +2935,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_DECL_REF: S = DeclRefExpr::CreateEmpty( - Context, - /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], - /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2], - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ? - Record[ASTStmtReader::NumExprFields + 6] : 0); + Context, + /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], + /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], + /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2], + /*NumTemplateArgs=*/ + Record[ASTStmtReader::NumExprFields + 2] + ? Record[ASTStmtReader::NumExprFields + 7] + : 0); break; case EXPR_INTEGER_LITERAL: @@ -3519,7 +3527,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { CollapsedNum, Empty); break; } - + case STMT_OMP_MASKED_TASKLOOP_DIRECTIVE: { unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields]; unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1]; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index bdf11001473e..26279d399b53 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -185,7 +185,7 @@ std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP, if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) continue; - for (const auto &KH : HS.findAllModulesForHeader(File)) { + for (const auto &KH : HS.findResolvedModulesForHeader(File)) { if (!KH.getModule()) continue; ModulesToProcess.push_back(KH.getModule()); @@ -200,7 +200,9 @@ std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP, CB(F); FileID FID = SourceMgr.translateFile(F); SourceLocation Loc = SourceMgr.getIncludeLoc(FID); - while (Loc.isValid()) { + // The include location of inferred module maps can point into the header + // file that triggered the inferring. Cut off the walk if that's the case. + while (Loc.isValid() && isModuleMap(SourceMgr.getFileCharacteristic(Loc))) { FID = SourceMgr.getFileID(Loc); CB(*SourceMgr.getFileEntryRefForID(FID)); Loc = SourceMgr.getIncludeLoc(FID); @@ -209,11 +211,18 @@ std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP, auto ProcessModuleOnce = [&](const Module *M) { for (const Module *Mod = M; Mod; Mod = Mod->Parent) - if (ProcessedModules.insert(Mod).second) + if (ProcessedModules.insert(Mod).second) { + auto Insert = [&](FileEntryRef F) { ModuleMaps.insert(F); }; + // The containing module map is affecting, because it's being pointed + // into by Module::DefinitionLoc. + if (auto ModuleMapFile = MM.getContainingModuleMapFile(Mod)) + ForIncludeChain(*ModuleMapFile, Insert); + // For inferred modules, the module map that allowed inferring is not in + // the include chain of the virtual containing module map file. It did + // affect the compilation, though. if (auto ModuleMapFile = MM.getModuleMapFileForUniquing(Mod)) - ForIncludeChain(*ModuleMapFile, [&](FileEntryRef F) { - ModuleMaps.insert(F); - }); + ForIncludeChain(*ModuleMapFile, Insert); + } }; for (const Module *CurrentModule : ModulesToProcess) { @@ -866,7 +875,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH); RECORD(PP_CONDITIONAL_STACK); RECORD(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS); - RECORD(PP_INCLUDED_FILES); RECORD(PP_ASSUME_NONNULL_LOC); // SourceManager Block. @@ -1243,6 +1251,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj. MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min. MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable + // Standard C++ module + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag @@ -1250,15 +1260,15 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, assert((!WritingModule || isysroot.empty()) && "writing module as a relocatable PCH?"); { - RecordData::value_type Record[] = { - METADATA, - VERSION_MAJOR, - VERSION_MINOR, - CLANG_VERSION_MAJOR, - CLANG_VERSION_MINOR, - !isysroot.empty(), - IncludeTimestamps, - ASTHasCompilerErrors}; + RecordData::value_type Record[] = {METADATA, + VERSION_MAJOR, + VERSION_MINOR, + CLANG_VERSION_MAJOR, + CLANG_VERSION_MINOR, + !isysroot.empty(), + isWritingStdCXXNamedModules(), + IncludeTimestamps, + ASTHasCompilerErrors}; Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); } @@ -1277,8 +1287,9 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, SmallString<128> BaseDir; if (PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd) { // Use the current working directory as the base path for all inputs. - auto *CWD = - Context.getSourceManager().getFileManager().getDirectory(".").get(); + auto CWD = + Context.getSourceManager().getFileManager().getOptionalDirectoryRef( + "."); BaseDir.assign(CWD->getName()); } else { BaseDir.assign(WritingModule->Directory->getName()); @@ -1288,11 +1299,11 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, // If the home of the module is the current working directory, then we // want to pick up the cwd of the build process loading the module, not // our cwd, when we load this module. - if (!(PP.getHeaderSearchInfo() + if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd && + (!PP.getHeaderSearchInfo() .getHeaderSearchOpts() .ModuleMapFileHomeIsCwd || - PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd) || - WritingModule->Directory->getName() != StringRef(".")) { + WritingModule->Directory->getName() != StringRef("."))) { // Module directory. auto Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY)); @@ -1349,6 +1360,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, continue; Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding + Record.push_back(M.StandardCXXModule); AddSourceLocation(M.ImportLoc, Record); // If we have calculated signature, there is no need to store @@ -1759,6 +1771,7 @@ namespace { struct data_type { const HeaderFileInfo &HFI; + bool AlreadyIncluded; ArrayRef<ModuleMap::KnownHeader> KnownHeaders; UnresolvedModule Unresolved; }; @@ -1804,7 +1817,8 @@ namespace { endian::Writer LE(Out, little); uint64_t Start = Out.tell(); (void)Start; - unsigned char Flags = (Data.HFI.isImport << 5) + unsigned char Flags = (Data.AlreadyIncluded << 6) + | (Data.HFI.isImport << 5) | (Data.HFI.isPragmaOnce << 4) | (Data.HFI.DirInfo << 1) | Data.HFI.IndexHeaderMapHeader; @@ -1884,7 +1898,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { // If the file didn't exist, we can still create a module if we were given // enough information in the module map. - for (auto U : M->MissingHeaders) { + for (const auto &U : M->MissingHeaders) { // Check that we were given enough information to build a module // without this file existing on disk. if (!U.Size || (!U.ModTime && IncludeTimestamps)) { @@ -1903,18 +1917,16 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { SavedStrings.push_back(FilenameDup.data()); HeaderFileInfoTrait::key_type Key = { - FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0 - }; + FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0}; HeaderFileInfoTrait::data_type Data = { - Empty, {}, {M, ModuleMap::headerKindToRole(U.Kind)} - }; + Empty, false, {}, {M, ModuleMap::headerKindToRole(U.Kind)}}; // FIXME: Deal with cases where there are multiple unresolved header // directives in different submodules for the same header. Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; } - - Worklist.append(M->submodule_begin(), M->submodule_end()); + auto SubmodulesRange = M->submodules(); + Worklist.append(SubmodulesRange.begin(), SubmodulesRange.end()); } } @@ -1950,11 +1962,13 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { SavedStrings.push_back(Filename.data()); } + bool Included = PP->alreadyIncluded(File); + HeaderFileInfoTrait::key_type Key = { Filename, File->getSize(), getTimestampForOutput(File) }; HeaderFileInfoTrait::data_type Data = { - *HFI, HS.getModuleMap().findResolvedModulesForHeader(File), {} + *HFI, Included, HS.getModuleMap().findResolvedModulesForHeader(File), {} }; Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; @@ -2260,29 +2274,6 @@ static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, return false; } -void ASTWriter::writeIncludedFiles(raw_ostream &Out, const Preprocessor &PP) { - using namespace llvm::support; - - const Preprocessor::IncludedFilesSet &IncludedFiles = PP.getIncludedFiles(); - - std::vector<uint32_t> IncludedInputFileIDs; - IncludedInputFileIDs.reserve(IncludedFiles.size()); - - for (const FileEntry *File : IncludedFiles) { - auto InputFileIt = InputFileIDs.find(File); - if (InputFileIt == InputFileIDs.end()) - continue; - IncludedInputFileIDs.push_back(InputFileIt->second); - } - - llvm::sort(IncludedInputFileIDs); - - endian::Writer LE(Out, little); - LE.write<uint32_t>(IncludedInputFileIDs.size()); - for (uint32_t ID : IncludedInputFileIDs) - LE.write<uint32_t>(ID); -} - /// Writes the block containing the serialized form of the /// preprocessor. void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { @@ -2531,20 +2522,6 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { MacroOffsetsBase - ASTBlockStartOffset}; Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, bytes(MacroOffsets)); } - - { - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(PP_INCLUDED_FILES)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned IncludedFilesAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - - SmallString<2048> Buffer; - raw_svector_ostream Out(Buffer); - writeIncludedFiles(Out, PP); - RecordData::value_type Record[] = {PP_INCLUDED_FILES}; - Stream.EmitRecordWithBlob(IncludedFilesAbbrev, Record, Buffer.data(), - Buffer.size()); - } } void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec, @@ -2701,9 +2678,8 @@ unsigned ASTWriter::getSubmoduleID(Module *Mod) { /// given module). static unsigned getNumberOfModules(Module *Mod) { unsigned ChildModules = 0; - for (auto Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); - Sub != SubEnd; ++Sub) - ChildModules += getNumberOfModules(*Sub); + for (auto *Submodule : Mod->submodules()) + ChildModules += getNumberOfModules(Submodule); return ChildModules + 1; } @@ -2719,7 +2695,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Kind + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Kind + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Definition location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem @@ -2820,12 +2797,16 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { ParentID = SubmoduleIDs[Mod->Parent]; } + uint64_t DefinitionLoc = + SourceLocationEncoding::encode(getAdjustedLocation(Mod->DefinitionLoc)); + // Emit the definition of the block. { RecordData::value_type Record[] = {SUBMODULE_DEFINITION, ID, ParentID, (RecordData::value_type)Mod->Kind, + DefinitionLoc, Mod->IsFramework, Mod->IsExplicit, Mod->IsSystem, @@ -2845,14 +2826,16 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { } // Emit the umbrella header, if there is one. - if (auto UmbrellaHeader = Mod->getUmbrellaHeader()) { + if (std::optional<Module::Header> UmbrellaHeader = + Mod->getUmbrellaHeaderAsWritten()) { RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_HEADER}; Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, - UmbrellaHeader.NameAsWritten); - } else if (auto UmbrellaDir = Mod->getUmbrellaDir()) { + UmbrellaHeader->NameAsWritten); + } else if (std::optional<Module::DirectoryName> UmbrellaDir = + Mod->getUmbrellaDirAsWritten()) { RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_DIR}; Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record, - UmbrellaDir.NameAsWritten); + UmbrellaDir->NameAsWritten); } // Emit the headers. @@ -2876,10 +2859,9 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { // Emit the top headers. { - auto TopHeaders = Mod->getTopHeaders(PP->getFileManager()); RecordData::value_type Record[] = {SUBMODULE_TOPHEADER}; - for (auto *H : TopHeaders) { - SmallString<128> HeaderName(H->getName()); + for (FileEntryRef H : Mod->getTopHeaders(PP->getFileManager())) { + SmallString<128> HeaderName(H.getName()); PreparePathForOutput(HeaderName); Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, HeaderName); } @@ -2995,20 +2977,41 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, assert(Flags == EncodeDiagStateFlags(State) && "diag state flags vary in single AST file"); + // If we ever serialize non-pragma mappings outside the initial state, the + // code below will need to consider more than getDefaultMapping. + assert(!IncludeNonPragmaStates || + State == Diag.DiagStatesByLoc.FirstDiagState); + unsigned &DiagStateID = DiagStateIDMap[State]; Record.push_back(DiagStateID); if (DiagStateID == 0) { DiagStateID = ++CurrID; + SmallVector<std::pair<unsigned, DiagnosticMapping>> Mappings; // Add a placeholder for the number of mappings. auto SizeIdx = Record.size(); Record.emplace_back(); for (const auto &I : *State) { - if (I.second.isPragma() || IncludeNonPragmaStates) { - Record.push_back(I.first); - Record.push_back(I.second.serialize()); - } + // Maybe skip non-pragmas. + if (!I.second.isPragma() && !IncludeNonPragmaStates) + continue; + // Skip default mappings. We have a mapping for every diagnostic ever + // emitted, regardless of whether it was customized. + if (!I.second.isPragma() && + I.second == DiagnosticIDs::getDefaultMapping(I.first)) + continue; + Mappings.push_back(I); + } + + // Sort by diag::kind for deterministic output. + llvm::sort(Mappings, [](const auto &LHS, const auto &RHS) { + return LHS.first < RHS.first; + }); + + for (const auto &I : Mappings) { + Record.push_back(I.first); + Record.push_back(I.second.serialize()); } // Update the placeholder. Record[SizeIdx] = (Record.size() - SizeIdx) / 2; @@ -3175,6 +3178,13 @@ void ASTWriter::WriteComments() { auto _ = llvm::make_scope_exit([this] { Stream.ExitBlock(); }); if (!PP->getPreprocessorOpts().WriteCommentListToPCH) return; + + // Don't write comments to BMI to reduce the size of BMI. + // If language services (e.g., clangd) want such abilities, + // we can offer a special option then. + if (isWritingStdCXXNamedModules()) + return; + RecordData Record; for (const auto &FO : Context->Comments.OrderedComments) { for (const auto &OC : FO.second) { @@ -3543,26 +3553,24 @@ public: // the mapping from persistent IDs to strings. Writer.SetIdentifierOffset(II, Out.tell()); + auto MacroOffset = Writer.getMacroDirectivesOffset(II); + // Emit the offset of the key/data length information to the interesting // identifiers table if necessary. - if (InterestingIdentifierOffsets && isInterestingIdentifier(II)) + if (InterestingIdentifierOffsets && + isInterestingIdentifier(II, MacroOffset)) InterestingIdentifierOffsets->push_back(Out.tell()); unsigned KeyLen = II->getLength() + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 - auto MacroOffset = Writer.getMacroDirectivesOffset(II); if (isInterestingIdentifier(II, MacroOffset)) { DataLen += 2; // 2 bytes for builtin ID DataLen += 2; // 2 bytes for flags if (MacroOffset) DataLen += 4; // MacroDirectives offset. - if (NeedDecls) { - for (IdentifierResolver::iterator D = IdResolver.begin(II), - DEnd = IdResolver.end(); - D != DEnd; ++D) - DataLen += 4; - } + if (NeedDecls) + DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) * 4; } return emitULEBKeyDataLength(KeyLen, DataLen, Out); } @@ -3607,8 +3615,7 @@ public: // "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<NamedDecl *, 16> Decls(IdResolver.begin(II), - IdResolver.end()); + SmallVector<NamedDecl *, 16> Decls(IdResolver.decls(II)); for (NamedDecl *D : llvm::reverse(Decls)) LE.write<uint32_t>( Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), D))); @@ -3634,9 +3641,8 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, // strings. { llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; - ASTIdentifierTableTrait Trait( - *this, PP, IdResolver, IsModule, - (getLangOpts().CPlusPlus && IsModule) ? &InterestingIdents : nullptr); + ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule, + IsModule ? &InterestingIdents : nullptr); // Look for any identifiers that were named while processing the // headers, but are otherwise not needed. We add these to the hash @@ -3645,13 +3651,13 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, // file. SmallVector<const IdentifierInfo *, 128> IIs; for (const auto &ID : PP.getIdentifierTable()) - IIs.push_back(ID.second); - // Sort the identifiers lexicographically before getting them references so + if (Trait.isInterestingNonMacroIdentifier(ID.second)) + IIs.push_back(ID.second); + // Sort the identifiers lexicographically before getting the references so // that their order is stable. llvm::sort(IIs, llvm::deref<std::less<>>()); for (const IdentifierInfo *II : IIs) - if (Trait.isInterestingNonMacroIdentifier(II)) - getIdentifierRef(II); + getIdentifierRef(II); // Create the on-disk hash table representation. We only store offsets // for identifiers that appear here for the first time. @@ -4252,6 +4258,7 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) { LateParsedTemplate &LPT = *LPTMapEntry.second; AddDeclRef(FD, Record); AddDeclRef(LPT.D, Record); + Record.push_back(LPT.FPO.getAsOpaqueInt()); Record.push_back(LPT.Toks.size()); for (const auto &Tok : LPT.Toks) { @@ -4382,6 +4389,7 @@ void ASTRecordWriter::AddAttr(const Attr *A) { Record.push_back(A->getParsedKind()); Record.push_back(A->getSyntax()); Record.push_back(A->getAttributeSpellingListIndexRaw()); + Record.push_back(A->isRegularKeywordAttribute()); #include "clang/Serialization/AttrPCHWrite.inc" } @@ -4412,6 +4420,14 @@ void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) { AddToken(T, Record); break; } + case tok::annot_pragma_pack: { + auto *Info = + static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue()); + Record.push_back(static_cast<unsigned>(Info->Action)); + AddString(Info->SlotLabel, Record); + AddToken(Info->Alignment, Record); + break; + } // Some annotation tokens do not use the PtrData field. case tok::annot_pragma_openmp: case tok::annot_pragma_openmp_end: @@ -4436,6 +4452,11 @@ void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) { assert(Context && "should have context when outputting path"); + // Leave special file names as they are. + StringRef PathStr(Path.data(), Path.size()); + if (PathStr == "<built-in>" || PathStr == "<command line>") + return false; + bool Changed = cleanPathForOutput(Context->getSourceManager().getFileManager(), Path); @@ -4873,13 +4894,9 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, } // Sort the identifiers to visit based on their name. llvm::sort(IIs, llvm::deref<std::less<>>()); - for (const IdentifierInfo *II : IIs) { - for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II), - DEnd = SemaRef.IdResolver.end(); - D != DEnd; ++D) { - GetDeclRef(*D); - } - } + for (const IdentifierInfo *II : IIs) + for (const Decl *D : SemaRef.IdResolver.decls(II)) + GetDeclRef(D); } // For method pool in the module, if it contains an entry for a selector, @@ -5101,7 +5118,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, }; llvm::SmallVector<ModuleInfo, 64> Imports; for (const auto *I : Context.local_imports()) { - assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end()); + assert(SubmoduleIDs.contains(I->getImportedModule())); Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()], I->getImportedModule())); } @@ -5167,6 +5184,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { const Decl *D = DeclUpdate.first; bool HasUpdatedBody = false; + bool HasAddedVarDefinition = false; RecordData RecordData; ASTRecordWriter Record(*this, RecordData); for (auto &Update : DeclUpdate.second) { @@ -5176,6 +5194,8 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { // to skip over the lazy body to reach statements for other records. if (Kind == UPD_CXX_ADDED_FUNCTION_DEFINITION) HasUpdatedBody = true; + else if (Kind == UPD_CXX_ADDED_VAR_DEFINITION) + HasAddedVarDefinition = true; else Record.push_back(Kind); @@ -5188,6 +5208,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { break; case UPD_CXX_ADDED_FUNCTION_DEFINITION: + case UPD_CXX_ADDED_VAR_DEFINITION: break; case UPD_CXX_POINT_OF_INSTANTIATION: @@ -5195,14 +5216,6 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { Record.AddSourceLocation(Update.getLoc()); break; - case UPD_CXX_ADDED_VAR_DEFINITION: { - const VarDecl *VD = cast<VarDecl>(D); - Record.push_back(VD->isInline()); - Record.push_back(VD->isInlineSpecified()); - Record.AddVarDeclInit(VD); - break; - } - case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: Record.AddStmt(const_cast<Expr *>( cast<ParmVarDecl>(Update.getDecl())->getDefaultArg())); @@ -5314,12 +5327,20 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { } } + // Add a trailing update record, if any. These must go last because we + // lazily load their attached statement. if (HasUpdatedBody) { const auto *Def = cast<FunctionDecl>(D); Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION); Record.push_back(Def->isInlined()); Record.AddSourceLocation(Def->getInnerLocStart()); Record.AddFunctionDefinition(Def); + } else if (HasAddedVarDefinition) { + const auto *VD = cast<VarDecl>(D); + Record.push_back(UPD_CXX_ADDED_VAR_DEFINITION); + Record.push_back(VD->isInline()); + Record.push_back(VD->isInlineSpecified()); + Record.AddVarDeclInit(VD); } OffsetsRecord.push_back(GetDeclRef(D)); @@ -5449,7 +5470,7 @@ MacroID ASTWriter::getMacroID(MacroInfo *MI) { if (!MI || MI->isBuiltinMacro()) return 0; - assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!"); + assert(MacroIDs.contains(MI) && "Macro not emitted!"); return MacroIDs[MI]; } @@ -5624,7 +5645,7 @@ DeclID ASTWriter::getDeclID(const Decl *D) { if (D->isFromASTFile()) return D->getGlobalID(); - assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!"); + assert(DeclIDs.contains(D) && "Declaration not emitted!"); return DeclIDs[D]; } @@ -5909,6 +5930,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { // getODRHash will compute the ODRHash if it has not been previously computed. Record->push_back(D->getODRHash()); + bool ModulesDebugInfo = Writer->Context->getLangOpts().ModulesDebugInfo && !D->isDependentType(); Record->push_back(ModulesDebugInfo); @@ -5917,24 +5939,24 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { // IsLambda bit is already saved. - Record->push_back(Data.NumBases); - if (Data.NumBases > 0) - AddCXXBaseSpecifiers(Data.bases()); - - // FIXME: Make VBases lazily computed when needed to avoid storing them. - Record->push_back(Data.NumVBases); - if (Data.NumVBases > 0) - AddCXXBaseSpecifiers(Data.vbases()); - AddUnresolvedSet(Data.Conversions.get(*Writer->Context)); Record->push_back(Data.ComputedVisibleConversions); if (Data.ComputedVisibleConversions) AddUnresolvedSet(Data.VisibleConversions.get(*Writer->Context)); // Data.Definition is the owning decl, no need to write it. - AddDeclRef(D->getFirstFriend()); - // Add lambda-specific data. - if (Data.IsLambda) { + if (!Data.IsLambda) { + Record->push_back(Data.NumBases); + if (Data.NumBases > 0) + AddCXXBaseSpecifiers(Data.bases()); + + // FIXME: Make VBases lazily computed when needed to avoid storing them. + Record->push_back(Data.NumVBases); + if (Data.NumVBases > 0) + AddCXXBaseSpecifiers(Data.vbases()); + + AddDeclRef(D->getFirstFriend()); + } else { auto &Lambda = D->getLambdaData(); Record->push_back(Lambda.DependencyKind); Record->push_back(Lambda.IsGenericLambda); @@ -5944,7 +5966,8 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { Record->push_back(Lambda.HasKnownInternalLinkage); Record->push_back(Lambda.ManglingNumber); Record->push_back(D->getDeviceLambdaManglingNumber()); - AddDeclRef(D->getLambdaContextDecl()); + // The lambda context declaration and index within the context are provided + // separately, so that they can be used for merging. AddTypeSourceInfo(Lambda.MethodTyInfo); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { const LambdaCapture &Capture = Lambda.Captures.front()[I]; @@ -5976,13 +5999,20 @@ void ASTRecordWriter::AddVarDeclInit(const VarDecl *VD) { return; } - unsigned Val = 1; + uint64_t Val = 1; if (EvaluatedStmt *ES = VD->getEvaluatedStmt()) { Val |= (ES->HasConstantInitialization ? 2 : 0); Val |= (ES->HasConstantDestruction ? 4 : 0); - // FIXME: Also emit the constant initializer value. + APValue *Evaluated = VD->getEvaluatedValue(); + // If the evaluted result is constant, emit it. + if (Evaluated && (Evaluated->isInt() || Evaluated->isFloat())) + Val |= 8; } push_back(Val); + if (Val & 8) { + AddAPValue(*VD->getEvaluatedValue()); + } + writeStmtRef(Init); } @@ -6049,12 +6079,12 @@ void ASTWriter::SelectorRead(SelectorID ID, Selector S) { void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, MacroDefinitionRecord *MD) { - assert(MacroDefinitions.find(MD) == MacroDefinitions.end()); + assert(!MacroDefinitions.contains(MD)); MacroDefinitions[MD] = ID; } void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { - assert(SubmoduleIDs.find(Mod) == SubmoduleIDs.end()); + assert(!SubmoduleIDs.contains(Mod)); SubmoduleIDs[Mod] = ID; } @@ -7128,6 +7158,19 @@ void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) { Record.AddSourceLocation(C->getLParenLoc()); } +void OMPClauseWriter::VisitOMPDoacrossClause(OMPDoacrossClause *C) { + Record.push_back(C->varlist_size()); + Record.push_back(C->getNumLoops()); + Record.AddSourceLocation(C->getLParenLoc()); + Record.push_back(C->getDependenceType()); + Record.AddSourceLocation(C->getDependenceLoc()); + Record.AddSourceLocation(C->getColonLoc()); + for (auto *VE : C->varlists()) + Record.AddStmt(VE); + for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) + Record.AddStmt(C->getLoopData(I)); +} + void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) { writeUInt32(TI->Sets.size()); for (const auto &Set : TI->Sets) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index a58e0d796b31..59dbc36d24e8 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -278,7 +278,7 @@ void ASTDeclWriter::Visit(Decl *D) { // Source locations require array (variable-length) abbreviations. The // abbreviation infrastructure requires that arrays are encoded last, so // we handle it here in the case of those classes derived from DeclaratorDecl - if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { + if (auto *DD = dyn_cast<DeclaratorDecl>(D)) { if (auto *TInfo = DD->getTypeSourceInfo()) Record.AddTypeLoc(TInfo->getTypeLoc()); } @@ -286,16 +286,38 @@ void ASTDeclWriter::Visit(Decl *D) { // Handle FunctionDecl's body here and write it after all other Stmts/Exprs // have been written. We want it last because we will not read it back when // retrieving it from the AST, we'll just lazily set the offset. - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (auto *FD = dyn_cast<FunctionDecl>(D)) { Record.push_back(FD->doesThisDeclarationHaveABody()); if (FD->doesThisDeclarationHaveABody()) Record.AddFunctionDefinition(FD); } + // Similar to FunctionDecls, handle VarDecl's initializer here and write it + // after all other Stmts/Exprs. We will not read the initializer until after + // we have finished recursive deserialization, because it can recursively + // refer back to the variable. + if (auto *VD = dyn_cast<VarDecl>(D)) { + Record.AddVarDeclInit(VD); + } + + // And similarly for FieldDecls. We already serialized whether there is a + // default member initializer. + if (auto *FD = dyn_cast<FieldDecl>(D)) { + if (FD->hasInClassInitializer()) { + if (Expr *Init = FD->getInClassInitializer()) { + Record.push_back(1); + Record.AddStmt(Init); + } else { + Record.push_back(0); + // Initializer has not been instantiated yet. + } + } + } + // If this declaration is also a DeclContext, write blocks for the // declarations that lexically stored inside its context and those // declarations that are visible from its context. - if (DeclContext *DC = dyn_cast<DeclContext>(D)) + if (auto *DC = dyn_cast<DeclContext>(D)) VisitDeclContext(DC); } @@ -411,6 +433,10 @@ void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { } void ASTDeclWriter::VisitTagDecl(TagDecl *D) { + static_assert(DeclContext::NumTagDeclBits == 10, + "You need to update the serializer after you change the " + "TagDeclBits"); + VisitRedeclarable(D); VisitTypeDecl(D); Record.push_back(D->getIdentifierNamespace()); @@ -435,6 +461,10 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) { } void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { + static_assert(DeclContext::NumEnumDeclBits == 20, + "You need to update the serializer after you change the " + "EnumDeclBits"); + VisitTagDecl(D); Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo()); if (!D->getIntegerTypeSourceInfo()) @@ -478,6 +508,10 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { } void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { + static_assert(DeclContext::NumRecordDeclBits == 41, + "You need to update the serializer after you change the " + "RecordDeclBits"); + VisitTagDecl(D); Record.push_back(D->hasFlexibleArrayMember()); Record.push_back(D->isAnonymousStructOrUnion()); @@ -546,6 +580,10 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { } void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { + static_assert(DeclContext::NumFunctionDeclBits == 30, + "You need to update the serializer after you change the " + "FunctionDeclBits"); + VisitRedeclarable(D); Record.push_back(D->getTemplatedKind()); @@ -692,11 +730,15 @@ void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { addExplicitSpecifier(D->getExplicitSpecifier(), Record); Record.AddDeclRef(D->Ctor); VisitFunctionDecl(D); - Record.push_back(D->isCopyDeductionCandidate()); + Record.push_back(static_cast<unsigned char>(D->getDeductionCandidateKind())); Code = serialization::DECL_CXX_DEDUCTION_GUIDE; } void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { + static_assert(DeclContext::NumObjCMethodDeclBits == 24, + "You need to update the serializer after you change the " + "ObjCMethodDeclBits"); + VisitNamedDecl(D); // FIXME: convert to LazyStmtPtr? // Unlike C/C++, method bodies will never be in header files. @@ -755,6 +797,10 @@ void ASTDeclWriter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { } void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { + static_assert(DeclContext::NumObjCContainerDeclBits == 51, + "You need to update the serializer after you change the " + "ObjCContainerDeclBits"); + VisitNamedDecl(D); Record.AddSourceLocation(D->getAtStartLoc()); Record.AddSourceRange(D->getAtEndRange()); @@ -935,14 +981,11 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { VisitDeclaratorDecl(D); Record.push_back(D->isMutable()); - FieldDecl::InitStorageKind ISK = D->InitStorage.getInt(); - Record.push_back(ISK); - if (ISK == FieldDecl::ISK_CapturedVLAType) + Record.push_back((D->StorageKind << 1) | D->BitField); + if (D->StorageKind == FieldDecl::ISK_CapturedVLAType) Record.AddTypeRef(QualType(D->getCapturedVLAType(), 0)); - else if (ISK) - Record.AddStmt(D->getInClassInitializer()); - - Record.AddStmt(D->getBitWidth()); + else if (D->BitField) + Record.AddStmt(D->getBitWidth()); if (!D->getDeclName()) Record.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D)); @@ -1013,6 +1056,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(D->getTSCSpec()); Record.push_back(D->getInitStyle()); Record.push_back(D->isARCPseudoStrong()); + bool HasDeducedType = false; if (!isa<ParmVarDecl>(D)) { Record.push_back(D->isThisDeclarationADemotedDefinition()); Record.push_back(D->isExceptionVariable()); @@ -1029,36 +1073,34 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { else Record.push_back(0); Record.push_back(D->isEscapingByref()); + HasDeducedType = D->getType()->getContainedDeducedType(); + Record.push_back(HasDeducedType); } Record.push_back(D->getLinkageInternal()); - Record.AddVarDeclInit(D); - - if (D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) { + if (D->hasAttr<BlocksAttr>()) { BlockVarCopyInit Init = Writer.Context->getBlockVarCopyInit(D); Record.AddStmt(Init.getCopyExpr()); if (Init.getCopyExpr()) Record.push_back(Init.canThrow()); } - if (D->getStorageDuration() == SD_Static) { - bool ModulesCodegen = false; - if (Writer.WritingModule && - !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo()) { - // When building a C++20 module interface unit or a partition unit, a - // strong definition in the module interface is provided by the - // compilation of that unit, not by its users. (Inline variables are still - // emitted in module users.) - ModulesCodegen = - (Writer.WritingModule->isInterfaceOrPartition() || - (D->hasAttr<DLLExportAttr>() && - Writer.Context->getLangOpts().BuildingPCHWithObjectFile)) && - Writer.Context->GetGVALinkageForVariable(D) == GVA_StrongExternal; - } - Record.push_back(ModulesCodegen); - if (ModulesCodegen) - Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D)); + bool ModulesCodegen = false; + if (Writer.WritingModule && D->getStorageDuration() == SD_Static && + !D->getDescribedVarTemplate()) { + // When building a C++20 module interface unit or a partition unit, a + // strong definition in the module interface is provided by the + // compilation of that unit, not by its users. (Inline variables are still + // emitted in module users.) + ModulesCodegen = + (Writer.WritingModule->isInterfaceOrPartition() || + (D->hasAttr<DLLExportAttr>() && + Writer.Context->getLangOpts().BuildingPCHWithObjectFile)) && + Writer.Context->GetGVALinkageForVariable(D) >= GVA_StrongExternal; } + Record.push_back(ModulesCodegen); + if (ModulesCodegen) + Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D)); enum { VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization @@ -1094,9 +1136,10 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->isConstexpr() && !D->isInitCapture() && !D->isPreviousDeclInSameBlockScope() && - !(D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) && !D->isEscapingByref() && + !HasDeducedType && D->getStorageDuration() != SD_Static && + !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo()) AbbrevToUse = Writer.getDeclVarAbbrev(); @@ -1241,6 +1284,10 @@ void ASTDeclWriter::VisitCapturedDecl(CapturedDecl *CD) { } void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { + static_assert(DeclContext::NumLinkageSpecDeclBits == 4, + "You need to update the serializer after you change the" + "LinkageSpecDeclBits"); + VisitDecl(D); Record.push_back(D->getLanguage()); Record.AddSourceLocation(D->getExternLoc()); @@ -1385,7 +1432,10 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { VisitRecordDecl(D); enum { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization + CXXRecNotTemplate = 0, + CXXRecTemplate, + CXXRecMemberSpecialization, + CXXLambda }; if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) { Record.push_back(CXXRecTemplate); @@ -1396,6 +1446,15 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { Record.AddDeclRef(MSInfo->getInstantiatedFrom()); Record.push_back(MSInfo->getTemplateSpecializationKind()); Record.AddSourceLocation(MSInfo->getPointOfInstantiation()); + } else if (D->isLambda()) { + // For a lambda, we need some information early for merging. + Record.push_back(CXXLambda); + if (auto *Context = D->getLambdaContextDecl()) { + Record.AddDeclRef(Context); + Record.push_back(D->getLambdaIndexInContext()); + } else { + Record.push_back(0); + } } else { Record.push_back(CXXRecNotTemplate); } @@ -1436,6 +1495,10 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { } void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { + static_assert(DeclContext::NumCXXConstructorDeclBits == 21, + "You need to update the serializer after you change the " + "CXXConstructorDeclBits"); + Record.push_back(D->getTrailingAllocKind()); addExplicitSpecifier(D->getExplicitSpecifier(), Record); if (auto Inherited = D->getInheritedConstructor()) { @@ -1812,6 +1875,10 @@ void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) { /// Emit the DeclContext part of a declaration context decl. void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { + static_assert(DeclContext::NumDeclContextBits == 13, + "You need to update the serializer after you change the " + "DeclContextBits"); + Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC)); Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC)); } @@ -1922,6 +1989,10 @@ void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { } void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { + static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 2, + "You need to update the serializer after you change the " + "NumOMPDeclareReductionDeclBits"); + VisitValueDecl(D); Record.AddSourceLocation(D->getBeginLoc()); Record.AddStmt(D->getCombinerIn()); @@ -1984,7 +2055,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FieldDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable - Abv->Add(BitCodeAbbrevOp(0)); // InitStyle + Abv->Add(BitCodeAbbrevOp(0)); // StorageKind // Type Source Info Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc @@ -2173,8 +2244,8 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // InitStyle Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong Abv->Add(BitCodeAbbrevOp(0)); // Linkage - Abv->Add(BitCodeAbbrevOp(0)); // HasInit - Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo + Abv->Add(BitCodeAbbrevOp(0)); // ModulesCodegen + Abv->Add(BitCodeAbbrevOp(0)); // VarKind (local enum) // ParmVarDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsObjCMethodParameter Abv->Add(BitCodeAbbrevOp(0)); // ScopeDepth @@ -2261,9 +2332,10 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope Abv->Add(BitCodeAbbrevOp(0)); // ImplicitParamKind Abv->Add(BitCodeAbbrevOp(0)); // EscapingByref + Abv->Add(BitCodeAbbrevOp(0)); // HasDeducedType Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // HasConstant* - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum) + Abv->Add(BitCodeAbbrevOp(0)); // ModulesCodeGen + Abv->Add(BitCodeAbbrevOp(0)); // VarKind (local enum) // Type Source Info Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc @@ -2353,6 +2425,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates Abv->Add(BitCodeAbbrevOp(0)); // RefersToEnclosingVariableOrCapture Abv->Add(BitCodeAbbrevOp(0)); // NonOdrUseReason + Abv->Add(BitCodeAbbrevOp(0)); // IsImmediateEscalating Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -2428,7 +2501,20 @@ void ASTWriter::WriteDeclAbbrevs() { /// relatively painless since they would presumably only do it for top-level /// decls. static bool isRequiredDecl(const Decl *D, ASTContext &Context, - bool WritingModule) { + Module *WritingModule) { + // Named modules have different semantics than header modules. Every named + // module units owns a translation unit. So the importer of named modules + // doesn't need to deserilize everything ahead of time. + if (WritingModule && WritingModule->isModulePurview()) { + // The PragmaCommentDecl and PragmaDetectMismatchDecl are MSVC's extension. + // And the behavior of MSVC for such cases will leak this to the module + // users. Given pragma is not a standard thing, the compiler has the space + // to do their own decision. Let's follow MSVC here. + if (isa<PragmaCommentDecl, PragmaDetectMismatchDecl>(D)) + return true; + return false; + } + // An ObjCMethodDecl is never considered as "required" because its // implementation container always is. @@ -2510,7 +2596,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { // compilation of that unit, not by its users. (Inline functions are still // emitted in module users.) Linkage = Writer->Context->GetGVALinkageForFunction(FD); - ModulesCodegen = *Linkage == GVA_StrongExternal; + ModulesCodegen = *Linkage >= GVA_StrongExternal; } if (Writer->Context->getLangOpts().ModulesCodegen || (FD->hasAttr<DLLExportAttr>() && diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index b35a7cee5af2..896e24c8a13d 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -42,6 +42,7 @@ namespace clang { Code(serialization::STMT_NULL_PTR), AbbrevToUse(0) {} ASTStmtWriter(const ASTStmtWriter&) = delete; + ASTStmtWriter &operator=(const ASTStmtWriter &) = delete; uint64_t Emit() { assert(Code != serialization::STMT_NULL_PTR && @@ -150,7 +151,7 @@ void ASTStmtWriter::VisitIfStmt(IfStmt *S) { if (HasElse) Record.AddStmt(S->getElse()); if (HasVar) - Record.AddDeclRef(S->getConditionVariable()); + Record.AddStmt(S->getConditionVariableDeclStmt()); if (HasInit) Record.AddStmt(S->getInit()); @@ -177,7 +178,7 @@ void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) { if (HasInit) Record.AddStmt(S->getInit()); if (HasVar) - Record.AddDeclRef(S->getConditionVariable()); + Record.AddStmt(S->getConditionVariableDeclStmt()); Record.AddSourceLocation(S->getSwitchLoc()); Record.AddSourceLocation(S->getLParenLoc()); @@ -198,7 +199,7 @@ void ASTStmtWriter::VisitWhileStmt(WhileStmt *S) { Record.AddStmt(S->getCond()); Record.AddStmt(S->getBody()); if (HasVar) - Record.AddDeclRef(S->getConditionVariable()); + Record.AddStmt(S->getConditionVariableDeclStmt()); Record.AddSourceLocation(S->getWhileLoc()); Record.AddSourceLocation(S->getLParenLoc()); @@ -220,7 +221,7 @@ void ASTStmtWriter::VisitForStmt(ForStmt *S) { VisitStmt(S); Record.AddStmt(S->getInit()); Record.AddStmt(S->getCond()); - Record.AddDeclRef(S->getConditionVariable()); + Record.AddStmt(S->getConditionVariableDeclStmt()); Record.AddStmt(S->getInc()); Record.AddStmt(S->getBody()); Record.AddSourceLocation(S->getForLoc()); @@ -316,7 +317,10 @@ void ASTStmtWriter::VisitGCCAsmStmt(GCCAsmStmt *S) { Record.AddStmt(S->getClobberStringLiteral(I)); // Labels - for (auto *E : S->labels()) Record.AddStmt(E); + for (unsigned I = 0, N = S->getNumLabels(); I != N; ++I) { + Record.AddIdentifierRef(S->getLabelIdentifier(I)); + Record.AddStmt(S->getLabelExpr(I)); + } Code = serialization::STMT_GCCASM; } @@ -593,6 +597,7 @@ void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { bool HasFunctionName = E->getFunctionName() != nullptr; Record.push_back(HasFunctionName); Record.push_back(E->getIdentKind()); // FIXME: stable encoding + Record.push_back(E->isTransparent()); Record.AddSourceLocation(E->getLocation()); if (HasFunctionName) Record.AddStmt(E->getFunctionName()); @@ -608,6 +613,7 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->refersToEnclosingVariableOrCapture()); Record.push_back(E->isNonOdrUse()); + Record.push_back(E->isImmediateEscalating()); if (E->hasTemplateKWAndArgsInfo()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -619,7 +625,8 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) && (E->getDecl() == E->getFoundDecl()) && nk == DeclarationName::Identifier && - !E->refersToEnclosingVariableOrCapture() && !E->isNonOdrUse()) { + !E->refersToEnclosingVariableOrCapture() && !E->isNonOdrUse() && + !E->isImmediateEscalating()) { AbbrevToUse = Writer.getDeclRefExprAbbrev(); } @@ -1087,7 +1094,7 @@ void ASTStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) { Record.push_back(E->usesGNUSyntax()); for (const DesignatedInitExpr::Designator &D : E->designators()) { if (D.isFieldDesignator()) { - if (FieldDecl *Field = D.getField()) { + if (FieldDecl *Field = D.getFieldDecl()) { Record.push_back(serialization::DESIG_FIELD_DECL); Record.AddDeclRef(Field); } else { @@ -1098,13 +1105,13 @@ void ASTStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) { Record.AddSourceLocation(D.getFieldLoc()); } else if (D.isArrayDesignator()) { Record.push_back(serialization::DESIG_ARRAY); - Record.push_back(D.getFirstExprIndex()); + Record.push_back(D.getArrayIndex()); Record.AddSourceLocation(D.getLBracketLoc()); Record.AddSourceLocation(D.getRBracketLoc()); } else { assert(D.isArrayRangeDesignator() && "Unknown designator"); Record.push_back(serialization::DESIG_ARRAY_RANGE); - Record.push_back(D.getFirstExprIndex()); + Record.push_back(D.getArrayIndex()); Record.AddSourceLocation(D.getLBracketLoc()); Record.AddSourceLocation(D.getEllipsisLoc()); Record.AddSourceLocation(D.getRBracketLoc()); @@ -1224,6 +1231,7 @@ void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { VisitExpr(E); Record.push_back(E->getNumAssocs()); + Record.push_back(E->isExprPredicate()); Record.push_back(E->ResultIndex); Record.AddSourceLocation(E->getGenericLoc()); Record.AddSourceLocation(E->getDefaultLoc()); @@ -1595,6 +1603,7 @@ void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { Record.push_back(E->isStdInitListInitialization()); Record.push_back(E->requiresZeroInitialization()); Record.push_back(E->getConstructionKind()); // FIXME: stable encoding + Record.push_back(E->isImmediateEscalating()); Record.AddSourceLocation(E->getLocation()); Record.AddDeclRef(E->getConstructor()); Record.AddSourceRange(E->getParenOrBraceRange()); @@ -1921,6 +1930,7 @@ ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { Record.AddTypeSourceInfo(E->getTypeSourceInfo()); Record.AddSourceLocation(E->getLParenLoc()); Record.AddSourceLocation(E->getRParenLoc()); + Record.push_back(E->isListInitialization()); Code = serialization::EXPR_CXX_UNRESOLVED_CONSTRUCT; } @@ -2698,16 +2708,14 @@ void ASTStmtWriter::VisitOMPTargetParallelGenericLoopDirective( //===----------------------------------------------------------------------===// unsigned ASTWriter::RecordSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && - "SwitchCase recorded twice"); + assert(!SwitchCaseIDs.contains(S) && "SwitchCase recorded twice"); unsigned NextID = SwitchCaseIDs.size(); SwitchCaseIDs[S] = NextID; return NextID; } unsigned ASTWriter::getSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && - "SwitchCase hasn't been seen yet"); + assert(SwitchCaseIDs.contains(S) && "SwitchCase hasn't been seen yet"); return SwitchCaseIDs[S]; } diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index b2283c2b3987..d57f4cec2eab 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -25,12 +25,12 @@ #include "llvm/Bitstream/BitstreamWriter.h" #include "llvm/Support/DJB.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/FileUtilities.h" #include "llvm/Support/LockFileManager.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" #include "llvm/Support/TimeProfiler.h" +#include "llvm/Support/raw_ostream.h" #include <cstdio> using namespace clang; using namespace serialization; @@ -281,15 +281,6 @@ GlobalModuleIndex::readIndex(StringRef Path) { llvm::Error::success()); } -void -GlobalModuleIndex::getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles) { - ModuleFiles.clear(); - for (unsigned I = 0, N = Modules.size(); I != N; ++I) { - if (ModuleFile *MF = Modules[I].File) - ModuleFiles.push_back(MF); - } -} - void GlobalModuleIndex::getModuleDependencies( ModuleFile *File, SmallVectorImpl<ModuleFile *> &Dependencies) { @@ -634,6 +625,9 @@ llvm::Error GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Skip the imported kind ++Idx; + // Skip if it is standard C++ module + ++Idx; + // Skip the import location ++Idx; @@ -913,8 +907,10 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, "failed writing index"); } - return llvm::writeFileAtomically((IndexPath + "-%%%%%%%%").str(), IndexPath, - OutputBuffer); + return llvm::writeToOutput(IndexPath, [&OutputBuffer](llvm::raw_ostream &OS) { + OS << OutputBuffer; + return llvm::Error::success(); + }); } namespace { diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 81dd54692d77..5b099b740e1d 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -59,11 +59,7 @@ ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const { } ModuleFile *ModuleManager::lookup(const FileEntry *File) const { - auto Known = Modules.find(File); - if (Known == Modules.end()) - return nullptr; - - return Known->second; + return Modules.lookup(File); } std::unique_ptr<llvm::MemoryBuffer> diff --git a/clang/lib/Serialization/PCHContainerOperations.cpp b/clang/lib/Serialization/PCHContainerOperations.cpp index d4990fce2d99..56ca3394385b 100644 --- a/clang/lib/Serialization/PCHContainerOperations.cpp +++ b/clang/lib/Serialization/PCHContainerOperations.cpp @@ -57,6 +57,11 @@ std::unique_ptr<ASTConsumer> RawPCHContainerWriter::CreatePCHContainerGenerator( return std::make_unique<RawPCHContainerGenerator>(std::move(OS), Buffer); } +ArrayRef<llvm::StringRef> RawPCHContainerReader::getFormats() const { + static StringRef Raw("raw"); + return ArrayRef(Raw); +} + StringRef RawPCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const { return Buffer.getBuffer(); |