https://github.com/vsapsai updated https://github.com/llvm/llvm-project/pull/176537
>From ce48e5df96af6db973c1024a29daa526e8f38f35 Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai <[email protected]> Date: Fri, 16 Jan 2026 23:09:37 -0800 Subject: [PATCH 1/2] [Modules] Add a test case when we are skipping module validation with a build session and use an outdated module. Check how it works in CI. rdar://165237499 --- ...build-session-validation-outdated-module.c | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 clang/test/Modules/build-session-validation-outdated-module.c diff --git a/clang/test/Modules/build-session-validation-outdated-module.c b/clang/test/Modules/build-session-validation-outdated-module.c new file mode 100644 index 0000000000000..693d1a8fd2cd3 --- /dev/null +++ b/clang/test/Modules/build-session-validation-outdated-module.c @@ -0,0 +1,86 @@ +// Test build session validation with parallel compilation for incremental builds. +// +// Shell is required for clang execution in background. +// REQUIRES: shell + +// RUN: rm -rf %t +// RUN: split-file %s %t +// Use the same command line arguments to ensure .pcm files are in the same location. +// RUN: echo "-fsyntax-only -I %/t/include" > %t/ctx.rsp +// RUN: echo "-fmodules -fmodules-cache-path=%/t/module-cache" >> %t/ctx.rsp +// RUN: echo "-fbuild-session-file=%/t/session.timestamp" >> %t/ctx.rsp +// RUN: echo "-fmodules-validate-once-per-build-session" >> %t/ctx.rsp +// RUN: echo "-Xclang -fno-modules-force-validate-user-headers" >> %t/ctx.rsp +// +// Add a build session file to avoid errors that it's missing. Doesn't do anything as we start with a clean build. +// RUN: touch %t/session.timestamp +// Generate a header that takes noticeable time to parse. +// RUN: %python %t/generate-expensive-header.py > %t/include/expensive-header.h +// +// Create SignatureExpectation.pcm with a specific Target signature. +// RUN: cp %t/version1.h %t/include/target.h +// RUN: echo "#include <signature-expectation.h>" | %clang @%t/ctx.rsp -x c - +// +// Built a different Target.pcm with a different signature. +// RUN: cp %t/version2.h %t/include/target.h +// Update the build session to rebuild Target. +// RUN: touch %t/session.timestamp +// RUN: echo "#include <target.h>" | %clang @%t/ctx.rsp -x c - +// +// Simulate the incremental build. +// RUN: cp %t/version3.h %t/include/target.h +// RUN: touch %t/session.timestamp +// RUN: sleep 1s +// Compile 2 files in parallel. +// RUN: %clang @%t/ctx.rsp %t/use-outdated-module.c & +// RUN: %clang @%t/ctx.rsp %t/rebuild-outdated-module.c +// RUN: wait + +//--- include/module.modulemap +module Target { + header "target.h" + textual header "expensive-header.h" + export * +} + +module SignatureExpectation { + header "signature-expectation.h" + export * +} + +//--- version1.h +// empty + +//--- version2.h +void some_func(void); + +//--- version3.h +#define TARGET_MACRO 1 + +//--- generate-expensive-header.py +num_items = 500000 +for i in range(num_items): + print(f"struct struct_{i} {{ int x; float *y; }};") + print(f"void func_{i}(int *x);") + +//--- include/signature-expectation.h +// Expensive header is used to slow down the build of SignatureExpectation module. +// Without the slow down we are able to validate and rebuild Target before another process can do it. +#include <expensive-header.h> +#include <target.h> + +//--- use-outdated-module.c +// At first load SignatureExpectation module, so it would load Target but +// reject it due to a signature mismatch. +// After this we rebuild SignatureExpectation and try to use already loaded +// Target buffer when encounter corresponding include in the source code. +#include <signature-expectation.h> + +#ifndef TARGET_MACRO +# error Macro is missing, probably using outdated Target module +#endif + +//--- rebuild-outdated-module.c +// We aim for another process to load the outdated module Target with +// the wrong signature before we rebuild it. +#include <target.h> >From 5344902cafffb92973d7a3a69f156200dcc225e0 Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai <[email protected]> Date: Mon, 19 Jan 2026 22:04:05 -0800 Subject: [PATCH 2/2] Move the test to clang-scan-deps as it will scan on multiple threads. --- ...build-session-validation-outdated-module.c | 122 ++++++++++++++++++ ...build-session-validation-outdated-module.c | 86 ------------ 2 files changed, 122 insertions(+), 86 deletions(-) create mode 100644 clang/test/ClangScanDeps/build-session-validation-outdated-module.c delete mode 100644 clang/test/Modules/build-session-validation-outdated-module.c diff --git a/clang/test/ClangScanDeps/build-session-validation-outdated-module.c b/clang/test/ClangScanDeps/build-session-validation-outdated-module.c new file mode 100644 index 0000000000000..7f2296aa4ae14 --- /dev/null +++ b/clang/test/ClangScanDeps/build-session-validation-outdated-module.c @@ -0,0 +1,122 @@ +// Test build session validation with parallel compilation for incremental builds. + +// RUN: rm -rf %t +// RUN: split-file %s %t +// Use the same command line arguments to ensure .pcm files are in the same location. +// RUN: echo "-fsyntax-only -I %/t/include" > %t/ctx.rsp +// RUN: echo "-fmodules -fmodules-cache-path=%/t/module-cache" >> %t/ctx.rsp +// RUN: echo "-fbuild-session-file=%/t/session.timestamp" >> %t/ctx.rsp +// RUN: echo "-fmodules-validate-once-per-build-session" >> %t/ctx.rsp +// +// Add a build session file to avoid errors that it's missing. Doesn't do anything as we start with a clean build. +// RUN: touch %t/session.timestamp +// Generate headers that take noticeable time to parse. The purpose is to tweak the timing, so can reproduce the error. +// RUN: %python %t/generate-expensive-header.py A 2000000 > %t/include/expensive-header.h +// RUN: %python %t/generate-expensive-header.py B 500000 > %t/include/less-expensive-header.h +// +// Create SignatureExpectation.pcm with a specific Target signature. +// RUN: cp %t/version1.h %t/include/target.h +// RUN: sed "s|DIR|%/t|g" %t/prepare-expected-signature.json.template > %t/prepare-expected-signature.json +// RUN: clang-scan-deps -compilation-database %t/prepare-expected-signature.json > /dev/null +// +// Built a different Target.pcm with a different signature. +// RUN: cp %t/version2.h %t/include/target.h +// Update the build session to rebuild Target. +// RUN: touch %t/session.timestamp +// RUN: sed "s|DIR|%/t|g" %t/create-outdated-module.json.template > %t/create-outdated-module.json +// RUN: clang-scan-deps -compilation-database %t/create-outdated-module.json > /dev/null +// +// Simulate the incremental build. +// RUN: cp %t/version3.h %t/include/target.h +// RUN: touch %t/session.timestamp +// Scan 2 files in parallel. +// RUN: sed "s|DIR|%/t|g" %t/incremental.json.template > %t/incremental.json +// RUN: clang-scan-deps -compilation-database %t/incremental.json > /dev/null + +//--- include/module.modulemap +module Target { + header "target.h" + export * +} + +module SignatureExpectation { + header "signature-expectation.h" + textual header "expensive-header.h" + export * +} + +//--- version1.h +// empty + +//--- version2.h +void some_func(void); + +//--- version3.h +void some_func(void); +#define TARGET_MACRO 1 + +//--- generate-expensive-header.py +import sys + +num_items = int(sys.argv[2]) +suffix = sys.argv[1] +for i in range(num_items): + if i == 0: + print(f"#define MACRO_{suffix}_{i} 0") + else: + print(f"#define MACRO_{suffix}_{i} MACRO_{suffix}_{i-1} + 1") + +//--- include/signature-expectation.h +// Expensive header is used to slow down the build of SignatureExpectation module. +// Without the slow down we are able to validate and rebuild Target before another thread can do it. +#include <expensive-header.h> +#include <target.h> + +//--- prepare-expected-signature.c +#include <signature-expectation.h> +//--- prepare-expected-signature.json.template +[{ + "file": "DIR/prepare-expected-signature.c", + "directory": "DIR", + "command": "clang @DIR/ctx.rsp DIR/prepare-expected-signature.c" +}] + +//--- create-outdated-module.c +#include <target.h> +//--- create-outdated-module.json.template +[{ + "file": "DIR/create-outdated-module.c", + "directory": "DIR", + "command": "clang @DIR/ctx.rsp DIR/create-outdated-module.c" +}] + +//--- use-outdated-module.c +// At first load SignatureExpectation module, so it would load Target but +// reject it due to a signature mismatch. +// After this we rebuild SignatureExpectation and try to use already loaded +// Target buffer when encounter corresponding include in the source code. +// The problem is that it corresponds to version2.h and not version3.h. +#include <signature-expectation.h> + +#ifndef TARGET_MACRO +# error Macro is missing, probably using outdated Target module +# include <missing macro> +#endif + +//--- rebuild-outdated-module.c +// We aim for another thread to load the outdated module Target with +// the wrong signature before we rebuild it. +#include <less-expensive-header.h> +#include <target.h> + +//--- incremental.json.template +[{ + "file": "DIR/use-outdated-module.c", + "directory": "DIR", + "command": "clang @DIR/ctx.rsp DIR/use-outdated-module.c" +}, +{ + "file": "DIR/rebuild-outdated-module.c", + "directory": "DIR", + "command": "clang @DIR/ctx.rsp DIR/rebuild-outdated-module.c" +}] diff --git a/clang/test/Modules/build-session-validation-outdated-module.c b/clang/test/Modules/build-session-validation-outdated-module.c deleted file mode 100644 index 693d1a8fd2cd3..0000000000000 --- a/clang/test/Modules/build-session-validation-outdated-module.c +++ /dev/null @@ -1,86 +0,0 @@ -// Test build session validation with parallel compilation for incremental builds. -// -// Shell is required for clang execution in background. -// REQUIRES: shell - -// RUN: rm -rf %t -// RUN: split-file %s %t -// Use the same command line arguments to ensure .pcm files are in the same location. -// RUN: echo "-fsyntax-only -I %/t/include" > %t/ctx.rsp -// RUN: echo "-fmodules -fmodules-cache-path=%/t/module-cache" >> %t/ctx.rsp -// RUN: echo "-fbuild-session-file=%/t/session.timestamp" >> %t/ctx.rsp -// RUN: echo "-fmodules-validate-once-per-build-session" >> %t/ctx.rsp -// RUN: echo "-Xclang -fno-modules-force-validate-user-headers" >> %t/ctx.rsp -// -// Add a build session file to avoid errors that it's missing. Doesn't do anything as we start with a clean build. -// RUN: touch %t/session.timestamp -// Generate a header that takes noticeable time to parse. -// RUN: %python %t/generate-expensive-header.py > %t/include/expensive-header.h -// -// Create SignatureExpectation.pcm with a specific Target signature. -// RUN: cp %t/version1.h %t/include/target.h -// RUN: echo "#include <signature-expectation.h>" | %clang @%t/ctx.rsp -x c - -// -// Built a different Target.pcm with a different signature. -// RUN: cp %t/version2.h %t/include/target.h -// Update the build session to rebuild Target. -// RUN: touch %t/session.timestamp -// RUN: echo "#include <target.h>" | %clang @%t/ctx.rsp -x c - -// -// Simulate the incremental build. -// RUN: cp %t/version3.h %t/include/target.h -// RUN: touch %t/session.timestamp -// RUN: sleep 1s -// Compile 2 files in parallel. -// RUN: %clang @%t/ctx.rsp %t/use-outdated-module.c & -// RUN: %clang @%t/ctx.rsp %t/rebuild-outdated-module.c -// RUN: wait - -//--- include/module.modulemap -module Target { - header "target.h" - textual header "expensive-header.h" - export * -} - -module SignatureExpectation { - header "signature-expectation.h" - export * -} - -//--- version1.h -// empty - -//--- version2.h -void some_func(void); - -//--- version3.h -#define TARGET_MACRO 1 - -//--- generate-expensive-header.py -num_items = 500000 -for i in range(num_items): - print(f"struct struct_{i} {{ int x; float *y; }};") - print(f"void func_{i}(int *x);") - -//--- include/signature-expectation.h -// Expensive header is used to slow down the build of SignatureExpectation module. -// Without the slow down we are able to validate and rebuild Target before another process can do it. -#include <expensive-header.h> -#include <target.h> - -//--- use-outdated-module.c -// At first load SignatureExpectation module, so it would load Target but -// reject it due to a signature mismatch. -// After this we rebuild SignatureExpectation and try to use already loaded -// Target buffer when encounter corresponding include in the source code. -#include <signature-expectation.h> - -#ifndef TARGET_MACRO -# error Macro is missing, probably using outdated Target module -#endif - -//--- rebuild-outdated-module.c -// We aim for another process to load the outdated module Target with -// the wrong signature before we rebuild it. -#include <target.h> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
