summaryrefslogtreecommitdiff
path: root/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Serialization/ASTReader.cpp')
-rw-r--r--lib/Serialization/ASTReader.cpp223
1 files changed, 159 insertions, 64 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 7f2c7f09e8a3..2d3884ebe021 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1247,6 +1247,12 @@ void ASTReader::Error(unsigned DiagID,
Diag(DiagID) << Arg1 << Arg2;
}
+void ASTReader::Error(unsigned DiagID, StringRef Arg1, StringRef Arg2,
+ unsigned Select) const {
+ if (!Diags.isDiagnosticInFlight())
+ Diag(DiagID) << Arg1 << Arg2 << Select;
+}
+
void ASTReader::Error(llvm::Error &&Err) const {
Error(toString(std::move(Err)));
}
@@ -1514,6 +1520,7 @@ bool ASTReader::ReadSLocEntry(int ID) {
}
SrcMgr::CharacteristicKind
FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
+ // FIXME: The FileID should be created from the FileEntryRef.
FileID FID = SourceMgr.createFileID(File, IncludeLoc, FileCharacter,
ID, BaseOffset + Record[0]);
SrcMgr::FileInfo &FileInfo =
@@ -1522,9 +1529,9 @@ bool ASTReader::ReadSLocEntry(int ID) {
if (Record[3])
FileInfo.setHasLineDirectives();
- const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
unsigned NumFileDecls = Record[7];
if (NumFileDecls && ContextObj) {
+ const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
NumFileDecls));
@@ -1822,12 +1829,17 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) {
// Determine whether the actual files are equivalent.
FileManager &FileMgr = Reader.getFileManager();
auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* {
- if (!Key.Imported)
- return FileMgr.getFile(Key.Filename);
+ if (!Key.Imported) {
+ if (auto File = FileMgr.getFile(Key.Filename))
+ return *File;
+ return nullptr;
+ }
std::string Resolved = Key.Filename;
Reader.ResolveImportedPath(M, Resolved);
- return FileMgr.getFile(Resolved);
+ if (auto File = FileMgr.getFile(Resolved))
+ return *File;
+ return nullptr;
};
const FileEntry *FEA = GetFile(a);
@@ -1904,7 +1916,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
// FIXME: This is not always the right filename-as-written, but we're not
// going to use this information to rebuild the module, so it doesn't make
// a lot of difference.
- Module::Header H = { key.Filename, FileMgr.getFile(Filename) };
+ Module::Header H = { key.Filename, *FileMgr.getFile(Filename) };
ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true);
HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader);
}
@@ -2235,6 +2247,24 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
R.TopLevelModuleMap = static_cast<bool>(Record[5]);
R.Filename = Blob;
ResolveImportedPath(F, R.Filename);
+
+ Expected<llvm::BitstreamEntry> MaybeEntry = Cursor.advance();
+ if (!MaybeEntry) // FIXME this drops errors on the floor.
+ consumeError(MaybeEntry.takeError());
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+ assert(Entry.Kind == llvm::BitstreamEntry::Record &&
+ "expected record type for input file hash");
+
+ Record.clear();
+ if (Expected<unsigned> Maybe = Cursor.readRecord(Entry.ID, Record))
+ assert(static_cast<InputFileRecordTypes>(Maybe.get()) == INPUT_FILE_HASH &&
+ "invalid record type for input file hash");
+ else {
+ // FIXME this drops errors on the floor.
+ consumeError(Maybe.takeError());
+ }
+ R.ContentHash = (static_cast<uint64_t>(Record[1]) << 32) |
+ static_cast<uint64_t>(Record[0]);
return R;
}
@@ -2265,8 +2295,12 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
bool Overridden = FI.Overridden;
bool Transient = FI.Transient;
StringRef Filename = FI.Filename;
+ uint64_t StoredContentHash = FI.ContentHash;
+
+ const FileEntry *File = nullptr;
+ if (auto FE = FileMgr.getFile(Filename, /*OpenFile=*/false))
+ File = *FE;
- const FileEntry *File = FileMgr.getFile(Filename, /*OpenFile=*/false);
// If we didn't find the file, resolve it relative to the
// original directory from which this AST file was created.
if (File == nullptr && !F.OriginalDir.empty() && !F.BaseDirectory.empty() &&
@@ -2274,7 +2308,8 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
std::string Resolved = resolveFileRelativeToOriginalDir(
Filename, F.OriginalDir, F.BaseDirectory);
if (!Resolved.empty())
- File = FileMgr.getFile(Resolved);
+ if (auto FE = FileMgr.getFile(Resolved))
+ File = *FE;
}
// For an overridden file, create a virtual file with the stored
@@ -2305,29 +2340,56 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
if ((!Overridden && !Transient) && SM.isFileOverridden(File)) {
if (Complain)
Error(diag::err_fe_pch_file_overridden, Filename);
- // After emitting the diagnostic, recover by disabling the override so
- // that the original file will be used.
- //
- // FIXME: This recovery is just as broken as the original state; there may
- // be another precompiled module that's using the overridden contents, or
- // we might be half way through parsing it. Instead, we should treat the
- // overridden contents as belonging to a separate FileEntry.
- SM.disableFileContentsOverride(File);
- // The FileEntry is a virtual file entry with the size of the contents
- // that would override the original contents. Set it to the original's
- // size/time.
- FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
- StoredSize, StoredTime);
+
+ // After emitting the diagnostic, bypass the overriding file to recover
+ // (this creates a separate FileEntry).
+ File = SM.bypassFileContentsOverride(*File);
+ if (!File) {
+ F.InputFilesLoaded[ID - 1] = InputFile::getNotFound();
+ return InputFile();
+ }
}
- bool IsOutOfDate = false;
+ enum ModificationType {
+ Size,
+ ModTime,
+ Content,
+ None,
+ };
+ auto HasInputFileChanged = [&]() {
+ if (StoredSize != File->getSize())
+ return ModificationType::Size;
+ if (!DisableValidation && StoredTime &&
+ StoredTime != File->getModificationTime()) {
+ // In case the modification time changes but not the content,
+ // accept the cached file as legit.
+ if (ValidateASTInputFilesContent &&
+ StoredContentHash != static_cast<uint64_t>(llvm::hash_code(-1))) {
+ auto MemBuffOrError = FileMgr.getBufferForFile(File);
+ if (!MemBuffOrError) {
+ if (!Complain)
+ return ModificationType::ModTime;
+ std::string ErrorStr = "could not get buffer for file '";
+ ErrorStr += File->getName();
+ ErrorStr += "'";
+ Error(ErrorStr);
+ return ModificationType::ModTime;
+ }
+ auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
+ if (StoredContentHash == static_cast<uint64_t>(ContentHash))
+ return ModificationType::None;
+ return ModificationType::Content;
+ }
+ return ModificationType::ModTime;
+ }
+ return ModificationType::None;
+ };
+
+ bool IsOutOfDate = false;
+ auto FileChange = HasInputFileChanged();
// For an overridden file, there is nothing to validate.
- if (!Overridden && //
- (StoredSize != File->getSize() ||
- (StoredTime && StoredTime != File->getModificationTime() &&
- !DisableValidation)
- )) {
+ if (!Overridden && FileChange != ModificationType::None) {
if (Complain) {
// Build a list of the PCH imports that got us here (in reverse).
SmallVector<ModuleFile *, 4> ImportStack(1, &F);
@@ -2336,13 +2398,17 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// The top-level PCH is stale.
StringRef TopLevelPCHName(ImportStack.back()->FileName);
- unsigned DiagnosticKind = moduleKindForDiagnostic(ImportStack.back()->Kind);
+ unsigned DiagnosticKind =
+ moduleKindForDiagnostic(ImportStack.back()->Kind);
if (DiagnosticKind == 0)
- Error(diag::err_fe_pch_file_modified, Filename, TopLevelPCHName);
+ Error(diag::err_fe_pch_file_modified, Filename, TopLevelPCHName,
+ (unsigned)FileChange);
else if (DiagnosticKind == 1)
- Error(diag::err_fe_module_file_modified, Filename, TopLevelPCHName);
+ Error(diag::err_fe_module_file_modified, Filename, TopLevelPCHName,
+ (unsigned)FileChange);
else
- Error(diag::err_fe_ast_file_modified, Filename, TopLevelPCHName);
+ Error(diag::err_fe_ast_file_modified, Filename, TopLevelPCHName,
+ (unsigned)FileChange);
// Print the import stack.
if (ImportStack.size() > 1 && !Diags.isDiagnosticInFlight()) {
@@ -2820,9 +2886,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
// Don't emit module relocation error if we have -fno-validate-pch
if (!PP.getPreprocessorOpts().DisablePCHValidation &&
F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) {
- const DirectoryEntry *BuildDir =
- PP.getFileManager().getDirectory(Blob);
- if (!BuildDir || BuildDir != M->Directory) {
+ auto BuildDir = PP.getFileManager().getDirectory(Blob);
+ if (!BuildDir || *BuildDir != M->Directory) {
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Diag(diag::err_imported_module_relocated)
<< F.ModuleName << Blob << M->Directory->getName();
@@ -3814,7 +3879,6 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
// Don't emit module relocation error if we have -fno-validate-pch
if (!PP.getPreprocessorOpts().DisablePCHValidation && !ModMap) {
- assert(ImportedBy && "top-level import should be verified");
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) {
if (auto *ASTFE = M ? M->getASTFile() : nullptr) {
// This module was defined by an imported (explicit) module.
@@ -3823,12 +3887,13 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
} else {
// This module was built with a different module map.
Diag(diag::err_imported_module_not_found)
- << F.ModuleName << F.FileName << ImportedBy->FileName
- << F.ModuleMapPath;
+ << F.ModuleName << F.FileName
+ << (ImportedBy ? ImportedBy->FileName : "") << F.ModuleMapPath
+ << !ImportedBy;
// In case it was imported by a PCH, there's a chance the user is
// just missing to include the search path to the directory containing
// the modulemap.
- if (ImportedBy->Kind == MK_PCH)
+ if (ImportedBy && ImportedBy->Kind == MK_PCH)
Diag(diag::note_imported_by_pch_module_not_found)
<< llvm::sys::path::parent_path(F.ModuleMapPath);
}
@@ -3839,14 +3904,16 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
assert(M->Name == F.ModuleName && "found module with different name");
// Check the primary module map file.
- const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath);
- if (StoredModMap == nullptr || StoredModMap != ModMap) {
+ auto StoredModMap = FileMgr.getFile(F.ModuleMapPath);
+ if (!StoredModMap || *StoredModMap != ModMap) {
assert(ModMap && "found module is missing module map file");
- assert(ImportedBy && "top-level import should be verified");
+ assert((ImportedBy || F.Kind == MK_ImplicitModule) &&
+ "top-level import should be verified");
+ bool NotImported = F.Kind == MK_ImplicitModule && !ImportedBy;
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Diag(diag::err_imported_module_modmap_changed)
- << F.ModuleName << ImportedBy->FileName
- << ModMap->getName() << F.ModuleMapPath;
+ << F.ModuleName << (NotImported ? F.FileName : ImportedBy->FileName)
+ << ModMap->getName() << F.ModuleMapPath << NotImported;
return OutOfDate;
}
@@ -3854,14 +3921,13 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) {
// FIXME: we should use input files rather than storing names.
std::string Filename = ReadPath(F, Record, Idx);
- const FileEntry *F =
- FileMgr.getFile(Filename, false, false);
- if (F == nullptr) {
+ auto F = FileMgr.getFile(Filename, false, false);
+ if (!F) {
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Error("could not find file '" + Filename +"' referenced by AST file");
return OutOfDate;
}
- AdditionalStoredMaps.insert(F);
+ AdditionalStoredMaps.insert(*F);
}
// Check any additional module map files (e.g. module.private.modulemap)
@@ -4035,7 +4101,7 @@ static void updateModuleTimestamp(ModuleFile &MF) {
// Overwrite the timestamp file contents so that file's mtime changes.
std::string TimestampFilename = MF.getTimestampFilename();
std::error_code EC;
- llvm::raw_fd_ostream OS(TimestampFilename, EC, llvm::sys::fs::F_Text);
+ llvm::raw_fd_ostream OS(TimestampFilename, EC, llvm::sys::fs::OF_Text);
if (EC)
return;
OS << "Timestamp file\n";
@@ -5187,6 +5253,8 @@ bool ASTReader::readASTFileControlBlock(
consumeError(MaybeRecordType.takeError());
}
switch ((InputFileRecordTypes)MaybeRecordType.get()) {
+ case INPUT_FILE_HASH:
+ break;
case INPUT_FILE:
bool Overridden = static_cast<bool>(Record[3]);
std::string Filename = Blob;
@@ -5459,10 +5527,10 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case SUBMODULE_UMBRELLA_HEADER: {
std::string Filename = Blob;
ResolveImportedPath(F, Filename);
- if (auto *Umbrella = PP.getFileManager().getFile(Filename)) {
+ if (auto Umbrella = PP.getFileManager().getFile(Filename)) {
if (!CurrentModule->getUmbrellaHeader())
- ModMap.setUmbrellaHeader(CurrentModule, Umbrella, Blob);
- else if (CurrentModule->getUmbrellaHeader().Entry != Umbrella) {
+ ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob);
+ else if (CurrentModule->getUmbrellaHeader().Entry != *Umbrella) {
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Error("mismatched umbrella headers in submodule");
return OutOfDate;
@@ -5492,10 +5560,10 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case SUBMODULE_UMBRELLA_DIR: {
std::string Dirname = Blob;
ResolveImportedPath(F, Dirname);
- if (auto *Umbrella = PP.getFileManager().getDirectory(Dirname)) {
+ if (auto Umbrella = PP.getFileManager().getDirectory(Dirname)) {
if (!CurrentModule->getUmbrellaDir())
- ModMap.setUmbrellaDir(CurrentModule, Umbrella, Blob);
- else if (CurrentModule->getUmbrellaDir().Entry != Umbrella) {
+ ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob);
+ else if (CurrentModule->getUmbrellaDir().Entry != *Umbrella) {
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Error("mismatched umbrella directories in submodule");
return OutOfDate;
@@ -5890,7 +5958,8 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]);
const FileEntry *File = nullptr;
if (!FullFileName.empty())
- File = PP.getFileManager().getFile(FullFileName);
+ if (auto FE = PP.getFileManager().getFile(FullFileName))
+ File = *FE;
// FIXME: Stable encoding
InclusionDirective::InclusionKind Kind
@@ -6373,7 +6442,8 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
unsigned IndexTypeQuals = Record[2];
unsigned Idx = 3;
llvm::APInt Size = ReadAPInt(Record, Idx);
- return Context.getConstantArrayType(ElementType, Size,
+ Expr *SizeExpr = ReadExpr(*Loc.F);
+ return Context.getConstantArrayType(ElementType, Size, SizeExpr,
ASM, IndexTypeQuals);
}
@@ -7413,6 +7483,11 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_OMP_ARRAY_SECTION:
T = Context.OMPArraySectionTy;
break;
+#define SVE_TYPE(Name, Id, SingletonId) \
+ case PREDEF_TYPE_##Id##_ID: \
+ T = Context.SingletonId; \
+ break;
+#include "clang/Basic/AArch64SVEACLETypes.def"
}
assert(!T.isNull() && "Unknown predefined type");
@@ -8716,7 +8791,7 @@ void ASTReader::ReadLateParsedTemplates(
/* In loop */) {
FunctionDecl *FD = cast<FunctionDecl>(GetDecl(LateParsedTemplates[Idx++]));
- auto LT = llvm::make_unique<LateParsedTemplate>();
+ auto LT = std::make_unique<LateParsedTemplate>();
LT->D = GetDecl(LateParsedTemplates[Idx++]);
ModuleFile *F = getOwningModuleFile(LT->D);
@@ -9270,9 +9345,11 @@ ASTReader::ReadTemplateParameterList(ModuleFile &F,
while (NumParams--)
Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
- // TODO: Concepts
+ bool HasRequiresClause = Record[Idx++];
+ Expr *RequiresClause = HasRequiresClause ? ReadExpr(F) : nullptr;
+
TemplateParameterList *TemplateParams = TemplateParameterList::Create(
- getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, nullptr);
+ getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause);
return TemplateParams;
}
@@ -9718,10 +9795,17 @@ void ASTReader::ReadComments() {
}
}
NextCursor:
- // De-serialized SourceLocations get negative FileIDs for other modules,
- // potentially invalidating the original order. Sort it again.
- llvm::sort(Comments, BeforeThanCompare<RawComment>(SourceMgr));
- Context.Comments.addDeserializedComments(Comments);
+ llvm::DenseMap<FileID, std::map<unsigned, RawComment *>>
+ FileToOffsetToComment;
+ for (RawComment *C : Comments) {
+ SourceLocation CommentLoc = C->getBeginLoc();
+ if (CommentLoc.isValid()) {
+ std::pair<FileID, unsigned> Loc =
+ SourceMgr.getDecomposedLoc(CommentLoc);
+ if (Loc.first.isValid())
+ Context.Comments.OrderedComments[Loc.first].emplace(Loc.second, C);
+ }
+ }
}
}
@@ -12134,7 +12218,7 @@ ASTReader::ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
StringRef isysroot, bool DisableValidation,
bool AllowASTWithCompilerErrors,
bool AllowConfigurationMismatch, bool ValidateSystemInputs,
- bool UseGlobalIndex,
+ bool ValidateASTInputFilesContent, bool UseGlobalIndex,
std::unique_ptr<llvm::Timer> ReadTimer)
: Listener(DisableValidation
? cast<ASTReaderListener>(new SimpleASTReaderListener(PP))
@@ -12148,6 +12232,7 @@ ASTReader::ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
AllowConfigurationMismatch(AllowConfigurationMismatch),
ValidateSystemInputs(ValidateSystemInputs),
+ ValidateASTInputFilesContent(ValidateASTInputFilesContent),
UseGlobalIndex(UseGlobalIndex), CurrSwitchCaseStmts(&SwitchCaseStmts) {
SourceMgr.setExternalSLocEntrySource(this);
@@ -12184,7 +12269,7 @@ Expected<unsigned> ASTRecordReader::readRecord(llvm::BitstreamCursor &Cursor,
////===----------------------------------------------------------------------===//
OMPClause *OMPClauseReader::readClause() {
- OMPClause *C;
+ OMPClause *C = nullptr;
switch (Record.readInt()) {
case OMPC_if:
C = new (Context) OMPIfClause();
@@ -12385,6 +12470,8 @@ OMPClause *OMPClauseReader::readClause() {
C = OMPAllocateClause::CreateEmpty(Context, Record.readInt());
break;
}
+ assert(C && "Unknown OMPClause type");
+
Visit(C);
C->setLocStart(Record.readSourceLocation());
C->setLocEnd(Record.readSourceLocation());
@@ -12412,6 +12499,7 @@ void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
}
void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) {
+ VisitOMPClauseWithPreInit(C);
C->setCondition(Record.readSubExpr());
C->setLParenLoc(Record.readSourceLocation());
}
@@ -12728,6 +12816,10 @@ void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
C->setFinals(Vars);
C->setStep(Record.readSubExpr());
C->setCalcStep(Record.readSubExpr());
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars + 1; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setUsedExprs(Vars);
}
void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) {
@@ -12904,16 +12996,19 @@ void OMPClauseReader::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
}
void OMPClauseReader::VisitOMPPriorityClause(OMPPriorityClause *C) {
+ VisitOMPClauseWithPreInit(C);
C->setPriority(Record.readSubExpr());
C->setLParenLoc(Record.readSourceLocation());
}
void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
+ VisitOMPClauseWithPreInit(C);
C->setGrainsize(Record.readSubExpr());
C->setLParenLoc(Record.readSourceLocation());
}
void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
+ VisitOMPClauseWithPreInit(C);
C->setNumTasks(Record.readSubExpr());
C->setLParenLoc(Record.readSourceLocation());
}