From 81ed4ed8c976a7208522675b4c6026bf76f485bb Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 9 May 2025 10:32:48 -0700 Subject: [PATCH 1/2] [clang][modules][deps] Implicit modules are out of date when their explicit imports are (#138920) The dependency scanner mixes implicitly- and explicitly-built modules. When an implicitly-built module imports an explicitly-built one, we never run the modification time validation checks, resulting in an out-of-date module cache. This PR fixes that by only skipping the modification time validation checks when both the imported module and its importer are built explicitly. rdar://150230022 --- clang/lib/Serialization/ModuleManager.cpp | 8 +- .../ClangScanDeps/modules-pch-common-stale.c | 178 ++++++++++++++++++ 2 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 clang/test/ClangScanDeps/modules-pch-common-stale.c diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 672dfbae7c0f5..16ee02b5b571f 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -120,8 +120,12 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, // Look for the file entry. This only fails if the expected size or // modification time differ. OptionalFileEntryRef Entry; - if (Type == MK_ExplicitModule || Type == MK_PrebuiltModule) { - // If we're not expecting to pull this file out of the module cache, it + bool IgnoreModTime = Type == MK_ExplicitModule || Type == MK_PrebuiltModule; + if (ImportedBy) + IgnoreModTime &= ImportedBy->Kind == MK_ExplicitModule || + ImportedBy->Kind == MK_PrebuiltModule; + if (IgnoreModTime) { + // If neither this file nor the importer are in the module cache, this file // might have a different mtime due to being moved across filesystems in // a distributed build. The size must still match, though. (As must the // contents, but we can't check that.) diff --git a/clang/test/ClangScanDeps/modules-pch-common-stale.c b/clang/test/ClangScanDeps/modules-pch-common-stale.c new file mode 100644 index 0000000000000..100124d9ad0b0 --- /dev/null +++ b/clang/test/ClangScanDeps/modules-pch-common-stale.c @@ -0,0 +1,178 @@ +// Test that modifications to a common header (imported from both a PCH and a TU) +// cause rebuilds of dependent modules imported from the TU on incremental build. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +//--- module.modulemap +module mod_common { header "mod_common.h" } +module mod_tu { header "mod_tu.h" } +module mod_tu_extra { header "mod_tu_extra.h" } + +//--- mod_common.h +#define MOD_COMMON_MACRO 0 +//--- mod_tu.h +#include "mod_common.h" +#if MOD_COMMON_MACRO +#include "mod_tu_extra.h" +#endif + +//--- mod_tu_extra.h + +//--- prefix.h +#include "mod_common.h" + +//--- tu.c +#include "mod_tu.h" + +// Clean: scan the PCH. +// RUN: clang-scan-deps -format experimental-full -o %t/deps_pch_clean.json -- \ +// RUN: %clang -x c-header %t/prefix.h -o %t/prefix.h.pch -F %t \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache + +// Clean: build the PCH. +// RUN: %deps-to-rsp %t/deps_pch_clean.json --module-name mod_common > %t/mod_common.rsp +// RUN: %deps-to-rsp %t/deps_pch_clean.json --tu-index 0 > %t/pch.rsp +// RUN: %clang @%t/mod_common.rsp +// RUN: %clang @%t/pch.rsp + +// Clean: scan the TU. +// RUN: clang-scan-deps -format experimental-full -o %t/deps_tu_clean.json -- \ +// RUN: %clang -c %t/tu.c -o %t/tu.o -include %t/prefix.h -F %t \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache +// RUN: cat %t/deps_tu_clean.json | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-TU-CLEAN -DPREFIX=%/t +// CHECK-TU-CLEAN: { +// CHECK-TU-CLEAN-NEXT: "modules": [ +// CHECK-TU-CLEAN-NEXT: { +// CHECK-TU-CLEAN-NEXT: "clang-module-deps": [], +// CHECK-TU-CLEAN-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-TU-CLEAN-NEXT: "command-line": [ +// CHECK-TU-CLEAN: ], +// CHECK-TU-CLEAN-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-CLEAN-NEXT: "file-deps": [ +// CHECK-TU-CLEAN-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-TU-CLEAN-NEXT: "[[PREFIX]]/mod_tu.h" +// CHECK-TU-CLEAN-NEXT: ], +// CHECK-TU-CLEAN-NEXT: "link-libraries": [], +// CHECK-TU-CLEAN-NEXT: "name": "mod_tu" +// CHECK-TU-CLEAN-NEXT: } +// CHECK-TU-CLEAN-NEXT: ], +// CHECK-TU-CLEAN-NEXT: "translation-units": [ +// CHECK-TU-CLEAN-NEXT: { +// CHECK-TU-CLEAN-NEXT: "commands": [ +// CHECK-TU-CLEAN-NEXT: { +// CHECK-TU-CLEAN-NEXT: "clang-context-hash": "{{.*}}", +// CHECK-TU-CLEAN-NEXT: "clang-module-deps": [ +// CHECK-TU-CLEAN-NEXT: { +// CHECK-TU-CLEAN-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-CLEAN-NEXT: "module-name": "mod_tu" +// CHECK-TU-CLEAN-NEXT: } +// CHECK-TU-CLEAN-NEXT: ], +// CHECK-TU-CLEAN-NEXT: "command-line": [ +// CHECK-TU-CLEAN: ], +// CHECK-TU-CLEAN-NEXT: "executable": "{{.*}}", +// CHECK-TU-CLEAN-NEXT: "file-deps": [ +// CHECK-TU-CLEAN-NEXT: "[[PREFIX]]/tu.c", +// CHECK-TU-CLEAN-NEXT: "[[PREFIX]]/prefix.h.pch" +// CHECK-TU-CLEAN-NEXT: ], +// CHECK-TU-CLEAN-NEXT: "input-file": "[[PREFIX]]/tu.c" +// CHECK-TU-CLEAN-NEXT: } +// CHECK-TU-CLEAN-NEXT: ] +// CHECK-TU-CLEAN-NEXT: } +// CHECK-TU-CLEAN: ] +// CHECK-TU-CLEAN: } + +// Clean: build the TU. +// RUN: %deps-to-rsp %t/deps_tu_clean.json --module-name mod_tu > %t/mod_tu.rsp +// RUN: %deps-to-rsp %t/deps_tu_clean.json --tu-index 0 > %t/tu.rsp +// RUN: %clang @%t/mod_tu.rsp +// RUN: %clang @%t/tu.rsp + +// Incremental: modify the common module. +// RUN: sleep 1 +// RUN: echo "#define MOD_COMMON_MACRO 1" > %t/mod_common.h + +// Incremental: scan the PCH. +// RUN: clang-scan-deps -format experimental-full -o %t/deps_pch_incremental.json -- \ +// RUN: %clang -x c-header %t/prefix.h -o %t/prefix.h.pch -F %t \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache + +// Incremental: build the PCH. +// RUN: %deps-to-rsp %t/deps_pch_incremental.json --module-name mod_common > %t/mod_common.rsp +// RUN: %deps-to-rsp %t/deps_pch_incremental.json --tu-index 0 > %t/pch.rsp +// RUN: %clang @%t/mod_common.rsp +// RUN: %clang @%t/pch.rsp + +// Incremental: scan the TU. This needs to invalidate modules imported from the +// TU that depend on modules imported from the PCH and discover the +// new dependency on 'mod_tu_extra'. +// RUN: clang-scan-deps -format experimental-full -o %t/deps_tu_incremental.json -- \ +// RUN: %clang -c %t/tu.c -o %t/tu.o -include %t/prefix.h -F %t \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache +// RUN: cat %t/deps_tu_incremental.json | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-TU-INCREMENTAL -DPREFIX=%/t +// CHECK-TU-INCREMENTAL: { +// CHECK-TU-INCREMENTAL-NEXT: "modules": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "clang-module-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "module-name": "mod_tu_extra" +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-TU-INCREMENTAL-NEXT: "command-line": [ +// CHECK-TU-INCREMENTAL: ], +// CHECK-TU-INCREMENTAL-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "file-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/mod_tu.h" +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "link-libraries": [], +// CHECK-TU-INCREMENTAL-NEXT: "name": "mod_tu" +// CHECK-TU-INCREMENTAL-NEXT: }, +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "clang-module-deps": [], +// CHECK-TU-INCREMENTAL-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-TU-INCREMENTAL-NEXT: "command-line": [ +// CHECK-TU-INCREMENTAL: ], +// CHECK-TU-INCREMENTAL-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "file-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/mod_tu_extra.h" +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "link-libraries": [], +// CHECK-TU-INCREMENTAL-NEXT: "name": "mod_tu_extra" +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "translation-units": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "commands": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "clang-context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "clang-module-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "module-name": "mod_tu" +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "command-line": [ +// CHECK-TU-INCREMENTAL: ], +// CHECK-TU-INCREMENTAL-NEXT: "executable": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "file-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/tu.c", +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/prefix.h.pch" +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "input-file": "[[PREFIX]]/tu.c" +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL-NEXT: ] +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL: ] +// CHECK-TU-INCREMENTAL: } + +// Incremental: build the TU. +// RUN: %deps-to-rsp %t/deps_tu_incremental.json --module-name mod_tu_extra > %t/mod_tu_extra.rsp +// RUN: %deps-to-rsp %t/deps_tu_incremental.json --module-name mod_tu > %t/mod_tu.rsp +// RUN: %deps-to-rsp %t/deps_tu_incremental.json --tu-index 0 > %t/tu.rsp +// RUN: %clang @%t/mod_tu_extra.rsp +// RUN: %clang @%t/mod_tu.rsp +// RUN: %clang @%t/tu.rsp From e4572669e9bc76ec649db98562eecbd09944ad2a Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Tue, 6 May 2025 13:04:35 -0700 Subject: [PATCH 2/2] [clang][deps][cas] CAS test for llvm#138920 In addition to the dependency issue described in llvm#138920, not rebuilding an implicit module when its explicitly-built dependency got out of date made us use stale include-tree of the implicitly-built module, which caused file content conflicts and the "file changed during build" error message. rdar://150230022 --- .../modules-include-tree-pch-common-stale.c | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 clang/test/ClangScanDeps/modules-include-tree-pch-common-stale.c diff --git a/clang/test/ClangScanDeps/modules-include-tree-pch-common-stale.c b/clang/test/ClangScanDeps/modules-include-tree-pch-common-stale.c new file mode 100644 index 0000000000000..041ba6814ee3e --- /dev/null +++ b/clang/test/ClangScanDeps/modules-include-tree-pch-common-stale.c @@ -0,0 +1,188 @@ +// Test that modifications to a common header (imported from both a PCH and a TU) +// cause rebuilds of dependent modules imported from the TU on incremental build. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +//--- module.modulemap +module mod_common { header "mod_common.h" } +module mod_tu { header "mod_tu.h" } +module mod_tu_extra { header "mod_tu_extra.h" } + +//--- mod_common.h +#define MOD_COMMON_MACRO 0 +//--- mod_tu.h +#include "mod_common.h" +#if MOD_COMMON_MACRO +#include "mod_tu_extra.h" +#endif + +//--- mod_tu_extra.h + +//--- prefix.h +#include "mod_common.h" + +//--- tu.c +#include "mod_tu.h" + +// Clean: scan the PCH. +// RUN: clang-scan-deps -format experimental-include-tree-full -cas-path %t/cas -o %t/deps_pch_clean.json -- \ +// RUN: %clang -x c-header %t/prefix.h -o %t/prefix.h.pch -F %t \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache + +// Clean: build the PCH. +// RUN: %deps-to-rsp %t/deps_pch_clean.json --module-name mod_common > %t/mod_common.rsp +// RUN: %deps-to-rsp %t/deps_pch_clean.json --tu-index 0 > %t/pch.rsp +// RUN: %clang @%t/mod_common.rsp +// RUN: %clang @%t/pch.rsp + +// Clean: scan the TU. +// RUN: clang-scan-deps -format experimental-include-tree-full -cas-path %t/cas -o %t/deps_tu_clean.json -- \ +// RUN: %clang -c %t/tu.c -o %t/tu.o -include %t/prefix.h -F %t \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache +// RUN: cat %t/deps_tu_clean.json | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-TU-CLEAN -DPREFIX=%/t +// CHECK-TU-CLEAN: { +// CHECK-TU-CLEAN-NEXT: "modules": [ +// CHECK-TU-CLEAN-NEXT: { +// CHECK-TU-CLEAN-NEXT: "cache-key": "llvmcas://{{.*}}", +// CHECK-TU-CLEAN-NEXT: "cas-include-tree-id": "llvmcas://{{.*}}", +// CHECK-TU-CLEAN-NEXT: "clang-module-deps": [], +// CHECK-TU-CLEAN-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-TU-CLEAN-NEXT: "command-line": [ +// CHECK-TU-CLEAN: ], +// CHECK-TU-CLEAN-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-CLEAN-NEXT: "file-deps": [ +// CHECK-TU-CLEAN-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-TU-CLEAN-NEXT: "[[PREFIX]]/mod_tu.h" +// CHECK-TU-CLEAN-NEXT: ], +// CHECK-TU-CLEAN-NEXT: "link-libraries": [], +// CHECK-TU-CLEAN-NEXT: "name": "mod_tu" +// CHECK-TU-CLEAN-NEXT: } +// CHECK-TU-CLEAN-NEXT: ], +// CHECK-TU-CLEAN-NEXT: "translation-units": [ +// CHECK-TU-CLEAN-NEXT: { +// CHECK-TU-CLEAN-NEXT: "commands": [ +// CHECK-TU-CLEAN-NEXT: { +// CHECK-TU-CLEAN-NEXT: "cache-key": "llvmcas://{{.*}}", +// CHECK-TU-CLEAN-NEXT: "cas-include-tree-id": "llvmcas://{{.*}}", +// CHECK-TU-CLEAN-NEXT: "clang-context-hash": "{{.*}}", +// CHECK-TU-CLEAN-NEXT: "clang-module-deps": [ +// CHECK-TU-CLEAN-NEXT: { +// CHECK-TU-CLEAN-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-CLEAN-NEXT: "module-name": "mod_tu" +// CHECK-TU-CLEAN-NEXT: } +// CHECK-TU-CLEAN-NEXT: ], +// CHECK-TU-CLEAN-NEXT: "command-line": [ +// CHECK-TU-CLEAN: ], +// CHECK-TU-CLEAN-NEXT: "executable": "{{.*}}", +// CHECK-TU-CLEAN-NEXT: "file-deps": [ +// CHECK-TU-CLEAN-NEXT: "[[PREFIX]]/tu.c", +// CHECK-TU-CLEAN-NEXT: "[[PREFIX]]/prefix.h.pch" +// CHECK-TU-CLEAN-NEXT: ], +// CHECK-TU-CLEAN-NEXT: "input-file": "[[PREFIX]]/tu.c" +// CHECK-TU-CLEAN-NEXT: } +// CHECK-TU-CLEAN-NEXT: ] +// CHECK-TU-CLEAN-NEXT: } +// CHECK-TU-CLEAN: ] +// CHECK-TU-CLEAN: } + +// Clean: build the TU. +// RUN: %deps-to-rsp %t/deps_tu_clean.json --module-name mod_tu > %t/mod_tu.rsp +// RUN: %deps-to-rsp %t/deps_tu_clean.json --tu-index 0 > %t/tu.rsp +// RUN: %clang @%t/mod_tu.rsp +// RUN: %clang @%t/tu.rsp + +// Incremental: modify the common module. +// RUN: sleep 1 +// RUN: echo "#define MOD_COMMON_MACRO 1" > %t/mod_common.h + +// Incremental: scan the PCH. +// RUN: clang-scan-deps -format experimental-include-tree-full -cas-path %t/cas -o %t/deps_pch_incremental.json -- \ +// RUN: %clang -x c-header %t/prefix.h -o %t/prefix.h.pch -F %t \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache + +// Incremental: build the PCH. +// RUN: %deps-to-rsp %t/deps_pch_incremental.json --module-name mod_common > %t/mod_common.rsp +// RUN: %deps-to-rsp %t/deps_pch_incremental.json --tu-index 0 > %t/pch.rsp +// RUN: %clang @%t/mod_common.rsp +// RUN: %clang @%t/pch.rsp + +// Incremental: scan the TU. This needs to invalidate modules imported from the +// TU that depend on modules imported from the PCH and discover the +// new dependency on 'mod_tu_extra'. +// RUN: clang-scan-deps -format experimental-include-tree-full -cas-path %t/cas -o %t/deps_tu_incremental.json -- \ +// RUN: %clang -c %t/tu.c -o %t/tu.o -include %t/prefix.h -F %t \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache +// RUN: cat %t/deps_tu_incremental.json | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-TU-INCREMENTAL -DPREFIX=%/t +// CHECK-TU-INCREMENTAL: { +// CHECK-TU-INCREMENTAL-NEXT: "modules": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "cache-key": "llvmcas://{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "cas-include-tree-id": "llvmcas://{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "clang-module-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "module-name": "mod_tu_extra" +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-TU-INCREMENTAL-NEXT: "command-line": [ +// CHECK-TU-INCREMENTAL: ], +// CHECK-TU-INCREMENTAL-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "file-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/mod_tu.h" +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "link-libraries": [], +// CHECK-TU-INCREMENTAL-NEXT: "name": "mod_tu" +// CHECK-TU-INCREMENTAL-NEXT: }, +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "cache-key": "llvmcas://{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "cas-include-tree-id": "llvmcas://{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "clang-module-deps": [], +// CHECK-TU-INCREMENTAL-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-TU-INCREMENTAL-NEXT: "command-line": [ +// CHECK-TU-INCREMENTAL: ], +// CHECK-TU-INCREMENTAL-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "file-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/mod_tu_extra.h" +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "link-libraries": [], +// CHECK-TU-INCREMENTAL-NEXT: "name": "mod_tu_extra" +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "translation-units": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "commands": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "cache-key": "llvmcas://{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "cas-include-tree-id": "llvmcas://{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "clang-context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "clang-module-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: { +// CHECK-TU-INCREMENTAL-NEXT: "context-hash": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "module-name": "mod_tu" +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "command-line": [ +// CHECK-TU-INCREMENTAL: ], +// CHECK-TU-INCREMENTAL-NEXT: "executable": "{{.*}}", +// CHECK-TU-INCREMENTAL-NEXT: "file-deps": [ +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/tu.c", +// CHECK-TU-INCREMENTAL-NEXT: "[[PREFIX]]/prefix.h.pch" +// CHECK-TU-INCREMENTAL-NEXT: ], +// CHECK-TU-INCREMENTAL-NEXT: "input-file": "[[PREFIX]]/tu.c" +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL-NEXT: ] +// CHECK-TU-INCREMENTAL-NEXT: } +// CHECK-TU-INCREMENTAL: ] +// CHECK-TU-INCREMENTAL: } + +// Incremental: build the TU. +// RUN: %deps-to-rsp %t/deps_tu_incremental.json --module-name mod_tu_extra > %t/mod_tu_extra.rsp +// RUN: %deps-to-rsp %t/deps_tu_incremental.json --module-name mod_tu > %t/mod_tu.rsp +// RUN: %deps-to-rsp %t/deps_tu_incremental.json --tu-index 0 > %t/tu.rsp +// RUN: %clang @%t/mod_tu_extra.rsp +// RUN: %clang @%t/mod_tu.rsp +// RUN: %clang @%t/tu.rsp