diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index bf3221be004d..f15a935d2af1 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -20,7 +20,7 @@ def err_fe_pch_malformed_block : Error< def err_fe_ast_file_modified : Error< "file '%0' has been modified since the " "%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; def err_fe_pch_file_overridden : Error< "file '%0' from the precompiled header has been overridden">; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b8c4889b10f9..1f9778dc6a0f 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2380,17 +2380,24 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { } } - enum ModificationType { - Size, - ModTime, - Content, - None, + struct Change { + enum ModificationKind { + Size, + ModTime, + Content, + None, + } Kind; + llvm::Optional Old = llvm::None; + llvm::Optional New = llvm::None; }; auto HasInputFileChanged = [&]() { if (StoredSize != File->getSize()) - return ModificationType::Size; + return Change{Change::Size, StoredSize, File->getSize()}; if (!shouldDisableValidationForFile(F) && StoredTime && StoredTime != File->getModificationTime()) { + Change MTimeChange = {Change::ModTime, StoredTime, + File->getModificationTime()}; + // In case the modification time changes but not the content, // accept the cached file as legit. if (ValidateASTInputFilesContent && @@ -2398,28 +2405,30 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { auto MemBuffOrError = FileMgr.getBufferForFile(File); if (!MemBuffOrError) { if (!Complain) - return ModificationType::ModTime; + return MTimeChange; std::string ErrorStr = "could not get buffer for file '"; ErrorStr += File->getName(); ErrorStr += "'"; Error(ErrorStr); - return ModificationType::ModTime; + return MTimeChange; } + // FIXME: hash_value is not guaranteed to be stable! auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer()); if (StoredContentHash == static_cast(ContentHash)) - return ModificationType::None; - return ModificationType::Content; + return Change{Change::None}; + + return Change{Change::Content}; } - return ModificationType::ModTime; + return MTimeChange; } - return ModificationType::None; + return Change{Change::None}; }; bool IsOutOfDate = false; auto FileChange = HasInputFileChanged(); // For an overridden file, there is nothing to validate. - if (!Overridden && FileChange != ModificationType::None) { + if (!Overridden && FileChange.Kind != Change::None) { if (Complain && !Diags.isDiagnosticInFlight()) { // Build a list of the PCH imports that got us here (in reverse). SmallVector ImportStack(1, &F); @@ -2430,7 +2439,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { StringRef TopLevelPCHName(ImportStack.back()->FileName); Diag(diag::err_fe_ast_file_modified) << 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. if (ImportStack.size() > 1) { diff --git a/clang/test/PCH/include-timestamp.cpp b/clang/test/PCH/include-timestamp.cpp index 36b887aee85f..0bee9b7f235c 100644 --- a/clang/test/PCH/include-timestamp.cpp +++ b/clang/test/PCH/include-timestamp.cpp @@ -31,4 +31,4 @@ void g() { f(); } // CHECK-BITCODE-TIMESTAMP-ON: > %t.h // 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 -// 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 // RUN: %clang_cc1 -isystem %t/usr/include -x objective-c-header -emit-pch -o %t.pch %t.h