diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 |
commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/clang/lib/Serialization | |
parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Serialization')
8 files changed, 1205 insertions, 2258 deletions
diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTCommon.cpp index 26b722b6b14a..96bc47dcdb4e 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTCommon.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTCommon.cpp @@ -412,6 +412,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::PragmaComment: case Decl::PragmaDetectMismatch: case Decl::FileScopeAsm: + case Decl::TopLevelStmt: case Decl::AccessSpec: case Decl::Friend: case Decl::FriendTemplate: @@ -430,9 +431,11 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::Decomposition: case Decl::Binding: case Decl::Concept: + case Decl::ImplicitConceptSpecialization: case Decl::LifetimeExtendedTemporary: case Decl::RequiresExprBody: case Decl::UnresolvedUsingIfExists: + case Decl::HLSLBuffer: return false; // These indirectly derive from Redeclarable<T> but are not actually @@ -472,7 +475,7 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { if (auto *VD = dyn_cast<VarDecl>(D)) return VD->isStaticLocal(); // FIXME: What about CapturedDecls (and declarations nested within them)? - return isa<TagDecl>(D) || isa<BlockDecl>(D); + return isa<TagDecl, BlockDecl>(D); } // Otherwise, we only care about anonymous class members / block-scope decls. @@ -482,5 +485,5 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { return false; if (!isa<RecordDecl, ObjCInterfaceDecl>(D->getLexicalDeclContext())) return false; - return isa<TagDecl>(D) || isa<FieldDecl>(D); + return isa<TagDecl, FieldDecl>(D); } diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp index d1e47c1045de..4d72596b7439 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp @@ -30,6 +30,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/ODRDiagsEmitter.h" #include "clang/AST/ODRHash.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/RawCommentList.h" @@ -96,8 +97,6 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallPtrSet.h" @@ -121,6 +120,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/Timer.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" @@ -134,6 +134,7 @@ #include <limits> #include <map> #include <memory> +#include <optional> #include <string> #include <system_error> #include <tuple> @@ -1223,7 +1224,7 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, auto &Lex = LexicalDecls[DC]; if (!Lex.first) { Lex = std::make_pair( - &M, llvm::makeArrayRef( + &M, llvm::ArrayRef( reinterpret_cast<const llvm::support::unaligned_uint32_t *>( Blob.data()), Blob.size() / 4)); @@ -1301,10 +1302,10 @@ void ASTReader::Error(llvm::Error &&Err) const { switch (NumArgs) { case 3: Arg3 = Diag.getStringArg(2); - LLVM_FALLTHROUGH; + [[fallthrough]]; case 2: Arg2 = Diag.getStringArg(1); - LLVM_FALLTHROUGH; + [[fallthrough]]; case 1: Arg1 = Diag.getStringArg(0); } @@ -1336,10 +1337,7 @@ void ASTReader::ParseLineTable(ModuleFile &F, const RecordData &Record) { // Parse the line entries std::vector<LineEntry> Entries; while (Idx < Record.size()) { - int FID = Record[Idx++]; - assert(FID >= 0 && "Serialized line entries for non-local file."); - // Remap FileID from 1-based old view. - FID += F.SLocEntryBaseID - 1; + FileID FID = ReadFileID(F, Record, Idx); // Extract the line entries unsigned NumEntries = Record[Idx++]; @@ -1356,7 +1354,7 @@ void ASTReader::ParseLineTable(ModuleFile &F, const RecordData &Record) { Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID, FileKind, IncludeOffset)); } - LineTable.AddEntry(FileID::get(FID), Entries); + LineTable.AddEntry(FID, Entries); } } @@ -1421,41 +1419,6 @@ llvm::Error ASTReader::ReadSourceManagerBlock(ModuleFile &F) { } } -/// If a header file is not found at the path that we expect it to be -/// and the PCH file was moved from its original location, try to resolve the -/// file by assuming that header+PCH were moved together and the header is in -/// the same place relative to the PCH. -static std::string -resolveFileRelativeToOriginalDir(const std::string &Filename, - const std::string &OriginalDir, - const std::string &CurrDir) { - assert(OriginalDir != CurrDir && - "No point trying to resolve the file if the PCH dir didn't change"); - - using namespace llvm::sys; - - SmallString<128> filePath(Filename); - fs::make_absolute(filePath); - assert(path::is_absolute(OriginalDir)); - SmallString<128> currPCHPath(CurrDir); - - path::const_iterator fileDirI = path::begin(path::parent_path(filePath)), - fileDirE = path::end(path::parent_path(filePath)); - path::const_iterator origDirI = path::begin(OriginalDir), - origDirE = path::end(OriginalDir); - // Skip the common path components from filePath and OriginalDir. - while (fileDirI != fileDirE && origDirI != origDirE && - *fileDirI == *origDirI) { - ++fileDirI; - ++origDirI; - } - for (; origDirI != origDirE; ++origDirI) - path::append(currPCHPath, ".."); - path::append(currPCHPath, fileDirI, fileDirE); - path::append(currPCHPath, path::filename(Filename)); - return std::string(currPCHPath.str()); -} - bool ASTReader::ReadSLocEntry(int ID) { if (ID == 0) return false; @@ -1488,19 +1451,25 @@ bool ASTReader::ReadSLocEntry(int ID) { unsigned RecCode = MaybeRecCode.get(); if (RecCode == SM_SLOC_BUFFER_BLOB_COMPRESSED) { - if (!llvm::compression::zlib::isAvailable()) { - Error("zlib is not available"); + // Inspect the first byte to differentiate zlib (\x78) and zstd + // (little-endian 0xFD2FB528). + const llvm::compression::Format F = + Blob.size() > 0 && Blob.data()[0] == 0x78 + ? llvm::compression::Format::Zlib + : llvm::compression::Format::Zstd; + if (const char *Reason = llvm::compression::getReasonIfUnsupported(F)) { + Error(Reason); return nullptr; } - SmallVector<uint8_t, 0> Uncompressed; - if (llvm::Error E = llvm::compression::zlib::uncompress( - llvm::arrayRefFromStringRef(Blob), Uncompressed, Record[0])) { + SmallVector<uint8_t, 0> Decompressed; + if (llvm::Error E = llvm::compression::decompress( + F, llvm::arrayRefFromStringRef(Blob), Decompressed, Record[0])) { Error("could not decompress embedded file contents: " + llvm::toString(std::move(E))); return nullptr; } return llvm::MemoryBuffer::getMemBufferCopy( - llvm::toStringRef(Uncompressed), Name); + llvm::toStringRef(Decompressed), Name); } else if (RecCode == SM_SLOC_BUFFER_BLOB) { return llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name, true); } else { @@ -1551,7 +1520,7 @@ bool ASTReader::ReadSLocEntry(int ID) { // we will also try to fail gracefully by setting up the SLocEntry. unsigned InputID = Record[4]; InputFile IF = getInputFile(*F, InputID); - Optional<FileEntryRef> File = IF.getFile(); + OptionalFileEntryRef File = IF.getFile(); bool OverriddenBuffer = IF.isOverridden(); // Note that we only check if a File was returned. If it was out-of-date @@ -1579,8 +1548,8 @@ bool ASTReader::ReadSLocEntry(int ID) { if (NumFileDecls && ContextObj) { const DeclID *FirstDecl = F->FileSortedDecls + Record[6]; assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); - FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl, - NumFileDecls)); + FileDeclIDs[FID] = + FileDeclsInfo(F, llvm::ArrayRef(FirstDecl, NumFileDecls)); } const SrcMgr::ContentCache &ContentCache = @@ -1699,11 +1668,38 @@ Token ASTReader::ReadToken(ModuleFile &F, const RecordDataImpl &Record, Token Tok; Tok.startToken(); Tok.setLocation(ReadSourceLocation(F, Record, Idx)); - Tok.setLength(Record[Idx++]); - if (IdentifierInfo *II = getLocalIdentifier(F, Record[Idx++])) - Tok.setIdentifierInfo(II); Tok.setKind((tok::TokenKind)Record[Idx++]); Tok.setFlag((Token::TokenFlags)Record[Idx++]); + + if (Tok.isAnnotation()) { + Tok.setAnnotationEndLoc(ReadSourceLocation(F, Record, Idx)); + switch (Tok.getKind()) { + case tok::annot_pragma_loop_hint: { + auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; + Info->PragmaName = ReadToken(F, Record, Idx); + Info->Option = ReadToken(F, Record, Idx); + unsigned NumTokens = Record[Idx++]; + SmallVector<Token, 4> Toks; + Toks.reserve(NumTokens); + for (unsigned I = 0; I < NumTokens; ++I) + Toks.push_back(ReadToken(F, Record, Idx)); + Info->Toks = llvm::ArrayRef(Toks).copy(PP.getPreprocessorAllocator()); + Tok.setAnnotationValue(static_cast<void *>(Info)); + break; + } + // Some annotation tokens do not use the PtrData field. + case tok::annot_pragma_openmp: + case tok::annot_pragma_openmp_end: + case tok::annot_pragma_unused: + break; + default: + llvm_unreachable("missing deserialization code for annotation token"); + } + } else { + Tok.setLength(Record[Idx++]); + if (IdentifierInfo *II = getLocalIdentifier(F, Record[Idx++])) + Tok.setIdentifierInfo(II); + } return Tok; } @@ -1935,8 +1931,8 @@ 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, little, unaligned>(d); - auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 3); - LocalSMID >>= 2; + auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 7); + LocalSMID >>= 3; // This header is part of a module. Associate it with the module to enable // implicit module import. @@ -1951,9 +1947,9 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, Reader.ResolveImportedPath(M, Filename); // FIXME: NameAsWritten Module::Header H = {std::string(key.Filename), "", - *FileMgr.getFile(Filename)}; + FileMgr.getOptionalFileRef(Filename)}; ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true); - HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader); + HFI.isModuleHeader |= ModuleMap::isModular(HeaderRole); } // This HeaderFileInfo was externally loaded. @@ -2269,8 +2265,15 @@ bool ASTReader::shouldDisableValidationForFile( return false; } -ASTReader::InputFileInfo -ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) { +InputFileInfo ASTReader::getInputFileInfo(ModuleFile &F, unsigned ID) { + // If this ID is bogus, just return an empty input file. + if (ID == 0 || ID > F.InputFileInfosLoaded.size()) + return InputFileInfo(); + + // If we've already loaded this input file, return it. + if (!F.InputFileInfosLoaded[ID - 1].Filename.empty()) + return F.InputFileInfosLoaded[ID - 1]; + // Go find this input file. BitstreamCursor &Cursor = F.InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); @@ -2323,6 +2326,9 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) { } R.ContentHash = (static_cast<uint64_t>(Record[1]) << 32) | static_cast<uint64_t>(Record[0]); + + // Note that we've loaded this input file info. + F.InputFileInfosLoaded[ID - 1] = R; return R; } @@ -2347,7 +2353,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { consumeError(std::move(Err)); } - InputFileInfo FI = readInputFileInfo(F, ID); + InputFileInfo FI = getInputFileInfo(F, ID); off_t StoredSize = FI.StoredSize; time_t StoredTime = FI.StoredTime; bool Overridden = FI.Overridden; @@ -2355,18 +2361,8 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { StringRef Filename = FI.Filename; uint64_t StoredContentHash = FI.ContentHash; - OptionalFileEntryRefDegradesToFileEntryPtr File = - expectedToOptional(FileMgr.getFileRef(Filename, /*OpenFile=*/false)); - - // If we didn't find the file, resolve it relative to the - // original directory from which this AST file was created. - if (!File && !F.OriginalDir.empty() && !F.BaseDirectory.empty() && - F.OriginalDir != F.BaseDirectory) { - std::string Resolved = resolveFileRelativeToOriginalDir( - std::string(Filename), F.OriginalDir, F.BaseDirectory); - if (!Resolved.empty()) - File = expectedToOptional(FileMgr.getFileRef(Resolved)); - } + OptionalFileEntryRefDegradesToFileEntryPtr File = OptionalFileEntryRef( + expectedToOptional(FileMgr.getFileRef(Filename, /*OpenFile=*/false))); // For an overridden file, create a virtual file with the stored // size/timestamp. @@ -2413,8 +2409,8 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { Content, None, } Kind; - llvm::Optional<int64_t> Old = llvm::None; - llvm::Optional<int64_t> New = llvm::None; + std::optional<int64_t> Old = std::nullopt; + std::optional<int64_t> New = std::nullopt; }; auto HasInputFileChanged = [&]() { if (StoredSize != File->getSize()) @@ -2683,12 +2679,11 @@ ASTReader::ReadControlBlock(ModuleFile &F, // so we verify all input files. Otherwise, verify only user input // files. - unsigned N = NumUserInputs; - if (ValidateSystemInputs || - (HSOpts.ModulesValidateOncePerBuildSession && - F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp && - F.Kind == MK_ImplicitModule)) - N = NumInputs; + unsigned N = ValidateSystemInputs ? NumInputs : NumUserInputs; + if (HSOpts.ModulesValidateOncePerBuildSession && + F.InputFilesValidationTimestamp > HSOpts.BuildSessionTimestamp && + F.Kind == MK_ImplicitModule) + N = NumUserInputs; for (unsigned I = 0; I < N; ++I) { InputFile IF = getInputFile(F, I+1, Complain); @@ -2705,7 +2700,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, : NumUserInputs; for (unsigned I = 0; I < N; ++I) { bool IsSystem = I >= NumUserInputs; - InputFileInfo FI = readInputFileInfo(F, I+1); + InputFileInfo FI = getInputFileInfo(F, I + 1); Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden, F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule); @@ -2922,11 +2917,6 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.OriginalSourceFileID = FileID::get(Record[0]); break; - case ORIGINAL_PCH_DIR: - F.OriginalDir = std::string(Blob); - ResolveImportedPath(F, F.OriginalDir); - break; - case MODULE_NAME: F.ModuleName = std::string(Blob); Diag(diag::remark_module_import) @@ -2987,6 +2977,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.InputFileOffsets = (const llvm::support::unaligned_uint64_t *)Blob.data(); F.InputFilesLoaded.resize(NumInputs); + F.InputFileInfosLoaded.resize(NumInputs); F.NumUserInputFiles = NumUserInputs; break; } @@ -3002,7 +2993,7 @@ void ASTReader::readIncludedFiles(ModuleFile &F, StringRef Blob, for (unsigned I = 0; I < FileCount; ++I) { size_t ID = endian::readNext<uint32_t, little, unaligned>(D); - InputFileInfo IFI = readInputFileInfo(F, ID); + InputFileInfo IFI = getInputFileInfo(F, ID); if (llvm::ErrorOr<const FileEntry *> File = PP.getFileManager().getFile(IFI.Filename)) PP.getIncludedFiles().insert(*File); @@ -3412,7 +3403,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, if (!Record.empty()) { unsigned Idx = 0, End = Record.size() - 1; bool ReachedEOFWhileSkipping = Record[Idx++]; - llvm::Optional<Preprocessor::PreambleSkipInfo> SkipInfo; + std::optional<Preprocessor::PreambleSkipInfo> SkipInfo; if (ReachedEOFWhileSkipping) { SourceLocation HashToken = ReadSourceLocation(F, Record, Idx); SourceLocation IfTokenLoc = ReadSourceLocation(F, Record, Idx); @@ -3453,9 +3444,14 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, std::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) = SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries, SLocSpaceSize); - if (!F.SLocEntryBaseID) + if (!F.SLocEntryBaseID) { + if (!Diags.isDiagnosticInFlight()) { + Diags.Report(SourceLocation(), diag::remark_sloc_usage); + SourceMgr.noteSLocAddressSpaceUsage(Diags); + } return llvm::createStringError(std::errc::invalid_argument, "ran out of source locations"); + } // Make our entry in the range map. BaseID is negative and growing, so // we invert it. Because we invert it, though, we need the other end of // the range. @@ -3968,13 +3964,14 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName, F.ImportLoc); auto &Map = PP.getHeaderSearchInfo().getModuleMap(); - const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr; + OptionalFileEntryRef ModMap = + M ? Map.getModuleMapFileForUniquing(M) : std::nullopt; // Don't emit module relocation error if we have -fno-validate-pch if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation & DisableValidationForModuleKind::Module) && !ModMap) { if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) { - if (auto ASTFE = M ? M->getASTFile() : None) { + if (auto ASTFE = M ? M->getASTFile() : std::nullopt) { // This module was defined by an imported (explicit) module. Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName << ASTFE->getName(); @@ -4257,9 +4254,10 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, SourceLocation ImportLoc, unsigned ClientLoadCapabilities, SmallVectorImpl<ImportedSubmodule> *Imported) { - llvm::SaveAndRestore<SourceLocation> - SetCurImportLocRAII(CurrentImportLoc, ImportLoc); - llvm::SaveAndRestore<Optional<ModuleKind>> SetCurModuleKindRAII( + llvm::TimeTraceScope scope("ReadAST", FileName); + + llvm::SaveAndRestore SetCurImportLocRAII(CurrentImportLoc, ImportLoc); + llvm::SaveAndRestore<std::optional<ModuleKind>> SetCurModuleKindRAII( CurrentDeserializingModuleKind, Type); // Defer any pending actions until we get to the end of reading the AST file. @@ -4276,10 +4274,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ReadASTCore(FileName, Type, ImportLoc, /*ImportedBy=*/nullptr, Loaded, 0, 0, ASTFileSignature(), ClientLoadCapabilities)) { - ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, - PP.getLangOpts().Modules - ? &PP.getHeaderSearchInfo().getModuleMap() - : nullptr); + ModuleMgr.removeModules(ModuleMgr.begin() + NumModules); // If we find that any modules are unusable, the global index is going // to be out-of-date. Just remove it. @@ -4299,6 +4294,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, // hit errors parsing the ASTs at this point. for (ImportedModule &M : Loaded) { ModuleFile &F = *M.Mod; + llvm::TimeTraceScope Scope2("Read Loaded AST", F.ModuleName); // Read the AST block. if (llvm::Error Err = ReadASTBlock(F, ClientLoadCapabilities)) { @@ -4343,10 +4339,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, // Map the original source file ID into the ID space of the current // compilation. - if (F.OriginalSourceFileID.isValid()) { - F.OriginalSourceFileID = FileID::get( - F.SLocEntryBaseID + F.OriginalSourceFileID.getOpaqueValue() - 1); - } + if (F.OriginalSourceFileID.isValid()) + F.OriginalSourceFileID = TranslateFileID(F, F.OriginalSourceFileID); // Preload all the pending interesting identifiers by marking them out of // date. @@ -4426,6 +4420,11 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, Unresolved.Mod->Imports.insert(ResolvedMod); continue; + case UnresolvedModuleRef::Affecting: + if (ResolvedMod) + Unresolved.Mod->AffectingClangModules.insert(ResolvedMod); + continue; + case UnresolvedModuleRef::Export: if (ResolvedMod || Unresolved.IsWildcard) Unresolved.Mod->Exports.push_back( @@ -4806,6 +4805,13 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl( Result = OutOfDate; // Don't return early. Read the signature. break; } + case HEADER_SEARCH_PATHS: { + bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; + if (!AllowCompatibleConfigurationMismatch && + ParseHeaderSearchPaths(Record, Complain, *Listener)) + Result = ConfigurationMismatch; + break; + } case DIAG_PRAGMA_MAPPINGS: if (!F) break; @@ -5213,19 +5219,28 @@ namespace { bool ASTReader::readASTFileControlBlock( StringRef Filename, FileManager &FileMgr, - const PCHContainerReader &PCHContainerRdr, - bool FindModuleFileExtensions, + const InMemoryModuleCache &ModuleCache, + const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, ASTReaderListener &Listener, bool ValidateDiagnosticOptions) { // Open the AST file. - // FIXME: This allows use of the VFS; we do not allow use of the - // VFS when actually loading a module. - auto Buffer = FileMgr.getBufferForFile(Filename); + std::unique_ptr<llvm::MemoryBuffer> OwnedBuffer; + llvm::MemoryBuffer *Buffer = ModuleCache.lookupPCM(Filename); if (!Buffer) { - return true; + // FIXME: We should add the pcm to the InMemoryModuleCache if it could be + // read again later, but we do not have the context here to determine if it + // is safe to change the result of InMemoryModuleCache::getPCMState(). + + // FIXME: This allows use of the VFS; we do not allow use of the + // VFS when actually loading a module. + auto BufferOrErr = FileMgr.getBufferForFile(Filename); + if (!BufferOrErr) + return true; + OwnedBuffer = std::move(*BufferOrErr); + Buffer = OwnedBuffer.get(); } // Initialize the stream - StringRef Bytes = PCHContainerRdr.ExtractPCH(**Buffer); + StringRef Bytes = PCHContainerRdr.ExtractPCH(*Buffer); BitstreamCursor Stream(Bytes); // Sniff for the signature. @@ -5478,6 +5493,7 @@ bool ASTReader::readASTFileControlBlock( } bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, + const InMemoryModuleCache &ModuleCache, const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts, const TargetOptions &TargetOpts, @@ -5487,9 +5503,9 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, ExistingModuleCachePath, FileMgr, RequireStrictOptionMatches); - return !readASTFileControlBlock(Filename, FileMgr, PCHContainerRdr, - /*FindModuleFileExtensions=*/false, - validator, + return !readASTFileControlBlock(Filename, FileMgr, ModuleCache, + PCHContainerRdr, + /*FindModuleFileExtensions=*/false, validator, /*ValidateDiagnosticOptions=*/true); } @@ -5645,7 +5661,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, // `Headers/`, so this path will never exist. std::string Filename = std::string(Blob); ResolveImportedPath(F, Filename); - if (auto Umbrella = PP.getFileManager().getFile(Filename)) { + if (auto Umbrella = PP.getFileManager().getOptionalFileRef(Filename)) { if (!CurrentModule->getUmbrellaHeader()) { // FIXME: NameAsWritten ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob, ""); @@ -5724,6 +5740,18 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, } break; + case SUBMODULE_AFFECTING_MODULES: + for (unsigned Idx = 0; Idx != Record.size(); ++Idx) { + UnresolvedModuleRef Unresolved; + Unresolved.File = &F; + Unresolved.Mod = CurrentModule; + Unresolved.ID = Record[Idx]; + Unresolved.Kind = UnresolvedModuleRef::Affecting; + Unresolved.IsWildcard = false; + UnresolvedModuleRefs.push_back(Unresolved); + } + break; + case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -5886,6 +5914,28 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, unsigned Idx = 0; HSOpts.Sysroot = ReadString(Record, Idx); + HSOpts.ResourceDir = ReadString(Record, Idx); + HSOpts.ModuleCachePath = ReadString(Record, Idx); + HSOpts.ModuleUserBuildPath = ReadString(Record, Idx); + HSOpts.DisableModuleHash = Record[Idx++]; + HSOpts.ImplicitModuleMaps = Record[Idx++]; + HSOpts.ModuleMapFileHomeIsCwd = Record[Idx++]; + HSOpts.EnablePrebuiltImplicitModules = Record[Idx++]; + HSOpts.UseBuiltinIncludes = Record[Idx++]; + HSOpts.UseStandardSystemIncludes = Record[Idx++]; + HSOpts.UseStandardCXXIncludes = Record[Idx++]; + HSOpts.UseLibcxx = Record[Idx++]; + std::string SpecificModuleCachePath = ReadString(Record, Idx); + + return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath, + Complain); +} + +bool ASTReader::ParseHeaderSearchPaths(const RecordData &Record, bool Complain, + ASTReaderListener &Listener) { + HeaderSearchOptions HSOpts; + unsigned Idx = 0; + // Include entries. for (unsigned N = Record[Idx++]; N; --N) { std::string Path = ReadString(Record, Idx); @@ -5904,21 +5954,13 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, HSOpts.SystemHeaderPrefixes.emplace_back(std::move(Prefix), IsSystemHeader); } - HSOpts.ResourceDir = ReadString(Record, Idx); - HSOpts.ModuleCachePath = ReadString(Record, Idx); - HSOpts.ModuleUserBuildPath = ReadString(Record, Idx); - HSOpts.DisableModuleHash = Record[Idx++]; - HSOpts.ImplicitModuleMaps = Record[Idx++]; - HSOpts.ModuleMapFileHomeIsCwd = Record[Idx++]; - HSOpts.EnablePrebuiltImplicitModules = Record[Idx++]; - HSOpts.UseBuiltinIncludes = Record[Idx++]; - HSOpts.UseStandardSystemIncludes = Record[Idx++]; - HSOpts.UseStandardCXXIncludes = Record[Idx++]; - HSOpts.UseLibcxx = Record[Idx++]; - std::string SpecificModuleCachePath = ReadString(Record, Idx); + // VFS overlay files. + for (unsigned N = Record[Idx++]; N; --N) { + std::string VFSOverlayFile = ReadString(Record, Idx); + HSOpts.VFSOverlayFiles.emplace_back(std::move(VFSOverlayFile)); + } - return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath, - Complain); + return Listener.ReadHeaderSearchPaths(HSOpts, Complain); } bool ASTReader::ParsePreprocessorOptions(const RecordData &Record, @@ -6084,7 +6126,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) { case PPD_INCLUSION_DIRECTIVE: { const char *FullFileNameStart = Blob.data() + Record[0]; StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]); - Optional<FileEntryRef> File; + OptionalFileEntryRef File; if (!FullFileName.empty()) File = PP.getFileManager().getOptionalFileRef(FullFileName); @@ -6223,8 +6265,8 @@ std::pair<unsigned, unsigned> /// Optionally returns true or false if the preallocated preprocessed /// entity with index \arg Index came from file \arg FID. -Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, - FileID FID) { +std::optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index, + FileID FID) { if (FID.isInvalid()) return false; @@ -6248,7 +6290,7 @@ namespace { /// Visitor used to search for information about a header file. class HeaderFileInfoVisitor { const FileEntry *FE; - Optional<HeaderFileInfo> HFI; + std::optional<HeaderFileInfo> HFI; public: explicit HeaderFileInfoVisitor(const FileEntry *FE) : FE(FE) {} @@ -6268,7 +6310,7 @@ namespace { return true; } - Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; } + std::optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; } }; } // namespace @@ -6276,8 +6318,8 @@ namespace { HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { HeaderFileInfoVisitor Visitor(FE); ModuleMgr.visit(Visitor); - if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) - return *HFI; + if (std::optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) + return *HFI; return HeaderFileInfo(); } @@ -6294,9 +6336,8 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { DiagStates.clear(); - auto ReadDiagState = - [&](const DiagState &BasedOn, SourceLocation Loc, - bool IncludeNonPragmaStates) -> DiagnosticsEngine::DiagState * { + auto ReadDiagState = [&](const DiagState &BasedOn, + bool IncludeNonPragmaStates) { unsigned BackrefID = Record[Idx++]; if (BackrefID != 0) return DiagStates[BackrefID - 1]; @@ -6357,7 +6398,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { Initial.EnableAllWarnings = Flags & 1; Flags >>= 1; Initial.IgnoreAllWarnings = Flags & 1; Flags >>= 1; Initial.ExtBehavior = (diag::Severity)Flags; - FirstState = ReadDiagState(Initial, SourceLocation(), true); + FirstState = ReadDiagState(Initial, true); assert(F.OriginalSourceFileID.isValid()); @@ -6370,8 +6411,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { // For prefix ASTs, start with whatever the user configured on the // command line. Idx++; // Skip flags. - FirstState = ReadDiagState(*Diag.DiagStatesByLoc.CurDiagState, - SourceLocation(), false); + FirstState = ReadDiagState(*Diag.DiagStatesByLoc.CurDiagState, false); } // Read the state transitions. @@ -6393,8 +6433,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { F.StateTransitions.reserve(F.StateTransitions.size() + Transitions); for (unsigned I = 0; I != Transitions; ++I) { unsigned Offset = Record[Idx++]; - auto *State = - ReadDiagState(*FirstState, Loc.getLocWithOffset(Offset), false); + auto *State = ReadDiagState(*FirstState, false); F.StateTransitions.push_back({State, Offset}); } } @@ -6404,7 +6443,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { "Invalid data, missing final pragma diagnostic state"); SourceLocation CurStateLoc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]); - auto *CurState = ReadDiagState(*FirstState, CurStateLoc, false); + auto *CurState = ReadDiagState(*FirstState, false); if (!F.isModule()) { Diag.DiagStatesByLoc.CurDiagState = CurState; @@ -6435,12 +6474,13 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) { M->DeclsBlockStartOffset); } -static llvm::Optional<Type::TypeClass> getTypeClassForCode(TypeCode code) { +static std::optional<Type::TypeClass> getTypeClassForCode(TypeCode code) { switch (code) { #define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \ case TYPE_##CODE_ID: return Type::CLASS_ID; #include "clang/Serialization/TypeBitCodes.def" - default: return llvm::None; + default: + return std::nullopt; } } @@ -6697,7 +6737,7 @@ void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { TL.setTypeofLoc(readSourceLocation()); TL.setLParenLoc(readSourceLocation()); TL.setRParenLoc(readSourceLocation()); - TL.setUnderlyingTInfo(GetTypeSourceInfo()); + TL.setUnmodifiedTInfo(GetTypeSourceInfo()); } void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { @@ -6722,8 +6762,9 @@ void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) { TL.setLAngleLoc(readSourceLocation()); TL.setRAngleLoc(readSourceLocation()); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo(i, Reader.readTemplateArgumentLocInfo( - TL.getTypePtr()->getArg(i).getKind())); + TL.setArgLocInfo( + i, Reader.readTemplateArgumentLocInfo( + TL.getTypePtr()->getTypeConstraintArguments()[i].getKind())); } if (Reader.readBool()) TL.setRParenLoc(readSourceLocation()); @@ -6771,10 +6812,9 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc( TL.setLAngleLoc(readSourceLocation()); TL.setRAngleLoc(readSourceLocation()); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo( - i, - Reader.readTemplateArgumentLocInfo( - TL.getTypePtr()->getArg(i).getKind())); + TL.setArgLocInfo(i, + Reader.readTemplateArgumentLocInfo( + TL.getTypePtr()->template_arguments()[i].getKind())); } void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { @@ -6806,10 +6846,9 @@ void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( TL.setLAngleLoc(readSourceLocation()); TL.setRAngleLoc(readSourceLocation()); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - TL.setArgLocInfo( - I, - Reader.readTemplateArgumentLocInfo( - TL.getTypePtr()->getArg(I).getKind())); + TL.setArgLocInfo(I, + Reader.readTemplateArgumentLocInfo( + TL.getTypePtr()->template_arguments()[I].getKind())); } void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { @@ -6818,6 +6857,7 @@ void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(readSourceLocation()); + TL.setNameEndLoc(readSourceLocation()); } void TypeLocReader::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { @@ -7262,8 +7302,7 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { // // FIXME: Merging a function definition should merge // all mergeable entities within it. - if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) || - isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) { + if (isa<TranslationUnitDecl, NamespaceDecl, RecordDecl, EnumDecl>(DC)) { if (DeclarationName Name = cast<NamedDecl>(D)->getDeclName()) { if (!getContext().getLangOpts().CPlusPlus && isa<TranslationUnitDecl>(DC)) { @@ -7997,8 +8036,8 @@ void ASTReader::UpdateSema() { PragmaAlignPackStack.front().PushLocation); DropFirst = true; } - for (const auto &Entry : llvm::makeArrayRef(PragmaAlignPackStack) - .drop_front(DropFirst ? 1 : 0)) { + for (const auto &Entry : + llvm::ArrayRef(PragmaAlignPackStack).drop_front(DropFirst ? 1 : 0)) { SemaObj->AlignPackStack.Stack.emplace_back( Entry.SlotLabel, Entry.Value, Entry.Location, Entry.PushLocation); } @@ -8029,7 +8068,7 @@ void ASTReader::UpdateSema() { DropFirst = true; } for (const auto &Entry : - llvm::makeArrayRef(FpPragmaStack).drop_front(DropFirst ? 1 : 0)) + llvm::ArrayRef(FpPragmaStack).drop_front(DropFirst ? 1 : 0)) SemaObj->FpPragmaStack.Stack.emplace_back( Entry.SlotLabel, Entry.Value, Entry.Location, Entry.PushLocation); if (FpPragmaCurrentLocation.isInvalid()) { @@ -8065,7 +8104,7 @@ IdentifierInfo *ASTReader::get(StringRef Name) { // lookups). Perform the lookup in PCH files, though, since we don't build // a complete initial identifier table if we're carrying on from a PCH. if (PP.getLangOpts().CPlusPlus) { - for (auto F : ModuleMgr.pch_modules()) + for (auto *F : ModuleMgr.pch_modules()) if (Visitor(*F)) break; } else { @@ -8272,8 +8311,8 @@ namespace serialization { /// Add the given set of methods to the method list. static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods, ObjCMethodList &List) { - for (auto I = Methods.rbegin(), E = Methods.rend(); I != E; ++I) - S.addMethodToGlobalList(&List, *I); + for (ObjCMethodDecl *M : llvm::reverse(Methods)) + S.addMethodToGlobalList(&List, M); } void ASTReader::ReadMethodPool(Selector Sel) { @@ -8725,8 +8764,7 @@ unsigned ASTReader::getModuleFileID(ModuleFile *F) { return (I - PCHModules.end()) << 1; } -llvm::Optional<ASTSourceDescriptor> -ASTReader::getSourceDescriptor(unsigned ID) { +std::optional<ASTSourceDescriptor> ASTReader::getSourceDescriptor(unsigned ID) { if (Module *M = getSubmodule(ID)) return ASTSourceDescriptor(*M); @@ -8737,10 +8775,11 @@ ASTReader::getSourceDescriptor(unsigned ID) { ModuleFile &MF = ModuleMgr.getPrimaryModule(); StringRef ModuleName = llvm::sys::path::filename(MF.OriginalSourceFileName); StringRef FileName = llvm::sys::path::filename(MF.FileName); - return ASTSourceDescriptor(ModuleName, MF.OriginalDir, FileName, - MF.Signature); + return ASTSourceDescriptor(ModuleName, + llvm::sys::path::parent_path(MF.FileName), + FileName, MF.Signature); } - return None; + return std::nullopt; } ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(const Decl *FD) { @@ -9207,30 +9246,16 @@ void ASTReader::visitInputFiles(serialization::ModuleFile &MF, void ASTReader::visitTopLevelModuleMaps( serialization::ModuleFile &MF, - llvm::function_ref<void(const FileEntry *FE)> Visitor) { + llvm::function_ref<void(FileEntryRef FE)> Visitor) { unsigned NumInputs = MF.InputFilesLoaded.size(); for (unsigned I = 0; I < NumInputs; ++I) { - InputFileInfo IFI = readInputFileInfo(MF, I + 1); + InputFileInfo IFI = getInputFileInfo(MF, I + 1); if (IFI.TopLevelModuleMap) - // FIXME: This unnecessarily re-reads the InputFileInfo. if (auto FE = getInputFile(MF, I + 1).getFile()) - Visitor(FE); + Visitor(*FE); } } -std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { - // If we know the owning module, use it. - if (Module *M = D->getImportedOwningModule()) - return M->getFullModuleName(); - - // Otherwise, use the name of the top-level module the decl is within. - if (ModuleFile *M = getOwningModuleFile(D)) - return M->ModuleName; - - // Not from a module. - return {}; -} - void ASTReader::finishPendingActions() { while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() || !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || @@ -9478,35 +9503,13 @@ void ASTReader::finishPendingActions() { PendingMergedDefinitionsToDeduplicate.clear(); } -static unsigned computeODRHash(QualType Ty) { - ODRHash Hasher; - Hasher.AddQualType(Ty); - return Hasher.CalculateHash(); -} - -static unsigned computeODRHash(const Stmt *S) { - ODRHash Hasher; - Hasher.AddStmt(S); - return Hasher.CalculateHash(); -} - -static unsigned computeODRHash(const Decl *D) { - assert(D); - ODRHash Hasher; - Hasher.AddSubDecl(D); - return Hasher.CalculateHash(); -} - -static unsigned computeODRHash(const TemplateArgument &TA) { - ODRHash Hasher; - Hasher.AddTemplateArgument(TA); - return Hasher.CalculateHash(); -} - void ASTReader::diagnoseOdrViolations() { if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() && + PendingRecordOdrMergeFailures.empty() && PendingFunctionOdrMergeFailures.empty() && - PendingEnumOdrMergeFailures.empty()) + PendingEnumOdrMergeFailures.empty() && + PendingObjCInterfaceOdrMergeFailures.empty() && + PendingObjCProtocolOdrMergeFailures.empty()) return; // Trigger the import of the full definition of each class that had any @@ -9528,6 +9531,25 @@ void ASTReader::diagnoseOdrViolations() { } } + // Trigger the import of the full definition of each record in C/ObjC. + auto RecordOdrMergeFailures = std::move(PendingRecordOdrMergeFailures); + PendingRecordOdrMergeFailures.clear(); + for (auto &Merge : RecordOdrMergeFailures) { + Merge.first->decls_begin(); + for (auto &D : Merge.second) + D->decls_begin(); + } + + // Trigger the import of the full interface definition. + auto ObjCInterfaceOdrMergeFailures = + std::move(PendingObjCInterfaceOdrMergeFailures); + PendingObjCInterfaceOdrMergeFailures.clear(); + for (auto &Merge : ObjCInterfaceOdrMergeFailures) { + Merge.first->decls_begin(); + for (auto &InterfacePair : Merge.second) + InterfacePair.first->decls_begin(); + } + // Trigger the import of functions. auto FunctionOdrMergeFailures = std::move(PendingFunctionOdrMergeFailures); PendingFunctionOdrMergeFailures.clear(); @@ -9552,6 +9574,16 @@ void ASTReader::diagnoseOdrViolations() { } } + // Trigger the import of the full protocol definition. + auto ObjCProtocolOdrMergeFailures = + std::move(PendingObjCProtocolOdrMergeFailures); + PendingObjCProtocolOdrMergeFailures.clear(); + for (auto &Merge : ObjCProtocolOdrMergeFailures) { + Merge.first->decls_begin(); + for (auto &ProtocolPair : Merge.second) + ProtocolPair.first->decls_begin(); + } + // For each declaration from a merged context, check that the canonical // definition of that context also contains a declaration of the same // entity. @@ -9573,7 +9605,7 @@ void ASTReader::diagnoseOdrViolations() { bool Found = false; const Decl *DCanon = D->getCanonicalDecl(); - for (auto RI : D->redecls()) { + for (auto *RI : D->redecls()) { if (RI->getLexicalDeclContext() == CanonDef) { Found = true; break; @@ -9615,9 +9647,10 @@ void ASTReader::diagnoseOdrViolations() { Deserializing RecursionGuard(this); std::string CanonDefModule = - getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef)); + ODRDiagsEmitter::getOwningModuleNameForDiagnostic( + cast<Decl>(CanonDef)); Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl) - << D << getOwningModuleNameForDiagnostic(D) + << D << ODRDiagsEmitter::getOwningModuleNameForDiagnostic(D) << CanonDef << CanonDefModule.empty() << CanonDefModule; if (Candidates.empty()) @@ -9634,392 +9667,17 @@ void ASTReader::diagnoseOdrViolations() { } } - if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty() && - EnumOdrMergeFailures.empty()) + if (OdrMergeFailures.empty() && RecordOdrMergeFailures.empty() && + FunctionOdrMergeFailures.empty() && EnumOdrMergeFailures.empty() && + ObjCInterfaceOdrMergeFailures.empty() && + ObjCProtocolOdrMergeFailures.empty()) return; // Ensure we don't accidentally recursively enter deserialization while // we're producing our diagnostics. Deserializing RecursionGuard(this); - - // Used with err_module_odr_violation_mismatch_decl and - // note_module_odr_violation_mismatch_decl - // This list should be the same Decl's as in ODRHash::isDeclToBeProcessed - enum ODRMismatchDecl { - EndOfClass, - PublicSpecifer, - PrivateSpecifer, - ProtectedSpecifer, - StaticAssert, - Field, - CXXMethod, - TypeAlias, - TypeDef, - Var, - Friend, - FunctionTemplate, - Other - }; - - // These lambdas have the common portions of the ODR diagnostics. This - // has the same return as Diag(), so addition parameters can be passed - // in with operator<< - auto ODRDiagField = [this](NamedDecl *FirstRecord, StringRef FirstModule, - StringRef SecondModule, - const FieldDecl *FirstField, - const FieldDecl *SecondField) { - enum ODRFieldDifference { - FieldName, - FieldTypeName, - FieldSingleBitField, - FieldDifferentWidthBitField, - FieldSingleMutable, - FieldSingleInitializer, - FieldDifferentInitializers, - }; - - auto DiagError = [FirstRecord, FirstField, FirstModule, - this](ODRFieldDifference DiffType) { - return Diag(FirstField->getLocation(), - diag::err_module_odr_violation_field) - << FirstRecord << FirstModule.empty() << FirstModule - << FirstField->getSourceRange() << DiffType; - }; - auto DiagNote = [SecondField, SecondModule, - this](ODRFieldDifference DiffType) { - return Diag(SecondField->getLocation(), - diag::note_module_odr_violation_field) - << SecondModule << SecondField->getSourceRange() << DiffType; - }; - - IdentifierInfo *FirstII = FirstField->getIdentifier(); - IdentifierInfo *SecondII = SecondField->getIdentifier(); - if (FirstII->getName() != SecondII->getName()) { - DiagError(FieldName) << FirstII; - DiagNote(FieldName) << SecondII; - return true; - } - - assert(getContext().hasSameType(FirstField->getType(), - SecondField->getType())); - - QualType FirstType = FirstField->getType(); - QualType SecondType = SecondField->getType(); - if (computeODRHash(FirstType) != computeODRHash(SecondType)) { - DiagError(FieldTypeName) << FirstII << FirstType; - DiagNote(FieldTypeName) << SecondII << SecondType; - return true; - } - - const bool IsFirstBitField = FirstField->isBitField(); - const bool IsSecondBitField = SecondField->isBitField(); - if (IsFirstBitField != IsSecondBitField) { - DiagError(FieldSingleBitField) << FirstII << IsFirstBitField; - DiagNote(FieldSingleBitField) << SecondII << IsSecondBitField; - return true; - } - - if (IsFirstBitField && IsSecondBitField) { - unsigned FirstBitWidthHash = computeODRHash(FirstField->getBitWidth()); - unsigned SecondBitWidthHash = computeODRHash(SecondField->getBitWidth()); - if (FirstBitWidthHash != SecondBitWidthHash) { - DiagError(FieldDifferentWidthBitField) - << FirstII << FirstField->getBitWidth()->getSourceRange(); - DiagNote(FieldDifferentWidthBitField) - << SecondII << SecondField->getBitWidth()->getSourceRange(); - return true; - } - } - - if (!PP.getLangOpts().CPlusPlus) - return false; - - const bool IsFirstMutable = FirstField->isMutable(); - const bool IsSecondMutable = SecondField->isMutable(); - if (IsFirstMutable != IsSecondMutable) { - DiagError(FieldSingleMutable) << FirstII << IsFirstMutable; - DiagNote(FieldSingleMutable) << SecondII << IsSecondMutable; - return true; - } - - const Expr *FirstInitializer = FirstField->getInClassInitializer(); - const Expr *SecondInitializer = SecondField->getInClassInitializer(); - if ((!FirstInitializer && SecondInitializer) || - (FirstInitializer && !SecondInitializer)) { - DiagError(FieldSingleInitializer) - << FirstII << (FirstInitializer != nullptr); - DiagNote(FieldSingleInitializer) - << SecondII << (SecondInitializer != nullptr); - return true; - } - - if (FirstInitializer && SecondInitializer) { - unsigned FirstInitHash = computeODRHash(FirstInitializer); - unsigned SecondInitHash = computeODRHash(SecondInitializer); - if (FirstInitHash != SecondInitHash) { - DiagError(FieldDifferentInitializers) - << FirstII << FirstInitializer->getSourceRange(); - DiagNote(FieldDifferentInitializers) - << SecondII << SecondInitializer->getSourceRange(); - return true; - } - } - - return false; - }; - - auto ODRDiagTypeDefOrAlias = - [this](NamedDecl *FirstRecord, StringRef FirstModule, - StringRef SecondModule, const TypedefNameDecl *FirstTD, - const TypedefNameDecl *SecondTD, bool IsTypeAlias) { - enum ODRTypedefDifference { - TypedefName, - TypedefType, - }; - - auto DiagError = [FirstRecord, FirstTD, FirstModule, - this](ODRTypedefDifference DiffType) { - return Diag(FirstTD->getLocation(), - diag::err_module_odr_violation_typedef) - << FirstRecord << FirstModule.empty() << FirstModule - << FirstTD->getSourceRange() << DiffType; - }; - auto DiagNote = [SecondTD, SecondModule, - this](ODRTypedefDifference DiffType) { - return Diag(SecondTD->getLocation(), - diag::note_module_odr_violation_typedef) - << SecondModule << SecondTD->getSourceRange() << DiffType; - }; - - DeclarationName FirstName = FirstTD->getDeclName(); - DeclarationName SecondName = SecondTD->getDeclName(); - if (FirstName != SecondName) { - DiagError(TypedefName) << IsTypeAlias << FirstName; - DiagNote(TypedefName) << IsTypeAlias << SecondName; - return true; - } - - QualType FirstType = FirstTD->getUnderlyingType(); - QualType SecondType = SecondTD->getUnderlyingType(); - if (computeODRHash(FirstType) != computeODRHash(SecondType)) { - DiagError(TypedefType) << IsTypeAlias << FirstName << FirstType; - DiagNote(TypedefType) << IsTypeAlias << SecondName << SecondType; - return true; - } - - return false; - }; - - auto ODRDiagVar = [this](NamedDecl *FirstRecord, StringRef FirstModule, - StringRef SecondModule, const VarDecl *FirstVD, - const VarDecl *SecondVD) { - enum ODRVarDifference { - VarName, - VarType, - VarSingleInitializer, - VarDifferentInitializer, - VarConstexpr, - }; - - auto DiagError = [FirstRecord, FirstVD, FirstModule, - this](ODRVarDifference DiffType) { - return Diag(FirstVD->getLocation(), - diag::err_module_odr_violation_variable) - << FirstRecord << FirstModule.empty() << FirstModule - << FirstVD->getSourceRange() << DiffType; - }; - auto DiagNote = [SecondVD, SecondModule, this](ODRVarDifference DiffType) { - return Diag(SecondVD->getLocation(), - diag::note_module_odr_violation_variable) - << SecondModule << SecondVD->getSourceRange() << DiffType; - }; - - DeclarationName FirstName = FirstVD->getDeclName(); - DeclarationName SecondName = SecondVD->getDeclName(); - if (FirstName != SecondName) { - DiagError(VarName) << FirstName; - DiagNote(VarName) << SecondName; - return true; - } - - QualType FirstType = FirstVD->getType(); - QualType SecondType = SecondVD->getType(); - if (computeODRHash(FirstType) != computeODRHash(SecondType)) { - DiagError(VarType) << FirstName << FirstType; - DiagNote(VarType) << SecondName << SecondType; - return true; - } - - if (!PP.getLangOpts().CPlusPlus) - return false; - - const Expr *FirstInit = FirstVD->getInit(); - const Expr *SecondInit = SecondVD->getInit(); - if ((FirstInit == nullptr) != (SecondInit == nullptr)) { - DiagError(VarSingleInitializer) - << FirstName << (FirstInit == nullptr) - << (FirstInit ? FirstInit->getSourceRange() : SourceRange()); - DiagNote(VarSingleInitializer) - << SecondName << (SecondInit == nullptr) - << (SecondInit ? SecondInit->getSourceRange() : SourceRange()); - return true; - } - - if (FirstInit && SecondInit && - computeODRHash(FirstInit) != computeODRHash(SecondInit)) { - DiagError(VarDifferentInitializer) - << FirstName << FirstInit->getSourceRange(); - DiagNote(VarDifferentInitializer) - << SecondName << SecondInit->getSourceRange(); - return true; - } - - const bool FirstIsConstexpr = FirstVD->isConstexpr(); - const bool SecondIsConstexpr = SecondVD->isConstexpr(); - if (FirstIsConstexpr != SecondIsConstexpr) { - DiagError(VarConstexpr) << FirstName << FirstIsConstexpr; - DiagNote(VarConstexpr) << SecondName << SecondIsConstexpr; - return true; - } - return false; - }; - - using DeclHashes = llvm::SmallVector<std::pair<Decl *, unsigned>, 4>; - auto PopulateHashes = [](DeclHashes &Hashes, RecordDecl *Record, - const DeclContext *DC) { - for (auto *D : Record->decls()) { - if (!ODRHash::isDeclToBeProcessed(D, DC)) - continue; - Hashes.emplace_back(D, computeODRHash(D)); - } - }; - - struct DiffResult { - Decl *FirstDecl = nullptr, *SecondDecl = nullptr; - ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other; - }; - - // If there is a diagnoseable difference, FirstDiffType and - // SecondDiffType will not be Other and FirstDecl and SecondDecl will be - // filled in if not EndOfClass. - auto FindTypeDiffs = [](DeclHashes &FirstHashes, DeclHashes &SecondHashes) { - auto DifferenceSelector = [](Decl *D) { - assert(D && "valid Decl required"); - switch (D->getKind()) { - default: - return Other; - case Decl::AccessSpec: - switch (D->getAccess()) { - case AS_public: - return PublicSpecifer; - case AS_private: - return PrivateSpecifer; - case AS_protected: - return ProtectedSpecifer; - case AS_none: - break; - } - llvm_unreachable("Invalid access specifier"); - case Decl::StaticAssert: - return StaticAssert; - case Decl::Field: - return Field; - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - return CXXMethod; - case Decl::TypeAlias: - return TypeAlias; - case Decl::Typedef: - return TypeDef; - case Decl::Var: - return Var; - case Decl::Friend: - return Friend; - case Decl::FunctionTemplate: - return FunctionTemplate; - } - }; - - DiffResult DR; - auto FirstIt = FirstHashes.begin(); - auto SecondIt = SecondHashes.begin(); - while (FirstIt != FirstHashes.end() || SecondIt != SecondHashes.end()) { - if (FirstIt != FirstHashes.end() && SecondIt != SecondHashes.end() && - FirstIt->second == SecondIt->second) { - ++FirstIt; - ++SecondIt; - continue; - } - - DR.FirstDecl = FirstIt == FirstHashes.end() ? nullptr : FirstIt->first; - DR.SecondDecl = - SecondIt == SecondHashes.end() ? nullptr : SecondIt->first; - - DR.FirstDiffType = - DR.FirstDecl ? DifferenceSelector(DR.FirstDecl) : EndOfClass; - DR.SecondDiffType = - DR.SecondDecl ? DifferenceSelector(DR.SecondDecl) : EndOfClass; - return DR; - } - return DR; - }; - - // Use this to diagnose that an unexpected Decl was encountered - // or no difference was detected. This causes a generic error - // message to be emitted. - auto DiagnoseODRUnexpected = [this](DiffResult &DR, NamedDecl *FirstRecord, - StringRef FirstModule, - NamedDecl *SecondRecord, - StringRef SecondModule) { - Diag(FirstRecord->getLocation(), - diag::err_module_odr_violation_different_definitions) - << FirstRecord << FirstModule.empty() << FirstModule; - - if (DR.FirstDecl) { - Diag(DR.FirstDecl->getLocation(), diag::note_first_module_difference) - << FirstRecord << DR.FirstDecl->getSourceRange(); - } - - Diag(SecondRecord->getLocation(), - diag::note_module_odr_violation_different_definitions) - << SecondModule; - - if (DR.SecondDecl) { - Diag(DR.SecondDecl->getLocation(), diag::note_second_module_difference) - << DR.SecondDecl->getSourceRange(); - } - }; - - auto DiagnoseODRMismatch = [this](DiffResult &DR, NamedDecl *FirstRecord, - StringRef FirstModule, - NamedDecl *SecondRecord, - StringRef SecondModule) { - auto GetMismatchedDeclLoc = [](const NamedDecl *Container, - ODRMismatchDecl DiffType, const Decl *D) { - SourceLocation Loc; - SourceRange Range; - auto *Tag = dyn_cast<TagDecl>(Container); - if (DiffType == EndOfClass && Tag) { - Loc = Tag->getBraceRange().getEnd(); - } else { - Loc = D->getLocation(); - Range = D->getSourceRange(); - } - return std::make_pair(Loc, Range); - }; - - auto FirstDiagInfo = - GetMismatchedDeclLoc(FirstRecord, DR.FirstDiffType, DR.FirstDecl); - Diag(FirstDiagInfo.first, diag::err_module_odr_violation_mismatch_decl) - << FirstRecord << FirstModule.empty() << FirstModule - << FirstDiagInfo.second << DR.FirstDiffType; - - auto SecondDiagInfo = - GetMismatchedDeclLoc(SecondRecord, DR.SecondDiffType, DR.SecondDecl); - Diag(SecondDiagInfo.first, diag::note_module_odr_violation_mismatch_decl) - << SecondModule << SecondDiagInfo.second << DR.SecondDiffType; - }; + ODRDiagsEmitter DiagsEmitter(Diags, getContext(), + getPreprocessor().getLangOpts()); // Issue any pending ODR-failure diagnostics. for (auto &Merge : OdrMergeFailures) { @@ -10030,986 +9688,12 @@ void ASTReader::diagnoseOdrViolations() { bool Diagnosed = false; CXXRecordDecl *FirstRecord = Merge.first; - std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord); for (auto &RecordPair : Merge.second) { - CXXRecordDecl *SecondRecord = RecordPair.first; - // Multiple different declarations got merged together; tell the user - // where they came from. - if (FirstRecord == SecondRecord) - continue; - - std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord); - - auto *FirstDD = FirstRecord->DefinitionData; - auto *SecondDD = RecordPair.second; - - assert(FirstDD && SecondDD && "Definitions without DefinitionData"); - - // Diagnostics from DefinitionData are emitted here. - if (FirstDD != SecondDD) { - enum ODRDefinitionDataDifference { - NumBases, - NumVBases, - BaseType, - BaseVirtual, - BaseAccess, - }; - auto ODRDiagBaseError = [FirstRecord, &FirstModule, - this](SourceLocation Loc, SourceRange Range, - ODRDefinitionDataDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_definition_data) - << FirstRecord << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagBaseNote = [&SecondModule, - this](SourceLocation Loc, SourceRange Range, - ODRDefinitionDataDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_definition_data) - << SecondModule << Range << DiffType; - }; - auto GetSourceRange = [](struct CXXRecordDecl::DefinitionData *DD) { - unsigned NumBases = DD->NumBases; - if (NumBases == 0) return SourceRange(); - ArrayRef<CXXBaseSpecifier> bases = DD->bases(); - return SourceRange(bases[0].getBeginLoc(), - bases[NumBases - 1].getEndLoc()); - }; - - unsigned FirstNumBases = FirstDD->NumBases; - unsigned FirstNumVBases = FirstDD->NumVBases; - unsigned SecondNumBases = SecondDD->NumBases; - unsigned SecondNumVBases = SecondDD->NumVBases; - if (FirstNumBases != SecondNumBases) { - ODRDiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD), - NumBases) - << FirstNumBases; - ODRDiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD), - NumBases) - << SecondNumBases; - Diagnosed = true; - break; - } - - if (FirstNumVBases != SecondNumVBases) { - ODRDiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD), - NumVBases) - << FirstNumVBases; - ODRDiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD), - NumVBases) - << SecondNumVBases; - Diagnosed = true; - break; - } - - ArrayRef<CXXBaseSpecifier> FirstBases = FirstDD->bases(); - ArrayRef<CXXBaseSpecifier> SecondBases = SecondDD->bases(); - unsigned I = 0; - for (I = 0; I < FirstNumBases; ++I) { - const CXXBaseSpecifier FirstBase = FirstBases[I]; - const CXXBaseSpecifier SecondBase = SecondBases[I]; - if (computeODRHash(FirstBase.getType()) != - computeODRHash(SecondBase.getType())) { - ODRDiagBaseError(FirstRecord->getLocation(), - FirstBase.getSourceRange(), BaseType) - << (I + 1) << FirstBase.getType(); - ODRDiagBaseNote(SecondRecord->getLocation(), - SecondBase.getSourceRange(), BaseType) - << (I + 1) << SecondBase.getType(); - break; - } - - if (FirstBase.isVirtual() != SecondBase.isVirtual()) { - ODRDiagBaseError(FirstRecord->getLocation(), - FirstBase.getSourceRange(), BaseVirtual) - << (I + 1) << FirstBase.isVirtual() << FirstBase.getType(); - ODRDiagBaseNote(SecondRecord->getLocation(), - SecondBase.getSourceRange(), BaseVirtual) - << (I + 1) << SecondBase.isVirtual() << SecondBase.getType(); - break; - } - - if (FirstBase.getAccessSpecifierAsWritten() != - SecondBase.getAccessSpecifierAsWritten()) { - ODRDiagBaseError(FirstRecord->getLocation(), - FirstBase.getSourceRange(), BaseAccess) - << (I + 1) << FirstBase.getType() - << (int)FirstBase.getAccessSpecifierAsWritten(); - ODRDiagBaseNote(SecondRecord->getLocation(), - SecondBase.getSourceRange(), BaseAccess) - << (I + 1) << SecondBase.getType() - << (int)SecondBase.getAccessSpecifierAsWritten(); - break; - } - } - - if (I != FirstNumBases) { - Diagnosed = true; - break; - } - } - - const ClassTemplateDecl *FirstTemplate = - FirstRecord->getDescribedClassTemplate(); - const ClassTemplateDecl *SecondTemplate = - SecondRecord->getDescribedClassTemplate(); - - assert(!FirstTemplate == !SecondTemplate && - "Both pointers should be null or non-null"); - - if (FirstTemplate && SecondTemplate) { - DeclHashes FirstTemplateHashes; - DeclHashes SecondTemplateHashes; - - auto PopulateTemplateParameterHashs = [](DeclHashes &Hashes, - const ClassTemplateDecl *TD) { - for (auto *D : TD->getTemplateParameters()->asArray()) { - Hashes.emplace_back(D, computeODRHash(D)); - } - }; - - PopulateTemplateParameterHashs(FirstTemplateHashes, FirstTemplate); - PopulateTemplateParameterHashs(SecondTemplateHashes, SecondTemplate); - - assert(FirstTemplateHashes.size() == SecondTemplateHashes.size() && - "Number of template parameters should be equal."); - - auto FirstIt = FirstTemplateHashes.begin(); - auto FirstEnd = FirstTemplateHashes.end(); - auto SecondIt = SecondTemplateHashes.begin(); - for (; FirstIt != FirstEnd; ++FirstIt, ++SecondIt) { - if (FirstIt->second == SecondIt->second) - continue; - - const NamedDecl* FirstDecl = cast<NamedDecl>(FirstIt->first); - const NamedDecl* SecondDecl = cast<NamedDecl>(SecondIt->first); - - assert(FirstDecl->getKind() == SecondDecl->getKind() && - "Parameter Decl's should be the same kind."); - - enum ODRTemplateDifference { - ParamEmptyName, - ParamName, - ParamSingleDefaultArgument, - ParamDifferentDefaultArgument, - }; - - auto hasDefaultArg = [](const NamedDecl *D) { - if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(D)) - return TTP->hasDefaultArgument() && - !TTP->defaultArgumentWasInherited(); - if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) - return NTTP->hasDefaultArgument() && - !NTTP->defaultArgumentWasInherited(); - auto *TTP = cast<TemplateTemplateParmDecl>(D); - return TTP->hasDefaultArgument() && - !TTP->defaultArgumentWasInherited(); - }; - bool hasFirstArg = hasDefaultArg(FirstDecl); - bool hasSecondArg = hasDefaultArg(SecondDecl); - - ODRTemplateDifference ErrDiffType; - ODRTemplateDifference NoteDiffType; - - DeclarationName FirstName = FirstDecl->getDeclName(); - DeclarationName SecondName = SecondDecl->getDeclName(); - - if (FirstName != SecondName) { - bool FirstNameEmpty = - FirstName.isIdentifier() && !FirstName.getAsIdentifierInfo(); - bool SecondNameEmpty = SecondName.isIdentifier() && - !SecondName.getAsIdentifierInfo(); - ErrDiffType = FirstNameEmpty ? ParamEmptyName : ParamName; - NoteDiffType = SecondNameEmpty ? ParamEmptyName : ParamName; - } else if (hasFirstArg == hasSecondArg) - ErrDiffType = NoteDiffType = ParamDifferentDefaultArgument; - else - ErrDiffType = NoteDiffType = ParamSingleDefaultArgument; - - Diag(FirstDecl->getLocation(), - diag::err_module_odr_violation_template_parameter) - << FirstRecord << FirstModule.empty() << FirstModule - << FirstDecl->getSourceRange() << ErrDiffType << hasFirstArg - << FirstName; - Diag(SecondDecl->getLocation(), - diag::note_module_odr_violation_template_parameter) - << SecondModule << SecondDecl->getSourceRange() << NoteDiffType - << hasSecondArg << SecondName; - break; - } - - if (FirstIt != FirstEnd) { - Diagnosed = true; - break; - } - } - - DeclHashes FirstHashes; - DeclHashes SecondHashes; - const DeclContext *DC = FirstRecord; - PopulateHashes(FirstHashes, FirstRecord, DC); - PopulateHashes(SecondHashes, SecondRecord, DC); - - DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes); - ODRMismatchDecl FirstDiffType = DR.FirstDiffType; - ODRMismatchDecl SecondDiffType = DR.SecondDiffType; - const Decl *FirstDecl = DR.FirstDecl; - const Decl *SecondDecl = DR.SecondDecl; - - if (FirstDiffType == Other || SecondDiffType == Other) { - DiagnoseODRUnexpected(DR, FirstRecord, FirstModule, SecondRecord, - SecondModule); + if (DiagsEmitter.diagnoseMismatch(FirstRecord, RecordPair.first, + RecordPair.second)) { Diagnosed = true; break; } - - if (FirstDiffType != SecondDiffType) { - DiagnoseODRMismatch(DR, FirstRecord, FirstModule, SecondRecord, - SecondModule); - Diagnosed = true; - break; - } - - // Used with err_module_odr_violation_record and - // note_module_odr_violation_record - enum ODRCXXRecordDifference { - StaticAssertCondition, - StaticAssertMessage, - StaticAssertOnlyMessage, - MethodName, - MethodDeleted, - MethodDefaulted, - MethodVirtual, - MethodStatic, - MethodVolatile, - MethodConst, - MethodInline, - MethodNumberParameters, - MethodParameterType, - MethodParameterName, - MethodParameterSingleDefaultArgument, - MethodParameterDifferentDefaultArgument, - MethodNoTemplateArguments, - MethodDifferentNumberTemplateArguments, - MethodDifferentTemplateArgument, - MethodSingleBody, - MethodDifferentBody, - FriendTypeFunction, - FriendType, - FriendFunction, - FunctionTemplateDifferentNumberParameters, - FunctionTemplateParameterDifferentKind, - FunctionTemplateParameterName, - FunctionTemplateParameterSingleDefaultArgument, - FunctionTemplateParameterDifferentDefaultArgument, - FunctionTemplateParameterDifferentType, - FunctionTemplatePackParameter, - }; - auto ODRDiagDeclError = [FirstRecord, &FirstModule, - this](SourceLocation Loc, SourceRange Range, - ODRCXXRecordDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_record) - << FirstRecord << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagDeclNote = [&SecondModule, - this](SourceLocation Loc, SourceRange Range, - ODRCXXRecordDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_record) - << SecondModule << Range << DiffType; - }; - - assert(FirstDiffType == SecondDiffType); - switch (FirstDiffType) { - case Other: - case EndOfClass: - case PublicSpecifer: - case PrivateSpecifer: - case ProtectedSpecifer: - llvm_unreachable("Invalid diff type"); - - case StaticAssert: { - const StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl); - const StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl); - - const Expr *FirstExpr = FirstSA->getAssertExpr(); - const Expr *SecondExpr = SecondSA->getAssertExpr(); - unsigned FirstODRHash = computeODRHash(FirstExpr); - unsigned SecondODRHash = computeODRHash(SecondExpr); - if (FirstODRHash != SecondODRHash) { - ODRDiagDeclError(FirstExpr->getBeginLoc(), - FirstExpr->getSourceRange(), StaticAssertCondition); - ODRDiagDeclNote(SecondExpr->getBeginLoc(), - SecondExpr->getSourceRange(), StaticAssertCondition); - Diagnosed = true; - break; - } - - const StringLiteral *FirstStr = FirstSA->getMessage(); - const StringLiteral *SecondStr = SecondSA->getMessage(); - assert((FirstStr || SecondStr) && "Both messages cannot be empty"); - if ((FirstStr && !SecondStr) || (!FirstStr && SecondStr)) { - SourceLocation FirstLoc, SecondLoc; - SourceRange FirstRange, SecondRange; - if (FirstStr) { - FirstLoc = FirstStr->getBeginLoc(); - FirstRange = FirstStr->getSourceRange(); - } else { - FirstLoc = FirstSA->getBeginLoc(); - FirstRange = FirstSA->getSourceRange(); - } - if (SecondStr) { - SecondLoc = SecondStr->getBeginLoc(); - SecondRange = SecondStr->getSourceRange(); - } else { - SecondLoc = SecondSA->getBeginLoc(); - SecondRange = SecondSA->getSourceRange(); - } - ODRDiagDeclError(FirstLoc, FirstRange, StaticAssertOnlyMessage) - << (FirstStr == nullptr); - ODRDiagDeclNote(SecondLoc, SecondRange, StaticAssertOnlyMessage) - << (SecondStr == nullptr); - Diagnosed = true; - break; - } - - if (FirstStr && SecondStr && - FirstStr->getString() != SecondStr->getString()) { - ODRDiagDeclError(FirstStr->getBeginLoc(), FirstStr->getSourceRange(), - StaticAssertMessage); - ODRDiagDeclNote(SecondStr->getBeginLoc(), SecondStr->getSourceRange(), - StaticAssertMessage); - Diagnosed = true; - break; - } - break; - } - case Field: { - Diagnosed = ODRDiagField(FirstRecord, FirstModule, SecondModule, - cast<FieldDecl>(FirstDecl), - cast<FieldDecl>(SecondDecl)); - break; - } - case CXXMethod: { - enum { - DiagMethod, - DiagConstructor, - DiagDestructor, - } FirstMethodType, - SecondMethodType; - auto GetMethodTypeForDiagnostics = [](const CXXMethodDecl* D) { - if (isa<CXXConstructorDecl>(D)) return DiagConstructor; - if (isa<CXXDestructorDecl>(D)) return DiagDestructor; - return DiagMethod; - }; - const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(FirstDecl); - const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(SecondDecl); - FirstMethodType = GetMethodTypeForDiagnostics(FirstMethod); - SecondMethodType = GetMethodTypeForDiagnostics(SecondMethod); - DeclarationName FirstName = FirstMethod->getDeclName(); - DeclarationName SecondName = SecondMethod->getDeclName(); - auto DiagMethodError = [&ODRDiagDeclError, FirstMethod, FirstMethodType, - FirstName](ODRCXXRecordDifference DiffType) { - return ODRDiagDeclError(FirstMethod->getLocation(), - FirstMethod->getSourceRange(), DiffType) - << FirstMethodType << FirstName; - }; - auto DiagMethodNote = [&ODRDiagDeclNote, SecondMethod, SecondMethodType, - SecondName](ODRCXXRecordDifference DiffType) { - return ODRDiagDeclNote(SecondMethod->getLocation(), - SecondMethod->getSourceRange(), DiffType) - << SecondMethodType << SecondName; - }; - - if (FirstMethodType != SecondMethodType || FirstName != SecondName) { - DiagMethodError(MethodName); - DiagMethodNote(MethodName); - Diagnosed = true; - break; - } - - const bool FirstDeleted = FirstMethod->isDeletedAsWritten(); - const bool SecondDeleted = SecondMethod->isDeletedAsWritten(); - if (FirstDeleted != SecondDeleted) { - DiagMethodError(MethodDeleted) << FirstDeleted; - DiagMethodNote(MethodDeleted) << SecondDeleted; - Diagnosed = true; - break; - } - - const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted(); - const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted(); - if (FirstDefaulted != SecondDefaulted) { - DiagMethodError(MethodDefaulted) << FirstDefaulted; - DiagMethodNote(MethodDefaulted) << SecondDefaulted; - Diagnosed = true; - break; - } - - const bool FirstVirtual = FirstMethod->isVirtualAsWritten(); - const bool SecondVirtual = SecondMethod->isVirtualAsWritten(); - const bool FirstPure = FirstMethod->isPure(); - const bool SecondPure = SecondMethod->isPure(); - if ((FirstVirtual || SecondVirtual) && - (FirstVirtual != SecondVirtual || FirstPure != SecondPure)) { - DiagMethodError(MethodVirtual) << FirstPure << FirstVirtual; - DiagMethodNote(MethodVirtual) << SecondPure << SecondVirtual; - Diagnosed = true; - break; - } - - // CXXMethodDecl::isStatic uses the canonical Decl. With Decl merging, - // FirstDecl is the canonical Decl of SecondDecl, so the storage - // class needs to be checked instead. - StorageClass FirstStorage = FirstMethod->getStorageClass(); - StorageClass SecondStorage = SecondMethod->getStorageClass(); - const bool FirstStatic = FirstStorage == SC_Static; - const bool SecondStatic = SecondStorage == SC_Static; - if (FirstStatic != SecondStatic) { - DiagMethodError(MethodStatic) << FirstStatic; - DiagMethodNote(MethodStatic) << SecondStatic; - Diagnosed = true; - break; - } - - const bool FirstVolatile = FirstMethod->isVolatile(); - const bool SecondVolatile = SecondMethod->isVolatile(); - if (FirstVolatile != SecondVolatile) { - DiagMethodError(MethodVolatile) << FirstVolatile; - DiagMethodNote(MethodVolatile) << SecondVolatile; - Diagnosed = true; - break; - } - - const bool FirstConst = FirstMethod->isConst(); - const bool SecondConst = SecondMethod->isConst(); - if (FirstConst != SecondConst) { - DiagMethodError(MethodConst) << FirstConst; - DiagMethodNote(MethodConst) << SecondConst; - Diagnosed = true; - break; - } - - const bool FirstInline = FirstMethod->isInlineSpecified(); - const bool SecondInline = SecondMethod->isInlineSpecified(); - if (FirstInline != SecondInline) { - DiagMethodError(MethodInline) << FirstInline; - DiagMethodNote(MethodInline) << SecondInline; - Diagnosed = true; - break; - } - - const unsigned FirstNumParameters = FirstMethod->param_size(); - const unsigned SecondNumParameters = SecondMethod->param_size(); - if (FirstNumParameters != SecondNumParameters) { - DiagMethodError(MethodNumberParameters) << FirstNumParameters; - DiagMethodNote(MethodNumberParameters) << SecondNumParameters; - Diagnosed = true; - break; - } - - // Need this status boolean to know when break out of the switch. - bool ParameterMismatch = false; - for (unsigned I = 0; I < FirstNumParameters; ++I) { - const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I); - const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I); - - QualType FirstParamType = FirstParam->getType(); - QualType SecondParamType = SecondParam->getType(); - if (FirstParamType != SecondParamType && - computeODRHash(FirstParamType) != - computeODRHash(SecondParamType)) { - if (const DecayedType *ParamDecayedType = - FirstParamType->getAs<DecayedType>()) { - DiagMethodError(MethodParameterType) - << (I + 1) << FirstParamType << true - << ParamDecayedType->getOriginalType(); - } else { - DiagMethodError(MethodParameterType) - << (I + 1) << FirstParamType << false; - } - - if (const DecayedType *ParamDecayedType = - SecondParamType->getAs<DecayedType>()) { - DiagMethodNote(MethodParameterType) - << (I + 1) << SecondParamType << true - << ParamDecayedType->getOriginalType(); - } else { - DiagMethodNote(MethodParameterType) - << (I + 1) << SecondParamType << false; - } - ParameterMismatch = true; - break; - } - - DeclarationName FirstParamName = FirstParam->getDeclName(); - DeclarationName SecondParamName = SecondParam->getDeclName(); - if (FirstParamName != SecondParamName) { - DiagMethodError(MethodParameterName) << (I + 1) << FirstParamName; - DiagMethodNote(MethodParameterName) << (I + 1) << SecondParamName; - ParameterMismatch = true; - break; - } - - const Expr *FirstInit = FirstParam->getInit(); - const Expr *SecondInit = SecondParam->getInit(); - if ((FirstInit == nullptr) != (SecondInit == nullptr)) { - DiagMethodError(MethodParameterSingleDefaultArgument) - << (I + 1) << (FirstInit == nullptr) - << (FirstInit ? FirstInit->getSourceRange() : SourceRange()); - DiagMethodNote(MethodParameterSingleDefaultArgument) - << (I + 1) << (SecondInit == nullptr) - << (SecondInit ? SecondInit->getSourceRange() : SourceRange()); - ParameterMismatch = true; - break; - } - - if (FirstInit && SecondInit && - computeODRHash(FirstInit) != computeODRHash(SecondInit)) { - DiagMethodError(MethodParameterDifferentDefaultArgument) - << (I + 1) << FirstInit->getSourceRange(); - DiagMethodNote(MethodParameterDifferentDefaultArgument) - << (I + 1) << SecondInit->getSourceRange(); - ParameterMismatch = true; - break; - } - } - - if (ParameterMismatch) { - Diagnosed = true; - break; - } - - const TemplateArgumentList *FirstTemplateArgs = - FirstMethod->getTemplateSpecializationArgs(); - const TemplateArgumentList *SecondTemplateArgs = - SecondMethod->getTemplateSpecializationArgs(); - - if ((FirstTemplateArgs && !SecondTemplateArgs) || - (!FirstTemplateArgs && SecondTemplateArgs)) { - DiagMethodError(MethodNoTemplateArguments) - << (FirstTemplateArgs != nullptr); - DiagMethodNote(MethodNoTemplateArguments) - << (SecondTemplateArgs != nullptr); - Diagnosed = true; - break; - } - - if (FirstTemplateArgs && SecondTemplateArgs) { - // Remove pack expansions from argument list. - auto ExpandTemplateArgumentList = - [](const TemplateArgumentList *TAL) { - llvm::SmallVector<const TemplateArgument *, 8> ExpandedList; - for (const TemplateArgument &TA : TAL->asArray()) { - if (TA.getKind() != TemplateArgument::Pack) { - ExpandedList.push_back(&TA); - continue; - } - llvm::append_range(ExpandedList, llvm::make_pointer_range( - TA.getPackAsArray())); - } - return ExpandedList; - }; - llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList = - ExpandTemplateArgumentList(FirstTemplateArgs); - llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList = - ExpandTemplateArgumentList(SecondTemplateArgs); - - if (FirstExpandedList.size() != SecondExpandedList.size()) { - DiagMethodError(MethodDifferentNumberTemplateArguments) - << (unsigned)FirstExpandedList.size(); - DiagMethodNote(MethodDifferentNumberTemplateArguments) - << (unsigned)SecondExpandedList.size(); - Diagnosed = true; - break; - } - - bool TemplateArgumentMismatch = false; - for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) { - const TemplateArgument &FirstTA = *FirstExpandedList[i], - &SecondTA = *SecondExpandedList[i]; - if (computeODRHash(FirstTA) == computeODRHash(SecondTA)) { - continue; - } - - DiagMethodError(MethodDifferentTemplateArgument) - << FirstTA << i + 1; - DiagMethodNote(MethodDifferentTemplateArgument) - << SecondTA << i + 1; - TemplateArgumentMismatch = true; - break; - } - - if (TemplateArgumentMismatch) { - Diagnosed = true; - break; - } - } - - // Compute the hash of the method as if it has no body. - auto ComputeCXXMethodODRHash = [](const CXXMethodDecl *D) { - ODRHash Hasher; - Hasher.AddFunctionDecl(D, true /*SkipBody*/); - return Hasher.CalculateHash(); - }; - - // Compare the hash generated to the hash stored. A difference means - // that a body was present in the original source. Due to merging, - // the standard way of detecting a body will not work. - const bool HasFirstBody = - ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash(); - const bool HasSecondBody = - ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash(); - - if (HasFirstBody != HasSecondBody) { - DiagMethodError(MethodSingleBody) << HasFirstBody; - DiagMethodNote(MethodSingleBody) << HasSecondBody; - Diagnosed = true; - break; - } - - if (HasFirstBody && HasSecondBody) { - DiagMethodError(MethodDifferentBody); - DiagMethodNote(MethodDifferentBody); - Diagnosed = true; - break; - } - - break; - } - case TypeAlias: - case TypeDef: { - Diagnosed = ODRDiagTypeDefOrAlias( - FirstRecord, FirstModule, SecondModule, - cast<TypedefNameDecl>(FirstDecl), cast<TypedefNameDecl>(SecondDecl), - FirstDiffType == TypeAlias); - break; - } - case Var: { - Diagnosed = - ODRDiagVar(FirstRecord, FirstModule, SecondModule, - cast<VarDecl>(FirstDecl), cast<VarDecl>(SecondDecl)); - break; - } - case Friend: { - const FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl); - const FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl); - - const NamedDecl *FirstND = FirstFriend->getFriendDecl(); - const NamedDecl *SecondND = SecondFriend->getFriendDecl(); - - TypeSourceInfo *FirstTSI = FirstFriend->getFriendType(); - TypeSourceInfo *SecondTSI = SecondFriend->getFriendType(); - - if (FirstND && SecondND) { - ODRDiagDeclError(FirstFriend->getFriendLoc(), - FirstFriend->getSourceRange(), FriendFunction) - << FirstND; - ODRDiagDeclNote(SecondFriend->getFriendLoc(), - SecondFriend->getSourceRange(), FriendFunction) - << SecondND; - Diagnosed = true; - break; - } - - if (FirstTSI && SecondTSI) { - QualType FirstFriendType = FirstTSI->getType(); - QualType SecondFriendType = SecondTSI->getType(); - assert(computeODRHash(FirstFriendType) != - computeODRHash(SecondFriendType)); - ODRDiagDeclError(FirstFriend->getFriendLoc(), - FirstFriend->getSourceRange(), FriendType) - << FirstFriendType; - ODRDiagDeclNote(SecondFriend->getFriendLoc(), - SecondFriend->getSourceRange(), FriendType) - << SecondFriendType; - Diagnosed = true; - break; - } - - ODRDiagDeclError(FirstFriend->getFriendLoc(), - FirstFriend->getSourceRange(), FriendTypeFunction) - << (FirstTSI == nullptr); - ODRDiagDeclNote(SecondFriend->getFriendLoc(), - SecondFriend->getSourceRange(), FriendTypeFunction) - << (SecondTSI == nullptr); - Diagnosed = true; - break; - } - case FunctionTemplate: { - const FunctionTemplateDecl *FirstTemplate = - cast<FunctionTemplateDecl>(FirstDecl); - const FunctionTemplateDecl *SecondTemplate = - cast<FunctionTemplateDecl>(SecondDecl); - - TemplateParameterList *FirstTPL = - FirstTemplate->getTemplateParameters(); - TemplateParameterList *SecondTPL = - SecondTemplate->getTemplateParameters(); - - auto DiagTemplateError = [&ODRDiagDeclError, FirstTemplate]( - ODRCXXRecordDifference DiffType) { - return ODRDiagDeclError(FirstTemplate->getLocation(), - FirstTemplate->getSourceRange(), DiffType) - << FirstTemplate; - }; - auto DiagTemplateNote = [&ODRDiagDeclNote, SecondTemplate]( - ODRCXXRecordDifference DiffType) { - return ODRDiagDeclNote(SecondTemplate->getLocation(), - SecondTemplate->getSourceRange(), DiffType) - << SecondTemplate; - }; - - if (FirstTPL->size() != SecondTPL->size()) { - DiagTemplateError(FunctionTemplateDifferentNumberParameters) - << FirstTPL->size(); - DiagTemplateNote(FunctionTemplateDifferentNumberParameters) - << SecondTPL->size(); - Diagnosed = true; - break; - } - - bool ParameterMismatch = false; - for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) { - NamedDecl *FirstParam = FirstTPL->getParam(i); - NamedDecl *SecondParam = SecondTPL->getParam(i); - - if (FirstParam->getKind() != SecondParam->getKind()) { - enum { - TemplateTypeParameter, - NonTypeTemplateParameter, - TemplateTemplateParameter, - }; - auto GetParamType = [](NamedDecl *D) { - switch (D->getKind()) { - default: - llvm_unreachable("Unexpected template parameter type"); - case Decl::TemplateTypeParm: - return TemplateTypeParameter; - case Decl::NonTypeTemplateParm: - return NonTypeTemplateParameter; - case Decl::TemplateTemplateParm: - return TemplateTemplateParameter; - } - }; - - DiagTemplateError(FunctionTemplateParameterDifferentKind) - << (i + 1) << GetParamType(FirstParam); - DiagTemplateNote(FunctionTemplateParameterDifferentKind) - << (i + 1) << GetParamType(SecondParam); - ParameterMismatch = true; - break; - } - - if (FirstParam->getName() != SecondParam->getName()) { - DiagTemplateError(FunctionTemplateParameterName) - << (i + 1) << (bool)FirstParam->getIdentifier() << FirstParam; - DiagTemplateNote(FunctionTemplateParameterName) - << (i + 1) << (bool)SecondParam->getIdentifier() << SecondParam; - ParameterMismatch = true; - break; - } - - if (isa<TemplateTypeParmDecl>(FirstParam) && - isa<TemplateTypeParmDecl>(SecondParam)) { - TemplateTypeParmDecl *FirstTTPD = - cast<TemplateTypeParmDecl>(FirstParam); - TemplateTypeParmDecl *SecondTTPD = - cast<TemplateTypeParmDecl>(SecondParam); - bool HasFirstDefaultArgument = - FirstTTPD->hasDefaultArgument() && - !FirstTTPD->defaultArgumentWasInherited(); - bool HasSecondDefaultArgument = - SecondTTPD->hasDefaultArgument() && - !SecondTTPD->defaultArgumentWasInherited(); - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument) - << (i + 1) << HasFirstDefaultArgument; - DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument) - << (i + 1) << HasSecondDefaultArgument; - ParameterMismatch = true; - break; - } - - if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - QualType FirstType = FirstTTPD->getDefaultArgument(); - QualType SecondType = SecondTTPD->getDefaultArgument(); - if (computeODRHash(FirstType) != computeODRHash(SecondType)) { - DiagTemplateError( - FunctionTemplateParameterDifferentDefaultArgument) - << (i + 1) << FirstType; - DiagTemplateNote( - FunctionTemplateParameterDifferentDefaultArgument) - << (i + 1) << SecondType; - ParameterMismatch = true; - break; - } - } - - if (FirstTTPD->isParameterPack() != - SecondTTPD->isParameterPack()) { - DiagTemplateError(FunctionTemplatePackParameter) - << (i + 1) << FirstTTPD->isParameterPack(); - DiagTemplateNote(FunctionTemplatePackParameter) - << (i + 1) << SecondTTPD->isParameterPack(); - ParameterMismatch = true; - break; - } - } - - if (isa<TemplateTemplateParmDecl>(FirstParam) && - isa<TemplateTemplateParmDecl>(SecondParam)) { - TemplateTemplateParmDecl *FirstTTPD = - cast<TemplateTemplateParmDecl>(FirstParam); - TemplateTemplateParmDecl *SecondTTPD = - cast<TemplateTemplateParmDecl>(SecondParam); - - TemplateParameterList *FirstTPL = - FirstTTPD->getTemplateParameters(); - TemplateParameterList *SecondTPL = - SecondTTPD->getTemplateParameters(); - - auto ComputeTemplateParameterListODRHash = - [](const TemplateParameterList *TPL) { - assert(TPL); - ODRHash Hasher; - Hasher.AddTemplateParameterList(TPL); - return Hasher.CalculateHash(); - }; - - if (ComputeTemplateParameterListODRHash(FirstTPL) != - ComputeTemplateParameterListODRHash(SecondTPL)) { - DiagTemplateError(FunctionTemplateParameterDifferentType) - << (i + 1); - DiagTemplateNote(FunctionTemplateParameterDifferentType) - << (i + 1); - ParameterMismatch = true; - break; - } - - bool HasFirstDefaultArgument = - FirstTTPD->hasDefaultArgument() && - !FirstTTPD->defaultArgumentWasInherited(); - bool HasSecondDefaultArgument = - SecondTTPD->hasDefaultArgument() && - !SecondTTPD->defaultArgumentWasInherited(); - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument) - << (i + 1) << HasFirstDefaultArgument; - DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument) - << (i + 1) << HasSecondDefaultArgument; - ParameterMismatch = true; - break; - } - - if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - TemplateArgument FirstTA = - FirstTTPD->getDefaultArgument().getArgument(); - TemplateArgument SecondTA = - SecondTTPD->getDefaultArgument().getArgument(); - if (computeODRHash(FirstTA) != computeODRHash(SecondTA)) { - DiagTemplateError( - FunctionTemplateParameterDifferentDefaultArgument) - << (i + 1) << FirstTA; - DiagTemplateNote( - FunctionTemplateParameterDifferentDefaultArgument) - << (i + 1) << SecondTA; - ParameterMismatch = true; - break; - } - } - - if (FirstTTPD->isParameterPack() != - SecondTTPD->isParameterPack()) { - DiagTemplateError(FunctionTemplatePackParameter) - << (i + 1) << FirstTTPD->isParameterPack(); - DiagTemplateNote(FunctionTemplatePackParameter) - << (i + 1) << SecondTTPD->isParameterPack(); - ParameterMismatch = true; - break; - } - } - - if (isa<NonTypeTemplateParmDecl>(FirstParam) && - isa<NonTypeTemplateParmDecl>(SecondParam)) { - NonTypeTemplateParmDecl *FirstNTTPD = - cast<NonTypeTemplateParmDecl>(FirstParam); - NonTypeTemplateParmDecl *SecondNTTPD = - cast<NonTypeTemplateParmDecl>(SecondParam); - - QualType FirstType = FirstNTTPD->getType(); - QualType SecondType = SecondNTTPD->getType(); - if (computeODRHash(FirstType) != computeODRHash(SecondType)) { - DiagTemplateError(FunctionTemplateParameterDifferentType) - << (i + 1); - DiagTemplateNote(FunctionTemplateParameterDifferentType) - << (i + 1); - ParameterMismatch = true; - break; - } - - bool HasFirstDefaultArgument = - FirstNTTPD->hasDefaultArgument() && - !FirstNTTPD->defaultArgumentWasInherited(); - bool HasSecondDefaultArgument = - SecondNTTPD->hasDefaultArgument() && - !SecondNTTPD->defaultArgumentWasInherited(); - if (HasFirstDefaultArgument != HasSecondDefaultArgument) { - DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument) - << (i + 1) << HasFirstDefaultArgument; - DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument) - << (i + 1) << HasSecondDefaultArgument; - ParameterMismatch = true; - break; - } - - if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument(); - Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument(); - if (computeODRHash(FirstDefaultArgument) != - computeODRHash(SecondDefaultArgument)) { - DiagTemplateError( - FunctionTemplateParameterDifferentDefaultArgument) - << (i + 1) << FirstDefaultArgument; - DiagTemplateNote( - FunctionTemplateParameterDifferentDefaultArgument) - << (i + 1) << SecondDefaultArgument; - ParameterMismatch = true; - break; - } - } - - if (FirstNTTPD->isParameterPack() != - SecondNTTPD->isParameterPack()) { - DiagTemplateError(FunctionTemplatePackParameter) - << (i + 1) << FirstNTTPD->isParameterPack(); - DiagTemplateNote(FunctionTemplatePackParameter) - << (i + 1) << SecondNTTPD->isParameterPack(); - ParameterMismatch = true; - break; - } - } - } - - if (ParameterMismatch) { - Diagnosed = true; - break; - } - - break; - } - } - - if (Diagnosed) - continue; - - Diag(FirstDecl->getLocation(), - diag::err_module_odr_violation_mismatch_decl_unknown) - << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType - << FirstDecl->getSourceRange(); - Diag(SecondDecl->getLocation(), - diag::note_module_odr_violation_mismatch_decl_unknown) - << SecondModule << FirstDiffType << SecondDecl->getSourceRange(); - Diagnosed = true; } if (!Diagnosed) { @@ -11021,158 +9705,39 @@ void ASTReader::diagnoseOdrViolations() { // FIXME: How can this even happen? Diag(Merge.first->getLocation(), diag::err_module_odr_violation_different_instantiations) - << Merge.first; + << Merge.first; } } - // Issue ODR failures diagnostics for functions. - for (auto &Merge : FunctionOdrMergeFailures) { - enum ODRFunctionDifference { - ReturnType, - ParameterName, - ParameterType, - ParameterSingleDefaultArgument, - ParameterDifferentDefaultArgument, - FunctionBody, - }; - - FunctionDecl *FirstFunction = Merge.first; - std::string FirstModule = getOwningModuleNameForDiagnostic(FirstFunction); + // Issue any pending ODR-failure diagnostics for RecordDecl in C/ObjC. Note + // that in C++ this is done as a part of CXXRecordDecl ODR checking. + for (auto &Merge : RecordOdrMergeFailures) { + // If we've already pointed out a specific problem with this class, don't + // bother issuing a general "something's different" diagnostic. + if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) + continue; + RecordDecl *FirstRecord = Merge.first; bool Diagnosed = false; - for (auto &SecondFunction : Merge.second) { - - if (FirstFunction == SecondFunction) - continue; - - std::string SecondModule = - getOwningModuleNameForDiagnostic(SecondFunction); - - auto ODRDiagError = [FirstFunction, &FirstModule, - this](SourceLocation Loc, SourceRange Range, - ODRFunctionDifference DiffType) { - return Diag(Loc, diag::err_module_odr_violation_function) - << FirstFunction << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc, - SourceRange Range, - ODRFunctionDifference DiffType) { - return Diag(Loc, diag::note_module_odr_violation_function) - << SecondModule << Range << DiffType; - }; - - if (computeODRHash(FirstFunction->getReturnType()) != - computeODRHash(SecondFunction->getReturnType())) { - ODRDiagError(FirstFunction->getReturnTypeSourceRange().getBegin(), - FirstFunction->getReturnTypeSourceRange(), ReturnType) - << FirstFunction->getReturnType(); - ODRDiagNote(SecondFunction->getReturnTypeSourceRange().getBegin(), - SecondFunction->getReturnTypeSourceRange(), ReturnType) - << SecondFunction->getReturnType(); + for (auto *SecondRecord : Merge.second) { + if (DiagsEmitter.diagnoseMismatch(FirstRecord, SecondRecord)) { Diagnosed = true; break; } + } + (void)Diagnosed; + assert(Diagnosed && "Unable to emit ODR diagnostic."); + } - assert(FirstFunction->param_size() == SecondFunction->param_size() && - "Merged functions with different number of parameters"); - - size_t ParamSize = FirstFunction->param_size(); - bool ParameterMismatch = false; - for (unsigned I = 0; I < ParamSize; ++I) { - const ParmVarDecl *FirstParam = FirstFunction->getParamDecl(I); - const ParmVarDecl *SecondParam = SecondFunction->getParamDecl(I); - - assert(getContext().hasSameType(FirstParam->getType(), - SecondParam->getType()) && - "Merged function has different parameter types."); - - if (FirstParam->getDeclName() != SecondParam->getDeclName()) { - ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), - ParameterName) - << I + 1 << FirstParam->getDeclName(); - ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), - ParameterName) - << I + 1 << SecondParam->getDeclName(); - ParameterMismatch = true; - break; - }; - - QualType FirstParamType = FirstParam->getType(); - QualType SecondParamType = SecondParam->getType(); - if (FirstParamType != SecondParamType && - computeODRHash(FirstParamType) != computeODRHash(SecondParamType)) { - if (const DecayedType *ParamDecayedType = - FirstParamType->getAs<DecayedType>()) { - ODRDiagError(FirstParam->getLocation(), - FirstParam->getSourceRange(), ParameterType) - << (I + 1) << FirstParamType << true - << ParamDecayedType->getOriginalType(); - } else { - ODRDiagError(FirstParam->getLocation(), - FirstParam->getSourceRange(), ParameterType) - << (I + 1) << FirstParamType << false; - } - - if (const DecayedType *ParamDecayedType = - SecondParamType->getAs<DecayedType>()) { - ODRDiagNote(SecondParam->getLocation(), - SecondParam->getSourceRange(), ParameterType) - << (I + 1) << SecondParamType << true - << ParamDecayedType->getOriginalType(); - } else { - ODRDiagNote(SecondParam->getLocation(), - SecondParam->getSourceRange(), ParameterType) - << (I + 1) << SecondParamType << false; - } - ParameterMismatch = true; - break; - } - - const Expr *FirstInit = FirstParam->getInit(); - const Expr *SecondInit = SecondParam->getInit(); - if ((FirstInit == nullptr) != (SecondInit == nullptr)) { - ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), - ParameterSingleDefaultArgument) - << (I + 1) << (FirstInit == nullptr) - << (FirstInit ? FirstInit->getSourceRange() : SourceRange()); - ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), - ParameterSingleDefaultArgument) - << (I + 1) << (SecondInit == nullptr) - << (SecondInit ? SecondInit->getSourceRange() : SourceRange()); - ParameterMismatch = true; - break; - } - - if (FirstInit && SecondInit && - computeODRHash(FirstInit) != computeODRHash(SecondInit)) { - ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), - ParameterDifferentDefaultArgument) - << (I + 1) << FirstInit->getSourceRange(); - ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), - ParameterDifferentDefaultArgument) - << (I + 1) << SecondInit->getSourceRange(); - ParameterMismatch = true; - break; - } - - assert(computeODRHash(FirstParam) == computeODRHash(SecondParam) && - "Undiagnosed parameter difference."); - } - - if (ParameterMismatch) { + // Issue ODR failures diagnostics for functions. + for (auto &Merge : FunctionOdrMergeFailures) { + FunctionDecl *FirstFunction = Merge.first; + bool Diagnosed = false; + for (auto &SecondFunction : Merge.second) { + if (DiagsEmitter.diagnoseMismatch(FirstFunction, SecondFunction)) { Diagnosed = true; break; } - - // If no error has been generated before now, assume the problem is in - // the body and generate a message. - ODRDiagError(FirstFunction->getLocation(), - FirstFunction->getSourceRange(), FunctionBody); - ODRDiagNote(SecondFunction->getLocation(), - SecondFunction->getSourceRange(), FunctionBody); - Diagnosed = true; - break; } (void)Diagnosed; assert(Diagnosed && "Unable to emit ODR diagnostic."); @@ -11180,164 +9745,57 @@ void ASTReader::diagnoseOdrViolations() { // Issue ODR failures diagnostics for enums. for (auto &Merge : EnumOdrMergeFailures) { - enum ODREnumDifference { - SingleScopedEnum, - EnumTagKeywordMismatch, - SingleSpecifiedType, - DifferentSpecifiedTypes, - DifferentNumberEnumConstants, - EnumConstantName, - EnumConstantSingleInitializer, - EnumConstantDifferentInitializer, - }; - // If we've already pointed out a specific problem with this enum, don't // bother issuing a general "something's different" diagnostic. if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) continue; EnumDecl *FirstEnum = Merge.first; - std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum); - - using DeclHashes = - llvm::SmallVector<std::pair<EnumConstantDecl *, unsigned>, 4>; - auto PopulateHashes = [FirstEnum](DeclHashes &Hashes, EnumDecl *Enum) { - for (auto *D : Enum->decls()) { - // Due to decl merging, the first EnumDecl is the parent of - // Decls in both records. - if (!ODRHash::isDeclToBeProcessed(D, FirstEnum)) - continue; - assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind"); - Hashes.emplace_back(cast<EnumConstantDecl>(D), computeODRHash(D)); - } - }; - DeclHashes FirstHashes; - PopulateHashes(FirstHashes, FirstEnum); bool Diagnosed = false; for (auto &SecondEnum : Merge.second) { - - if (FirstEnum == SecondEnum) - continue; - - std::string SecondModule = - getOwningModuleNameForDiagnostic(SecondEnum); - - auto ODRDiagError = [FirstEnum, &FirstModule, - this](const auto *DiagAnchor, - ODREnumDifference DiffType) { - return Diag(DiagAnchor->getLocation(), - diag::err_module_odr_violation_enum) - << FirstEnum << FirstModule.empty() << FirstModule - << DiagAnchor->getSourceRange() << DiffType; - }; - auto ODRDiagNote = [&SecondModule, this](const auto *DiagAnchor, - ODREnumDifference DiffType) { - return Diag(DiagAnchor->getLocation(), - diag::note_module_odr_violation_enum) - << SecondModule << DiagAnchor->getSourceRange() << DiffType; - }; - - if (FirstEnum->isScoped() != SecondEnum->isScoped()) { - ODRDiagError(FirstEnum, SingleScopedEnum) << FirstEnum->isScoped(); - ODRDiagNote(SecondEnum, SingleScopedEnum) << SecondEnum->isScoped(); + if (DiagsEmitter.diagnoseMismatch(FirstEnum, SecondEnum)) { Diagnosed = true; - continue; + break; } + } + (void)Diagnosed; + assert(Diagnosed && "Unable to emit ODR diagnostic."); + } - if (FirstEnum->isScoped() && SecondEnum->isScoped()) { - if (FirstEnum->isScopedUsingClassTag() != - SecondEnum->isScopedUsingClassTag()) { - ODRDiagError(FirstEnum, EnumTagKeywordMismatch) - << FirstEnum->isScopedUsingClassTag(); - ODRDiagNote(SecondEnum, EnumTagKeywordMismatch) - << SecondEnum->isScopedUsingClassTag(); - Diagnosed = true; - continue; - } - } + for (auto &Merge : ObjCInterfaceOdrMergeFailures) { + // If we've already pointed out a specific problem with this interface, + // don't bother issuing a general "something's different" diagnostic. + if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) + continue; - QualType FirstUnderlyingType = - FirstEnum->getIntegerTypeSourceInfo() - ? FirstEnum->getIntegerTypeSourceInfo()->getType() - : QualType(); - QualType SecondUnderlyingType = - SecondEnum->getIntegerTypeSourceInfo() - ? SecondEnum->getIntegerTypeSourceInfo()->getType() - : QualType(); - if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) { - ODRDiagError(FirstEnum, SingleSpecifiedType) - << !FirstUnderlyingType.isNull(); - ODRDiagNote(SecondEnum, SingleSpecifiedType) - << !SecondUnderlyingType.isNull(); + bool Diagnosed = false; + ObjCInterfaceDecl *FirstID = Merge.first; + for (auto &InterfacePair : Merge.second) { + if (DiagsEmitter.diagnoseMismatch(FirstID, InterfacePair.first, + InterfacePair.second)) { Diagnosed = true; - continue; - } - - if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) { - if (computeODRHash(FirstUnderlyingType) != - computeODRHash(SecondUnderlyingType)) { - ODRDiagError(FirstEnum, DifferentSpecifiedTypes) - << FirstUnderlyingType; - ODRDiagNote(SecondEnum, DifferentSpecifiedTypes) - << SecondUnderlyingType; - Diagnosed = true; - continue; - } + break; } + } + (void)Diagnosed; + assert(Diagnosed && "Unable to emit ODR diagnostic."); + } - DeclHashes SecondHashes; - PopulateHashes(SecondHashes, SecondEnum); + for (auto &Merge : ObjCProtocolOdrMergeFailures) { + // If we've already pointed out a specific problem with this protocol, + // don't bother issuing a general "something's different" diagnostic. + if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) + continue; - if (FirstHashes.size() != SecondHashes.size()) { - ODRDiagError(FirstEnum, DifferentNumberEnumConstants) - << (int)FirstHashes.size(); - ODRDiagNote(SecondEnum, DifferentNumberEnumConstants) - << (int)SecondHashes.size(); + ObjCProtocolDecl *FirstProtocol = Merge.first; + bool Diagnosed = false; + for (auto &ProtocolPair : Merge.second) { + if (DiagsEmitter.diagnoseMismatch(FirstProtocol, ProtocolPair.first, + ProtocolPair.second)) { Diagnosed = true; - continue; - } - - for (unsigned I = 0; I < FirstHashes.size(); ++I) { - if (FirstHashes[I].second == SecondHashes[I].second) - continue; - const EnumConstantDecl *FirstConstant = FirstHashes[I].first; - const EnumConstantDecl *SecondConstant = SecondHashes[I].first; - - if (FirstConstant->getDeclName() != SecondConstant->getDeclName()) { - - ODRDiagError(FirstConstant, EnumConstantName) - << I + 1 << FirstConstant; - ODRDiagNote(SecondConstant, EnumConstantName) - << I + 1 << SecondConstant; - Diagnosed = true; - break; - } - - const Expr *FirstInit = FirstConstant->getInitExpr(); - const Expr *SecondInit = SecondConstant->getInitExpr(); - if (!FirstInit && !SecondInit) - continue; - - if (!FirstInit || !SecondInit) { - ODRDiagError(FirstConstant, EnumConstantSingleInitializer) - << I + 1 << FirstConstant << (FirstInit != nullptr); - ODRDiagNote(SecondConstant, EnumConstantSingleInitializer) - << I + 1 << SecondConstant << (SecondInit != nullptr); - Diagnosed = true; - break; - } - - if (computeODRHash(FirstInit) != computeODRHash(SecondInit)) { - ODRDiagError(FirstConstant, EnumConstantDifferentInitializer) - << I + 1 << FirstConstant; - ODRDiagNote(SecondConstant, EnumConstantDifferentInitializer) - << I + 1 << SecondConstant; - Diagnosed = true; - break; - } + break; } } - (void)Diagnosed; assert(Diagnosed && "Unable to emit ODR diagnostic."); } @@ -11619,7 +10077,16 @@ OMPClause *OMPClauseReader::readClause() { case llvm::omp::OMPC_atomic_default_mem_order: C = new (Context) OMPAtomicDefaultMemOrderClause(); break; - case llvm::omp::OMPC_private: + case llvm::omp::OMPC_at: + C = new (Context) OMPAtClause(); + break; + case llvm::omp::OMPC_severity: + C = new (Context) OMPSeverityClause(); + break; + case llvm::omp::OMPC_message: + C = new (Context) OMPMessageClause(); + break; + case llvm::omp::OMPC_private: C = OMPPrivateClause::CreateEmpty(Context, Record.readInt()); break; case llvm::omp::OMPC_firstprivate: @@ -11805,6 +10272,9 @@ OMPClause *OMPClauseReader::readClause() { case llvm::omp::OMPC_align: C = new (Context) OMPAlignClause(); break; + case llvm::omp::OMPC_ompx_dyn_cgroup_mem: + C = new (Context) OMPXDynCGroupMemClause(); + break; #define OMP_CLAUSE_NO_CLASS(Enum, Str) \ case llvm::omp::Enum: \ break; @@ -12021,6 +10491,23 @@ void OMPClauseReader::VisitOMPAtomicDefaultMemOrderClause( C->setAtomicDefaultMemOrderKindKwLoc(Record.readSourceLocation()); } +void OMPClauseReader::VisitOMPAtClause(OMPAtClause *C) { + C->setAtKind(static_cast<OpenMPAtClauseKind>(Record.readInt())); + C->setLParenLoc(Record.readSourceLocation()); + C->setAtKindKwLoc(Record.readSourceLocation()); +} + +void OMPClauseReader::VisitOMPSeverityClause(OMPSeverityClause *C) { + C->setSeverityKind(static_cast<OpenMPSeverityClauseKind>(Record.readInt())); + C->setLParenLoc(Record.readSourceLocation()); + C->setSeverityKindKwLoc(Record.readSourceLocation()); +} + +void OMPClauseReader::VisitOMPMessageClause(OMPMessageClause *C) { + C->setMessageString(Record.readSubExpr()); + C->setLParenLoc(Record.readSourceLocation()); +} + void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) { C->setLParenLoc(Record.readSourceLocation()); unsigned NumVars = C->varlist_size(); @@ -12347,10 +10834,13 @@ void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) { void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) { C->setLParenLoc(Record.readSourceLocation()); + bool HasIteratorModifier = false; for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) { C->setMapTypeModifier( I, static_cast<OpenMPMapModifierKind>(Record.readInt())); C->setMapTypeModifierLoc(I, Record.readSourceLocation()); + if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator) + HasIteratorModifier = true; } C->setMapperQualifierLoc(Record.readNestedNameSpecifierLoc()); C->setMapperIdInfo(Record.readDeclarationNameInfo()); @@ -12375,6 +10865,9 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) { UDMappers.push_back(Record.readExpr()); C->setUDMapperRefs(UDMappers); + if (HasIteratorModifier) + C->setIteratorModifier(Record.readExpr()); + SmallVector<ValueDecl *, 16> Decls; Decls.reserve(UniqueDecls); for (unsigned i = 0; i < UniqueDecls; ++i) @@ -12436,13 +10929,17 @@ void OMPClauseReader::VisitOMPPriorityClause(OMPPriorityClause *C) { void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) { VisitOMPClauseWithPreInit(C); + C->setModifier(Record.readEnum<OpenMPGrainsizeClauseModifier>()); C->setGrainsize(Record.readSubExpr()); + C->setModifierLoc(Record.readSourceLocation()); C->setLParenLoc(Record.readSourceLocation()); } void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) { VisitOMPClauseWithPreInit(C); + C->setModifier(Record.readEnum<OpenMPNumTasksClauseModifier>()); C->setNumTasks(Record.readSubExpr()); + C->setModifierLoc(Record.readSourceLocation()); C->setLParenLoc(Record.readSourceLocation()); } @@ -12825,8 +11322,10 @@ void OMPClauseReader::VisitOMPAffinityClause(OMPAffinityClause *C) { void OMPClauseReader::VisitOMPOrderClause(OMPOrderClause *C) { C->setKind(Record.readEnum<OpenMPOrderClauseKind>()); + C->setModifier(Record.readEnum<OpenMPOrderClauseModifier>()); C->setLParenLoc(Record.readSourceLocation()); C->setKindKwLoc(Record.readSourceLocation()); + C->setModifierKwLoc(Record.readSourceLocation()); } void OMPClauseReader::VisitOMPFilterClause(OMPFilterClause *C) { @@ -12846,6 +11345,12 @@ void OMPClauseReader::VisitOMPAlignClause(OMPAlignClause *C) { C->setLParenLoc(Record.readSourceLocation()); } +void OMPClauseReader::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) { + VisitOMPClauseWithPreInit(C); + C->setSize(Record.readSubExpr()); + C->setLParenLoc(Record.readSourceLocation()); +} + OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() { OMPTraitInfo &TI = getContext().getNewOMPTraitInfo(); TI.Sets.resize(readUInt32()); diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp index 73800191dfc1..8cb513eff13e 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp @@ -322,6 +322,7 @@ namespace clang { void VisitNamedDecl(NamedDecl *ND); void VisitLabelDecl(LabelDecl *LD); void VisitNamespaceDecl(NamespaceDecl *D); + void VisitHLSLBufferDecl(HLSLBufferDecl *D); void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *TD); @@ -381,8 +382,10 @@ namespace clang { void VisitDecompositionDecl(DecompositionDecl *DD); void VisitBindingDecl(BindingDecl *BD); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - DeclID VisitTemplateDecl(TemplateDecl *D); + void VisitTemplateDecl(TemplateDecl *D); void VisitConceptDecl(ConceptDecl *D); + void VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D); void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); @@ -399,6 +402,7 @@ namespace clang { void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitExportDecl(ExportDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); + void VisitTopLevelStmtDecl(TopLevelStmtDecl *D); void VisitImportDecl(ImportDecl *D); void VisitAccessSpecDecl(AccessSpecDecl *D); void VisitFriendDecl(FriendDecl *D); @@ -414,14 +418,15 @@ namespace clang { template<typename T> RedeclarableResult VisitRedeclarable(Redeclarable<T> *D); - template<typename T> - void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl, - DeclID TemplatePatternID = 0); + template <typename T> + void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl); - template<typename T> + void mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, + RedeclarableResult &Redecl); + + template <typename T> void mergeRedeclarable(Redeclarable<T> *D, T *Existing, - RedeclarableResult &Redecl, - DeclID TemplatePatternID = 0); + RedeclarableResult &Redecl); template<typename T> void mergeMergeable(Mergeable<T> *D); @@ -430,7 +435,7 @@ namespace clang { void mergeTemplatePattern(RedeclarableTemplateDecl *D, RedeclarableTemplateDecl *Existing, - DeclID DsID, bool IsKeyDecl); + bool IsKeyDecl); ObjCTypeParamList *ReadObjCTypeParamList(); @@ -563,7 +568,7 @@ void ASTDeclReader::Visit(Decl *D) { void ASTDeclReader::VisitDecl(Decl *D) { if (D->isTemplateParameter() || D->isTemplateParameterPack() || - isa<ParmVarDecl>(D) || isa<ObjCTypeParamDecl>(D)) { + isa<ParmVarDecl, ObjCTypeParamDecl>(D)) { // We don't want to deserialize the DeclContext of a template // parameter or of a parameter of a function template immediately. These // entities might be used in the formulation of its DeclContext (for @@ -824,6 +829,7 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); + RD->setODRHash(Record.readInt()); // Maintain the invariant of a redeclaration chain containing only // a single definition. @@ -844,6 +850,8 @@ void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { Reader.MergedDeclContexts.insert(std::make_pair(RD, OldDef)); RD->demoteThisDefinitionToDeclaration(); Reader.mergeDefinitionVisibility(OldDef, RD); + if (OldDef->getODRHash() != RD->getODRHash()) + Reader.PendingRecordOdrMergeFailures[OldDef].push_back(RD); } else { OldDef = RD; } @@ -886,88 +894,27 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { RedeclarableResult Redecl = VisitRedeclarable(FD); - VisitDeclaratorDecl(FD); - - // Attach a type to this function. Use the real type if possible, but fall - // back to the type as written if it involves a deduced return type. - if (FD->getTypeSourceInfo() && - FD->getTypeSourceInfo()->getType()->castAs<FunctionType>() - ->getReturnType()->getContainedAutoType()) { - // We'll set up the real type in Visit, once we've finished loading the - // function. - FD->setType(FD->getTypeSourceInfo()->getType()); - Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID}); - } else { - FD->setType(Reader.GetType(DeferredTypeID)); - } - DeferredTypeID = 0; - - FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName()); - FD->IdentifierNamespace = Record.readInt(); - - // FunctionDecl's body is handled last at ASTDeclReader::Visit, - // after everything else is read. - - FD->setStorageClass(static_cast<StorageClass>(Record.readInt())); - FD->setInlineSpecified(Record.readInt()); - FD->setImplicitlyInline(Record.readInt()); - FD->setVirtualAsWritten(Record.readInt()); - // We defer calling `FunctionDecl::setPure()` here as for methods of - // `CXXTemplateSpecializationDecl`s, we may not have connected up the - // definition (which is required for `setPure`). - const bool Pure = Record.readInt(); - FD->setHasInheritedPrototype(Record.readInt()); - FD->setHasWrittenPrototype(Record.readInt()); - FD->setDeletedAsWritten(Record.readInt()); - FD->setTrivial(Record.readInt()); - FD->setTrivialForCall(Record.readInt()); - FD->setDefaulted(Record.readInt()); - FD->setExplicitlyDefaulted(Record.readInt()); - FD->setHasImplicitReturnZero(Record.readInt()); - FD->setConstexprKind(static_cast<ConstexprSpecKind>(Record.readInt())); - FD->setUsesSEHTry(Record.readInt()); - FD->setHasSkippedBody(Record.readInt()); - FD->setIsMultiVersion(Record.readInt()); - FD->setLateTemplateParsed(Record.readInt()); - - FD->setCachedLinkage(static_cast<Linkage>(Record.readInt())); - FD->EndRangeLoc = readSourceLocation(); - FD->ODRHash = Record.readInt(); - FD->setHasODRHash(true); - - if (FD->isDefaulted()) { - if (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)); - } - } + FunctionDecl *Existing = nullptr; switch ((FunctionDecl::TemplatedKind)Record.readInt()) { case FunctionDecl::TK_NonTemplate: - mergeRedeclarable(FD, Redecl); break; case FunctionDecl::TK_DependentNonTemplate: - mergeRedeclarable(FD, Redecl); FD->setInstantiatedFromDecl(readDeclAs<FunctionDecl>()); break; - case FunctionDecl::TK_FunctionTemplate: - // Merged when we merge the template. - FD->setDescribedFunctionTemplate(readDeclAs<FunctionTemplateDecl>()); + case FunctionDecl::TK_FunctionTemplate: { + auto *Template = readDeclAs<FunctionTemplateDecl>(); + Template->init(FD); + FD->setDescribedFunctionTemplate(Template); break; + } case FunctionDecl::TK_MemberSpecialization: { auto *InstFD = readDeclAs<FunctionDecl>(); auto TSK = (TemplateSpecializationKind)Record.readInt(); SourceLocation POI = readSourceLocation(); FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - mergeRedeclarable(FD, Redecl); break; } case FunctionDecl::TK_FunctionTemplateSpecialization: { @@ -1038,7 +985,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { else { assert(Reader.getContext().getLangOpts().Modules && "already deserialized this template specialization"); - mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl); + Existing = ExistingInfo->getFunction(); } } break; @@ -1066,6 +1013,97 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { } } + VisitDeclaratorDecl(FD); + + // Attach a type to this function. Use the real type if possible, but fall + // back to the type as written if it involves a deduced return type. + if (FD->getTypeSourceInfo() && FD->getTypeSourceInfo() + ->getType() + ->castAs<FunctionType>() + ->getReturnType() + ->getContainedAutoType()) { + // We'll set up the real type in Visit, once we've finished loading the + // function. + FD->setType(FD->getTypeSourceInfo()->getType()); + Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID}); + } else { + FD->setType(Reader.GetType(DeferredTypeID)); + } + DeferredTypeID = 0; + + FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName()); + FD->IdentifierNamespace = Record.readInt(); + + // FunctionDecl's body is handled last at ASTDeclReader::Visit, + // after everything else is read. + + FD->setStorageClass(static_cast<StorageClass>(Record.readInt())); + FD->setInlineSpecified(Record.readInt()); + FD->setImplicitlyInline(Record.readInt()); + FD->setVirtualAsWritten(Record.readInt()); + // We defer calling `FunctionDecl::setPure()` here as for methods of + // `CXXTemplateSpecializationDecl`s, we may not have connected up the + // definition (which is required for `setPure`). + const bool Pure = Record.readInt(); + FD->setHasInheritedPrototype(Record.readInt()); + FD->setHasWrittenPrototype(Record.readInt()); + FD->setDeletedAsWritten(Record.readInt()); + FD->setTrivial(Record.readInt()); + FD->setTrivialForCall(Record.readInt()); + FD->setDefaulted(Record.readInt()); + FD->setExplicitlyDefaulted(Record.readInt()); + FD->setIneligibleOrNotSelected(Record.readInt()); + FD->setHasImplicitReturnZero(Record.readInt()); + FD->setConstexprKind(static_cast<ConstexprSpecKind>(Record.readInt())); + FD->setUsesSEHTry(Record.readInt()); + FD->setHasSkippedBody(Record.readInt()); + FD->setIsMultiVersion(Record.readInt()); + FD->setLateTemplateParsed(Record.readInt()); + FD->setFriendConstraintRefersToEnclosingTemplate(Record.readInt()); + + FD->setCachedLinkage(static_cast<Linkage>(Record.readInt())); + FD->EndRangeLoc = readSourceLocation(); + FD->setDefaultLoc(readSourceLocation()); + + FD->ODRHash = Record.readInt(); + FD->setHasODRHash(true); + + if (FD->isDefaulted()) { + if (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)); + } + } + + if (Existing) + mergeRedeclarable(FD, Existing, Redecl); + else if (auto Kind = FD->getTemplatedKind(); + Kind == FunctionDecl::TK_FunctionTemplate || + Kind == FunctionDecl::TK_FunctionTemplateSpecialization) { + // Function Templates have their FunctionTemplateDecls merged instead of + // their FunctionDecls. + auto merge = [this, &Redecl, FD](auto &&F) { + auto *Existing = cast_or_null<FunctionDecl>(Redecl.getKnownMergeTarget()); + RedeclarableResult NewRedecl(Existing ? F(Existing) : nullptr, + Redecl.getFirstID(), Redecl.isKeyDecl()); + mergeRedeclarableTemplate(F(FD), NewRedecl); + }; + if (Kind == FunctionDecl::TK_FunctionTemplate) + merge( + [](FunctionDecl *FD) { return FD->getDescribedFunctionTemplate(); }); + else + merge([](FunctionDecl *FD) { + return FD->getTemplateSpecializationInfo()->getTemplate(); + }); + } else + mergeRedeclarable(FD, Redecl); + // Defer calling `setPure` until merging above has guaranteed we've set // `DefinitionData` (as this will need to access it). FD->setPure(Pure); @@ -1169,6 +1207,8 @@ void ASTDeclReader::ReadObjCDefinitionData( Data.EndLoc = readSourceLocation(); Data.HasDesignatedInitializers = Record.readInt(); + Data.ODRHash = Record.readInt(); + Data.HasODRHash = true; // Read the directly referenced protocols and their SourceLocations. unsigned NumProtocols = Record.readInt(); @@ -1196,13 +1236,16 @@ void ASTDeclReader::ReadObjCDefinitionData( void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, struct ObjCInterfaceDecl::DefinitionData &&NewDD) { struct ObjCInterfaceDecl::DefinitionData &DD = D->data(); - if (DD.Definition != NewDD.Definition) { - Reader.MergedDeclContexts.insert( - std::make_pair(NewDD.Definition, DD.Definition)); - Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition); - } + if (DD.Definition == NewDD.Definition) + return; + + Reader.MergedDeclContexts.insert( + std::make_pair(NewDD.Definition, DD.Definition)); + Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition); - // FIXME: odr checking? + if (D->getODRHash() != NewDD.ODRHash) + Reader.PendingObjCInterfaceOdrMergeFailures[DD.Definition].push_back( + {NewDD.Definition, &NewDD}); } void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { @@ -1297,18 +1340,23 @@ void ASTDeclReader::ReadObjCDefinitionData( ProtoLocs.push_back(readSourceLocation()); Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), Reader.getContext()); + Data.ODRHash = Record.readInt(); + Data.HasODRHash = true; } -void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D, - struct ObjCProtocolDecl::DefinitionData &&NewDD) { +void ASTDeclReader::MergeDefinitionData( + ObjCProtocolDecl *D, struct ObjCProtocolDecl::DefinitionData &&NewDD) { struct ObjCProtocolDecl::DefinitionData &DD = D->data(); - if (DD.Definition != NewDD.Definition) { - Reader.MergedDeclContexts.insert( - std::make_pair(NewDD.Definition, DD.Definition)); - Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition); - } + if (DD.Definition == NewDD.Definition) + return; + + Reader.MergedDeclContexts.insert( + std::make_pair(NewDD.Definition, DD.Definition)); + Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition); - // FIXME: odr checking? + if (D->getODRHash() != NewDD.ODRHash) + Reader.PendingObjCProtocolOdrMergeFailures[DD.Definition].push_back( + {NewDD.Definition, &NewDD}); } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { @@ -1640,6 +1688,11 @@ void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { AD->setRParenLoc(readSourceLocation()); } +void ASTDeclReader::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) { + VisitDecl(D); + D->Statement = Record.readStmt(); +} + void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { VisitDecl(BD); BD->setBody(cast_or_null<CompoundStmt>(Record.readStmt())); @@ -1707,6 +1760,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); D->setInline(Record.readInt()); + D->setNested(Record.readInt()); D->LocStart = readSourceLocation(); D->RBraceLoc = readSourceLocation(); @@ -1720,7 +1774,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { } else { // Link this namespace back to the first declaration, which has already // been deserialized. - D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl()); + D->AnonOrFirstNamespaceAndFlags.setPointer(D->getFirstDecl()); } mergeRedeclarable(D, Redecl); @@ -1735,6 +1789,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { } } +void ASTDeclReader::VisitHLSLBufferDecl(HLSLBufferDecl *D) { + VisitNamedDecl(D); + VisitDeclContext(D); + D->IsCBuffer = Record.readBool(); + D->KwLoc = readSourceLocation(); + D->LBraceLoc = readSourceLocation(); + D->RBraceLoc = readSourceLocation(); +} + void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); @@ -1761,7 +1824,7 @@ void ASTDeclReader::VisitUsingEnumDecl(UsingEnumDecl *D) { VisitNamedDecl(D); D->setUsingLoc(readSourceLocation()); D->setEnumLoc(readSourceLocation()); - D->Enum = readDeclAs<EnumDecl>(); + D->setEnumType(Record.readTypeSourceInfo()); D->FirstUsingShadow.setPointer(readDeclAs<UsingShadowDecl>()); if (auto *Pattern = readDeclAs<UsingEnumDecl>()) Reader.getContext().setInstantiatedFromUsingEnumDecl(D, Pattern); @@ -1872,9 +1935,12 @@ void ASTDeclReader::ReadCXXDefinitionData( Lambda.ManglingNumber = Record.readInt(); D->setDeviceLambdaManglingNumber(Record.readInt()); Lambda.ContextDecl = readDeclID(); - Lambda.Captures = (Capture *)Reader.getContext().Allocate( - sizeof(Capture) * Lambda.NumCaptures); - Capture *ToCapture = Lambda.Captures; + Capture *ToCapture = nullptr; + if (Lambda.NumCaptures) { + ToCapture = (Capture *)Reader.getContext().Allocate(sizeof(Capture) * + Lambda.NumCaptures); + Lambda.AddCaptureList(Reader.getContext(), ToCapture); + } Lambda.MethodTyInfo = readTypeSourceInfo(); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { SourceLocation Loc = readSourceLocation(); @@ -1958,8 +2024,26 @@ void ASTDeclReader::MergeDefinitionData( // lazily load it. if (DD.IsLambda) { - // FIXME: ODR-checking for merging lambdas (this happens, for instance, - // when they occur within the body of a function template specialization). + auto &Lambda1 = static_cast<CXXRecordDecl::LambdaDefinitionData &>(DD); + auto &Lambda2 = static_cast<CXXRecordDecl::LambdaDefinitionData &>(MergeDD); + DetectedOdrViolation |= Lambda1.DependencyKind != Lambda2.DependencyKind; + DetectedOdrViolation |= Lambda1.IsGenericLambda != Lambda2.IsGenericLambda; + DetectedOdrViolation |= Lambda1.CaptureDefault != Lambda2.CaptureDefault; + DetectedOdrViolation |= Lambda1.NumCaptures != Lambda2.NumCaptures; + DetectedOdrViolation |= + Lambda1.NumExplicitCaptures != Lambda2.NumExplicitCaptures; + DetectedOdrViolation |= + Lambda1.HasKnownInternalLinkage != Lambda2.HasKnownInternalLinkage; + DetectedOdrViolation |= Lambda1.ManglingNumber != Lambda2.ManglingNumber; + + if (Lambda1.NumCaptures && Lambda1.NumCaptures == Lambda2.NumCaptures) { + for (unsigned I = 0, N = Lambda1.NumCaptures; I != N; ++I) { + LambdaCapture &Cap1 = Lambda1.Captures.front()[I]; + LambdaCapture &Cap2 = Lambda2.Captures.front()[I]; + DetectedOdrViolation |= Cap1.getCaptureKind() != Cap2.getCaptureKind(); + } + Lambda1.AddCaptureList(Reader.getContext(), Lambda2.Captures.front()); + } } if (D->getODRHash() != MergeDD.ODRHash) { @@ -2175,15 +2259,12 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { D->FriendLoc = readSourceLocation(); } -DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { +void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { VisitNamedDecl(D); - DeclID PatternID = readDeclID(); - auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); - TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); - D->init(TemplatedDecl, TemplateParams); - - return PatternID; + assert(!D->TemplateParams && "TemplateParams already set!"); + D->TemplateParams = Record.readTemplateParameterList(); + D->init(readDeclAs<NamedDecl>()); } void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) { @@ -2192,6 +2273,17 @@ void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) { mergeMergeable(D); } +void ASTDeclReader::VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D) { + // The size of the template list was read during creation of the Decl, so we + // don't have to re-read it here. + VisitDecl(D); + llvm::SmallVector<TemplateArgument, 4> Args; + for (unsigned I = 0; I < D->NumTemplateArgs; ++I) + Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/true)); + D->setTemplateArguments(Args); +} + void ASTDeclReader::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { } @@ -2220,21 +2312,15 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { } } - DeclID PatternID = VisitTemplateDecl(D); + VisitTemplateDecl(D); D->IdentifierNamespace = Record.readInt(); - mergeRedeclarable(D, Redecl, PatternID); - - // If we merged the template with a prior declaration chain, merge the common - // pointer. - // FIXME: Actually merge here, don't just overwrite. - D->Common = D->getCanonicalDecl()->Common; - return Redecl; } void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); if (ThisDeclID == Redecl.getFirstID()) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of @@ -2262,6 +2348,7 @@ void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { /// VarTemplateDecl beyond TemplateDecl... void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); if (ThisDeclID == Redecl.getFirstID()) { // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of @@ -2390,8 +2477,6 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( VarTemplateSpecializationDecl *D) { - RedeclarableResult Redecl = VisitVarDeclImpl(D); - ASTContext &C = Reader.getContext(); if (Decl *InstD = readDecl()) { if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) { @@ -2428,6 +2513,8 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( D->SpecializationKind = (TemplateSpecializationKind)Record.readInt(); D->IsCompleteDefinition = Record.readInt(); + RedeclarableResult Redecl = VisitVarDeclImpl(D); + bool writtenAsCanonicalDecl = Record.readInt(); if (writtenAsCanonicalDecl) { auto *CanonPattern = readDeclAs<VarTemplateDecl>(); @@ -2535,7 +2622,8 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { } void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); + RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); } void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { @@ -2632,10 +2720,9 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { /// Attempts to merge the given declaration (D) with another declaration /// of the same entity. -template<typename T> +template <typename T> void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, - RedeclarableResult &Redecl, - DeclID TemplatePatternID) { + RedeclarableResult &Redecl) { // If modules are not available, there is no reason to perform this merge. if (!Reader.getContext().getLangOpts().Modules) return; @@ -2648,10 +2735,19 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, if (auto *Existing = Redecl.getKnownMergeTarget()) // We already know of an existing declaration we should merge with. - mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID); + mergeRedeclarable(D, cast<T>(Existing), Redecl); else if (FindExistingResult ExistingRes = findExisting(D)) if (T *Existing = ExistingRes) - mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); + mergeRedeclarable(D, Existing, Redecl); +} + +void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, + RedeclarableResult &Redecl) { + mergeRedeclarable(D, Redecl); + // If we merged the template with a prior declaration chain, merge the + // common pointer. + // FIXME: Actually merge here, don't just overwrite. + D->Common = D->getCanonicalDecl()->Common; } /// "Cast" to type T, asserting if we don't have an implicit conversion. @@ -2666,7 +2762,7 @@ template<typename T> static T assert_cast(...) { /// declarations. void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, RedeclarableTemplateDecl *Existing, - DeclID DsID, bool IsKeyDecl) { + bool IsKeyDecl) { auto *DPattern = D->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl(); RedeclarableResult Result(/*MergeWith*/ ExistingPattern, @@ -2706,17 +2802,13 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, /// Attempts to merge the given declaration (D) with another declaration /// of the same entity. -template<typename T> +template <typename T> void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, - RedeclarableResult &Redecl, - DeclID TemplatePatternID) { + RedeclarableResult &Redecl) { auto *D = static_cast<T *>(DBase); T *ExistingCanon = Existing->getCanonicalDecl(); T *DCanon = D->getCanonicalDecl(); if (ExistingCanon != DCanon) { - assert(DCanon->getGlobalID() == Redecl.getFirstID() && - "already merged this declaration"); - // Have our redeclaration link point back at the canonical declaration // of the existing declaration, so that this declaration has the // appropriate canonical declaration. @@ -2729,14 +2821,14 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, // We cannot have loaded any redeclarations of this declaration yet, so // there's nothing else that needs to be updated. if (auto *Namespace = dyn_cast<NamespaceDecl>(D)) - Namespace->AnonOrFirstNamespaceAndInline.setPointer( - assert_cast<NamespaceDecl*>(ExistingCanon)); + Namespace->AnonOrFirstNamespaceAndFlags.setPointer( + assert_cast<NamespaceDecl *>(ExistingCanon)); // When we merge a template, merge its pattern. if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D)) mergeTemplatePattern( - DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon), - TemplatePatternID, Redecl.isKeyDecl()); + DTemplate, assert_cast<RedeclarableTemplateDecl *>(ExistingCanon), + Redecl.isKeyDecl()); // If this declaration is a key declaration, make a note of that. if (Redecl.isKeyDecl()) @@ -2859,6 +2951,8 @@ public: return Reader.readInt(); } + bool readBool() { return Reader.readBool(); } + SourceRange readSourceRange() { return Reader.readSourceRange(); } @@ -2964,16 +3058,11 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { return false; } - if (isa<FileScopeAsmDecl>(D) || - isa<ObjCProtocolDecl>(D) || - isa<ObjCImplDecl>(D) || - isa<ImportDecl>(D) || - isa<PragmaCommentDecl>(D) || - isa<PragmaDetectMismatchDecl>(D)) + if (isa<FileScopeAsmDecl, TopLevelStmtDecl, ObjCProtocolDecl, ObjCImplDecl, + ImportDecl, PragmaCommentDecl, PragmaDetectMismatchDecl>(D)) return true; - if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D) || - isa<OMPDeclareMapperDecl>(D) || isa<OMPAllocateDecl>(D) || - isa<OMPRequiresDecl>(D)) + if (isa<OMPThreadPrivateDecl, OMPDeclareReductionDecl, OMPDeclareMapperDecl, + OMPAllocateDecl, OMPRequiresDecl>(D)) return !D->getDeclContext()->isFunctionOrMethod(); if (const auto *Var = dyn_cast<VarDecl>(D)) return Var->isFileVarDecl() && @@ -3776,6 +3865,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_FILE_SCOPE_ASM: D = FileScopeAsmDecl::CreateDeserialized(Context, ID); break; + case DECL_TOP_LEVEL_STMT_DECL: + D = TopLevelStmtDecl::CreateDeserialized(Context, ID); + break; case DECL_BLOCK: D = BlockDecl::CreateDeserialized(Context, ID); break; @@ -3853,6 +3945,13 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_OBJC_TYPE_PARAM: D = ObjCTypeParamDecl::CreateDeserialized(Context, ID); break; + case DECL_HLSL_BUFFER: + D = HLSLBufferDecl::CreateDeserialized(Context, ID); + break; + case DECL_IMPLICIT_CONCEPT_SPECIALIZATION: + D = ImplicitConceptSpecializationDecl::CreateDeserialized(Context, ID, + Record.readInt()); + break; } assert(D && "Unknown declaration reading AST file"); @@ -3906,8 +4005,7 @@ void ASTReader::PassInterestingDeclsToConsumer() { // Guard variable to avoid recursively redoing the process of passing // decls to consumer. - SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, - true); + SaveAndRestore GuardPassingDeclsToConsumer(PassingDeclsToConsumer, true); // Ensure that we've loaded all potentially-interesting declarations // that need to be eagerly loaded. @@ -3985,7 +4083,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { } // Add the lazy specializations to the template. assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) || - isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) && + isa<FunctionTemplateDecl, VarTemplateDecl>(D)) && "Must not have pending specializations"); if (auto *CTD = dyn_cast<ClassTemplateDecl>(D)) ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs); diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp index e0ae019bf803..46d653c7f940 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp @@ -61,6 +61,7 @@ #include <algorithm> #include <cassert> #include <cstdint> +#include <optional> #include <string> using namespace clang; @@ -772,6 +773,7 @@ static ConstraintSatisfaction readConstraintSatisfaction(ASTRecordReader &Record) { ConstraintSatisfaction Satisfaction; Satisfaction.IsSatisfied = Record.readInt(); + Satisfaction.ContainsErrors = Record.readInt(); if (!Satisfaction.IsSatisfied) { unsigned NumDetailRecords = Record.readInt(); for (unsigned i = 0; i != NumDetailRecords; ++i) { @@ -793,17 +795,13 @@ readConstraintSatisfaction(ASTRecordReader &Record) { void ASTStmtReader::VisitConceptSpecializationExpr( ConceptSpecializationExpr *E) { VisitExpr(E); - unsigned NumTemplateArgs = Record.readInt(); E->NestedNameSpec = Record.readNestedNameSpecifierLoc(); E->TemplateKWLoc = Record.readSourceLocation(); E->ConceptName = Record.readDeclarationNameInfo(); E->NamedConcept = readDeclAs<ConceptDecl>(); E->FoundDecl = Record.readDeclAs<NamedDecl>(); + E->SpecDecl = Record.readDeclAs<ImplicitConceptSpecializationDecl>(); E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); - llvm::SmallVector<TemplateArgument, 4> Args; - for (unsigned I = 0; I < NumTemplateArgs; ++I) - Args.push_back(Record.readTemplateArgument()); - E->setTemplateArguments(Args); E->Satisfaction = E->isValueDependent() ? nullptr : ASTConstraintSatisfaction::Create(Record.getContext(), readConstraintSatisfaction(Record)); @@ -860,7 +858,7 @@ void ASTStmtReader::VisitRequiresExpr(RequiresExpr *E) { } else E = Record.readExpr(); - llvm::Optional<concepts::ExprRequirement::ReturnTypeRequirement> Req; + std::optional<concepts::ExprRequirement::ReturnTypeRequirement> Req; ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr; SourceLocation NoexceptLoc; if (RK == concepts::Requirement::RK_Simple) { @@ -898,9 +896,17 @@ void ASTStmtReader::VisitRequiresExpr(RequiresExpr *E) { std::move(*Req)); } break; case concepts::Requirement::RK_Nested: { - if (/* IsSubstitutionDiagnostic */Record.readInt()) { + 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( - readSubstitutionDiagnostic(Record)); + Record.getContext(), + StringRef(InvalidConstraintBuf, InvalidConstraint.size()), + readConstraintSatisfaction(Record)); break; } Expr *E = Record.readExpr(); @@ -1827,13 +1833,19 @@ void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { E->Param = readDeclAs<ParmVarDecl>(); E->UsedContext = readDeclAs<DeclContext>(); E->CXXDefaultArgExprBits.Loc = readSourceLocation(); + E->CXXDefaultArgExprBits.HasRewrittenInit = Record.readInt(); + if (E->CXXDefaultArgExprBits.HasRewrittenInit) + *E->getTrailingObjects<Expr *>() = Record.readSubExpr(); } void ASTStmtReader::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { VisitExpr(E); + E->CXXDefaultInitExprBits.HasRewrittenInit = Record.readInt(); E->Field = readDeclAs<FieldDecl>(); E->UsedContext = readDeclAs<DeclContext>(); E->CXXDefaultInitExprBits.Loc = readSourceLocation(); + if (E->CXXDefaultInitExprBits.HasRewrittenInit) + *E->getTrailingObjects<Expr *>() = Record.readSubExpr(); } void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { @@ -2117,8 +2129,10 @@ void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) { void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); - E->ParamAndRef.setPointer(readDeclAs<NonTypeTemplateParmDecl>()); - E->ParamAndRef.setInt(Record.readInt()); + E->AssociatedDeclAndRef.setPointer(readDeclAs<Decl>()); + E->AssociatedDeclAndRef.setInt(Record.readInt()); + E->Index = Record.readInt(); + E->PackIndex = Record.readInt(); E->SubstNonTypeTemplateParmExprBits.NameLoc = readSourceLocation(); E->Replacement = Record.readSubExpr(); } @@ -2126,7 +2140,8 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E) { VisitExpr(E); - E->Param = readDeclAs<NonTypeTemplateParmDecl>(); + E->AssociatedDecl = readDeclAs<Decl>(); + E->Index = Record.readInt(); TemplateArgument ArgPack = Record.readTemplateArgument(); if (ArgPack.getKind() != TemplateArgument::Pack) return; @@ -2167,6 +2182,31 @@ void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) { E->Opcode = (BinaryOperatorKind)Record.readInt(); } +void ASTStmtReader::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) { + VisitExpr(E); + unsigned ExpectedNumExprs = Record.readInt(); + assert(E->NumExprs == ExpectedNumExprs && + "expected number of expressions does not equal the actual number of " + "serialized expressions."); + E->NumUserSpecifiedExprs = Record.readInt(); + E->InitLoc = readSourceLocation(); + E->LParenLoc = readSourceLocation(); + E->RParenLoc = readSourceLocation(); + for (unsigned I = 0; I < ExpectedNumExprs; I++) + E->getTrailingObjects<Expr *>()[I] = Record.readSubExpr(); + + bool HasArrayFillerOrUnionDecl = Record.readBool(); + if (HasArrayFillerOrUnionDecl) { + bool HasArrayFiller = Record.readBool(); + if (HasArrayFiller) { + E->setArrayFiller(Record.readSubExpr()); + } else { + E->setInitializedFieldInUnion(readDeclAs<FieldDecl>()); + } + } + E->updateDependence(); +} + void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); E->SourceExpr = Record.readSubExpr(); @@ -2412,6 +2452,13 @@ void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPErrorDirective(OMPErrorDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + Record.skipInts(1); + VisitOMPExecutableDirective(D); +} + void ASTStmtReader::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); @@ -3359,6 +3406,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_ERROR_DIRECTIVE: + S = OMPErrorDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case STMT_OMP_TASKGROUP_DIRECTIVE: S = OMPTaskgroupDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); @@ -3817,11 +3869,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_CXX_DEFAULT_ARG: - S = new (Context) CXXDefaultArgExpr(Empty); + S = CXXDefaultArgExpr::CreateEmpty( + Context, /*HasRewrittenInit=*/Record[ASTStmtReader::NumExprFields]); break; case EXPR_CXX_DEFAULT_INIT: - S = new (Context) CXXDefaultInitExpr(Empty); + S = CXXDefaultInitExpr::CreateEmpty( + Context, /*HasRewrittenInit=*/Record[ASTStmtReader::NumExprFields]); break; case EXPR_CXX_BIND_TEMPORARY: @@ -3946,6 +4000,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) CXXFoldExpr(Empty); break; + case EXPR_CXX_PAREN_LIST_INIT: + S = CXXParenListInitExpr::CreateEmpty( + Context, /*numExprs=*/Record[ASTStmtReader::NumExprFields], Empty); + break; + case EXPR_OPAQUE_VALUE: S = new (Context) OpaqueValueExpr(Empty); break; @@ -3999,8 +4058,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_CONCEPT_SPECIALIZATION: { - unsigned numTemplateArgs = Record[ASTStmtReader::NumExprFields]; - S = ConceptSpecializationExpr::Create(Context, Empty, numTemplateArgs); + S = new (Context) ConceptSpecializationExpr(Empty); break; } diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp index 0739dcc1ce60..bdf11001473e 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp @@ -77,7 +77,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" @@ -100,6 +99,7 @@ #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" #include "llvm/Support/SHA1.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -108,9 +108,9 @@ #include <cstdlib> #include <cstring> #include <ctime> -#include <deque> #include <limits> #include <memory> +#include <optional> #include <queue> #include <tuple> #include <utility> @@ -161,12 +161,14 @@ static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) { namespace { -std::set<const FileEntry *> GetAllModuleMaps(const HeaderSearch &HS, - Module *RootModule) { +std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP, + Module *RootModule) { std::set<const FileEntry *> ModuleMaps{}; std::set<const Module *> ProcessedModules; SmallVector<const Module *> ModulesToProcess{RootModule}; + const HeaderSearch &HS = PP.getHeaderSearchInfo(); + SmallVector<const FileEntry *, 16> FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); @@ -190,30 +192,36 @@ std::set<const FileEntry *> GetAllModuleMaps(const HeaderSearch &HS, } } - while (!ModulesToProcess.empty()) { - auto *CurrentModule = ModulesToProcess.pop_back_val(); - ProcessedModules.insert(CurrentModule); + const ModuleMap &MM = HS.getModuleMap(); + SourceManager &SourceMgr = PP.getSourceManager(); - auto *ModuleMapFile = - HS.getModuleMap().getModuleMapFileForUniquing(CurrentModule); - if (!ModuleMapFile) { - continue; + auto ForIncludeChain = [&](FileEntryRef F, + llvm::function_ref<void(FileEntryRef)> CB) { + CB(F); + FileID FID = SourceMgr.translateFile(F); + SourceLocation Loc = SourceMgr.getIncludeLoc(FID); + while (Loc.isValid()) { + FID = SourceMgr.getFileID(Loc); + CB(*SourceMgr.getFileEntryRefForID(FID)); + Loc = SourceMgr.getIncludeLoc(FID); } + }; - ModuleMaps.insert(ModuleMapFile); - - for (auto *ImportedModule : (CurrentModule)->Imports) { - if (!ImportedModule || - ProcessedModules.find(ImportedModule) != ProcessedModules.end()) { - continue; - } - ModulesToProcess.push_back(ImportedModule); - } + auto ProcessModuleOnce = [&](const Module *M) { + for (const Module *Mod = M; Mod; Mod = Mod->Parent) + if (ProcessedModules.insert(Mod).second) + if (auto ModuleMapFile = MM.getModuleMapFileForUniquing(Mod)) + ForIncludeChain(*ModuleMapFile, [&](FileEntryRef F) { + ModuleMaps.insert(F); + }); + }; + for (const Module *CurrentModule : ModulesToProcess) { + ProcessModuleOnce(CurrentModule); + for (const Module *ImportedModule : CurrentModule->Imports) + ProcessModuleOnce(ImportedModule); for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses) - if (UndeclaredModule && - ProcessedModules.find(UndeclaredModule) == ProcessedModules.end()) - ModulesToProcess.push_back(UndeclaredModule); + ProcessModuleOnce(UndeclaredModule); } return ModuleMaps; @@ -437,7 +445,7 @@ void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { addSourceLocation(TL.getTypeofLoc()); addSourceLocation(TL.getLParenLoc()); addSourceLocation(TL.getRParenLoc()); - Record.AddTypeSourceInfo(TL.getUnderlyingTInfo()); + Record.AddTypeSourceInfo(TL.getUnmodifiedTInfo()); } void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { @@ -463,8 +471,9 @@ void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) { addSourceLocation(TL.getLAngleLoc()); addSourceLocation(TL.getRAngleLoc()); for (unsigned I = 0; I < TL.getNumArgs(); ++I) - Record.AddTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(), - TL.getArgLocInfo(I)); + Record.AddTemplateArgumentLocInfo( + TL.getTypePtr()->getTypeConstraintArguments()[I].getKind(), + TL.getArgLocInfo(I)); } Record.push_back(TL.isDecltypeAuto()); if (TL.isDecltypeAuto()) @@ -560,6 +569,7 @@ void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { addSourceLocation(TL.getNameLoc()); + addSourceLocation(TL.getNameEndLoc()); } void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { @@ -734,6 +744,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_USER_DEFINED_LITERAL); RECORD(EXPR_CXX_STD_INITIALIZER_LIST); RECORD(EXPR_CXX_BOOL_LITERAL); + RECORD(EXPR_CXX_PAREN_LIST_INIT); RECORD(EXPR_CXX_NULL_PTR_LITERAL); RECORD(EXPR_CXX_TYPEID_EXPR); RECORD(EXPR_CXX_TYPEID_TYPE); @@ -786,7 +797,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MODULE_MAP_FILE); RECORD(IMPORTS); RECORD(ORIGINAL_FILE); - RECORD(ORIGINAL_PCH_DIR); RECORD(ORIGINAL_FILE_ID); RECORD(INPUT_FILE_OFFSETS); @@ -884,6 +894,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(SUBMODULE_TOPHEADER); RECORD(SUBMODULE_UMBRELLA_DIR); RECORD(SUBMODULE_IMPORTS); + RECORD(SUBMODULE_AFFECTING_MODULES); RECORD(SUBMODULE_EXPORTS); RECORD(SUBMODULE_REQUIRES); RECORD(SUBMODULE_EXCLUDED_HEADER); @@ -1017,6 +1028,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_PRAGMA_DETECT_MISMATCH); RECORD(DECL_OMP_DECLARE_REDUCTION); RECORD(DECL_OMP_ALLOCATE); + RECORD(DECL_HLSL_BUFFER); // Statements and Exprs can occur in the Decls and Types block. AddStmtsExprs(Stream, Record); @@ -1034,6 +1046,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(SIGNATURE); RECORD(AST_BLOCK_HASH); RECORD(DIAGNOSTIC_OPTIONS); + RECORD(HEADER_SEARCH_PATHS); RECORD(DIAG_PRAGMA_MAPPINGS); #undef RECORD @@ -1164,6 +1177,35 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record); Record.clear(); + // Header search paths. + Record.clear(); + const HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); + + // Include entries. + Record.push_back(HSOpts.UserEntries.size()); + for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) { + const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I]; + AddString(Entry.Path, Record); + Record.push_back(static_cast<unsigned>(Entry.Group)); + Record.push_back(Entry.IsFramework); + Record.push_back(Entry.IgnoreSysRoot); + } + + // System header prefixes. + Record.push_back(HSOpts.SystemHeaderPrefixes.size()); + for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) { + AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record); + Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader); + } + + // VFS overlay files. + Record.push_back(HSOpts.VFSOverlayFiles.size()); + for (StringRef VFSOverlayFile : HSOpts.VFSOverlayFiles) + AddString(VFSOverlayFile, Record); + + Stream.EmitRecord(HEADER_SEARCH_PATHS, Record); + // Write out the diagnostic/pragma mappings. WritePragmaDiagnosticMappings(Diags, /* isModule = */ WritingModule); @@ -1187,8 +1229,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, /// Write the control block. void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, - StringRef isysroot, - const std::string &OutputFile) { + StringRef isysroot) { using namespace llvm; Stream.EnterSubblock(CONTROL_BLOCK_ID, 5); @@ -1283,7 +1324,12 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, if (auto *AdditionalModMaps = Map.getAdditionalModuleMapFiles(WritingModule)) { Record.push_back(AdditionalModMaps->size()); - for (const FileEntry *F : *AdditionalModMaps) + SmallVector<const FileEntry *, 1> ModMaps(AdditionalModMaps->begin(), + AdditionalModMaps->end()); + llvm::sort(ModMaps, [](const FileEntry *A, const FileEntry *B) { + return A->getName() < B->getName(); + }); + for (const FileEntry *F : ModMaps) AddPath(F->getName(), Record); } else { Record.push_back(0); @@ -1385,27 +1431,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, // Header search options. Record.clear(); - const HeaderSearchOptions &HSOpts - = PP.getHeaderSearchInfo().getHeaderSearchOpts(); - AddString(HSOpts.Sysroot, Record); - - // Include entries. - Record.push_back(HSOpts.UserEntries.size()); - for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) { - const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I]; - AddString(Entry.Path, Record); - Record.push_back(static_cast<unsigned>(Entry.Group)); - Record.push_back(Entry.IsFramework); - Record.push_back(Entry.IgnoreSysRoot); - } - - // System header prefixes. - Record.push_back(HSOpts.SystemHeaderPrefixes.size()); - for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) { - AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record); - Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader); - } + const HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); + AddString(HSOpts.Sysroot, Record); AddString(HSOpts.ResourceDir, Record); AddString(HSOpts.ModuleCachePath, Record); AddString(HSOpts.ModuleUserBuildPath, Record); @@ -1463,38 +1492,16 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.clear(); Record.push_back(ORIGINAL_FILE); - Record.push_back(SM.getMainFileID().getOpaqueValue()); + AddFileID(SM.getMainFileID(), Record); EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName()); } Record.clear(); - Record.push_back(SM.getMainFileID().getOpaqueValue()); + AddFileID(SM.getMainFileID(), Record); Stream.EmitRecord(ORIGINAL_FILE_ID, Record); - // Original PCH directory - if (!OutputFile.empty() && OutputFile != "-") { - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(ORIGINAL_PCH_DIR)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); - - SmallString<128> OutputPath(OutputFile); - PreparePathForOutput(OutputPath); - StringRef origDir = llvm::sys::path::parent_path(OutputPath); - - RecordData::value_type Record[] = {ORIGINAL_PCH_DIR}; - Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); - } - - std::set<const FileEntry *> AffectingModuleMaps; - if (WritingModule) { - AffectingModuleMaps = - GetAllModuleMaps(PP.getHeaderSearchInfo(), WritingModule); - } - WriteInputFiles(Context.SourceMgr, - PP.getHeaderSearchInfo().getHeaderSearchOpts(), - AffectingModuleMaps); + PP.getHeaderSearchInfo().getHeaderSearchOpts()); Stream.ExitBlock(); } @@ -1502,19 +1509,20 @@ namespace { /// An input file. struct InputFileEntry { - const FileEntry *File; + FileEntryRef File; bool IsSystemFile; bool IsTransient; bool BufferOverridden; bool IsTopLevelModuleMap; uint32_t ContentHash[2]; + + InputFileEntry(FileEntryRef File) : File(File) {} }; } // namespace -void ASTWriter::WriteInputFiles( - SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, - std::set<const FileEntry *> &AffectingModuleMaps) { +void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, + HeaderSearchOptions &HSOpts) { using namespace llvm; Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); @@ -1538,9 +1546,9 @@ void ASTWriter::WriteInputFiles( IFHAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); unsigned IFHAbbrevCode = Stream.EmitAbbrev(std::move(IFHAbbrev)); - // Get all ContentCache objects for files, sorted by whether the file is a - // system one or not. System files go at the back, users files at the front. - std::deque<InputFileEntry> SortedFiles; + // Get all ContentCache objects for files. + std::vector<InputFileEntry> UserFiles; + std::vector<InputFileEntry> SystemFiles; for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { // Get this source location entry. const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); @@ -1554,18 +1562,11 @@ void ASTWriter::WriteInputFiles( if (!Cache->OrigEntry) continue; - if (isModuleMap(File.getFileCharacteristic()) && - !isSystem(File.getFileCharacteristic()) && - !AffectingModuleMaps.empty() && - AffectingModuleMaps.find(Cache->OrigEntry) == - AffectingModuleMaps.end()) { - SkippedModuleMaps.insert(Cache->OrigEntry); - // Do not emit modulemaps that do not affect current module. + // Do not emit input files that do not affect current module. + if (!IsSLocAffecting[I]) continue; - } - InputFileEntry Entry; - Entry.File = Cache->OrigEntry; + InputFileEntry Entry(*Cache->OrigEntry); Entry.IsSystemFile = isSystem(File.getFileCharacteristic()); Entry.IsTransient = Cache->IsTransient; Entry.BufferOverridden = Cache->BufferOverridden; @@ -1580,9 +1581,8 @@ void ASTWriter::WriteInputFiles( if (MemBuff) ContentHash = hash_value(MemBuff->getBuffer()); else - // FIXME: The path should be taken from the FileEntryRef. PP->Diag(SourceLocation(), diag::err_module_unable_to_hash_content) - << Entry.File->getName(); + << Entry.File.getName(); } auto CH = llvm::APInt(64, ContentHash); Entry.ContentHash[0] = @@ -1591,11 +1591,15 @@ void ASTWriter::WriteInputFiles( static_cast<uint32_t>(CH.getHiBits(32).getZExtValue()); if (Entry.IsSystemFile) - SortedFiles.push_back(Entry); + SystemFiles.push_back(Entry); else - SortedFiles.push_front(Entry); + UserFiles.push_back(Entry); } + // User files go at the front, system files at the back. + auto SortedFiles = llvm::concat<InputFileEntry>(std::move(UserFiles), + std::move(SystemFiles)); + unsigned UserFilesNum = 0; // Write out all of the input files. std::vector<uint64_t> InputFileOffsets; @@ -1618,14 +1622,13 @@ void ASTWriter::WriteInputFiles( RecordData::value_type Record[] = { INPUT_FILE, InputFileOffsets.size(), - (uint64_t)Entry.File->getSize(), + (uint64_t)Entry.File.getSize(), (uint64_t)getTimestampForOutput(Entry.File), Entry.BufferOverridden, Entry.IsTransient, Entry.IsTopLevelModuleMap}; - // FIXME: The path should be taken from the FileEntryRef. - EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName()); + EmitRecordWithPath(IFAbbrevCode, Record, Entry.File.getNameAsRequested()); } // Emit content hash for this file. @@ -1830,14 +1833,12 @@ namespace { auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { - uint32_t Value = (ModID << 2) | (unsigned)Role; - assert((Value >> 2) == ModID && "overflow in header module info"); + uint32_t Value = (ModID << 3) | (unsigned)Role; + assert((Value >> 3) == ModID && "overflow in header module info"); LE.write<uint32_t>(Value); } }; - // FIXME: If the header is excluded, we should write out some - // record of that fact. for (auto ModInfo : Data.KnownHeaders) EmitModule(ModInfo.getModule(), ModInfo.getRole()); if (Data.Unresolved.getPointer()) @@ -1879,7 +1880,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { // headers list when emitting resolved headers in the first loop below. // FIXME: It'd be preferable to avoid doing this if we were given // sufficient stat information in the module map. - HS.getModuleMap().resolveHeaderDirectives(M, /*File=*/llvm::None); + HS.getModuleMap().resolveHeaderDirectives(M, /*File=*/std::nullopt); // If the file didn't exist, we can still create a module if we were given // enough information in the module map. @@ -2001,6 +2002,14 @@ static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob, // Compress the buffer if possible. We expect that almost all PCM // consumers will not want its contents. SmallVector<uint8_t, 0> CompressedBuffer; + if (llvm::compression::zstd::isAvailable()) { + llvm::compression::zstd::compress( + llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer, 9); + RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1}; + Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record, + llvm::toStringRef(CompressedBuffer)); + return; + } if (llvm::compression::zlib::isAvailable()) { llvm::compression::zlib::compress( llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer); @@ -2054,7 +2063,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Record the offset of this source-location entry. uint64_t Offset = Stream.GetCurrentBitNo() - SLocEntryOffsetsBase; assert((Offset >> 32) == 0 && "SLocEntry offset too large"); - SLocEntryOffsets.push_back(Offset); // Figure out which record code to use. unsigned Code; @@ -2069,17 +2077,15 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.clear(); Record.push_back(Code); - // Starting offset of this entry within this module, so skip the dummy. - Record.push_back(SLoc->getOffset() - 2); if (SLoc->isFile()) { const SrcMgr::FileInfo &File = SLoc->getFile(); const SrcMgr::ContentCache *Content = &File.getContentCache(); - if (Content->OrigEntry && !SkippedModuleMaps.empty() && - SkippedModuleMaps.find(Content->OrigEntry) != - SkippedModuleMaps.end()) { - // Do not emit files that were not listed as inputs. + // Do not emit files that were not listed as inputs. + if (!IsSLocAffecting[I]) continue; - } + 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); Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding Record.push_back(File.hasLineDirectives()); @@ -2093,7 +2099,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, assert(InputFileIDs[Content->OrigEntry] != 0 && "Missed file entry"); Record.push_back(InputFileIDs[Content->OrigEntry]); - Record.push_back(File.NumCreatedFIDs); + Record.push_back(getAdjustedNumCreatedFIDs(FID)); FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID); if (FDI != FileDeclIDs.end()) { @@ -2115,7 +2121,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // We add one to the size so that we capture the trailing NULL // that is required by llvm::MemoryBuffer::getMemBuffer (on // the reader side). - llvm::Optional<llvm::MemoryBufferRef> Buffer = + std::optional<llvm::MemoryBufferRef> Buffer = Content->getBufferOrNone(PP.getDiagnostics(), PP.getFileManager()); StringRef Name = Buffer ? Buffer->getBufferIdentifier() : ""; Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, @@ -2129,7 +2135,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, if (EmitBlob) { // Include the implicit terminating null character in the on-disk buffer // if we're writing it uncompressed. - llvm::Optional<llvm::MemoryBufferRef> Buffer = + std::optional<llvm::MemoryBufferRef> Buffer = Content->getBufferOrNone(PP.getDiagnostics(), PP.getFileManager()); if (!Buffer) Buffer = llvm::MemoryBufferRef("<<<INVALID BUFFER>>>", ""); @@ -2140,6 +2146,9 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, } else { // The source location entry is a macro expansion. const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion(); + SLocEntryOffsets.push_back(Offset); + // Starting offset of this entry within this module, so skip the dummy. + Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2); LocSeq::State Seq; AddSourceLocation(Expansion.getSpellingLoc(), Record, Seq); AddSourceLocation(Expansion.getExpansionLocStart(), Record, Seq); @@ -2153,7 +2162,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, SourceLocation::UIntTy NextOffset = SourceMgr.getNextLocalOffset(); if (I + 1 != N) NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset(); - Record.push_back(NextOffset - SLoc->getOffset() - 1); + Record.push_back(getAdjustedOffset(NextOffset - SLoc->getOffset()) - 1); Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record); } } @@ -2177,7 +2186,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, { RecordData::value_type Record[] = { SOURCE_LOCATION_OFFSETS, SLocEntryOffsets.size(), - SourceMgr.getNextLocalOffset() - 1 /* skip dummy */, + getAdjustedOffset(SourceMgr.getNextLocalOffset()) - 1 /* skip dummy */, SLocEntryOffsetsBase - SourceManagerBlockOffset}; Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, bytes(SLocEntryOffsets)); @@ -2213,8 +2222,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, if (L.first.ID < 0) continue; - // Emit the file ID - Record.push_back(L.first.ID); + AddFileID(L.first, Record); // Emit the line entries Record.push_back(L.second.size()); @@ -2341,11 +2349,14 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { // Construct the list of identifiers with macro directives that need to be // serialized. SmallVector<const IdentifierInfo *, 128> MacroIdentifiers; - for (auto &Id : PP.getIdentifierTable()) - if (Id.second->hadMacroDefinition() && - (!Id.second->isFromAST() || - Id.second->hasChangedSinceDeserialization())) - MacroIdentifiers.push_back(Id.second); + // It is meaningless to emit macros for named modules. It only wastes times + // and spaces. + if (!isWritingStdCXXNamedModules()) + for (auto &Id : PP.getIdentifierTable()) + if (Id.second->hadMacroDefinition() && + (!Id.second->isFromAST() || + Id.second->hasChangedSinceDeserialization())) + MacroIdentifiers.push_back(Id.second); // Sort the set of macro definitions that need to be serialized by the // name of the macro, to provide a stable ordering. llvm::sort(MacroIdentifiers, llvm::deref<std::less<>>()); @@ -2577,7 +2588,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec, uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase; assert((Offset >> 32) == 0 && "Preprocessed entity offset too large"); PreprocessedEntityOffsets.push_back( - PPEntityOffset((*E)->getSourceRange(), Offset)); + PPEntityOffset(getAdjustedRange((*E)->getSourceRange()), Offset)); if (auto *MD = dyn_cast<MacroDefinitionRecord>(*E)) { // Record this macro definition's ID. @@ -2677,12 +2688,12 @@ unsigned ASTWriter::getLocalOrImportedSubmoduleID(const Module *Mod) { } unsigned ASTWriter::getSubmoduleID(Module *Mod) { + unsigned ID = getLocalOrImportedSubmoduleID(Mod); // FIXME: This can easily happen, if we have a reference to a submodule that // did not result in us loading a module file for that submodule. For // instance, a cross-top-level-module 'conflict' declaration will hit this. - unsigned ID = getLocalOrImportedSubmoduleID(Mod); - assert((ID || !Mod) && - "asked for module ID for non-local, non-imported module"); + // assert((ID || !Mod) && + // "asked for module ID for non-local, non-imported module"); return ID; } @@ -2882,6 +2893,14 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecord(SUBMODULE_IMPORTS, Record); } + // Emit the modules affecting compilation that were not imported. + if (!Mod->AffectingClangModules.empty()) { + RecordData Record; + for (auto *I : Mod->AffectingClangModules) + Record.push_back(getSubmoduleID(I)); + Stream.EmitRecord(SUBMODULE_AFFECTING_MODULES, Record); + } + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; @@ -3016,7 +3035,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, Record.push_back(FileIDAndFile.second.StateTransitions.size()); for (auto &StatePoint : FileIDAndFile.second.StateTransitions) { - Record.push_back(StatePoint.Offset); + Record.push_back(getAdjustedOffset(StatePoint.Offset)); AddDiagState(StatePoint.State, false); } } @@ -4350,7 +4369,8 @@ void ASTRecordWriter::AddAttr(const Attr *A) { // FIXME: Clang can't handle the serialization/deserialization of // preferred_name properly now. See // https://github.com/llvm/llvm-project/issues/56490 for example. - if (!A || (isa<PreferredNameAttr>(A) && Writer->isWritingNamedModules())) + if (!A || (isa<PreferredNameAttr>(A) && + Writer->isWritingStdCXXNamedModules())) return Record.push_back(0); Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs @@ -4375,15 +4395,37 @@ void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) { void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) { AddSourceLocation(Tok.getLocation(), Record); - Record.push_back(Tok.getLength()); - - // FIXME: When reading literal tokens, reconstruct the literal pointer - // if it is needed. - AddIdentifierRef(Tok.getIdentifierInfo(), Record); // FIXME: Should translate token kind to a stable encoding. Record.push_back(Tok.getKind()); // FIXME: Should translate token flags to a stable encoding. Record.push_back(Tok.getFlags()); + + if (Tok.isAnnotation()) { + AddSourceLocation(Tok.getAnnotationEndLoc(), Record); + switch (Tok.getKind()) { + case tok::annot_pragma_loop_hint: { + auto *Info = static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue()); + AddToken(Info->PragmaName, Record); + AddToken(Info->Option, Record); + Record.push_back(Info->Toks.size()); + for (const auto &T : Info->Toks) + AddToken(T, Record); + break; + } + // Some annotation tokens do not use the PtrData field. + case tok::annot_pragma_openmp: + case tok::annot_pragma_openmp_end: + case tok::annot_pragma_unused: + break; + default: + llvm_unreachable("missing serialization code for annotation token"); + } + } else { + Record.push_back(Tok.getLength()); + // FIXME: When reading literal tokens, reconstruct the literal pointer if it + // is needed. + AddIdentifierRef(Tok.getIdentifierInfo(), Record); + } } void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { @@ -4425,11 +4467,11 @@ void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record, void ASTWriter::AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record) { Record.push_back(Version.getMajor()); - if (Optional<unsigned> Minor = Version.getMinor()) + if (std::optional<unsigned> Minor = Version.getMinor()) Record.push_back(*Minor + 1); else Record.push_back(0); - if (Optional<unsigned> Subminor = Version.getSubminor()) + if (std::optional<unsigned> Subminor = Version.getSubminor()) Record.push_back(*Subminor + 1); else Record.push_back(0); @@ -4481,11 +4523,11 @@ time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const { return IncludeTimestamps ? E->getModificationTime() : 0; } -ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, - const std::string &OutputFile, +ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, StringRef OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors, bool ShouldCacheASTInMemory) { + llvm::TimeTraceScope scope("WriteAST", OutputFile); WritingAST = true; ASTHasCompilerErrors = hasErrors; @@ -4501,8 +4543,7 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, Context = &SemaRef.Context; PP = &SemaRef.PP; this->WritingModule = WritingModule; - ASTFileSignature Signature = - WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule); + ASTFileSignature Signature = WriteASTCore(SemaRef, isysroot, WritingModule); Context = nullptr; PP = nullptr; this->WritingModule = nullptr; @@ -4527,8 +4568,69 @@ static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, } } +void ASTWriter::collectNonAffectingInputFiles() { + SourceManager &SrcMgr = PP->getSourceManager(); + unsigned N = SrcMgr.local_sloc_entry_size(); + + IsSLocAffecting.resize(N, true); + + if (!WritingModule) + return; + + auto AffectingModuleMaps = GetAffectingModuleMaps(*PP, WritingModule); + + unsigned FileIDAdjustment = 0; + unsigned OffsetAdjustment = 0; + + NonAffectingFileIDAdjustments.reserve(N); + NonAffectingOffsetAdjustments.reserve(N); + + NonAffectingFileIDAdjustments.push_back(FileIDAdjustment); + NonAffectingOffsetAdjustments.push_back(OffsetAdjustment); + + for (unsigned I = 1; I != N; ++I) { + const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I); + FileID FID = FileID::get(I); + assert(&SrcMgr.getSLocEntry(FID) == SLoc); + + if (!SLoc->isFile()) + continue; + const SrcMgr::FileInfo &File = SLoc->getFile(); + const SrcMgr::ContentCache *Cache = &File.getContentCache(); + if (!Cache->OrigEntry) + continue; + + if (!isModuleMap(File.getFileCharacteristic()) || + AffectingModuleMaps.empty() || + AffectingModuleMaps.find(Cache->OrigEntry) != AffectingModuleMaps.end()) + continue; + + IsSLocAffecting[I] = false; + + FileIDAdjustment += 1; + // Even empty files take up one element in the offset table. + OffsetAdjustment += SrcMgr.getFileIDSize(FID) + 1; + + // If the previous file was non-affecting as well, just extend its entry + // with our information. + if (!NonAffectingFileIDs.empty() && + NonAffectingFileIDs.back().ID == FID.ID - 1) { + NonAffectingFileIDs.back() = FID; + NonAffectingRanges.back().setEnd(SrcMgr.getLocForEndOfFile(FID)); + NonAffectingFileIDAdjustments.back() = FileIDAdjustment; + NonAffectingOffsetAdjustments.back() = OffsetAdjustment; + continue; + } + + NonAffectingFileIDs.push_back(FID); + NonAffectingRanges.emplace_back(SrcMgr.getLocForStartOfFile(FID), + SrcMgr.getLocForEndOfFile(FID)); + NonAffectingFileIDAdjustments.push_back(FileIDAdjustment); + NonAffectingOffsetAdjustments.push_back(OffsetAdjustment); + } +} + ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, - const std::string &OutputFile, Module *WritingModule) { using namespace llvm; @@ -4541,6 +4643,8 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, ASTContext &Context = SemaRef.Context; Preprocessor &PP = SemaRef.PP; + collectNonAffectingInputFiles(); + // Set up predefined declaration IDs. auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) { if (D) { @@ -4682,7 +4786,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, } // Write the control block - WriteControlBlock(PP, Context, isysroot, OutputFile); + WriteControlBlock(PP, Context, isysroot); // Write the remaining AST contents. Stream.FlushToWord(); @@ -5205,7 +5309,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { break; case UPD_ADDED_ATTR_TO_RECORD: - Record.AddAttributes(llvm::makeArrayRef(Update.getAttr())); + Record.AddAttributes(llvm::ArrayRef(Update.getAttr())); break; } } @@ -5229,8 +5333,75 @@ void ASTWriter::AddAlignPackInfo(const Sema::AlignPackInfo &Info, Record.push_back(Raw); } +FileID ASTWriter::getAdjustedFileID(FileID FID) const { + if (FID.isInvalid() || PP->getSourceManager().isLoadedFileID(FID) || + NonAffectingFileIDs.empty()) + return FID; + auto It = llvm::lower_bound(NonAffectingFileIDs, FID); + unsigned Idx = std::distance(NonAffectingFileIDs.begin(), It); + unsigned Offset = NonAffectingFileIDAdjustments[Idx]; + return FileID::get(FID.getOpaqueValue() - Offset); +} + +unsigned ASTWriter::getAdjustedNumCreatedFIDs(FileID FID) const { + unsigned NumCreatedFIDs = PP->getSourceManager() + .getLocalSLocEntry(FID.ID) + .getFile() + .NumCreatedFIDs; + + unsigned AdjustedNumCreatedFIDs = 0; + for (unsigned I = FID.ID, N = I + NumCreatedFIDs; I != N; ++I) + if (IsSLocAffecting[I]) + ++AdjustedNumCreatedFIDs; + return AdjustedNumCreatedFIDs; +} + +SourceLocation ASTWriter::getAdjustedLocation(SourceLocation Loc) const { + if (Loc.isInvalid()) + return Loc; + return Loc.getLocWithOffset(-getAdjustment(Loc.getOffset())); +} + +SourceRange ASTWriter::getAdjustedRange(SourceRange Range) const { + return SourceRange(getAdjustedLocation(Range.getBegin()), + getAdjustedLocation(Range.getEnd())); +} + +SourceLocation::UIntTy +ASTWriter::getAdjustedOffset(SourceLocation::UIntTy Offset) const { + return Offset - getAdjustment(Offset); +} + +SourceLocation::UIntTy +ASTWriter::getAdjustment(SourceLocation::UIntTy Offset) const { + if (NonAffectingRanges.empty()) + return 0; + + if (PP->getSourceManager().isLoadedOffset(Offset)) + return 0; + + if (Offset > NonAffectingRanges.back().getEnd().getOffset()) + return NonAffectingOffsetAdjustments.back(); + + if (Offset < NonAffectingRanges.front().getBegin().getOffset()) + return 0; + + auto Contains = [](const SourceRange &Range, SourceLocation::UIntTy Offset) { + return Range.getEnd().getOffset() < Offset; + }; + + auto It = llvm::lower_bound(NonAffectingRanges, Offset, Contains); + unsigned Idx = std::distance(NonAffectingRanges.begin(), It); + return NonAffectingOffsetAdjustments[Idx]; +} + +void ASTWriter::AddFileID(FileID FID, RecordDataImpl &Record) { + Record.push_back(getAdjustedFileID(FID).getOpaqueValue()); +} + void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record, SourceLocationSequence *Seq) { + Loc = getAdjustedLocation(Loc); Record.push_back(SourceLocationEncoding::encode(Loc, Seq)); } @@ -5472,7 +5643,7 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { // a function/objc method, should not have TU as lexical context. // TemplateTemplateParmDecls that are part of an alias template, should not // have TU as lexical context. - if (isa<ParmVarDecl>(D) || isa<TemplateTemplateParmDecl>(D)) + if (isa<ParmVarDecl, TemplateTemplateParmDecl>(D)) return; SourceManager &SM = Context->getSourceManager(); @@ -5484,6 +5655,7 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { if (FID.isInvalid()) return; assert(SM.getSLocEntry(FID).isFile()); + assert(IsSLocAffecting[FID.ID]); std::unique_ptr<DeclIDInFileInfo> &Info = FileDeclIDs[FID]; if (!Info) @@ -5775,7 +5947,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { AddDeclRef(D->getLambdaContextDecl()); AddTypeSourceInfo(Lambda.MethodTyInfo); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { - const LambdaCapture &Capture = Lambda.Captures[I]; + const LambdaCapture &Capture = Lambda.Captures.front()[I]; AddSourceLocation(Capture.getLocation()); Record->push_back(Capture.isImplicit()); Record->push_back(Capture.getCaptureKind()); @@ -5786,7 +5958,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { break; case LCK_ByCopy: case LCK_ByRef: - VarDecl *Var = + ValueDecl *Var = Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr; AddDeclRef(Var); AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc() @@ -6618,9 +6790,12 @@ void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) { Record.push_back(C->getTotalComponentListNum()); Record.push_back(C->getTotalComponentsNum()); Record.AddSourceLocation(C->getLParenLoc()); + bool HasIteratorModifier = false; for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) { Record.push_back(C->getMapTypeModifier(I)); Record.AddSourceLocation(C->getMapTypeModifierLoc(I)); + if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator) + HasIteratorModifier = true; } Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc()); Record.AddDeclarationNameInfo(C->getMapperIdInfo()); @@ -6631,6 +6806,8 @@ void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) { Record.AddStmt(E); for (auto *E : C->mapperlists()) Record.AddStmt(E); + if (HasIteratorModifier) + Record.AddStmt(C->getIteratorModifier()); for (auto *D : C->all_decls()) Record.AddDeclRef(D); for (auto N : C->all_num_lists()) @@ -6672,13 +6849,17 @@ void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) { void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) { VisitOMPClauseWithPreInit(C); + Record.writeEnum(C->getModifier()); Record.AddStmt(C->getGrainsize()); + Record.AddSourceLocation(C->getModifierLoc()); Record.AddSourceLocation(C->getLParenLoc()); } void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) { VisitOMPClauseWithPreInit(C); + Record.writeEnum(C->getModifier()); Record.AddStmt(C->getNumTasks()); + Record.AddSourceLocation(C->getModifierLoc()); Record.AddSourceLocation(C->getLParenLoc()); } @@ -6866,6 +7047,23 @@ void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause( Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc()); } +void OMPClauseWriter::VisitOMPAtClause(OMPAtClause *C) { + Record.push_back(C->getAtKind()); + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getAtKindKwLoc()); +} + +void OMPClauseWriter::VisitOMPSeverityClause(OMPSeverityClause *C) { + Record.push_back(C->getSeverityKind()); + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getSeverityKindKwLoc()); +} + +void OMPClauseWriter::VisitOMPMessageClause(OMPMessageClause *C) { + Record.AddStmt(C->getMessageString()); + Record.AddSourceLocation(C->getLParenLoc()); +} + void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) { Record.push_back(C->varlist_size()); Record.AddSourceLocation(C->getLParenLoc()); @@ -6891,8 +7089,10 @@ void OMPClauseWriter::VisitOMPExclusiveClause(OMPExclusiveClause *C) { void OMPClauseWriter::VisitOMPOrderClause(OMPOrderClause *C) { Record.writeEnum(C->getKind()); + Record.writeEnum(C->getModifier()); Record.AddSourceLocation(C->getLParenLoc()); Record.AddSourceLocation(C->getKindKwLoc()); + Record.AddSourceLocation(C->getModifierKwLoc()); } void OMPClauseWriter::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) { @@ -6922,6 +7122,12 @@ void OMPClauseWriter::VisitOMPBindClause(OMPBindClause *C) { Record.AddSourceLocation(C->getBindKindLoc()); } +void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) { + VisitOMPClauseWithPreInit(C); + Record.AddStmt(C->getSize()); + Record.AddSourceLocation(C->getLParenLoc()); +} + void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) { writeUInt32(TI->Sets.size()); for (const auto &Set : TI->Sets) { diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp index 35b8db27bd0e..a58e0d796b31 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp @@ -23,6 +23,7 @@ #include "clang/Serialization/ASTRecordWriter.h" #include "llvm/Bitstream/BitstreamWriter.h" #include "llvm/Support/ErrorHandling.h" +#include <optional> using namespace clang; using namespace serialization; @@ -107,6 +108,8 @@ namespace clang { void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitTemplateDecl(TemplateDecl *D); void VisitConceptDecl(ConceptDecl *D); + void VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D); void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); @@ -122,6 +125,7 @@ namespace clang { void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitExportDecl(ExportDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); + void VisitTopLevelStmtDecl(TopLevelStmtDecl *D); void VisitImportDecl(ImportDecl *D); void VisitAccessSpecDecl(AccessSpecDecl *D); void VisitFriendDecl(FriendDecl *D); @@ -131,10 +135,9 @@ namespace clang { void VisitCapturedDecl(CapturedDecl *D); void VisitEmptyDecl(EmptyDecl *D); void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); - void VisitDeclContext(DeclContext *DC); template <typename T> void VisitRedeclarable(Redeclarable<T> *D); - + void VisitHLSLBufferDecl(HLSLBufferDecl *D); // FIXME: Put in the same order is DeclNodes.td? void VisitObjCMethodDecl(ObjCMethodDecl *D); @@ -167,7 +170,7 @@ namespace clang { } Record.push_back(typeParams->size()); - for (auto typeParam : *typeParams) { + for (auto *typeParam : *typeParams) { Record.AddDeclRef(typeParam); } Record.AddSourceLocation(typeParams->getLAngleLoc()); @@ -203,7 +206,7 @@ namespace clang { return Common->PartialSpecializations; } ArrayRef<Decl> getPartialSpecializations(FunctionTemplateDecl::Common *) { - return None; + return std::nullopt; } template<typename DeclTy> @@ -221,7 +224,7 @@ namespace clang { ArrayRef<DeclID> LazySpecializations; if (auto *LS = Common->LazySpecializations) - LazySpecializations = llvm::makeArrayRef(LS + 1, LS[0]); + LazySpecializations = llvm::ArrayRef(LS + 1, LS[0]); // Add a slot to the record for the number of specializations. unsigned I = Record.size(); @@ -488,6 +491,10 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { Record.push_back(D->hasNonTrivialToPrimitiveCopyCUnion()); Record.push_back(D->isParamDestroyedInCallee()); Record.push_back(D->getArgPassingRestrictions()); + // Only compute this for C/Objective-C, in C++ this is computed as part + // of CXXRecordDecl. + if (!isa<CXXRecordDecl>(D)) + Record.push_back(D->getODRHash()); if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && @@ -540,46 +547,6 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { VisitRedeclarable(D); - VisitDeclaratorDecl(D); - Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); - Record.push_back(D->getIdentifierNamespace()); - - // FunctionDecl's body is handled last at ASTWriterDecl::Visit, - // after everything else is written. - Record.push_back(static_cast<int>(D->getStorageClass())); // FIXME: stable encoding - Record.push_back(D->isInlineSpecified()); - Record.push_back(D->isInlined()); - Record.push_back(D->isVirtualAsWritten()); - Record.push_back(D->isPure()); - Record.push_back(D->hasInheritedPrototype()); - Record.push_back(D->hasWrittenPrototype()); - Record.push_back(D->isDeletedBit()); - Record.push_back(D->isTrivial()); - Record.push_back(D->isTrivialForCall()); - Record.push_back(D->isDefaulted()); - Record.push_back(D->isExplicitlyDefaulted()); - Record.push_back(D->hasImplicitReturnZero()); - Record.push_back(static_cast<uint64_t>(D->getConstexprKind())); - Record.push_back(D->usesSEHTry()); - Record.push_back(D->hasSkippedBody()); - Record.push_back(D->isMultiVersion()); - Record.push_back(D->isLateTemplateParsed()); - Record.push_back(D->getLinkageInternal()); - Record.AddSourceLocation(D->getEndLoc()); - - Record.push_back(D->getODRHash()); - - if (D->isDefaulted()) { - if (auto *FDI = D->getDefaultedFunctionInfo()) { - Record.push_back(FDI->getUnqualifiedLookups().size()); - for (DeclAccessPair P : FDI->getUnqualifiedLookups()) { - Record.AddDeclRef(P.getDecl()); - Record.push_back(P.getAccess()); - } - } else { - Record.push_back(0); - } - } Record.push_back(D->getTemplatedKind()); switch (D->getTemplatedKind()) { @@ -660,8 +627,53 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { } } + VisitDeclaratorDecl(D); + Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); + Record.push_back(D->getIdentifierNamespace()); + + // FunctionDecl's body is handled last at ASTWriterDecl::Visit, + // after everything else is written. + Record.push_back( + static_cast<int>(D->getStorageClass())); // FIXME: stable encoding + Record.push_back(D->isInlineSpecified()); + Record.push_back(D->isInlined()); + Record.push_back(D->isVirtualAsWritten()); + Record.push_back(D->isPure()); + Record.push_back(D->hasInheritedPrototype()); + Record.push_back(D->hasWrittenPrototype()); + Record.push_back(D->isDeletedBit()); + Record.push_back(D->isTrivial()); + Record.push_back(D->isTrivialForCall()); + Record.push_back(D->isDefaulted()); + Record.push_back(D->isExplicitlyDefaulted()); + Record.push_back(D->isIneligibleOrNotSelected()); + Record.push_back(D->hasImplicitReturnZero()); + Record.push_back(static_cast<uint64_t>(D->getConstexprKind())); + Record.push_back(D->usesSEHTry()); + Record.push_back(D->hasSkippedBody()); + Record.push_back(D->isMultiVersion()); + Record.push_back(D->isLateTemplateParsed()); + Record.push_back(D->FriendConstraintRefersToEnclosingTemplate()); + Record.push_back(D->getLinkageInternal()); + Record.AddSourceLocation(D->getEndLoc()); + Record.AddSourceLocation(D->getDefaultLoc()); + + Record.push_back(D->getODRHash()); + + if (D->isDefaulted()) { + if (auto *FDI = D->getDefaultedFunctionInfo()) { + Record.push_back(FDI->getUnqualifiedLookups().size()); + for (DeclAccessPair P : FDI->getUnqualifiedLookups()) { + Record.AddDeclRef(P.getDecl()); + Record.push_back(P.getAccess()); + } + } else { + Record.push_back(0); + } + } + Record.push_back(D->param_size()); - for (auto P : D->parameters()) + for (auto *P : D->parameters()) Record.AddDeclRef(P); Code = serialization::DECL_FUNCTION; } @@ -763,6 +775,7 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Record.AddTypeSourceInfo(D->getSuperClassTInfo()); Record.AddSourceLocation(D->getEndOfDefinitionLoc()); Record.push_back(Data.HasDesignatedInitializers); + Record.push_back(D->getODRHash()); // Write out the protocols that are directly referenced by the @interface. Record.push_back(Data.ReferencedProtocols.size()); @@ -825,6 +838,7 @@ void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { Record.AddDeclRef(I); for (const auto &PL : D->protocol_locs()) Record.AddSourceLocation(PL); + Record.push_back(D->getODRHash()); } Code = serialization::DECL_OBJC_PROTOCOL; @@ -900,7 +914,7 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { Record.push_back(D->NumIvarInitializers); if (D->NumIvarInitializers) Record.AddCXXCtorInitializers( - llvm::makeArrayRef(D->init_begin(), D->init_end())); + llvm::ArrayRef(D->init_begin(), D->init_end())); Code = serialization::DECL_OBJC_IMPLEMENTATION; } @@ -1030,8 +1044,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { if (D->getStorageDuration() == SD_Static) { bool ModulesCodegen = false; if (Writer.WritingModule && - !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo() && - !isa<VarTemplateSpecializationDecl>(D)) { + !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo()) { // When building a C++20 module interface unit or a partition unit, a // strong definition in the module interface is provided by the // compilation of that unit, not by its users. (Inline variables are still @@ -1165,6 +1178,12 @@ void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { Code = serialization::DECL_FILE_SCOPE_ASM; } +void ASTDeclWriter::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) { + VisitDecl(D); + Record.AddStmt(D->getStmt()); + Code = serialization::DECL_TOP_LEVEL_STMT_DECL; +} + void ASTDeclWriter::VisitEmptyDecl(EmptyDecl *D) { VisitDecl(D); Code = serialization::DECL_EMPTY; @@ -1246,6 +1265,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { VisitRedeclarable(D); VisitNamedDecl(D); Record.push_back(D->isInline()); + Record.push_back(D->isNested()); Record.AddSourceLocation(D->getBeginLoc()); Record.AddSourceLocation(D->getRBraceLoc()); @@ -1293,7 +1313,7 @@ void ASTDeclWriter::VisitUsingEnumDecl(UsingEnumDecl *D) { VisitNamedDecl(D); Record.AddSourceLocation(D->getUsingLoc()); Record.AddSourceLocation(D->getEnumLoc()); - Record.AddDeclRef(D->getEnumDecl()); + Record.AddTypeSourceInfo(D->getEnumType()); Record.AddDeclRef(D->FirstUsingShadow.getPointer()); Record.AddDeclRef(Context.getInstantiatedFromUsingEnumDecl(D)); Code = serialization::DECL_USING_ENUM; @@ -1404,14 +1424,12 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { } if (D->getDeclContext() == D->getLexicalDeclContext() && - D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->hasAttrs() && - !D->isTopLevelDeclInObjCContainer() && + D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && + !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->hasExtInfo() && - !D->hasInheritedPrototype() && - D->hasWrittenPrototype()) + !D->hasExtInfo() && !D->hasInheritedPrototype() && + D->hasWrittenPrototype() && + D->getTemplatedKind() == FunctionDecl::TK_NonTemplate) AbbrevToUse = Writer.getDeclCXXMethodAbbrev(); Code = serialization::DECL_CXX_METHOD; @@ -1505,8 +1523,8 @@ void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) { void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) { VisitNamedDecl(D); - Record.AddDeclRef(D->getTemplatedDecl()); Record.AddTemplateParameterList(D->getTemplateParameters()); + Record.AddDeclRef(D->getTemplatedDecl()); } void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) { @@ -1515,6 +1533,15 @@ void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) { Code = serialization::DECL_CONCEPT; } +void ASTDeclWriter::VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D) { + Record.push_back(D->getTemplateArguments().size()); + VisitDecl(D); + for (const TemplateArgument &Arg : D->getTemplateArguments()) + Record.AddTemplateArgument(Arg); + Code = serialization::DECL_IMPLICIT_CONCEPT_SPECIALIZATION; +} + void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { Code = serialization::DECL_REQUIRES_EXPR_BODY; } @@ -1607,8 +1634,6 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *D) { RegisterTemplateSpecialization(D->getSpecializedTemplate(), D); - VisitVarDecl(D); - llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> InstFrom = D->getSpecializedTemplateOrPartial(); if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) { @@ -1629,6 +1654,9 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( Record.AddSourceLocation(D->getPointOfInstantiation()); Record.push_back(D->getSpecializationKind()); Record.push_back(D->IsCompleteDefinition); + + VisitVarDecl(D); + Record.push_back(D->isCanonicalDecl()); if (D->isCanonicalDecl()) { @@ -1864,6 +1892,17 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { } } +void ASTDeclWriter::VisitHLSLBufferDecl(HLSLBufferDecl *D) { + VisitNamedDecl(D); + VisitDeclContext(D); + Record.push_back(D->isCBuffer()); + Record.AddSourceLocation(D->getLocStart()); + Record.AddSourceLocation(D->getLBraceLoc()); + Record.AddSourceLocation(D->getRBraceLoc()); + + Code = serialization::DECL_HLSL_BUFFER; +} + void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { Record.writeOMPChildren(D->Data); VisitDecl(D); @@ -2093,6 +2132,8 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // getArgPassingRestrictions Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); + // ODRHash + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 26)); // DC Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset @@ -2233,6 +2274,8 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD)); // RedeclarableDecl Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl + // FIXME: Implement abbreviation for other template kinds. + Abv->Add(BitCodeAbbrevOp(FunctionDecl::TK_NonTemplate)); // TemplateKind // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext @@ -2269,20 +2312,22 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsIneligibleOrNotSelected Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Constexpr Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // FriendConstraintRefersToEnclosingTemplate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Default Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind // This Array slurps the rest of the record. Fortunately we want to encode // (nearly) all the remaining (variable number of) fields in the same way. // - // This is the function template information if any, then + // This is: // NumParams and Params[] from FunctionDecl, and // NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl. // @@ -2389,7 +2434,7 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context, // File scoped assembly or obj-c or OMP declare target implementation must be // seen. - if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D)) + if (isa<FileScopeAsmDecl, TopLevelStmtDecl, ObjCImplDecl>(D)) return true; if (WritingModule && isPartOfPerModuleInitializer(D)) { @@ -2429,11 +2474,12 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { SourceLocation Loc = D->getLocation(); unsigned Index = ID - FirstDeclID; if (DeclOffsets.size() == Index) - DeclOffsets.emplace_back(Loc, Offset, DeclTypesBlockStartOffset); + DeclOffsets.emplace_back(getAdjustedLocation(Loc), Offset, + DeclTypesBlockStartOffset); else if (DeclOffsets.size() < Index) { // FIXME: Can/should this happen? DeclOffsets.resize(Index+1); - DeclOffsets[Index].setLocation(Loc); + DeclOffsets[Index].setLocation(getAdjustedLocation(Loc)); DeclOffsets[Index].setBitOffset(Offset, DeclTypesBlockStartOffset); } else { llvm_unreachable("declarations should be emitted in ID order"); @@ -2456,7 +2502,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { assert(FD->doesThisDeclarationHaveABody()); bool ModulesCodegen = false; if (!FD->isDependentContext()) { - Optional<GVALinkage> Linkage; + std::optional<GVALinkage> Linkage; if (Writer->WritingModule && Writer->WritingModule->isInterfaceOrPartition()) { // When building a C++20 module interface unit or a partition unit, a @@ -2486,8 +2532,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { Record->push_back(CD->getNumCtorInitializers()); if (CD->getNumCtorInitializers()) - AddCXXCtorInitializers( - llvm::makeArrayRef(CD->init_begin(), CD->init_end())); + AddCXXCtorInitializers(llvm::ArrayRef(CD->init_begin(), CD->init_end())); } AddStmt(FD->getBody()); } diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp index 5e5a86ee01a2..b35a7cee5af2 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp @@ -402,6 +402,7 @@ static void addConstraintSatisfaction(ASTRecordWriter &Record, const ASTConstraintSatisfaction &Satisfaction) { Record.push_back(Satisfaction.IsSatisfied); + Record.push_back(Satisfaction.ContainsErrors); if (!Satisfaction.IsSatisfied) { Record.push_back(Satisfaction.NumRecords); for (const auto &DetailRecord : Satisfaction) { @@ -432,16 +433,13 @@ addSubstitutionDiagnostic( void ASTStmtWriter::VisitConceptSpecializationExpr( ConceptSpecializationExpr *E) { VisitExpr(E); - ArrayRef<TemplateArgument> TemplateArgs = E->getTemplateArguments(); - Record.push_back(TemplateArgs.size()); Record.AddNestedNameSpecifierLoc(E->getNestedNameSpecifierLoc()); Record.AddSourceLocation(E->getTemplateKWLoc()); Record.AddDeclarationNameInfo(E->getConceptNameInfo()); Record.AddDeclRef(E->getNamedConcept()); Record.AddDeclRef(E->getFoundDecl()); + Record.AddDeclRef(E->getSpecializationDecl()); Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten()); - for (const TemplateArgument &Arg : TemplateArgs) - Record.AddTemplateArgument(Arg); if (!E->isValueDependent()) addConstraintSatisfaction(Record, E->getSatisfaction()); @@ -495,12 +493,12 @@ void ASTStmtWriter::VisitRequiresExpr(RequiresExpr *E) { } else { auto *NestedReq = cast<concepts::NestedRequirement>(R); Record.push_back(concepts::Requirement::RK_Nested); - Record.push_back(NestedReq->isSubstitutionFailure()); - if (NestedReq->isSubstitutionFailure()){ - addSubstitutionDiagnostic(Record, - NestedReq->getSubstitutionDiagnostic()); + Record.push_back(NestedReq->hasInvalidConstraint()); + if (NestedReq->hasInvalidConstraint()) { + Record.AddString(NestedReq->getInvalidConstraintEntity()); + addConstraintSatisfaction(Record, *NestedReq->Satisfaction); } else { - Record.AddStmt(NestedReq->Value.get<Expr *>()); + Record.AddStmt(NestedReq->getConstraintExpr()); if (!NestedReq->isDependent()) addConstraintSatisfaction(Record, *NestedReq->Satisfaction); } @@ -1747,14 +1745,20 @@ void ASTStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { Record.AddDeclRef(E->getParam()); Record.AddDeclRef(cast_or_null<Decl>(E->getUsedContext())); Record.AddSourceLocation(E->getUsedLocation()); + Record.push_back(E->hasRewrittenInit()); + if (E->hasRewrittenInit()) + Record.AddStmt(E->getRewrittenExpr()); Code = serialization::EXPR_CXX_DEFAULT_ARG; } void ASTStmtWriter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { VisitExpr(E); + Record.push_back(E->hasRewrittenInit()); Record.AddDeclRef(E->getField()); Record.AddDeclRef(cast_or_null<Decl>(E->getUsedContext())); Record.AddSourceLocation(E->getExprLoc()); + if (E->hasRewrittenInit()) + Record.AddStmt(E->getRewrittenExpr()); Code = serialization::EXPR_CXX_DEFAULT_INIT; } @@ -2027,8 +2031,13 @@ void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); - Record.AddDeclRef(E->getParameter()); + Record.AddDeclRef(E->getAssociatedDecl()); Record.push_back(E->isReferenceParameter()); + Record.push_back(E->getIndex()); + if (auto PackIndex = E->getPackIndex()) + Record.push_back(*PackIndex + 1); + else + Record.push_back(0); Record.AddSourceLocation(E->getNameLoc()); Record.AddStmt(E->getReplacement()); Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM; @@ -2037,7 +2046,8 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr( void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E) { VisitExpr(E); - Record.AddDeclRef(E->getParameterPack()); + Record.AddDeclRef(E->getAssociatedDecl()); + Record.push_back(E->getIndex()); Record.AddTemplateArgument(E->getArgumentPack()); Record.AddSourceLocation(E->getParameterPackLocation()); Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK; @@ -2077,6 +2087,30 @@ void ASTStmtWriter::VisitCXXFoldExpr(CXXFoldExpr *E) { Code = serialization::EXPR_CXX_FOLD; } +void ASTStmtWriter::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) { + VisitExpr(E); + ArrayRef<Expr *> InitExprs = E->getInitExprs(); + Record.push_back(InitExprs.size()); + Record.push_back(E->getUserSpecifiedInitExprs().size()); + Record.AddSourceLocation(E->getInitLoc()); + Record.AddSourceLocation(E->getBeginLoc()); + Record.AddSourceLocation(E->getEndLoc()); + for (Expr *InitExpr : E->getInitExprs()) + Record.AddStmt(InitExpr); + Expr *ArrayFiller = E->getArrayFiller(); + FieldDecl *UnionField = E->getInitializedFieldInUnion(); + bool HasArrayFillerOrUnionDecl = ArrayFiller || UnionField; + Record.push_back(HasArrayFillerOrUnionDecl); + if (HasArrayFillerOrUnionDecl) { + Record.push_back(static_cast<bool>(ArrayFiller)); + if (ArrayFiller) + Record.AddStmt(ArrayFiller); + else + Record.AddDeclRef(UnionField); + } + Code = serialization::EXPR_CXX_PAREN_LIST_INIT; +} + void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); Record.AddStmt(E->getSourceExpr()); @@ -2392,6 +2426,13 @@ void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) { Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE; } +void ASTStmtWriter::VisitOMPErrorDirective(OMPErrorDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_ERROR_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); diff --git a/contrib/llvm-project/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm-project/clang/lib/Serialization/ModuleManager.cpp index 4fd217cf7a6e..81dd54692d77 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ModuleManager.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ModuleManager.cpp @@ -249,7 +249,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, return NewlyLoaded; } -void ModuleManager::removeModules(ModuleIterator First, ModuleMap *modMap) { +void ModuleManager::removeModules(ModuleIterator First) { auto Last = end(); if (First == Last) return; @@ -280,19 +280,10 @@ void ModuleManager::removeModules(ModuleIterator First, ModuleMap *modMap) { } } - // Delete the modules and erase them from the various structures. - for (ModuleIterator victim = First; victim != Last; ++victim) { + // Delete the modules. + for (ModuleIterator victim = First; victim != Last; ++victim) Modules.erase(victim->File); - if (modMap) { - StringRef ModuleName = victim->ModuleName; - if (Module *mod = modMap->findModule(ModuleName)) { - mod->setASTFile(None); - } - } - } - - // Delete the modules. Chain.erase(Chain.begin() + (First - begin()), Chain.end()); } @@ -453,14 +444,14 @@ void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor, bool ModuleManager::lookupModuleFile(StringRef FileName, off_t ExpectedSize, time_t ExpectedModTime, - Optional<FileEntryRef> &File) { - File = None; + OptionalFileEntryRef &File) { + File = std::nullopt; if (FileName == "-") return false; // Open the file immediately to ensure there is no race between stat'ing and // opening the file. - Optional<FileEntryRef> FileOrErr = + OptionalFileEntryRef FileOrErr = expectedToOptional(FileMgr.getFileRef(FileName, /*OpenFile=*/true, /*CacheFailure=*/false)); if (!FileOrErr) |