https://github.com/necto updated https://github.com/llvm/llvm-project/pull/196057
>From b43ad5369e2a905c10b13104e81f3e1485099295 Mon Sep 17 00:00:00 2001 From: Arseniy Zaostrovnykh <[email protected]> Date: Wed, 6 May 2026 14:27:32 +0200 Subject: [PATCH 1/3] [clang] relocatable PCH do not support files with different mtime --- clang/test/PCH/relocatable-pch-mtime.c | 78 ++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 clang/test/PCH/relocatable-pch-mtime.c diff --git a/clang/test/PCH/relocatable-pch-mtime.c b/clang/test/PCH/relocatable-pch-mtime.c new file mode 100644 index 0000000000000..70eedf9eb2635 --- /dev/null +++ b/clang/test/PCH/relocatable-pch-mtime.c @@ -0,0 +1,78 @@ +// Test the mtime validation behavior of a relocatable PCH when source files +// are relocated and their timestamps change. Without content validation any +// mtime difference is a hard error. With -fvalidate-ast-input-files-content +// an mtime mismatch falls back to a content hash comparison, which tolerates +// mtime drift but still catches genuine content changes. + +// RUN: rm -rf %t +// RUN: mkdir -p %t/sysroot_orig/usr/include + +// Create a simple header in the original sysroot. +// RUN: echo '#ifndef TEST_H' > %t/sysroot_orig/usr/include/test.h +// RUN: echo '#define TEST_H' >> %t/sysroot_orig/usr/include/test.h +// RUN: echo 'int relocated_val = 42;' >> %t/sysroot_orig/usr/include/test.h +// RUN: echo '#endif' >> %t/sysroot_orig/usr/include/test.h + +// Generate a relocatable PCH against the original sysroot. Include +// -fvalidate-ast-input-files-content so that content hashes are stored in +// the PCH and can be compared on subsequent loads. +// RUN: %clang_cc1 -x c-header -relocatable-pch -emit-pch \ +// RUN: -isysroot %t/sysroot_orig -fvalidate-ast-input-files-content \ +// RUN: -o %t/test.pch %t/sysroot_orig/usr/include/test.h + +// Baseline: loading with the original sysroot succeeds. +// RUN: %clang_cc1 -include-pch %t/test.pch \ +// RUN: -isysroot %t/sysroot_orig \ +// RUN: -fsyntax-only %s + +// Set up a new sysroot by moving the header there (simulating workspace relocation). +// RUN: mkdir -p %t/sysroot_new/usr/include +// RUN: mv %t/sysroot_orig/usr/include/test.h %t/sysroot_new/usr/include/test.h + +// Loading the relocatable PCH with the new sysroot and with mtime preserved works. +// RUN: %clang_cc1 -include-pch %t/test.pch \ +// RUN: -isysroot %t/sysroot_new \ +// RUN: -fsyntax-only %s + +// Advance mtime of the relocated header by 1 hour to simulate timestamp drift +// that naturally occurs when files are relocated, without changing content. +// RUN: %python -c "import os,sys; t=os.path.getmtime(sys.argv[1])+3600; os.utime(sys.argv[1],(t,t))" \ +// RUN: %t/sysroot_new/usr/include/test.h + +// Mtime changed but content is identical: the relocatable PCH is rejected +// RUN: not %clang_cc1 -include-pch %t/test.pch \ +// RUN: -isysroot %t/sysroot_new \ +// RUN: -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-MTIME,CHECK + +// With content validation the mtime mismatch falls back to a content hash +// comparison; since the content is unchanged the PCH loads successfully. +// RUN: %clang_cc1 -include-pch %t/test.pch \ +// RUN: -isysroot %t/sysroot_new -fvalidate-ast-input-files-content \ +// RUN: -fsyntax-only %s + +// Overwrite the header with different content of the same size (42 -> 69). +// RUN: echo '#ifndef TEST_H' > %t/sysroot_new/usr/include/test.h +// RUN: echo '#define TEST_H' >> %t/sysroot_new/usr/include/test.h +// RUN: echo 'int relocated_val = 69;' >> %t/sysroot_new/usr/include/test.h +// RUN: echo '#endif' >> %t/sysroot_new/usr/include/test.h + +// Advance the mtime again to ensure it differs from the value stored in the PCH. +// On a fast machine, the newly written file might have the same mtime as the original. +// RUN: %python -c "import os,sys; t=os.path.getmtime(sys.argv[1])+3600; os.utime(sys.argv[1],(t,t))" \ +// RUN: %t/sysroot_new/usr/include/test.h + +// Without content validation the mtime mismatch is reported. +// RUN: not %clang_cc1 -include-pch %t/test.pch \ +// RUN: -isysroot %t/sysroot_new \ +// RUN: -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-MTIME,CHECK + +// With content validation the change is caught even though size is the same. +// RUN: not %clang_cc1 -include-pch %t/test.pch \ +// RUN: -isysroot %t/sysroot_new -fvalidate-ast-input-files-content \ +// RUN: -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-CONTENT,CHECK + +// CHECK: fatal error: file '{{.*}}test.h' has been modified since the precompiled header '{{.*}}test.pch' was built +// CHECK-CONTENT: note: content changed +// CHECK-MTIME: note: mtime changed + +int get_val(void) { return relocated_val; } >From c234c837530750594fc98b691deb3ebabe1d1e76 Mon Sep 17 00:00:00 2001 From: Arseniy Zaostrovnykh <[email protected]> Date: Wed, 6 May 2026 15:39:40 +0200 Subject: [PATCH 2/3] [clang] Accept mtime change for input files of relocatable PCH Relocatable PCH are expected to tolerate a change in the absolute path of input files. It is natural that the files with different absolute paths can often have different mtime, so mtime should not be used as a proxy for file change when loading a relocatable PCH. -- CPP-8274 --- clang/lib/Serialization/ASTReader.cpp | 6 ++++++ clang/test/PCH/relocatable-pch-mtime.c | 22 +++++++++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 2c0b908314fa5..82e44037ea1d2 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2974,6 +2974,12 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { FileChange.Kind == Change::None) FileChange = HasInputContentChanged(FileChange); + // Ignore modification time of relocated inputs: + // files at different absolute paths are likely to have mismatching mtime, + // even if their contents match. + if (FileChange.Kind == Change::ModTime && F.RelocatablePCH) + FileChange = Change{Change::None}; + // For an overridden file, there is nothing to validate. if (!Overridden && FileChange.Kind != Change::None) { if (Complain) { diff --git a/clang/test/PCH/relocatable-pch-mtime.c b/clang/test/PCH/relocatable-pch-mtime.c index 70eedf9eb2635..4961e50ce754d 100644 --- a/clang/test/PCH/relocatable-pch-mtime.c +++ b/clang/test/PCH/relocatable-pch-mtime.c @@ -1,8 +1,8 @@ // Test the mtime validation behavior of a relocatable PCH when source files -// are relocated and their timestamps change. Without content validation any -// mtime difference is a hard error. With -fvalidate-ast-input-files-content -// an mtime mismatch falls back to a content hash comparison, which tolerates -// mtime drift but still catches genuine content changes. +// are relocated and their timestamps change. Mtime drift is expected after +// relocation, so a bare mtime mismatch is tolerated. With +// -fvalidate-ast-input-files-content an mtime mismatch falls back to a +// content hash comparison, which still catches genuine content changes. // RUN: rm -rf %t // RUN: mkdir -p %t/sysroot_orig/usr/include @@ -39,10 +39,10 @@ // RUN: %python -c "import os,sys; t=os.path.getmtime(sys.argv[1])+3600; os.utime(sys.argv[1],(t,t))" \ // RUN: %t/sysroot_new/usr/include/test.h -// Mtime changed but content is identical: the relocatable PCH is rejected -// RUN: not %clang_cc1 -include-pch %t/test.pch \ +// Mtime changed but content is identical: the relocatable PCH is accepted. +// RUN: %clang_cc1 -include-pch %t/test.pch \ // RUN: -isysroot %t/sysroot_new \ -// RUN: -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-MTIME,CHECK +// RUN: -fsyntax-only %s // With content validation the mtime mismatch falls back to a content hash // comparison; since the content is unchanged the PCH loads successfully. @@ -61,10 +61,11 @@ // RUN: %python -c "import os,sys; t=os.path.getmtime(sys.argv[1])+3600; os.utime(sys.argv[1],(t,t))" \ // RUN: %t/sysroot_new/usr/include/test.h -// Without content validation the mtime mismatch is reported. -// RUN: not %clang_cc1 -include-pch %t/test.pch \ +// Without content validation, mtime drift is tolerated and the content change +// goes undetected. +// RUN: %clang_cc1 -include-pch %t/test.pch \ // RUN: -isysroot %t/sysroot_new \ -// RUN: -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-MTIME,CHECK +// RUN: -fsyntax-only %s // With content validation the change is caught even though size is the same. // RUN: not %clang_cc1 -include-pch %t/test.pch \ @@ -73,6 +74,5 @@ // CHECK: fatal error: file '{{.*}}test.h' has been modified since the precompiled header '{{.*}}test.pch' was built // CHECK-CONTENT: note: content changed -// CHECK-MTIME: note: mtime changed int get_val(void) { return relocated_val; } >From 046717e56ddb7984a85429149004190f00ecd9eb Mon Sep 17 00:00:00 2001 From: Arseniy Zaostrovnykh <[email protected]> Date: Wed, 6 May 2026 16:29:59 +0200 Subject: [PATCH 3/3] [NFC] Simplify FileCheck invocation --- clang/test/PCH/relocatable-pch-mtime.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/PCH/relocatable-pch-mtime.c b/clang/test/PCH/relocatable-pch-mtime.c index 4961e50ce754d..df07a8deab248 100644 --- a/clang/test/PCH/relocatable-pch-mtime.c +++ b/clang/test/PCH/relocatable-pch-mtime.c @@ -70,9 +70,9 @@ // With content validation the change is caught even though size is the same. // RUN: not %clang_cc1 -include-pch %t/test.pch \ // RUN: -isysroot %t/sysroot_new -fvalidate-ast-input-files-content \ -// RUN: -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-CONTENT,CHECK +// RUN: -fsyntax-only %s 2>&1 | FileCheck %s // CHECK: fatal error: file '{{.*}}test.h' has been modified since the precompiled header '{{.*}}test.pch' was built -// CHECK-CONTENT: note: content changed +// CHECK: note: content changed int get_val(void) { return relocated_val; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
