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