diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2024-07-27 23:34:35 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-10-23 18:26:01 +0000 |
commit | 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583 (patch) | |
tree | 6cf5ab1f05330c6773b1f3f64799d56a9c7a1faa /contrib/llvm-project/clang/lib/Serialization | |
parent | 6b9f7133aba44189d9625c352bc2c2a59baf18ef (diff) | |
parent | ac9a064cb179f3425b310fa2847f8764ac970a4d (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Serialization')
15 files changed, 2734 insertions, 1330 deletions
diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTCommon.cpp index 6110e287b7fb..444a8a3d3a51 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTCommon.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTCommon.cpp @@ -186,6 +186,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break; + case BuiltinType::UnresolvedTemplate: + ID = PREDEF_TYPE_UNRESOLVED_TEMPLATE; + break; case BuiltinType::BoundMember: ID = PREDEF_TYPE_BOUND_MEMBER; break; @@ -255,14 +258,19 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { ID = PREDEF_TYPE_##Id##_ID; \ break; #include "clang/Basic/WebAssemblyReferenceTypes.def" +#define AMDGPU_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + ID = PREDEF_TYPE_##Id##_ID; \ + break; +#include "clang/Basic/AMDGPUTypes.def" case BuiltinType::BuiltinFn: ID = PREDEF_TYPE_BUILTIN_FN; break; case BuiltinType::IncompleteMatrixIdx: ID = PREDEF_TYPE_INCOMPLETE_MATRIX_IDX; break; - case BuiltinType::OMPArraySection: - ID = PREDEF_TYPE_OMP_ARRAY_SECTION; + case BuiltinType::ArraySection: + ID = PREDEF_TYPE_ARRAY_SECTION; break; case BuiltinType::OMPArrayShaping: ID = PREDEF_TYPE_OMP_ARRAY_SHAPING; @@ -275,7 +283,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { break; } - return TypeIdx(ID); + return TypeIdx(0, ID); } unsigned serialization::ComputeHash(Selector Sel) { @@ -284,7 +292,7 @@ unsigned serialization::ComputeHash(Selector Sel) { ++N; unsigned R = 5381; for (unsigned I = 0; I != N; ++I) - if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) + if (const IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) R = llvm::djbHash(II->getName(), R); return R; } @@ -338,7 +346,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) { // FIXME: These are defined in one place, but properties in class extensions // end up being back-patched into the main interface. See - // Sema::HandlePropertyInClassExtension for the offending code. + // SemaObjC::HandlePropertyInClassExtension for the offending code. case Decl::ObjCInterface: return nullptr; diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTCommon.h b/contrib/llvm-project/clang/lib/Serialization/ASTCommon.h index 296642e3674a..0230908d3e05 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTCommon.h +++ b/contrib/llvm-project/clang/lib/Serialization/ASTCommon.h @@ -46,30 +46,6 @@ enum DeclUpdateKind { TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); -template <typename IdxForTypeTy> -TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) { - if (T.isNull()) - return PREDEF_TYPE_NULL_ID; - - unsigned FastQuals = T.getLocalFastQualifiers(); - T.removeLocalFastQualifiers(); - - if (T.hasLocalNonFastQualifiers()) - return IdxForType(T).asTypeID(FastQuals); - - assert(!T.hasLocalQualifiers()); - - if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) - return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); - - if (T == Context.AutoDeductTy) - return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); - if (T == Context.AutoRRefDeductTy) - return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); - - return IdxForType(T).asTypeID(FastQuals); -} - unsigned ComputeHash(Selector Sel); /// Retrieve the "definitive" declaration that provides all of the diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp index 490b8cb10a48..3cb96df12e4d 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp @@ -31,7 +31,7 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/ODRDiagsEmitter.h" -#include "clang/AST/ODRHash.h" +#include "clang/AST/OpenACCClause.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/RawCommentList.h" #include "clang/AST/TemplateBase.h" @@ -40,9 +40,11 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/ASTSourceDescriptor.h" #include "clang/Basic/CommentOptions.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticError.h" +#include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/ExceptionSpecificationType.h" @@ -53,6 +55,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/OpenACCKinds.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PragmaKinds.h" @@ -76,6 +79,8 @@ #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Scope.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" @@ -827,36 +832,37 @@ bool SimpleASTReaderListener::ReadPreprocessorOptions( OptionValidateNone); } -/// Check the header search options deserialized from the control block -/// against the header search options in an existing preprocessor. +/// Check that the specified and the existing module cache paths are equivalent. /// /// \param Diags If non-null, produce diagnostics for any mismatches incurred. -static bool checkHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef SpecificModuleCachePath, - StringRef ExistingModuleCachePath, - DiagnosticsEngine *Diags, - const LangOptions &LangOpts, - const PreprocessorOptions &PPOpts) { - if (LangOpts.Modules) { - if (SpecificModuleCachePath != ExistingModuleCachePath && - !PPOpts.AllowPCHWithDifferentModulesCachePath) { - if (Diags) - Diags->Report(diag::err_pch_modulecache_mismatch) - << SpecificModuleCachePath << ExistingModuleCachePath; - return true; - } - } - - return false; +/// \returns true when the module cache paths differ. +static bool checkModuleCachePath(llvm::vfs::FileSystem &VFS, + StringRef SpecificModuleCachePath, + StringRef ExistingModuleCachePath, + DiagnosticsEngine *Diags, + const LangOptions &LangOpts, + const PreprocessorOptions &PPOpts) { + if (!LangOpts.Modules || PPOpts.AllowPCHWithDifferentModulesCachePath || + SpecificModuleCachePath == ExistingModuleCachePath) + return false; + auto EqualOrErr = + VFS.equivalent(SpecificModuleCachePath, ExistingModuleCachePath); + if (EqualOrErr && *EqualOrErr) + return false; + if (Diags) + Diags->Report(diag::err_pch_modulecache_mismatch) + << SpecificModuleCachePath << ExistingModuleCachePath; + return true; } bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, StringRef SpecificModuleCachePath, bool Complain) { - return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath, - PP.getHeaderSearchInfo().getModuleCachePath(), - Complain ? &Reader.Diags : nullptr, - PP.getLangOpts(), PP.getPreprocessorOpts()); + return checkModuleCachePath(Reader.getFileManager().getVirtualFileSystem(), + SpecificModuleCachePath, + PP.getHeaderSearchInfo().getModuleCachePath(), + Complain ? &Reader.Diags : nullptr, + PP.getLangOpts(), PP.getPreprocessorOpts()); } void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) { @@ -902,6 +908,39 @@ unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) { return serialization::ComputeHash(Sel); } +LocalDeclID LocalDeclID::get(ASTReader &Reader, ModuleFile &MF, DeclID Value) { + LocalDeclID ID(Value); +#ifndef NDEBUG + if (!MF.ModuleOffsetMap.empty()) + Reader.ReadModuleOffsetMap(MF); + + unsigned ModuleFileIndex = ID.getModuleFileIndex(); + unsigned LocalDeclID = ID.getLocalDeclIndex(); + + assert(ModuleFileIndex <= MF.TransitiveImports.size()); + + ModuleFile *OwningModuleFile = + ModuleFileIndex == 0 ? &MF : MF.TransitiveImports[ModuleFileIndex - 1]; + assert(OwningModuleFile); + + unsigned LocalNumDecls = OwningModuleFile->LocalNumDecls; + + if (!ModuleFileIndex) + LocalNumDecls += NUM_PREDEF_DECL_IDS; + + assert(LocalDeclID < LocalNumDecls); +#endif + (void)Reader; + (void)MF; + return ID; +} + +LocalDeclID LocalDeclID::get(ASTReader &Reader, ModuleFile &MF, + unsigned ModuleFileIndex, unsigned LocalDeclID) { + DeclID Value = (DeclID)ModuleFileIndex << 32 | (DeclID)LocalDeclID; + return LocalDeclID::get(Reader, MF, Value); +} + std::pair<unsigned, unsigned> ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) { return readULEBKeyDataLength(d); @@ -912,20 +951,19 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) { using namespace llvm::support; SelectorTable &SelTable = Reader.getContext().Selectors; - unsigned N = - endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d); - IdentifierInfo *FirstII = Reader.getLocalIdentifier( - F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)); + unsigned N = endian::readNext<uint16_t, llvm::endianness::little>(d); + const IdentifierInfo *FirstII = Reader.getLocalIdentifier( + F, endian::readNext<IdentifierID, llvm::endianness::little>(d)); if (N == 0) return SelTable.getNullarySelector(FirstII); else if (N == 1) return SelTable.getUnarySelector(FirstII); - SmallVector<IdentifierInfo *, 16> Args; + SmallVector<const IdentifierInfo *, 16> Args; Args.push_back(FirstII); for (unsigned I = 1; I != N; ++I) Args.push_back(Reader.getLocalIdentifier( - F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d))); + F, endian::readNext<IdentifierID, llvm::endianness::little>(d))); return SelTable.getSelector(N, Args.data()); } @@ -938,11 +976,11 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, data_type Result; Result.ID = Reader.getGlobalSelectorID( - F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)); + F, endian::readNext<uint32_t, llvm::endianness::little>(d)); unsigned FullInstanceBits = - endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d); + endian::readNext<uint16_t, llvm::endianness::little>(d); unsigned FullFactoryBits = - endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d); + endian::readNext<uint16_t, llvm::endianness::little>(d); Result.InstanceBits = FullInstanceBits & 0x3; Result.InstanceHasMoreThanOneDecl = (FullInstanceBits >> 2) & 0x1; Result.FactoryBits = FullFactoryBits & 0x3; @@ -953,16 +991,18 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, // Load instance methods for (unsigned I = 0; I != NumInstanceMethods; ++I) { if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>( - F, - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d))) + F, LocalDeclID::get( + Reader, F, + endian::readNext<DeclID, llvm::endianness::little>(d)))) Result.Instance.push_back(Method); } // Load factory methods for (unsigned I = 0; I != NumFactoryMethods; ++I) { if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>( - F, - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d))) + F, LocalDeclID::get( + Reader, F, + endian::readNext<DeclID, llvm::endianness::little>(d)))) Result.Factory.push_back(Method); } @@ -985,11 +1025,14 @@ ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) { } /// Whether the given identifier is "interesting". -static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II, +static bool isInterestingIdentifier(ASTReader &Reader, const IdentifierInfo &II, bool IsModule) { + bool IsInteresting = + II.getNotableIdentifierID() != tok::NotableIdentifierKind::not_notable || + II.getBuiltinID() != Builtin::ID::NotBuiltin || + II.getObjCKeywordID() != tok::ObjCKeywordKind::objc_not_keyword; return II.hadMacroDefinition() || II.isPoisoned() || - (!IsModule && II.getObjCOrBuiltinID()) || - II.hasRevertedTokenIDToIdentifier() || + (!IsModule && IsInteresting) || II.hasRevertedTokenIDToIdentifier() || (!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) && II.getFETokenInfo()); } @@ -1000,11 +1043,11 @@ static bool readBit(unsigned &Bits) { return Value; } -IdentID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) { +IdentifierID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) { using namespace llvm::support; - unsigned RawID = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d); + IdentifierID RawID = + endian::readNext<IdentifierID, llvm::endianness::little>(d); return Reader.getGlobalIdentifierID(F, RawID >> 1); } @@ -1022,10 +1065,12 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, unsigned DataLen) { using namespace llvm::support; - unsigned RawID = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d); + IdentifierID RawID = + endian::readNext<IdentifierID, llvm::endianness::little>(d); bool IsInteresting = RawID & 0x01; + DataLen -= sizeof(IdentifierID); + // Wipe out the "is interesting" bit. RawID = RawID >> 1; @@ -1038,7 +1083,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, markIdentifierFromAST(Reader, *II); Reader.markIdentifierUpToDate(II); - IdentID ID = Reader.getGlobalIdentifierID(F, RawID); + IdentifierID ID = Reader.getGlobalIdentifierID(F, RawID); if (!IsInteresting) { // For uninteresting identifiers, there's nothing else to do. Just notify // the reader that we've finished loading this identifier. @@ -1047,9 +1092,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, } unsigned ObjCOrBuiltinID = - endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d); - unsigned Bits = - endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d); + endian::readNext<uint16_t, llvm::endianness::little>(d); + unsigned Bits = endian::readNext<uint16_t, llvm::endianness::little>(d); bool CPlusPlusOperatorKeyword = readBit(Bits); bool HasRevertedTokenIDToIdentifier = readBit(Bits); bool Poisoned = readBit(Bits); @@ -1057,7 +1101,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, bool HadMacroDefinition = readBit(Bits); assert(Bits == 0 && "Extra bits in the identifier?"); - DataLen -= 8; + DataLen -= sizeof(uint16_t) * 2; // Set or check the various bits in the IdentifierInfo structure. // Token IDs are read-only. @@ -1078,7 +1122,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // definition. if (HadMacroDefinition) { uint32_t MacroDirectivesOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d); + endian::readNext<uint32_t, llvm::endianness::little>(d); DataLen -= 4; Reader.addPendingMacro(II, &F, MacroDirectivesOffset); @@ -1089,11 +1133,12 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, // Read all of the declarations visible at global scope with this // name. if (DataLen > 0) { - SmallVector<uint32_t, 4> DeclIDs; - for (; DataLen > 0; DataLen -= 4) + SmallVector<GlobalDeclID, 4> DeclIDs; + for (; DataLen > 0; DataLen -= sizeof(DeclID)) DeclIDs.push_back(Reader.getGlobalDeclID( - F, - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d))); + F, LocalDeclID::get( + Reader, F, + endian::readNext<DeclID, llvm::endianness::little>(d)))); Reader.SetGloballyVisibleDecls(II, DeclIDs); } @@ -1155,7 +1200,7 @@ unsigned DeclarationNameKey::getHash() const { break; } - return ID.ComputeHash(); + return ID.computeStableHash(); } ModuleFile * @@ -1163,7 +1208,7 @@ ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) { using namespace llvm::support; uint32_t ModuleFileID = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d); + endian::readNext<uint32_t, llvm::endianness::little>(d); return Reader.getLocalModuleFile(F, ModuleFileID); } @@ -1183,18 +1228,15 @@ ASTDeclContextNameLookupTrait::ReadKey(const unsigned char *d, unsigned) { case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXDeductionGuideName: Data = (uint64_t)Reader.getLocalIdentifier( - F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)); + F, endian::readNext<IdentifierID, llvm::endianness::little>(d)); break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - Data = - (uint64_t)Reader - .getLocalSelector( - F, - endian::readNext<uint32_t, llvm::endianness::little, unaligned>( - d)) - .getAsOpaquePtr(); + Data = (uint64_t)Reader + .getLocalSelector( + F, endian::readNext<uint32_t, llvm::endianness::little>(d)) + .getAsOpaquePtr(); break; case DeclarationName::CXXOperatorName: Data = *d++; // OverloadedOperatorKind @@ -1216,10 +1258,10 @@ void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type, data_type_builder &Val) { using namespace llvm::support; - for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) { - uint32_t LocalID = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d); - Val.insert(Reader.getGlobalDeclID(F, LocalID)); + for (unsigned NumDecls = DataLen / sizeof(DeclID); NumDecls; --NumDecls) { + LocalDeclID ID = LocalDeclID::get( + Reader, F, endian::readNext<DeclID, llvm::endianness::little>(d)); + Val.insert(Reader.getGlobalDeclID(F, ID)); } } @@ -1265,9 +1307,8 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, if (!Lex.first) { Lex = std::make_pair( &M, llvm::ArrayRef( - reinterpret_cast<const llvm::support::unaligned_uint32_t *>( - Blob.data()), - Blob.size() / 4)); + reinterpret_cast<const unaligned_decl_id_t *>(Blob.data()), + Blob.size() / sizeof(DeclID))); } DC->setHasExternalLexicalStorage(true); return false; @@ -1276,7 +1317,7 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M, BitstreamCursor &Cursor, uint64_t Offset, - DeclID ID) { + GlobalDeclID ID) { assert(Offset != 0); SavedStreamPosition SavedPosition(Cursor); @@ -1651,15 +1692,14 @@ bool ASTReader::ReadSLocEntry(int ID) { FileCharacter = (SrcMgr::CharacteristicKind)Record[2]; FileID FID = SourceMgr.createFileID(*File, IncludeLoc, FileCharacter, ID, BaseOffset + Record[0]); - SrcMgr::FileInfo &FileInfo = - const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()); + SrcMgr::FileInfo &FileInfo = SourceMgr.getSLocEntry(FID).getFile(); FileInfo.NumCreatedFIDs = Record[5]; if (Record[3]) FileInfo.setHasLineDirectives(); unsigned NumFileDecls = Record[7]; if (NumFileDecls && ContextObj) { - const DeclID *FirstDecl = F->FileSortedDecls + Record[6]; + const unaligned_decl_id_t *FirstDecl = F->FileSortedDecls + Record[6]; assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); FileDeclIDs[FID] = FileDeclsInfo(F, llvm::ArrayRef(FirstDecl, NumFileDecls)); @@ -1695,8 +1735,7 @@ bool ASTReader::ReadSLocEntry(int ID) { 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()); + auto &FileInfo = SourceMgr.getSLocEntry(FID).getFile(); FileInfo.setHasLineDirectives(); } break; @@ -1993,7 +2032,10 @@ const FileEntry *HeaderFileInfoTrait::getFile(const internal_key_type &Key) { } unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) { - return llvm::hash_combine(ikey.Size, ikey.ModTime); + uint8_t buf[sizeof(ikey.Size) + sizeof(ikey.ModTime)]; + memcpy(buf, &ikey.Size, sizeof(ikey.Size)); + memcpy(buf + sizeof(ikey.Size), &ikey.ModTime, sizeof(ikey.ModTime)); + return llvm::xxh3_64bits(buf); } HeaderFileInfoTrait::internal_key_type @@ -2027,10 +2069,9 @@ HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) { using namespace llvm::support; internal_key_type ikey; - ikey.Size = - off_t(endian::readNext<uint64_t, llvm::endianness::little, unaligned>(d)); - ikey.ModTime = time_t( - endian::readNext<uint64_t, llvm::endianness::little, unaligned>(d)); + ikey.Size = off_t(endian::readNext<uint64_t, llvm::endianness::little>(d)); + ikey.ModTime = + time_t(endian::readNext<uint64_t, llvm::endianness::little>(d)); ikey.Filename = (const char *)d; ikey.Imported = true; return ikey; @@ -2057,10 +2098,10 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, HFI.isPragmaOnce |= (Flags >> 4) & 0x01; HFI.DirInfo = (Flags >> 1) & 0x07; HFI.IndexHeaderMapHeader = Flags & 0x01; - HFI.ControllingMacroID = Reader.getGlobalIdentifierID( - M, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)); + HFI.LazyControllingMacro = Reader.getGlobalIdentifierID( + M, endian::readNext<IdentifierID, llvm::endianness::little>(d)); if (unsigned FrameworkOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)) { + endian::readNext<uint32_t, llvm::endianness::little>(d)) { // The framework offset is 1 greater than the actual offset, // since 0 is used as an indicator for "no framework name". StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1); @@ -2071,7 +2112,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { uint32_t LocalSMID = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d); + endian::readNext<uint32_t, llvm::endianness::little>(d); auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 7); LocalSMID >>= 3; @@ -2091,7 +2132,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, Module::Header H = {std::string(key.Filename), "", *FE}; ModMap.addHeader(Mod, H, HeaderRole, /*Imported=*/true); } - HFI.isModuleHeader |= ModuleMap::isModular(HeaderRole); + HFI.mergeModuleMembership(HeaderRole); } // This HeaderFileInfo was externally loaded. @@ -2224,7 +2265,7 @@ namespace { } // namespace -void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) { +void ASTReader::updateOutOfDateIdentifier(const IdentifierInfo &II) { // Note that we are loading an identifier. Deserializing AnIdentifier(this); @@ -2249,11 +2290,11 @@ void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) { markIdentifierUpToDate(&II); } -void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { +void ASTReader::markIdentifierUpToDate(const IdentifierInfo *II) { if (!II) return; - II->setOutOfDate(false); + const_cast<IdentifierInfo *>(II)->setOutOfDate(false); // Update the generation for this identifier. if (getContext().getLangOpts().Modules) @@ -2587,7 +2628,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { "We should only check the content of the inputs with " "ValidateASTInputFilesContent enabled."); - if (StoredContentHash == static_cast<uint64_t>(llvm::hash_code(-1))) + if (StoredContentHash == 0) return OriginalChange; auto MemBuffOrError = FileMgr.getBufferForFile(*File); @@ -2601,8 +2642,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { return OriginalChange; } - // FIXME: hash_value is not guaranteed to be stable! - auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer()); + auto ContentHash = xxh3_64bits(MemBuffOrError.get()->getBuffer()); if (StoredContentHash == static_cast<uint64_t>(ContentHash)) return Change{Change::None}; @@ -2635,6 +2675,14 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { F.StandardCXXModule && FileChange.Kind == Change::None) FileChange = HasInputContentChanged(FileChange); + // When we have StoredTime equal to zero and ValidateASTInputFilesContent, + // it is better to check the content of the input files because we cannot rely + // on the file modification time, which will be the same (zero) for these + // files. + if (!StoredTime && ValidateASTInputFilesContent && + FileChange.Kind == Change::None) + FileChange = HasInputContentChanged(FileChange); + // For an overridden file, there is nothing to validate. if (!Overridden && FileChange.Kind != Change::None) { if (Complain && !Diags.isDiagnosticInFlight()) { @@ -3035,8 +3083,10 @@ ASTReader::ReadControlBlock(ModuleFile &F, // 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. - SourceLocation ImportLoc = + auto [ImportLoc, ImportModuleFileIndex] = ReadUntranslatedSourceLocation(Record[Idx++]); + // The import location must belong to the current module file itself. + assert(ImportModuleFileIndex == 0); off_t StoredSize = !IsImportingStdCXXModule ? (off_t)Record[Idx++] : 0; time_t StoredModTime = !IsImportingStdCXXModule ? (time_t)Record[Idx++] : 0; @@ -3344,22 +3394,13 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, return llvm::createStringError( std::errc::illegal_byte_sequence, "duplicate TYPE_OFFSET record in AST file"); - F.TypeOffsets = reinterpret_cast<const UnderalignedInt64 *>(Blob.data()); + F.TypeOffsets = reinterpret_cast<const UnalignedUInt64 *>(Blob.data()); F.LocalNumTypes = Record[0]; - unsigned LocalBaseTypeIndex = Record[1]; F.BaseTypeIndex = getTotalNumTypes(); - if (F.LocalNumTypes > 0) { - // Introduce the global -> local mapping for types within this module. - GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F)); - - // Introduce the local -> global mapping for types within this module. - F.TypeRemap.insertOrReplace( - std::make_pair(LocalBaseTypeIndex, - F.BaseTypeIndex - LocalBaseTypeIndex)); - + if (F.LocalNumTypes > 0) TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes); - } + break; } @@ -3370,35 +3411,19 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, "duplicate DECL_OFFSET record in AST file"); F.DeclOffsets = (const DeclOffset *)Blob.data(); F.LocalNumDecls = Record[0]; - unsigned LocalBaseDeclID = Record[1]; - F.BaseDeclID = getTotalNumDecls(); - - if (F.LocalNumDecls > 0) { - // Introduce the global -> local mapping for declarations within this - // module. - GlobalDeclMap.insert( - std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F)); - - // Introduce the local -> global mapping for declarations within this - // module. - F.DeclRemap.insertOrReplace( - std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID)); - - // Introduce the global -> local mapping for declarations within this - // module. - F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID; + F.BaseDeclIndex = getTotalNumDecls(); + if (F.LocalNumDecls > 0) DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls); - } + break; } case TU_UPDATE_LEXICAL: { DeclContext *TU = ContextObj->getTranslationUnitDecl(); LexicalContents Contents( - reinterpret_cast<const llvm::support::unaligned_uint32_t *>( - Blob.data()), - static_cast<unsigned int>(Blob.size() / 4)); + reinterpret_cast<const unaligned_decl_id_t *>(Blob.data()), + static_cast<unsigned int>(Blob.size() / sizeof(DeclID))); TULexicalDecls.push_back(std::make_pair(&F, Contents)); TU->setHasExternalLexicalStorage(true); break; @@ -3406,7 +3431,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case UPDATE_VISIBLE: { unsigned Idx = 0; - serialization::DeclID ID = ReadDeclID(F, Record, Idx); + GlobalDeclID ID = ReadDeclID(F, Record, Idx); auto *Data = (const unsigned char*)Blob.data(); PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&F, Data}); // If we've already loaded the decl, perform the updates when we finish @@ -3438,24 +3463,11 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, "duplicate IDENTIFIER_OFFSET record in AST file"); F.IdentifierOffsets = (const uint32_t *)Blob.data(); F.LocalNumIdentifiers = Record[0]; - unsigned LocalBaseIdentifierID = Record[1]; F.BaseIdentifierID = getTotalNumIdentifiers(); - if (F.LocalNumIdentifiers > 0) { - // Introduce the global -> local mapping for identifiers within this - // module. - GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1, - &F)); - - // Introduce the local -> global mapping for identifiers within this - // module. - F.IdentifierRemap.insertOrReplace( - std::make_pair(LocalBaseIdentifierID, - F.BaseIdentifierID - LocalBaseIdentifierID)); - + if (F.LocalNumIdentifiers > 0) IdentifiersLoaded.resize(IdentifiersLoaded.size() + F.LocalNumIdentifiers); - } break; } @@ -3466,8 +3478,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case EAGERLY_DESERIALIZED_DECLS: // FIXME: Skip reading this record if our ASTConsumer doesn't care // about "interesting" decls (for instance, if we're building a module). - for (unsigned I = 0, N = Record.size(); I != N; ++I) - EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + EagerlyDeserializedDecls.push_back(ReadDeclID(F, Record, I)); break; case MODULAR_CODEGEN_DECLS: @@ -3475,8 +3487,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, // them (ie: if we're not codegenerating this module). if (F.Kind == MK_MainFile || getContext().getLangOpts().BuildingPCHWithObjectFile) - for (unsigned I = 0, N = Record.size(); I != N; ++I) - EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + EagerlyDeserializedDecls.push_back(ReadDeclID(F, Record, I)); break; case SPECIAL_TYPES: @@ -3507,13 +3519,13 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; case UNUSED_FILESCOPED_DECLS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + UnusedFileScopedDecls.push_back(ReadDeclID(F, Record, I)); break; case DELEGATING_CTORS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + DelegatingCtorDecls.push_back(ReadDeclID(F, Record, I)); break; case WEAK_UNDECLARED_IDENTIFIERS: @@ -3588,6 +3600,17 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; } + case PP_UNSAFE_BUFFER_USAGE: { + if (!Record.empty()) { + SmallVector<SourceLocation, 64> SrcLocs; + unsigned Idx = 0; + while (Idx < Record.size()) + SrcLocs.push_back(ReadSourceLocation(F, Record, Idx)); + PP.setDeserializedSafeBufferOptOutMap(SrcLocs); + } + break; + } + case PP_CONDITIONAL_STACK: if (!Record.empty()) { unsigned Idx = 0, End = Record.size() - 1; @@ -3621,7 +3644,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; case FILE_SORTED_DECLS: - F.FileSortedDecls = (const DeclID *)Blob.data(); + F.FileSortedDecls = (const unaligned_decl_id_t *)Blob.data(); F.NumFileSortedDecls = Record[0]; break; @@ -3655,13 +3678,6 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, std::make_pair(SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset - SLocSpaceSize,&F)); - // Initialize the remapping table. - // Invalid stays invalid. - F.SLocRemap.insertOrReplace(std::make_pair(0U, 0)); - // This module. Base was 2 when being compiled. - F.SLocRemap.insertOrReplace(std::make_pair( - 2U, static_cast<SourceLocation::IntTy>(F.SLocEntryBaseOffset - 2))); - TotalNumSLocEntries += F.LocalNumSLocEntries; break; } @@ -3675,8 +3691,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; case EXT_VECTOR_DECLS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + ExtVectorDecls.push_back(ReadDeclID(F, Record, I)); break; case VTABLE_USES: @@ -3690,18 +3706,14 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, VTableUses.clear(); for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) { - VTableUses.push_back(getGlobalDeclID(F, Record[Idx++])); VTableUses.push_back( - ReadSourceLocation(F, Record, Idx).getRawEncoding()); - VTableUses.push_back(Record[Idx++]); + {ReadDeclID(F, Record, Idx), + ReadSourceLocation(F, Record, Idx).getRawEncoding(), + (bool)Record[Idx++]}); } break; case PENDING_IMPLICIT_INSTANTIATIONS: - if (PendingInstantiations.size() % 2 != 0) - return llvm::createStringError( - std::errc::illegal_byte_sequence, - "Invalid existing PendingInstantiations"); if (Record.size() % 2 != 0) return llvm::createStringError( @@ -3709,9 +3721,9 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, "Invalid PENDING_IMPLICIT_INSTANTIATIONS block"); for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { - PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++])); PendingInstantiations.push_back( - ReadSourceLocation(F, Record, I).getRawEncoding()); + {ReadDeclID(F, Record, I), + ReadSourceLocation(F, Record, I).getRawEncoding()}); } break; @@ -3719,8 +3731,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, if (Record.size() != 3) return llvm::createStringError(std::errc::illegal_byte_sequence, "Invalid SEMA_DECL_REFS block"); - for (unsigned I = 0, N = Record.size(); I != N; ++I) - SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + SemaDeclRefs.push_back(ReadDeclID(F, Record, I)); break; case PPD_ENTITIES_OFFSETS: { @@ -3778,9 +3790,9 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, return llvm::createStringError( std::errc::illegal_byte_sequence, "invalid DECL_UPDATE_OFFSETS block in AST file"); - for (unsigned I = 0, N = Record.size(); I != N; I += 2) { - GlobalDeclID ID = getGlobalDeclID(F, Record[I]); - DeclUpdateOffsets[ID].push_back(std::make_pair(&F, Record[I + 1])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) { + GlobalDeclID ID = ReadDeclID(F, Record, I); + DeclUpdateOffsets[ID].push_back(std::make_pair(&F, Record[I++])); // If we've already loaded the decl, perform the updates when we finish // loading this block. @@ -3790,6 +3802,33 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, } break; + case DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD: { + if (Record.size() % 3 != 0) + return llvm::createStringError( + std::errc::illegal_byte_sequence, + "invalid DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD block in AST " + "file"); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) { + GlobalDeclID ID = ReadDeclID(F, Record, I); + + uint64_t BaseOffset = F.DeclsBlockStartOffset; + assert(BaseOffset && "Invalid DeclsBlockStartOffset for module file!"); + uint64_t LocalLexicalOffset = Record[I++]; + uint64_t LexicalOffset = + LocalLexicalOffset ? BaseOffset + LocalLexicalOffset : 0; + uint64_t LocalVisibleOffset = Record[I++]; + uint64_t VisibleOffset = + LocalVisibleOffset ? BaseOffset + LocalVisibleOffset : 0; + + DelayedNamespaceOffsetMap[ID] = {LexicalOffset, VisibleOffset}; + + assert(!GetExistingDecl(ID) && + "We shouldn't load the namespace in the front of delayed " + "namespace lexical and visible block"); + } + break; + } + case OBJC_CATEGORIES_MAP: if (F.LocalNumObjCCategoriesInMap != 0) return llvm::createStringError( @@ -3808,8 +3847,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, // Later tables overwrite earlier ones. // FIXME: Modules will have trouble with this. CUDASpecialDeclRefs.clear(); - for (unsigned I = 0, N = Record.size(); I != N; ++I) - CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + CUDASpecialDeclRefs.push_back(ReadDeclID(F, Record, I)); break; case HEADER_SEARCH_TABLE: @@ -3849,33 +3888,29 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; case TENTATIVE_DEFINITIONS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + TentativeDefinitions.push_back(ReadDeclID(F, Record, I)); break; case KNOWN_NAMESPACES: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - KnownNamespaces.push_back(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + KnownNamespaces.push_back(ReadDeclID(F, Record, I)); break; case UNDEFINED_BUT_USED: - if (UndefinedButUsed.size() % 2 != 0) - return llvm::createStringError(std::errc::illegal_byte_sequence, - "Invalid existing UndefinedButUsed"); - if (Record.size() % 2 != 0) return llvm::createStringError(std::errc::illegal_byte_sequence, "invalid undefined-but-used record"); for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) { - UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++])); UndefinedButUsed.push_back( - ReadSourceLocation(F, Record, I).getRawEncoding()); + {ReadDeclID(F, Record, I), + ReadSourceLocation(F, Record, I).getRawEncoding()}); } break; case DELETE_EXPRS_TO_ANALYZE: for (unsigned I = 0, N = Record.size(); I != N;) { - DelayedDeleteExprs.push_back(getGlobalDeclID(F, Record[I++])); + DelayedDeleteExprs.push_back(ReadDeclID(F, Record, I).getRawValue()); const uint64_t Count = Record[I++]; DelayedDeleteExprs.push_back(Count); for (uint64_t C = 0; C < Count; ++C) { @@ -3958,16 +3993,15 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; case UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - UnusedLocalTypedefNameCandidates.push_back( - getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + UnusedLocalTypedefNameCandidates.push_back(ReadDeclID(F, Record, I)); break; case CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH: if (Record.size() != 1) return llvm::createStringError(std::errc::illegal_byte_sequence, "invalid cuda pragma options record"); - ForceCUDAHostDeviceDepth = Record[0]; + ForceHostDeviceDepth = Record[0]; break; case ALIGN_PACK_PRAGMA_OPTIONS: { @@ -4015,8 +4049,8 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, } case DECLS_TO_CHECK_FOR_DEFERRED_DIAGS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - DeclsToCheckForDeferredDiags.insert(getGlobalDeclID(F, Record[I])); + for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) + DeclsToCheckForDeferredDiags.insert(ReadDeclID(F, Record, I)); break; } } @@ -4030,25 +4064,14 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { const unsigned char *DataEnd = Data + F.ModuleOffsetMap.size(); F.ModuleOffsetMap = StringRef(); - // If we see this entry before SOURCE_LOCATION_OFFSETS, add placeholders. - if (F.SLocRemap.find(0) == F.SLocRemap.end()) { - F.SLocRemap.insert(std::make_pair(0U, 0)); - F.SLocRemap.insert(std::make_pair(2U, 1)); - } - - // Continuous range maps we may be updating in our module. - using SLocRemapBuilder = - ContinuousRangeMap<SourceLocation::UIntTy, SourceLocation::IntTy, - 2>::Builder; using RemapBuilder = ContinuousRangeMap<uint32_t, int, 2>::Builder; - SLocRemapBuilder SLocRemap(F.SLocRemap); - RemapBuilder IdentifierRemap(F.IdentifierRemap); RemapBuilder MacroRemap(F.MacroRemap); RemapBuilder PreprocessedEntityRemap(F.PreprocessedEntityRemap); RemapBuilder SubmoduleRemap(F.SubmoduleRemap); RemapBuilder SelectorRemap(F.SelectorRemap); - RemapBuilder DeclRemap(F.DeclRemap); - RemapBuilder TypeRemap(F.TypeRemap); + + auto &ImportedModuleVector = F.TransitiveImports; + assert(ImportedModuleVector.empty()); while (Data < DataEnd) { // FIXME: Looking up dependency modules by filename is horrible. Let's @@ -4056,9 +4079,8 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { // how it goes... using namespace llvm::support; ModuleKind Kind = static_cast<ModuleKind>( - endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data)); - uint16_t Len = - endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); + endian::readNext<uint8_t, llvm::endianness::little>(Data)); + uint16_t Len = endian::readNext<uint16_t, llvm::endianness::little>(Data); StringRef Name = StringRef((const char*)Data, Len); Data += Len; ModuleFile *OM = (Kind == MK_PrebuiltModule || Kind == MK_ExplicitModule || @@ -4066,29 +4088,22 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { ? ModuleMgr.lookupByModuleName(Name) : ModuleMgr.lookupByFileName(Name)); if (!OM) { - std::string Msg = - "SourceLocation remap refers to unknown module, cannot find "; + std::string Msg = "refers to unknown module, cannot find "; Msg.append(std::string(Name)); Error(Msg); return; } - SourceLocation::UIntTy SLocOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); - uint32_t IdentifierIDOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); + ImportedModuleVector.push_back(OM); + uint32_t MacroIDOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); + endian::readNext<uint32_t, llvm::endianness::little>(Data); uint32_t PreprocessedEntityIDOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); + endian::readNext<uint32_t, llvm::endianness::little>(Data); uint32_t SubmoduleIDOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); + endian::readNext<uint32_t, llvm::endianness::little>(Data); uint32_t SelectorIDOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); - uint32_t DeclIDOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); - uint32_t TypeIndexOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); + endian::readNext<uint32_t, llvm::endianness::little>(Data); auto mapOffset = [&](uint32_t Offset, uint32_t BaseOffset, RemapBuilder &Remap) { @@ -4098,24 +4113,11 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { static_cast<int>(BaseOffset - Offset))); }; - constexpr SourceLocation::UIntTy SLocNone = - std::numeric_limits<SourceLocation::UIntTy>::max(); - if (SLocOffset != SLocNone) - SLocRemap.insert(std::make_pair( - SLocOffset, static_cast<SourceLocation::IntTy>( - OM->SLocEntryBaseOffset - SLocOffset))); - - mapOffset(IdentifierIDOffset, OM->BaseIdentifierID, IdentifierRemap); mapOffset(MacroIDOffset, OM->BaseMacroID, MacroRemap); mapOffset(PreprocessedEntityIDOffset, OM->BasePreprocessedEntityID, PreprocessedEntityRemap); mapOffset(SubmoduleIDOffset, OM->BaseSubmoduleID, SubmoduleRemap); mapOffset(SelectorIDOffset, OM->BaseSelectorID, SelectorRemap); - mapOffset(DeclIDOffset, OM->BaseDeclID, DeclRemap); - mapOffset(TypeIndexOffset, OM->BaseTypeIndex, TypeRemap); - - // Global -> local mappings. - F.GlobalToLocalDeclIDs[OM] = DeclIDOffset; } } @@ -4229,9 +4231,9 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, /// Move the given method to the back of the global list of methods. static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { // Find the entry for this selector in the method pool. - Sema::GlobalMethodPool::iterator Known - = S.MethodPool.find(Method->getSelector()); - if (Known == S.MethodPool.end()) + SemaObjC::GlobalMethodPool::iterator Known = + S.ObjC().MethodPool.find(Method->getSelector()); + if (Known == S.ObjC().MethodPool.end()) return; // Retrieve the appropriate method list. @@ -4641,8 +4643,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ModuleKind Type, if (ContextObj) { for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) { loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), - ObjCClassesLoaded[I], - PreviousGeneration); + ObjCClassesLoaded[I], PreviousGeneration); } } @@ -4977,7 +4978,7 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl( } case HEADER_SEARCH_PATHS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; - if (!AllowCompatibleConfigurationMismatch && + if (Listener && !AllowCompatibleConfigurationMismatch && ParseHeaderSearchPaths(Record, Complain, *Listener)) Result = ConfigurationMismatch; break; @@ -4992,15 +4993,12 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl( Record.begin(), Record.end()); break; case HEADER_SEARCH_ENTRY_USAGE: - if (!F) - break; - unsigned Count = Record[0]; - const char *Byte = Blob.data(); - F->SearchPathUsage = llvm::BitVector(Count, false); - for (unsigned I = 0; I < Count; ++Byte) - for (unsigned Bit = 0; Bit < 8 && I < Count; ++Bit, ++I) - if (*Byte & (1 << Bit)) - F->SearchPathUsage[I] = true; + if (F) + F->SearchPathUsage = ReadBitVector(Record, Blob); + break; + case VFS_USAGE: + if (F) + F->VFSUsage = ReadBitVector(Record, Blob); break; } } @@ -5089,20 +5087,21 @@ void ASTReader::InitializeContext() { // If there's a listener, notify them that we "read" the translation unit. if (DeserializationListener) - DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, - Context.getTranslationUnitDecl()); + DeserializationListener->DeclRead( + GlobalDeclID(PREDEF_DECL_TRANSLATION_UNIT_ID), + Context.getTranslationUnitDecl()); // FIXME: Find a better way to deal with collisions between these // built-in types. Right now, we just ignore the problem. // Load the special types. if (SpecialTypes.size() >= NumSpecialTypeIDs) { - if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) { + if (TypeID String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) { if (!Context.CFConstantStringTypeDecl) Context.setCFConstantStringType(GetType(String)); } - if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) { + if (TypeID File = SpecialTypes[SPECIAL_TYPE_FILE]) { QualType FileType = GetType(File); if (FileType.isNull()) { Error("FILE type is NULL"); @@ -5123,7 +5122,7 @@ void ASTReader::InitializeContext() { } } - if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) { + if (TypeID Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) { QualType Jmp_bufType = GetType(Jmp_buf); if (Jmp_bufType.isNull()) { Error("jmp_buf type is NULL"); @@ -5144,7 +5143,7 @@ void ASTReader::InitializeContext() { } } - if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) { + if (TypeID Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) { QualType Sigjmp_bufType = GetType(Sigjmp_buf); if (Sigjmp_bufType.isNull()) { Error("sigjmp_buf type is NULL"); @@ -5162,25 +5161,24 @@ void ASTReader::InitializeContext() { } } - if (unsigned ObjCIdRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) { + if (TypeID ObjCIdRedef = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) { if (Context.ObjCIdRedefinitionType.isNull()) Context.ObjCIdRedefinitionType = GetType(ObjCIdRedef); } - if (unsigned ObjCClassRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) { + if (TypeID ObjCClassRedef = + SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) { if (Context.ObjCClassRedefinitionType.isNull()) Context.ObjCClassRedefinitionType = GetType(ObjCClassRedef); } - if (unsigned ObjCSelRedef - = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) { + if (TypeID ObjCSelRedef = + SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) { if (Context.ObjCSelRedefinitionType.isNull()) Context.ObjCSelRedefinitionType = GetType(ObjCSelRedef); } - if (unsigned Ucontext_t = SpecialTypes[SPECIAL_TYPE_UCONTEXT_T]) { + if (TypeID Ucontext_t = SpecialTypes[SPECIAL_TYPE_UCONTEXT_T]) { QualType Ucontext_tType = GetType(Ucontext_t); if (Ucontext_tType.isNull()) { Error("ucontext_t type is NULL"); @@ -5376,9 +5374,9 @@ namespace { bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, StringRef SpecificModuleCachePath, bool Complain) override { - return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath, - ExistingModuleCachePath, nullptr, - ExistingLangOpts, ExistingPPOpts); + return checkModuleCachePath( + FileMgr.getVirtualFileSystem(), SpecificModuleCachePath, + ExistingModuleCachePath, nullptr, ExistingLangOpts, ExistingPPOpts); } bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, @@ -5398,7 +5396,8 @@ bool ASTReader::readASTFileControlBlock( StringRef Filename, FileManager &FileMgr, const InMemoryModuleCache &ModuleCache, const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, - ASTReaderListener &Listener, bool ValidateDiagnosticOptions) { + ASTReaderListener &Listener, bool ValidateDiagnosticOptions, + unsigned ClientLoadCapabilities) { // Open the AST file. std::unique_ptr<llvm::MemoryBuffer> OwnedBuffer; llvm::MemoryBuffer *Buffer = ModuleCache.lookupPCM(Filename); @@ -5453,7 +5452,7 @@ bool ASTReader::readASTFileControlBlock( switch (Entry.ID) { case OPTIONS_BLOCK_ID: { std::string IgnoredSuggestedPredefines; - if (ReadOptionsBlock(Stream, ARR_ConfigurationMismatch | ARR_OutOfDate, + if (ReadOptionsBlock(Stream, ClientLoadCapabilities, /*AllowCompatibleConfigurationMismatch*/ false, Listener, IgnoredSuggestedPredefines) != Success) return true; @@ -5679,7 +5678,7 @@ bool ASTReader::readASTFileControlBlock( // Scan for the UNHASHED_CONTROL_BLOCK_ID block. if (readUnhashedControlBlockImpl( - nullptr, Bytes, ARR_ConfigurationMismatch | ARR_OutOfDate, + nullptr, Bytes, ClientLoadCapabilities, /*AllowCompatibleConfigurationMismatch*/ false, &Listener, ValidateDiagnosticOptions) != Success) return true; @@ -5997,9 +5996,9 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, case SUBMODULE_INITIALIZERS: { if (!ContextObj) break; - SmallVector<uint32_t, 16> Inits; - for (auto &ID : Record) - Inits.push_back(getGlobalDeclID(F, ID)); + SmallVector<GlobalDeclID, 16> Inits; + for (unsigned I = 0; I < Record.size(); /*in loop*/) + Inits.push_back(ReadDeclID(F, Record, I)); ContextObj->addLazyModuleInitializers(CurrentModule, Inits); break; } @@ -6242,8 +6241,8 @@ SourceRange ASTReader::ReadSkippedRange(unsigned GlobalIndex) { unsigned LocalIndex = GlobalIndex - M->BasePreprocessedSkippedRangeID; assert(LocalIndex < M->NumPreprocessedSkippedRanges); PPSkippedRange RawRange = M->PreprocessedSkippedRangeOffsets[LocalIndex]; - SourceRange Range(TranslateSourceLocation(*M, RawRange.getBegin()), - TranslateSourceLocation(*M, RawRange.getEnd())); + SourceRange Range(ReadSourceLocation(*M, RawRange.getBegin()), + ReadSourceLocation(*M, RawRange.getEnd())); assert(Range.isValid()); return Range; } @@ -6262,7 +6261,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); if (llvm::Error Err = M.PreprocessorDetailCursor.JumpToBit( - M.MacroOffsetsBase + PPOffs.BitOffset)) { + M.MacroOffsetsBase + PPOffs.getOffset())) { Error(std::move(Err)); return nullptr; } @@ -6279,8 +6278,8 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { return nullptr; // Read the record. - SourceRange Range(TranslateSourceLocation(M, PPOffs.getBegin()), - TranslateSourceLocation(M, PPOffs.getEnd())); + SourceRange Range(ReadSourceLocation(M, PPOffs.getBegin()), + ReadSourceLocation(M, PPOffs.getEnd())); PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); StringRef Blob; RecordData Record; @@ -6392,7 +6391,7 @@ struct PPEntityComp { } SourceLocation getLoc(const PPEntityOffset &PPE) const { - return Reader.TranslateSourceLocation(M, PPE.getBegin()); + return Reader.ReadSourceLocation(M, PPE.getBegin()); } }; @@ -6436,7 +6435,7 @@ PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc, PPI = First; std::advance(PPI, Half); if (SourceMgr.isBeforeInTranslationUnit( - TranslateSourceLocation(M, PPI->getEnd()), Loc)) { + ReadSourceLocation(M, PPI->getEnd()), Loc)) { First = PPI; ++First; Count = Count - Half - 1; @@ -6477,7 +6476,7 @@ std::optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, unsigned LocalIndex = PPInfo.second; const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex]; - SourceLocation Loc = TranslateSourceLocation(M, PPOffs.getBegin()); + SourceLocation Loc = ReadSourceLocation(M, PPOffs.getBegin()); if (Loc.isInvalid()) return false; @@ -6621,17 +6620,15 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { while (NumLocations--) { assert(Idx < Record.size() && "Invalid data, missing pragma diagnostic states"); - SourceLocation Loc = ReadSourceLocation(F, Record[Idx++]); - auto IDAndOffset = SourceMgr.getDecomposedLoc(Loc); - assert(IDAndOffset.first.isValid() && "invalid FileID for transition"); - assert(IDAndOffset.second == 0 && "not a start location for a FileID"); + FileID FID = ReadFileID(F, Record, Idx); + assert(FID.isValid() && "invalid FileID for transition"); unsigned Transitions = Record[Idx++]; // Note that we don't need to set up Parent/ParentOffset here, because // we won't be changing the diagnostic state within imported FileIDs // (other than perhaps appending to the main source file, which has no // parent). - auto &F = Diag.DiagStatesByLoc.Files[IDAndOffset.first]; + auto &F = Diag.DiagStatesByLoc.Files[FID]; F.StateTransitions.reserve(F.StateTransitions.size() + Transitions); for (unsigned I = 0; I != Transitions; ++I) { unsigned Offset = Record[Idx++]; @@ -6666,13 +6663,10 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { } /// Get the correct cursor and offset for loading a type. -ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { - GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index); - assert(I != GlobalTypeMap.end() && "Corrupted global type map"); - ModuleFile *M = I->second; - return RecordLocation( - M, M->TypeOffsets[Index - M->BaseTypeIndex].getBitOffset() + - M->DeclsBlockStartOffset); +ASTReader::RecordLocation ASTReader::TypeCursorForIndex(TypeID ID) { + auto [M, Index] = translateTypeIDToIndex(ID); + return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex].get() + + M->DeclsBlockStartOffset); } static std::optional<Type::TypeClass> getTypeClassForCode(TypeCode code) { @@ -6691,10 +6685,10 @@ static std::optional<Type::TypeClass> getTypeClassForCode(TypeCode code) { /// routine actually reads the record corresponding to the type at the given /// location. It is a helper routine for GetType, which deals with reading type /// IDs. -QualType ASTReader::readTypeRecord(unsigned Index) { +QualType ASTReader::readTypeRecord(TypeID ID) { assert(ContextObj && "reading type with no AST context"); ASTContext &Context = *ContextObj; - RecordLocation Loc = TypeCursorForIndex(Index); + RecordLocation Loc = TypeCursorForIndex(ID); BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; // Keep track of where we are in the stream, then jump back there @@ -6809,6 +6803,10 @@ void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing to do } +void TypeLocReader::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) { + // nothing to do +} + void TypeLocReader::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) { TL.setExpansionLoc(readSourceLocation()); } @@ -6946,6 +6944,10 @@ void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { TL.setRParenLoc(readSourceLocation()); } +void TypeLocReader::VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) { + TL.setEllipsisLoc(readSourceLocation()); +} + void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { TL.setKWLoc(readSourceLocation()); TL.setLParenLoc(readSourceLocation()); @@ -6990,6 +6992,10 @@ void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { TL.setAttr(ReadAttr()); } +void TypeLocReader::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { + // Nothing to do +} + void TypeLocReader::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { // Nothing to do. } @@ -7123,15 +7129,44 @@ TypeSourceInfo *ASTRecordReader::readTypeSourceInfo() { return TInfo; } +static unsigned getIndexForTypeID(serialization::TypeID ID) { + return (ID & llvm::maskTrailingOnes<TypeID>(32)) >> Qualifiers::FastWidth; +} + +static unsigned getModuleFileIndexForTypeID(serialization::TypeID ID) { + return ID >> 32; +} + +static bool isPredefinedType(serialization::TypeID ID) { + // We don't need to erase the higher bits since if these bits are not 0, + // it must be larger than NUM_PREDEF_TYPE_IDS. + return (ID >> Qualifiers::FastWidth) < NUM_PREDEF_TYPE_IDS; +} + +std::pair<ModuleFile *, unsigned> +ASTReader::translateTypeIDToIndex(serialization::TypeID ID) const { + assert(!isPredefinedType(ID) && + "Predefined type shouldn't be in TypesLoaded"); + unsigned ModuleFileIndex = getModuleFileIndexForTypeID(ID); + assert(ModuleFileIndex && "Untranslated Local Decl?"); + + ModuleFile *OwningModuleFile = &getModuleManager()[ModuleFileIndex - 1]; + assert(OwningModuleFile && + "untranslated type ID or local type ID shouldn't be in TypesLoaded"); + + return {OwningModuleFile, + OwningModuleFile->BaseTypeIndex + getIndexForTypeID(ID)}; +} + QualType ASTReader::GetType(TypeID ID) { assert(ContextObj && "reading type with no AST context"); ASTContext &Context = *ContextObj; unsigned FastQuals = ID & Qualifiers::FastMask; - unsigned Index = ID >> Qualifiers::FastWidth; - if (Index < NUM_PREDEF_TYPE_IDS) { + if (isPredefinedType(ID)) { QualType T; + unsigned Index = getIndexForTypeID(ID); switch ((PredefinedTypeIDs)Index) { case PREDEF_TYPE_LAST_ID: // We should never use this one. @@ -7288,6 +7323,9 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break; + case PREDEF_TYPE_UNRESOLVED_TEMPLATE: + T = Context.UnresolvedTemplateTy; + break; case PREDEF_TYPE_BOUND_MEMBER: T = Context.BoundMemberTy; break; @@ -7361,11 +7399,11 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_INCOMPLETE_MATRIX_IDX: T = Context.IncompleteMatrixIdxTy; break; - case PREDEF_TYPE_OMP_ARRAY_SECTION: - T = Context.OMPArraySectionTy; + case PREDEF_TYPE_ARRAY_SECTION: + T = Context.ArraySectionTy; break; case PREDEF_TYPE_OMP_ARRAY_SHAPING: - T = Context.OMPArraySectionTy; + T = Context.OMPArrayShapingTy; break; case PREDEF_TYPE_OMP_ITERATOR: T = Context.OMPIteratorTy; @@ -7390,16 +7428,22 @@ QualType ASTReader::GetType(TypeID ID) { T = Context.SingletonId; \ break; #include "clang/Basic/WebAssemblyReferenceTypes.def" +#define AMDGPU_TYPE(Name, Id, SingletonId) \ + case PREDEF_TYPE_##Id##_ID: \ + T = Context.SingletonId; \ + break; +#include "clang/Basic/AMDGPUTypes.def" } assert(!T.isNull() && "Unknown predefined type"); return T.withFastQualifiers(FastQuals); } - Index -= NUM_PREDEF_TYPE_IDS; + unsigned Index = translateTypeIDToIndex(ID).second; + assert(Index < TypesLoaded.size() && "Type index out-of-range"); if (TypesLoaded[Index].isNull()) { - TypesLoaded[Index] = readTypeRecord(Index); + TypesLoaded[Index] = readTypeRecord(ID); if (TypesLoaded[Index].isNull()) return QualType(); @@ -7412,27 +7456,28 @@ QualType ASTReader::GetType(TypeID ID) { return TypesLoaded[Index].withFastQualifiers(FastQuals); } -QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) { +QualType ASTReader::getLocalType(ModuleFile &F, LocalTypeID LocalID) { return GetType(getGlobalTypeID(F, LocalID)); } -serialization::TypeID -ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const { - unsigned FastQuals = LocalID & Qualifiers::FastMask; - unsigned LocalIndex = LocalID >> Qualifiers::FastWidth; - - if (LocalIndex < NUM_PREDEF_TYPE_IDS) +serialization::TypeID ASTReader::getGlobalTypeID(ModuleFile &F, + LocalTypeID LocalID) const { + if (isPredefinedType(LocalID)) return LocalID; if (!F.ModuleOffsetMap.empty()) ReadModuleOffsetMap(F); - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = F.TypeRemap.find(LocalIndex - NUM_PREDEF_TYPE_IDS); - assert(I != F.TypeRemap.end() && "Invalid index into type index remap"); + unsigned ModuleFileIndex = getModuleFileIndexForTypeID(LocalID); + LocalID &= llvm::maskTrailingOnes<TypeID>(32); - unsigned GlobalIndex = LocalIndex + I->second; - return (GlobalIndex << Qualifiers::FastWidth) | FastQuals; + if (ModuleFileIndex == 0) + LocalID -= NUM_PREDEF_TYPE_IDS << Qualifiers::FastWidth; + + ModuleFile &MF = + ModuleFileIndex ? *F.TransitiveImports[ModuleFileIndex - 1] : F; + ModuleFileIndex = MF.Index + 1; + return ((uint64_t)ModuleFileIndex << 32) | LocalID; } TemplateArgumentLocInfo @@ -7494,9 +7539,7 @@ ASTRecordReader::readASTTemplateArgumentListInfo() { return ASTTemplateArgumentListInfo::Create(getContext(), Result); } -Decl *ASTReader::GetExternalDecl(uint32_t ID) { - return GetDecl(ID); -} +Decl *ASTReader::GetExternalDecl(GlobalDeclID ID) { return GetDecl(ID); } void ASTReader::CompleteRedeclChain(const Decl *D) { if (NumCurrentElementsDeserializing) { @@ -7629,51 +7672,61 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { return Bases; } -serialization::DeclID -ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const { +GlobalDeclID ASTReader::getGlobalDeclID(ModuleFile &F, + LocalDeclID LocalID) const { if (LocalID < NUM_PREDEF_DECL_IDS) - return LocalID; + return GlobalDeclID(LocalID.getRawValue()); + + unsigned OwningModuleFileIndex = LocalID.getModuleFileIndex(); + DeclID ID = LocalID.getLocalDeclIndex(); if (!F.ModuleOffsetMap.empty()) ReadModuleOffsetMap(F); - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS); - assert(I != F.DeclRemap.end() && "Invalid index into decl index remap"); + ModuleFile *OwningModuleFile = + OwningModuleFileIndex == 0 + ? &F + : F.TransitiveImports[OwningModuleFileIndex - 1]; - return LocalID + I->second; + if (OwningModuleFileIndex == 0) + ID -= NUM_PREDEF_DECL_IDS; + + uint64_t NewModuleFileIndex = OwningModuleFile->Index + 1; + return GlobalDeclID(NewModuleFileIndex, ID); } -bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID, - ModuleFile &M) const { +bool ASTReader::isDeclIDFromModule(GlobalDeclID ID, ModuleFile &M) const { // Predefined decls aren't from any module. if (ID < NUM_PREDEF_DECL_IDS) return false; - return ID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID && - ID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls; + unsigned ModuleFileIndex = ID.getModuleFileIndex(); + return M.Index == ModuleFileIndex - 1; } -ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) { +ModuleFile *ASTReader::getOwningModuleFile(GlobalDeclID ID) const { + // Predefined decls aren't from any module. + if (ID < NUM_PREDEF_DECL_IDS) + return nullptr; + + uint64_t ModuleFileIndex = ID.getModuleFileIndex(); + assert(ModuleFileIndex && "Untranslated Local Decl?"); + + return &getModuleManager()[ModuleFileIndex - 1]; +} + +ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) const { if (!D->isFromASTFile()) return nullptr; - GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID()); - assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); - return I->second; + + return getOwningModuleFile(D->getGlobalID()); } SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { if (ID < NUM_PREDEF_DECL_IDS) return SourceLocation(); - unsigned Index = ID - NUM_PREDEF_DECL_IDS; - - if (Index > DeclsLoaded.size()) { - Error("declaration ID out-of-range for AST file"); - return SourceLocation(); - } - - if (Decl *D = DeclsLoaded[Index]) + if (Decl *D = GetExistingDecl(ID)) return D->getLocation(); SourceLocation Loc; @@ -7740,8 +7793,19 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) { llvm_unreachable("PredefinedDeclIDs unknown enum value"); } -Decl *ASTReader::GetExistingDecl(DeclID ID) { +unsigned ASTReader::translateGlobalDeclIDToIndex(GlobalDeclID GlobalID) const { + ModuleFile *OwningModuleFile = getOwningModuleFile(GlobalID); + if (!OwningModuleFile) { + assert(GlobalID < NUM_PREDEF_DECL_IDS && "Untransalted Global ID?"); + return GlobalID.getRawValue(); + } + + return OwningModuleFile->BaseDeclIndex + GlobalID.getLocalDeclIndex(); +} + +Decl *ASTReader::GetExistingDecl(GlobalDeclID ID) { assert(ContextObj && "reading decl with no AST context"); + if (ID < NUM_PREDEF_DECL_IDS) { Decl *D = getPredefinedDecl(*ContextObj, (PredefinedDeclIDs)ID); if (D) { @@ -7754,7 +7818,7 @@ Decl *ASTReader::GetExistingDecl(DeclID ID) { return D; } - unsigned Index = ID - NUM_PREDEF_DECL_IDS; + unsigned Index = translateGlobalDeclIDToIndex(ID); if (Index >= DeclsLoaded.size()) { assert(0 && "declaration ID out-of-range for AST file"); @@ -7765,11 +7829,11 @@ Decl *ASTReader::GetExistingDecl(DeclID ID) { return DeclsLoaded[Index]; } -Decl *ASTReader::GetDecl(DeclID ID) { +Decl *ASTReader::GetDecl(GlobalDeclID ID) { if (ID < NUM_PREDEF_DECL_IDS) return GetExistingDecl(ID); - unsigned Index = ID - NUM_PREDEF_DECL_IDS; + unsigned Index = translateGlobalDeclIDToIndex(ID); if (Index >= DeclsLoaded.size()) { assert(0 && "declaration ID out-of-range for AST file"); @@ -7786,32 +7850,43 @@ Decl *ASTReader::GetDecl(DeclID ID) { return DeclsLoaded[Index]; } -DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, - DeclID GlobalID) { +LocalDeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, + GlobalDeclID GlobalID) { if (GlobalID < NUM_PREDEF_DECL_IDS) - return GlobalID; + return LocalDeclID::get(*this, M, GlobalID.getRawValue()); - GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID); - assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); - ModuleFile *Owner = I->second; + if (!M.ModuleOffsetMap.empty()) + ReadModuleOffsetMap(M); - llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos - = M.GlobalToLocalDeclIDs.find(Owner); - if (Pos == M.GlobalToLocalDeclIDs.end()) - return 0; + ModuleFile *Owner = getOwningModuleFile(GlobalID); + DeclID ID = GlobalID.getLocalDeclIndex(); + + if (Owner == &M) { + ID += NUM_PREDEF_DECL_IDS; + return LocalDeclID::get(*this, M, ID); + } + + uint64_t OrignalModuleFileIndex = 0; + for (unsigned I = 0; I < M.TransitiveImports.size(); I++) + if (M.TransitiveImports[I] == Owner) { + OrignalModuleFileIndex = I + 1; + break; + } + + if (!OrignalModuleFileIndex) + return LocalDeclID(); - return GlobalID - Owner->BaseDeclID + Pos->second; + return LocalDeclID::get(*this, M, OrignalModuleFileIndex, ID); } -serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, - const RecordData &Record, - unsigned &Idx) { +GlobalDeclID ASTReader::ReadDeclID(ModuleFile &F, const RecordDataImpl &Record, + unsigned &Idx) { if (Idx >= Record.size()) { Error("Corrupted AST file"); - return 0; + return GlobalDeclID(0); } - return getGlobalDeclID(F, Record[Idx++]); + return getGlobalDeclID(F, LocalDeclID::get(*this, F, Record[Idx++])); } /// Resolve the offset of a statement into a statement. @@ -7847,7 +7922,7 @@ void ASTReader::FindExternalLexicalDecls( if (!IsKindWeWant(K)) continue; - auto ID = (serialization::DeclID)+LexicalDecls[I + 1]; + auto ID = (DeclID) + LexicalDecls[I + 1]; // Don't add predefined declarations to the lexical context more // than once. @@ -7858,7 +7933,7 @@ void ASTReader::FindExternalLexicalDecls( PredefsVisited[ID] = true; } - if (Decl *D = GetLocalDecl(*M, ID)) { + if (Decl *D = GetLocalDecl(*M, LocalDeclID::get(*this, *M, ID))) { assert(D->getKind() == K && "wrong kind for lexical decl"); if (!DC->isDeclInLexicalTraversal(D)) Decls.push_back(D); @@ -7880,32 +7955,34 @@ void ASTReader::FindExternalLexicalDecls( namespace { -class DeclIDComp { +class UnalignedDeclIDComp { ASTReader &Reader; ModuleFile &Mod; public: - DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {} + UnalignedDeclIDComp(ASTReader &Reader, ModuleFile &M) + : Reader(Reader), Mod(M) {} - bool operator()(LocalDeclID L, LocalDeclID R) const { + bool operator()(unaligned_decl_id_t L, unaligned_decl_id_t R) const { SourceLocation LHS = getLocation(L); SourceLocation RHS = getLocation(R); return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); } - bool operator()(SourceLocation LHS, LocalDeclID R) const { + bool operator()(SourceLocation LHS, unaligned_decl_id_t R) const { SourceLocation RHS = getLocation(R); return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); } - bool operator()(LocalDeclID L, SourceLocation RHS) const { + bool operator()(unaligned_decl_id_t L, SourceLocation RHS) const { SourceLocation LHS = getLocation(L); return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS); } - SourceLocation getLocation(LocalDeclID ID) const { + SourceLocation getLocation(unaligned_decl_id_t ID) const { return Reader.getSourceManager().getFileLoc( - Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID))); + Reader.getSourceLocationForDeclID( + Reader.getGlobalDeclID(Mod, LocalDeclID::get(Reader, Mod, ID)))); } }; @@ -7928,8 +8005,8 @@ void ASTReader::FindFileRegionDecls(FileID File, BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset); SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length); - DeclIDComp DIDComp(*this, *DInfo.Mod); - ArrayRef<serialization::LocalDeclID>::iterator BeginIt = + UnalignedDeclIDComp DIDComp(*this, *DInfo.Mod); + ArrayRef<unaligned_decl_id_t>::iterator BeginIt = llvm::lower_bound(DInfo.Decls, BeginLoc, DIDComp); if (BeginIt != DInfo.Decls.begin()) --BeginIt; @@ -7938,18 +8015,20 @@ void ASTReader::FindFileRegionDecls(FileID File, // to backtrack until we find it otherwise we will fail to report that the // region overlaps with an objc container. while (BeginIt != DInfo.Decls.begin() && - GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt)) + GetDecl(getGlobalDeclID(*DInfo.Mod, + LocalDeclID::get(*this, *DInfo.Mod, *BeginIt))) ->isTopLevelDeclInObjCContainer()) --BeginIt; - ArrayRef<serialization::LocalDeclID>::iterator EndIt = + ArrayRef<unaligned_decl_id_t>::iterator EndIt = llvm::upper_bound(DInfo.Decls, EndLoc, DIDComp); if (EndIt != DInfo.Decls.end()) ++EndIt; - for (ArrayRef<serialization::LocalDeclID>::iterator - DIt = BeginIt; DIt != EndIt; ++DIt) - Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt))); + for (ArrayRef<unaligned_decl_id_t>::iterator DIt = BeginIt; DIt != EndIt; + ++DIt) + Decls.push_back(GetDecl(getGlobalDeclID( + *DInfo.Mod, LocalDeclID::get(*this, *DInfo.Mod, *DIt)))); } bool @@ -7969,7 +8048,8 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, // Load the list of declarations. SmallVector<NamedDecl *, 64> Decls; llvm::SmallPtrSet<NamedDecl *, 8> Found; - for (DeclID ID : It->second.Table.find(Name)) { + + for (GlobalDeclID ID : It->second.Table.find(Name)) { NamedDecl *ND = cast<NamedDecl>(GetDecl(ID)); if (ND->getDeclName() == Name && Found.insert(ND).second) Decls.push_back(ND); @@ -7990,7 +8070,7 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { DeclsMap Decls; - for (DeclID ID : It->second.Table.findAll()) { + for (GlobalDeclID ID : It->second.Table.findAll()) { NamedDecl *ND = cast<NamedDecl>(GetDecl(ID)); Decls[ND->getDeclName()].push_back(ND); } @@ -8140,19 +8220,15 @@ dumpModuleIDMap(StringRef Name, llvm::errs() << Name << ":\n"; for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); - I != IEnd; ++I) { - llvm::errs() << " " << I->first << " -> " << I->second->FileName - << "\n"; - } + I != IEnd; ++I) + llvm::errs() << " " << (DeclID)I->first << " -> " << I->second->FileName + << "\n"; } LLVM_DUMP_METHOD void ASTReader::dump() { llvm::errs() << "*** PCH/ModuleFile Remappings:\n"; dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap); dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap); - dumpModuleIDMap("Global type map", GlobalTypeMap); - dumpModuleIDMap("Global declaration map", GlobalDeclMap); - dumpModuleIDMap("Global identifier map", GlobalIdentifierMap); dumpModuleIDMap("Global macro map", GlobalMacroMap); dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap); dumpModuleIDMap("Global selector map", GlobalSelectorMap); @@ -8188,7 +8264,7 @@ void ASTReader::InitializeSema(Sema &S) { // Makes sure any declarations that were deserialized "too early" // still get added to the identifier's declaration chains. - for (uint64_t ID : PreloadedDeclIDs) { + for (GlobalDeclID ID : PreloadedDeclIDs) { NamedDecl *D = cast<NamedDecl>(GetDecl(ID)); pushExternalDeclIntoScope(D, D->getDeclName()); } @@ -8217,11 +8293,11 @@ void ASTReader::UpdateSema() { assert(SemaDeclRefs.size() % 3 == 0); for (unsigned I = 0; I != SemaDeclRefs.size(); I += 3) { if (!SemaObj->StdNamespace) - SemaObj->StdNamespace = SemaDeclRefs[I]; + SemaObj->StdNamespace = SemaDeclRefs[I].getRawValue(); if (!SemaObj->StdBadAlloc) - SemaObj->StdBadAlloc = SemaDeclRefs[I+1]; + SemaObj->StdBadAlloc = SemaDeclRefs[I + 1].getRawValue(); if (!SemaObj->StdAlignValT) - SemaObj->StdAlignValT = SemaDeclRefs[I+2]; + SemaObj->StdAlignValT = SemaDeclRefs[I + 2].getRawValue(); } SemaDeclRefs.clear(); } @@ -8238,7 +8314,7 @@ void ASTReader::UpdateSema() { PragmaMSPointersToMembersState, PointersToMembersPragmaLocation); } - SemaObj->ForceCUDAHostDeviceDepth = ForceCUDAHostDeviceDepth; + SemaObj->CUDA().ForceHostDeviceDepth = ForceHostDeviceDepth; if (PragmaAlignPackCurrentValue) { // The bottom of the stack might have a default value. It must be adjusted @@ -8534,7 +8610,7 @@ namespace serialization { static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods, ObjCMethodList &List) { for (ObjCMethodDecl *M : llvm::reverse(Methods)) - S.addMethodToGlobalList(&List, M); + S.ObjC().addMethodToGlobalList(&List, M); } void ASTReader::ReadMethodPool(Selector Sel) { @@ -8559,8 +8635,10 @@ void ASTReader::ReadMethodPool(Selector Sel) { return; Sema &S = *getSema(); - Sema::GlobalMethodPool::iterator Pos = - S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethodPool::Lists())) + SemaObjC::GlobalMethodPool::iterator Pos = + S.ObjC() + .MethodPool + .insert(std::make_pair(Sel, SemaObjC::GlobalMethodPool::Lists())) .first; Pos->second.first.setBits(Visitor.getInstanceBits()); @@ -8594,18 +8672,20 @@ void ASTReader::ReadKnownNamespaces( void ASTReader::ReadUndefinedButUsed( llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) { for (unsigned Idx = 0, N = UndefinedButUsed.size(); Idx != N;) { - NamedDecl *D = cast<NamedDecl>(GetDecl(UndefinedButUsed[Idx++])); - SourceLocation Loc = - SourceLocation::getFromRawEncoding(UndefinedButUsed[Idx++]); + UndefinedButUsedDecl &U = UndefinedButUsed[Idx++]; + NamedDecl *D = cast<NamedDecl>(GetDecl(U.ID)); + SourceLocation Loc = SourceLocation::getFromRawEncoding(U.RawLoc); Undefined.insert(std::make_pair(D, Loc)); } + UndefinedButUsed.clear(); } void ASTReader::ReadMismatchingDeleteExpressions(llvm::MapVector< FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> & Exprs) { for (unsigned Idx = 0, N = DelayedDeleteExprs.size(); Idx != N;) { - FieldDecl *FD = cast<FieldDecl>(GetDecl(DelayedDeleteExprs[Idx++])); + FieldDecl *FD = + cast<FieldDecl>(GetDecl(GlobalDeclID(DelayedDeleteExprs[Idx++]))); uint64_t Count = DelayedDeleteExprs[Idx++]; for (uint64_t C = 0; C < Count; ++C) { SourceLocation DeleteLoc = @@ -8719,9 +8799,10 @@ void ASTReader::ReadWeakUndeclaredIdentifiers( void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) { for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) { ExternalVTableUse VT; - VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(VTableUses[Idx++])); - VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]); - VT.DefinitionRequired = VTableUses[Idx++]; + VTableUse &TableInfo = VTableUses[Idx++]; + VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(TableInfo.ID)); + VT.Location = SourceLocation::getFromRawEncoding(TableInfo.RawLoc); + VT.DefinitionRequired = TableInfo.Used; VTables.push_back(VT); } @@ -8731,9 +8812,9 @@ void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) { void ASTReader::ReadPendingInstantiations( SmallVectorImpl<std::pair<ValueDecl *, SourceLocation>> &Pending) { for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) { - ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++])); - SourceLocation Loc - = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]); + PendingInstantiation &Inst = PendingInstantiations[Idx++]; + ValueDecl *D = cast<ValueDecl>(GetDecl(Inst.ID)); + SourceLocation Loc = SourceLocation::getFromRawEncoding(Inst.RawLoc); Pending.push_back(std::make_pair(D, Loc)); } @@ -8748,11 +8829,10 @@ void ASTReader::ReadLateParsedTemplates( RecordDataImpl &LateParsed = LPT.second; for (unsigned Idx = 0, N = LateParsed.size(); Idx < N; /* In loop */) { - FunctionDecl *FD = - cast<FunctionDecl>(GetLocalDecl(*FMod, LateParsed[Idx++])); + FunctionDecl *FD = ReadDeclAs<FunctionDecl>(*FMod, LateParsed, Idx); auto LT = std::make_unique<LateParsedTemplate>(); - LT->D = GetLocalDecl(*FMod, LateParsed[Idx++]); + LT->D = ReadDecl(*FMod, LateParsed, Idx); LT->FPO = FPOptions::getFromOpaqueInt(LateParsed[Idx++]); ModuleFile *F = getOwningModuleFile(LT->D); @@ -8788,8 +8868,9 @@ void ASTReader::LoadSelector(Selector Sel) { void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) { assert(ID && "Non-zero identifier ID required"); - assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range"); - IdentifiersLoaded[ID - 1] = II; + unsigned Index = translateIdentifierIDToIndex(ID).second; + assert(Index < IdentifiersLoaded.size() && "identifier ID out of range"); + IdentifiersLoaded[Index] = II; if (DeserializationListener) DeserializationListener->IdentifierRead(ID, II); } @@ -8810,10 +8891,9 @@ void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) { /// \param Decls if non-null, this vector will be populated with the set of /// deserialized declarations. These declarations will not be pushed into /// scope. -void -ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, - const SmallVectorImpl<uint32_t> &DeclIDs, - SmallVectorImpl<Decl *> *Decls) { +void ASTReader::SetGloballyVisibleDecls( + IdentifierInfo *II, const SmallVectorImpl<GlobalDeclID> &DeclIDs, + SmallVectorImpl<Decl *> *Decls) { if (NumCurrentElementsDeserializing && !Decls) { PendingIdentifierInfos[II].append(DeclIDs.begin(), DeclIDs.end()); return; @@ -8843,6 +8923,22 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, } } +std::pair<ModuleFile *, unsigned> +ASTReader::translateIdentifierIDToIndex(IdentifierID ID) const { + if (ID == 0) + return {nullptr, 0}; + + unsigned ModuleFileIndex = ID >> 32; + unsigned LocalID = ID & llvm::maskTrailingOnes<IdentifierID>(32); + + assert(ModuleFileIndex && "not translating loaded IdentifierID?"); + assert(getModuleManager().size() > ModuleFileIndex - 1); + + ModuleFile &MF = getModuleManager()[ModuleFileIndex - 1]; + assert(LocalID < MF.LocalNumIdentifiers); + return {&MF, MF.BaseIdentifierID + LocalID}; +} + IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { if (ID == 0) return nullptr; @@ -8852,45 +8948,48 @@ IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) { return nullptr; } - ID -= 1; - if (!IdentifiersLoaded[ID]) { - GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1); - assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map"); - ModuleFile *M = I->second; - unsigned Index = ID - M->BaseIdentifierID; + auto [M, Index] = translateIdentifierIDToIndex(ID); + if (!IdentifiersLoaded[Index]) { + assert(M != nullptr && "Untranslated Identifier ID?"); + assert(Index >= M->BaseIdentifierID); + unsigned LocalIndex = Index - M->BaseIdentifierID; const unsigned char *Data = - M->IdentifierTableData + M->IdentifierOffsets[Index]; + M->IdentifierTableData + M->IdentifierOffsets[LocalIndex]; ASTIdentifierLookupTrait Trait(*this, *M); auto KeyDataLen = Trait.ReadKeyDataLength(Data); auto Key = Trait.ReadKey(Data, KeyDataLen.first); auto &II = PP.getIdentifierTable().get(Key); - IdentifiersLoaded[ID] = &II; + IdentifiersLoaded[Index] = &II; markIdentifierFromAST(*this, II); if (DeserializationListener) - DeserializationListener->IdentifierRead(ID + 1, &II); + DeserializationListener->IdentifierRead(ID, &II); } - return IdentifiersLoaded[ID]; + return IdentifiersLoaded[Index]; } -IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) { +IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, uint64_t LocalID) { return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID)); } -IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) { +IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, uint64_t LocalID) { if (LocalID < NUM_PREDEF_IDENT_IDS) return LocalID; if (!M.ModuleOffsetMap.empty()) ReadModuleOffsetMap(M); - ContinuousRangeMap<uint32_t, int, 2>::iterator I - = M.IdentifierRemap.find(LocalID - NUM_PREDEF_IDENT_IDS); - assert(I != M.IdentifierRemap.end() - && "Invalid index into identifier index remap"); + unsigned ModuleFileIndex = LocalID >> 32; + LocalID &= llvm::maskTrailingOnes<IdentifierID>(32); + ModuleFile *MF = + ModuleFileIndex ? M.TransitiveImports[ModuleFileIndex - 1] : &M; + assert(MF && "malformed identifier ID encoding?"); - return LocalID + I->second; + if (!ModuleFileIndex) + LocalID -= NUM_PREDEF_IDENT_IDS; + + return ((IdentifierID)(MF->Index + 1) << 32) | LocalID; } MacroInfo *ASTReader::getMacro(MacroID ID) { @@ -8935,7 +9034,7 @@ MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) { } serialization::SubmoduleID -ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) { +ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) const { if (LocalID < NUM_PREDEF_SUBMODULE_IDS) return LocalID; @@ -8968,7 +9067,7 @@ Module *ASTReader::getModule(unsigned ID) { return getSubmodule(ID); } -ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &M, unsigned ID) { +ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &M, unsigned ID) const { if (ID & 1) { // It's a module, look it up by submodule ID. auto I = GlobalSubmoduleMap.find(getGlobalSubmoduleID(M, ID >> 1)); @@ -9111,6 +9210,10 @@ DeclarationNameInfo ASTRecordReader::readDeclarationNameInfo() { return NameInfo; } +TypeCoupledDeclRefInfo ASTRecordReader::readTypeCoupledDeclRefInfo() { + return TypeCoupledDeclRefInfo(readDeclAs<ValueDecl>(), readBool()); +} + void ASTRecordReader::readQualifierInfo(QualifierInfo &Info) { Info.QualifierLoc = readNestedNameSpecifierLoc(); unsigned NumTPLists = readInt(); @@ -9157,7 +9260,7 @@ void ASTRecordReader::readUnresolvedSet(LazyASTUnresolvedSet &Set) { unsigned NumDecls = readInt(); Set.reserve(getContext(), NumDecls); while (NumDecls--) { - DeclID ID = readDeclID(); + GlobalDeclID ID = readDeclID(); AccessSpecifier AS = (AccessSpecifier) readInt(); Set.addLazyDecl(getContext(), ID, AS); } @@ -9312,6 +9415,18 @@ SourceRange ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record, return SourceRange(beg, end); } +llvm::BitVector ASTReader::ReadBitVector(const RecordData &Record, + const StringRef Blob) { + unsigned Count = Record[0]; + const char *Byte = Blob.data(); + llvm::BitVector Ret = llvm::BitVector(Count, false); + for (unsigned I = 0; I < Count; ++Byte) + for (unsigned Bit = 0; Bit < 8 && I < Count; ++Bit, ++I) + if (*Byte & (1 << Bit)) + Ret[I] = true; + return Ret; +} + /// Read a floating-point value llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) { return llvm::APFloat(Sem, readAPInt()); @@ -9367,6 +9482,20 @@ DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) const { return Diags.Report(Loc, DiagID); } +void ASTReader::warnStackExhausted(SourceLocation Loc) { + // When Sema is available, avoid duplicate errors. + if (SemaObj) { + SemaObj->warnStackExhausted(Loc); + return; + } + + if (WarnedStackExhausted) + return; + WarnedStackExhausted = true; + + Diag(Loc, diag::warn_stack_exhausted); +} + /// Retrieve the identifier table associated with the /// preprocessor. IdentifierTable &ASTReader::getIdentifierTable() { @@ -9521,7 +9650,7 @@ void ASTReader::finishPendingActions() { while (!PendingIdentifierInfos.empty()) { IdentifierInfo *II = PendingIdentifierInfos.back().first; - SmallVector<uint32_t, 4> DeclIDs = + SmallVector<GlobalDeclID, 4> DeclIDs = std::move(PendingIdentifierInfos.back().second); PendingIdentifierInfos.pop_back(); @@ -9745,7 +9874,8 @@ void ASTReader::finishPendingActions() { !NonConstDefn->isLateTemplateParsed() && // We only perform ODR checks for decls not in the explicit // global module fragment. - !FD->shouldSkipCheckingODR() && + !shouldSkipCheckingODR(FD) && + !shouldSkipCheckingODR(NonConstDefn) && FD->getODRHash() != NonConstDefn->getODRHash()) { if (!isa<CXXMethodDecl>(FD)) { PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); @@ -10139,7 +10269,7 @@ void ASTReader::FinishedDeserializing() { } void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { - if (IdentifierInfo *II = Name.getAsIdentifierInfo()) { + if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { // Remove any fake results before adding any real ones. auto It = PendingFakeLookupResults.find(II); if (It != PendingFakeLookupResults.end()) { @@ -10335,6 +10465,9 @@ OMPClause *OMPClauseReader::readClause() { case llvm::omp::OMPC_relaxed: C = new (Context) OMPRelaxedClause(); break; + case llvm::omp::OMPC_weak: + C = new (Context) OMPWeakClause(); + break; case llvm::omp::OMPC_threads: C = new (Context) OMPThreadsClause(); break; @@ -10733,6 +10866,8 @@ void OMPClauseReader::VisitOMPReleaseClause(OMPReleaseClause *) {} void OMPClauseReader::VisitOMPRelaxedClause(OMPRelaxedClause *) {} +void OMPClauseReader::VisitOMPWeakClause(OMPWeakClause *) {} + void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {} void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {} @@ -11717,3 +11852,209 @@ void ASTRecordReader::readOMPChildren(OMPChildren *Data) { for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I) Data->getChildren()[I] = readStmt(); } + +SmallVector<Expr *> ASTRecordReader::readOpenACCVarList() { + unsigned NumVars = readInt(); + llvm::SmallVector<Expr *> VarList; + for (unsigned I = 0; I < NumVars; ++I) + VarList.push_back(readSubExpr()); + return VarList; +} + +SmallVector<Expr *> ASTRecordReader::readOpenACCIntExprList() { + unsigned NumExprs = readInt(); + llvm::SmallVector<Expr *> ExprList; + for (unsigned I = 0; I < NumExprs; ++I) + ExprList.push_back(readSubExpr()); + return ExprList; +} + +OpenACCClause *ASTRecordReader::readOpenACCClause() { + OpenACCClauseKind ClauseKind = readEnum<OpenACCClauseKind>(); + SourceLocation BeginLoc = readSourceLocation(); + SourceLocation EndLoc = readSourceLocation(); + + switch (ClauseKind) { + case OpenACCClauseKind::Default: { + SourceLocation LParenLoc = readSourceLocation(); + OpenACCDefaultClauseKind DCK = readEnum<OpenACCDefaultClauseKind>(); + return OpenACCDefaultClause::Create(getContext(), DCK, BeginLoc, LParenLoc, + EndLoc); + } + case OpenACCClauseKind::If: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *CondExpr = readSubExpr(); + return OpenACCIfClause::Create(getContext(), BeginLoc, LParenLoc, CondExpr, + EndLoc); + } + case OpenACCClauseKind::Self: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *CondExpr = readBool() ? readSubExpr() : nullptr; + return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc, + CondExpr, EndLoc); + } + case OpenACCClauseKind::NumGangs: { + SourceLocation LParenLoc = readSourceLocation(); + unsigned NumClauses = readInt(); + llvm::SmallVector<Expr *> IntExprs; + for (unsigned I = 0; I < NumClauses; ++I) + IntExprs.push_back(readSubExpr()); + return OpenACCNumGangsClause::Create(getContext(), BeginLoc, LParenLoc, + IntExprs, EndLoc); + } + case OpenACCClauseKind::NumWorkers: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *IntExpr = readSubExpr(); + return OpenACCNumWorkersClause::Create(getContext(), BeginLoc, LParenLoc, + IntExpr, EndLoc); + } + case OpenACCClauseKind::VectorLength: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *IntExpr = readSubExpr(); + return OpenACCVectorLengthClause::Create(getContext(), BeginLoc, LParenLoc, + IntExpr, EndLoc); + } + case OpenACCClauseKind::Private: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCPrivateClause::Create(getContext(), BeginLoc, LParenLoc, + VarList, EndLoc); + } + case OpenACCClauseKind::FirstPrivate: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCFirstPrivateClause::Create(getContext(), BeginLoc, LParenLoc, + VarList, EndLoc); + } + case OpenACCClauseKind::Attach: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCAttachClause::Create(getContext(), BeginLoc, LParenLoc, + VarList, EndLoc); + } + case OpenACCClauseKind::DevicePtr: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCDevicePtrClause::Create(getContext(), BeginLoc, LParenLoc, + VarList, EndLoc); + } + case OpenACCClauseKind::NoCreate: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCNoCreateClause::Create(getContext(), BeginLoc, LParenLoc, + VarList, EndLoc); + } + case OpenACCClauseKind::Present: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCPresentClause::Create(getContext(), BeginLoc, LParenLoc, + VarList, EndLoc); + } + case OpenACCClauseKind::PCopy: + case OpenACCClauseKind::PresentOrCopy: + case OpenACCClauseKind::Copy: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCCopyClause::Create(getContext(), ClauseKind, BeginLoc, + LParenLoc, VarList, EndLoc); + } + case OpenACCClauseKind::CopyIn: + case OpenACCClauseKind::PCopyIn: + case OpenACCClauseKind::PresentOrCopyIn: { + SourceLocation LParenLoc = readSourceLocation(); + bool IsReadOnly = readBool(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCCopyInClause::Create(getContext(), ClauseKind, BeginLoc, + LParenLoc, IsReadOnly, VarList, EndLoc); + } + case OpenACCClauseKind::CopyOut: + case OpenACCClauseKind::PCopyOut: + case OpenACCClauseKind::PresentOrCopyOut: { + SourceLocation LParenLoc = readSourceLocation(); + bool IsZero = readBool(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCCopyOutClause::Create(getContext(), ClauseKind, BeginLoc, + LParenLoc, IsZero, VarList, EndLoc); + } + case OpenACCClauseKind::Create: + case OpenACCClauseKind::PCreate: + case OpenACCClauseKind::PresentOrCreate: { + SourceLocation LParenLoc = readSourceLocation(); + bool IsZero = readBool(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCCreateClause::Create(getContext(), ClauseKind, BeginLoc, + LParenLoc, IsZero, VarList, EndLoc); + } + case OpenACCClauseKind::Async: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *AsyncExpr = readBool() ? readSubExpr() : nullptr; + return OpenACCAsyncClause::Create(getContext(), BeginLoc, LParenLoc, + AsyncExpr, EndLoc); + } + case OpenACCClauseKind::Wait: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *DevNumExpr = readBool() ? readSubExpr() : nullptr; + SourceLocation QueuesLoc = readSourceLocation(); + llvm::SmallVector<Expr *> QueueIdExprs = readOpenACCIntExprList(); + return OpenACCWaitClause::Create(getContext(), BeginLoc, LParenLoc, + DevNumExpr, QueuesLoc, QueueIdExprs, + EndLoc); + } + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector<DeviceTypeArgument> Archs; + unsigned NumArchs = readInt(); + + for (unsigned I = 0; I < NumArchs; ++I) { + IdentifierInfo *Ident = readBool() ? readIdentifier() : nullptr; + SourceLocation Loc = readSourceLocation(); + Archs.emplace_back(Ident, Loc); + } + + return OpenACCDeviceTypeClause::Create(getContext(), ClauseKind, BeginLoc, + LParenLoc, Archs, EndLoc); + } + case OpenACCClauseKind::Reduction: { + SourceLocation LParenLoc = readSourceLocation(); + OpenACCReductionOperator Op = readEnum<OpenACCReductionOperator>(); + llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); + return OpenACCReductionClause::Create(getContext(), BeginLoc, LParenLoc, Op, + VarList, EndLoc); + } + case OpenACCClauseKind::Seq: + return OpenACCSeqClause::Create(getContext(), BeginLoc, EndLoc); + case OpenACCClauseKind::Independent: + return OpenACCIndependentClause::Create(getContext(), BeginLoc, EndLoc); + case OpenACCClauseKind::Auto: + return OpenACCAutoClause::Create(getContext(), BeginLoc, EndLoc); + + case OpenACCClauseKind::Finalize: + case OpenACCClauseKind::IfPresent: + case OpenACCClauseKind::Worker: + case OpenACCClauseKind::Vector: + case OpenACCClauseKind::NoHost: + case OpenACCClauseKind::UseDevice: + case OpenACCClauseKind::Delete: + case OpenACCClauseKind::Detach: + case OpenACCClauseKind::Device: + case OpenACCClauseKind::DeviceResident: + case OpenACCClauseKind::Host: + case OpenACCClauseKind::Link: + case OpenACCClauseKind::Collapse: + case OpenACCClauseKind::Bind: + case OpenACCClauseKind::DeviceNum: + case OpenACCClauseKind::DefaultAsync: + case OpenACCClauseKind::Tile: + case OpenACCClauseKind::Gang: + case OpenACCClauseKind::Invalid: + llvm_unreachable("Clause serialization not yet implemented"); + } + llvm_unreachable("Invalid Clause Kind"); +} + +void ASTRecordReader::readOpenACCClauseList( + MutableArrayRef<const OpenACCClause *> Clauses) { + for (unsigned I = 0; I < Clauses.size(); ++I) + Clauses[I] = readOpenACCClause(); +} diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp index 110f55f8c0f4..31ab6c651d59 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp @@ -49,6 +49,7 @@ #include "clang/Basic/PragmaKinds.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/Stack.h" #include "clang/Sema/IdentifierResolver.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTRecordReader.h" @@ -84,18 +85,16 @@ namespace clang { ASTReader &Reader; ASTRecordReader &Record; ASTReader::RecordLocation Loc; - const DeclID ThisDeclID; + const GlobalDeclID ThisDeclID; const SourceLocation ThisDeclLoc; using RecordData = ASTReader::RecordData; TypeID DeferredTypeID = 0; unsigned AnonymousDeclNumber = 0; - GlobalDeclID NamedDeclForTagDecl = 0; + GlobalDeclID NamedDeclForTagDecl = GlobalDeclID(); IdentifierInfo *TypedefNameForLinkage = nullptr; - bool HasPendingBody = false; - ///A flag to carry the information for a decl from the entity is /// used. We use it to delay the marking of the canonical decl as used until /// the entire declaration is deserialized and merged. @@ -126,15 +125,13 @@ namespace clang { return Record.readTypeSourceInfo(); } - serialization::DeclID readDeclID() { - return Record.readDeclID(); - } + GlobalDeclID readDeclID() { return Record.readDeclID(); } std::string readString() { return Record.readString(); } - void readDeclIDList(SmallVectorImpl<DeclID> &IDs) { + void readDeclIDList(SmallVectorImpl<GlobalDeclID> &IDs) { for (unsigned I = 0, Size = Record.readInt(); I != Size; ++I) IDs.push_back(readDeclID()); } @@ -260,14 +257,14 @@ namespace clang { public: ASTDeclReader(ASTReader &Reader, ASTRecordReader &Record, - ASTReader::RecordLocation Loc, - DeclID thisDeclID, SourceLocation ThisDeclLoc) + ASTReader::RecordLocation Loc, GlobalDeclID thisDeclID, + SourceLocation ThisDeclLoc) : Reader(Reader), Record(Record), Loc(Loc), ThisDeclID(thisDeclID), ThisDeclLoc(ThisDeclLoc) {} - template <typename T> static - void AddLazySpecializations(T *D, - SmallVectorImpl<serialization::DeclID>& IDs) { + template <typename T> + static void AddLazySpecializations(T *D, + SmallVectorImpl<GlobalDeclID> &IDs) { if (IDs.empty()) return; @@ -277,13 +274,14 @@ namespace clang { auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations; if (auto &Old = LazySpecializations) { - IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); + IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0].getRawValue()); llvm::sort(IDs); IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); } - auto *Result = new (C) serialization::DeclID[1 + IDs.size()]; - *Result = IDs.size(); + auto *Result = new (C) GlobalDeclID[1 + IDs.size()]; + *Result = GlobalDeclID(IDs.size()); + std::copy(IDs.begin(), IDs.end(), Result + 1); LazySpecializations = Result; @@ -314,13 +312,10 @@ namespace clang { static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D); static void markIncompleteDeclChainImpl(...); - /// Determine whether this declaration has a pending body. - bool hasPendingBody() const { return HasPendingBody; } - void ReadFunctionDefinition(FunctionDecl *FD); void Visit(Decl *D); - void UpdateDecl(Decl *D, SmallVectorImpl<serialization::DeclID> &); + void UpdateDecl(Decl *D, SmallVectorImpl<GlobalDeclID> &); static void setNextObjCCategory(ObjCCategoryDecl *Cat, ObjCCategoryDecl *Next) { @@ -541,7 +536,6 @@ void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) { } // Store the offset of the body so we can lazily load it later. Reader.PendingBodies[FD] = GetCurrentCursorOffset(); - HasPendingBody = true; } void ASTDeclReader::Visit(Decl *D) { @@ -563,7 +557,7 @@ void ASTDeclReader::Visit(Decl *D) { // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. - if (NamedDeclForTagDecl) + if (NamedDeclForTagDecl.isValid()) cast<TagDecl>(D)->TypedefNameDeclOrQualifier = cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl)); } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { @@ -607,8 +601,8 @@ void ASTDeclReader::VisitDecl(Decl *D) { // placeholder. GlobalDeclID SemaDCIDForTemplateParmDecl = readDeclID(); GlobalDeclID LexicalDCIDForTemplateParmDecl = - HasStandaloneLexicalDC ? readDeclID() : 0; - if (!LexicalDCIDForTemplateParmDecl) + HasStandaloneLexicalDC ? readDeclID() : GlobalDeclID(); + if (LexicalDCIDForTemplateParmDecl.isInvalid()) LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl; Reader.addPendingDeclContextInfo(D, SemaDCIDForTemplateParmDecl, @@ -800,21 +794,16 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { BitsUnpacker EnumDeclBits(Record.readInt()); ED->setNumPositiveBits(EnumDeclBits.getNextBits(/*Width=*/8)); ED->setNumNegativeBits(EnumDeclBits.getNextBits(/*Width=*/8)); - bool ShouldSkipCheckingODR = EnumDeclBits.getNextBit(); ED->setScoped(EnumDeclBits.getNextBit()); ED->setScopedUsingClassTag(EnumDeclBits.getNextBit()); ED->setFixed(EnumDeclBits.getNextBit()); - if (!ShouldSkipCheckingODR) { - ED->setHasODRHash(true); - ED->ODRHash = Record.readInt(); - } + ED->setHasODRHash(true); + ED->ODRHash = Record.readInt(); // If this is a definition subject to the ODR, and we already have a // definition, merge this one into it. - if (ED->isCompleteDefinition() && - Reader.getContext().getLangOpts().Modules && - Reader.getContext().getLangOpts().CPlusPlus) { + if (ED->isCompleteDefinition() && Reader.getContext().getLangOpts().Modules) { EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()]; if (!OldDef) { // This is the first time we've seen an imported definition. Look for a @@ -832,7 +821,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { Reader.mergeDefinitionVisibility(OldDef, ED); // We don't want to check the ODR hash value for declarations from global // module fragment. - if (!ED->shouldSkipCheckingODR() && + if (!shouldSkipCheckingODR(ED) && !shouldSkipCheckingODR(OldDef) && OldDef->getODRHash() != ED->getODRHash()) Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED); } else { @@ -872,9 +861,6 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); - // We should only reach here if we're in C/Objective-C. There is no - // global module fragment. - assert(!RD->shouldSkipCheckingODR()); RD->setODRHash(Record.readInt()); // Maintain the invariant of a redeclaration chain containing only @@ -1074,7 +1060,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3)); FD->setStorageClass((StorageClass)FunctionDeclBits.getNextBits(/*Width=*/3)); - bool ShouldSkipCheckingODR = FunctionDeclBits.getNextBit(); FD->setInlineSpecified(FunctionDeclBits.getNextBit()); FD->setImplicitlyInline(FunctionDeclBits.getNextBit()); FD->setHasSkippedBody(FunctionDeclBits.getNextBit()); @@ -1104,21 +1089,29 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { if (FD->isExplicitlyDefaulted()) FD->setDefaultLoc(readSourceLocation()); - if (!ShouldSkipCheckingODR) { - FD->ODRHash = Record.readInt(); - FD->setHasODRHash(true); - } + FD->ODRHash = Record.readInt(); + FD->setHasODRHash(true); - if (FD->isDefaulted()) { - if (unsigned NumLookups = Record.readInt()) { + if (FD->isDefaulted() || FD->isDeletedAsWritten()) { + // If 'Info' is nonzero, we need to read an DefaultedOrDeletedInfo; if, + // additionally, the second bit is also set, we also need to read + // a DeletedMessage for the DefaultedOrDeletedInfo. + if (auto Info = Record.readInt()) { + bool HasMessage = Info & 2; + StringLiteral *DeletedMessage = + HasMessage ? cast<StringLiteral>(Record.readExpr()) : nullptr; + + unsigned NumLookups = Record.readInt(); SmallVector<DeclAccessPair, 8> Lookups; for (unsigned I = 0; I != NumLookups; ++I) { NamedDecl *ND = Record.readDeclAs<NamedDecl>(); AccessSpecifier AS = (AccessSpecifier)Record.readInt(); Lookups.push_back(DeclAccessPair::make(ND, AS)); } - FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create( - Reader.getContext(), Lookups)); + + FD->setDefaultedOrDeletedInfo( + FunctionDecl::DefaultedOrDeletedFunctionInfo::Create( + Reader.getContext(), Lookups, DeletedMessage)); } } @@ -1164,7 +1157,6 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { // Load the body on-demand. Most clients won't care, because method // definitions rarely show up in headers. Reader.PendingBodies[MD] = GetCurrentCursorOffset(); - HasPendingBody = true; } MD->setSelfDecl(readDeclAs<ImplicitParamDecl>()); MD->setCmdDecl(readDeclAs<ImplicitParamDecl>()); @@ -1845,18 +1837,13 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { // this namespace; loading it might load a later declaration of the // same namespace, and we have an invariant that older declarations // get merged before newer ones try to merge. - GlobalDeclID AnonNamespace = 0; - if (Redecl.getFirstID() == ThisDeclID) { + GlobalDeclID AnonNamespace; + if (Redecl.getFirstID() == ThisDeclID) AnonNamespace = readDeclID(); - } else { - // Link this namespace back to the first declaration, which has already - // been deserialized. - D->AnonOrFirstNamespaceAndFlags.setPointer(D->getFirstDecl()); - } mergeRedeclarable(D, Redecl); - if (AnonNamespace) { + if (AnonNamespace.isValid()) { // Each module has its own anonymous namespace, which is disjoint from // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. @@ -1975,8 +1962,6 @@ void ASTDeclReader::ReadCXXDefinitionData( BitsUnpacker CXXRecordDeclBits = Record.readInt(); - bool ShouldSkipCheckingODR = CXXRecordDeclBits.getNextBit(); - #define FIELD(Name, Width, Merge) \ if (!CXXRecordDeclBits.canGetNextNBits(Width)) \ CXXRecordDeclBits.updateValue(Record.readInt()); \ @@ -1985,12 +1970,9 @@ void ASTDeclReader::ReadCXXDefinitionData( #include "clang/AST/CXXRecordDeclDefinitionBits.def" #undef FIELD - // We only perform ODR checks for decls not in GMF. - if (!ShouldSkipCheckingODR) { - // Note: the caller has deserialized the IsLambda bit already. - Data.ODRHash = Record.readInt(); - Data.HasODRHash = true; - } + // Note: the caller has deserialized the IsLambda bit already. + Data.ODRHash = Record.readInt(); + Data.HasODRHash = true; if (Record.readInt()) { Reader.DefinitionSource[D] = @@ -2016,7 +1998,7 @@ void ASTDeclReader::ReadCXXDefinitionData( if (Data.NumVBases) Data.VBases = ReadGlobalOffset(); - Data.FirstFriend = readDeclID(); + Data.FirstFriend = readDeclID().getRawValue(); } else { using Capture = LambdaCapture; @@ -2152,7 +2134,7 @@ void ASTDeclReader::MergeDefinitionData( } // We don't want to check ODR for decls in the global module fragment. - if (MergeDD.Definition->shouldSkipCheckingODR()) + if (shouldSkipCheckingODR(MergeDD.Definition) || shouldSkipCheckingODR(D)) return; if (D->getODRHash() != MergeDD.ODRHash) { @@ -2275,12 +2257,12 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { // Lazily load the key function to avoid deserializing every method so we can // compute it. if (WasDefinition) { - DeclID KeyFn = readDeclID(); - if (KeyFn && D->isCompleteDefinition()) + GlobalDeclID KeyFn = readDeclID(); + if (KeyFn.isValid() && D->isCompleteDefinition()) // FIXME: This is wrong for the ARM ABI, where some other module may have // made this function no longer be a key function. We need an update // record or similar for that case. - C.KeyFunctions[D] = KeyFn; + C.KeyFunctions[D] = KeyFn.getRawValue(); } return Redecl; @@ -2369,7 +2351,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { for (unsigned i = 0; i != D->NumTPLists; ++i) D->getTrailingObjects<TemplateParameterList *>()[i] = Record.readTemplateParameterList(); - D->NextFriend = readDeclID(); + D->NextFriend = readDeclID().getRawValue(); D->UnsupportedFriend = (Record.readInt() != 0); D->FriendLoc = readSourceLocation(); } @@ -2454,7 +2436,7 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector<serialization::DeclID, 32> SpecIDs; + SmallVector<GlobalDeclID, 32> SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2482,7 +2464,7 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector<serialization::DeclID, 32> SpecIDs; + SmallVector<GlobalDeclID, 32> SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2548,16 +2530,17 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( } } - // Explicit info. - if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { - auto *ExplicitInfo = - new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = readSourceLocation(); + // extern/template keyword locations for explicit instantiations + if (Record.readBool()) { + auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; + ExplicitInfo->ExternKeywordLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; } + if (Record.readBool()) + D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo()); + return Redecl; } @@ -2567,7 +2550,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( // need them for profiling TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); @@ -2584,7 +2566,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This FunctionTemplateDecl owns a CommonPtr; read it. - SmallVector<serialization::DeclID, 32> SpecIDs; + SmallVector<GlobalDeclID, 32> SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2617,16 +2599,17 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( } } - // Explicit info. - if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { - auto *ExplicitInfo = - new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = readSourceLocation(); + // extern/template keyword locations for explicit instantiations + if (Record.readBool()) { + auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; + ExplicitInfo->ExternKeywordLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; } + if (Record.readBool()) + D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo()); + SmallVector<TemplateArgument, 8> TemplArgs; Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true); D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs); @@ -2666,7 +2649,6 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D) { TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); @@ -2695,7 +2677,8 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { } if (Record.readInt()) - D->setDefaultArgument(readTypeSourceInfo()); + D->setDefaultArgument(Reader.getContext(), + Record.readTemplateArgumentLoc()); } void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { @@ -2716,12 +2699,14 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { // Rest of NonTypeTemplateParmDecl. D->ParameterPack = Record.readInt(); if (Record.readInt()) - D->setDefaultArgument(Record.readExpr()); + D->setDefaultArgument(Reader.getContext(), + Record.readTemplateArgumentLoc()); } } void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { VisitTemplateDecl(D); + D->setDeclaredWithTypename(Record.readBool()); // TemplateParmPosition. D->setDepth(Record.readInt()); D->setPosition(Record.readInt()); @@ -2779,7 +2764,7 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) { template <typename T> ASTDeclReader::RedeclarableResult ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { - DeclID FirstDeclID = readDeclID(); + GlobalDeclID FirstDeclID = readDeclID(); Decl *MergeWith = nullptr; bool IsKeyDecl = ThisDeclID == FirstDeclID; @@ -2787,9 +2772,9 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { uint64_t RedeclOffset = 0; - // 0 indicates that this declaration was the only declaration of its entity, - // and is used for space optimization. - if (FirstDeclID == 0) { + // invalid FirstDeclID indicates that this declaration was the only + // declaration of its entity, and is used for space optimization. + if (FirstDeclID.isInvalid()) { FirstDeclID = ThisDeclID; IsKeyDecl = true; IsFirstLocalDecl = true; @@ -2918,9 +2903,9 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, bool IsKeyDecl) { auto *DPattern = D->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl(); - RedeclarableResult Result(/*MergeWith*/ ExistingPattern, - DPattern->getCanonicalDecl()->getGlobalID(), - IsKeyDecl); + RedeclarableResult Result( + /*MergeWith*/ ExistingPattern, + DPattern->getCanonicalDecl()->getGlobalID(), IsKeyDecl); if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) { // Merge with any existing definition. @@ -2970,13 +2955,6 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, ExistingCanon->Used |= D->Used; D->Used = false; - // When we merge a namespace, update its pointer to the first namespace. - // We cannot have loaded any redeclarations of this declaration yet, so - // there's nothing else that needs to be updated. - if (auto *Namespace = dyn_cast<NamespaceDecl>(D)) - Namespace->AnonOrFirstNamespaceAndFlags.setPointer( - assert_cast<NamespaceDecl *>(ExistingCanon)); - // When we merge a template, merge its pattern. if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D)) mergeTemplatePattern( @@ -3075,14 +3053,14 @@ void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { Expr *Init = Record.readExpr(); auto IK = static_cast<OMPDeclareReductionInitKind>(Record.readInt()); D->setInitializer(Init, IK); - D->PrevDeclInScope = readDeclID(); + D->PrevDeclInScope = readDeclID().getRawValue(); } void ASTDeclReader::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { Record.readOMPChildren(D->Data); VisitValueDecl(D); D->VarName = Record.readDeclarationName(); - D->PrevDeclInScope = readDeclID(); + D->PrevDeclInScope = readDeclID().getRawValue(); } void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { @@ -3136,9 +3114,7 @@ public: OMPTraitInfo *readOMPTraitInfo() { return Reader.readOMPTraitInfo(); } - template <typename T> T *GetLocalDeclAs(uint32_t LocalID) { - return Reader.GetLocalDeclAs<T>(LocalID); - } + template <typename T> T *readDeclAs() { return Reader.readDeclAs<T>(); } }; } @@ -3205,7 +3181,7 @@ inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) { /// This routine should return true for anything that might affect /// code generation, e.g., inline function definitions, Objective-C /// declarations with metadata, etc. -static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { +bool ASTReader::isConsumerInterestedIn(Decl *D) { // An ObjCMethodDecl is never considered as "interesting" because its // implementation container always is. @@ -3214,7 +3190,7 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { if (isPartOfPerModuleInitializer(D)) { auto *M = D->getImportedOwningModule(); if (M && M->Kind == Module::ModuleMapModule && - Ctx.DeclMustBeEmitted(D)) + getContext().DeclMustBeEmitted(D)) return false; } @@ -3229,7 +3205,7 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { (Var->isThisDeclarationADefinition() == VarDecl::Definition || OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Var)); if (const auto *Func = dyn_cast<FunctionDecl>(D)) - return Func->doesThisDeclarationHaveABody() || HasBody; + return Func->doesThisDeclarationHaveABody() || PendingBodies.count(D); if (auto *ES = D->getASTContext().getExternalSource()) if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) @@ -3239,14 +3215,13 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { } /// Get the correct cursor and offset for loading a declaration. -ASTReader::RecordLocation -ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) { - GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); - assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); - ModuleFile *M = I->second; - const DeclOffset &DOffs = - M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS]; - Loc = TranslateSourceLocation(*M, DOffs.getLocation()); +ASTReader::RecordLocation ASTReader::DeclCursorForID(GlobalDeclID ID, + SourceLocation &Loc) { + ModuleFile *M = getOwningModuleFile(ID); + assert(M); + unsigned LocalDeclIndex = ID.getLocalDeclIndex(); + const DeclOffset &DOffs = M->DeclOffsets[LocalDeclIndex]; + Loc = ReadSourceLocation(*M, DOffs.getRawLoc()); return RecordLocation(M, DOffs.getBitOffset(M->DeclsBlockStartOffset)); } @@ -3292,7 +3267,7 @@ ASTDeclReader::getOrFakePrimaryClassDefinition(ASTReader &Reader, DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, DeclContext *DC) { if (auto *ND = dyn_cast<NamespaceDecl>(DC)) - return ND->getOriginalNamespace(); + return ND->getFirstDecl(); if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) return getOrFakePrimaryClassDefinition(Reader, RD); @@ -3301,16 +3276,15 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, return RD->getDefinition(); if (auto *ED = dyn_cast<EnumDecl>(DC)) - return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() - : nullptr; + return ED->getDefinition(); if (auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) return OID->getDefinition(); - // We can see the TU here only if we have no Sema object. In that case, - // there's no TU scope to look in, so using the DC alone is sufficient. + // We can see the TU here only if we have no Sema object. It is possible + // we're in clang-repl so we still need to get the primary context. if (auto *TU = dyn_cast<TranslationUnitDecl>(DC)) - return TU; + return TU->getPrimaryContext(); return nullptr; } @@ -3526,7 +3500,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // same template specialization into the same CXXRecordDecl. auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext()); if (MergedDCIt != Reader.MergedDeclContexts.end() && - !D->shouldSkipCheckingODR() && MergedDCIt->second == D->getDeclContext()) + !shouldSkipCheckingODR(D) && MergedDCIt->second == D->getDeclContext()) Reader.PendingOdrMergeChecks.push_back(D); return FindExistingResult(Reader, D, /*Existing=*/nullptr, @@ -3723,6 +3697,23 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, #include "clang/AST/DeclNodes.inc" } + // [basic.link]/p10: + // If two declarations of an entity are attached to different modules, + // the program is ill-formed; + // + // FIXME: Get rid of the enumeration of decl types once we have an appropriate + // abstract for decls of an entity. e.g., the namespace decl and using decl + // doesn't introduce an entity. + if (Module *M = Previous->getOwningModule(); + M && M->isNamedModule() && + isa<VarDecl, FunctionDecl, TagDecl, RedeclarableTemplateDecl>(Previous) && + !Reader.getContext().isInSameModule(M, D->getOwningModule())) { + Reader.Diag(Previous->getLocation(), + diag::err_multiple_decl_in_different_modules) + << cast<NamedDecl>(Previous) << M->Name; + Reader.Diag(D->getLocation(), diag::note_also_found); + } + // If the declaration was visible in one module, a redeclaration of it in // another module remains visible even if it wouldn't be visible by itself. // @@ -3788,8 +3779,7 @@ void ASTReader::markIncompleteDeclChain(Decl *D) { } /// Read the declaration at the given offset from the AST file. -Decl *ASTReader::ReadDeclRecord(DeclID ID) { - unsigned Index = ID - NUM_PREDEF_DECL_IDS; +Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { SourceLocation DeclLoc; RecordLocation Loc = DeclCursorForID(ID, DeclLoc); llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; @@ -3823,6 +3813,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { llvm::report_fatal_error( Twine("ASTReader::readDeclRecord failed reading decl code: ") + toString(MaybeDeclCode.takeError())); + switch ((DeclCode)MaybeDeclCode.get()) { case DECL_CONTEXT_LEXICAL: case DECL_CONTEXT_VISIBLE: @@ -3949,9 +3940,8 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { } case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: { bool HasTypeConstraint = Record.readInt(); - D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, - Record.readInt(), - HasTypeConstraint); + D = NonTypeTemplateParmDecl::CreateDeserialized( + Context, ID, Record.readInt(), HasTypeConstraint); break; } case DECL_TEMPLATE_TEMPLATE_PARM: @@ -4120,17 +4110,29 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { } assert(D && "Unknown declaration reading AST file"); - LoadedDecl(Index, D); + LoadedDecl(translateGlobalDeclIDToIndex(ID), D); // Set the DeclContext before doing any deserialization, to make sure internal // calls to Decl::getASTContext() by Decl's methods will find the // TranslationUnitDecl without crashing. D->setDeclContext(Context.getTranslationUnitDecl()); - Reader.Visit(D); + + // Reading some declarations can result in deep recursion. + clang::runWithSufficientStackSpace([&] { warnStackExhausted(DeclLoc); }, + [&] { Reader.Visit(D); }); // If this declaration is also a declaration context, get the // offsets for its tables of lexical and visible declarations. if (auto *DC = dyn_cast<DeclContext>(D)) { std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); + + // Get the lexical and visible block for the delayed namespace. + // It is sufficient to judge if ID is in DelayedNamespaceOffsetMap. + // But it may be more efficient to filter the other cases. + if (!Offsets.first && !Offsets.second && isa<NamespaceDecl>(D)) + if (auto Iter = DelayedNamespaceOffsetMap.find(ID); + Iter != DelayedNamespaceOffsetMap.end()) + Offsets = Iter->second; + if (Offsets.first && ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC)) return nullptr; @@ -4156,8 +4158,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // AST consumer might need to know about, queue it. // We don't pass it to the consumer immediately because we may be in recursive // loading, and some declarations may still be initializing. - PotentiallyInterestingDecls.push_back( - InterestingDecl(D, Reader.hasPendingBody())); + PotentiallyInterestingDecls.push_back(D); return D; } @@ -4178,24 +4179,48 @@ void ASTReader::PassInterestingDeclsToConsumer() { GetDecl(ID); EagerlyDeserializedDecls.clear(); - while (!PotentiallyInterestingDecls.empty()) { - InterestingDecl D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); - if (isConsumerInterestedIn(getContext(), D.getDecl(), D.hasPendingBody())) - PassInterestingDeclToConsumer(D.getDecl()); + auto ConsumingPotentialInterestingDecls = [this]() { + while (!PotentiallyInterestingDecls.empty()) { + Decl *D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); + } + }; + std::deque<Decl *> MaybeInterestingDecls = + std::move(PotentiallyInterestingDecls); + PotentiallyInterestingDecls.clear(); + assert(PotentiallyInterestingDecls.empty()); + while (!MaybeInterestingDecls.empty()) { + Decl *D = MaybeInterestingDecls.front(); + MaybeInterestingDecls.pop_front(); + // Since we load the variable's initializers lazily, it'd be problematic + // if the initializers dependent on each other. So here we try to load the + // initializers of static variables to make sure they are passed to code + // generator by order. If we read anything interesting, we would consume + // that before emitting the current declaration. + if (auto *VD = dyn_cast<VarDecl>(D); + VD && VD->isFileVarDecl() && !VD->isExternallyVisible()) + VD->getInit(); + ConsumingPotentialInterestingDecls(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); } + + // If we add any new potential interesting decl in the last call, consume it. + ConsumingPotentialInterestingDecls(); } void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // The declaration may have been modified by files later in the chain. // If this is the case, read the record containing the updates from each file // and pass it to ASTDeclReader to make the modifications. - serialization::GlobalDeclID ID = Record.ID; + GlobalDeclID ID = Record.ID; Decl *D = Record.D; ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); - SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs; + SmallVector<GlobalDeclID, 8> PendingLazySpecializationIDs; if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); @@ -4205,8 +4230,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // the declaration, then we know it was interesting and we skip the call // to isConsumerInterestedIn because it is unsafe to call in the // current ASTReader state. - bool WasInteresting = - Record.JustLoaded || isConsumerInterestedIn(getContext(), D, false); + bool WasInteresting = Record.JustLoaded || isConsumerInterestedIn(D); for (auto &FileAndOffset : UpdateOffsets) { ModuleFile *F = FileAndOffset.first; uint64_t Offset = FileAndOffset.second; @@ -4238,10 +4262,8 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // We might have made this declaration interesting. If so, remember that // we need to hand it off to the consumer. - if (!WasInteresting && - isConsumerInterestedIn(getContext(), D, Reader.hasPendingBody())) { - PotentiallyInterestingDecls.push_back( - InterestingDecl(D, Reader.hasPendingBody())); + if (!WasInteresting && isConsumerInterestedIn(D)) { + PotentiallyInterestingDecls.push_back(D); WasInteresting = true; } } @@ -4318,7 +4340,8 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { // we should instead generate one loop per kind and dispatch up-front? Decl *MostRecent = FirstLocal; for (unsigned I = 0, N = Record.size(); I != N; ++I) { - auto *D = GetLocalDecl(*M, Record[N - I - 1]); + unsigned Idx = N - I - 1; + auto *D = ReadDecl(*M, Record, Idx); ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl); MostRecent = D; } @@ -4335,7 +4358,7 @@ namespace { llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized; ObjCCategoryDecl *Tail = nullptr; llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; - serialization::GlobalDeclID InterfaceID; + GlobalDeclID InterfaceID; unsigned PreviousGeneration; void add(ObjCCategoryDecl *Cat) { @@ -4377,11 +4400,10 @@ namespace { } public: - ObjCCategoriesVisitor(ASTReader &Reader, - ObjCInterfaceDecl *Interface, - llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized, - serialization::GlobalDeclID InterfaceID, - unsigned PreviousGeneration) + ObjCCategoriesVisitor( + ASTReader &Reader, ObjCInterfaceDecl *Interface, + llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized, + GlobalDeclID InterfaceID, unsigned PreviousGeneration) : Reader(Reader), Interface(Interface), Deserialized(Deserialized), InterfaceID(InterfaceID), PreviousGeneration(PreviousGeneration) { // Populate the name -> category map with the set of known categories. @@ -4403,8 +4425,9 @@ namespace { // Map global ID of the definition down to the local ID used in this // module file. If there is no such mapping, we'll find nothing here // (or in any module it imports). - DeclID LocalID = Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID); - if (!LocalID) + LocalDeclID LocalID = + Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID); + if (LocalID.isInvalid()) return true; // Perform a binary search to find the local redeclarations for this @@ -4415,7 +4438,7 @@ namespace { M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap, Compare); if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap || - Result->DefinitionID != LocalID) { + LocalID != Result->getDefinitionID()) { // We didn't find anything. If the class definition is in this module // file, then the module files it depends on cannot have any categories, // so suppress further lookup. @@ -4427,16 +4450,14 @@ namespace { unsigned N = M.ObjCCategories[Offset]; M.ObjCCategories[Offset++] = 0; // Don't try to deserialize again for (unsigned I = 0; I != N; ++I) - add(cast_or_null<ObjCCategoryDecl>( - Reader.GetLocalDecl(M, M.ObjCCategories[Offset++]))); + add(Reader.ReadDeclAs<ObjCCategoryDecl>(M, M.ObjCCategories, Offset)); return true; } }; } // namespace -void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID, - ObjCInterfaceDecl *D, +void ASTReader::loadObjCCategories(GlobalDeclID ID, ObjCInterfaceDecl *D, unsigned PreviousGeneration) { ObjCCategoriesVisitor Visitor(*this, D, CategoriesDeserialized, ID, PreviousGeneration); @@ -4464,8 +4485,9 @@ static void forAllLaterRedecls(DeclT *D, Fn F) { } } -void ASTDeclReader::UpdateDecl(Decl *D, - llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) { +void ASTDeclReader::UpdateDecl( + Decl *D, + llvm::SmallVectorImpl<GlobalDeclID> &PendingLazySpecializationIDs) { while (Record.getIdx() < Record.size()) { switch ((DeclUpdateKind)Record.readInt()) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm-project/clang/lib/Serialization/ASTReaderInternals.h index 25a46ddabcb7..536b19f91691 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderInternals.h +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderInternals.h @@ -49,15 +49,15 @@ public: static const int MaxTables = 4; /// The lookup result is a list of global declaration IDs. - using data_type = SmallVector<DeclID, 4>; + using data_type = SmallVector<GlobalDeclID, 4>; struct data_type_builder { data_type &Data; - llvm::DenseSet<DeclID> Found; + llvm::DenseSet<GlobalDeclID> Found; data_type_builder(data_type &D) : Data(D) {} - void insert(DeclID ID) { + void insert(GlobalDeclID ID) { // Just use a linear scan unless we have more than a few IDs. if (Found.empty() && !Data.empty()) { if (Data.size() <= 4) { @@ -108,7 +108,7 @@ public: static void MergeDataInto(const data_type &From, data_type_builder &To) { To.Data.reserve(To.Data.size() + From.size()); - for (DeclID ID : From) + for (GlobalDeclID ID : From) To.insert(ID); } @@ -175,7 +175,7 @@ public: const unsigned char* d, unsigned DataLen); - IdentID ReadIdentifierID(const unsigned char *d); + IdentifierID ReadIdentifierID(const unsigned char *d); ASTReader &getReader() const { return Reader; } }; diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp index 85ecfa1a1a0b..c1361efd8c5f 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp @@ -790,19 +790,19 @@ readConstraintSatisfaction(ASTRecordReader &Record) { ConstraintSatisfaction Satisfaction; Satisfaction.IsSatisfied = Record.readInt(); Satisfaction.ContainsErrors = Record.readInt(); + const ASTContext &C = Record.getContext(); if (!Satisfaction.IsSatisfied) { unsigned NumDetailRecords = Record.readInt(); for (unsigned i = 0; i != NumDetailRecords; ++i) { - Expr *ConstraintExpr = Record.readExpr(); if (/* IsDiagnostic */Record.readInt()) { SourceLocation DiagLocation = Record.readSourceLocation(); - std::string DiagMessage = Record.readString(); + StringRef DiagMessage = C.backupStr(Record.readString()); + Satisfaction.Details.emplace_back( - ConstraintExpr, new (Record.getContext()) - ConstraintSatisfaction::SubstitutionDiagnostic{ - DiagLocation, DiagMessage}); + new (C) ConstraintSatisfaction::SubstitutionDiagnostic( + DiagLocation, DiagMessage)); } else - Satisfaction.Details.emplace_back(ConstraintExpr, Record.readExpr()); + Satisfaction.Details.emplace_back(Record.readExpr()); } } return Satisfaction; @@ -821,9 +821,11 @@ void ASTStmtReader::VisitConceptSpecializationExpr( static concepts::Requirement::SubstitutionDiagnostic * readSubstitutionDiagnostic(ASTRecordReader &Record) { - std::string SubstitutedEntity = Record.readString(); + const ASTContext &C = Record.getContext(); + StringRef SubstitutedEntity = C.backupStr(Record.readString()); SourceLocation DiagLoc = Record.readSourceLocation(); - std::string DiagMessage = Record.readString(); + StringRef DiagMessage = C.backupStr(Record.readString()); + return new (Record.getContext()) concepts::Requirement::SubstitutionDiagnostic{SubstitutedEntity, DiagLoc, DiagMessage}; @@ -908,26 +910,21 @@ void ASTStmtReader::VisitRequiresExpr(RequiresExpr *E) { std::move(*Req)); } break; case concepts::Requirement::RK_Nested: { + ASTContext &C = Record.getContext(); bool HasInvalidConstraint = Record.readInt(); if (HasInvalidConstraint) { - std::string InvalidConstraint = Record.readString(); - char *InvalidConstraintBuf = - new (Record.getContext()) char[InvalidConstraint.size()]; - std::copy(InvalidConstraint.begin(), InvalidConstraint.end(), - InvalidConstraintBuf); - R = new (Record.getContext()) concepts::NestedRequirement( - Record.getContext(), - StringRef(InvalidConstraintBuf, InvalidConstraint.size()), + StringRef InvalidConstraint = C.backupStr(Record.readString()); + R = new (C) concepts::NestedRequirement( + Record.getContext(), InvalidConstraint, readConstraintSatisfaction(Record)); break; } Expr *E = Record.readExpr(); if (E->isInstantiationDependent()) - R = new (Record.getContext()) concepts::NestedRequirement(E); + R = new (C) concepts::NestedRequirement(E); else - R = new (Record.getContext()) - concepts::NestedRequirement(Record.getContext(), E, - readConstraintSatisfaction(Record)); + R = new (C) concepts::NestedRequirement( + C, E, readConstraintSatisfaction(Record)); } break; } if (!R) @@ -956,14 +953,22 @@ void ASTStmtReader::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E) { E->setRBracketLoc(readSourceLocation()); } -void ASTStmtReader::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) { +void ASTStmtReader::VisitArraySectionExpr(ArraySectionExpr *E) { VisitExpr(E); + E->ASType = Record.readEnum<ArraySectionExpr::ArraySectionType>(); + E->setBase(Record.readSubExpr()); E->setLowerBound(Record.readSubExpr()); E->setLength(Record.readSubExpr()); - E->setStride(Record.readSubExpr()); + + if (E->isOMPArraySection()) + E->setStride(Record.readSubExpr()); + E->setColonLocFirst(readSourceLocation()); - E->setColonLocSecond(readSourceLocation()); + + if (E->isOMPArraySection()) + E->setColonLocSecond(readSourceLocation()); + E->setRBracketLoc(readSourceLocation()); } @@ -1047,30 +1052,22 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { E->MemberDNLoc = Record.readDeclarationNameLoc(E->MemberDecl->getDeclName()); E->MemberLoc = Record.readSourceLocation(); E->MemberExprBits.IsArrow = CurrentUnpackingBits->getNextBit(); - E->MemberExprBits.HasQualifierOrFoundDecl = HasQualifier || HasFoundDecl; + E->MemberExprBits.HasQualifier = HasQualifier; + E->MemberExprBits.HasFoundDecl = HasFoundDecl; E->MemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo; E->MemberExprBits.HadMultipleCandidates = CurrentUnpackingBits->getNextBit(); E->MemberExprBits.NonOdrUseReason = CurrentUnpackingBits->getNextBits(/*Width=*/2); E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); - if (HasQualifier || HasFoundDecl) { - DeclAccessPair FoundDecl; - if (HasFoundDecl) { - auto *FoundD = Record.readDeclAs<NamedDecl>(); - auto AS = (AccessSpecifier)CurrentUnpackingBits->getNextBits(/*Width=*/2); - FoundDecl = DeclAccessPair::make(FoundD, AS); - } else { - FoundDecl = DeclAccessPair::make(E->MemberDecl, - E->MemberDecl->getAccess()); - } - E->getTrailingObjects<MemberExprNameQualifier>()->FoundDecl = FoundDecl; + if (HasQualifier) + new (E->getTrailingObjects<NestedNameSpecifierLoc>()) + NestedNameSpecifierLoc(Record.readNestedNameSpecifierLoc()); - NestedNameSpecifierLoc QualifierLoc; - if (HasQualifier) - QualifierLoc = Record.readNestedNameSpecifierLoc(); - E->getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc = - QualifierLoc; + if (HasFoundDecl) { + auto *FoundD = Record.readDeclAs<NamedDecl>(); + auto AS = (AccessSpecifier)CurrentUnpackingBits->getNextBits(/*Width=*/2); + *E->getTrailingObjects<DeclAccessPair>() = DeclAccessPair::make(FoundD, AS); } if (HasTemplateInfo) @@ -1323,6 +1320,16 @@ void ASTStmtReader::VisitSourceLocExpr(SourceLocExpr *E) { E->SourceLocExprBits.Kind = Record.readInt(); } +void ASTStmtReader::VisitEmbedExpr(EmbedExpr *E) { + VisitExpr(E); + E->EmbedKeywordLoc = readSourceLocation(); + EmbedDataStorage *Data = new (Record.getContext()) EmbedDataStorage; + Data->BinaryData = cast<StringLiteral>(Record.readSubStmt()); + E->Data = Data; + E->Begin = Record.readInt(); + E->NumOfElements = Record.readInt(); +} + void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) { VisitExpr(E); E->setAmpAmpLoc(readSourceLocation()); @@ -1849,6 +1856,7 @@ void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) { VisitExpr(E); E->setLocation(readSourceLocation()); E->setImplicit(Record.readInt()); + E->setCapturedByCopyInLambdaWithExplicitObjectParameter(Record.readInt()); } void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) { @@ -2103,7 +2111,6 @@ void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); E->UnresolvedLookupExprBits.RequiresADL = CurrentUnpackingBits->getNextBit(); - E->UnresolvedLookupExprBits.Overloaded = CurrentUnpackingBits->getNextBit(); E->NamingClass = readDeclAs<CXXRecordDecl>(); } @@ -2174,6 +2181,19 @@ void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) { } } +void ASTStmtReader::VisitPackIndexingExpr(PackIndexingExpr *E) { + VisitExpr(E); + E->TransformedExpressions = Record.readInt(); + E->ExpandedToEmptyPack = Record.readInt(); + E->EllipsisLoc = readSourceLocation(); + E->RSquareLoc = readSourceLocation(); + E->SubExprs[0] = Record.readStmt(); + E->SubExprs[1] = Record.readStmt(); + auto **Exprs = E->getTrailingObjects<Expr *>(); + for (unsigned I = 0; I < E->TransformedExpressions; ++I) + Exprs[I] = Record.readExpr(); +} + void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); @@ -2415,6 +2435,14 @@ void ASTStmtReader::VisitOMPUnrollDirective(OMPUnrollDirective *D) { VisitOMPLoopTransformationDirective(D); } +void ASTStmtReader::VisitOMPReverseDirective(OMPReverseDirective *D) { + VisitOMPLoopTransformationDirective(D); +} + +void ASTStmtReader::VisitOMPInterchangeDirective(OMPInterchangeDirective *D) { + VisitOMPLoopTransformationDirective(D); +} + void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) { VisitOMPLoopDirective(D); D->setHasCancel(Record.readBool()); @@ -2764,6 +2792,7 @@ void ASTStmtReader::VisitOMPTeamsGenericLoopDirective( void ASTStmtReader::VisitOMPTargetTeamsGenericLoopDirective( OMPTargetTeamsGenericLoopDirective *D) { VisitOMPLoopDirective(D); + D->setCanBeParallelFor(Record.readBool()); } void ASTStmtReader::VisitOMPParallelGenericLoopDirective( @@ -2777,6 +2806,34 @@ void ASTStmtReader::VisitOMPTargetParallelGenericLoopDirective( } //===----------------------------------------------------------------------===// +// OpenACC Constructs/Directives. +//===----------------------------------------------------------------------===// +void ASTStmtReader::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) { + (void)Record.readInt(); + S->Kind = Record.readEnum<OpenACCDirectiveKind>(); + S->Range = Record.readSourceRange(); + S->DirectiveLoc = Record.readSourceLocation(); + Record.readOpenACCClauseList(S->Clauses); +} + +void ASTStmtReader::VisitOpenACCAssociatedStmtConstruct( + OpenACCAssociatedStmtConstruct *S) { + VisitOpenACCConstructStmt(S); + S->setAssociatedStmt(Record.readSubStmt()); +} + +void ASTStmtReader::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) { + VisitStmt(S); + VisitOpenACCAssociatedStmtConstruct(S); + S->findAndSetChildLoops(); +} + +void ASTStmtReader::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) { + VisitStmt(S); + VisitOpenACCAssociatedStmtConstruct(S); +} + +//===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -3064,8 +3121,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) MatrixSubscriptExpr(Empty); break; - case EXPR_OMP_ARRAY_SECTION: - S = new (Context) OMPArraySectionExpr(Empty); + case EXPR_ARRAY_SECTION: + S = new (Context) ArraySectionExpr(Empty); break; case EXPR_OMP_ARRAY_SHAPING: @@ -3191,6 +3248,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) SourceLocExpr(Empty); break; + case EXPR_BUILTIN_PP_EMBED: + S = new (Context) EmbedExpr(Empty); + break; + case EXPR_ADDR_LABEL: S = new (Context) AddrLabelExpr(Empty); break; @@ -3401,6 +3462,22 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } + case STMT_OMP_REVERSE_DIRECTIVE: { + assert(Record[ASTStmtReader::NumStmtFields] == 1 && + "Reverse directive accepts only a single loop"); + assert(Record[ASTStmtReader::NumStmtFields + 1] == 0 && + "Reverse directive has no clauses"); + S = OMPReverseDirective::CreateEmpty(Context); + break; + } + + case STMT_OMP_INTERCHANGE_DIRECTIVE: { + unsigned NumLoops = Record[ASTStmtReader::NumStmtFields]; + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1]; + S = OMPInterchangeDirective::CreateEmpty(Context, NumClauses, NumLoops); + break; + } + case STMT_OMP_FOR_DIRECTIVE: { unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields]; unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1]; @@ -4102,6 +4179,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { /*NumPartialArgs=*/Record[ASTStmtReader::NumExprFields]); break; + case EXPR_PACK_INDEXING: + S = PackIndexingExpr::CreateDeserialized( + Context, + /*TransformedExprs=*/Record[ASTStmtReader::NumExprFields]); + break; + case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM: S = new (Context) SubstNonTypeTemplateParmExpr(Empty); break; @@ -4188,7 +4271,16 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) ConceptSpecializationExpr(Empty); break; } - + case STMT_OPENACC_COMPUTE_CONSTRUCT: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + S = OpenACCComputeConstruct::CreateEmpty(Context, NumClauses); + break; + } + case STMT_OPENACC_LOOP_CONSTRUCT: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + S = OpenACCLoopConstruct::CreateEmpty(Context, NumClauses); + break; + } case EXPR_REQUIRES: unsigned numLocalParameters = Record[ASTStmtReader::NumExprFields]; unsigned numRequirement = Record[ASTStmtReader::NumExprFields + 1]; diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp index 378a1f86bd53..c78d8943d6d9 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp @@ -29,6 +29,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/LambdaCapture.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OpenACCClause.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/RawCommentList.h" #include "clang/AST/TemplateName.h" @@ -44,6 +45,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/OpenACCKinds.h" #include "clang/Basic/OpenCLOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" @@ -63,6 +65,8 @@ #include "clang/Sema/IdentifierResolver.h" #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTReader.h" @@ -161,79 +165,108 @@ static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) { namespace { -std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP, - Module *RootModule) { - SmallVector<const Module *> ModulesToProcess{RootModule}; +std::optional<std::set<const FileEntry *>> +GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { + if (!PP.getHeaderSearchInfo() + .getHeaderSearchOpts() + .ModulesPruneNonAffectingModuleMaps) + return std::nullopt; const HeaderSearch &HS = PP.getHeaderSearchInfo(); - - SmallVector<OptionalFileEntryRef, 16> FilesByUID; - HS.getFileMgr().GetUniqueIDMapping(FilesByUID); - - if (FilesByUID.size() > HS.header_file_size()) - FilesByUID.resize(HS.header_file_size()); - - for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { - OptionalFileEntryRef File = FilesByUID[UID]; - if (!File) - continue; - - const HeaderFileInfo *HFI = - HS.getExistingFileInfo(*File, /*WantExternal*/ false); - if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) - continue; - - for (const auto &KH : HS.findResolvedModulesForHeader(*File)) { - if (!KH.getModule()) - continue; - ModulesToProcess.push_back(KH.getModule()); - } - } - const ModuleMap &MM = HS.getModuleMap(); - SourceManager &SourceMgr = PP.getSourceManager(); - std::set<const FileEntry *> ModuleMaps{}; - auto CollectIncludingModuleMaps = [&](FileEntryRef F) { - if (!ModuleMaps.insert(F).second) + std::set<const FileEntry *> ModuleMaps; + std::set<const Module *> ProcessedModules; + auto CollectModuleMapsForHierarchy = [&](const Module *M) { + M = M->getTopLevelModule(); + + if (!ProcessedModules.insert(M).second) return; - FileID FID = SourceMgr.translateFile(F); - SourceLocation Loc = SourceMgr.getIncludeLoc(FID); - // 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); - if (!ModuleMaps.insert(*SourceMgr.getFileEntryRefForID(FID)).second) - break; - Loc = SourceMgr.getIncludeLoc(FID); - } - }; - std::set<const Module *> ProcessedModules; - auto CollectIncludingMapsFromAncestors = [&](const Module *M) { - for (const Module *Mod = M; Mod; Mod = Mod->Parent) { - if (!ProcessedModules.insert(Mod).second) - break; + std::queue<const Module *> Q; + Q.push(M); + while (!Q.empty()) { + const Module *Mod = Q.front(); + Q.pop(); + // The containing module map is affecting, because it's being pointed // into by Module::DefinitionLoc. - if (auto ModuleMapFile = MM.getContainingModuleMapFile(Mod)) - CollectIncludingModuleMaps(*ModuleMapFile); - // 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)) - CollectIncludingModuleMaps(*ModuleMapFile); + if (auto FE = MM.getContainingModuleMapFile(Mod)) + ModuleMaps.insert(*FE); + // For inferred modules, the module map that allowed inferring is not + // related to the virtual containing module map file. It did affect the + // compilation, though. + if (auto FE = MM.getModuleMapFileForUniquing(Mod)) + ModuleMaps.insert(*FE); + + for (auto *SubM : Mod->submodules()) + Q.push(SubM); } }; - for (const Module *CurrentModule : ModulesToProcess) { - CollectIncludingMapsFromAncestors(CurrentModule); + // Handle all the affecting modules referenced from the root module. + + CollectModuleMapsForHierarchy(RootModule); + + std::queue<const Module *> Q; + Q.push(RootModule); + while (!Q.empty()) { + const Module *CurrentModule = Q.front(); + Q.pop(); + for (const Module *ImportedModule : CurrentModule->Imports) - CollectIncludingMapsFromAncestors(ImportedModule); + CollectModuleMapsForHierarchy(ImportedModule); for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses) - CollectIncludingMapsFromAncestors(UndeclaredModule); + CollectModuleMapsForHierarchy(UndeclaredModule); + + for (auto *M : CurrentModule->submodules()) + Q.push(M); } + // Handle textually-included headers that belong to other modules. + + SmallVector<OptionalFileEntryRef, 16> FilesByUID; + HS.getFileMgr().GetUniqueIDMapping(FilesByUID); + + if (FilesByUID.size() > HS.header_file_size()) + FilesByUID.resize(HS.header_file_size()); + + for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { + OptionalFileEntryRef File = FilesByUID[UID]; + if (!File) + continue; + + const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File); + if (!HFI) + continue; // We have no information on this being a header file. + if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader) + continue; // Modular header, handled in the above module-based loop. + if (!HFI->isCompilingModuleHeader && !HFI->IsLocallyIncluded) + continue; // Non-modular header not included locally is not affecting. + + for (const auto &KH : HS.findResolvedModulesForHeader(*File)) + if (const Module *M = KH.getModule()) + CollectModuleMapsForHierarchy(M); + } + + // FIXME: This algorithm is not correct for module map hierarchies where + // module map file defining a (sub)module of a top-level module X includes + // a module map file that defines a (sub)module of another top-level module Y. + // Whenever X is affecting and Y is not, "replaying" this PCM file will fail + // when parsing module map files for X due to not knowing about the `extern` + // module map for Y. + // + // We don't have a good way to fix it here. We could mark all children of + // affecting module map files as being affecting as well, but that's + // expensive. SourceManager does not model the edge from parent to child + // SLocEntries, so instead, we would need to iterate over leaf module map + // files, walk up their include hierarchy and check whether we arrive at an + // affecting module map. + // + // Instead of complicating and slowing down this function, we should probably + // just ban module map hierarchies where module map defining a (sub)module X + // includes a module map defining a module that's not a submodule of X. + return ModuleMaps; } @@ -318,6 +351,10 @@ void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing to do } +void TypeLocWriter::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) { + // nothing to do +} + void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { addSourceLocation(TL.getCaretLoc()); } @@ -482,6 +519,10 @@ void ASTRecordWriter::AddConceptReference(const ConceptReference *CR) { AddASTTemplateArgumentListInfo(CR->getTemplateArgsAsWritten()); } +void TypeLocWriter::VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) { + addSourceLocation(TL.getEllipsisLoc()); +} + void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) { addSourceLocation(TL.getNameLoc()); auto *CR = TL.getConceptReference(); @@ -510,6 +551,10 @@ void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) { Record.AddAttr(TL.getAttr()); } +void TypeLocWriter::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { + // Nothing to do +} + void TypeLocWriter::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { // Nothing to do. } @@ -784,6 +829,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_ARRAY_TYPE_TRAIT); RECORD(EXPR_PACK_EXPANSION); RECORD(EXPR_SIZEOF_PACK); + RECORD(EXPR_PACK_INDEXING); RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM); RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK); RECORD(EXPR_FUNCTION_PARM_PACK); @@ -850,6 +896,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(WEAK_UNDECLARED_IDENTIFIERS); RECORD(PENDING_IMPLICIT_INSTANTIATIONS); RECORD(UPDATE_VISIBLE); + RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD); RECORD(DECL_UPDATE_OFFSETS); RECORD(DECL_UPDATES); RECORD(CUDA_SPECIAL_DECL_REFS); @@ -879,6 +926,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(PP_CONDITIONAL_STACK); RECORD(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS); RECORD(PP_ASSUME_NONNULL_LOC); + RECORD(PP_UNSAFE_BUFFER_USAGE); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -1002,6 +1050,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_UNRESOLVED_USING_VALUE); RECORD(DECL_UNRESOLVED_USING_TYPENAME); RECORD(DECL_LINKAGE_SPEC); + RECORD(DECL_EXPORT); RECORD(DECL_CXX_RECORD); RECORD(DECL_CXX_METHOD); RECORD(DECL_CXX_CONSTRUCTOR); @@ -1142,26 +1191,72 @@ ASTWriter::createSignature() const { return std::make_pair(ASTBlockHash, Signature); } +ASTFileSignature ASTWriter::createSignatureForNamedModule() const { + llvm::SHA1 Hasher; + Hasher.update(StringRef(Buffer.data(), Buffer.size())); + + assert(WritingModule); + assert(WritingModule->isNamedModule()); + + // We need to combine all the export imported modules no matter + // we used it or not. + for (auto [ExportImported, _] : WritingModule->Exports) + Hasher.update(ExportImported->Signature); + + // We combine all the used modules to make sure the signature is precise. + // Consider the case like: + // + // // a.cppm + // export module a; + // export inline int a() { ... } + // + // // b.cppm + // export module b; + // import a; + // export inline int b() { return a(); } + // + // Since both `a()` and `b()` are inline, we need to make sure the BMI of + // `b.pcm` will change after the implementation of `a()` changes. We can't + // get that naturally since we won't record the body of `a()` during the + // writing process. We can't reuse ODRHash here since ODRHash won't calculate + // the called function recursively. So ODRHash will be problematic if `a()` + // calls other inline functions. + // + // Probably we can solve this by a new hash mechanism. But the safety and + // efficiency may a problem too. Here we just combine the hash value of the + // used modules conservatively. + for (Module *M : TouchedTopLevelModules) + Hasher.update(M->Signature); + + return ASTFileSignature::create(Hasher.result()); +} + +static void BackpatchSignatureAt(llvm::BitstreamWriter &Stream, + const ASTFileSignature &S, uint64_t BitNo) { + for (uint8_t Byte : S) { + Stream.BackpatchByte(BitNo, Byte); + BitNo += 8; + } +} + ASTFileSignature ASTWriter::backpatchSignature() { + if (isWritingStdCXXNamedModules()) { + ASTFileSignature Signature = createSignatureForNamedModule(); + BackpatchSignatureAt(Stream, Signature, SignatureOffset); + return Signature; + } + if (!WritingModule || !PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent) return {}; // For implicit modules, write the hash of the PCM as its signature. - - auto BackpatchSignatureAt = [&](const ASTFileSignature &S, uint64_t BitNo) { - for (uint8_t Byte : S) { - Stream.BackpatchByte(BitNo, Byte); - BitNo += 8; - } - }; - ASTFileSignature ASTBlockHash; ASTFileSignature Signature; std::tie(ASTBlockHash, Signature) = createSignature(); - BackpatchSignatureAt(ASTBlockHash, ASTBlockHashOffset); - BackpatchSignatureAt(Signature, SignatureOffset); + BackpatchSignatureAt(Stream, ASTBlockHash, ASTBlockHashOffset); + BackpatchSignatureAt(Stream, Signature, SignatureOffset); return Signature; } @@ -1178,9 +1273,11 @@ void ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, RecordData Record; Stream.EnterSubblock(UNHASHED_CONTROL_BLOCK_ID, 5); - // For implicit modules, write the hash of the PCM as its signature. - if (WritingModule && - PP.getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent) { + // For implicit modules and C++20 named modules, write the hash of the PCM as + // its signature. + if (isWritingStdCXXNamedModules() || + (WritingModule && + PP.getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent)) { // At this point, we don't know the actual signature of the file or the AST // block - we're only able to compute those at the end of the serialization // process. Let's store dummy signatures for now, and replace them with the @@ -1191,21 +1288,24 @@ void ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, auto Dummy = ASTFileSignature::createDummy(); SmallString<128> Blob{Dummy.begin(), Dummy.end()}; - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(AST_BLOCK_HASH)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned ASTBlockHashAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); + // We don't need AST Block hash in named modules. + if (!isWritingStdCXXNamedModules()) { + auto Abbrev = std::make_shared<BitCodeAbbrev>(); + Abbrev->Add(BitCodeAbbrevOp(AST_BLOCK_HASH)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned ASTBlockHashAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - Abbrev = std::make_shared<BitCodeAbbrev>(); + Record.push_back(AST_BLOCK_HASH); + Stream.EmitRecordWithBlob(ASTBlockHashAbbrev, Record, Blob); + ASTBlockHashOffset = Stream.GetCurrentBitNo() - Blob.size() * 8; + Record.clear(); + } + + auto Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(SIGNATURE)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned SignatureAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); - Record.push_back(AST_BLOCK_HASH); - Stream.EmitRecordWithBlob(ASTBlockHashAbbrev, Record, Blob); - ASTBlockHashOffset = Stream.GetCurrentBitNo() - Blob.size() * 8; - Record.clear(); - Record.push_back(SIGNATURE); Stream.EmitRecordWithBlob(SignatureAbbrev, Record, Blob); SignatureOffset = Stream.GetCurrentBitNo() - Blob.size() * 8; @@ -1265,18 +1365,30 @@ void ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, WritePragmaDiagnosticMappings(Diags, /* isModule = */ WritingModule); // Header search entry usage. - auto HSEntryUsage = PP.getHeaderSearchInfo().computeUserEntryUsage(); - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_ENTRY_USAGE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits. - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Bit vector. - unsigned HSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); { + auto HSEntryUsage = PP.getHeaderSearchInfo().computeUserEntryUsage(); + auto Abbrev = std::make_shared<BitCodeAbbrev>(); + Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_ENTRY_USAGE)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits. + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Bit vector. + unsigned HSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); RecordData::value_type Record[] = {HEADER_SEARCH_ENTRY_USAGE, HSEntryUsage.size()}; Stream.EmitRecordWithBlob(HSUsageAbbrevCode, Record, bytes(HSEntryUsage)); } + // VFS usage. + { + auto VFSUsage = PP.getHeaderSearchInfo().collectVFSUsageAndClear(); + auto Abbrev = std::make_shared<BitCodeAbbrev>(); + Abbrev->Add(BitCodeAbbrevOp(VFS_USAGE)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits. + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Bit vector. + unsigned VFSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); + RecordData::value_type Record[] = {VFS_USAGE, VFSUsage.size()}; + Stream.EmitRecordWithBlob(VFSUsageAbbrevCode, Record, bytes(VFSUsage)); + } + // Leave the options block. Stream.ExitBlock(); UnhashedControlBlockRange.second = Stream.GetCurrentBitNo() >> 3; @@ -1350,7 +1462,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, (!PP.getHeaderSearchInfo() .getHeaderSearchOpts() .ModuleMapFileHomeIsCwd || - WritingModule->Directory->getName() != StringRef("."))) { + WritingModule->Directory->getName() != ".")) { // Module directory. auto Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY)); @@ -1595,6 +1707,18 @@ struct InputFileEntry { } // namespace +SourceLocation ASTWriter::getAffectingIncludeLoc(const SourceManager &SourceMgr, + const SrcMgr::FileInfo &File) { + SourceLocation IncludeLoc = File.getIncludeLoc(); + if (IncludeLoc.isValid()) { + FileID IncludeFID = SourceMgr.getFileID(IncludeLoc); + assert(IncludeFID.isValid() && "IncludeLoc in invalid file"); + if (!IsSLocAffecting[IncludeFID.ID]) + IncludeLoc = SourceLocation(); + } + return IncludeLoc; +} + void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts) { using namespace llvm; @@ -1648,26 +1772,22 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, Entry.IsSystemFile = isSystem(File.getFileCharacteristic()); Entry.IsTransient = Cache->IsTransient; Entry.BufferOverridden = Cache->BufferOverridden; - Entry.IsTopLevel = File.getIncludeLoc().isInvalid(); + Entry.IsTopLevel = getAffectingIncludeLoc(SourceMgr, File).isInvalid(); Entry.IsModuleMap = isModuleMap(File.getFileCharacteristic()); - auto ContentHash = hash_code(-1); + uint64_t ContentHash = 0; if (PP->getHeaderSearchInfo() .getHeaderSearchOpts() .ValidateASTInputFilesContent) { auto MemBuff = Cache->getBufferIfLoaded(); if (MemBuff) - ContentHash = hash_value(MemBuff->getBuffer()); + ContentHash = xxh3_64bits(MemBuff->getBuffer()); else PP->Diag(SourceLocation(), diag::err_module_unable_to_hash_content) << Entry.File.getName(); } - auto CH = llvm::APInt(64, ContentHash); - Entry.ContentHash[0] = - static_cast<uint32_t>(CH.getLoBits(32).getZExtValue()); - Entry.ContentHash[1] = - static_cast<uint32_t>(CH.getHiBits(32).getZExtValue()); - + Entry.ContentHash[0] = uint32_t(ContentHash); + Entry.ContentHash[1] = uint32_t(ContentHash >> 32); if (Entry.IsSystemFile) SystemFiles.push_back(Entry); else @@ -1848,9 +1968,15 @@ namespace { llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>; struct data_type { - const HeaderFileInfo &HFI; + data_type(const HeaderFileInfo &HFI, bool AlreadyIncluded, + ArrayRef<ModuleMap::KnownHeader> KnownHeaders, + UnresolvedModule Unresolved) + : HFI(HFI), AlreadyIncluded(AlreadyIncluded), + KnownHeaders(KnownHeaders), Unresolved(Unresolved) {} + + HeaderFileInfo HFI; bool AlreadyIncluded; - ArrayRef<ModuleMap::KnownHeader> KnownHeaders; + SmallVector<ModuleMap::KnownHeader, 1> KnownHeaders; UnresolvedModule Unresolved; }; using data_type_ref = const data_type &; @@ -1862,13 +1988,16 @@ namespace { // The hash is based only on size/time of the file, so that the reader can // match even when symlinking or excess path elements ("foo/../", "../") // change the form of the name. However, complete path is still the key. - return llvm::hash_combine(key.Size, key.ModTime); + uint8_t buf[sizeof(key.Size) + sizeof(key.ModTime)]; + memcpy(buf, &key.Size, sizeof(key.Size)); + memcpy(buf + sizeof(key.Size), &key.ModTime, sizeof(key.ModTime)); + return llvm::xxh3_64bits(buf); } std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) { unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; - unsigned DataLen = 1 + 4 + 4; + unsigned DataLen = 1 + sizeof(IdentifierID) + 4; for (auto ModInfo : Data.KnownHeaders) if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) DataLen += 4; @@ -1903,10 +2032,11 @@ namespace { | Data.HFI.IndexHeaderMapHeader; LE.write<uint8_t>(Flags); - if (!Data.HFI.ControllingMacro) - LE.write<uint32_t>(Data.HFI.ControllingMacroID); + if (Data.HFI.LazyControllingMacro.isID()) + LE.write<IdentifierID>(Data.HFI.LazyControllingMacro.getID()); else - LE.write<uint32_t>(Writer.getIdentifierRef(Data.HFI.ControllingMacro)); + LE.write<IdentifierID>( + Writer.getIdentifierRef(Data.HFI.LazyControllingMacro.getPtr())); unsigned Offset = 0; if (!Data.HFI.Framework.empty()) { @@ -2020,16 +2150,13 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { if (!File) continue; - // Get the file info. This will load info from the external source if - // necessary. Skip emitting this file if we have no information on it - // as a header file (in which case HFI will be null) or if it hasn't - // changed since it was loaded. Also skip it if it's for a modular header - // from a different module; in that case, we rely on the module(s) - // containing the header to provide this information. - const HeaderFileInfo *HFI = - HS.getExistingFileInfo(*File, /*WantExternal*/!Chain); - if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) - continue; + const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File); + if (!HFI) + continue; // We have no information on this being a header file. + if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader) + continue; // Header file info is tracked by the owning module file. + if (!HFI->isCompilingModuleHeader && !PP->alreadyIncluded(*File)) + continue; // Non-modular header not included is not needed. // Massage the file path into an appropriate form. StringRef Filename = File->getName(); @@ -2178,7 +2305,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, SLocEntryOffsets.push_back(Offset); // Starting offset of this entry within this module, so skip the dummy. Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2); - AddSourceLocation(File.getIncludeLoc(), Record); + AddSourceLocation(getAffectingIncludeLoc(SourceMgr, File), Record); Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding Record.push_back(File.hasLineDirectives()); @@ -2398,6 +2525,12 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { Record.clear(); } + // Write the safe buffer opt-out region map in PP + for (SourceLocation &S : PP.serializeSafeBufferOptOutMap()) + AddSourceLocation(S, Record); + Stream.EmitRecord(PP_UNSAFE_BUFFER_USAGE, Record); + Record.clear(); + // Enter the preprocessor block. Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3); @@ -2636,8 +2769,10 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec, uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase; assert((Offset >> 32) == 0 && "Preprocessed entity offset too large"); - PreprocessedEntityOffsets.push_back( - PPEntityOffset(getAdjustedRange((*E)->getSourceRange()), Offset)); + SourceRange R = getAdjustedRange((*E)->getSourceRange()); + PreprocessedEntityOffsets.emplace_back( + getRawSourceLocationEncoding(R.getBegin()), + getRawSourceLocationEncoding(R.getEnd()), Offset); if (auto *MD = dyn_cast<MacroDefinitionRecord>(*E)) { // Record this macro definition's ID. @@ -2704,7 +2839,9 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec, std::vector<PPSkippedRange> SerializedSkippedRanges; SerializedSkippedRanges.reserve(SkippedRanges.size()); for (auto const& Range : SkippedRanges) - SerializedSkippedRanges.emplace_back(Range); + SerializedSkippedRanges.emplace_back( + getRawSourceLocationEncoding(Range.getBegin()), + getRawSourceLocationEncoding(Range.getEnd())); using namespace llvm; auto Abbrev = std::make_shared<BitCodeAbbrev>(); @@ -2870,8 +3007,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { ParentID = SubmoduleIDs[Mod->Parent]; } - uint64_t DefinitionLoc = - SourceLocationEncoding::encode(getAdjustedLocation(Mod->DefinitionLoc)); + SourceLocationEncoding::RawLocEncoding DefinitionLoc = + getRawSourceLocationEncoding(getAdjustedLocation(Mod->DefinitionLoc)); // Emit the definition of the block. { @@ -2895,8 +3032,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { // Emit the requirements. for (const auto &R : Mod->Requirements) { - RecordData::value_type Record[] = {SUBMODULE_REQUIRES, R.second}; - Stream.EmitRecordWithBlob(RequiresAbbrev, Record, R.first); + RecordData::value_type Record[] = {SUBMODULE_REQUIRES, R.RequiredState}; + Stream.EmitRecordWithBlob(RequiresAbbrev, Record, R.FeatureName); } // Emit the umbrella header, if there is one. @@ -2997,10 +3134,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM); } - // Emit the initializers, if any. + // Emit the reachable initializers. + // The initializer may only be unreachable in reduced BMI. RecordData Inits; for (Decl *D : Context->getModuleInitializers(Mod)) - Inits.push_back(GetDeclRef(D)); + if (wasDeclEmitted(D)) + AddDeclRef(D, Inits); if (!Inits.empty()) Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits); @@ -3079,9 +3218,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, } // Sort by diag::kind for deterministic output. - llvm::sort(Mappings, [](const auto &LHS, const auto &RHS) { - return LHS.first < RHS.first; - }); + llvm::sort(Mappings, llvm::less_first()); for (const auto &I : Mappings) { Record.push_back(I.first); @@ -3106,9 +3243,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, continue; ++NumLocations; - SourceLocation Loc = Diag.SourceMgr->getComposedLoc(FileIDAndFile.first, 0); - assert(!Loc.isInvalid() && "start loc for valid FileID is invalid"); - AddSourceLocation(Loc, Record); + AddFileID(FileIDAndFile.first, Record); Record.push_back(FileIDAndFile.second.StateTransitions.size()); for (auto &StatePoint : FileIDAndFile.second.StateTransitions) { @@ -3139,22 +3274,23 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, /// Write the representation of a type to the AST stream. void ASTWriter::WriteType(QualType T) { TypeIdx &IdxRef = TypeIdxs[T]; - if (IdxRef.getIndex() == 0) // we haven't seen this type before. - IdxRef = TypeIdx(NextTypeID++); + if (IdxRef.getValue() == 0) // we haven't seen this type before. + IdxRef = TypeIdx(0, NextTypeID++); TypeIdx Idx = IdxRef; - assert(Idx.getIndex() >= FirstTypeID && "Re-writing a type from a prior AST"); + assert(Idx.getModuleFileIndex() == 0 && "Re-writing a type from a prior AST"); + assert(Idx.getValue() >= FirstTypeID && "Writing predefined type"); // Emit the type's representation. uint64_t Offset = ASTTypeWriter(*this).write(T) - DeclTypesBlockStartOffset; // Record the offset for this type. - unsigned Index = Idx.getIndex() - FirstTypeID; + uint64_t Index = Idx.getValue() - FirstTypeID; if (TypeOffsets.size() == Index) TypeOffsets.emplace_back(Offset); else if (TypeOffsets.size() < Index) { TypeOffsets.resize(Index + 1); - TypeOffsets[Index].setBitOffset(Offset); + TypeOffsets[Index].set(Offset); } else { llvm_unreachable("Types emitted in wrong order"); } @@ -3164,21 +3300,48 @@ void ASTWriter::WriteType(QualType T) { // Declaration Serialization //===----------------------------------------------------------------------===// +static bool IsInternalDeclFromFileContext(const Decl *D) { + auto *ND = dyn_cast<NamedDecl>(D); + if (!ND) + return false; + + if (!D->getDeclContext()->getRedeclContext()->isFileContext()) + return false; + + return ND->getFormalLinkage() == Linkage::Internal; +} + /// Write the block containing all of the declaration IDs /// lexically declared within the given DeclContext. /// /// \returns the offset of the DECL_CONTEXT_LEXICAL block within the /// bitstream, or 0 if no block was written. uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, - DeclContext *DC) { + const DeclContext *DC) { if (DC->decls_empty()) return 0; + // In reduced BMI, we don't care the declarations in functions. + if (GeneratingReducedBMI && DC->isFunctionOrMethod()) + return 0; + uint64_t Offset = Stream.GetCurrentBitNo(); - SmallVector<uint32_t, 128> KindDeclPairs; + SmallVector<DeclID, 128> KindDeclPairs; for (const auto *D : DC->decls()) { + if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D)) + continue; + + // We don't need to write decls with internal linkage into reduced BMI. + // If such decls gets emitted due to it get used from inline functions, + // the program illegal. However, there are too many use of static inline + // functions in the global module fragment and it will be breaking change + // to forbid that. So we have to allow to emit such declarations from GMF. + if (GeneratingReducedBMI && !D->isFromExplicitGlobalModule() && + IsInternalDeclFromFileContext(D)) + continue; + KindDeclPairs.push_back(D->getKind()); - KindDeclPairs.push_back(GetDeclRef(D)); + KindDeclPairs.push_back(GetDeclRef(D).getRawValue()); } ++NumLexicalDeclContexts; @@ -3195,12 +3358,10 @@ void ASTWriter::WriteTypeDeclOffsets() { auto Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base type index Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); { - RecordData::value_type Record[] = {TYPE_OFFSET, TypeOffsets.size(), - FirstTypeID - NUM_PREDEF_TYPE_IDS}; + RecordData::value_type Record[] = {TYPE_OFFSET, TypeOffsets.size()}; Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets)); } @@ -3208,12 +3369,10 @@ void ASTWriter::WriteTypeDeclOffsets() { Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base decl ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); { - RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size(), - FirstDeclID - NUM_PREDEF_DECL_IDS}; + RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size()}; Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets)); } } @@ -3234,7 +3393,7 @@ void ASTWriter::WriteFileDeclIDsMap() { Info.FirstDeclIndex = FileGroupedDeclIDs.size(); llvm::stable_sort(Info.DeclIDs); for (auto &LocDeclEntry : Info.DeclIDs) - FileGroupedDeclIDs.push_back(LocDeclEntry.second); + FileGroupedDeclIDs.push_back(LocDeclEntry.second.getRawValue()); } auto Abbrev = std::make_shared<BitCodeAbbrev>(); @@ -3305,16 +3464,18 @@ public: std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream& Out, Selector Sel, data_type_ref Methods) { - unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); + unsigned KeyLen = + 2 + (Sel.getNumArgs() ? Sel.getNumArgs() * sizeof(IdentifierID) + : sizeof(IdentifierID)); unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) if (ShouldWriteMethodListNode(Method)) - DataLen += 4; + DataLen += sizeof(DeclID); for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) if (ShouldWriteMethodListNode(Method)) - DataLen += 4; + DataLen += sizeof(DeclID); return emitULEBKeyDataLength(KeyLen, DataLen, Out); } @@ -3330,7 +3491,7 @@ public: if (N == 0) N = 1; for (unsigned I = 0; I != N; ++I) - LE.write<uint32_t>( + LE.write<IdentifierID>( Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); } @@ -3372,11 +3533,11 @@ public: for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) if (ShouldWriteMethodListNode(Method)) - LE.write<uint32_t>(Writer.getDeclID(Method->getMethod())); + LE.write<DeclID>((DeclID)Writer.getDeclID(Method->getMethod())); for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) if (ShouldWriteMethodListNode(Method)) - LE.write<uint32_t>(Writer.getDeclID(Method->getMethod())); + LE.write<DeclID>((DeclID)Writer.getDeclID(Method->getMethod())); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } @@ -3398,7 +3559,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { using namespace llvm; // Do we have to do anything at all? - if (SemaRef.MethodPool.empty() && SelectorIDs.empty()) + if (SemaRef.ObjC().MethodPool.empty() && SelectorIDs.empty()) return; unsigned NumTableEntries = 0; // Create and write out the blob that contains selectors and the method pool. @@ -3412,13 +3573,14 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { for (auto &SelectorAndID : SelectorIDs) { Selector S = SelectorAndID.first; SelectorID ID = SelectorAndID.second; - Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S); + SemaObjC::GlobalMethodPool::iterator F = + SemaRef.ObjC().MethodPool.find(S); ASTMethodPoolTrait::data_type Data = { ID, ObjCMethodList(), ObjCMethodList() }; - if (F != SemaRef.MethodPool.end()) { + if (F != SemaRef.ObjC().MethodPool.end()) { Data.Instance = F->second.first; Data.Factory = F->second.second; } @@ -3503,7 +3665,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { using namespace llvm; - if (SemaRef.ReferencedSelectors.empty()) + if (SemaRef.ObjC().ReferencedSelectors.empty()) return; RecordData Record; @@ -3512,7 +3674,7 @@ void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { // Note: this writes out all references even for a dependent AST. But it is // very tricky to fix, and given that @selector shouldn't really appear in // headers, probably not worth it. It's not a correctness issue. - for (auto &SelectorAndLocation : SemaRef.ReferencedSelectors) { + for (auto &SelectorAndLocation : SemaRef.ObjC().ReferencedSelectors) { Selector Sel = SelectorAndLocation.first; SourceLocation Loc = SelectorAndLocation.second; Writer.AddSelectorRef(Sel); @@ -3567,6 +3729,29 @@ static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts, namespace { +bool IsInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset, + bool IsModule, bool IsCPlusPlus) { + bool NeedDecls = !IsModule || !IsCPlusPlus; + + bool IsInteresting = + II->getNotableIdentifierID() != tok::NotableIdentifierKind::not_notable || + II->getBuiltinID() != Builtin::ID::NotBuiltin || + II->getObjCKeywordID() != tok::ObjCKeywordKind::objc_not_keyword; + if (MacroOffset || II->isPoisoned() || (!IsModule && IsInteresting) || + II->hasRevertedTokenIDToIdentifier() || + (NeedDecls && II->getFETokenInfo())) + return true; + + return false; +} + +bool IsInterestingNonMacroIdentifier(const IdentifierInfo *II, + ASTWriter &Writer) { + bool IsModule = Writer.isWritingModule(); + bool IsCPlusPlus = Writer.getLangOpts().CPlusPlus; + return IsInterestingIdentifier(II, /*MacroOffset=*/0, IsModule, IsCPlusPlus); +} + class ASTIdentifierTableTrait { ASTWriter &Writer; Preprocessor &PP; @@ -3580,20 +3765,15 @@ class ASTIdentifierTableTrait { /// doesn't check whether the name has macros defined; use PublicMacroIterator /// to check that. bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) { - if (MacroOffset || II->isPoisoned() || - (!IsModule && II->getObjCOrBuiltinID()) || - II->hasRevertedTokenIDToIdentifier() || - (NeedDecls && II->getFETokenInfo())) - return true; - - return false; + return IsInterestingIdentifier(II, MacroOffset, IsModule, + Writer.getLangOpts().CPlusPlus); } public: - using key_type = IdentifierInfo *; + using key_type = const IdentifierInfo *; using key_type_ref = key_type; - using data_type = IdentID; + using data_type = IdentifierID; using data_type_ref = data_type; using hash_value_type = unsigned; @@ -3617,12 +3797,8 @@ public: return isInterestingIdentifier(II, MacroOffset); } - bool isInterestingNonMacroIdentifier(const IdentifierInfo *II) { - return isInterestingIdentifier(II, 0); - } - std::pair<unsigned, unsigned> - EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { + EmitKeyDataLength(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID) { // Record the location of the identifier data. This is used when generating // the mapping from persistent IDs to strings. Writer.SetIdentifierOffset(II, Out.tell()); @@ -3636,7 +3812,7 @@ public: InterestingIdentifierOffsets->push_back(Out.tell()); unsigned KeyLen = II->getLength() + 1; - unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 + unsigned DataLen = sizeof(IdentifierID); // bytes for the persistent ID << 1 if (isInterestingIdentifier(II, MacroOffset)) { DataLen += 2; // 2 bytes for builtin ID DataLen += 2; // 2 bytes for flags @@ -3644,29 +3820,29 @@ public: DataLen += 4; // MacroDirectives offset. if (NeedDecls) - DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) * 4; + DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) * + sizeof(DeclID); } return emitULEBKeyDataLength(KeyLen, DataLen, Out); } - void EmitKey(raw_ostream& Out, const IdentifierInfo* II, - unsigned KeyLen) { + void EmitKey(raw_ostream &Out, const IdentifierInfo *II, unsigned KeyLen) { Out.write(II->getNameStart(), KeyLen); } - void EmitData(raw_ostream& Out, IdentifierInfo* II, - IdentID ID, unsigned) { + void EmitData(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID, + unsigned) { using namespace llvm::support; endian::Writer LE(Out, llvm::endianness::little); auto MacroOffset = Writer.getMacroDirectivesOffset(II); if (!isInterestingIdentifier(II, MacroOffset)) { - LE.write<uint32_t>(ID << 1); + LE.write<IdentifierID>(ID << 1); return; } - LE.write<uint32_t>((ID << 1) | 0x01); + LE.write<IdentifierID>((ID << 1) | 0x01); uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID(); assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); LE.write<uint16_t>(Bits); @@ -3691,14 +3867,18 @@ public: // Only emit declarations that aren't from a chained PCH, though. SmallVector<NamedDecl *, 16> Decls(IdResolver.decls(II)); for (NamedDecl *D : llvm::reverse(Decls)) - LE.write<uint32_t>( - Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), D))); + LE.write<DeclID>((DeclID)Writer.getDeclID( + getDeclForLocalLookup(PP.getLangOpts(), D))); } } }; } // namespace +/// If the \param IdentifierID ID is a local Identifier ID. If the higher +/// bits of ID is 0, it implies that the ID doesn't come from AST files. +static bool isLocalIdentifierID(IdentifierID ID) { return !(ID >> 32); } + /// Write the identifier table into the AST file. /// /// The identifier table consists of a blob containing string data @@ -3718,32 +3898,17 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, 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 - // table to enable checking of the predefines buffer in the case - // where the user adds new macro definitions when building the AST - // file. - SmallVector<const IdentifierInfo *, 128> IIs; - for (const auto &ID : PP.getIdentifierTable()) - 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) - getIdentifierRef(II); - // Create the on-disk hash table representation. We only store offsets // for identifiers that appear here for the first time. IdentifierOffsets.resize(NextIdentID - FirstIdentID); for (auto IdentIDPair : IdentifierIDs) { - auto *II = const_cast<IdentifierInfo *>(IdentIDPair.first); - IdentID ID = IdentIDPair.second; + const IdentifierInfo *II = IdentIDPair.first; + IdentifierID ID = IdentIDPair.second; assert(II && "NULL identifier in identifier table"); + // Write out identifiers if either the ID is local or the identifier has // changed since it was loaded. - if (ID >= FirstIdentID || !Chain || !II->isFromAST() - || II->hasChangedSinceDeserialization() || + if (isLocalIdentifierID(ID) || II->hasChangedSinceDeserialization() || (Trait.needDecls() && II->hasFETokenInfoChangedSinceDeserialization())) Generator.insert(II, ID, Trait); @@ -3777,7 +3942,6 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, auto Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); @@ -3787,8 +3951,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, #endif RecordData::value_type Record[] = {IDENTIFIER_OFFSET, - IdentifierOffsets.size(), - FirstIdentID - NUM_PREDEF_IDENT_IDS}; + IdentifierOffsets.size()}; Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, bytes(IdentifierOffsets)); @@ -3807,7 +3970,7 @@ namespace { // Trait used for the on-disk hash table used in the method pool. class ASTDeclContextNameLookupTrait { ASTWriter &Writer; - llvm::SmallVector<DeclID, 64> DeclIDs; + llvm::SmallVector<LocalDeclID, 64> DeclIDs; public: using key_type = DeclarationNameKey; @@ -3826,15 +3989,31 @@ public: data_type getData(const Coll &Decls) { unsigned Start = DeclIDs.size(); for (NamedDecl *D : Decls) { - DeclIDs.push_back( - Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D))); + NamedDecl *DeclForLocalLookup = + getDeclForLocalLookup(Writer.getLangOpts(), D); + + if (Writer.getDoneWritingDeclsAndTypes() && + !Writer.wasDeclEmitted(DeclForLocalLookup)) + continue; + + // Try to avoid writing internal decls to reduced BMI. + // See comments in ASTWriter::WriteDeclContextLexicalBlock for details. + if (Writer.isGeneratingReducedBMI() && + !DeclForLocalLookup->isFromExplicitGlobalModule() && + IsInternalDeclFromFileContext(DeclForLocalLookup)) + continue; + + DeclIDs.push_back(Writer.GetDeclRef(DeclForLocalLookup)); } return std::make_pair(Start, DeclIDs.size()); } data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) { unsigned Start = DeclIDs.size(); - llvm::append_range(DeclIDs, FromReader); + DeclIDs.insert( + DeclIDs.end(), + DeclIDIterator<GlobalDeclID, LocalDeclID>(FromReader.begin()), + DeclIDIterator<GlobalDeclID, LocalDeclID>(FromReader.end())); return std::make_pair(Start, DeclIDs.size()); } @@ -3862,11 +4041,13 @@ public: unsigned KeyLen = 1; switch (Name.getKind()) { case DeclarationName::Identifier: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXDeductionGuideName: + KeyLen += sizeof(IdentifierID); + break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - case DeclarationName::CXXLiteralOperatorName: - case DeclarationName::CXXDeductionGuideName: KeyLen += 4; break; case DeclarationName::CXXOperatorName: @@ -3879,8 +4060,8 @@ public: break; } - // 4 bytes for each DeclID. - unsigned DataLen = 4 * (Lookup.second - Lookup.first); + // length of DeclIDs. + unsigned DataLen = sizeof(DeclID) * (Lookup.second - Lookup.first); return emitULEBKeyDataLength(KeyLen, DataLen, Out); } @@ -3894,7 +4075,7 @@ public: case DeclarationName::Identifier: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXDeductionGuideName: - LE.write<uint32_t>(Writer.getIdentifierRef(Name.getIdentifier())); + LE.write<IdentifierID>(Writer.getIdentifierRef(Name.getIdentifier())); return; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: @@ -3923,7 +4104,7 @@ public: endian::Writer LE(Out, llvm::endianness::little); uint64_t Start = Out.tell(); (void)Start; for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I) - LE.write<uint32_t>(DeclIDs[I]); + LE.write<DeclID>((DeclID)DeclIDs[I]); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } }; @@ -3936,11 +4117,28 @@ bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result, DC->hasNeedToReconcileExternalVisibleStorage(); } -bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result, - DeclContext *DC) { - for (auto *D : Result.getLookupResult()) - if (!getDeclForLocalLookup(getLangOpts(), D)->isFromASTFile()) - return false; +/// Returns ture if all of the lookup result are either external, not emitted or +/// predefined. In such cases, the lookup result is not interesting and we don't +/// need to record the result in the current being written module. Return false +/// otherwise. +static bool isLookupResultNotInteresting(ASTWriter &Writer, + StoredDeclsList &Result) { + for (auto *D : Result.getLookupResult()) { + auto *LocalD = getDeclForLocalLookup(Writer.getLangOpts(), D); + if (LocalD->isFromASTFile()) + continue; + + // We can only be sure whether the local declaration is reachable + // after we done writing the declarations and types. + if (Writer.getDoneWritingDeclsAndTypes() && !Writer.wasDeclEmitted(LocalD)) + continue; + + // We don't need to emit the predefined decls. + if (Writer.isDeclPredefined(LocalD)) + continue; + + return false; + } return true; } @@ -3978,8 +4176,17 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, // don't need to write an entry for the name at all. If we can't // write out a lookup set without performing more deserialization, // just skip this entry. - if (isLookupResultExternal(Result, DC) && - isLookupResultEntirelyExternal(Result, DC)) + // + // Also in reduced BMI, we'd like to avoid writing unreachable + // declarations in GMF, so we need to avoid writing declarations + // that entirely external or unreachable. + // + // FIMXE: It looks sufficient to test + // isLookupResultNotInteresting here. But due to bug we have + // to test isLookupResultExternal here. See + // https://github.com/llvm/llvm-project/issues/61065 for details. + if ((GeneratingReducedBMI || isLookupResultExternal(Result, DC)) && + isLookupResultNotInteresting(*this, Result)) continue; // We also skip empty results. If any of the results could be external and @@ -4170,9 +4377,21 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, continue; } - for (NamedDecl *ND : Result) - if (!ND->isFromASTFile()) - GetDeclRef(ND); + for (NamedDecl *ND : Result) { + if (ND->isFromASTFile()) + continue; + + if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND)) + continue; + + // We don't need to force emitting internal decls into reduced BMI. + // See comments in ASTWriter::WriteDeclContextLexicalBlock for details. + if (GeneratingReducedBMI && !ND->isFromExplicitGlobalModule() && + IsInternalDeclFromFileContext(ND)) + continue; + + GetDeclRef(ND); + } } return 0; @@ -4233,7 +4452,8 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC))); // Write the lookup table - RecordData::value_type Record[] = {UPDATE_VISIBLE, getDeclID(cast<Decl>(DC))}; + RecordData::value_type Record[] = {UPDATE_VISIBLE, + getDeclID(cast<Decl>(DC)).getRawValue()}; Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable); } @@ -4263,8 +4483,8 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { Stream.EmitRecord(OPENCL_EXTENSIONS, Record); } void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) { - if (SemaRef.ForceCUDAHostDeviceDepth > 0) { - RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth}; + if (SemaRef.CUDA().ForceHostDeviceDepth > 0) { + RecordData::value_type Record[] = {SemaRef.CUDA().ForceHostDeviceDepth}; Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record); } } @@ -4287,7 +4507,7 @@ void ASTWriter::WriteObjCCategories() { Cat = Class->known_categories_begin(), CatEnd = Class->known_categories_end(); Cat != CatEnd; ++Cat, ++Size) { - assert(getDeclID(*Cat) != 0 && "Bogus category"); + assert(getDeclID(*Cat).isValid() && "Bogus category"); AddDeclRef(*Cat, Categories); } @@ -4578,11 +4798,18 @@ void ASTWriter::AddVersionTuple(const VersionTuple &Version, /// Note that the identifier II occurs at the given offset /// within the identifier table. void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { - IdentID ID = IdentifierIDs[II]; + IdentifierID ID = IdentifierIDs[II]; // Only store offsets new to this AST file. Other identifier names are looked // up earlier in the chain and thus don't need an offset. - if (ID >= FirstIdentID) - IdentifierOffsets[ID - FirstIdentID] = Offset; + if (!isLocalIdentifierID(ID)) + return; + + // For local identifiers, the module file index must be 0. + + assert(ID != 0); + ID -= NUM_PREDEF_IDENT_IDS; + assert(ID < IdentifierOffsets.size()); + IdentifierOffsets[ID] = Offset; } /// Note that the selector Sel occurs at the given offset @@ -4601,10 +4828,12 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer, InMemoryModuleCache &ModuleCache, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, - bool IncludeTimestamps, bool BuildingImplicitModule) + bool IncludeTimestamps, bool BuildingImplicitModule, + bool GeneratingReducedBMI) : Stream(Stream), Buffer(Buffer), ModuleCache(ModuleCache), IncludeTimestamps(IncludeTimestamps), - BuildingImplicitModule(BuildingImplicitModule) { + BuildingImplicitModule(BuildingImplicitModule), + GeneratingReducedBMI(GeneratingReducedBMI) { for (const auto &Ext : Extensions) { if (auto Writer = Ext->createExtensionWriter(*this)) ModuleFileExtensionWriters.push_back(std::move(Writer)); @@ -4659,15 +4888,23 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, StringRef OutputFile, } template<typename Vector> -static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, - ASTWriter::RecordData &Record) { +static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec) { + for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end(); + I != E; ++I) { + Writer.GetDeclRef(*I); + } +} + +template <typename Vector> +static void AddLazyVectorEmiitedDecls(ASTWriter &Writer, Vector &Vec, + ASTWriter::RecordData &Record) { for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end(); I != E; ++I) { - Writer.AddDeclRef(*I, Record); + Writer.AddEmittedDeclRef(*I, Record); } } -void ASTWriter::collectNonAffectingInputFiles() { +void ASTWriter::computeNonAffectingInputFiles() { SourceManager &SrcMgr = PP->getSourceManager(); unsigned N = SrcMgr.local_sloc_entry_size(); @@ -4699,9 +4936,16 @@ void ASTWriter::collectNonAffectingInputFiles() { if (!Cache->OrigEntry) continue; - if (!isModuleMap(File.getFileCharacteristic()) || - AffectingModuleMaps.empty() || - llvm::is_contained(AffectingModuleMaps, *Cache->OrigEntry)) + // Don't prune anything other than module maps. + if (!isModuleMap(File.getFileCharacteristic())) + continue; + + // Don't prune module maps if all are guaranteed to be affecting. + if (!AffectingModuleMaps) + continue; + + // Don't prune module maps that are affecting. + if (llvm::is_contained(*AffectingModuleMaps, *Cache->OrigEntry)) continue; IsSLocAffecting[I] = false; @@ -4727,32 +4971,43 @@ void ASTWriter::collectNonAffectingInputFiles() { NonAffectingFileIDAdjustments.push_back(FileIDAdjustment); NonAffectingOffsetAdjustments.push_back(OffsetAdjustment); } -} - -ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, - Module *WritingModule) { - using namespace llvm; - bool isModule = WritingModule != nullptr; + if (!PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesIncludeVFSUsage) + return; - // Make sure that the AST reader knows to finalize itself. - if (Chain) - Chain->finalizeForWriting(); + FileManager &FileMgr = PP->getFileManager(); + FileMgr.trackVFSUsage(true); + // Lookup the paths in the VFS to trigger `-ivfsoverlay` usage tracking. + for (StringRef Path : + PP->getHeaderSearchInfo().getHeaderSearchOpts().VFSOverlayFiles) + FileMgr.getVirtualFileSystem().exists(Path); + for (unsigned I = 1; I != N; ++I) { + if (IsSLocAffecting[I]) { + const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I); + if (!SLoc->isFile()) + continue; + const SrcMgr::FileInfo &File = SLoc->getFile(); + const SrcMgr::ContentCache *Cache = &File.getContentCache(); + if (!Cache->OrigEntry) + continue; + FileMgr.getVirtualFileSystem().exists( + Cache->OrigEntry->getNameAsRequested()); + } + } + FileMgr.trackVFSUsage(false); +} +void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) { ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - - // This needs to be done very early, since everything that writes - // SourceLocations or FileIDs depends on it. - collectNonAffectingInputFiles(); - writeUnhashedControlBlock(PP, Context); + bool isModule = WritingModule != nullptr; // Set up predefined declaration IDs. auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) { if (D) { assert(D->isCanonicalDecl() && "predefined decl is not canonical"); DeclIDs[D] = ID; + PredefinedDecls.insert(D); } }; RegisterPredefDecl(Context.getTranslationUnitDecl(), @@ -4782,103 +5037,276 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, RegisterPredefDecl(Context.TypePackElementDecl, PREDEF_DECL_TYPE_PACK_ELEMENT_ID); - // Build a record containing all of the tentative definitions in this file, in + const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + + // Force all top level declarations to be emitted. + // + // We start emitting top level declarations from the module purview to + // implement the eliding unreachable declaration feature. + for (const auto *D : TU->noload_decls()) { + if (D->isFromASTFile()) + continue; + + if (GeneratingReducedBMI) { + if (D->isFromExplicitGlobalModule()) + continue; + + // Don't force emitting static entities. + // + // Technically, all static entities shouldn't be in reduced BMI. The + // language also specifies that the program exposes TU-local entities + // is ill-formed. However, in practice, there are a lot of projects + // uses `static inline` in the headers. So we can't get rid of all + // static entities in reduced BMI now. + if (IsInternalDeclFromFileContext(D)) + continue; + } + + // If we're writing C++ named modules, don't emit declarations which are + // not from modules by default. They may be built in declarations (be + // handled above) or implcit declarations (see the implementation of + // `Sema::Initialize()` for example). + if (isWritingStdCXXNamedModules() && !D->getOwningModule() && + D->isImplicit()) + continue; + + GetDeclRef(D); + } + + if (GeneratingReducedBMI) + return; + + // Writing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for // headers. RecordData TentativeDefinitions; - AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); + AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions); - // Build a record containing all of the file scoped decls in this file. - RecordData UnusedFileScopedDecls; + // Writing all of the file scoped decls in this file. if (!isModule) - AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, - UnusedFileScopedDecls); + AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls); - // Build a record containing all of the delegating constructors we still need + // Writing all of the delegating constructors we still need // to resolve. - RecordData DelegatingCtorDecls; if (!isModule) - AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); + AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls); - // Write the set of weak, undeclared identifiers. We always write the - // entire table, since later PCH files in a PCH chain are only interested in - // the results at the end of the chain. - RecordData WeakUndeclaredIdentifiers; - for (const auto &WeakUndeclaredIdentifierList : - SemaRef.WeakUndeclaredIdentifiers) { - const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first; - for (const auto &WI : WeakUndeclaredIdentifierList.second) { - AddIdentifierRef(II, WeakUndeclaredIdentifiers); - AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); - AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); + // Writing all of the ext_vector declarations. + AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls); + + // Writing all of the VTable uses information. + if (!SemaRef.VTableUses.empty()) + for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) + GetDeclRef(SemaRef.VTableUses[I].first); + + // Writing all of the UnusedLocalTypedefNameCandidates. + for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) + GetDeclRef(TD); + + // Writing all of pending implicit instantiations. + for (const auto &I : SemaRef.PendingInstantiations) + GetDeclRef(I.first); + assert(SemaRef.PendingLocalImplicitInstantiations.empty() && + "There are local ones at end of translation unit!"); + + // Writing some declaration references. + if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) { + GetDeclRef(SemaRef.getStdNamespace()); + GetDeclRef(SemaRef.getStdBadAlloc()); + GetDeclRef(SemaRef.getStdAlignValT()); + } + + if (Context.getcudaConfigureCallDecl()) + GetDeclRef(Context.getcudaConfigureCallDecl()); + + // Writing all of the known namespaces. + for (const auto &I : SemaRef.KnownNamespaces) + if (!I.second) + GetDeclRef(I.first); + + // Writing all used, undefined objects that require definitions. + SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined; + SemaRef.getUndefinedButUsed(Undefined); + for (const auto &I : Undefined) + GetDeclRef(I.first); + + // Writing all delete-expressions that we would like to + // analyze later in AST. + if (!isModule) + for (const auto &DeleteExprsInfo : + SemaRef.getMismatchingDeleteExpressions()) + GetDeclRef(DeleteExprsInfo.first); + + // Make sure visible decls, added to DeclContexts previously loaded from + // an AST file, are registered for serialization. Likewise for template + // specializations added to imported templates. + for (const auto *I : DeclsToEmitEvenIfUnreferenced) + GetDeclRef(I); + DeclsToEmitEvenIfUnreferenced.clear(); + + // Make sure all decls associated with an identifier are registered for + // serialization, if we're storing decls with identifiers. + if (!WritingModule || !getLangOpts().CPlusPlus) { + llvm::SmallVector<const IdentifierInfo*, 256> IIs; + for (const auto &ID : SemaRef.PP.getIdentifierTable()) { + const IdentifierInfo *II = ID.second; + if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) + IIs.push_back(II); } + // Sort the identifiers to visit based on their name. + llvm::sort(IIs, llvm::deref<std::less<>>()); + for (const IdentifierInfo *II : IIs) + for (const Decl *D : SemaRef.IdResolver.decls(II)) + GetDeclRef(D); } - // Build a record containing all of the ext_vector declarations. + // Write all of the DeclsToCheckForDeferredDiags. + for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) + GetDeclRef(D); +} + +void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) { + ASTContext &Context = SemaRef.Context; + + bool isModule = WritingModule != nullptr; + + // Write the record containing external, unnamed definitions. + if (!EagerlyDeserializedDecls.empty()) + Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); + + if (!ModularCodegenDecls.empty()) + Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); + + // Write the record containing tentative definitions. + RecordData TentativeDefinitions; + AddLazyVectorEmiitedDecls(*this, SemaRef.TentativeDefinitions, + TentativeDefinitions); + if (!TentativeDefinitions.empty()) + Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); + + // Write the record containing unused file scoped decls. + RecordData UnusedFileScopedDecls; + if (!isModule) + AddLazyVectorEmiitedDecls(*this, SemaRef.UnusedFileScopedDecls, + UnusedFileScopedDecls); + if (!UnusedFileScopedDecls.empty()) + Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); + + // Write the record containing ext_vector type names. RecordData ExtVectorDecls; - AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); + AddLazyVectorEmiitedDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); + if (!ExtVectorDecls.empty()) + Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); - // Build a record containing all of the VTable uses information. + // Write the record containing VTable uses information. RecordData VTableUses; if (!SemaRef.VTableUses.empty()) { for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { - AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); + CXXRecordDecl *D = SemaRef.VTableUses[I].first; + if (!wasDeclEmitted(D)) + continue; + + AddDeclRef(D, VTableUses); AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); - VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); + VTableUses.push_back(SemaRef.VTablesUsed[D]); } + Stream.EmitRecord(VTABLE_USES, VTableUses); } - // Build a record containing all of the UnusedLocalTypedefNameCandidates. + // Write the record containing potentially unused local typedefs. RecordData UnusedLocalTypedefNameCandidates; for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) - AddDeclRef(TD, UnusedLocalTypedefNameCandidates); + AddEmittedDeclRef(TD, UnusedLocalTypedefNameCandidates); + if (!UnusedLocalTypedefNameCandidates.empty()) + Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, + UnusedLocalTypedefNameCandidates); - // Build a record containing all of pending implicit instantiations. + // Write the record containing pending implicit instantiations. RecordData PendingInstantiations; for (const auto &I : SemaRef.PendingInstantiations) { + if (!wasDeclEmitted(I.first)) + continue; + AddDeclRef(I.first, PendingInstantiations); AddSourceLocation(I.second, PendingInstantiations); } - assert(SemaRef.PendingLocalImplicitInstantiations.empty() && - "There are local ones at end of translation unit!"); + if (!PendingInstantiations.empty()) + Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); - // Build a record containing some declaration references. + // Write the record containing declaration references of Sema. RecordData SemaDeclRefs; if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) { - AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdAlignValT(), SemaDeclRefs); + auto AddEmittedDeclRefOrZero = [this, &SemaDeclRefs](Decl *D) { + if (!D || !wasDeclEmitted(D)) + SemaDeclRefs.push_back(0); + else + AddDeclRef(D, SemaDeclRefs); + }; + + AddEmittedDeclRefOrZero(SemaRef.getStdNamespace()); + AddEmittedDeclRefOrZero(SemaRef.getStdBadAlloc()); + AddEmittedDeclRefOrZero(SemaRef.getStdAlignValT()); } + if (!SemaDeclRefs.empty()) + Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); + // Write the record containing decls to be checked for deferred diags. + RecordData DeclsToCheckForDeferredDiags; + for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) + if (wasDeclEmitted(D)) + AddDeclRef(D, DeclsToCheckForDeferredDiags); + if (!DeclsToCheckForDeferredDiags.empty()) + Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS, + DeclsToCheckForDeferredDiags); + + // Write the record containing CUDA-specific declaration references. RecordData CUDASpecialDeclRefs; - if (Context.getcudaConfigureCallDecl()) { - AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs); + if (auto *CudaCallDecl = Context.getcudaConfigureCallDecl(); + CudaCallDecl && wasDeclEmitted(CudaCallDecl)) { + AddDeclRef(CudaCallDecl, CUDASpecialDeclRefs); + Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); } - // Build a record containing all of the known namespaces. + // Write the delegating constructors. + RecordData DelegatingCtorDecls; + if (!isModule) + AddLazyVectorEmiitedDecls(*this, SemaRef.DelegatingCtorDecls, + DelegatingCtorDecls); + if (!DelegatingCtorDecls.empty()) + Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); + + // Write the known namespaces. RecordData KnownNamespaces; for (const auto &I : SemaRef.KnownNamespaces) { - if (!I.second) + if (!I.second && wasDeclEmitted(I.first)) AddDeclRef(I.first, KnownNamespaces); } + if (!KnownNamespaces.empty()) + Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); - // Build a record of all used, undefined objects that require definitions. + // Write the undefined internal functions and variables, and inline functions. RecordData UndefinedButUsed; - SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined; SemaRef.getUndefinedButUsed(Undefined); for (const auto &I : Undefined) { + if (!wasDeclEmitted(I.first)) + continue; + AddDeclRef(I.first, UndefinedButUsed); AddSourceLocation(I.second, UndefinedButUsed); } + if (!UndefinedButUsed.empty()) + Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); - // Build a record containing all delete-expressions that we would like to + // Write all delete-expressions that we would like to // analyze later in AST. RecordData DeleteExprsToAnalyze; - if (!isModule) { for (const auto &DeleteExprsInfo : SemaRef.getMismatchingDeleteExpressions()) { + if (!wasDeclEmitted(DeleteExprsInfo.first)) + continue; + AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); for (const auto &DeleteLoc : DeleteExprsInfo.second) { @@ -4887,6 +5315,87 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, } } } + if (!DeleteExprsToAnalyze.empty()) + Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); +} + +ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, + Module *WritingModule) { + using namespace llvm; + + bool isModule = WritingModule != nullptr; + + // Make sure that the AST reader knows to finalize itself. + if (Chain) + Chain->finalizeForWriting(); + + ASTContext &Context = SemaRef.Context; + Preprocessor &PP = SemaRef.PP; + + // This needs to be done very early, since everything that writes + // SourceLocations or FileIDs depends on it. + computeNonAffectingInputFiles(); + + writeUnhashedControlBlock(PP, Context); + + // Don't reuse type ID and Identifier ID from readers for C++ standard named + // modules since we want to support no-transitive-change model for named + // modules. The theory for no-transitive-change model is, + // for a user of a named module, the user can only access the indirectly + // imported decls via the directly imported module. So that it is possible to + // control what matters to the users when writing the module. It would be + // problematic if the users can reuse the type IDs and identifier IDs from + // indirectly imported modules arbitrarily. So we choose to clear these ID + // here. + if (isWritingStdCXXNamedModules()) { + TypeIdxs.clear(); + IdentifierIDs.clear(); + } + + // Look for any identifiers that were named while processing the + // headers, but are otherwise not needed. We add these to the hash + // table to enable checking of the predefines buffer in the case + // where the user adds new macro definitions when building the AST + // file. + // + // We do this before emitting any Decl and Types to make sure the + // Identifier ID is stable. + SmallVector<const IdentifierInfo *, 128> IIs; + for (const auto &ID : PP.getIdentifierTable()) + if (IsInterestingNonMacroIdentifier(ID.second, *this)) + 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) + getIdentifierRef(II); + + // Write the set of weak, undeclared identifiers. We always write the + // entire table, since later PCH files in a PCH chain are only interested in + // the results at the end of the chain. + RecordData WeakUndeclaredIdentifiers; + for (const auto &WeakUndeclaredIdentifierList : + SemaRef.WeakUndeclaredIdentifiers) { + const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first; + for (const auto &WI : WeakUndeclaredIdentifierList.second) { + AddIdentifierRef(II, WeakUndeclaredIdentifiers); + AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); + AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); + } + } + + // Form the record of special types. + RecordData SpecialTypes; + AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); + AddTypeRef(Context.getFILEType(), SpecialTypes); + AddTypeRef(Context.getjmp_bufType(), SpecialTypes); + AddTypeRef(Context.getsigjmp_bufType(), SpecialTypes); + AddTypeRef(Context.ObjCIdRedefinitionType, SpecialTypes); + AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes); + AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); + AddTypeRef(Context.getucontext_tType(), SpecialTypes); + + PrepareWritingSpecialDecls(SemaRef); // Write the control block WriteControlBlock(PP, Context, isysroot); @@ -4904,83 +5413,6 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Stream.EmitRecord(METADATA_OLD_FORMAT, Record); } - // Create a lexical update block containing all of the declarations in the - // translation unit that do not come from other AST files. - const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - SmallVector<uint32_t, 128> NewGlobalKindDeclPairs; - for (const auto *D : TU->noload_decls()) { - if (!D->isFromASTFile()) { - NewGlobalKindDeclPairs.push_back(D->getKind()); - NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); - } - } - - auto Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); - { - RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; - Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, - bytes(NewGlobalKindDeclPairs)); - } - - // And a visible updates block for the translation unit. - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); - WriteDeclContextVisibleUpdate(TU); - - // If we have any extern "C" names, write out a visible update for them. - if (Context.ExternCContext) - WriteDeclContextVisibleUpdate(Context.ExternCContext); - - // If the translation unit has an anonymous namespace, and we don't already - // have an update block for it, write it as an update block. - // FIXME: Why do we not do this if there's already an update block? - if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { - ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; - if (Record.empty()) - Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS)); - } - - // Add update records for all mangling numbers and static local numbers. - // These aren't really update records, but this is a convenient way of - // tagging this rare extra data onto the declarations. - for (const auto &Number : Context.MangleNumbers) - if (!Number.first->isFromASTFile()) - DeclUpdates[Number.first].push_back(DeclUpdate(UPD_MANGLING_NUMBER, - Number.second)); - for (const auto &Number : Context.StaticLocalNumbers) - if (!Number.first->isFromASTFile()) - DeclUpdates[Number.first].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER, - Number.second)); - - // Make sure visible decls, added to DeclContexts previously loaded from - // an AST file, are registered for serialization. Likewise for template - // specializations added to imported templates. - for (const auto *I : DeclsToEmitEvenIfUnreferenced) { - GetDeclRef(I); - } - - // Make sure all decls associated with an identifier are registered for - // serialization, if we're storing decls with identifiers. - if (!WritingModule || !getLangOpts().CPlusPlus) { - llvm::SmallVector<const IdentifierInfo*, 256> IIs; - for (const auto &ID : PP.getIdentifierTable()) { - const IdentifierInfo *II = ID.second; - if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) - IIs.push_back(II); - } - // Sort the identifiers to visit based on their name. - llvm::sort(IIs, llvm::deref<std::less<>>()); - 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, // the entry should be complete, containing everything introduced by that // module and all modules it imports. It's possible that the entry is out of @@ -4992,18 +5424,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, for (auto &SelectorAndID : SelectorIDs) AllSelectors.push_back(SelectorAndID.first); for (auto &Selector : AllSelectors) - SemaRef.updateOutOfDateSelector(Selector); - - // Form the record of special types. - RecordData SpecialTypes; - AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); - AddTypeRef(Context.getFILEType(), SpecialTypes); - AddTypeRef(Context.getjmp_bufType(), SpecialTypes); - AddTypeRef(Context.getsigjmp_bufType(), SpecialTypes); - AddTypeRef(Context.ObjCIdRedefinitionType, SpecialTypes); - AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes); - AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); - AddTypeRef(Context.getucontext_tType(), SpecialTypes); + SemaRef.ObjC().updateOutOfDateSelector(Selector); if (Chain) { // Write the mapping information describing our module dependencies and how @@ -5055,15 +5476,11 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, // These values should be unique within a chain, since they will be read // as keys into ContinuousRangeMaps. - writeBaseIDOrNone(M.SLocEntryBaseOffset, M.LocalNumSLocEntries); - writeBaseIDOrNone(M.BaseIdentifierID, M.LocalNumIdentifiers); writeBaseIDOrNone(M.BaseMacroID, M.LocalNumMacros); writeBaseIDOrNone(M.BasePreprocessedEntityID, M.NumPreprocessedEntities); writeBaseIDOrNone(M.BaseSubmoduleID, M.LocalNumSubmodules); writeBaseIDOrNone(M.BaseSelectorID, M.LocalNumSelectors); - writeBaseIDOrNone(M.BaseDeclID, M.LocalNumDecls); - writeBaseIDOrNone(M.BaseTypeIndex, M.LocalNumTypes); } } RecordData::value_type Record[] = {MODULE_OFFSET_MAP}; @@ -5071,38 +5488,8 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Buffer.data(), Buffer.size()); } - // Build a record containing all of the DeclsToCheckForDeferredDiags. - SmallVector<serialization::DeclID, 64> DeclsToCheckForDeferredDiags; - for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) - DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D)); + WriteDeclAndTypes(Context); - RecordData DeclUpdatesOffsetsRecord; - - // Keep writing types, declarations, and declaration update records - // until we've emitted all of them. - Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5); - DeclTypesBlockStartOffset = Stream.GetCurrentBitNo(); - WriteTypeAbbrevs(); - WriteDeclAbbrevs(); - do { - WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - } while (!DeclUpdates.empty()); - Stream.ExitBlock(); - - DoneWritingDeclsAndTypes = true; - - // These things can only be done once we've written out decls and types. - WriteTypeDeclOffsets(); - if (!DeclUpdatesOffsetsRecord.empty()) - Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); WriteFileDeclIDsMap(); WriteSourceManagerBlock(Context.getSourceManager(), PP); WriteComments(); @@ -5122,75 +5509,13 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); - // Write the record containing external, unnamed definitions. - if (!EagerlyDeserializedDecls.empty()) - Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); - - if (!ModularCodegenDecls.empty()) - Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); - - // Write the record containing tentative definitions. - if (!TentativeDefinitions.empty()) - Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); - - // Write the record containing unused file scoped decls. - if (!UnusedFileScopedDecls.empty()) - Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); + WriteSpecialDeclRecords(SemaRef); // Write the record containing weak undeclared identifiers. if (!WeakUndeclaredIdentifiers.empty()) Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, WeakUndeclaredIdentifiers); - // Write the record containing ext_vector type names. - if (!ExtVectorDecls.empty()) - Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); - - // Write the record containing VTable uses information. - if (!VTableUses.empty()) - Stream.EmitRecord(VTABLE_USES, VTableUses); - - // Write the record containing potentially unused local typedefs. - if (!UnusedLocalTypedefNameCandidates.empty()) - Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, - UnusedLocalTypedefNameCandidates); - - // Write the record containing pending implicit instantiations. - if (!PendingInstantiations.empty()) - Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); - - // Write the record containing declaration references of Sema. - if (!SemaDeclRefs.empty()) - Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); - - // Write the record containing decls to be checked for deferred diags. - if (!DeclsToCheckForDeferredDiags.empty()) - Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS, - DeclsToCheckForDeferredDiags); - - // Write the record containing CUDA-specific declaration references. - if (!CUDASpecialDeclRefs.empty()) - Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); - - // Write the delegating constructors. - if (!DelegatingCtorDecls.empty()) - Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); - - // Write the known namespaces. - if (!KnownNamespaces.empty()) - Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); - - // Write the undefined internal functions and variables, and inline functions. - if (!UndefinedButUsed.empty()) - Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); - - if (!DeleteExprsToAnalyze.empty()) - Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); - - // Write the visible updates to DeclContexts. - for (auto *DC : UpdatedDeclContexts) - WriteDeclContextVisibleUpdate(DC); - if (!WritingModule) { // Write the submodules that were imported, if any. struct ModuleInfo { @@ -5255,6 +5580,142 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, return backpatchSignature(); } +void ASTWriter::EnteringModulePurview() { + // In C++20 named modules, all entities before entering the module purview + // lives in the GMF. + if (GeneratingReducedBMI) + DeclUpdatesFromGMF.swap(DeclUpdates); +} + +// Add update records for all mangling numbers and static local numbers. +// These aren't really update records, but this is a convenient way of +// tagging this rare extra data onto the declarations. +void ASTWriter::AddedManglingNumber(const Decl *D, unsigned Number) { + if (D->isFromASTFile()) + return; + + DeclUpdates[D].push_back(DeclUpdate(UPD_MANGLING_NUMBER, Number)); +} +void ASTWriter::AddedStaticLocalNumbers(const Decl *D, unsigned Number) { + if (D->isFromASTFile()) + return; + + DeclUpdates[D].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER, Number)); +} + +void ASTWriter::AddedAnonymousNamespace(const TranslationUnitDecl *TU, + NamespaceDecl *AnonNamespace) { + // If the translation unit has an anonymous namespace, and we don't already + // have an update block for it, write it as an update block. + // FIXME: Why do we not do this if there's already an update block? + if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { + ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; + if (Record.empty()) + Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS)); + } +} + +void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { + // Keep writing types, declarations, and declaration update records + // until we've emitted all of them. + RecordData DeclUpdatesOffsetsRecord; + Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5); + DeclTypesBlockStartOffset = Stream.GetCurrentBitNo(); + WriteTypeAbbrevs(); + WriteDeclAbbrevs(); + do { + WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord); + while (!DeclTypesToEmit.empty()) { + DeclOrType DOT = DeclTypesToEmit.front(); + DeclTypesToEmit.pop(); + if (DOT.isType()) + WriteType(DOT.getType()); + else + WriteDecl(Context, DOT.getDecl()); + } + } while (!DeclUpdates.empty()); + + DoneWritingDeclsAndTypes = true; + + // DelayedNamespace is only meaningful in reduced BMI. + // See the comments of DelayedNamespace for details. + assert(DelayedNamespace.empty() || GeneratingReducedBMI); + RecordData DelayedNamespaceRecord; + for (NamespaceDecl *NS : DelayedNamespace) { + uint64_t LexicalOffset = WriteDeclContextLexicalBlock(Context, NS); + uint64_t VisibleOffset = WriteDeclContextVisibleBlock(Context, NS); + + // Write the offset relative to current block. + if (LexicalOffset) + LexicalOffset -= DeclTypesBlockStartOffset; + + if (VisibleOffset) + VisibleOffset -= DeclTypesBlockStartOffset; + + AddDeclRef(NS, DelayedNamespaceRecord); + DelayedNamespaceRecord.push_back(LexicalOffset); + DelayedNamespaceRecord.push_back(VisibleOffset); + } + + // The process of writing lexical and visible block for delayed namespace + // shouldn't introduce any new decls, types or update to emit. + assert(DeclTypesToEmit.empty()); + assert(DeclUpdates.empty()); + + Stream.ExitBlock(); + + // These things can only be done once we've written out decls and types. + WriteTypeDeclOffsets(); + if (!DeclUpdatesOffsetsRecord.empty()) + Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); + + if (!DelayedNamespaceRecord.empty()) + Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD, + DelayedNamespaceRecord); + + const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + // Create a lexical update block containing all of the declarations in the + // translation unit that do not come from other AST files. + SmallVector<DeclID, 128> NewGlobalKindDeclPairs; + for (const auto *D : TU->noload_decls()) { + if (D->isFromASTFile()) + continue; + + // In reduced BMI, skip unreached declarations. + if (!wasDeclEmitted(D)) + continue; + + NewGlobalKindDeclPairs.push_back(D->getKind()); + NewGlobalKindDeclPairs.push_back(GetDeclRef(D).getRawValue()); + } + + auto Abv = std::make_shared<llvm::BitCodeAbbrev>(); + Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; + Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, + bytes(NewGlobalKindDeclPairs)); + + Abv = std::make_shared<llvm::BitCodeAbbrev>(); + Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + // And a visible updates block for the translation unit. + WriteDeclContextVisibleUpdate(TU); + + // If we have any extern "C" names, write out a visible update for them. + if (Context.ExternCContext) + WriteDeclContextVisibleUpdate(Context.ExternCContext); + + // Write the visible updates to DeclContexts. + for (auto *DC : UpdatedDeclContexts) + WriteDeclContextVisibleUpdate(DC); +} + void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { if (DeclUpdates.empty()) return; @@ -5286,7 +5747,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: assert(Update.getDecl() && "no decl to add?"); - Record.push_back(GetDeclRef(Update.getDecl())); + Record.AddDeclRef(Update.getDecl()); break; case UPD_CXX_ADDED_FUNCTION_DEFINITION: @@ -5299,8 +5760,8 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { break; case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: - Record.AddStmt(const_cast<Expr *>( - cast<ParmVarDecl>(Update.getDecl())->getDefaultArg())); + Record.writeStmtRef( + cast<ParmVarDecl>(Update.getDecl())->getDefaultArg()); break; case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: @@ -5314,8 +5775,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { Record.push_back(RD->isParamDestroyedInCallee()); Record.push_back(llvm::to_underlying(RD->getArgPassingRestrictions())); Record.AddCXXDefinitionData(RD); - Record.AddOffset(WriteDeclContextLexicalBlock( - *Context, const_cast<CXXRecordDecl *>(RD))); + Record.AddOffset(WriteDeclContextLexicalBlock(*Context, RD)); // This state is sometimes updated by template instantiation, when we // switch from the specialization referring to the template declaration @@ -5411,21 +5871,23 @@ 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); + if (!GeneratingReducedBMI || !CanElideDeclDef(D)) { + 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)); + AddDeclRef(D, OffsetsRecord); OffsetsRecord.push_back(Record.Emit(DECL_UPDATES)); } } @@ -5502,10 +5964,34 @@ void ASTWriter::AddFileID(FileID FID, RecordDataImpl &Record) { Record.push_back(getAdjustedFileID(FID).getOpaqueValue()); } +SourceLocationEncoding::RawLocEncoding +ASTWriter::getRawSourceLocationEncoding(SourceLocation Loc, LocSeq *Seq) { + unsigned BaseOffset = 0; + unsigned ModuleFileIndex = 0; + + // See SourceLocationEncoding.h for the encoding details. + if (Context->getSourceManager().isLoadedSourceLocation(Loc) && + Loc.isValid()) { + assert(getChain()); + auto SLocMapI = getChain()->GlobalSLocOffsetMap.find( + SourceManager::MaxLoadedOffset - Loc.getOffset() - 1); + assert(SLocMapI != getChain()->GlobalSLocOffsetMap.end() && + "Corrupted global sloc offset map"); + ModuleFile *F = SLocMapI->second; + BaseOffset = F->SLocEntryBaseOffset - 2; + // 0 means the location is not loaded. So we need to add 1 to the index to + // make it clear. + ModuleFileIndex = F->Index + 1; + assert(&getChain()->getModuleManager()[F->Index] == F); + } + + return SourceLocationEncoding::encode(Loc, BaseOffset, ModuleFileIndex, Seq); +} + void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record, SourceLocationSequence *Seq) { Loc = getAdjustedLocation(Loc); - Record.push_back(SourceLocationEncoding::encode(Loc, Seq)); + Record.push_back(getRawSourceLocationEncoding(Loc, Seq)); } void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record, @@ -5522,11 +6008,11 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor Record.push_back(getIdentifierRef(II)); } -IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { +IdentifierID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { if (!II) return 0; - IdentID &ID = IdentifierIDs[II]; + IdentifierID &ID = IdentifierIDs[II]; if (ID == 0) ID = NextIdentID++; return ID; @@ -5650,6 +6136,31 @@ void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) { Record.push_back(GetOrCreateTypeID(T)); } +template <typename IdxForTypeTy> +static TypeID MakeTypeID(ASTContext &Context, QualType T, + IdxForTypeTy IdxForType) { + if (T.isNull()) + return PREDEF_TYPE_NULL_ID; + + unsigned FastQuals = T.getLocalFastQualifiers(); + T.removeLocalFastQualifiers(); + + if (T.hasLocalNonFastQualifiers()) + return IdxForType(T).asTypeID(FastQuals); + + assert(!T.hasLocalQualifiers()); + + if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) + return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); + + if (T == Context.AutoDeductTy) + return TypeIdx(0, PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); + if (T == Context.AutoRRefDeductTy) + return TypeIdx(0, PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); + + return IdxForType(T).asTypeID(FastQuals); +} + TypeID ASTWriter::GetOrCreateTypeID(QualType T) { assert(Context); return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { @@ -5658,7 +6169,7 @@ TypeID ASTWriter::GetOrCreateTypeID(QualType T) { assert(!T.getLocalFastQualifiers()); TypeIdx &Idx = TypeIdxs[T]; - if (Idx.getIndex() == 0) { + if (Idx.getValue() == 0) { if (DoneWritingDeclsAndTypes) { assert(0 && "New type seen after serializing all the types to emit!"); return TypeIdx(); @@ -5666,48 +6177,54 @@ TypeID ASTWriter::GetOrCreateTypeID(QualType T) { // We haven't seen this type before. Assign it a new ID and put it // into the queue of types to emit. - Idx = TypeIdx(NextTypeID++); + Idx = TypeIdx(0, NextTypeID++); DeclTypesToEmit.push(T); } return Idx; }); } -TypeID ASTWriter::getTypeID(QualType T) const { - assert(Context); - return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { - if (T.isNull()) - return TypeIdx(); - assert(!T.getLocalFastQualifiers()); +void ASTWriter::AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record) { + if (!wasDeclEmitted(D)) + return; - TypeIdxMap::const_iterator I = TypeIdxs.find(T); - assert(I != TypeIdxs.end() && "Type not emitted!"); - return I->second; - }); + AddDeclRef(D, Record); } void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { - Record.push_back(GetDeclRef(D)); + Record.push_back(GetDeclRef(D).getRawValue()); } -DeclID ASTWriter::GetDeclRef(const Decl *D) { +LocalDeclID ASTWriter::GetDeclRef(const Decl *D) { assert(WritingAST && "Cannot request a declaration ID before AST writing"); if (!D) { - return 0; + return LocalDeclID(); + } + + // If the DeclUpdate from the GMF gets touched, emit it. + if (auto *Iter = DeclUpdatesFromGMF.find(D); + Iter != DeclUpdatesFromGMF.end()) { + for (DeclUpdate &Update : Iter->second) + DeclUpdates[D].push_back(Update); + DeclUpdatesFromGMF.erase(Iter); } // If D comes from an AST file, its declaration ID is already known and // fixed. - if (D->isFromASTFile()) - return D->getGlobalID(); + if (D->isFromASTFile()) { + if (isWritingStdCXXNamedModules() && D->getOwningModule()) + TouchedTopLevelModules.insert(D->getOwningModule()->getTopLevelModule()); + + return LocalDeclID(D->getGlobalID()); + } assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer"); - DeclID &ID = DeclIDs[D]; - if (ID == 0) { + LocalDeclID &ID = DeclIDs[D]; + if (ID.isInvalid()) { if (DoneWritingDeclsAndTypes) { assert(0 && "New decl seen after serializing all the decls to emit!"); - return 0; + return LocalDeclID(); } // We haven't seen this declaration before. Give it a new ID and @@ -5719,21 +6236,37 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) { return ID; } -DeclID ASTWriter::getDeclID(const Decl *D) { +LocalDeclID ASTWriter::getDeclID(const Decl *D) { if (!D) - return 0; + return LocalDeclID(); // If D comes from an AST file, its declaration ID is already known and // fixed. if (D->isFromASTFile()) - return D->getGlobalID(); + return LocalDeclID(D->getGlobalID()); assert(DeclIDs.contains(D) && "Declaration not emitted!"); return DeclIDs[D]; } -void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { - assert(ID); +bool ASTWriter::wasDeclEmitted(const Decl *D) const { + assert(D); + + assert(DoneWritingDeclsAndTypes && + "wasDeclEmitted should only be called after writing declarations"); + + if (D->isFromASTFile()) + return true; + + bool Emitted = DeclIDs.contains(D); + assert((Emitted || (!D->getOwningModule() && isWritingStdCXXNamedModules()) || + GeneratingReducedBMI) && + "The declaration within modules can only be omitted in reduced BMI."); + return Emitted; +} + +void ASTWriter::associateDeclWithFile(const Decl *D, LocalDeclID ID) { + assert(ID.isValid()); assert(D); SourceLocation Loc = D->getLocation(); @@ -5765,7 +6298,7 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { if (!Info) Info = std::make_unique<DeclIDInFileInfo>(); - std::pair<unsigned, serialization::DeclID> LocDecl(Offset, ID); + std::pair<unsigned, LocalDeclID> LocDecl(Offset, ID); LocDeclIDsTy &Decls = Info->DeclIDs; Decls.push_back(LocDecl); } @@ -5898,7 +6431,7 @@ void ASTRecordWriter::AddTemplateParameterList( AddDeclRef(P); if (const Expr *RequiresClause = TemplateParams->getRequiresClause()) { Record->push_back(true); - AddStmt(const_cast<Expr*>(RequiresClause)); + writeStmtRef(RequiresClause); } else { Record->push_back(false); } @@ -6010,9 +6543,6 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { BitsPacker DefinitionBits; - bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR(); - DefinitionBits.addBit(ShouldSkipCheckingODR); - #define FIELD(Name, Width, Merge) \ if (!DefinitionBits.canWriteNextNBits(Width)) { \ Record->push_back(DefinitionBits); \ @@ -6025,17 +6555,15 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { Record->push_back(DefinitionBits); - // We only perform ODR checks for decls not in GMF. - if (!ShouldSkipCheckingODR) - // getODRHash will compute the ODRHash if it has not been previously - // computed. - Record->push_back(D->getODRHash()); + // 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); if (ModulesDebugInfo) - Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(D)); + Writer->AddDeclRef(D, Writer->ModularCodegenDecls); // IsLambda bit is already saved. @@ -6139,23 +6667,30 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { // Note, this will get called multiple times, once one the reader starts up // and again each time it's done reading a PCH or module. - FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); - FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); - FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacros(); FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); - NextDeclID = FirstDeclID; - NextTypeID = FirstTypeID; - NextIdentID = FirstIdentID; NextMacroID = FirstMacroID; NextSelectorID = FirstSelectorID; NextSubmoduleID = FirstSubmoduleID; } -void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { - // Always keep the highest ID. See \p TypeRead() for more information. - IdentID &StoredID = IdentifierIDs[II]; +void ASTWriter::IdentifierRead(IdentifierID ID, IdentifierInfo *II) { + // Don't reuse Type ID from external modules for named modules. See the + // comments in WriteASTCore for details. + if (isWritingStdCXXNamedModules()) + return; + + IdentifierID &StoredID = IdentifierIDs[II]; + unsigned OriginalModuleFileIndex = StoredID >> 32; + + // Always keep the local identifier ID. See \p TypeRead() for more + // information. + if (OriginalModuleFileIndex == 0 && StoredID) + return; + + // Otherwise, keep the highest ID since the module file comes later has + // higher module file indexes. if (ID > StoredID) StoredID = ID; } @@ -6168,13 +6703,29 @@ void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) { } void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { - // Always take the highest-numbered type index. This copes with an interesting + // Don't reuse Type ID from external modules for named modules. See the + // comments in WriteASTCore for details. + if (isWritingStdCXXNamedModules()) + return; + + // Always take the type index that comes in later module files. + // This copes with an interesting // case for chained AST writing where we schedule writing the type and then, // later, deserialize the type from another AST. In this case, we want to - // keep the higher-numbered entry so that we can properly write it out to + // keep the entry from a later module so that we can properly write it out to // the AST file. TypeIdx &StoredIdx = TypeIdxs[T]; - if (Idx.getIndex() >= StoredIdx.getIndex()) + + // Ignore it if the type comes from the current being written module file. + // Since the current module file being written logically has the highest + // index. + unsigned ModuleFileIndex = StoredIdx.getModuleFileIndex(); + if (ModuleFileIndex == 0 && StoredIdx.getValue()) + return; + + // Otherwise, keep the highest ID since the module file comes later has + // higher module file indexes. + if (Idx.getModuleFileIndex() >= StoredIdx.getModuleFileIndex()) StoredIdx = Idx; } @@ -6659,6 +7210,8 @@ void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {} void OMPClauseWriter::VisitOMPRelaxedClause(OMPRelaxedClause *) {} +void OMPClauseWriter::VisitOMPWeakClause(OMPWeakClause *) {} + void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {} void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {} @@ -7325,3 +7878,208 @@ void ASTRecordWriter::writeOMPChildren(OMPChildren *Data) { for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I) AddStmt(Data->getChildren()[I]); } + +void ASTRecordWriter::writeOpenACCVarList(const OpenACCClauseWithVarList *C) { + writeUInt32(C->getVarList().size()); + for (Expr *E : C->getVarList()) + AddStmt(E); +} + +void ASTRecordWriter::writeOpenACCIntExprList(ArrayRef<Expr *> Exprs) { + writeUInt32(Exprs.size()); + for (Expr *E : Exprs) + AddStmt(E); +} + +void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { + writeEnum(C->getClauseKind()); + writeSourceLocation(C->getBeginLoc()); + writeSourceLocation(C->getEndLoc()); + + switch (C->getClauseKind()) { + case OpenACCClauseKind::Default: { + const auto *DC = cast<OpenACCDefaultClause>(C); + writeSourceLocation(DC->getLParenLoc()); + writeEnum(DC->getDefaultClauseKind()); + return; + } + case OpenACCClauseKind::If: { + const auto *IC = cast<OpenACCIfClause>(C); + writeSourceLocation(IC->getLParenLoc()); + AddStmt(const_cast<Expr*>(IC->getConditionExpr())); + return; + } + case OpenACCClauseKind::Self: { + const auto *SC = cast<OpenACCSelfClause>(C); + writeSourceLocation(SC->getLParenLoc()); + writeBool(SC->hasConditionExpr()); + if (SC->hasConditionExpr()) + AddStmt(const_cast<Expr*>(SC->getConditionExpr())); + return; + } + case OpenACCClauseKind::NumGangs: { + const auto *NGC = cast<OpenACCNumGangsClause>(C); + writeSourceLocation(NGC->getLParenLoc()); + writeUInt32(NGC->getIntExprs().size()); + for (Expr *E : NGC->getIntExprs()) + AddStmt(E); + return; + } + case OpenACCClauseKind::NumWorkers: { + const auto *NWC = cast<OpenACCNumWorkersClause>(C); + writeSourceLocation(NWC->getLParenLoc()); + AddStmt(const_cast<Expr*>(NWC->getIntExpr())); + return; + } + case OpenACCClauseKind::VectorLength: { + const auto *NWC = cast<OpenACCVectorLengthClause>(C); + writeSourceLocation(NWC->getLParenLoc()); + AddStmt(const_cast<Expr*>(NWC->getIntExpr())); + return; + } + case OpenACCClauseKind::Private: { + const auto *PC = cast<OpenACCPrivateClause>(C); + writeSourceLocation(PC->getLParenLoc()); + writeOpenACCVarList(PC); + return; + } + case OpenACCClauseKind::FirstPrivate: { + const auto *FPC = cast<OpenACCFirstPrivateClause>(C); + writeSourceLocation(FPC->getLParenLoc()); + writeOpenACCVarList(FPC); + return; + } + case OpenACCClauseKind::Attach: { + const auto *AC = cast<OpenACCAttachClause>(C); + writeSourceLocation(AC->getLParenLoc()); + writeOpenACCVarList(AC); + return; + } + case OpenACCClauseKind::DevicePtr: { + const auto *DPC = cast<OpenACCDevicePtrClause>(C); + writeSourceLocation(DPC->getLParenLoc()); + writeOpenACCVarList(DPC); + return; + } + case OpenACCClauseKind::NoCreate: { + const auto *NCC = cast<OpenACCNoCreateClause>(C); + writeSourceLocation(NCC->getLParenLoc()); + writeOpenACCVarList(NCC); + return; + } + case OpenACCClauseKind::Present: { + const auto *PC = cast<OpenACCPresentClause>(C); + writeSourceLocation(PC->getLParenLoc()); + writeOpenACCVarList(PC); + return; + } + case OpenACCClauseKind::Copy: + case OpenACCClauseKind::PCopy: + case OpenACCClauseKind::PresentOrCopy: { + const auto *CC = cast<OpenACCCopyClause>(C); + writeSourceLocation(CC->getLParenLoc()); + writeOpenACCVarList(CC); + return; + } + case OpenACCClauseKind::CopyIn: + case OpenACCClauseKind::PCopyIn: + case OpenACCClauseKind::PresentOrCopyIn: { + const auto *CIC = cast<OpenACCCopyInClause>(C); + writeSourceLocation(CIC->getLParenLoc()); + writeBool(CIC->isReadOnly()); + writeOpenACCVarList(CIC); + return; + } + case OpenACCClauseKind::CopyOut: + case OpenACCClauseKind::PCopyOut: + case OpenACCClauseKind::PresentOrCopyOut: { + const auto *COC = cast<OpenACCCopyOutClause>(C); + writeSourceLocation(COC->getLParenLoc()); + writeBool(COC->isZero()); + writeOpenACCVarList(COC); + return; + } + case OpenACCClauseKind::Create: + case OpenACCClauseKind::PCreate: + case OpenACCClauseKind::PresentOrCreate: { + const auto *CC = cast<OpenACCCreateClause>(C); + writeSourceLocation(CC->getLParenLoc()); + writeBool(CC->isZero()); + writeOpenACCVarList(CC); + return; + } + case OpenACCClauseKind::Async: { + const auto *AC = cast<OpenACCAsyncClause>(C); + writeSourceLocation(AC->getLParenLoc()); + writeBool(AC->hasIntExpr()); + if (AC->hasIntExpr()) + AddStmt(const_cast<Expr*>(AC->getIntExpr())); + return; + } + case OpenACCClauseKind::Wait: { + const auto *WC = cast<OpenACCWaitClause>(C); + writeSourceLocation(WC->getLParenLoc()); + writeBool(WC->getDevNumExpr()); + if (Expr *DNE = WC->getDevNumExpr()) + AddStmt(DNE); + writeSourceLocation(WC->getQueuesLoc()); + + writeOpenACCIntExprList(WC->getQueueIdExprs()); + return; + } + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: { + const auto *DTC = cast<OpenACCDeviceTypeClause>(C); + writeSourceLocation(DTC->getLParenLoc()); + writeUInt32(DTC->getArchitectures().size()); + for (const DeviceTypeArgument &Arg : DTC->getArchitectures()) { + writeBool(Arg.first); + if (Arg.first) + AddIdentifierRef(Arg.first); + writeSourceLocation(Arg.second); + } + return; + } + case OpenACCClauseKind::Reduction: { + const auto *RC = cast<OpenACCReductionClause>(C); + writeSourceLocation(RC->getLParenLoc()); + writeEnum(RC->getReductionOp()); + writeOpenACCVarList(RC); + return; + } + case OpenACCClauseKind::Seq: + case OpenACCClauseKind::Independent: + case OpenACCClauseKind::Auto: + // Nothing to do here, there is no additional information beyond the + // begin/end loc and clause kind. + return; + + case OpenACCClauseKind::Finalize: + case OpenACCClauseKind::IfPresent: + case OpenACCClauseKind::Worker: + case OpenACCClauseKind::Vector: + case OpenACCClauseKind::NoHost: + case OpenACCClauseKind::UseDevice: + case OpenACCClauseKind::Delete: + case OpenACCClauseKind::Detach: + case OpenACCClauseKind::Device: + case OpenACCClauseKind::DeviceResident: + case OpenACCClauseKind::Host: + case OpenACCClauseKind::Link: + case OpenACCClauseKind::Collapse: + case OpenACCClauseKind::Bind: + case OpenACCClauseKind::DeviceNum: + case OpenACCClauseKind::DefaultAsync: + case OpenACCClauseKind::Tile: + case OpenACCClauseKind::Gang: + case OpenACCClauseKind::Invalid: + llvm_unreachable("Clause serialization not yet implemented"); + } + llvm_unreachable("Invalid Clause Kind"); +} + +void ASTRecordWriter::writeOpenACCClauseList( + ArrayRef<const OpenACCClause *> Clauses) { + for (const OpenACCClause *Clause : Clauses) + writeOpenACCClause(Clause); +} diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp index 42583c09f009..17c774038571 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp @@ -40,11 +40,14 @@ namespace clang { serialization::DeclCode Code; unsigned AbbrevToUse; + bool GeneratingReducedBMI = false; + public: ASTDeclWriter(ASTWriter &Writer, ASTContext &Context, - ASTWriter::RecordDataImpl &Record) + ASTWriter::RecordDataImpl &Record, bool GeneratingReducedBMI) : Writer(Writer), Context(Context), Record(Writer, Record), - Code((serialization::DeclCode)0), AbbrevToUse(0) {} + Code((serialization::DeclCode)0), AbbrevToUse(0), + GeneratingReducedBMI(GeneratingReducedBMI) {} uint64_t Emit(Decl *D) { if (!Code) @@ -220,9 +223,9 @@ namespace clang { assert(!Common->LazySpecializations); } - ArrayRef<DeclID> LazySpecializations; + ArrayRef<GlobalDeclID> LazySpecializations; if (auto *LS = Common->LazySpecializations) - LazySpecializations = llvm::ArrayRef(LS + 1, LS[0]); + LazySpecializations = llvm::ArrayRef(LS + 1, LS[0].getRawValue()); // Add a slot to the record for the number of specializations. unsigned I = Record.size(); @@ -240,7 +243,9 @@ namespace clang { assert(D->isCanonicalDecl() && "non-canonical decl in set"); AddFirstDeclFromEachModule(D, /*IncludeLocal*/true); } - Record.append(LazySpecializations.begin(), LazySpecializations.end()); + Record.append( + DeclIDIterator<GlobalDeclID, DeclID>(LazySpecializations.begin()), + DeclIDIterator<GlobalDeclID, DeclID>(LazySpecializations.end())); // Update the size entry we added earlier. Record[I] = Record.size() - I - 1; @@ -270,6 +275,34 @@ namespace clang { }; } +bool clang::CanElideDeclDef(const Decl *D) { + if (auto *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->isInlined() || FD->isConstexpr()) + return false; + + if (FD->isDependentContext()) + return false; + + if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return false; + } + + if (auto *VD = dyn_cast<VarDecl>(D)) { + if (!VD->getDeclContext()->getRedeclContext()->isFileContext() || + VD->isInline() || VD->isConstexpr() || isa<ParmVarDecl>(VD) || + // Constant initialized variable may not affect the ABI, but they + // may be used in constant evaluation in the frontend, so we have + // to remain them. + VD->hasConstantInitialization()) + return false; + + if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return false; + } + + return true; +} + void ASTDeclWriter::Visit(Decl *D) { DeclVisitor<ASTDeclWriter>::Visit(D); @@ -285,9 +318,12 @@ void ASTDeclWriter::Visit(Decl *D) { // 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 (auto *FD = dyn_cast<FunctionDecl>(D)) { - Record.push_back(FD->doesThisDeclarationHaveABody()); - if (FD->doesThisDeclarationHaveABody()) - Record.AddFunctionDefinition(FD); + if (!GeneratingReducedBMI || !CanElideDeclDef(FD)) { + Record.push_back(FD->doesThisDeclarationHaveABody()); + if (FD->doesThisDeclarationHaveABody()) + Record.AddFunctionDefinition(FD); + } else + Record.push_back(0); } // Similar to FunctionDecls, handle VarDecl's initializer here and write it @@ -295,7 +331,10 @@ void ASTDeclWriter::Visit(Decl *D) { // we have finished recursive deserialization, because it can recursively // refer back to the variable. if (auto *VD = dyn_cast<VarDecl>(D)) { - Record.AddVarDeclInit(VD); + if (!GeneratingReducedBMI || !CanElideDeclDef(VD)) + Record.AddVarDeclInit(VD); + else + Record.push_back(0); } // And similarly for FieldDecls. We already serialized whether there is a @@ -488,16 +527,12 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { BitsPacker EnumDeclBits; EnumDeclBits.addBits(D->getNumPositiveBits(), /*BitWidth=*/8); EnumDeclBits.addBits(D->getNumNegativeBits(), /*BitWidth=*/8); - bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR(); - EnumDeclBits.addBit(ShouldSkipCheckingODR); EnumDeclBits.addBit(D->isScoped()); EnumDeclBits.addBit(D->isScopedUsingClassTag()); EnumDeclBits.addBit(D->isFixed()); Record.push_back(EnumDeclBits); - // We only perform ODR checks for decls not in GMF. - if (!ShouldSkipCheckingODR) - Record.push_back(D->getODRHash()); + Record.push_back(D->getODRHash()); if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) { Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); @@ -514,7 +549,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { !D->isTopLevelDeclInObjCContainer() && !CXXRecordDecl::classofKind(D->getKind()) && !D->getIntegerTypeSourceInfo() && !D->getMemberSpecializationInfo() && - !needsAnonymousDeclarationNumber(D) && !D->shouldSkipCheckingODR() && + !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier) AbbrevToUse = Writer.getDeclEnumAbbrev(); @@ -680,8 +715,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { // FIXME: stable encoding FunctionDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), 3); FunctionDeclBits.addBits((uint32_t)D->getStorageClass(), /*BitWidth=*/3); - bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR(); - FunctionDeclBits.addBit(ShouldSkipCheckingODR); FunctionDeclBits.addBit(D->isInlineSpecified()); FunctionDeclBits.addBit(D->isInlined()); FunctionDeclBits.addBit(D->hasSkippedBody()); @@ -707,12 +740,17 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { if (D->isExplicitlyDefaulted()) Record.AddSourceLocation(D->getDefaultLoc()); - // We only perform ODR checks for decls not in GMF. - if (!ShouldSkipCheckingODR) - Record.push_back(D->getODRHash()); + Record.push_back(D->getODRHash()); + + if (D->isDefaulted() || D->isDeletedAsWritten()) { + if (auto *FDI = D->getDefalutedOrDeletedInfo()) { + // Store both that there is an DefaultedOrDeletedInfo and whether it + // contains a DeletedMessage. + StringLiteral *DeletedMessage = FDI->getDeletedMessage(); + Record.push_back(1 | (DeletedMessage ? 2 : 0)); + if (DeletedMessage) + Record.AddStmt(DeletedMessage); - if (D->isDefaulted()) { - if (auto *FDI = D->getDefaultedFunctionInfo()) { Record.push_back(FDI->getUnqualifiedLookups().size()); for (DeclAccessPair P : FDI->getUnqualifiedLookups()) { Record.AddDeclRef(P.getDecl()); @@ -1122,7 +1160,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(VarDeclBits); if (ModulesCodegen) - Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D)); + Writer.AddDeclRef(D, Writer.ModularCodegenDecls); if (D->hasAttr<BlocksAttr>()) { BlockVarCopyInit Init = Writer.Context->getBlockVarCopyInit(D); @@ -1337,7 +1375,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { Record.AddSourceLocation(D->getBeginLoc()); Record.AddSourceLocation(D->getRBraceLoc()); - if (D->isOriginalNamespace()) + if (D->isFirstDecl()) Record.AddDeclRef(D->getAnonymousNamespace()); Code = serialization::DECL_NAMESPACE; @@ -1514,8 +1552,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->shouldSkipCheckingODR() && !D->hasExtInfo() && - !D->isExplicitlyDefaulted()) { + !D->hasExtInfo() && !D->isExplicitlyDefaulted()) { if (D->getTemplatedKind() == FunctionDecl::TK_NonTemplate || D->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate || D->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || @@ -1681,6 +1718,15 @@ void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (D->isFirstDecl()) AddTemplateSpecializations(D); + + // Force emitting the corresponding deduction guide in reduced BMI mode. + // Otherwise, the deduction guide may be optimized out incorrectly. + if (Writer.isGeneratingReducedBMI()) { + auto Name = Context.DeclarationNames.getCXXDeductionGuideName(D); + for (auto *DG : D->getDeclContext()->noload_lookup(Name)) + Writer.GetDeclRef(DG->getCanonicalDecl()); + } + Code = serialization::DECL_CLASS_TEMPLATE; } @@ -1710,20 +1756,28 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl()); } - // Explicit info. - Record.AddTypeSourceInfo(D->getTypeAsWritten()); - if (D->getTypeAsWritten()) { - Record.AddSourceLocation(D->getExternLoc()); + bool ExplicitInstantiation = + D->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDeclaration || + D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; + Record.push_back(ExplicitInstantiation); + if (ExplicitInstantiation) { + Record.AddSourceLocation(D->getExternKeywordLoc()); Record.AddSourceLocation(D->getTemplateKeywordLoc()); } + const ASTTemplateArgumentListInfo *ArgsWritten = + D->getTemplateArgsAsWritten(); + Record.push_back(!!ArgsWritten); + if (ArgsWritten) + Record.AddASTTemplateArgumentListInfo(ArgsWritten); + Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION; } void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { Record.AddTemplateParameterList(D->getTemplateParameters()); - Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); VisitClassTemplateSpecializationDecl(D); @@ -1757,13 +1811,22 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); } - // Explicit info. - Record.AddTypeSourceInfo(D->getTypeAsWritten()); - if (D->getTypeAsWritten()) { - Record.AddSourceLocation(D->getExternLoc()); + bool ExplicitInstantiation = + D->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDeclaration || + D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; + Record.push_back(ExplicitInstantiation); + if (ExplicitInstantiation) { + Record.AddSourceLocation(D->getExternKeywordLoc()); Record.AddSourceLocation(D->getTemplateKeywordLoc()); } + const ASTTemplateArgumentListInfo *ArgsWritten = + D->getTemplateArgsAsWritten(); + Record.push_back(!!ArgsWritten); + if (ArgsWritten) + Record.AddASTTemplateArgumentListInfo(ArgsWritten); + Record.AddTemplateArgumentList(&D->getTemplateArgs()); Record.AddSourceLocation(D->getPointOfInstantiation()); Record.push_back(D->getSpecializationKind()); @@ -1784,7 +1847,6 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D) { Record.AddTemplateParameterList(D->getTemplateParameters()); - Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); VisitVarTemplateSpecializationDecl(D); @@ -1828,7 +1890,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { !D->defaultArgumentWasInherited(); Record.push_back(OwnsDefaultArg); if (OwnsDefaultArg) - Record.AddTypeSourceInfo(D->getDefaultArgumentInfo()); + Record.AddTemplateArgumentLoc(D->getDefaultArgument()); if (!TC && !OwnsDefaultArg && D->getDeclContext() == D->getLexicalDeclContext() && @@ -1870,7 +1932,7 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { !D->defaultArgumentWasInherited(); Record.push_back(OwnsDefaultArg); if (OwnsDefaultArg) - Record.AddStmt(D->getDefaultArgument()); + Record.AddTemplateArgumentLoc(D->getDefaultArgument()); Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; } } @@ -1883,6 +1945,7 @@ void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { Record.push_back(D->getNumExpansionTemplateParameters()); VisitTemplateDecl(D); + Record.push_back(D->wasDeclaredWithTypename()); // TemplateParmPosition. Record.push_back(D->getDepth()); Record.push_back(D->getPosition()); @@ -1924,8 +1987,22 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { "You need to update the serializer after you change the " "DeclContextBits"); - Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC)); - Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC)); + uint64_t LexicalOffset = 0; + uint64_t VisibleOffset = 0; + + if (Writer.isGeneratingReducedBMI() && isa<NamespaceDecl>(DC) && + cast<NamespaceDecl>(DC)->isFromExplicitGlobalModule()) { + // In reduced BMI, delay writing lexical and visible block for namespace + // in the global module fragment. See the comments of DelayedNamespace for + // details. + Writer.DelayedNamespace.push_back(cast<NamespaceDecl>(DC)); + } else { + LexicalOffset = Writer.WriteDeclContextLexicalBlock(Context, DC); + VisibleOffset = Writer.WriteDeclContextVisibleBlock(Context, DC); + } + + Record.AddOffset(LexicalOffset); + Record.AddOffset(VisibleOffset); } const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) { @@ -2718,10 +2795,10 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { "serializing"); // Determine the ID for this declaration. - serialization::DeclID ID; + LocalDeclID ID; assert(!D->isFromASTFile() && "should not be emitting imported decl"); - serialization::DeclID &IDR = DeclIDs[D]; - if (IDR == 0) + LocalDeclID &IDR = DeclIDs[D]; + if (IDR.isInvalid()) IDR = NextDeclID++; ID = IDR; @@ -2729,7 +2806,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { assert(ID >= FirstDeclID && "invalid decl ID"); RecordData Record; - ASTDeclWriter W(*this, Context, Record); + ASTDeclWriter W(*this, Context, Record, GeneratingReducedBMI); // Build a record for this declaration W.Visit(D); @@ -2739,14 +2816,16 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { // Record the offset for this declaration SourceLocation Loc = D->getLocation(); - unsigned Index = ID - FirstDeclID; + SourceLocationEncoding::RawLocEncoding RawLoc = + getRawSourceLocationEncoding(getAdjustedLocation(Loc)); + + unsigned Index = ID.getRawValue() - FirstDeclID.getRawValue(); if (DeclOffsets.size() == Index) - DeclOffsets.emplace_back(getAdjustedLocation(Loc), Offset, - DeclTypesBlockStartOffset); + DeclOffsets.emplace_back(RawLoc, Offset, DeclTypesBlockStartOffset); else if (DeclOffsets.size() < Index) { // FIXME: Can/should this happen? DeclOffsets.resize(Index+1); - DeclOffsets[Index].setLocation(getAdjustedLocation(Loc)); + DeclOffsets[Index].setRawLoc(RawLoc); DeclOffsets[Index].setBitOffset(Offset, DeclTypesBlockStartOffset); } else { llvm_unreachable("declarations should be emitted in ID order"); @@ -2759,7 +2838,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { // Note declarations that should be deserialized eagerly so that we can add // them to a record in the AST file later. if (isRequiredDecl(D, Context, WritingModule)) - EagerlyDeserializedDecls.push_back(ID); + AddDeclRef(D, EagerlyDeserializedDecls); } void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { @@ -2795,7 +2874,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { } Record->push_back(ModulesCodegen); if (ModulesCodegen) - Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(FD)); + Writer->AddDeclRef(FD, Writer->ModularCodegenDecls); if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { Record->push_back(CD->getNumCtorInitializers()); if (CD->getNumCtorInitializers()) diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp index e5836f5dcbe9..caa222277f06 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp @@ -19,7 +19,7 @@ #include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/Token.h" -#include "clang/Sema/DeclSpec.h" +#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTRecordWriter.h" #include "llvm/Bitstream/BitstreamWriter.h" using namespace clang; @@ -38,7 +38,7 @@ namespace clang { unsigned AbbrevToUse; /// A helper that can help us to write a packed bit across function - /// calls. For example, we may write seperate bits in seperate functions: + /// calls. For example, we may write separate bits in separate functions: /// /// void VisitA(A* a) { /// Record.push_back(a->isSomething()); @@ -474,14 +474,12 @@ addConstraintSatisfaction(ASTRecordWriter &Record, if (!Satisfaction.IsSatisfied) { Record.push_back(Satisfaction.NumRecords); for (const auto &DetailRecord : Satisfaction) { - Record.AddStmt(const_cast<Expr *>(DetailRecord.first)); - auto *E = DetailRecord.second.dyn_cast<Expr *>(); - Record.push_back(E == nullptr); + auto *E = DetailRecord.dyn_cast<Expr *>(); + Record.push_back(/* IsDiagnostic */ E == nullptr); if (E) Record.AddStmt(E); else { - auto *Diag = DetailRecord.second.get<std::pair<SourceLocation, - StringRef> *>(); + auto *Diag = DetailRecord.get<std::pair<SourceLocation, StringRef> *>(); Record.AddSourceLocation(Diag->first); Record.AddString(Diag->second); } @@ -881,16 +879,21 @@ void ASTStmtWriter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E) { Code = serialization::EXPR_ARRAY_SUBSCRIPT; } -void ASTStmtWriter::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) { +void ASTStmtWriter::VisitArraySectionExpr(ArraySectionExpr *E) { VisitExpr(E); + Record.writeEnum(E->ASType); Record.AddStmt(E->getBase()); Record.AddStmt(E->getLowerBound()); Record.AddStmt(E->getLength()); - Record.AddStmt(E->getStride()); + if (E->isOMPArraySection()) + Record.AddStmt(E->getStride()); Record.AddSourceLocation(E->getColonLocFirst()); - Record.AddSourceLocation(E->getColonLocSecond()); + + if (E->isOMPArraySection()) + Record.AddSourceLocation(E->getColonLocSecond()); + Record.AddSourceLocation(E->getRBracketLoc()); - Code = serialization::EXPR_OMP_ARRAY_SECTION; + Code = serialization::EXPR_ARRAY_SECTION; } void ASTStmtWriter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) { @@ -970,10 +973,7 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { VisitExpr(E); bool HasQualifier = E->hasQualifier(); - bool HasFoundDecl = - E->hasQualifierOrFoundDecl() && - (E->getFoundDecl().getDecl() != E->getMemberDecl() || - E->getFoundDecl().getAccess() != E->getMemberDecl()->getAccess()); + bool HasFoundDecl = E->hasFoundDecl(); bool HasTemplateInfo = E->hasTemplateKWAndArgsInfo(); unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -995,15 +995,15 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { CurrentPackingBits.addBits(E->isNonOdrUse(), /*Width=*/2); Record.AddSourceLocation(E->getOperatorLoc()); + if (HasQualifier) + Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); + if (HasFoundDecl) { DeclAccessPair FoundDecl = E->getFoundDecl(); Record.AddDeclRef(FoundDecl.getDecl()); CurrentPackingBits.addBits(FoundDecl.getAccess(), /*BitWidth=*/2); } - if (HasQualifier) - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - if (HasTemplateInfo) AddTemplateKWAndArgsInfo(*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(), E->getTrailingObjects<TemplateArgumentLoc>()); @@ -1261,6 +1261,16 @@ void ASTStmtWriter::VisitSourceLocExpr(SourceLocExpr *E) { Code = serialization::EXPR_SOURCE_LOC; } +void ASTStmtWriter::VisitEmbedExpr(EmbedExpr *E) { + VisitExpr(E); + Record.AddSourceLocation(E->getBeginLoc()); + Record.AddSourceLocation(E->getEndLoc()); + Record.AddStmt(E->getDataStringLiteral()); + Record.writeUInt32(E->getStartingElementPos()); + Record.writeUInt32(E->getDataElementCount()); + Code = serialization::EXPR_BUILTIN_PP_EMBED; +} + void ASTStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) { VisitExpr(E); Record.AddSourceLocation(E->getAmpAmpLoc()); @@ -1842,6 +1852,7 @@ void ASTStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) { VisitExpr(E); Record.AddSourceLocation(E->getLocation()); Record.push_back(E->isImplicit()); + Record.push_back(E->isCapturedByCopyInLambdaWithExplicitObjectParameter()); Code = serialization::EXPR_CXX_THIS; } @@ -2085,9 +2096,24 @@ void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); CurrentPackingBits.addBit(E->requiresADL()); - CurrentPackingBits.addBit(E->isOverloaded()); Record.AddDeclRef(E->getNamingClass()); Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP; + + if (Writer.isWritingStdCXXNamedModules() && Writer.getChain()) { + // Referencing all the possible declarations to make sure the change get + // propagted. + DeclarationName Name = E->getName(); + for (auto *Found : + Writer.getASTContext().getTranslationUnitDecl()->lookup(Name)) + if (Found->isFromASTFile()) + Writer.GetDeclRef(Found); + + llvm::SmallVector<NamespaceDecl *> ExternalNSs; + Writer.getChain()->ReadKnownNamespaces(ExternalNSs); + for (auto *NS : ExternalNSs) + for (auto *Found : NS->lookup(Name)) + Writer.GetDeclRef(Found); + } } void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) { @@ -2153,6 +2179,19 @@ void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { Code = serialization::EXPR_SIZEOF_PACK; } +void ASTStmtWriter::VisitPackIndexingExpr(PackIndexingExpr *E) { + VisitExpr(E); + Record.push_back(E->TransformedExpressions); + Record.push_back(E->ExpandedToEmptyPack); + Record.AddSourceLocation(E->getEllipsisLoc()); + Record.AddSourceLocation(E->getRSquareLoc()); + Record.AddStmt(E->getPackIdExpression()); + Record.AddStmt(E->getIndexExpr()); + for (Expr *Sub : E->getExpressions()) + Record.AddStmt(Sub); + Code = serialization::EXPR_PACK_INDEXING; +} + void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); @@ -2398,6 +2437,16 @@ void ASTStmtWriter::VisitOMPUnrollDirective(OMPUnrollDirective *D) { Code = serialization::STMT_OMP_UNROLL_DIRECTIVE; } +void ASTStmtWriter::VisitOMPReverseDirective(OMPReverseDirective *D) { + VisitOMPLoopTransformationDirective(D); + Code = serialization::STMT_OMP_REVERSE_DIRECTIVE; +} + +void ASTStmtWriter::VisitOMPInterchangeDirective(OMPInterchangeDirective *D) { + VisitOMPLoopTransformationDirective(D); + Code = serialization::STMT_OMP_INTERCHANGE_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPForDirective(OMPForDirective *D) { VisitOMPLoopDirective(D); Record.writeBool(D->hasCancel()); @@ -2810,6 +2859,7 @@ void ASTStmtWriter::VisitOMPTeamsGenericLoopDirective( void ASTStmtWriter::VisitOMPTargetTeamsGenericLoopDirective( OMPTargetTeamsGenericLoopDirective *D) { VisitOMPLoopDirective(D); + Record.writeBool(D->canBeParallelFor()); Code = serialization::STMT_OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE; } @@ -2826,6 +2876,35 @@ void ASTStmtWriter::VisitOMPTargetParallelGenericLoopDirective( } //===----------------------------------------------------------------------===// +// OpenACC Constructs/Directives. +//===----------------------------------------------------------------------===// +void ASTStmtWriter::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) { + Record.push_back(S->clauses().size()); + Record.writeEnum(S->Kind); + Record.AddSourceRange(S->Range); + Record.AddSourceLocation(S->DirectiveLoc); + Record.writeOpenACCClauseList(S->clauses()); +} + +void ASTStmtWriter::VisitOpenACCAssociatedStmtConstruct( + OpenACCAssociatedStmtConstruct *S) { + VisitOpenACCConstructStmt(S); + Record.AddStmt(S->getAssociatedStmt()); +} + +void ASTStmtWriter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) { + VisitStmt(S); + VisitOpenACCAssociatedStmtConstruct(S); + Code = serialization::STMT_OPENACC_COMPUTE_CONSTRUCT; +} + +void ASTStmtWriter::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) { + VisitStmt(S); + VisitOpenACCAssociatedStmtConstruct(S); + Code = serialization::STMT_OPENACC_LOOP_CONSTRUCT; +} + +//===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/contrib/llvm-project/clang/lib/Serialization/GeneratePCH.cpp b/contrib/llvm-project/clang/lib/Serialization/GeneratePCH.cpp index cf8084333811..cc06106a4770 100644 --- a/contrib/llvm-project/clang/lib/Serialization/GeneratePCH.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/GeneratePCH.cpp @@ -12,7 +12,9 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Serialization/ASTWriter.h" @@ -21,15 +23,16 @@ using namespace clang; PCHGenerator::PCHGenerator( - const Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer, + Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile, + StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, bool AllowASTWithErrors, bool IncludeTimestamps, - bool BuildingImplicitModule, bool ShouldCacheASTInMemory) + bool BuildingImplicitModule, bool ShouldCacheASTInMemory, + bool GeneratingReducedBMI) : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()), SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data), Writer(Stream, this->Buffer->Data, ModuleCache, Extensions, - IncludeTimestamps, BuildingImplicitModule), + IncludeTimestamps, BuildingImplicitModule, GeneratingReducedBMI), AllowASTWithErrors(AllowASTWithErrors), ShouldCacheASTInMemory(ShouldCacheASTInMemory) { this->Buffer->IsComplete = false; @@ -38,6 +41,21 @@ PCHGenerator::PCHGenerator( PCHGenerator::~PCHGenerator() { } +Module *PCHGenerator::getEmittingModule(ASTContext &) { + Module *M = nullptr; + + if (PP.getLangOpts().isCompilingModule()) { + M = PP.getHeaderSearchInfo().lookupModule(PP.getLangOpts().CurrentModule, + SourceLocation(), + /*AllowSearch*/ false); + if (!M) + assert(PP.getDiagnostics().hasErrorOccurred() && + "emitting module but current module doesn't exist"); + } + + return M; +} + void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { // Don't create a PCH if there were fatal failures during module loading. if (PP.getModuleLoader().HadFatalFailure) @@ -47,16 +65,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { if (hasErrors && !AllowASTWithErrors) return; - Module *Module = nullptr; - if (PP.getLangOpts().isCompilingModule()) { - Module = PP.getHeaderSearchInfo().lookupModule( - PP.getLangOpts().CurrentModule, SourceLocation(), - /*AllowSearch*/ false); - if (!Module) { - assert(hasErrors && "emitting module but current module doesn't exist"); - return; - } - } + Module *Module = getEmittingModule(Ctx); // Errors that do not prevent the PCH from being written should not cause the // overall compilation to fail either. @@ -78,3 +87,53 @@ ASTMutationListener *PCHGenerator::GetASTMutationListener() { ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { return &Writer; } + +void PCHGenerator::anchor() {} + +CXX20ModulesGenerator::CXX20ModulesGenerator(Preprocessor &PP, + InMemoryModuleCache &ModuleCache, + StringRef OutputFile, + bool GeneratingReducedBMI) + : PCHGenerator( + PP, ModuleCache, OutputFile, llvm::StringRef(), + std::make_shared<PCHBuffer>(), + /*Extensions=*/ArrayRef<std::shared_ptr<ModuleFileExtension>>(), + /*AllowASTWithErrors*/ false, /*IncludeTimestamps=*/false, + /*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false, + GeneratingReducedBMI) {} + +Module *CXX20ModulesGenerator::getEmittingModule(ASTContext &Ctx) { + Module *M = Ctx.getCurrentNamedModule(); + assert(M && M->isNamedModuleUnit() && + "CXX20ModulesGenerator should only be used with C++20 Named modules."); + return M; +} + +void CXX20ModulesGenerator::HandleTranslationUnit(ASTContext &Ctx) { + // FIMXE: We'd better to wrap such options to a new class ASTWriterOptions + // since this is not about searching header really. + HeaderSearchOptions &HSOpts = + getPreprocessor().getHeaderSearchInfo().getHeaderSearchOpts(); + HSOpts.ModulesSkipDiagnosticOptions = true; + HSOpts.ModulesSkipHeaderSearchPaths = true; + + PCHGenerator::HandleTranslationUnit(Ctx); + + if (!isComplete()) + return; + + std::error_code EC; + auto OS = std::make_unique<llvm::raw_fd_ostream>(getOutputFile(), EC); + if (EC) { + getDiagnostics().Report(diag::err_fe_unable_to_open_output) + << getOutputFile() << EC.message() << "\n"; + return; + } + + *OS << getBufferPtr()->Data; + OS->flush(); +} + +void CXX20ModulesGenerator::anchor() {} + +void ReducedBMIGenerator::anchor() {} diff --git a/contrib/llvm-project/clang/lib/Serialization/GlobalModuleIndex.cpp b/contrib/llvm-project/clang/lib/Serialization/GlobalModuleIndex.cpp index dd4fc3e00905..1163943c5dff 100644 --- a/contrib/llvm-project/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -13,7 +13,6 @@ #include "clang/Serialization/GlobalModuleIndex.h" #include "ASTReaderInternals.h" #include "clang/Basic/FileManager.h" -#include "clang/Lex/HeaderSearch.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ModuleFile.h" #include "clang/Serialization/PCHContainerOperations.h" @@ -89,10 +88,8 @@ public: static std::pair<unsigned, unsigned> ReadKeyDataLength(const unsigned char*& d) { using namespace llvm::support; - unsigned KeyLen = - endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d); - unsigned DataLen = - endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d); + unsigned KeyLen = endian::readNext<uint16_t, llvm::endianness::little>(d); + unsigned DataLen = endian::readNext<uint16_t, llvm::endianness::little>(d); return std::make_pair(KeyLen, DataLen); } @@ -113,8 +110,7 @@ public: data_type Result; while (DataLen > 0) { - unsigned ID = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d); + unsigned ID = endian::readNext<uint32_t, llvm::endianness::little>(d); Result.push_back(ID); DataLen -= 4; } @@ -514,8 +510,8 @@ namespace { // The first bit indicates whether this identifier is interesting. // That's all we care about. using namespace llvm::support; - unsigned RawID = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d); + IdentifierID RawID = + endian::readNext<IdentifierID, llvm::endianness::little>(d); bool IsInteresting = RawID & 0x01; return std::make_pair(k, IsInteresting); } diff --git a/contrib/llvm-project/clang/lib/Serialization/ModuleFile.cpp b/contrib/llvm-project/clang/lib/Serialization/ModuleFile.cpp index db896fd36115..4858cdbda554 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ModuleFile.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ModuleFile.cpp @@ -59,11 +59,9 @@ LLVM_DUMP_METHOD void ModuleFile::dump() { // Remapping tables. llvm::errs() << " Base source location offset: " << SLocEntryBaseOffset << '\n'; - dumpLocalRemap("Source location offset local -> global map", SLocRemap); llvm::errs() << " Base identifier ID: " << BaseIdentifierID << '\n' << " Number of identifiers: " << LocalNumIdentifiers << '\n'; - dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap); llvm::errs() << " Base macro ID: " << BaseMacroID << '\n' << " Number of macros: " << LocalNumMacros << '\n'; @@ -86,9 +84,7 @@ LLVM_DUMP_METHOD void ModuleFile::dump() { llvm::errs() << " Base type index: " << BaseTypeIndex << '\n' << " Number of types: " << LocalNumTypes << '\n'; - dumpLocalRemap("Type index local -> global map", TypeRemap); - llvm::errs() << " Base decl ID: " << BaseDeclID << '\n' + llvm::errs() << " Base decl index: " << BaseDeclIndex << '\n' << " Number of decls: " << LocalNumDecls << '\n'; - dumpLocalRemap("Decl ID local -> global map", DeclRemap); } diff --git a/contrib/llvm-project/clang/lib/Serialization/ModuleFileExtension.cpp b/contrib/llvm-project/clang/lib/Serialization/ModuleFileExtension.cpp index 95fff41e0d7a..729529b5fca1 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ModuleFileExtension.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ModuleFileExtension.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// #include "clang/Serialization/ModuleFileExtension.h" -#include "llvm/ADT/Hashing.h" + using namespace clang; char ModuleFileExtension::ID = 0; diff --git a/contrib/llvm-project/clang/lib/Serialization/MultiOnDiskHashTable.h b/contrib/llvm-project/clang/lib/Serialization/MultiOnDiskHashTable.h index 2402a628b512..a0d75ec3a9e7 100644 --- a/contrib/llvm-project/clang/lib/Serialization/MultiOnDiskHashTable.h +++ b/contrib/llvm-project/clang/lib/Serialization/MultiOnDiskHashTable.h @@ -200,11 +200,11 @@ public: storage_type Ptr = Data; uint32_t BucketOffset = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Ptr); + endian::readNext<uint32_t, llvm::endianness::little>(Ptr); // Read the list of overridden files. uint32_t NumFiles = - endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Ptr); + endian::readNext<uint32_t, llvm::endianness::little>(Ptr); // FIXME: Add a reserve() to TinyPtrVector so that we don't need to make // an additional copy. llvm::SmallVector<file_type, 16> OverriddenFiles; diff --git a/contrib/llvm-project/clang/lib/Serialization/PCHContainerOperations.cpp b/contrib/llvm-project/clang/lib/Serialization/PCHContainerOperations.cpp index 56ca3394385b..4aedb7debcff 100644 --- a/contrib/llvm-project/clang/lib/Serialization/PCHContainerOperations.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/PCHContainerOperations.cpp @@ -12,8 +12,6 @@ #include "clang/Serialization/PCHContainerOperations.h" #include "clang/AST/ASTConsumer.h" -#include "clang/Lex/ModuleLoader.h" -#include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Support/raw_ostream.h" #include <utility> |