Extend diagnostic for out of date AST input file.
If the size has changed, list the old and new sizes; if the mtime has changed, list the old and new mtimes (as raw time_t values).
This commit is contained in:
parent
2de2dbef2a
commit
df7b6b9142
|
@ -20,7 +20,7 @@ def err_fe_pch_malformed_block : Error<
|
||||||
def err_fe_ast_file_modified : Error<
|
def err_fe_ast_file_modified : Error<
|
||||||
"file '%0' has been modified since the "
|
"file '%0' has been modified since the "
|
||||||
"%select{precompiled header|module file|AST file}1 '%2' was built"
|
"%select{precompiled header|module file|AST file}1 '%2' was built"
|
||||||
": %select{size|mtime|content}3 changed">,
|
": %select{size|mtime|content}3 changed%select{| (was %5, now %6)}4">,
|
||||||
DefaultFatal;
|
DefaultFatal;
|
||||||
def err_fe_pch_file_overridden : Error<
|
def err_fe_pch_file_overridden : Error<
|
||||||
"file '%0' from the precompiled header has been overridden">;
|
"file '%0' from the precompiled header has been overridden">;
|
||||||
|
|
|
@ -2380,17 +2380,24 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ModificationType {
|
struct Change {
|
||||||
Size,
|
enum ModificationKind {
|
||||||
ModTime,
|
Size,
|
||||||
Content,
|
ModTime,
|
||||||
None,
|
Content,
|
||||||
|
None,
|
||||||
|
} Kind;
|
||||||
|
llvm::Optional<int64_t> Old = llvm::None;
|
||||||
|
llvm::Optional<int64_t> New = llvm::None;
|
||||||
};
|
};
|
||||||
auto HasInputFileChanged = [&]() {
|
auto HasInputFileChanged = [&]() {
|
||||||
if (StoredSize != File->getSize())
|
if (StoredSize != File->getSize())
|
||||||
return ModificationType::Size;
|
return Change{Change::Size, StoredSize, File->getSize()};
|
||||||
if (!shouldDisableValidationForFile(F) && StoredTime &&
|
if (!shouldDisableValidationForFile(F) && StoredTime &&
|
||||||
StoredTime != File->getModificationTime()) {
|
StoredTime != File->getModificationTime()) {
|
||||||
|
Change MTimeChange = {Change::ModTime, StoredTime,
|
||||||
|
File->getModificationTime()};
|
||||||
|
|
||||||
// In case the modification time changes but not the content,
|
// In case the modification time changes but not the content,
|
||||||
// accept the cached file as legit.
|
// accept the cached file as legit.
|
||||||
if (ValidateASTInputFilesContent &&
|
if (ValidateASTInputFilesContent &&
|
||||||
|
@ -2398,28 +2405,30 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
|
||||||
auto MemBuffOrError = FileMgr.getBufferForFile(File);
|
auto MemBuffOrError = FileMgr.getBufferForFile(File);
|
||||||
if (!MemBuffOrError) {
|
if (!MemBuffOrError) {
|
||||||
if (!Complain)
|
if (!Complain)
|
||||||
return ModificationType::ModTime;
|
return MTimeChange;
|
||||||
std::string ErrorStr = "could not get buffer for file '";
|
std::string ErrorStr = "could not get buffer for file '";
|
||||||
ErrorStr += File->getName();
|
ErrorStr += File->getName();
|
||||||
ErrorStr += "'";
|
ErrorStr += "'";
|
||||||
Error(ErrorStr);
|
Error(ErrorStr);
|
||||||
return ModificationType::ModTime;
|
return MTimeChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: hash_value is not guaranteed to be stable!
|
||||||
auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
|
auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
|
||||||
if (StoredContentHash == static_cast<uint64_t>(ContentHash))
|
if (StoredContentHash == static_cast<uint64_t>(ContentHash))
|
||||||
return ModificationType::None;
|
return Change{Change::None};
|
||||||
return ModificationType::Content;
|
|
||||||
|
return Change{Change::Content};
|
||||||
}
|
}
|
||||||
return ModificationType::ModTime;
|
return MTimeChange;
|
||||||
}
|
}
|
||||||
return ModificationType::None;
|
return Change{Change::None};
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsOutOfDate = false;
|
bool IsOutOfDate = false;
|
||||||
auto FileChange = HasInputFileChanged();
|
auto FileChange = HasInputFileChanged();
|
||||||
// For an overridden file, there is nothing to validate.
|
// For an overridden file, there is nothing to validate.
|
||||||
if (!Overridden && FileChange != ModificationType::None) {
|
if (!Overridden && FileChange.Kind != Change::None) {
|
||||||
if (Complain && !Diags.isDiagnosticInFlight()) {
|
if (Complain && !Diags.isDiagnosticInFlight()) {
|
||||||
// Build a list of the PCH imports that got us here (in reverse).
|
// Build a list of the PCH imports that got us here (in reverse).
|
||||||
SmallVector<ModuleFile *, 4> ImportStack(1, &F);
|
SmallVector<ModuleFile *, 4> ImportStack(1, &F);
|
||||||
|
@ -2430,7 +2439,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
|
||||||
StringRef TopLevelPCHName(ImportStack.back()->FileName);
|
StringRef TopLevelPCHName(ImportStack.back()->FileName);
|
||||||
Diag(diag::err_fe_ast_file_modified)
|
Diag(diag::err_fe_ast_file_modified)
|
||||||
<< Filename << moduleKindForDiagnostic(ImportStack.back()->Kind)
|
<< Filename << moduleKindForDiagnostic(ImportStack.back()->Kind)
|
||||||
<< TopLevelPCHName << FileChange;
|
<< TopLevelPCHName << FileChange.Kind
|
||||||
|
<< (FileChange.Old && FileChange.New)
|
||||||
|
<< llvm::itostr(FileChange.Old.getValueOr(0))
|
||||||
|
<< llvm::itostr(FileChange.New.getValueOr(0));
|
||||||
|
|
||||||
// Print the import stack.
|
// Print the import stack.
|
||||||
if (ImportStack.size() > 1) {
|
if (ImportStack.size() > 1) {
|
||||||
|
|
|
@ -31,4 +31,4 @@ void g() { f(); }
|
||||||
// CHECK-BITCODE-TIMESTAMP-ON: <INPUT_FILE abbrevid={{.*}} op0={{.*}} op1={{.*}} op2={{[^0]}}
|
// CHECK-BITCODE-TIMESTAMP-ON: <INPUT_FILE abbrevid={{.*}} op0={{.*}} op1={{.*}} op2={{[^0]}}
|
||||||
// CHECK-BITCODE-TIMESTAMP-OFF: <INPUT_FILE abbrevid={{.*}} op0={{.*}} op1={{.*}} op2={{[0]}}
|
// CHECK-BITCODE-TIMESTAMP-OFF: <INPUT_FILE abbrevid={{.*}} op0={{.*}} op1={{.*}} op2={{[0]}}
|
||||||
|
|
||||||
// CHECK-TIMESTAMP: fatal error: file {{.*}} has been modified since the precompiled header {{.*}} was built
|
// CHECK-TIMESTAMP: fatal error: file {{.*}} has been modified since the precompiled header {{.*}} was built: mtime changed (was {{.*}}, now {{.*}})
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
// RUN: echo ' ' >> %t.h
|
// RUN: echo ' ' >> %t.h
|
||||||
// RUN: not %clang_cc1 -isystem %t/usr/include -verify-pch %t.pch 2> %t.log.2
|
// RUN: not %clang_cc1 -isystem %t/usr/include -verify-pch %t.pch 2> %t.log.2
|
||||||
// RUN: FileCheck -check-prefix=CHECK-STALE-DEP %s < %t.log.2
|
// RUN: FileCheck -check-prefix=CHECK-STALE-DEP %s < %t.log.2
|
||||||
// CHECK-STALE-DEP: file '{{.*}}.h' has been modified since the precompiled header '{{.*}}.pch' was built
|
// CHECK-STALE-DEP: file '{{.*}}.h' has been modified since the precompiled header '{{.*}}.pch' was built: size changed (was {{.*}}, now {{.*}})
|
||||||
|
|
||||||
// Stale dependency in system header
|
// Stale dependency in system header
|
||||||
// RUN: %clang_cc1 -isystem %t/usr/include -x objective-c-header -emit-pch -o %t.pch %t.h
|
// RUN: %clang_cc1 -isystem %t/usr/include -x objective-c-header -emit-pch -o %t.pch %t.h
|
||||||
|
|
Loading…
Reference in New Issue