diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index b93a9dcd759eb..b2db9bab5b2b2 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -8932,6 +8932,7 @@ def fsycl_is_host : Flag<["-"], "fsycl-is-host">, // Driver CAS options. def fdepscan_EQ : Joined<["-"], "fdepscan=">, Group, + Visibility<[ClangOption, CLOption]>, HelpText<"Scan for dependencies ahead of compiling, generating a" " pruned CAS tree to send to -fcas-fs. Values are" " 'auto'," @@ -8985,6 +8986,7 @@ def fdepscan_daemon_EQ : Joined<["-"], "fdepscan-daemon=">, Group, " parent processes.">; def fdepscan_include_tree : Flag<["-"], "fdepscan-include-tree">, + Visibility<[ClangOption, CLOption]>, Group, HelpText<"Set dep-scanner to produce the include tree">; // CAS prefix map options. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 4972cc7336a4d..bf4f708e94c2b 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -6367,7 +6367,11 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, // Output to a temporary file? if ((!AtTopLevel && !isSaveTempsEnabled() && !C.getArgs().hasArg(options::OPT__SLASH_Fo)) || - CCGenDiagnostics) { + CCGenDiagnostics || + // Use a temp file for the depscan reponse file in CL mode + // (even with a /Fo flag). + (!AtTopLevel && isa(JA) && + JA.getType() == types::TY_ResponseFile && IsCLMode())) { StringRef Name = llvm::sys::path::filename(BaseInput); std::pair Split = Name.split('.'); const char *Suffix = diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 51d19958b286c..43346b4204e13 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4813,7 +4813,9 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, addDebugPrefixMapArg(D, TC, Args, CmdArgs); // Add the output path to the object file for CodeView debug infos. - if (EmitCodeView && Output.isFilename()) + // Skip this for temp depscan reponse file name. + if (EmitCodeView && Output.isFilename() && + Output.getType() != types::TY_ResponseFile) addDebugObjectName(Args, CmdArgs, DebugCompilationDir, Output.getFilename()); } diff --git a/clang/test/ClangScanDeps/cas-case-sensitivity.c b/clang/test/ClangScanDeps/cas-case-sensitivity.c index 68915d62bfc82..d4d426478e3f4 100644 --- a/clang/test/ClangScanDeps/cas-case-sensitivity.c +++ b/clang/test/ClangScanDeps/cas-case-sensitivity.c @@ -10,14 +10,14 @@ // RUN: sed -e 's/^.*llvmcas/llvmcas/' -e 's/ for.*$//' %t/result1.txt > %t/casid1 // RUN: sed -e 's/^.*llvmcas/llvmcas/' -e 's/ for.*$//' %t/result2.txt > %t/casid2 -// RUN: llvm-cas --cas %t/cas --ls-tree-recursive @%t/casid1 | FileCheck -check-prefix=TREE %s -DPREFIX=%/t -// RUN: llvm-cas --cas %t/cas --ls-tree-recursive @%t/casid2 | FileCheck -check-prefix=TREE %s -DPREFIX=%/t +// RUN: llvm-cas --cas %t/cas --ls-tree-recursive @%t/casid1 | FileCheck -check-prefix=TREE %s -DPREFIX=%{t-tree-/} +// RUN: llvm-cas --cas %t/cas --ls-tree-recursive @%t/casid2 | FileCheck -check-prefix=TREE %s -DPREFIX=%{t-tree-/} // asdf: FileCheck -check-prefix=TREE %s -input-file %t/result1.txt -DPREFIX=%/t -// TREE: file llvmcas://{{.*}} [[PREFIX]]/Header.h -// TREE: syml llvmcas://{{.*}} [[PREFIX]]/header.h -> Header -// TREE: file llvmcas://{{.*}} [[PREFIX]]/t{{[12]}}.c +// TREE: file llvmcas://{{.*}} [[PREFIX]]{{/|\\}}Header.h +// TREE: syml llvmcas://{{.*}} [[PREFIX]]{{/|\\}}header.h -> Header +// TREE: file llvmcas://{{.*}} [[PREFIX]]{{/|\\}}t{{[12]}}.c //--- cdb1.json.template [ diff --git a/clang/test/ClangScanDeps/cas-clang-cl.c b/clang/test/ClangScanDeps/cas-clang-cl.c new file mode 100644 index 0000000000000..b7e2ffae4603e --- /dev/null +++ b/clang/test/ClangScanDeps/cas-clang-cl.c @@ -0,0 +1,17 @@ +// REQUIRES: ondisk_cas + +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %clang_cl -c /clang:-fdepscan=inline /clang:-fdepscan-include-tree -Xclang -fcas-path -Xclang %t/cas -Xclang -Rcompile-job-cache -- %t/test.c 2>&1 | FileCheck %s -check-prefix=CACHE-MISS +// RUN: %clang_cl -c /clang:-fdepscan=inline /clang:-fdepscan-include-tree -Xclang -fcas-path -Xclang %t/cas -Xclang -Rcompile-job-cache -- %t/test.c 2>&1 | FileCheck %s -check-prefix=CACHE-HIT + +// In debug mode +// RUN: %clang_cl -c /clang:-fdepscan=inline /clang:-fdepscan-include-tree -Xclang -fcas-path -Xclang %t/cas -Xclang -Rcompile-job-cache /Z7 -- %t/test.c 2>&1 | FileCheck %s -check-prefix=CACHE-MISS +// RUN: %clang_cl -c /clang:-fdepscan=inline /clang:-fdepscan-include-tree -Xclang -fcas-path -Xclang %t/cas -Xclang -Rcompile-job-cache /Z7 -- %t/test.c 2>&1 | FileCheck %s -check-prefix=CACHE-HIT + +// CACHE-HIT: remark: compile job cache hit +// CACHE-MISS: remark: compile job cache miss + +//--- test.c +int main() { return 0; } diff --git a/clang/test/ClangScanDeps/cas-fs-multiple-commands.c b/clang/test/ClangScanDeps/cas-fs-multiple-commands.c index 28bf3857cf334..c03ba69384e6d 100644 --- a/clang/test/ClangScanDeps/cas-fs-multiple-commands.c +++ b/clang/test/ClangScanDeps/cas-fs-multiple-commands.c @@ -19,7 +19,7 @@ // RUN: cat %t/deps.0.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t -// RUN: CLANG_CACHE_USE_CASFS_DEPSCAN=1 c-index-test core -scan-deps -working-dir %t -cas-path %t/cas -output-dir %t/modules -- \ +// RUN: env CLANG_CACHE_USE_CASFS_DEPSCAN=1 c-index-test core -scan-deps -working-dir %t -cas-path %t/cas -output-dir %t/modules -- \ // RUN: %clang -target x86_64-apple-darwin -c %t/tu.c -save-temps=obj -o %t/tu.o \ // RUN: -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ // RUN: > %t/deps.txt diff --git a/clang/test/ClangScanDeps/cas-fs-prefix-mapping.c b/clang/test/ClangScanDeps/cas-fs-prefix-mapping.c index 3f3c6dfbe6857..134032e050271 100644 --- a/clang/test/ClangScanDeps/cas-fs-prefix-mapping.c +++ b/clang/test/ClangScanDeps/cas-fs-prefix-mapping.c @@ -4,21 +4,21 @@ // REQUIRES: ondisk_cas // RUN: rm -rf %t // RUN: split-file %s %t -// RUN: sed -e "s|DIR|%t|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb.json.template > %t/cdb.json +// RUN: sed -e "s|DIR|%/t|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb.json.template > %t/cdb.json // == Tree // Ensure the filesystem has the mapped paths. // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-tree -cas-path %t/cas \ -// RUN: -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: | sed -E 's/tree ([^ ]+) for.*/\1/' > %t/tree_id.txt // RUN: llvm-cas -cas %t/cas -ls-tree-recursive @%t/tree_id.txt > %t/tree_result.txt -// RUN: FileCheck %s -input-file %t/tree_result.txt -check-prefix=FILES +// RUN: FileCheck %s -input-file %t/tree_result.txt -DROOT=%{/roott} -check-prefix=FILES -// FILES: file llvmcas://{{.*}} /^sdk/usr/include/stdlib.h -// FILES: file llvmcas://{{.*}} /^src/t.c -// FILES: file llvmcas://{{.*}} /^src/top.h -// FILES: file llvmcas://{{.*}} /^tc/lib/clang/{{.*}}/include/stdarg.h +// FILES: file llvmcas://{{.*}} [[ROOT]]^sdk/usr/include/stdlib.h +// FILES: file llvmcas://{{.*}} [[ROOT]]^src/t.c +// FILES: file llvmcas://{{.*}} [[ROOT]]^src/top.h +// FILES: file llvmcas://{{.*}} [[ROOT]]^tc/lib/clang/{{.*}}/include/stdarg.h // == Full Tree // This should have the same filesystem as above, and we also check the command- @@ -26,18 +26,18 @@ // RUN: cat %t/tree_id.txt > %t/full_tree_result.txt // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-tree-full -cas-path %t/cas \ -// RUN: -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: >> %t/full_tree_result.txt -// RUN: FileCheck %s -input-file %t/full_tree_result.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK +// RUN: cat %t/full_tree_result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize SDK_PREFIX=%/S/Inputs/SDK --sanitize ROOT^=%/root^ --enable-yaml-compatibility %s // == Full // Same as full tree. // RUN: cat %t/tree_id.txt > %t/full_result.txt // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -cas-path %t/cas \ -// RUN: -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: >> %t/full_result.txt -// RUN: FileCheck %s -input-file %t/full_result.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK +// RUN: cat %t/full_result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize SDK_PREFIX=%/S/Inputs/SDK --sanitize ROOT^=%/root^ --enable-yaml-compatibility %s // CHECK: [[MAPPED_FS_ID:llvmcas://[[:xdigit:]]+]] // CHECK: "modules": [] @@ -49,36 +49,36 @@ // CHECK: "clang-module-deps": [] // CHECK: "command-line": [ // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[MAPPED_FS_ID]]" // CHECK: "-fcas-fs-working-directory" -// CHECK-NEXT: "/^src" +// CHECK-NEXT: "ROOT^src" // CHECK: "-x" // CHECK-NEXT: "c" -// CHECK-NEXT: "/^src/t.c" +// CHECK-NEXT: "ROOT^src{{/|\\\\}}t.c" // CHECK: "-isysroot" -// CHECK-NEXT: "/^sdk" +// CHECK-NEXT: "ROOT^sdk" // CHECK: "-resource-dir" -// CHECK-NEXT: "/^tc/lib/clang/{{.*}}" +// CHECK-NEXT: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" // CHECK: "-isystem" -// CHECK-NEXT: "/^sdk/usr/local/include +// CHECK-NEXT: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}local{{/|\\\\}}include // CHECK: "-isystem" -// CHECK-NEXT: "/^tc/lib/clang/{{.*}}/include" +// CHECK-NEXT: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}{{/|\\\\}}include" // CHECK: "-internal-externc-isystem" -// CHECK-NEXT: "/^sdk/usr/include" -// CHECK: "-fdebug-compilation-dir=/^src" -// CHECK: "-fcoverage-compilation-dir=/^src" -// CHECK-NOT: [[PREFIX]] -// CHECK-NOT: [[SDK_PREFIX]] +// CHECK-NEXT: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}include" +// CHECK: "-fdebug-compilation-dir=ROOT^src" +// CHECK: "-fcoverage-compilation-dir=ROOT^src" +// CHECK-NOT: PREFIX +// CHECK-NOT: SDK_PREFIX // CHECK: ] // CHECK: "file-deps": [ -// CHECK: "[[PREFIX]]/t.c" -// CHECK: "[[PREFIX]]/top.h" -// CHECK: "{{.*}}include/stdarg.h" -// CHECK: "[[SDK_PREFIX]]/usr/include/stdlib.h" +// CHECK: "PREFIX{{/|\\\\}}t.c" +// CHECK: "PREFIX{{/|\\\\}}top.h" +// CHECK: "{{.*}}include{{/|\\\\}}stdarg.h" +// CHECK: "SDK_PREFIX{{/|\\\\}}usr{{/|\\\\}}include{{/|\\\\}}stdlib.h" // CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/t.c" +// CHECK: "input-file": "PREFIX{{/|\\\\}}t.c" //--- cdb.json.template [ diff --git a/clang/test/ClangScanDeps/cas-trees.c b/clang/test/ClangScanDeps/cas-trees.c index 8c5af789f4fc5..b49893623a670 100644 --- a/clang/test/ClangScanDeps/cas-trees.c +++ b/clang/test/ClangScanDeps/cas-trees.c @@ -6,13 +6,13 @@ // RUN: clang-scan-deps -compilation-database %t/cdb.json -cas-path %t/cas -format experimental-tree -mode preprocess-dependency-directives > %t/result1.txt // RUN: clang-scan-deps -compilation-database %t/cdb.json -cas-path %t/cas -format experimental-tree -mode preprocess > %t/result2.txt // RUN: diff -u %t/result1.txt %t/result2.txt -// RUN: FileCheck %s -input-file %t/result1.txt -DPREFIX=%/t +// RUN: cat %t/result1.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t %s -// CHECK: tree {{.*}} for '[[PREFIX]]/t1.c' -// CHECK-NEXT: tree {{.*}} for '[[PREFIX]]/t2.c' +// CHECK: tree {{.*}} for 'PREFIX{{/|\\}}t1.c' +// CHECK-NEXT: tree {{.*}} for 'PREFIX{{/|\\}}t2.c' // RUN: clang-scan-deps -compilation-database %t/cdb.json -cas-path %t/cas -format experimental-tree-full -mode preprocess > %t/full_result.json -// RUN: cat %t/full_result.json | FileCheck %s -DPREFIX=%/t --check-prefix=FULL-TREE +// RUN: cat %t/full_result.json | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s --check-prefix=FULL-TREE // FULL-TREE: { // FULL-TREE-NEXT: "modules": [], @@ -24,17 +24,17 @@ // FULL-TREE-NEXT: "clang-module-deps": [], // FULL-TREE-NEXT: "command-line": [ // FULL-TREE: "-fcas-path" -// FULL-TREE-NEXT: "[[PREFIX]]{{.}}cas" +// FULL-TREE-NEXT: "PREFIX{{/|\\\\}}cas" // FULL-TREE: "-fcas-fs" // FULL-TREE-NEXT: "[[T1_ROOT_ID]]" // FULL-TREE: "-fcache-compile-job" // FULL-TREE: ], // FULL-TREE: "file-deps": [ -// FULL-TREE-NEXT: "[[PREFIX]]/t1.c", -// FULL-TREE-NEXT: "[[PREFIX]]/top.h", -// FULL-TREE-NEXT: "[[PREFIX]]/n1.h" +// FULL-TREE-NEXT: "PREFIX{{/|\\\\}}t1.c", +// FULL-TREE-NEXT: "PREFIX{{/|\\\\}}top.h", +// FULL-TREE-NEXT: "PREFIX{{/|\\\\}}n1.h" // FULL-TREE-NEXT: ], -// FULL-TREE-NEXT: "input-file": "[[PREFIX]]/t1.c" +// FULL-TREE-NEXT: "input-file": "PREFIX{{/|\\\\}}t1.c" // FULL-TREE-NEXT: } // FULL-TREE: { // FULL-TREE: "cache-key": "[[T2_CACHE_KEY:llvmcas://[[:xdigit:]]+]]" @@ -43,16 +43,16 @@ // FULL-TREE-NEXT: "clang-module-deps": [], // FULL-TREE-NEXT: "command-line": [ // FULL-TREE: "-fcas-path" -// FULL-TREE-NEXT: "[[PREFIX]]{{.}}cas" +// FULL-TREE-NEXT: "PREFIX{{/|\\\\}}cas" // FULL-TREE: "-fcas-fs" // FULL-TREE-NEXT: "[[T2_ROOT_ID]]" // FULL-TREE: "-fcache-compile-job" // FULL-TREE: ], // FULL-TREE: "file-deps": [ -// FULL-TREE-NEXT: "[[PREFIX]]/t2.c", -// FULL-TREE-NEXT: "[[PREFIX]]/n1.h" +// FULL-TREE-NEXT: "PREFIX{{/|\\\\}}t2.c", +// FULL-TREE-NEXT: "PREFIX{{/|\\\\}}n1.h" // FULL-TREE-NEXT: ], -// FULL-TREE-NEXT: "input-file": "[[PREFIX]]/t2.c" +// FULL-TREE-NEXT: "input-file": "PREFIX{{/|\\\\}}t2.c" // FULL-TREE-NEXT: } // Build with caching @@ -83,20 +83,20 @@ // COMBINED: remark: compile job cache miss for '[[T1_CACHE_KEY]]' // COMBINED-NEXT: remark: compile job cache miss for '[[T2_CACHE_KEY]]' -// RUN: clang-scan-deps -compilation-database %t/cdb.json -cas-path %t/cas -format experimental-tree -emit-cas-compdb | FileCheck %s -DPREFIX=%/t -DCLANG=%clang -check-prefix=COMPDB +// RUN: clang-scan-deps -compilation-database %t/cdb.json -cas-path %t/cas -format experimental-tree -emit-cas-compdb | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize CLANG=%/clang --enable-yaml-compatibility %s -check-prefix=COMPDB // COMPDB: [ // COMPDB: { -// COMPDB: "file": "[[PREFIX]]/t1.c", -// COMPDB: "directory": "[[PREFIX]]", +// COMPDB: "file": "PREFIX{{/|\\\\}}t1.c", +// COMPDB: "directory": "PREFIX", // COMPDB: "arguments": [ -// COMPDB: "[[CLANG]]", +// COMPDB: "CLANG", // COMPDB: "-cc1", // COMPDB: "-fcas-path", -// COMPDB: "[[PREFIX]]/cas", +// COMPDB: "PREFIX{{/|\\\\}}cas", // COMPDB: "-fcas-fs", // COMPDB: { -// COMPDB: "file": "[[PREFIX]]/t2.c", -// COMPDB: "directory": "[[PREFIX]]", +// COMPDB: "file": "PREFIX{{/|\\\\}}t2.c", +// COMPDB: "directory": "PREFIX", // COMPDB: "arguments": [ diff --git a/clang/test/ClangScanDeps/include-tree-prefix-mapping-pch-remap.c b/clang/test/ClangScanDeps/include-tree-prefix-mapping-pch-remap.c index 8c379ef60014d..d117fa5ffadf2 100644 --- a/clang/test/ClangScanDeps/include-tree-prefix-mapping-pch-remap.c +++ b/clang/test/ClangScanDeps/include-tree-prefix-mapping-pch-remap.c @@ -1,11 +1,11 @@ // REQUIRES: ondisk_cas // RUN: rm -rf %t // RUN: split-file %s %t -// RUN: sed -e "s|DIR|%t|g" %t/cdb.json.template > %t/cdb.json +// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json // RUN: clang-scan-deps -compilation-database %t/cdb.json \ // RUN: -format experimental-include-tree-full -cas-path %t/cas \ -// RUN: -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc > %t/deps.json +// RUN: -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc > %t/deps.json //--- cdb.json.template [{ diff --git a/clang/test/ClangScanDeps/include-tree-prefix-mapping.c b/clang/test/ClangScanDeps/include-tree-prefix-mapping.c index e0842a7be6b98..a61c9e00b94be 100644 --- a/clang/test/ClangScanDeps/include-tree-prefix-mapping.c +++ b/clang/test/ClangScanDeps/include-tree-prefix-mapping.c @@ -1,33 +1,33 @@ // REQUIRES: ondisk_cas // RUN: rm -rf %t // RUN: split-file %s %t -// RUN: sed -e "s|DIR|%t|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb.json.template > %t/cdb.json +// RUN: sed -e "s|DIR|%/t|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb.json.template > %t/cdb.json // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-include-tree -cas-path %t/cas \ -// RUN: -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc > %t/result.txt -// RUN: FileCheck %s -input-file %t/result.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK +// RUN: -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc > %t/result.txt +// RUN: cat %t/result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize SDK_PREFIX=%/S/Inputs/SDK --sanitize ROOT^=%/root^ %s -// CHECK: {{.*}} - [[PREFIX]]/t.c -// CHECK-NOT: [[PREFIX]] -// CHECK-NOT: [[SDK_PREFIX]] -// CHECK: /^src{{[/\\]}}t.c -// CHECK: /^src{{[/\\]}}top.h -// CHECK: /^tc{{[/\\]}}lib{{[/\\]}}clang{{[/\\]}}{{.*}}{{[/\\]}}include{{[/\\]}}stdarg.h -// CHECK: /^sdk{{[/\\]}}usr{{[/\\]}}include{{[/\\]}}stdlib.h +// CHECK: {{.*}} - PREFIX{{/|\\}}t.c +// CHECK-NOT: PREFIX +// CHECK-NOT: SDK_PREFIX +// CHECK: ROOT^src{{[/\\]}}t.c +// CHECK: ROOT^src{{[/\\]}}top.h +// CHECK: ROOT^tc{{[/\\]}}lib{{[/\\]}}clang{{[/\\]}}{{.*}}{{[/\\]}}include{{[/\\]}}stdarg.h +// CHECK: ROOT^sdk{{[/\\]}}usr{{[/\\]}}include{{[/\\]}}stdlib.h // RUN: clang-scan-deps -compilation-database %t/cdb.json \ // RUN: -format experimental-include-tree-full -cas-path %t/cas \ -// RUN: -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc > %t/deps.json +// RUN: -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc > %t/deps.json // RUN: cat %t/result.txt > %t/full.txt // RUN: echo "FULL DEPS START" >> %t/full.txt -// RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' >> %t/full.txt +// RUN: cat %t/deps.json >> %t/full.txt -// RUN: FileCheck %s -DPREFIX=%/t -DSDK_PREFIX=%S/Inputs/SDK -check-prefix=FULL -input-file %t/full.txt +// RUN: cat %t/full.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize SDK_PREFIX=%/S/Inputs/SDK --sanitize ROOT^=%/root^ --enable-yaml-compatibility %s -check-prefix=FULL // Capture the tree id from experimental-include-tree ; ensure that it matches // the result from experimental-full. -// FULL: [[TREE_ID:llvmcas://[[:xdigit:]]+]] - [[PREFIX]]/t.c +// FULL: [[TREE_ID:llvmcas://[[:xdigit:]]+]] - PREFIX{{/|\\}}t.c // FULL: FULL DEPS START // FULL-NEXT: { @@ -40,7 +40,7 @@ // FULL: "command-line": [ // FULL-NEXT: "-cc1" // FULL: "-fcas-path" -// FULL-NEXT: "[[PREFIX]]/cas" +// FULL-NEXT: "PREFIX{{/|\\\\}}cas" // FULL: "-disable-free" // FULL: "-fcas-include-tree" // FULL-NEXT: "[[TREE_ID]]" @@ -49,15 +49,15 @@ // FULL: "-x" // FULL-NEXT: "c" // FULL: "-isysroot" -// FULL-NEXT: "/^sdk" +// FULL-NEXT: "ROOT^sdk" // FULL: ] // FULL: "file-deps": [ -// FULL-DAG: "[[PREFIX]]/t.c" -// FULL-DAG: "[[PREFIX]]/top.h" -// FULL-DAG: "{{.*}}/stdarg.h" -// FULL-DAG: "[[SDK_PREFIX]]/usr/include/stdlib.h" +// FULL-DAG: "PREFIX{{/|\\\\}}t.c" +// FULL-DAG: "PREFIX{{/|\\\\}}top.h" +// FULL-DAG: "{{.*}}{{/|\\\\}}stdarg.h" +// FULL-DAG: "SDK_PREFIX{{/|\\\\}}usr{{/|\\\\}}include{{/|\\\\}}stdlib.h" // FULL: ] -// FULL: "input-file": "[[PREFIX]]/t.c" +// FULL: "input-file": "PREFIX{{/|\\\\}}t.c" // FULL: } // FULL: ] // FULL: } diff --git a/clang/test/ClangScanDeps/include-tree-preserve-pch-path.c b/clang/test/ClangScanDeps/include-tree-preserve-pch-path.c index c9331dea2dc51..3ef420105bbd5 100644 --- a/clang/test/ClangScanDeps/include-tree-preserve-pch-path.c +++ b/clang/test/ClangScanDeps/include-tree-preserve-pch-path.c @@ -20,7 +20,7 @@ // RUN: %deps-to-rsp %t/deps_tu.json --tu-index 0 > %t/tu.rsp // RUN: %clang @%t/tu.rsp -// RUN: cat %t/tu.ll | FileCheck %s -check-prefix=LLVMIR -DPREFIX=%/t +// RUN: cat %t/tu.ll | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s -check-prefix=LLVMIR // LLVMIR: !DICompileUnit({{.*}}, splitDebugFilename: "prefix.pch" // Extract include-tree casid diff --git a/clang/test/ClangScanDeps/include-tree-with-pch.c b/clang/test/ClangScanDeps/include-tree-with-pch.c index 1c6d0e2791b7e..f056a13ed4b8d 100644 --- a/clang/test/ClangScanDeps/include-tree-with-pch.c +++ b/clang/test/ClangScanDeps/include-tree-with-pch.c @@ -5,33 +5,33 @@ // RUN: %clang -x c-header %t/prefix.h -target x86_64-apple-macos12 -o %t/prefix.pch -fdepscan=inline -fdepscan-include-tree -Xclang -fcas-path -Xclang %t/cas // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-include-tree -cas-path %t/cas > %t/result.txt -// RUN: FileCheck %s -input-file %t/result.txt -DPREFIX=%/t +// RUN: cat %t/result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t %s -// CHECK: {{.*}} - [[PREFIX]]/t.c +// CHECK: {{.*}} - PREFIX{{/|\\}}t.c // CHECK-NEXT: (PCH) -// CHECK-NEXT: [[PREFIX]]/t.c +// CHECK-NEXT: PREFIX{{/|\\}}t.c // CHECK-NEXT: 1:1 -// CHECK-NEXT: [[PREFIX]]/t.h +// CHECK-NEXT: PREFIX{{/|\\}}t.h // CHECK-NEXT: Files: -// CHECK-NEXT: [[PREFIX]]/t.c -// CHECK-NEXT: [[PREFIX]]/t.h -// CHECK-NEXT: [[PREFIX]]/prefix.h -// CHECK-NEXT: [[PREFIX]]/n1.h -// CHECK-NEXT: [[PREFIX]]/n2.h -// CHECK-NEXT: [[PREFIX]]/n3.h -// CHECK-NOT: [[PREFIX]] +// CHECK-NEXT: PREFIX{{/|\\}}t.c +// CHECK-NEXT: PREFIX{{/|\\}}t.h +// CHECK-NEXT: PREFIX{{/|\\}}prefix.h +// CHECK-NEXT: PREFIX{{/|\\}}n1.h +// CHECK-NEXT: PREFIX{{/|\\}}n2.h +// CHECK-NEXT: PREFIX{{/|\\}}n3.h +// CHECK-NOT: PREFIX // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-include-tree-full -cas-path %t/cas > %t/deps.json // RUN: cat %t/result.txt > %t/full.txt // RUN: echo "FULL DEPS START" >> %t/full.txt -// RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' >> %t/full.txt +// RUN: cat %t/deps.json >> %t/full.txt -// RUN: FileCheck %s -DPREFIX=%/t -DCLANG=%clang -check-prefix=FULL -input-file %t/full.txt +// RUN: cat %t/full.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize CLANG=%/clang --enable-yaml-compatibility -check-prefix=FULL %s // Capture the tree id from experimental-include-tree ; ensure that it matches // the result from experimental-full. -// FULL: [[TREE_ID:llvmcas://[[:xdigit:]]+]] - [[PREFIX]]/t.c +// FULL: [[TREE_ID:llvmcas://[[:xdigit:]]+]] - PREFIX{{/|\\}}t.c // FULL: FULL DEPS START // FULL-NEXT: { @@ -44,7 +44,7 @@ // FULL: "command-line": [ // FULL-NEXT: "-cc1" // FULL: "-fcas-path" -// FULL-NEXT: "[[PREFIX]]/cas" +// FULL-NEXT: "PREFIX{{/|\\\\}}cas" // FULL: "-disable-free" // FULL: "-fcas-include-tree" // FULL-NEXT: "[[TREE_ID]]" @@ -57,13 +57,13 @@ // FULL-NEXT: "t.c" // FULL-NOT: "t.c" // FULL: ] -// FULL: "executable": "[[CLANG]]" +// FULL: "executable": "CLANG" // FULL: "file-deps": [ -// FULL-NEXT: "[[PREFIX]]/t.c" -// FULL-NEXT: "[[PREFIX]]/t.h" -// FULL-NEXT: "[[PREFIX]]/prefix.pch" +// FULL-NEXT: "PREFIX{{/|\\\\}}t.c" +// FULL-NEXT: "PREFIX{{/|\\\\}}t.h" +// FULL-NEXT: "PREFIX{{/|\\\\}}prefix.pch" // FULL-NEXT: ] -// FULL: "input-file": "[[PREFIX]]/t.c" +// FULL: "input-file": "PREFIX{{/|\\\\}}t.c" // FULL: } // FULL: ] // FULL: } diff --git a/clang/test/ClangScanDeps/include-tree-working-directory.c b/clang/test/ClangScanDeps/include-tree-working-directory.c index 9da7f609c9ce3..8630ce5f184d5 100644 --- a/clang/test/ClangScanDeps/include-tree-working-directory.c +++ b/clang/test/ClangScanDeps/include-tree-working-directory.c @@ -20,18 +20,18 @@ // CACHE-HIT: remark: compile job cache hit // RUN: cat %t/tu.rsp | sed -E 's|.*"-fcas-include-tree" "(llvmcas://[[:xdigit:]]+)".*|\1|' > %t/tu.casid -// RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/tu.casid | FileCheck %s -DPREFIX=%/t +// RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/tu.casid | %PathSanitizingFileCheck --sanitize PREFIX=%/t %s -// CHECK: [[PREFIX]]/t.c llvmcas:// +// CHECK: PREFIX{{/|\\}}t.c llvmcas:// // CHECK: 1:1 llvmcas:// -// CHECK: 2:1 [[PREFIX]]/relative/h1.h llvmcas:// +// CHECK: 2:1 PREFIX{{/|\\}}relative{{/|\\}}h1.h llvmcas:// // CHECK: Files: -// CHECK: [[PREFIX]]/t.c llvmcas:// -// CHECK: [[PREFIX]]/relative/h1.h llvmcas:// +// CHECK: PREFIX{{/|\\}}t.c llvmcas:// +// CHECK: PREFIX{{/|\\}}relative{{/|\\}}h1.h llvmcas:// /// Using a different working directory should cache hit as well. /// FIXME: Working directory affects some codegen options added by clang driver, preserve them to make sure the cache hit. -// RUN: sed -e "s|DIR|%/t|g" %t/cdb2.json.template > %t/cdb2.json +// RUN: sed -e "s|DIR|%/t|g" %t/cdb2.json.template | sed -e "s|SEP|%{fs-sep-yaml}|g" > %t/cdb2.json // RUN: clang-scan-deps -compilation-database %t/cdb2.json -format experimental-include-tree-full -cas-path %t/cas \ // RUN: > %t/deps2.json // RUN: %deps-to-rsp %t/deps2.json --tu-index 0 > %t/tu2.rsp @@ -48,7 +48,7 @@ //--- cdb2.json.template [{ "directory": "DIR/other", - "command": "clang -c DIR/t.c -I DIR/relative -working-directory DIR/other -o DIR/t2.o -MD -serialize-diagnostics DIR/t2.dia -fdebug-compilation-dir=DIR -fcoverage-compilation-dir=DIR", + "command": "clang -c DIRSEPt.c -I DIRSEPrelative -working-directory DIR/other -o DIR/t2.o -MD -serialize-diagnostics DIR/t2.dia -fdebug-compilation-dir=DIR -fcoverage-compilation-dir=DIR", "file": "DIR/t.c" }] diff --git a/clang/test/ClangScanDeps/include-tree.c b/clang/test/ClangScanDeps/include-tree.c index 29c64fa5f9edc..5d9fbf8d06926 100644 --- a/clang/test/ClangScanDeps/include-tree.c +++ b/clang/test/ClangScanDeps/include-tree.c @@ -12,21 +12,21 @@ // Make sure order is as expected. // RUN: FileCheck %s -input-file %t/result1.txt -DPREFIX=%/t -check-prefix ORDER -// ORDER: {{.*}} - [[PREFIX]]/t.c -// ORDER-NEXT: [[PREFIX]]/t.c +// ORDER: {{.*}} - [[PREFIX]]{{[/\\]}}t.c +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}t.c // ORDER-NEXT: 1:1 -// ORDER-NEXT: [[PREFIX]]/top.h -// ORDER-NEXT: [[PREFIX]]/n1.h -// ORDER-NEXT: [[PREFIX]]/n2.h -// ORDER-NEXT: [[PREFIX]]/n3.h -// ORDER-NEXT: [[PREFIX]]/n3.h -// ORDER-NEXT: [[PREFIX]]/n2.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}top.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}n1.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}n2.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}n3.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}n3.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}n2.h // ORDER-NEXT: Files: -// ORDER-NEXT: [[PREFIX]]/t.c -// ORDER-NEXT: [[PREFIX]]/top.h -// ORDER-NEXT: [[PREFIX]]/n1.h -// ORDER-NEXT: [[PREFIX]]/n2.h -// ORDER-NEXT: [[PREFIX]]/n3.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}t.c +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}top.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}n1.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}n2.h +// ORDER-NEXT: [[PREFIX]]{{[/\\]}}n3.h // ORDER-NOT: [[PREFIX]] // Full dependency output @@ -34,13 +34,13 @@ // RUN: cat %t/result1.txt > %t/full.txt // RUN: echo "FULL DEPS START" >> %t/full.txt -// RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' >> %t/full.txt +// RUN: cat %t/deps.json >> %t/full.txt -// RUN: FileCheck %s -DPREFIX=%/t -DCLANG=%clang -check-prefix=FULL -input-file %t/full.txt +// RUN: cat %t/full.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize CLANG=%/clang --enable-yaml-compatibility %s -check-prefix=FULL // Capture the tree id from experimental-include-tree ; ensure that it matches // the result from experimental-full. -// FULL: [[TREE_ID:llvmcas://[[:xdigit:]]+]] - [[PREFIX]]/t.c +// FULL: [[TREE_ID:llvmcas://[[:xdigit:]]+]] - PREFIX{{/|\\}}t.c // FULL: FULL DEPS START // FULL-NEXT: { @@ -54,7 +54,7 @@ // FULL: "command-line": [ // FULL-NEXT: "-cc1" // FULL: "-fcas-path" -// FULL-NEXT: "[[PREFIX]]/cas" +// FULL-NEXT: "PREFIX{{/|\\\\}}cas" // FULL: "-disable-free" // FULL: "-fcas-include-tree" // FULL-NEXT: "[[TREE_ID]]" @@ -67,17 +67,17 @@ // FULL-NEXT: "t.c" // FULL-NOT: "t.c" // FULL: ] -// FULL: "executable": "[[CLANG]]" +// FULL: "executable": "CLANG", // FULL: "file-deps": [ -// FULL-NEXT: "[[PREFIX]]/t.c" -// FULL-NEXT: "[[PREFIX]]/top.h" -// FULL-NEXT: "[[PREFIX]]/n1.h" -// FULL-NEXT: "[[PREFIX]]/n2.h" -// FULL-NEXT: "[[PREFIX]]/n3.h" -// FULL-NEXT: "[[PREFIX]]/n3.h" -// FULL-NEXT: "[[PREFIX]]/n2.h" +// FULL-NEXT: "PREFIX{{/|\\\\}}t.c" +// FULL-NEXT: "PREFIX{{/|\\\\}}top.h" +// FULL-NEXT: "PREFIX{{/|\\\\}}n1.h" +// FULL-NEXT: "PREFIX{{/|\\\\}}n2.h" +// FULL-NEXT: "PREFIX{{/|\\\\}}n3.h" +// FULL-NEXT: "PREFIX{{/|\\\\}}n3.h" +// FULL-NEXT: "PREFIX{{/|\\\\}}n2.h" // FULL-NEXT: ] -// FULL: "input-file": "[[PREFIX]]/t.c" +// FULL: "input-file": "PREFIX{{/|\\\\}}t.c" // FULL: } // FULL: ] // FULL: } @@ -110,16 +110,16 @@ //--- t.c #include "top.h" // this is top -// CHECK: [[@LINE]]:1 [[PREFIX]]/top.h +// CHECK: [[@LINE]]:1 [[PREFIX]]{{[/\\]}}top.h // Skipped because of macro guard. #include "n1.h" #include "n3.h" -// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]/n3.h +// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]{{[/\\]}}n3.h #include "n2.h" -// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]/n2.h +// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]{{[/\\]}}n2.h //--- top.h #ifndef _TOP_H_ @@ -131,10 +131,10 @@ typedef int MyT; #define WHATEVER 1 #include "n1.h" -// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]/n1.h +// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]{{[/\\]}}n1.h #include "n3.h" -// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]/n3.h +// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]{{[/\\]}}n3.h #define ANOTHER 2 @@ -149,7 +149,7 @@ struct S { int x1; #include "n2.h" -// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]/n2.h +// CHECK-DAG: [[@LINE]]:1 [[PREFIX]]{{[/\\]}}n2.h int x2; diff --git a/clang/test/ClangScanDeps/modules-cas-context-hash.c b/clang/test/ClangScanDeps/modules-cas-context-hash.c index b80709d5acda1..3ff42bbe08743 100644 --- a/clang/test/ClangScanDeps/modules-cas-context-hash.c +++ b/clang/test/ClangScanDeps/modules-cas-context-hash.c @@ -12,7 +12,7 @@ // RUN: -cas-path %t/cas2 -format experimental-include-tree-full \ // RUN: >> %t/result.json -// RUN: cat %t/result.json | FileCheck %s -DPREFIX=%/t +// RUN: cat %t/result.json | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s // CHECK: "modules": [ // CHECK: { @@ -33,7 +33,7 @@ // CHECK: ], // CHECK: "command-line": [ // CHECK: "-fmodule-file-cache-key" -// CHECK: "[[PREFIX]]/outputs/[[HASH]]/Mod-[[HASH]].pcm" +// CHECK: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}[[HASH]]{{/|\\\\}}Mod-[[HASH]].pcm" // CHECK: "llvmcas://[[KEY]]" // CHECK: ] @@ -57,7 +57,7 @@ // CHECK: ], // CHECK: "command-line": [ // CHECK: "-fmodule-file-cache-key" -// CHECK: "[[PREFIX]]/outputs/[[HASH]]/Mod-[[HASH]].pcm" +// CHECK: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}[[HASH]]{{/|\\\\}}Mod-[[HASH]].pcm" // CHECK: "llvmcas://[[KEY]]" // CHECK: ] @@ -105,4 +105,4 @@ module Mod { header "Mod.h" } //--- Mod.h //--- tu.c -#include "Mod.h" \ No newline at end of file +#include "Mod.h" diff --git a/clang/test/ClangScanDeps/modules-cas-fs-prefix-mapping-caching.c b/clang/test/ClangScanDeps/modules-cas-fs-prefix-mapping-caching.c index 230b21b83fae7..064d9f0d20783 100644 --- a/clang/test/ClangScanDeps/modules-cas-fs-prefix-mapping-caching.c +++ b/clang/test/ClangScanDeps/modules-cas-fs-prefix-mapping-caching.c @@ -5,19 +5,19 @@ // RUN: rm -rf %t // RUN: split-file %s %t // RUN: cp -r %t/dir1 %t/dir2 -// RUN: sed -e "s|DIR|%t/dir1|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb.json.template > %t/dir1/cdb.json -// RUN: sed -e "s|DIR|%t/dir2|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb.json.template > %t/dir2/cdb.json +// RUN: sed -e "s|DIR|%/t/dir1|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb.json.template > %t/dir1/cdb.json +// RUN: sed -e "s|DIR|%/t/dir2|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb.json.template > %t/dir2/cdb.json // RUN: clang-scan-deps -compilation-database %t/dir1/cdb.json -format experimental-full \ // RUN: -cas-path %t/cas -module-files-dir %t/dir1/modules \ -// RUN: -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ -// RUN: -prefix-map=%t/dir1/modules=/^modules -prefix-map=%t/dir1=/^src -optimize-args=none \ +// RUN: -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ +// RUN: -prefix-map=%t/dir1/modules=%/root^modules -prefix-map=%t/dir1=%/root^src -optimize-args=none \ // RUN: > %t/dir1.txt // RUN: clang-scan-deps -compilation-database %t/dir2/cdb.json -format experimental-full \ // RUN: -cas-path %t/cas -module-files-dir %t/dir2/modules \ -// RUN: -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ -// RUN: -prefix-map=%t/dir2/modules=/^modules -prefix-map=%t/dir2=/^src -optimize-args=none \ +// RUN: -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ +// RUN: -prefix-map=%t/dir2/modules=%/root^modules -prefix-map=%t/dir2=%/root^src -optimize-args=none \ // RUN: > %t/dir2.txt // Extract individual commands. @@ -29,15 +29,21 @@ // RUN: %deps-to-rsp %t/dir2.txt --module-name=A > %t/dir2/A.cc1.rsp // RUN: %deps-to-rsp %t/dir2.txt --tu-index 0 > %t/dir2/tu.cc1.rsp -// RUN: (cd %t/dir1; %clang @B.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-MISS -// RUN: (cd %t/dir1; %clang @A.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-MISS -// RUN: (cd %t/dir1; %clang @tu.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-MISS +// RUN: cd %t/dir1 && %clang @B.cc1.rsp > %t/miss-B.txt 2>&1 +// RUN: cat %t/miss-B.txt | FileCheck %s -check-prefix=CACHE-MISS +// RUN: cd %t/dir1 && %clang @A.cc1.rsp > %t/miss-A.txt 2>&1 +// RUN: cat %t/miss-A.txt | FileCheck %s -check-prefix=CACHE-MISS +// RUN: cd %t/dir1 && %clang @tu.cc1.rsp > %t/miss-tu.txt 2>&1 +// RUN: cat %t/miss-tu.txt | FileCheck %s -check-prefix=CACHE-MISS // CACHE-MISS: compile job cache miss -// RUN: (cd %t/dir2; %clang @B.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-HIT -// RUN: (cd %t/dir2; %clang @A.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-HIT -// RUN: (cd %t/dir2; %clang @tu.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-HIT +// RUN: cd %t/dir2 && %clang @B.cc1.rsp > %t/hit-B.txt 2>&1 +// RUN: cat %t/hit-B.txt | FileCheck %s -check-prefix=CACHE-HIT +// RUN: cd %t/dir2 && %clang @A.cc1.rsp > %t/hit-A.txt 2>&1 +// RUN: cat %t/hit-B.txt | FileCheck %s -check-prefix=CACHE-HIT +// RUN: cd %t/dir2 && %clang @tu.cc1.rsp > %t/hit-tu.txt 2>&1 +// RUN: cat %t/hit-tu.txt | FileCheck %s -check-prefix=CACHE-HIT // CACHE-HIT: compile job cache hit diff --git a/clang/test/ClangScanDeps/modules-cas-fs-prefix-mapping.c b/clang/test/ClangScanDeps/modules-cas-fs-prefix-mapping.c index 24190438079f4..63892d1a87595 100644 --- a/clang/test/ClangScanDeps/modules-cas-fs-prefix-mapping.c +++ b/clang/test/ClangScanDeps/modules-cas-fs-prefix-mapping.c @@ -5,15 +5,15 @@ // RUN: rm -rf %t // RUN: split-file %s %t -// RUN: sed -e "s|DIR|%t|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb.json.template > %t/cdb.json +// RUN: sed -e "s|DIR|%/t|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb.json.template > %t/cdb.json // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full \ // RUN: -cas-path %t/cas -module-files-dir %t/modules \ -// RUN: -prefix-map=%t/modules=/^modules -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/modules=%/root^modules -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: > %t/full_result.txt // Check the command-lines. -// RUN: FileCheck %s -input-file %t/full_result.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK +// RUN: cat %t/full_result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize SDK_PREFIX=%/S/Inputs/SDK --sanitize ROOT^=%/root^ --enable-yaml-compatibility %s // Extract individual commands. // RUN: %deps-to-rsp %t/full_result.txt --module-name=B > %t/B.cc1.rsp @@ -27,18 +27,18 @@ // RUN: llvm-cas -cas %t/cas -ls-tree-recursive @%t/B_id.txt > %t/B_fs.txt // RUN: llvm-cas -cas %t/cas -ls-tree-recursive @%t/A_id.txt > %t/A_fs.txt // RUN: llvm-cas -cas %t/cas -ls-tree-recursive @%t/tu_id.txt > %t/tu_fs.txt -// RUN: FileCheck %s -input-file %t/A_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefixes=FS_NEG,FS -// RUN: FileCheck %s -input-file %t/B_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefixes=FS_NEG,FS -// RUN: FileCheck %s -input-file %t/tu_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefixes=FS_NEG,FS +// RUN: FileCheck %s -input-file %t/A_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -DROOT=%{/roott} -check-prefixes=FS_NEG,FS +// RUN: FileCheck %s -input-file %t/B_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -DROOT=%{/roott} -check-prefixes=FS_NEG,FS +// RUN: FileCheck %s -input-file %t/tu_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -DROOT=%{/roott} -check-prefixes=FS_NEG,FS // FS_NEG-NOT: [[PREFIX]] // FS_NEG-NOT: [[SDK_PREFIX]] // FS_NEG-NOT: .pcm{{$}} -// FS: file llvmcas://{{.*}} /^sdk/usr/include/stdlib.h -// FS: file llvmcas://{{.*}} /^src/a.h -// FS: file llvmcas://{{.*}} /^src/b.h -// FS: file llvmcas://{{.*}} /^src/module.modulemap -// FS: file llvmcas://{{.*}} /^tc/lib/clang/{{.*}}/include/stdarg.h +// FS: file llvmcas://{{.*}} [[ROOT]]^sdk/usr/include/stdlib.h +// FS: file llvmcas://{{.*}} [[ROOT]]^src/a.h +// FS: file llvmcas://{{.*}} [[ROOT]]^src/b.h +// FS: file llvmcas://{{.*}} [[ROOT]]^src/module.modulemap +// FS: file llvmcas://{{.*}} [[ROOT]]^tc/lib/clang/{{.*}}/include/stdarg.h // Check that it builds. // RUN: %clang @%t/B.cc1.rsp @@ -54,71 +54,71 @@ // CHECK: "module-name": "B" // CHECK: } // CHECK: ] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK: "-fcas-path" -// CHECK: "[[PREFIX]]/cas" +// CHECK: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK: "[[A_ROOT_ID]]" // CHECK: "-fcas-fs-working-directory" -// CHECK: "/^src" -// CHECK: "-fmodule-map-file=/^src/module.modulemap" +// CHECK: "ROOT^src" +// CHECK: "-fmodule-map-file=ROOT^src{{/|\\\\}}module.modulemap" // CHECK: "-o" -// CHECK: "[[PREFIX]]/modules/{{.*}}/A-{{.*}}.pcm" +// CHECK: "PREFIX{{/|\\\\}}modules{{/|\\\\}}{{.*}}{{/|\\\\}}A-{{.*}}.pcm" // CHECK: "-fmodule-file-cache-key" -// CHECK: "/^modules/{{.*}}/B-[[B_CONTEXT_HASH:[^.]+]].pcm" +// CHECK: "ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}B-[[B_CONTEXT_HASH:[^.]+]].pcm" // CHECK: "llvmcas://{{.*}}" // CHECK: "-x" // CHECK: "c" -// CHECK: "/^src/module.modulemap" +// CHECK: "ROOT^src{{/|\\\\}}module.modulemap" // CHECK: "-isysroot" -// CHECK: "/^sdk" +// CHECK: "ROOT^sdk" // CHECK: "-resource-dir" -// CHECK: "/^tc/lib/clang/{{.*}}" -// CHECK: "-fmodule-file=B=/^modules/{{.*}}/B-[[B_CONTEXT_HASH]].pcm" +// CHECK: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" +// CHECK: "-fmodule-file=B=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}B-[[B_CONTEXT_HASH]].pcm" // CHECK: "-isystem" -// CHECK: "/^tc/lib/clang/{{.*}}/include" +// CHECK: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}{{/|\\\\}}include" // CHECK: "-internal-externc-isystem" -// CHECK: "/^sdk/usr/include" +// CHECK: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}include" // CHECK: ] // CHECK: "file-deps": [ -// CHECK: "[[PREFIX]]/module.modulemap" -// CHECK: "[[PREFIX]]/a.h" +// CHECK: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK: "PREFIX{{/|\\\\}}a.h" // CHECK: ] // CHECK: "name": "A" // CHECK: } // CHECK: { // CHECK: "casfs-root-id": "[[B_ROOT_ID:llvmcas://[[:xdigit:]]+]]" // CHECK: "clang-module-deps": [], -// CHECK: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK: "-fcas-path" -// CHECK: "[[PREFIX]]/cas" +// CHECK: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK: "[[B_ROOT_ID]]" // CHECK: "-fcas-fs-working-directory" -// CHECK: "/^src" +// CHECK: "ROOT^src" // CHECK: "-o" -// CHECK: "[[PREFIX]]/modules/{{.*}}/B-[[B_CONTEXT_HASH]].pcm" +// CHECK: "PREFIX{{/|\\\\}}modules{{/|\\\\}}{{.*}}{{/|\\\\}}B-[[B_CONTEXT_HASH]].pcm" // CHECK: "-x" // CHECK: "c" -// CHECK: "/^src/module.modulemap" +// CHECK: "ROOT^src{{/|\\\\}}module.modulemap" // CHECK: "-isysroot" -// CHECK: "/^sdk" +// CHECK: "ROOT^sdk" // CHECK: "-resource-dir" -// CHECK: "/^tc/lib/clang/{{.*}}" +// CHECK: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" // CHECK: "-isystem" -// CHECK: "/^tc/lib/clang/{{.*}}/include" +// CHECK: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}{{/|\\\\}}include" // CHECK: "-internal-externc-isystem" -// CHECK: "/^sdk/usr/include" +// CHECK: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}include" // CHECK: ] // CHECK: "context-hash": "[[B_CONTEXT_HASH]]" // CHECK: "file-deps": [ // Note: PREFIX, SDK_PREFIX and toolchain path are unordered -// CHECK-DAG: "[[PREFIX]]/module.modulemap" -// CHECK-DAG: "[[PREFIX]]/b.h" -// CHECK-DAG: "{{.*}}/include/stdarg.h" -// CHECK-DAG: "[[SDK_PREFIX]]/usr/include/stdlib.h" +// CHECK-DAG: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-DAG: "PREFIX{{/|\\\\}}b.h" +// CHECK-DAG: "{{.*}}{{/|\\\\}}include{{/|\\\\}}stdarg.h" +// CHECK-DAG: "SDK_PREFIX{{/|\\\\}}usr{{/|\\\\}}include{{/|\\\\}}stdlib.h" // CHECK: ] // CHECK: "name": "B" // CHECK: } @@ -135,32 +135,32 @@ // CHECK: ] // CHECK: "command-line": [ // CHECK: "-fcas-path" -// CHECK: "[[PREFIX]]/cas" +// CHECK: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK: "[[TU_ROOT_ID]]" // CHECK: "-fcas-fs-working-directory" -// CHECK: "/^src" -// CHECK: "-fmodule-map-file=/^src/module.modulemap" +// CHECK: "ROOT^src" +// CHECK: "-fmodule-map-file=ROOT^src{{/|\\\\}}module.modulemap" // CHECK: "-fmodule-file-cache-key" -// CHECK: "/^modules/{{.*}}A-{{.*}}.pcm" +// CHECK: "ROOT^modules{{/|\\\\}}{{.*}}A-{{.*}}.pcm" // CHECK: "llvmcas://{{.*}}" // CHECK: "-x" // CHECK: "c" -// CHECK: "/^src/t.c" +// CHECK: "ROOT^src{{/|\\\\}}t.c" // CHECK: "-isysroot" -// CHECK: "/^sdk" +// CHECK: "ROOT^sdk" // CHECK: "-resource-dir" -// CHECK: "/^tc/lib/clang/{{.*}}" -// CHECK: "-fmodule-file=A=/^modules/{{.*}}/A-{{.*}}.pcm" +// CHECK: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" +// CHECK: "-fmodule-file=A=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}A-{{.*}}.pcm" // CHECK: "-isystem" -// CHECK: "/^tc/lib/clang/{{.*}}/include" +// CHECK: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}{{/|\\\\}}include" // CHECK: "-internal-externc-isystem" -// CHECK: "/^sdk/usr/include" +// CHECK: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}include" // CHECK: ], // CHECK: "file-deps": [ -// CHECK: "[[PREFIX]]/t.c" +// CHECK: "PREFIX{{/|\\\\}}t.c" // CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/t.c" +// CHECK: "input-file": "PREFIX{{/|\\\\}}t.c" // CHECK: } diff --git a/clang/test/ClangScanDeps/modules-cas-full-by-mod-name.c b/clang/test/ClangScanDeps/modules-cas-full-by-mod-name.c index 957e383e2cb99..4a6603641d4c7 100644 --- a/clang/test/ClangScanDeps/modules-cas-full-by-mod-name.c +++ b/clang/test/ClangScanDeps/modules-cas-full-by-mod-name.c @@ -30,7 +30,7 @@ module transitive { header "transitive.h" } // RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json // RUN: clang-scan-deps -compilation-database %t/cdb.json \ // RUN: -cas-path %t/cas -format experimental-full -module-name=root > %t/result.json -// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s +// RUN: cat %t/result.json | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s // CHECK: { // CHECK-NEXT: "modules": [ @@ -43,7 +43,7 @@ module transitive { header "transitive.h" } // CHECK-NEXT: "module-name": "transitive" // CHECK-NEXT: } // CHECK-NEXT: ], -// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap", // CHECK-NEXT: "command-line": [ // CHECK: "-fmodule-file-cache-key" // CHECK-NEXT: "{{.*transitive-.*\.pcm}}" @@ -51,8 +51,8 @@ module transitive { header "transitive.h" } // CHECK: ], // CHECK-NEXT: "context-hash": "{{.*}}", // CHECK-NEXT: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/direct.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}direct.h" // CHECK-NEXT: ], // CHECK-NEXT: "link-libraries": [], // CHECK-NEXT: "name": "direct" @@ -66,7 +66,7 @@ module transitive { header "transitive.h" } // CHECK-NEXT: "module-name": "direct" // CHECK-NEXT: } // CHECK-NEXT: ], -// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap", // CHECK-NEXT: "command-line": [ // CHECK: "-fmodule-file-cache-key" // CHECK-NEXT: "{{.*direct-.*\.pcm}}" @@ -74,9 +74,9 @@ module transitive { header "transitive.h" } // CHECK: ], // CHECK-NEXT: "context-hash": "{{.*}}", // CHECK-NEXT: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/root.h" -// CHECK-NEXT: "[[PREFIX]]/root/textual.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}root.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}root{{/|\\\\}}textual.h" // CHECK-NEXT: ], // CHECK-NEXT: "link-libraries": [], // CHECK-NEXT: "name": "root" @@ -85,13 +85,13 @@ module transitive { header "transitive.h" } // CHECK-NEXT: "cache-key": "[[TRANSITIVE_CACHE_KEY]]" // CHECK-NEXT: "casfs-root-id": "[[LEFT_ROOT_ID]]" // CHECK-NEXT: "clang-module-deps": [], -// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap", // CHECK-NEXT: "command-line": [ // CHECK: ], // CHECK-NEXT: "context-hash": "{{.*}}", // CHECK-NEXT: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/transitive.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}transitive.h" // CHECK-NEXT: ], // CHECK-NEXT: "link-libraries": [], // CHECK-NEXT: "name": "transitive" diff --git a/clang/test/ClangScanDeps/modules-cas-trees-cwd.c b/clang/test/ClangScanDeps/modules-cas-trees-cwd.c index de2611c3c3655..2491ce885437c 100644 --- a/clang/test/ClangScanDeps/modules-cas-trees-cwd.c +++ b/clang/test/ClangScanDeps/modules-cas-trees-cwd.c @@ -22,14 +22,14 @@ // RUN: %clang @%t/tu.rsp // Check specifics of the command-line -// RUN: cat %t/deps.json | FileCheck %s -DPREFIX=%/t +// RUN: cat %t/deps.json | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s // CHECK: { // CHECK-NEXT: "modules": [ // CHECK-NEXT: { // CHECK: "command-line": [ // CHECK: "-fcas-fs-working-directory" -// CHECK-NEXT: "[[PREFIX]]/B" +// CHECK-NEXT: "PREFIX{{/|\\\\}}B" // CHECK: ] // CHECK: "name": "Mod" // CHECK: } @@ -40,7 +40,7 @@ // CHECK: { // CHECK: "command-line": [ // CHECK: "-fcas-fs-working-directory" -// CHECK-NEXT: "[[PREFIX]]/B" +// CHECK-NEXT: "PREFIX{{/|\\\\}}B" // CHECK: ] //--- cdb.json.template diff --git a/clang/test/ClangScanDeps/modules-cas-trees-with-pch.c b/clang/test/ClangScanDeps/modules-cas-trees-with-pch.c index d936e618ba770..7c1dcaedec128 100644 --- a/clang/test/ClangScanDeps/modules-cas-trees-with-pch.c +++ b/clang/test/ClangScanDeps/modules-cas-trees-with-pch.c @@ -15,7 +15,7 @@ // RUN: > %t/deps_pch.json // == Check specifics of the command-line -// RUN: cat %t/deps_pch.json | FileCheck %s -DPREFIX=%/t -check-prefix=PCH +// RUN: cat %t/deps_pch.json | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s -check-prefix=PCH // == Build PCH // RUN: %deps-to-rsp %t/deps_pch.json --module-name A > %t/A.rsp @@ -36,7 +36,7 @@ // RUN: > %t/deps.json // == Check specifics of the command-line -// RUN: cat %t/deps.json | FileCheck %s -DPREFIX=%/t +// RUN: cat %t/deps.json | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s // == Build TU, including PCH // RUN: %deps-to-rsp %t/deps.json --module-name C > %t/C.rsp @@ -60,7 +60,7 @@ // PCH: "command-line": [ // PCH-NEXT: "-cc1" // PCH: "-fcas-path" -// PCH-NEXT: "[[PREFIX]]{{.}}cas" +// PCH-NEXT: "PREFIX{{/|\\\\}}cas" // PCH: "-fcas-fs" // PCH-NEXT: "[[A_ROOT_ID]]" // PCH: "-o" @@ -73,8 +73,8 @@ // PCH: "-fmodule-file={{(B=)?}}[[B_PCM]]" // PCH: ] // PCH: "file-deps": [ -// PCH-NEXT: "[[PREFIX]]{{.}}module.modulemap" -// PCH-NEXT: "[[PREFIX]]{{.}}A.h" +// PCH-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// PCH-NEXT: "PREFIX{{/|\\\\}}A.h" // PCH-NEXT: ] // PCH: "name": "A" // PCH: } @@ -84,7 +84,7 @@ // PCH: "command-line": [ // PCH-NEXT: "-cc1" // PCH: "-fcas-path" -// PCH-NEXT: "[[PREFIX]]{{.}}cas" +// PCH-NEXT: "PREFIX{{/|\\\\}}cas" // PCH: "-fcas-fs" // PCH-NEXT: "[[B_ROOT_ID]]" // PCH: "-o" @@ -93,8 +93,8 @@ // PCH: "-emit-module" // PCH: ] // PCH: "file-deps": [ -// PCH-NEXT: "[[PREFIX]]{{.}}module.modulemap" -// PCH-NEXT: "[[PREFIX]]{{.}}B.h" +// PCH-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// PCH-NEXT: "PREFIX{{/|\\\\}}B.h" // PCH-NEXT: ] // PCH: "name": "B" // PCH: } @@ -112,7 +112,7 @@ // PCH: "command-line": [ // PCH-NEXT: "-cc1" // PCH: "-fcas-path" -// PCH-NEXT: "[[PREFIX]]{{.}}cas" +// PCH-NEXT: "PREFIX{{/|\\\\}}cas" // PCH: "-fcas-fs" // PCH-NEXT: "[[PCH_ROOT_ID]]" // PCH: "-fno-pch-timestamp" @@ -124,7 +124,7 @@ // PCH: "-fmodule-file={{(A=)?}}[[A_PCM]]" // PCH: ] // PCH: "file-deps": [ -// PCH-NEXT: "[[PREFIX]]{{.}}prefix.h" +// PCH-NEXT: "PREFIX{{/|\\\\}}prefix.h" // PCH-NEXT: ] // PCH: } @@ -136,7 +136,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]{{.}}cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[C_ROOT_ID]]" // CHECK: "-o" @@ -149,8 +149,8 @@ // CHECK: "[[B_CACHE_KEY:llvmcas://[[:xdigit:]]+]]" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]{{.}}module.modulemap" -// CHECK-NEXT: "[[PREFIX]]{{.}}C.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}C.h" // CHECK-NEXT: ] // CHECK: "name": "C" // CHECK: } @@ -168,7 +168,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]{{.}}cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[TU_ROOT_ID]]" // CHECK: "-fno-pch-timestamp" @@ -179,8 +179,8 @@ // CHECK: "-fmodule-file={{(C=)?}}[[C_PCM]]" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]{{.}}tu.c" -// CHECK-NEXT: "[[PREFIX]]{{.}}prefix.h.pch" +// CHECK-NEXT: "PREFIX{{/|\\\\}}tu.c" +// CHECK-NEXT: "PREFIX{{/|\\\\}}prefix.h.pch" // CHECK-NEXT: ] // CHECK: } diff --git a/clang/test/ClangScanDeps/modules-cas-trees.c b/clang/test/ClangScanDeps/modules-cas-trees.c index 2077b697c6c13..48d6ef11bfee2 100644 --- a/clang/test/ClangScanDeps/modules-cas-trees.c +++ b/clang/test/ClangScanDeps/modules-cas-trees.c @@ -59,7 +59,7 @@ // CACHE-MISS: remark: compile job cache miss // Check specifics of the command-line -// RUN: cat %t/deps.json | FileCheck %s -DPREFIX=%/t +// RUN: cat %t/deps.json | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s // CHECK: { // CHECK-NEXT: "modules": [ @@ -74,7 +74,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]{{.}}cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[LEFT_ROOT_ID]]" // CHECK: "-o" @@ -87,8 +87,8 @@ // CHECK: "-fmodule-file={{(Top=)?}}[[TOP_PCM]]" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]{{.}}module.modulemap" -// CHECK-NEXT: "[[PREFIX]]{{.}}Left.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}Left.h" // CHECK-NEXT: ] // CHECK: "name": "Left" // CHECK: } @@ -103,7 +103,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]{{.}}cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[RIGHT_ROOT_ID]]" // CHECK: "-o" @@ -116,8 +116,8 @@ // CHECK: "-fmodule-file={{(Top=)?}}[[TOP_PCM]]" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]{{.}}module.modulemap" -// CHECK-NEXT: "[[PREFIX]]{{.}}Right.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}Right.h" // CHECK: ] // CHECK: "name": "Right" // CHECK: } @@ -128,7 +128,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]{{.}}cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[TOP_ROOT_ID]]" // CHECK: "-o" @@ -137,8 +137,8 @@ // CHECK: "-emit-module" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]{{.}}module.modulemap" -// CHECK-NEXT: "[[PREFIX]]{{.}}Top.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}Top.h" // CHECK: ] // CHECK: "name": "Top" // CHECK: } @@ -160,7 +160,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]{{.}}cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[TU_ROOT_ID]]" // CHECK: "-fcache-compile-job" @@ -174,7 +174,7 @@ // CHECK: "-fmodule-file={{(Right=)?}}[[RIGHT_PCM]]" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]{{.}}tu.c" +// CHECK-NEXT: "PREFIX{{/|\\\\}}tu.c" // CHECK-NEXT: ] // CHECK: } diff --git a/clang/test/ClangScanDeps/modules-include-tree-implementation.c b/clang/test/ClangScanDeps/modules-include-tree-implementation.c index 282742ad803f1..09add56f6f1e0 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-implementation.c +++ b/clang/test/ClangScanDeps/modules-include-tree-implementation.c @@ -17,7 +17,7 @@ // RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/tu.casid | FileCheck %s -DPREFIX=%/t // RUN: %clang @%t/tu.rsp -// CHECK: [[PREFIX]]/tu.c llvmcas://{{[[:xdigit:]]+}} +// CHECK: [[PREFIX]]{{[/\\]}}tu.c llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} // Note: this is surprising, but correct: when building the implementation files @@ -25,14 +25,14 @@ // machinery. The second include is treated as a module import (unless in a PCH) // but will not actually import the module only trigger visibility changes. -// CHECK: 2:1 [[PREFIX]]/Mod.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 [[PREFIX]]{{[/\\]}}Mod.h llvmcas://{{[[:xdigit:]]+}} // CHECK: Submodule: Mod // CHECK: 3:1 (Module for visibility only) Mod // CHECK: Files: -// CHECK: [[PREFIX]]/tu.c llvmcas://{{[[:xdigit:]]+}} +// CHECK: [[PREFIX]]{{[/\\]}}tu.c llvmcas://{{[[:xdigit:]]+}} // CHECK-NOT: [[PREFIX]]/module.modulemap -// CHECK: [[PREFIX]]/Mod.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: [[PREFIX]]{{[/\\]}}Mod.h llvmcas://{{[[:xdigit:]]+}} // CHECK-NOT: [[PREFIX]]/module.modulemap // RUN: %deps-to-rsp %t/deps.json --tu-index 1 > %t/tu_missing_module.rsp diff --git a/clang/test/ClangScanDeps/modules-include-tree-inferred.m b/clang/test/ClangScanDeps/modules-include-tree-inferred.m index df0668d54e8bd..4d3957dd345ed 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-inferred.m +++ b/clang/test/ClangScanDeps/modules-include-tree-inferred.m @@ -18,15 +18,15 @@ // CHECK: llvmcas:// // CHECK: 1:1 llvmcas:// -// CHECK: 2:1 [[PREFIX]]/Mod.framework/Headers/Mod.h llvmcas:// +// CHECK: 2:1 [[PREFIX]]{{[/\\]}}Mod.framework{{[/\\]}}Headers{{[/\\]}}Mod.h llvmcas:// // CHECK: Submodule: Mod // CHECK: Module Map: // CHECK: Mod (framework) // CHECK: link Mod (framework) // CHECK: Files: -// CHECK-NOT: [[PREFIX]]/module.modulemap -// CHECK: [[PREFIX]]/Mod.framework/Headers/Mod.h llvmcas:// -// CHECK-NOT: [[PREFIX]]/module.modulemap +// CHECK-NOT: [[PREFIX]]{{[/\\]}}module.modulemap +// CHECK: [[PREFIX]]{{[/\\]}}Mod.framework{{[/\\]}}Headers{{[/\\]}}Mod.h llvmcas:// +// CHECK-NOT: [[PREFIX]]{{[/\\]}}module.modulemap //--- cdb.json.template [{ diff --git a/clang/test/ClangScanDeps/modules-include-tree-missing-submodule.c b/clang/test/ClangScanDeps/modules-include-tree-missing-submodule.c index 81408220f3e99..46356a7118aa2 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-missing-submodule.c +++ b/clang/test/ClangScanDeps/modules-include-tree-missing-submodule.c @@ -37,7 +37,7 @@ // CHECK-LABEL: MODULE Foo // CHECK: llvmcas:// // CHECK: 1:1 llvmcas:// -// CHECK: 2:1 [[PREFIX]]/Foo.framework/Headers/Foo.h llvmcas:// +// CHECK: 2:1 [[PREFIX]]{{[/\\]}}Foo.framework{{[/\\]}}Headers{{[/\\]}}Foo.h llvmcas:// // CHECK: Submodule: Foo // CHECK-NOT: Bar // CHECK: Module Map: @@ -50,7 +50,7 @@ // CHECK: (PCH) llvmcas:// // CHECK: [[PREFIX]]/tu.c llvmcas:// // CHECK: 1:1 llvmcas:// -// CHECK: 2:1 (Spurious import) (Module) Foo.Bar [[PREFIX]]/Foo.framework/Headers/Bar.h llvmcas:// +// CHECK: 2:1 (Spurious import) (Module) Foo.Bar [[PREFIX]]{{[/\\]}}Foo.framework{{[/\\]}}Headers{{[/\\]}}Bar.h llvmcas:// // RUN: %clang @%t/tu.rsp diff --git a/clang/test/ClangScanDeps/modules-include-tree-pch-common-stale.c b/clang/test/ClangScanDeps/modules-include-tree-pch-common-stale.c index 041ba6814ee3e..33fa3f2132dee 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-pch-common-stale.c +++ b/clang/test/ClangScanDeps/modules-include-tree-pch-common-stale.c @@ -1,3 +1,5 @@ +// REQUIRES: ondisk_cas + // 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. diff --git a/clang/test/ClangScanDeps/modules-include-tree-pch-with-private.c b/clang/test/ClangScanDeps/modules-include-tree-pch-with-private.c index 3104a5b68badc..32e4811081172 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-pch-with-private.c +++ b/clang/test/ClangScanDeps/modules-include-tree-pch-with-private.c @@ -47,7 +47,7 @@ // CHECK-LABEL: MODULE Indirect2 // CHECK: llvmcas:// // CHECK: 1:1 llvmcas:// -// CHECK: 2:1 [[PREFIX]]/indirect2.h llvmcas:// +// CHECK: 2:1 [[PREFIX]]{{[/\\]}}indirect2.h llvmcas:// // CHECK: Submodule: Indirect2 // CHECK: 2:1 (Module) Indirect1 // CHECK: 3:1 (Module) Mod_Private diff --git a/clang/test/ClangScanDeps/modules-include-tree-prefix-map.c b/clang/test/ClangScanDeps/modules-include-tree-prefix-map.c index 8eb7da7be4bea..cde604544d5fc 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-prefix-map.c +++ b/clang/test/ClangScanDeps/modules-include-tree-prefix-map.c @@ -4,12 +4,13 @@ // RUN: rm -rf %t // RUN: split-file %s %t/dir1 // RUN: cp -r %t/dir1 %t/dir2 -// RUN: sed -e "s|DIR|%/t/dir1|g" -e "s|CLANG|%clang|g" %t/dir1/cdb.json.template > %t/cdb1.json -// RUN: sed -e "s|DIR|%/t/dir2|g" -e "s|CLANG|%clang|g" %t/dir1/cdb.json.template > %t/cdb2.json +// RUN: sed -e "s|DIR|%/t/dir1|g" -e "s|CLANG|%/ncclang|g" %t/dir1/cdb.json.template > %t/cdb1.json +// RUN: sed -e "s|DIR|%/t/dir2|g" -e "s|CLANG|%/ncclang|g" %t/dir1/cdb.json.template > %t/cdb2.json // RUN: clang-scan-deps -compilation-database %t/cdb1.json \ // RUN: -cas-path %t/cas -module-files-dir %t/dir1/outputs \ -// RUN: -prefix-map=%t/dir1/outputs=/^modules -prefix-map=%t/dir1=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/dir1/outputs=%/root^modules -prefix-map=%t/dir1=%/root^src \ +// RUN: -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: -format experimental-include-tree-full -mode preprocess-dependency-directives -optimize-args=none \ // RUN: > %t/deps.json @@ -45,50 +46,50 @@ // RUN: cat %t/deps.json >> %t/result.txt -// RUN: FileCheck %s -input-file %t/result.txt -DPREFIX=%/t +// RUN: cat %t/result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize ROOT^=%/root^ --enable-yaml-compatibility %s // CHECK-LABEL: MODULE Top // CHECK: llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} -// CHECK: 2:1 /^src/Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 ROOT^src{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} // CHECK: Module Map: // CHECK: Top // CHECK: export * // CHECK: Files: // CHECK-NOT: module.modulemap -// CHECK: /^src/Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} // CHECK-NOT: module.modulemap // CHECK-LABEL: MODULE Left // CHECK: llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} -// CHECK: 2:1 /^src/Left.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 ROOT^src{{/|\\}}Left.h llvmcas://{{[[:xdigit:]]+}} // CHECK: 2:1 (Module) Top // CHECK: Module Map: // CHECK: Left // CHECK: export * // CHECK: Files: // CHECK-NOT: module.modulemap -// CHECK: /^src/Left.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}Left.h llvmcas://{{[[:xdigit:]]+}} // CHECK-NOT: module.modulemap -// CHECK: /^src/Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} // CHECK-LABEL: MODULE Right // CHECK: llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} -// CHECK: 2:1 /^src/Right.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 ROOT^src{{/|\\}}Right.h llvmcas://{{[[:xdigit:]]+}} // CHECK: 2:1 (Module) Top // CHECK: Module Map: // CHECK: Right // CHECK: export * // CHECK: Files: // CHECK-NOT: module.modulemap -// CHECK: /^src/Right.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}Right.h llvmcas://{{[[:xdigit:]]+}} // CHECK-NOT: module.modulemap -// CHECK: /^src/Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} // CHECK-LABEL: TRANSLATION UNIT -// CHECK: /^src/tu.m llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}tu.m llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} // CHECK: 2:1 (Module) Left // CHECK: 3:1 (Module) Right @@ -100,9 +101,9 @@ // CHECK-NOT: Module Map // CHECK: Files: // CHECK-NOT: module.modulemap -// CHECK: /^src/Left.h llvmcas://{{[[:xdigit:]]+}} -// CHECK: /^src/Top.h llvmcas://{{[[:xdigit:]]+}} -// CHECK: /^src/Right.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}Left.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: ROOT^src{{/|\\}}Right.h llvmcas://{{[[:xdigit:]]+}} // CHECK-LABEL: System module-includes // CHECK-NEXT: #import "sys.h" @@ -117,14 +118,14 @@ // CHECK: "module-name": "Top" // CHECK: } // CHECK-NEXT: ] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/dir1/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}dir1{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK-NOT: -fmodule-map-file // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/dir1/outputs/{{.*}}/Left-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Left-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -132,16 +133,16 @@ // CHECK: "-fcache-compile-job" // CHECK: "-emit-module" // CHECK: "-fmodule-file-cache-key" -// CHECK-NEXT: "/^modules/{{.*}}/Top-{{.*}}.pcm" +// CHECK-NEXT: "ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" -// CHECK: "-fmodule-file=Top=/^modules/{{.*}}/Top-{{.*}}.pcm" +// CHECK: "-fmodule-file=Top=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK: "-fmodules" // CHECK: "-fmodule-name=Left" // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/dir1/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/dir1/Left.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}Left.h" // CHECK: ] // CHECK: "name": "Left" // CHECK: } @@ -152,14 +153,14 @@ // CHECK: "module-name": "Top" // CHECK: } // CHECK-NEXT: ] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/dir1/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}dir1{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK-NOT: -fmodule-map-file // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/dir1/outputs/{{.*}}/Right-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -167,29 +168,29 @@ // CHECK: "-fcache-compile-job" // CHECK: "-emit-module" // CHECK: "-fmodule-file-cache-key -// CHECK-NEXT: "/^modules/{{.*}}/Top-{{.*}}.pcm" +// CHECK-NEXT: "ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" -// CHECK: "-fmodule-file=Top=/^modules/{{.*}}/Top-{{.*}}.pcm" +// CHECK: "-fmodule-file=Top=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK: "-fmodules" // CHECK: "-fmodule-name=Right" // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/dir1/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/dir1/Right.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}Right.h" // CHECK-NEXT: ] // CHECK: "name": "Right" // CHECK: } // CHECK-NEXT: { // CHECK: "cas-include-tree-id": "[[SYS_TREE:llvmcas://[[:xdigit:]]+]]" // CHECK: "clang-module-deps": [] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/dir1/System/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}dir1{{/|\\\\}}System{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/dir1/outputs/{{.*}}/System-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}System-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -201,22 +202,22 @@ // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-DAG: "[[PREFIX]]/dir1/System/module.modulemap" -// CHECK-DAG: "[[PREFIX]]/dir1/System/sys.h" -// CHECK-DAG: "{{.*}}/stdbool.h" +// CHECK-DAG: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}System{{/|\\\\}}module.modulemap" +// CHECK-DAG: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}System{{/|\\\\}}sys.h" +// CHECK-DAG: "{{.*}}{{/|\\\\}}stdbool.h" // CHECK: ] // CHECK: "name": "System" // CHECK: } // CHECK-NEXT: { // CHECK: "cas-include-tree-id": "[[TOP_TREE:llvmcas://[[:xdigit:]]+]]" // CHECK: "clang-module-deps": [] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/dir1/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}dir1{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/dir1/outputs/{{.*}}/Top-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -228,8 +229,8 @@ // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/dir1/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/dir1/Top.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}Top.h" // CHECK-NEXT: ] // CHECK: "name": "Top" // CHECK: } @@ -253,7 +254,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK-NOT: -fmodule-map-file // CHECK: "-disable-free" // CHECK: "-fcas-include-tree" @@ -261,20 +262,20 @@ // CHECK: "-fcache-compile-job" // CHECK: "-fsyntax-only" // CHECK: "-fmodule-file-cache-key" -// CHECK-NEXT: "/^modules/{{.*}}/Left-{{.*}}.pcm" +// CHECK-NEXT: "ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}Left-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" // CHECK: "-fmodule-file-cache-key" -// CHECK-NEXT: "/^modules/{{.*}}/Right-{{.*}}.pcm" +// CHECK-NEXT: "ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" -// CHECK: "-fmodule-file=Left=/^modules/{{.*}}/Left-{{.*}}.pcm" -// CHECK: "-fmodule-file=Right=/^modules/{{.*}}/Right-{{.*}}.pcm" +// CHECK: "-fmodule-file=Left=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}Left-{{.*}}.pcm" +// CHECK: "-fmodule-file=Right=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK: "-fmodules" // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/dir1/tu.m" +// CHECK-NEXT: "PREFIX{{/|\\\\}}dir1{{/|\\\\}}tu.m" // CHECK-NEXT: ] -// CHECK: "input-file": "[[PREFIX]]/dir1/tu.m" +// CHECK: "input-file": "PREFIX{{/|\\\\}}dir1{{/|\\\\}}tu.m" // CHECK: } // CHECK-NEXT: ] // CHECK-NEXT: } @@ -291,7 +292,8 @@ // Scan in a different directory // RUN: clang-scan-deps -compilation-database %t/cdb2.json \ // RUN: -cas-path %t/cas -module-files-dir %t/dir2/outputs \ -// RUN: -prefix-map=%t/dir2/outputs=/^modules -prefix-map=%t/dir2=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/dir2/outputs=%/root^modules -prefix-map=%t/dir2=%/root^src \ +// RUN: -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: -format experimental-include-tree-full -mode preprocess-dependency-directives -optimize-args=none \ // RUN: > %t/deps2.json diff --git a/clang/test/ClangScanDeps/modules-include-tree-submodules.c b/clang/test/ClangScanDeps/modules-include-tree-submodules.c index 91b92443258f3..d6963dff9edcf 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-submodules.c +++ b/clang/test/ClangScanDeps/modules-include-tree-submodules.c @@ -30,7 +30,7 @@ // RUN: echo "TRANSLATION UNIT 2" >> %t/result.txt // RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/tu2.casid >> %t/result.txt -// RUN: FileCheck %s -input-file %t/result.txt -DPREFIX=%/t +// RUN: cat %t/result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t %s // Build the include-tree commands // RUN: %clang @%t/TwoSubs.rsp @@ -39,27 +39,27 @@ // RUN: not %clang @%t/tu2.rsp 2>&1 | FileCheck %s -check-prefix=TU2 // CHECK: MODULE TwoSubs -// CHECK: 2:1 [[PREFIX]]/Sub1.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 PREFIX{{/|\\}}Sub1.h llvmcas://{{[[:xdigit:]]+}} // CHECK: Submodule: TwoSubs.Sub1 -// CHECK: 3:1 [[PREFIX]]/Sub2.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 3:1 PREFIX{{/|\\}}Sub2.h llvmcas://{{[[:xdigit:]]+}} // CHECK: Submodule: TwoSubs.Sub2 // CHECK: MODULE WithExplicit -// CHECK: 2:1 [[PREFIX]]/TopLevel.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 PREFIX{{/|\\}}TopLevel.h llvmcas://{{[[:xdigit:]]+}} // CHECK: Submodule: WithExplicit -// CHECK: 3:1 [[PREFIX]]/Implicit.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 3:1 PREFIX{{/|\\}}Implicit.h llvmcas://{{[[:xdigit:]]+}} // CHECK: Submodule: WithExplicit.Implicit -// CHECK: 4:1 [[PREFIX]]/Explicit.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 4:1 PREFIX{{/|\\}}Explicit.h llvmcas://{{[[:xdigit:]]+}} // CHECK: Submodule: WithExplicit.Explicit // CHECK: TRANSLATION UNIT 1 -// CHECK: [[PREFIX]]/tu1.c llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}tu1.c llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} // CHECK: 2:1 (Module) TwoSubs.Sub1 // CHECK: 3:1 (Module) WithExplicit // CHECK: TRANSLATION UNIT 2 -// CHECK: [[PREFIX]]/tu2.c llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}tu2.c llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} // CHECK: 2:1 (Module) TwoSubs.Sub2 // CHECK: 3:1 (Module) WithExplicit.Explicit diff --git a/clang/test/ClangScanDeps/modules-include-tree-with-pch.c b/clang/test/ClangScanDeps/modules-include-tree-with-pch.c index d8efe277c35ab..c9300de986180 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-with-pch.c +++ b/clang/test/ClangScanDeps/modules-include-tree-with-pch.c @@ -34,28 +34,28 @@ // RUN: rm -rf %t/outputs // RUN: %clang @%t/tu.rsp -// RUN: FileCheck %s -input-file %t/deps.json -DPREFIX=%/t +// RUN: cat %t/deps.json | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s // CHECK: { // CHECK-NEXT: "modules": [ // CHECK-NEXT: { // CHECK: "clang-module-deps": [] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Right-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" // CHECK-NEXT: "[[RIGHT_TREE:llvmcas://[[:xdigit:]]+]]" // CHECK: "-fcache-compile-job" // CHECK: "-emit-module" -// CHECK: "-fmodule-file=[[PREFIX]]/outputs/{{.*}}/Top-{{.*}}.pcm" +// CHECK: "-fmodule-file=PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK: "-fmodule-file-cache-key" -// CHECK-NEXT: "[[PREFIX]]/{{.*}}/Top-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" // CHECK: "-x" // CHECK-NEXT: "c" @@ -64,8 +64,8 @@ // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/Right.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}Right.h" // CHECK-NEXT: ] // CHECK: "name": "Right" // CHECK: } @@ -83,7 +83,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK-NOT: -fmodule-map-file= // CHECK: "-disable-free" // CHECK: "-fcas-include-tree" @@ -91,19 +91,19 @@ // CHECK: "-fcache-compile-job" // CHECK: "-fsyntax-only" // CHECK: "-fmodule-file-cache-key" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Right-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" // CHECK: "-x" // CHECK-NEXT: "c" -// CHECK: "-fmodule-file=Right=[[PREFIX]]/outputs/{{.*}}/Right-{{.*}}.pcm" +// CHECK: "-fmodule-file=Right=PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK: "-fmodules" // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/tu.c" -// CHECK-NEXT: "[[PREFIX]]/prefix.h.pch" +// CHECK-NEXT: "PREFIX{{/|\\\\}}tu.c" +// CHECK-NEXT: "PREFIX{{/|\\\\}}prefix.h.pch" // CHECK-NEXT: ] -// CHECK: "input-file": "[[PREFIX]]/tu.c" +// CHECK: "input-file": "PREFIX{{/|\\\\}}tu.c" // CHECK: } // CHECK-NEXT: ] // CHECK-NEXT: } diff --git a/clang/test/ClangScanDeps/modules-include-tree-working-directory.c b/clang/test/ClangScanDeps/modules-include-tree-working-directory.c index 0c6e24472f5a6..a143a36700b0a 100644 --- a/clang/test/ClangScanDeps/modules-include-tree-working-directory.c +++ b/clang/test/ClangScanDeps/modules-include-tree-working-directory.c @@ -23,9 +23,9 @@ // RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/H.casid | FileCheck %s -DPREFIX=%/t // CHEK:C -// CHECK: 2:1 [[PREFIX]]/relative/h1.h llvmcas:// +// CHECK: 2:1 [[PREFIX]]{{[/\\]}}relative{{[/\\]}}h1.h llvmcas:// // CHECK: Files: -// CHECK: [[PREFIX]]/relative/h1.h llvmcas:// +// CHECK: [[PREFIX]]{{[/\\]}}relative{{[/\\]}}h1.h llvmcas:// //--- cdb.json.template [{ diff --git a/clang/test/ClangScanDeps/modules-include-tree.c b/clang/test/ClangScanDeps/modules-include-tree.c index de61673523e53..46485b1f99ff0 100644 --- a/clang/test/ClangScanDeps/modules-include-tree.c +++ b/clang/test/ClangScanDeps/modules-include-tree.c @@ -33,50 +33,50 @@ // RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/tu.casid >> %t/result.txt // RUN: cat %t/deps.json >> %t/result.txt -// RUN: FileCheck %s -input-file %t/result.txt -DPREFIX=%/t +// RUN: cat %t/result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --enable-yaml-compatibility %s // CHECK-LABEL: MODULE Top // CHECK: llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} -// CHECK: 2:1 [[PREFIX]]/Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 PREFIX{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} // CHECK: Module Map: // CHECK: Top // CHECK: export * // CHECK: Files: -// CHECK-NOT: [[PREFIX]]/module.modulemap -// CHECK: [[PREFIX]]/Top.h llvmcas://{{[[:xdigit:]]+}} -// CHECK-NOT: [[PREFIX]]/module.modulemap +// CHECK-NOT: PREFIX{{/|\\}}module.modulemap +// CHECK: PREFIX{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK-NOT: PREFIX{{/|\\}}module.modulemap // CHECK-LABEL: MODULE Left // CHECK: llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} -// CHECK: 2:1 [[PREFIX]]/Left.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 PREFIX{{/|\\}}Left.h llvmcas://{{[[:xdigit:]]+}} // CHECK: 2:1 (Module) Top // CHECK: Module Map: // CHECK: Left // CHECK: export * // CHECK: Files: -// CHECK-NOT: [[PREFIX]]/module.modulemap llvmcas://{{[[:xdigit:]]+}} -// CHECK: [[PREFIX]]/Left.h llvmcas://{{[[:xdigit:]]+}} -// CHECK-NOT: [[PREFIX]]/module.modulemap llvmcas://{{[[:xdigit:]]+}} -// CHECK: [[PREFIX]]/Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK-NOT: PREFIX{{/|\\}}module.modulemap llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}Left.h llvmcas://{{[[:xdigit:]]+}} +// CHECK-NOT: PREFIX{{/|\\}}module.modulemap llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} // CHECK-LABEL: MODULE Right // CHECK: llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} -// CHECK: 2:1 [[PREFIX]]/Right.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: 2:1 PREFIX{{/|\\}}Right.h llvmcas://{{[[:xdigit:]]+}} // CHECK: 2:1 (Module) Top // CHECK: Module Map: // CHECK: Right // CHECK: export * // CHECK: Files: -// CHECK-NOT: [[PREFIX]]/module.modulemap llvmcas://{{[[:xdigit:]]+}} -// CHECK: [[PREFIX]]/Right.h llvmcas://{{[[:xdigit:]]+}} -// CHECK-NOT: [[PREFIX]]/module.modulemap llvmcas://{{[[:xdigit:]]+}} -// CHECK: [[PREFIX]]/Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK-NOT: PREFIX{{/|\\}}module.modulemap llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}Right.h llvmcas://{{[[:xdigit:]]+}} +// CHECK-NOT: PREFIX{{/|\\}}module.modulemap llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} // CHECK-LABEL: TRANSLATION UNIT -// CHECK: [[PREFIX]]/tu.m llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}tu.m llvmcas://{{[[:xdigit:]]+}} // CHECK: 1:1 llvmcas://{{[[:xdigit:]]+}} // CHECK: 2:1 (Module) Left // CHECK: 3:1 (Module) Right @@ -87,10 +87,10 @@ // CHECK-NOT: Module Map // CHECK: Files: -// CHECK-NOT: [[PREFIX]]/module.modulemap llvmcas://{{[[:xdigit:]]+}} -// CHECK: [[PREFIX]]/Left.h llvmcas://{{[[:xdigit:]]+}} -// CHECK: [[PREFIX]]/Top.h llvmcas://{{[[:xdigit:]]+}} -// CHECK: [[PREFIX]]/Right.h llvmcas://{{[[:xdigit:]]+}} +// CHECK-NOT: PREFIX{{/|\\}}module.modulemap llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}Left.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}Top.h llvmcas://{{[[:xdigit:]]+}} +// CHECK: PREFIX{{/|\\}}Right.h llvmcas://{{[[:xdigit:]]+}} // CHECK: { // CHECK-NEXT "modules": [ @@ -101,14 +101,14 @@ // CHECK: "module-name": "Top" // CHECK: } // CHECK-NEXT: ] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK-NOT: -fmodule-map-file // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Left-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Left-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -116,16 +116,16 @@ // CHECK: "-fcache-compile-job" // CHECK: "-emit-module" // CHECK: "-fmodule-file-cache-key" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Top-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" -// CHECK: "-fmodule-file=Top=[[PREFIX]]/outputs/{{.*}}/Top-{{.*}}.pcm" +// CHECK: "-fmodule-file=Top=PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK: "-fmodules" // CHECK: "-fmodule-name=Left" // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/Left.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}Left.h" // CHECK: ] // CHECK: "name": "Left" // CHECK: } @@ -136,14 +136,14 @@ // CHECK: "module-name": "Top" // CHECK: } // CHECK-NEXT: ] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK-NOT: -fmodule-map-file // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Right-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -151,29 +151,29 @@ // CHECK: "-fcache-compile-job" // CHECK: "-emit-module" // CHECK: "-fmodule-file-cache-key -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Top-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" -// CHECK: "-fmodule-file=Top=[[PREFIX]]/outputs/{{.*}}/Top-{{.*}}.pcm" +// CHECK: "-fmodule-file=Top=PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK: "-fmodules" // CHECK: "-fmodule-name=Right" // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/Right.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}Right.h" // CHECK-NEXT: ] // CHECK: "name": "Right" // CHECK: } // CHECK-NEXT: { // CHECK: "cas-include-tree-id": "[[TOP_TREE:llvmcas://[[:xdigit:]]+]]" // CHECK: "clang-module-deps": [] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Top-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Top-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -185,21 +185,21 @@ // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/Top.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}Top.h" // CHECK-NEXT: ] // CHECK: "name": "Top" // CHECK: } // CHECK-NEXT: { // CHECK: "cas-include-tree-id": "[[AT_IMPORT_TREE:llvmcas://[[:xdigit:]]+]]" // CHECK: "clang-module-deps": [] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/ZAtImport-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}ZAtImport-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -211,21 +211,21 @@ // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/AtImport.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}AtImport.h" // CHECK-NEXT: ] // CHECK: "name": "ZAtImport" // CHECK: } // CHECK-NEXT: { // CHECK: "cas-include-tree-id": "[[PRAGMA_IMPORT_TREE:llvmcas://[[:xdigit:]]+]]" // CHECK: "clang-module-deps": [] -// CHECK: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// CHECK: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-o" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/ZPragmaImport-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}ZPragmaImport-{{.*}}.pcm" // CHECK: "-disable-free" // CHECK: "-fno-pch-timestamp" // CHECK: "-fcas-include-tree" @@ -237,8 +237,8 @@ // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/module.modulemap" -// CHECK-NEXT: "[[PREFIX]]/PragmaImport.h" +// CHECK-NEXT: "PREFIX{{/|\\\\}}module.modulemap" +// CHECK-NEXT: "PREFIX{{/|\\\\}}PragmaImport.h" // CHECK-NEXT: ] // CHECK: "name": "ZPragmaImport" // CHECK: } @@ -265,7 +265,7 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK-NOT: -fmodule-map-file // CHECK: "-disable-free" // CHECK: "-fcas-include-tree" @@ -273,20 +273,20 @@ // CHECK: "-fcache-compile-job" // CHECK: "-fsyntax-only" // CHECK: "-fmodule-file-cache-key" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Left-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Left-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" // CHECK: "-fmodule-file-cache-key" -// CHECK-NEXT: "[[PREFIX]]/outputs/{{.*}}/Right-{{.*}}.pcm" +// CHECK-NEXT: "PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK-NEXT: "llvmcas://{{[[:xdigit:]]+}}" -// CHECK: "-fmodule-file=Left=[[PREFIX]]/outputs/{{.*}}/Left-{{.*}}.pcm" -// CHECK: "-fmodule-file=Right=[[PREFIX]]/outputs/{{.*}}/Right-{{.*}}.pcm" +// CHECK: "-fmodule-file=Left=PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Left-{{.*}}.pcm" +// CHECK: "-fmodule-file=Right=PREFIX{{/|\\\\}}outputs{{/|\\\\}}{{.*}}{{/|\\\\}}Right-{{.*}}.pcm" // CHECK: "-fmodules" // CHECK: "-fno-implicit-modules" // CHECK: ] // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/tu.m" +// CHECK-NEXT: "PREFIX{{/|\\\\}}tu.m" // CHECK-NEXT: ] -// CHECK: "input-file": "[[PREFIX]]/tu.m" +// CHECK: "input-file": "PREFIX{{/|\\\\}}tu.m" // CHECK: } // CHECK-NEXT: ] // CHECK-NEXT: } diff --git a/clang/test/ClangScanDeps/modules-pch-cas-fs-prefix-mapping-caching.c b/clang/test/ClangScanDeps/modules-pch-cas-fs-prefix-mapping-caching.c index 3341c048b87ee..b68a623fe3774 100644 --- a/clang/test/ClangScanDeps/modules-pch-cas-fs-prefix-mapping-caching.c +++ b/clang/test/ClangScanDeps/modules-pch-cas-fs-prefix-mapping-caching.c @@ -5,62 +5,72 @@ // RUN: rm -rf %t // RUN: split-file %s %t // RUN: cp -r %t/dir1 %t/dir2 -// RUN: sed -e "s|DIR|%t/dir1|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb.json.template > %t/dir1/cdb.json -// RUN: sed -e "s|DIR|%t/dir1|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb_pch.json.template > %t/dir1/cdb_pch.json -// RUN: sed -e "s|DIR|%t/dir2|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb.json.template > %t/dir2/cdb.json -// RUN: sed -e "s|DIR|%t/dir2|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb_pch.json.template > %t/dir2/cdb_pch.json +// RUN: sed -e "s|DIR|%/t/dir1|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb.json.template > %t/dir1/cdb.json +// RUN: sed -e "s|DIR|%/t/dir1|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb_pch.json.template > %t/dir1/cdb_pch.json +// RUN: sed -e "s|DIR|%/t/dir2|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb.json.template > %t/dir2/cdb.json +// RUN: sed -e "s|DIR|%/t/dir2|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb_pch.json.template > %t/dir2/cdb_pch.json // == Scan PCH // RUN: clang-scan-deps -compilation-database %t/dir1/cdb_pch.json -format experimental-full -optimize-args=none \ // RUN: -cas-path %t/cas -module-files-dir %t/dir1/modules \ -// RUN: -prefix-map=%t/dir1/modules=/^modules -prefix-map=%t/dir1=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/dir1/modules=%/root^modules -prefix-map=%t/dir1=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: > %t/pch_dir1.txt // RUN: clang-scan-deps -compilation-database %t/dir2/cdb_pch.json -format experimental-full -optimize-args=none \ // RUN: -cas-path %t/cas -module-files-dir %t/dir2/modules \ -// RUN: -prefix-map=%t/dir2/modules=/^modules -prefix-map=%t/dir2=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/dir2/modules=%/root^modules -prefix-map=%t/dir2=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: > %t/pch_dir2.txt // == Build PCH // RUN: %deps-to-rsp %t/pch_dir1.txt --module-name=B > %t/dir1/B.cc1.rsp // RUN: %deps-to-rsp %t/pch_dir1.txt --module-name=A > %t/dir1/A.cc1.rsp // RUN: %deps-to-rsp %t/pch_dir1.txt --tu-index 0 > %t/dir1/pch.cc1.rsp -// RUN: (cd %t/dir1; %clang @B.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-MISS -// RUN: (cd %t/dir1; %clang @A.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-MISS -// RUN: (cd %t/dir1; %clang @pch.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-MISS +// RUN: cd %t/dir1 && %clang @B.cc1.rsp > %t/miss-B.txt 2>&1 +// RUN: cat %t/miss-B.txt | FileCheck %s -check-prefix=CACHE-MISS +// RUN: cd %t/dir1 && %clang @A.cc1.rsp > %t/miss-A.txt 2>&1 +// RUN: cat %t/miss-A.txt | FileCheck %s -check-prefix=CACHE-MISS +// RUN: cd %t/dir1 && %clang @pch.cc1.rsp > %t/miss-pch.txt 2>&1 +// RUN: cat %t/miss-pch.txt | FileCheck %s -check-prefix=CACHE-MISS // CACHE-MISS: compile job cache miss // RUN: %deps-to-rsp %t/pch_dir2.txt --module-name=B > %t/dir2/B.cc1.rsp // RUN: %deps-to-rsp %t/pch_dir2.txt --module-name=A > %t/dir2/A.cc1.rsp // RUN: %deps-to-rsp %t/pch_dir2.txt --tu-index 0 > %t/dir2/pch.cc1.rsp -// RUN: (cd %t/dir2; %clang @B.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-HIT -// RUN: (cd %t/dir2; %clang @A.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-HIT -// RUN: (cd %t/dir2; %clang @pch.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-HIT +// RUN: cd %t/dir2 && %clang @B.cc1.rsp > %t/hit-B.txt 2>&1 +// RUN: cat %t/hit-B.txt | FileCheck %s -check-prefix=CACHE-HIT +// RUN: cd %t/dir2 && %clang @A.cc1.rsp > %t/hit-A.txt 2>&1 +// RUN: cat %t/hit-B.txt | FileCheck %s -check-prefix=CACHE-HIT +// RUN: cd %t/dir2 && %clang @pch.cc1.rsp > %t/hit-pch.txt 2>&1 +// RUN: cat %t/hit-pch.txt | FileCheck %s -check-prefix=CACHE-HIT // CACHE-HIT: compile job cache hit // == Scan TU, including PCH // RUN: clang-scan-deps -compilation-database %t/dir1/cdb.json -format experimental-full -optimize-args=none \ // RUN: -cas-path %t/cas -module-files-dir %t/dir1/modules \ -// RUN: -prefix-map=%t/dir1/modules=/^modules -prefix-map=%t/dir1=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/dir1/modules=%/root^modules -prefix-map=%t/dir1=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: > %t/dir1.txt // RUN: clang-scan-deps -compilation-database %t/dir2/cdb.json -format experimental-full -optimize-args=none \ // RUN: -cas-path %t/cas -module-files-dir %t/dir2/modules \ -// RUN: -prefix-map=%t/dir2/modules=/^modules -prefix-map=%t/dir2=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/dir2/modules=%/root^modules -prefix-map=%t/dir2=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: > %t/dir2.txt // == Build TU // RUN: %deps-to-rsp %t/dir1.txt --module-name=C > %t/dir1/C.cc1.rsp // RUN: %deps-to-rsp %t/dir1.txt --tu-index 0 > %t/dir1/tu.cc1.rsp -// RUN: (cd %t/dir1; %clang @C.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-MISS -// RUN: (cd %t/dir1; %clang @tu.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-MISS +// RUN: cd %t/dir1 && %clang @C.cc1.rsp > %t/c-miss.txt 2>&1 +// RUN: cat %t/c-miss.txt | FileCheck %s -check-prefix=CACHE-MISS +// RUN: cd %t/dir1 && %clang @tu.cc1.rsp > %t/tu-miss.txt 2>&1 +// RUN: cat %t/tu-miss.txt | FileCheck %s -check-prefix=CACHE-MISS // RUN: %deps-to-rsp %t/dir2.txt --module-name=C > %t/dir2/C.cc1.rsp // RUN: %deps-to-rsp %t/dir2.txt --tu-index 0 > %t/dir2/tu.cc1.rsp -// RUN: (cd %t/dir2; %clang @C.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-HIT -// RUN: (cd %t/dir2; %clang @tu.cc1.rsp) 2>&1 | FileCheck %s -check-prefix=CACHE-HIT +// RUN: cd %t/dir2 && %clang @C.cc1.rsp > %t/c-hit.txt 2>&1 +// RUN: cat %t/c-hit.txt | FileCheck %s -check-prefix=CACHE-HIT +// RUN: cd %t/dir2 && %clang @tu.cc1.rsp > %t/tu-hit.txt 2>&1 +// RUN: cat %t/tu-hit.txt | FileCheck %s -check-prefix=CACHE-HIT // RUN: diff -u %t/dir1/prefix.h.pch %t/dir2/prefix.h.pch // RUN: diff -r -u %t/dir1/modules %t/dir2/modules diff --git a/clang/test/ClangScanDeps/modules-pch-cas-fs-prefix-mapping.c b/clang/test/ClangScanDeps/modules-pch-cas-fs-prefix-mapping.c index aee657ce58e3d..8dad299143de9 100644 --- a/clang/test/ClangScanDeps/modules-pch-cas-fs-prefix-mapping.c +++ b/clang/test/ClangScanDeps/modules-pch-cas-fs-prefix-mapping.c @@ -5,17 +5,17 @@ // RUN: rm -rf %t // RUN: split-file %s %t -// RUN: sed -e "s|DIR|%t|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb.json.template > %t/cdb.json -// RUN: sed -e "s|DIR|%t|g" -e "s|CLANG|%clang|g" -e "s|SDK|%S/Inputs/SDK|g" %t/cdb_pch.json.template > %t/cdb_pch.json +// RUN: sed -e "s|DIR|%/t|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb.json.template > %t/cdb.json +// RUN: sed -e "s|DIR|%/t|g" -e "s|CLANG|%/ncclang|g" -e "s|SDK|%/S/Inputs/SDK|g" %t/cdb_pch.json.template > %t/cdb_pch.json // == Scan PCH // RUN: clang-scan-deps -compilation-database %t/cdb_pch.json -format experimental-full \ // RUN: -cas-path %t/cas -module-files-dir %t/modules \ -// RUN: -prefix-map=%t/modules=/^modules -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/modules=%/root^modules -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: > %t/pch_result.txt // == Check specifics of the PCH command-line -// RUN: FileCheck %s -input-file %t/pch_result.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefix=PCH +// RUN: cat %t/pch_result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize SDK_PREFIX=%/S/Inputs/SDK --sanitize ROOT^=%/root^ --enable-yaml-compatibility %s -check-prefix=PCH // == Build PCH // RUN: %deps-to-rsp %t/pch_result.txt --module-name=B > %t/B.cc1.rsp @@ -30,11 +30,11 @@ // == Scan TU, including PCH // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full \ // RUN: -cas-path %t/cas -module-files-dir %t/modules \ -// RUN: -prefix-map=%t/modules=/^modules -prefix-map=%t=/^src -prefix-map-sdk=/^sdk -prefix-map-toolchain=/^tc \ +// RUN: -prefix-map=%t/modules=%/root^modules -prefix-map=%t=%/root^src -prefix-map-sdk=%/root^sdk -prefix-map-toolchain=%/root^tc \ // RUN: > %t/result.txt // == Check specifics of the TU command-line -// RUN: FileCheck %s -input-file %t/result.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK +// RUN: cat %t/result.txt | %PathSanitizingFileCheck --sanitize PREFIX=%/t --sanitize SDK_PREFIX=%/S/Inputs/SDK --sanitize ROOT^=%/root^ --enable-yaml-compatibility %s // == Build TU // RUN: %deps-to-rsp %t/result.txt --module-name=C > %t/C.cc1.rsp @@ -55,20 +55,20 @@ // RUN: llvm-cas -cas %t/cas -ls-tree-recursive @%t/pch_id.txt > %t/pch_fs.txt // RUN: llvm-cas -cas %t/cas -ls-tree-recursive @%t/tu_id.txt > %t/tu_fs.txt -// RUN: FileCheck %s -input-file %t/A_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefixes=FS_NEG,FS -// RUN: FileCheck %s -input-file %t/B_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefixes=FS_NEG,FS -// RUN: FileCheck %s -input-file %t/C_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefixes=FS_NEG,FS -// RUN: FileCheck %s -input-file %t/pch_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefixes=FS_NEG,FS -// RUN: FileCheck %s -input-file %t/tu_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -check-prefixes=FS_NEG,FS +// RUN: FileCheck %s -input-file %t/A_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -DROOT=%{/roott} -check-prefixes=FS_NEG,FS +// RUN: FileCheck %s -input-file %t/B_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -DROOT=%{/roott} -check-prefixes=FS_NEG,FS +// RUN: FileCheck %s -input-file %t/C_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -DROOT=%{/roott} -check-prefixes=FS_NEG,FS +// RUN: FileCheck %s -input-file %t/pch_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -DROOT=%{/roott} -check-prefixes=FS_NEG,FS +// RUN: FileCheck %s -input-file %t/tu_fs.txt -DPREFIX=%t -DSDK_PREFIX=%S/Inputs/SDK -DROOT=%{/roott} -check-prefixes=FS_NEG,FS // FS_NEG-NOT: [[PREFIX]] // FS_NEG-NOT: [[SDK_PREFIX]] // FS_NEG-NOT: .pcm{{$}} -// FS: file llvmcas://{{.*}} /^sdk/usr/include/stdlib.h -// FS: file llvmcas://{{.*}} /^src/a.h -// FS: file llvmcas://{{.*}} /^src/b.h -// FS: file llvmcas://{{.*}} /^src/module.modulemap -// FS: file llvmcas://{{.*}} /^tc/lib/clang/{{.*}}/include/stdarg.h +// FS: file llvmcas://{{.*}} [[ROOT]]^sdk/usr/include/stdlib.h +// FS: file llvmcas://{{.*}} [[ROOT]]^src/a.h +// FS: file llvmcas://{{.*}} [[ROOT]]^src/b.h +// FS: file llvmcas://{{.*}} [[ROOT]]^src/module.modulemap +// FS: file llvmcas://{{.*}} [[ROOT]]^tc/lib/clang/{{.*}}/include/stdarg.h // Check that it builds. // RUN: %clang @%t/B.cc1.rsp @@ -84,71 +84,71 @@ // PCH: "module-name": "B" // PCH: } // PCH: ] -// PCH: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// PCH: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // PCH: "command-line": [ // PCH: "-fcas-path" -// PCH: "[[PREFIX]]/cas" +// PCH: "PREFIX{{/|\\\\}}cas" // PCH: "-fcas-fs" // PCH: "[[A_ROOT_ID]]" // PCH: "-fcas-fs-working-directory" -// PCH: "/^src" -// PCH: "-fmodule-map-file=/^src/module.modulemap" +// PCH: "ROOT^src" +// PCH: "-fmodule-map-file=ROOT^src{{/|\\\\}}module.modulemap" // PCH: "-o" -// PCH: "[[PREFIX]]/modules/{{.*}}/A-{{.*}}.pcm" +// PCH: "PREFIX{{/|\\\\}}modules{{/|\\\\}}{{.*}}{{/|\\\\}}A-{{.*}}.pcm" // PCH: "-fmodule-file-cache-key" -// PCH: "/^modules/{{.*}}/B-[[B_CONTEXT_HASH:[^.]+]].pcm" +// PCH: "ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}B-[[B_CONTEXT_HASH:[^.]+]].pcm" // PCH: "llvmcas://{{.*}}" // PCH: "-x" // PCH: "c" -// PCH: "/^src/module.modulemap" +// PCH: "ROOT^src{{/|\\\\}}module.modulemap" // PCH: "-isysroot" -// PCH: "/^sdk" +// PCH: "ROOT^sdk" // PCH: "-resource-dir" -// PCH: "/^tc/lib/clang/{{.*}}" -// PCH: "-fmodule-file=B=/^modules/{{.*}}/B-[[B_CONTEXT_HASH]].pcm" +// PCH: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" +// PCH: "-fmodule-file=B=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}B-[[B_CONTEXT_HASH]].pcm" // PCH: "-isystem" -// PCH: "/^tc/lib/clang/{{.*}}/include" +// PCH: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}{{/|\\\\}}include" // PCH: "-internal-externc-isystem" -// PCH: "/^sdk/usr/include" +// PCH: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}include" // PCH: ] // PCH: "file-deps": [ -// PCH: "[[PREFIX]]/module.modulemap" -// PCH: "[[PREFIX]]/a.h" +// PCH: "PREFIX{{/|\\\\}}module.modulemap" +// PCH: "PREFIX{{/|\\\\}}a.h" // PCH: ] // PCH: "name": "A" // PCH: } // PCH: { // PCH: "casfs-root-id": "[[B_ROOT_ID:llvmcas://[[:xdigit:]]+]]" // PCH: "clang-module-deps": [], -// PCH: "clang-modulemap-file": "[[PREFIX]]/module.modulemap" +// PCH: "clang-modulemap-file": "PREFIX{{/|\\\\}}module.modulemap" // PCH: "command-line": [ // PCH: "-fcas-path" -// PCH: "[[PREFIX]]/cas" +// PCH: "PREFIX{{/|\\\\}}cas" // PCH: "-fcas-fs" // PCH: "[[B_ROOT_ID]]" // PCH: "-fcas-fs-working-directory" -// PCH: "/^src" +// PCH: "ROOT^src" // PCH: "-o" -// PCH: "[[PREFIX]]/modules/{{.*}}/B-[[B_CONTEXT_HASH]].pcm" +// PCH: "PREFIX{{/|\\\\}}modules{{/|\\\\}}{{.*}}{{/|\\\\}}B-[[B_CONTEXT_HASH]].pcm" // PCH: "-x" // PCH: "c" -// PCH: "/^src/module.modulemap" +// PCH: "ROOT^src{{/|\\\\}}module.modulemap" // PCH: "-isysroot" -// PCH: "/^sdk" +// PCH: "ROOT^sdk" // PCH: "-resource-dir" -// PCH: "/^tc/lib/clang/{{.*}}" +// PCH: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" // PCH: "-isystem" -// PCH: "/^tc/lib/clang/{{.*}}/include" +// PCH: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}{{/|\\\\}}include" // PCH: "-internal-externc-isystem" -// PCH: "/^sdk/usr/include" +// PCH: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}include" // PCH: ] // PCH: "context-hash": "[[B_CONTEXT_HASH]]" // PCH: "file-deps": [ // Note: PREFIX, SDK_PREFIX and toolchain path are unordered -// PCH-DAG: "[[PREFIX]]/module.modulemap" -// PCH-DAG: "[[PREFIX]]/b.h" -// PCH-DAG: "[[SDK_PREFIX]]/usr/include/stdlib.h" -// PCH-DAG: "{{.*}}/include/stdarg.h" +// PCH-DAG: "PREFIX{{/|\\\\}}module.modulemap" +// PCH-DAG: "PREFIX{{/|\\\\}}b.h" +// PCH-DAG: "SDK_PREFIX{{/|\\\\}}usr{{/|\\\\}}include{{/|\\\\}}stdlib.h" +// PCH-DAG: "{{.*}}{{/|\\\\}}include{{/|\\\\}}stdarg.h" // PCH: ] // PCH: "name": "B" // PCH: } @@ -165,32 +165,32 @@ // PCH: ] // PCH: "command-line": [ // PCH: "-fcas-path" -// PCH: "[[PREFIX]]/cas" +// PCH: "PREFIX{{/|\\\\}}cas" // PCH: "-fcas-fs" // PCH: "[[TU_ROOT_ID]]" // PCH: "-fcas-fs-working-directory" -// PCH: "/^src" -// PCH: "-fmodule-map-file=/^src/module.modulemap" +// PCH: "ROOT^src" +// PCH: "-fmodule-map-file=ROOT^src{{/|\\\\}}module.modulemap" // PCH: "-fmodule-file-cache-key" -// PCH: "/^modules/{{.*}}A-{{.*}}.pcm" +// PCH: "ROOT^modules{{/|\\\\}}{{.*}}A-{{.*}}.pcm" // PCH: "llvmcas://{{.*}}" // PCH: "-x" // PCH: "c-header" -// PCH: "/^src/prefix.h" +// PCH: "ROOT^src{{/|\\\\}}prefix.h" // PCH: "-isysroot" -// PCH: "/^sdk" +// PCH: "ROOT^sdk" // PCH: "-resource-dir" -// PCH: "/^tc/lib/clang/{{.*}}" -// PCH: "-fmodule-file=A=/^modules/{{.*}}/A-{{.*}}.pcm" +// PCH: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" +// PCH: "-fmodule-file=A=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}A-{{.*}}.pcm" // PCH: "-isystem" -// PCH: "/^tc/lib/clang/{{.*}}/include" +// PCH: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}{{/|\\\\}}include" // PCH: "-internal-externc-isystem" -// PCH: "/^sdk/usr/include" +// PCH: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}include" // PCH: ], // PCH: "file-deps": [ -// PCH: "[[PREFIX]]/prefix.h" +// PCH: "PREFIX{{/|\\\\}}prefix.h" // PCH: ] -// PCH: "input-file": "[[PREFIX]]/prefix.h" +// PCH: "input-file": "PREFIX{{/|\\\\}}prefix.h" // PCH: } // CHECK: { @@ -201,26 +201,26 @@ // CHECK: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]{{.}}cas" +// CHECK-NEXT: "PREFIX{{.}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[C_ROOT_ID]]" // CHECK: "-fcas-fs-working-directory" -// CHECK-NEXT: "/^src" +// CHECK-NEXT: "ROOT^src" // CHECK: "-fcache-compile-job" // CHECK: "-emit-module" -// CHECK: "-fmodule-file=/^modules/{{.*}}/B-{{.*}}.pcm" +// CHECK: "-fmodule-file=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}B-{{.*}}.pcm" // CHECK: "-fmodule-file-cache-key" -// CHECK: "/^modules/{{.*}}/B-{{.*}}.pcm" +// CHECK: "ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}B-{{.*}}.pcm" // CHECK: "llvmcas://{{.*}}" // CHECK: "-x" // CHECK-NEXT: "c" -// CHECK-NEXT: "/^src/module.modulemap" +// CHECK-NEXT: "ROOT^src{{/|\\\\}}module.modulemap" // CHECK: "-isysroot" -// CHECK-NEXT: "/^sdk" +// CHECK-NEXT: "ROOT^sdk" // CHECK: "-resource-dir" -// CHECK-NEXT: "/^tc/lib/clang/{{.*}}" -// CHECK-NOT: [[PREFIX]] -// CHECK-NOT: [[SDK_PREFIX]] +// CHECK-NEXT: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" +// CHECK-NOT: PREFIX +// CHECK-NOT: SDK_PREFIX // CHECK: ] // CHECK: "name": "C" // CHECK: } @@ -237,37 +237,37 @@ // CHECK: ] // CHECK: "command-line": [ // CHECK: "-fcas-path" -// CHECK-NEXT: "[[PREFIX]]/cas" +// CHECK-NEXT: "PREFIX{{/|\\\\}}cas" // CHECK: "-fcas-fs" // CHECK-NEXT: "[[TU_ROOT_ID]]" // CHECK: "-fcas-fs-working-directory" -// CHECK-NEXT: "/^src" -// CHECK: "-fmodule-map-file=/^src/module.modulemap" +// CHECK-NEXT: "ROOT^src" +// CHECK: "-fmodule-map-file=ROOT^src{{/|\\\\}}module.modulemap" // CHECK: "-fmodule-file-cache-key" -// CHECK: "/^modules/{{.*}}C-{{.*}}.pcm" +// CHECK: "ROOT^modules{{/|\\\\}}{{.*}}C-{{.*}}.pcm" // CHECK: "llvmcas://{{.*}}" // CHECK: "-x" // CHECK-NEXT: "c" -// CHECK-NEXT: "/^src/t.c" +// CHECK-NEXT: "ROOT^src{{/|\\\\}}t.c" // CHECK: "-isysroot" -// CHECK-NEXT: "/^sdk" +// CHECK-NEXT: "ROOT^sdk" // CHECK: "-resource-dir" -// CHECK-NEXT: "/^tc/lib/clang/{{.*}}" -// CHECK: "-fmodule-file=C=/^modules/{{.*}}/C-{{.*}}.pcm" +// CHECK-NEXT: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}" +// CHECK: "-fmodule-file=C=ROOT^modules{{/|\\\\}}{{.*}}{{/|\\\\}}C-{{.*}}.pcm" // CHECK: "-isystem" -// CHECK-NEXT: "/^sdk/usr/local/include" +// CHECK-NEXT: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}local{{/|\\\\}}include" // CHECK: "-isystem" -// CHECK-NEXT: "/^tc/lib/clang/{{.*}}/include" +// CHECK-NEXT: "ROOT^tc{{/|\\\\}}lib{{/|\\\\}}clang{{/|\\\\}}{{.*}}{{/|\\\\}}include" // CHECK: "-internal-externc-isystem" -// CHECK-NEXT: "/^sdk/usr/include" +// CHECK-NEXT: "ROOT^sdk{{/|\\\\}}usr{{/|\\\\}}include" // CHECK: "-include-pch" -// CHECK-NEXT: "/^src/prefix.h.pch" +// CHECK-NEXT: "ROOT^src{{/|\\\\}}prefix.h.pch" // CHECK: ], // CHECK: "file-deps": [ -// CHECK: "[[PREFIX]]/t.c" -// CHECK: "[[PREFIX]]/prefix.h.pch" +// CHECK: "PREFIX{{/|\\\\}}t.c" +// CHECK: "PREFIX{{/|\\\\}}prefix.h.pch" // CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/t.c" +// CHECK: "input-file": "PREFIX{{/|\\\\}}t.c" // CHECK: } //--- cdb.json.template diff --git a/clang/test/Driver/fdepscan-prefix-map-sdk-win.c b/clang/test/Driver/fdepscan-prefix-map-sdk-win.c new file mode 100644 index 0000000000000..5aadb9d50f3b5 --- /dev/null +++ b/clang/test/Driver/fdepscan-prefix-map-sdk-win.c @@ -0,0 +1,10 @@ +// REQUIRES: system-windows + +// RUN: %clang -fdepscan-prefix-map-sdk=\^sdk -### %s 2>&1 | FileCheck %s -check-prefix=NONE +// RUN: %clang -fdepscan-prefix-map-sdk=\^sdk -isysroot relative -### %s 2>&1 | FileCheck %s -check-prefix=NONE + +// NONE-NOT: -fdepscan-prefix-map + +// RUN: %clang -fdepscan-prefix-map-sdk=\^sdk -isysroot C:\sys\path -### %s 2>&1 | FileCheck %s +// RUN: %clang -fdepscan-prefix-map-sdk=\^sdk --sysroot C:\sys\path -### %s 2>&1 | FileCheck %s +// CHECK: "-fdepscan-prefix-map" "C:\\sys\\path" "\\^sdk" diff --git a/clang/test/Driver/fdepscan-prefix-map-sdk.c b/clang/test/Driver/fdepscan-prefix-map-sdk.c index b2c61a6131a83..9d9e4185c0ad4 100644 --- a/clang/test/Driver/fdepscan-prefix-map-sdk.c +++ b/clang/test/Driver/fdepscan-prefix-map-sdk.c @@ -1,3 +1,5 @@ +// REQUIRES: !system-windows + // RUN: %clang -fdepscan-prefix-map-sdk=/^sdk -### %s 2>&1 | FileCheck %s -check-prefix=NONE // RUN: %clang -fdepscan-prefix-map-sdk=/^sdk -isysroot relative -### %s 2>&1 | FileCheck %s -check-prefix=NONE diff --git a/clang/test/Driver/fdepscan-prefix-map-toolchain-win.c b/clang/test/Driver/fdepscan-prefix-map-toolchain-win.c new file mode 100644 index 0000000000000..7bff2d88bdc39 --- /dev/null +++ b/clang/test/Driver/fdepscan-prefix-map-toolchain-win.c @@ -0,0 +1,17 @@ +// REQUIRES: system-windows + +// RUN: %clang -fdepscan-prefix-map-toolchain=\^tc -resource-dir '' -### %s 2>&1 | FileCheck %s -check-prefix=NONE +// RUN: %clang -fdepscan-prefix-map-toolchain=\^tc -resource-dir relative -### %s 2>&1 | FileCheck %s -check-prefix=NONE +// RUN: %clang -fdepscan-prefix-map-toolchain=\^tc -resource-dir C:\lib\clang\10 -### %s 2>&1 | FileCheck %s -check-prefix=NONE + +// NONE-NOT: -fdepscan-prefix-map + +// RUN: %clang -fdepscan-prefix-map-toolchain=\^tc -resource-dir C:\tc\10 -### %s 2>&1 | FileCheck %s +// RUN: %clang -fdepscan-prefix-map-toolchain=\^tc -resource-dir C:\tc\lib\clang\10 -### %s 2>&1 | FileCheck %s +// RUN: %clang -fdepscan-prefix-map-toolchain=\^tc -resource-dir C:\tc\usr\lib\clang\10 -### %s 2>&1 | FileCheck %s + +// CHECK: "-fdepscan-prefix-map" "C:\\tc" "\\^tc" + +// Implicit resource-dir +// RUN: %clang -fdepscan-prefix-map-toolchain=\^tc -### %s 2>&1 | FileCheck %s -check-prefix=CHECK_IMPLICIT +// CHECK_IMPLICIT: "-fdepscan-prefix-map" "{{.*}}" "\\^tc" diff --git a/clang/test/Driver/fdepscan-prefix-map-toolchain.c b/clang/test/Driver/fdepscan-prefix-map-toolchain.c index 4f2853583840a..42e9cd9dc05db 100644 --- a/clang/test/Driver/fdepscan-prefix-map-toolchain.c +++ b/clang/test/Driver/fdepscan-prefix-map-toolchain.c @@ -1,3 +1,5 @@ +// REQUIRES: !system-windows + // RUN: %clang -fdepscan-prefix-map-toolchain=/^tc -resource-dir '' -### %s 2>&1 | FileCheck %s -check-prefix=NONE // RUN: %clang -fdepscan-prefix-map-toolchain=/^tc -resource-dir relative -### %s 2>&1 | FileCheck %s -check-prefix=NONE // RUN: %clang -fdepscan-prefix-map-toolchain=/^tc -resource-dir /lib/clang/10 -### %s 2>&1 | FileCheck %s -check-prefix=NONE diff --git a/clang/test/Driver/fdepscan-prefix-map-win.c b/clang/test/Driver/fdepscan-prefix-map-win.c new file mode 100644 index 0000000000000..e5a06befc560b --- /dev/null +++ b/clang/test/Driver/fdepscan-prefix-map-win.c @@ -0,0 +1,13 @@ +// REQUIRES: system-windows + +// RUN: not %clang -fdepscan-prefix-map=\^bad -### %s 2>&1 | FileCheck %s -check-prefix=INVALID +// RUN: not %clang -fdepscan-prefix-map==\^bad -### %s 2>&1 | FileCheck %s -check-prefix=INVALID +// RUN: not %clang -fdepscan-prefix-map=relative=\^bad -### %s 2>&1 | FileCheck %s -check-prefix=INVALID +// RUN: not %clang -fdepscan-prefix-map=\=\^bad -### %s 2>&1 | FileCheck %s -check-prefix=INVALID +// INVALID: error: invalid argument '{{.*}}\^bad' to -fdepscan-prefix-map= + +// RUN: %clang -fdepscan-prefix-map=C:\good=\^good -### %s 2>&1 | FileCheck --check-prefix CHECK_CORRECT %s +// CHECK_CORRECT: "-fdepscan-prefix-map" "C:\\good" "\\^good" + +// RUN %clang -fdepscan-prefix-map=C:\a=\^a -fdepscan-prefix-map C:\b \^b -fdepscan-prefix-map=C:\c=\^c -fdepscan-prefix-map C:\d \^d -### %s 2>&1 | FileCheck --check-prefix=CHECK_MIXED %s +// CHECK_MIXED: "-fdepscan-prefix-map" "C:\\a" "\\^a" "-fdepscan-prefix-map" "C:\\b" "\\^b" "-fdepscan-prefix-map" "C:\\c" "\\^c" "-fdepscan-prefix-map" "C:\\d" "\\^d" diff --git a/clang/test/Driver/fdepscan-prefix-map.c b/clang/test/Driver/fdepscan-prefix-map.c index d752e09b49d13..d4d8124aa22d2 100644 --- a/clang/test/Driver/fdepscan-prefix-map.c +++ b/clang/test/Driver/fdepscan-prefix-map.c @@ -1,3 +1,5 @@ +// REQUIRES: !system-windows + // RUN: not %clang -fdepscan-prefix-map=/^bad -### %s 2>&1 | FileCheck %s -check-prefix=INVALID // RUN: not %clang -fdepscan-prefix-map==/^bad -### %s 2>&1 | FileCheck %s -check-prefix=INVALID // RUN: not %clang -fdepscan-prefix-map=relative=/^bad -### %s 2>&1 | FileCheck %s -check-prefix=INVALID diff --git a/clang/test/Index/Core/scan-deps-cas.m b/clang/test/Index/Core/scan-deps-cas.m index 07e737a5864d2..dfc302abd9e99 100644 --- a/clang/test/Index/Core/scan-deps-cas.m +++ b/clang/test/Index/Core/scan-deps-cas.m @@ -6,19 +6,19 @@ // RUN: -- %clang -c -I %S/Inputs/module \ // RUN: -fmodules -fmodules-cache-path=%t/mcpit \ // RUN: -o FoE.o -x objective-c %s > %t.result -// RUN: cat %t.result | sed 's/\\/\//g' | FileCheck %s -DPREFIX=%S -DOUTPUTS=%/t -check-prefix=INCLUDE_TREE +// RUN: cat %t.result | FileCheck %s -DPREFIX=%S -DOUTPUTS=%/t -check-prefix=INCLUDE_TREE // RUN: env CLANG_CACHE_USE_CASFS_DEPSCAN=1 c-index-test core --scan-deps -working-dir %S -output-dir=%t -cas-path %t/cas \ // RUN: -- %clang -c -I %S/Inputs/module \ // RUN: -fmodules -fmodules-cache-path=%t/mcp \ // RUN: -o FoE.o -x objective-c %s > %t.casfs.result -// RUN: cat %t.casfs.result | sed 's/\\/\//g' | FileCheck %s -DPREFIX=%S -DOUTPUTS=%/t +// RUN: cat %t.casfs.result | FileCheck %s -DPREFIX=%S -DOUTPUTS=%/t // RUN: env CLANG_CACHE_USE_INCLUDE_TREE=1 c-index-test core --scan-deps -working-dir %S -output-dir=%t -cas-path %t/cas \ // RUN: -- %clang -c -I %S/Inputs/module \ // RUN: -fmodules -fmodules-cache-path=%t/mcpit \ // RUN: -o FoE.o -x objective-c %s > %t.includetree.result -// RUN: cat %t.includetree.result | sed 's/\\/\//g' | FileCheck %s -DPREFIX=%S -DOUTPUTS=%/t -check-prefix=INCLUDE_TREE +// RUN: cat %t.includetree.result | FileCheck %s -DPREFIX=%S -DOUTPUTS=%/t -check-prefix=INCLUDE_TREE // RUN: c-index-test core --scan-deps -working-dir %S -output-dir=%t \ // RUN: -- %clang -c -I %S/Inputs/module \ @@ -35,15 +35,15 @@ // CHECK-NEXT: name: ModA // CHECK-NEXT: context-hash: [[HASH_MOD_A:[A-Z0-9]+]] // CHECK-NEXT: cwd-ignored: 0 -// CHECK-NEXT: module-map-path: [[PREFIX]]/Inputs/module/module.modulemap +// CHECK-NEXT: module-map-path: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}module.modulemap // CHECK-NEXT: casfs-root-id: [[CASFS_MODA_ROOT_ID:llvmcas://[[:xdigit:]]+]] // CHECK-NEXT: cache-key: [[CASFS_MODA_CACHE_KEY:llvmcas://[[:xdigit:]]+]] // CHECK-NEXT: module-deps: // CHECK-NEXT: file-deps: -// CHECK-NEXT: [[PREFIX]]/Inputs/module/module.modulemap -// CHECK-NEXT: [[PREFIX]]/Inputs/module/ModA.h -// CHECK-NEXT: [[PREFIX]]/Inputs/module/SubModA.h -// CHECK-NEXT: [[PREFIX]]/Inputs/module/SubSubModA.h +// CHECK-NEXT: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}module.modulemap +// CHECK-NEXT: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}ModA.h +// CHECK-NEXT: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}SubModA.h +// CHECK-NEXT: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}SubSubModA.h // CHECK-NEXT: link libraries: // CHECK-NEXT: libModA(framework) // CHECK-NEXT: libModB @@ -65,7 +65,7 @@ // CHECK-NEXT: module-deps: // CHECK-NEXT: ModA:[[HASH_MOD_A]] // CHECK-NEXT: file-deps: -// CHECK-NEXT: [[PREFIX]]/scan-deps-cas.m +// CHECK-NEXT: [[PREFIX]]{{[/\\]}}scan-deps-cas.m // CHECK-NEXT: build-args: // CHECK-SAME: -cc1 // CHECK-SAME: -fcas-path @@ -80,15 +80,15 @@ // INCLUDE_TREE-NEXT: name: ModA // INCLUDE_TREE-NEXT: context-hash: [[HASH_MOD_A:[A-Z0-9]+]] // INCLUDE_TREE-NEXT: cwd-ignored: 0 -// INCLUDE_TREE-NEXT: module-map-path: [[PREFIX]]/Inputs/module/module.modulemap +// INCLUDE_TREE-NEXT: module-map-path: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}module.modulemap // INCLUDE_TREE-NEXT: include-tree-id: [[ModA_INCLUDE_TREE_ID:llvmcas://[[:xdigit:]]+]] // INCLUDE_TREE-NEXT: cache-key: [[ModA_CACHE_KEY:llvmcas://[[:xdigit:]]+]] // INCLUDE_TREE-NEXT: module-deps: // INCLUDE_TREE-NEXT: file-deps: -// INCLUDE_TREE-NEXT: [[PREFIX]]/Inputs/module/module.modulemap -// INCLUDE_TREE-NEXT: [[PREFIX]]/Inputs/module/ModA.h -// INCLUDE_TREE-NEXT: [[PREFIX]]/Inputs/module/SubModA.h -// INCLUDE_TREE-NEXT: [[PREFIX]]/Inputs/module/SubSubModA.h +// INCLUDE_TREE-NEXT: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}module.modulemap +// INCLUDE_TREE-NEXT: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}ModA.h +// INCLUDE_TREE-NEXT: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}SubModA.h +// INCLUDE_TREE-NEXT: [[PREFIX]]{{[/\\]}}Inputs{{[/\\]}}module{{[/\\]}}SubSubModA.h // INCLUDE_TREE-NEXT: link libraries: // INCLUDE_TREE-NEXT: libModA(framework) // INCLUDE_TREE-NEXT: libModB @@ -107,7 +107,7 @@ // INCLUDE_TREE-NEXT: module-deps: // INCLUDE_TREE-NEXT: ModA:[[HASH_MOD_A]] // INCLUDE_TREE-NEXT: file-deps: -// INCLUDE_TREE-NEXT: [[PREFIX]]/scan-deps-cas.m +// INCLUDE_TREE-NEXT: [[PREFIX]]{{[/\\]}}scan-deps-cas.m // INCLUDE_TREE-NEXT: build-args: // INCLUDE_TREE-SAME: -cc1 // INCLUDE_TREE-SAME: -fcas-path diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index 09b997e00c9c4..c8b95ec3eb66f 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -250,6 +250,18 @@ def have_host_clang_repl_cuda(): ) ) +config.substitutions.append( + ( + "%PathSanitizingFileCheck", + '"%s" %s %s' + % ( + config.python_executable, + os.path.join(config.clang_src_dir, "utils", "PathSanitizingFileCheck"), + '--enable-windows-compatibility' if platform.system() == 'Windows' else '', + ), + ) +) + # Determine whether the test target is compatible with execution on the host. if "aarch64" in config.host_arch: config.available_features.add("aarch64-host") diff --git a/clang/tools/driver/cc1depscan_main.cpp b/clang/tools/driver/cc1depscan_main.cpp index ef75a1f3fddd5..d1634c527ba3e 100644 --- a/clang/tools/driver/cc1depscan_main.cpp +++ b/clang/tools/driver/cc1depscan_main.cpp @@ -59,6 +59,7 @@ #if LLVM_ON_UNIX #include // FIXME: Unix-only. Not portable. #include // FIXME: Unix-only. Not portable. +#endif // LLVM_ON_UNIX #ifdef CLANG_HAVE_RLIMITS #include @@ -66,7 +67,9 @@ using namespace clang; using namespace llvm::opt; +#if LLVM_ON_UNIX using cc1depscand::DepscanSharing; +#endif // LLVM_ON_UNIX using llvm::Error; #define DEBUG_TYPE "cc1depscand" @@ -203,6 +206,7 @@ class SharedStream { }; } // namespace +#ifdef LLVM_ON_UNIX namespace { /// FIXME: Move to LLVMSupport; probably llvm/Support/Process.h. /// @@ -354,6 +358,7 @@ makeDepscanDaemonPath(StringRef Mode, const DepscanSharing &Sharing) { return std::nullopt; } +#endif // LLVM_ON_UNIX static int scanAndUpdateCC1Inline(const char *Exec, ArrayRef InputArgs, @@ -371,6 +376,7 @@ static Expected scanAndUpdateCC1InlineWithTool( SmallVectorImpl &OutputArgs, llvm::cas::ObjectStore &DB, llvm::function_ref SaveArg); +#ifdef LLVM_ON_UNIX static int scanAndUpdateCC1UsingDaemon( const char *Exec, ArrayRef OldArgs, StringRef WorkingDirectory, SmallVectorImpl &NewArgs, @@ -432,6 +438,7 @@ static int scanAndUpdateCC1UsingDaemon( return 0; } +#endif // LLVM_ON_UNIX // FIXME: This is a copy of Command::writeResponseFile. Command is too deeply // tied with clang::Driver to use directly. @@ -480,6 +487,7 @@ static int scanAndUpdateCC1(const char *Exec, ArrayRef OldArgs, } // Collect these before returning to ensure they're claimed. +#ifdef LLVM_ON_UNIX DepscanSharing Sharing; if (Arg *A = Args.getLastArg(options::OPT_fdepscan_share_stop_EQ)) Sharing.Stop = A->getValue(); @@ -515,9 +523,11 @@ static int scanAndUpdateCC1(const char *Exec, ArrayRef OldArgs, } } +#endif // LLVM_ON_UNIX bool ProduceIncludeTree = Args.hasArg(options::OPT_fdepscan_include_tree); auto SaveArg = [&Args](const Twine &T) { return Args.MakeArgString(T); }; +#ifdef LLVM_ON_UNIX CompilerInvocation::GenerateCASArgs(CASOpts, Sharing.CASArgs, SaveArg); if (ProduceIncludeTree) Sharing.CASArgs.push_back("-fdepscan-include-tree"); @@ -526,6 +536,7 @@ static int scanAndUpdateCC1(const char *Exec, ArrayRef OldArgs, return scanAndUpdateCC1UsingDaemon(Exec, OldArgs, WorkingDirectory, NewArgs, *DaemonPath, Sharing, Diag, SaveArg, CASOpts, RootID); +#endif // LLVM_ON_UNIX return scanAndUpdateCC1Inline(Exec, OldArgs, WorkingDirectory, NewArgs, ProduceIncludeTree, SaveArg, CASOpts, Diag, @@ -626,6 +637,7 @@ int cc1depscan_main(ArrayRef Argv, const char *Argv0, return 0; } +#ifdef LLVM_ON_UNIX namespace { struct ScanServer { const char *Argv0 = nullptr; @@ -1079,6 +1091,7 @@ int ScanServer::listen() { return 0; } +#endif // LLVM_ON_UNIX static Expected scanAndUpdateCC1InlineWithTool( tooling::dependencies::DependencyScanningTool &Tool, @@ -1151,4 +1164,3 @@ scanAndUpdateCC1Inline(const char *Exec, ArrayRef InputArgs, return DiagsConsumer->getNumErrors() != 0; } -#endif /* LLVM_ON_UNIX */ diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index b37fd7e426c53..aca3577b410b0 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -92,9 +92,9 @@ extern int cc1_main(ArrayRef Argv, const char *Argv0, #if LLVM_ON_UNIX extern int cc1depscand_main(ArrayRef Argv, const char *Argv0, void *MainAddr); +#endif /* LLVM_ON_UNIX */ extern int cc1depscan_main(ArrayRef Argv, const char *Argv0, void *MainAddr); -#endif /* LLVM_ON_UNIX */ extern int cc1as_main(ArrayRef Argv, const char *Argv0, void *MainAddr); extern int cc1gen_reproducer_main(ArrayRef Argv, @@ -250,10 +250,10 @@ static int ExecuteCC1Tool(SmallVectorImpl &ArgV, if (Tool == "-cc1depscand") return cc1depscand_main(ArrayRef(ArgV).slice(2), ArgV[0], GetExecutablePathVP); +#endif /* LLVM_ON_UNIX */ if (Tool == "-cc1depscan") return cc1depscan_main(ArrayRef(ArgV).slice(2), ArgV[0], GetExecutablePathVP); -#endif /* LLVM_ON_UNIX */ if (Tool == "-cc1as") return cc1as_main(ArrayRef(ArgV).slice(2), ArgV[0], GetExecutablePathVP); if (Tool == "-cc1gen-reproducer") diff --git a/clang/unittests/CAS/IncludeTreeTest.cpp b/clang/unittests/CAS/IncludeTreeTest.cpp index ef4a1eb777f33..677f7a5c621d4 100644 --- a/clang/unittests/CAS/IncludeTreeTest.cpp +++ b/clang/unittests/CAS/IncludeTreeTest.cpp @@ -17,6 +17,7 @@ using namespace tooling; using namespace dependencies; TEST(IncludeTree, IncludeTreeScan) { + StringRef PathSep = llvm::sys::path::get_separator(); std::shared_ptr DB = llvm::cas::createInMemoryCAS(); auto FS = llvm::makeIntrusiveRefCnt(); FS->setCurrentWorkingDirectory("/root"); @@ -109,7 +110,7 @@ TEST(IncludeTree, IncludeTreeScan) { EXPECT_EQ(A1->getFileCharacteristic(), SrcMgr::C_User); IncludeTree::FileInfo FI; ASSERT_THAT_ERROR(A1File->getFileInfo().moveInto(FI), llvm::Succeeded()); - EXPECT_EQ(FI.Filename, "./a1.h"); + EXPECT_EQ(FI.Filename, "." + PathSep.str() + "a1.h"); EXPECT_EQ(FI.Contents, A1Contents); EXPECT_FALSE(A1->getCheckResult(0)); EXPECT_TRUE(A1->getCheckResult(1)); @@ -123,7 +124,7 @@ TEST(IncludeTree, IncludeTreeScan) { EXPECT_EQ(B1->getFileCharacteristic(), SrcMgr::C_User); IncludeTree::FileInfo FI; ASSERT_THAT_ERROR(B1->getBaseFileInfo().moveInto(FI), llvm::Succeeded()); - EXPECT_EQ(FI.Filename, "./b1.h"); + EXPECT_EQ(FI.Filename, "." + PathSep.str() + "b1.h"); EXPECT_EQ(FI.Contents, ""); ASSERT_EQ(B1->getNumIncludes(), uint32_t(0)); @@ -138,7 +139,7 @@ TEST(IncludeTree, IncludeTreeScan) { EXPECT_EQ(Sys->getFileCharacteristic(), SrcMgr::C_System); IncludeTree::FileInfo FI; ASSERT_THAT_ERROR(Sys->getBaseFileInfo().moveInto(FI), llvm::Succeeded()); - EXPECT_EQ(FI.Filename, "sys/sys.h"); + EXPECT_EQ(FI.Filename, "sys" + PathSep.str() + "sys.h"); EXPECT_EQ(FI.Contents, ""); ASSERT_EQ(Sys->getNumIncludes(), uint32_t(0)); @@ -298,6 +299,7 @@ TEST(IncludeTree, IncludeTreeFileListDuplicates) { } TEST(IncludeTree, IncludeTreeFileSystemOverlay) { + StringRef PathSep = llvm::sys::path::get_separator(); std::shared_ptr DB = llvm::cas::createInMemoryCAS(); SmallVector Files; for (unsigned I = 0; I < 10; ++I) { @@ -328,11 +330,12 @@ TEST(IncludeTree, IncludeTreeFileSystemOverlay) { std::error_code EC; int NumFile = 0; - for (auto I = OverlayFS.dir_begin("/dir", EC); + for (auto I = OverlayFS.dir_begin(PathSep.str() + "dir", EC); !EC && I != llvm::vfs::directory_iterator(); I.increment(EC)) { ASSERT_FALSE(EC); ++NumFile; - std::string Path = "/dir/file" + std::to_string(NumFile); + std::string Path = PathSep.str() + "dir" + PathSep.str() + "file" + + std::to_string(NumFile); ASSERT_EQ(I->path(), Path); } ASSERT_EQ(NumFile, 2); diff --git a/clang/unittests/Tooling/DependencyScanningCASFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanningCASFilesystemTest.cpp index cf31eba9d0f54..de2e308407020 100644 --- a/clang/unittests/Tooling/DependencyScanningCASFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanningCASFilesystemTest.cpp @@ -24,7 +24,13 @@ using llvm::unittest::TempLink; TEST(DependencyScanningCASFilesystem, FilenameSpelling) { TempDir TestDir("DependencyScanningCASFilesystemTest", /*Unique=*/true); TempFile TestFile(TestDir.path("File.h"), "", "#define FOO\n"); +#ifndef _WIN32 TempLink TestLink("File.h", TestDir.path("SymFile.h")); +#else + // As the create_link uses a hard link on Windows, the full path is + // required for the link target. + TempLink TestLink(TestDir.path("File.h"), TestDir.path("SymFile.h")); +#endif std::unique_ptr CAS = llvm::cas::createInMemoryCAS(); std::unique_ptr Cache = llvm::cas::createInMemoryActionCache(); diff --git a/clang/utils/PathSanitizingFileCheck b/clang/utils/PathSanitizingFileCheck new file mode 100644 index 0000000000000..cb717299a3a5c --- /dev/null +++ b/clang/utils/PathSanitizingFileCheck @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +# utils/PathSanitizingFileCheck -*- python -*- +# +# This source file is part of the Swift.org open source project +# +# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +# Licensed under Apache License v2.0 with Runtime Library Exception +# +# See https://swift.org/LICENSE.txt for license information +# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors + +import argparse +import io +import re +import subprocess +import sys + + +def main(): + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=""" +PathSanitizingFileCheck is a wrapper around LLVM's FileCheck. In addition +to all FileCheck features, PathSanitizingFileCheck can replace given +strings in the input with other strings. This feature is used to replace +paths to the source and build directories with path-independent +constants.""") + + parser.add_argument( + "--sanitize", + help="replace the given string with another string", + metavar="REPLACEMENT=SOURCE", + action="append", + dest="sanitize_strings", + default=[]) + + parser.add_argument( + "--use-filecheck", + help="path to LLVM FileCheck executable", + metavar="PATH", + action="store", + dest="file_check_path", + default="FileCheck") + + parser.add_argument( + "--enable-windows-compatibility", + help="Enable Windows path compatibility, which checks against both " + "forward slashes and backward slashes.", + action="store_true") + + parser.add_argument( + "--enable-yaml-compatibility", + help="Enable YAML path compatibility. Since YAML double escapes " + "backward slashes, we need to check for them escaped. Only " + "available if Windows compatibility is enabled.", + action="store_true") + + parser.add_argument( + "--dry-run", + help="Apply the replacements to the input and print the result " + "to standard output", + action="store_true") + + parser.add_argument( + "--ignore-runtime-warnings", + help="Ignore warnings from the Swift runtime", + action="store_true") + + args, unknown_args = parser.parse_known_args() + + if args.enable_windows_compatibility: + if args.enable_yaml_compatibility: + # Put the double escaped backslahes before the single + # escaped to ensure longest match + slashes_re = r'(/|\\\\\\\\|\\\\)' + else: + slashes_re = r'(/|\\\\)' + else: + slashes_re = r'/' + + stdin = io.open(sys.stdin.fileno(), 'r', encoding='utf-8', errors='ignore').read() + + for s in args.sanitize_strings: + replacement, pattern = s.split('=', 1) + # Since we want to use pattern as a regex in some platforms, we need + # to escape it first, and then replace the escaped slash + # literal (r'\\/') for our platform-dependent slash regex. + stdin = re.sub(re.sub(r'\\/' if sys.version_info[0] < 3 else r'/', + slashes_re, re.escape(pattern)), + replacement, stdin) + + # Because we force the backtracer on in the tests, we can get runtime + # warnings about privileged programs. Suppress those, and also the + # warning it might emit if backtracing isn't supported on the test platform. + # Additionally, suppress warnings about unknown backtracer options, since + # we might want to add new ones to the lit tests and we should ignore + # messages from the system copy of the runtime in that case. + if args.ignore_runtime_warnings: + stdin = re.sub(r'^swift runtime: (backtrace-on-crash is not ' + r'supported|unknown) .*\n', "", stdin, flags=re.M) + + if args.dry_run: + print(stdin) + return 0 + else: + p = subprocess.Popen( + [args.file_check_path] + unknown_args, stdin=subprocess.PIPE) + stdout, stderr = p.communicate(stdin.encode('utf-8')) + if stdout is not None: + print(stdout) + if stderr is not None: + print(stderr, file=sys.stderr) + return p.wait() + + +if __name__ == '__main__': + exit(main()) diff --git a/llvm/include/llvm/CAS/ActionCache.h b/llvm/include/llvm/CAS/ActionCache.h index 42236c9b5b45f..40c284e9dd574 100644 --- a/llvm/include/llvm/CAS/ActionCache.h +++ b/llvm/include/llvm/CAS/ActionCache.h @@ -48,7 +48,6 @@ using AsyncCASIDValue = AsyncValue; struct AsyncErrorValue { Error take() { return std::move(Value); } - AsyncErrorValue() : Value(Error::success()) {} AsyncErrorValue(Error &&E) : Value(std::move(E)) {} private: diff --git a/llvm/include/llvm/CAS/CASFileSystem.h b/llvm/include/llvm/CAS/CASFileSystem.h index d4d19461aa701..896db1cdd6ed6 100644 --- a/llvm/include/llvm/CAS/CASFileSystem.h +++ b/llvm/include/llvm/CAS/CASFileSystem.h @@ -17,15 +17,13 @@ namespace cas { class ObjectStore; class CASID; -// FIXME: Consider taking a "mount point". Then this could perhaps be -// generalized for windows. Expected> -createCASFileSystem(std::shared_ptr DB, const CASID &RootID); +createCASFileSystem(std::shared_ptr DB, const CASID &RootID, + sys::path::Style PathStyle = sys::path::Style::native); -// FIXME: Consider taking a "mount point". Then this could perhaps be -// generalized for windows. Expected> -createCASFileSystem(ObjectStore &DB, const CASID &RootID); +createCASFileSystem(ObjectStore &DB, const CASID &RootID, + sys::path::Style PathStyle = sys::path::Style::native); } // namespace cas } // namespace llvm diff --git a/llvm/include/llvm/CAS/CASID.h b/llvm/include/llvm/CAS/CASID.h index fcac19aae9911..748bc1ead2f94 100644 --- a/llvm/include/llvm/CAS/CASID.h +++ b/llvm/include/llvm/CAS/CASID.h @@ -127,7 +127,6 @@ class CASID { template struct AsyncValue { Expected> take() { return std::move(Value); } - AsyncValue() : Value(std::nullopt) {} AsyncValue(Error &&E) : Value(std::move(E)) {} AsyncValue(T &&V) : Value(std::move(V)) {} AsyncValue(std::nullopt_t) : Value(std::nullopt) {} diff --git a/llvm/include/llvm/CAS/FileSystemCache.h b/llvm/include/llvm/CAS/FileSystemCache.h index 410ff2eb5fe1e..7deee27d60927 100644 --- a/llvm/include/llvm/CAS/FileSystemCache.h +++ b/llvm/include/llvm/CAS/FileSystemCache.h @@ -27,6 +27,37 @@ namespace llvm { namespace cas { +// Used to create StringRef from Twine and slash canonicalization on +// Windows. +struct PathStorage { + SmallString<261> Storage; + StringRef Path; + PathStorage() {} + PathStorage(const Twine &InputPath, + sys::path::Style Style = sys::path::Style::native) { + if (is_style_windows(Style)) { + // Canonicalize to backslahes + InputPath.toVector(Storage); + llvm::sys::path::make_preferred(Storage, Style); + Path = Storage.str(); + } else { + InputPath.toVector(Storage); + Path = Storage.str(); + } + } + PathStorage(StringRef InputPath, + sys::path::Style Style = sys::path::Style::native) { + if (is_style_windows(Style)) { + // Canonicalize to backslahes + Storage = InputPath; + llvm::sys::path::make_preferred(Storage, Style); + Path = Storage.str(); + } else { + Path = InputPath; + } + } +}; + /// Caching for lazily discovering a CAS-based filesystem. /// /// FIXME: Extract most of this into llvm::vfs::FileSystemCache, so that it can @@ -43,14 +74,16 @@ class FileSystemCache : public ThreadSafeRefCountedBase { struct DirectoryListingInfo; struct LookupPathState { + sys::path::Style PathStyle; DirectoryEntry *Entry; StringRef Remaining; StringRef Name; StringRef AfterName; - LookupPathState(DirectoryEntry &Entry, StringRef Remaining) - : Entry(&Entry), Remaining(Remaining) { - size_t Slash = Remaining.find('/'); + LookupPathState(sys::path::Style PathStyle, DirectoryEntry &Entry, + StringRef Remaining) + : PathStyle(PathStyle), Entry(&Entry), Remaining(Remaining) { + size_t Slash = Remaining.find(get_separator(PathStyle)[0]); Name = Remaining.substr(0, Slash); AfterName = Slash == StringRef::npos ? "" : Remaining.drop_front(Slash); } @@ -63,11 +96,11 @@ class FileSystemCache : public ThreadSafeRefCountedBase { // Optional, this should crash if advancing to far, and users of // LookupPathState should be updated. if (AfterName.empty()) - *this = LookupPathState(NewEntry, AfterName); - else if (AfterName == "/") - *this = LookupPathState(NewEntry, "."); + *this = LookupPathState(PathStyle, NewEntry, AfterName); + else if (AfterName == get_separator(PathStyle)) + *this = LookupPathState(PathStyle, NewEntry, "."); else - *this = LookupPathState(NewEntry, AfterName.drop_front()); + *this = LookupPathState(PathStyle, NewEntry, AfterName.drop_front()); } void skip() { advance(*Entry); } }; @@ -185,11 +218,13 @@ class FileSystemCache : public ThreadSafeRefCountedBase { std::error_code setCurrentWorkingDirectory(const Twine &Path); - static StringRef canonicalizeWorkingDirectory(const Twine &Path, + static StringRef canonicalizeWorkingDirectory(sys::path::Style PathStyle, StringRef WorkingDirectory, SmallVectorImpl &Storage); - DirectoryEntry &getRoot() { return *Root; } + DirectoryEntry &getRoot(StringRef root_path, + std::optional RootRef = std::nullopt); + sys::path::Style getPathStyle() const { return PathStyle; } using LookupSymlinkPathType = unique_function(StringRef)>; @@ -201,7 +236,8 @@ class FileSystemCache : public ThreadSafeRefCountedBase { FileSystemCache(FileSystemCache &&) = delete; FileSystemCache(const FileSystemCache &) = delete; - explicit FileSystemCache(std::optional Root = std::nullopt); + FileSystemCache(sys::path::Style PathStyle = sys::path::Style::native) + : PathStyle(PathStyle) {} private: ThreadSafeAllocator> FileAlloc; @@ -210,7 +246,8 @@ class FileSystemCache : public ThreadSafeRefCountedBase { ThreadSafeAllocator> EntryAlloc; ThreadSafeAllocator> TreePathAlloc; - DirectoryEntry *Root = nullptr; + // Support multiple roots for Windows + DenseMap Roots; struct { DirectoryEntry *Entry = nullptr; @@ -218,6 +255,7 @@ class FileSystemCache : public ThreadSafeRefCountedBase { /// as \c Entry->getTreePath(). std::string Path; } WorkingDirectory; + sys::path::Style PathStyle; }; class FileSystemCache::DirectoryEntry : public vfs::CachedDirectoryEntry { @@ -446,21 +484,22 @@ class FileSystemCache::VFSDirIterImpl : public vfs::detail::DirIterImpl { std::error_code increment() override; static std::shared_ptr - create(LookupSymlinkPathType LookupSymlinkPath, StringRef ParentPath, - ArrayRef Entries); + create(FileSystemCache *Cache, LookupSymlinkPathType LookupSymlinkPath, + StringRef ParentPath, ArrayRef Entries); void operator delete(void *Ptr) { ::free(Ptr); } private: void setEntry(); - VFSDirIterImpl(LookupSymlinkPathType LookupSymlinkPath, StringRef ParentPath, - ArrayRef Entries) - : LookupSymlinkPath(std::move(LookupSymlinkPath)), ParentPath(ParentPath), - Entries(Entries), I(this->Entries.begin()) { + VFSDirIterImpl(FileSystemCache *Cache, LookupSymlinkPathType LookupSymlinkPath, + StringRef ParentPath, ArrayRef Entries) + : Cache(Cache), LookupSymlinkPath(std::move(LookupSymlinkPath)), + ParentPath(ParentPath), Entries(Entries), I(this->Entries.begin()) { setEntry(); } + FileSystemCache *Cache; LookupSymlinkPathType LookupSymlinkPath; StringRef ParentPath; ArrayRef Entries; diff --git a/llvm/include/llvm/CAS/HierarchicalTreeBuilder.h b/llvm/include/llvm/CAS/HierarchicalTreeBuilder.h index f51a0762bed5d..2bde171aad31e 100644 --- a/llvm/include/llvm/CAS/HierarchicalTreeBuilder.h +++ b/llvm/include/llvm/CAS/HierarchicalTreeBuilder.h @@ -16,6 +16,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" // FIXME: Split out sys::fs::file_status. #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" #include namespace llvm { @@ -43,6 +44,8 @@ class HierarchicalTreeBuilder { std::string Path; }; + sys::path::Style PathStyle; + /// Preallocate space for small trees, common when creating cache keys. SmallVector Entries; SmallVector TreeContents; @@ -51,6 +54,9 @@ class HierarchicalTreeBuilder { const Twine &Path); public: + HierarchicalTreeBuilder(sys::path::Style PathStyle = sys::path::Style::native) + : PathStyle(PathStyle) {} + /// Add a hierarchical entry at \p Path, which is expected to be from the /// top-level (otherwise, the caller should prepend a working directory). /// diff --git a/llvm/include/llvm/CAS/TreePath.h b/llvm/include/llvm/CAS/TreePath.h new file mode 100644 index 0000000000000..054f0e94fb72c --- /dev/null +++ b/llvm/include/llvm/CAS/TreePath.h @@ -0,0 +1,45 @@ +//===- llvm/CAS/TreePath.h - Tree path utility ------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CAS_TREEPATH_H +#define LLVM_CAS_TREEPATH_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Path.h" +#include + +namespace llvm::cas { + +// On Windows, prepend a dummy root backslash to tree paths internally +// (\C:\foo) and distinguish them from normal file paths (C:\foo) that +// come from and return to clients and are passed to sys::fs +// functions. This is so that we can have a single root and CAS ID +// representing the root of the filesystem (that may otherwise spread +// across multiple trees / drives) and the path handling to be more +// uniform with the Posix systems. These convert paths between them. +// TODO: Reassess this way of handling multiple roots for Windows later. +inline std::string getTreePath(StringRef FilePath, sys::path::Style PathStyle) { + if (sys::path::is_style_windows(PathStyle)) { + assert(FilePath[0] != '\\'); + std::string TreePath = "\\" + std::string(FilePath); + return TreePath; + } + return FilePath.str(); +} + +inline StringRef getFilePath(StringRef TreePath, sys::path::Style PathStyle) { + if (sys::path::is_style_windows(PathStyle)) { + assert(TreePath[0] == '\\'); + return TreePath.drop_front(1); + } + return TreePath; +} + +} // namespace llvm::cas + +#endif // LLVM_CAS_TREEPATH_H diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h index 56b09cd866846..3228dcec13a76 100644 --- a/llvm/include/llvm/Support/FileSystem.h +++ b/llvm/include/llvm/Support/FileSystem.h @@ -410,6 +410,11 @@ LLVM_ABI std::error_code copy_file(const Twine &From, int ToFD); /// platform-specific error_code. LLVM_ABI std::error_code resize_file(int FD, uint64_t Size); +/// Resize path to size with sparse files explicitly enabled. It uses +/// FSCTL_SET_SPARSE On Windows. This is the same as resize_file on +/// non-Windows +LLVM_ABI std::error_code resize_file_sparse(int FD, uint64_t Size); + /// Resize \p FD to \p Size before mapping \a mapped_file_region::readwrite. On /// non-Windows, this calls \a resize_file(). On Windows, this is a no-op, /// since the subsequent mapping (via \c CreateFileMapping) automatically diff --git a/llvm/include/llvm/Support/PrefixMapper.h b/llvm/include/llvm/Support/PrefixMapper.h index 69782e4e35ea4..8c483c5694892 100644 --- a/llvm/include/llvm/Support/PrefixMapper.h +++ b/llvm/include/llvm/Support/PrefixMapper.h @@ -170,8 +170,8 @@ class TreePathPrefixMapper : public PrefixMapper { /// Find the tree path for \p Path, getting the real path for its parent /// directory but not following symlinks in \a sys::path::filename(). /// - /// \returns The tree path, or the original path if there are any errors. - StringRef getTreePath(StringRef Path); + /// \returns The tree path, or none if there are any errors. + std::optional getTreePath(StringRef Path); public: void add(const MappedPrefix &Mapping) override; diff --git a/llvm/lib/CAS/CASFileSystem.cpp b/llvm/lib/CAS/CASFileSystem.cpp index 6485cfac0d038..6262f188e7856 100644 --- a/llvm/lib/CAS/CASFileSystem.cpp +++ b/llvm/lib/CAS/CASFileSystem.cpp @@ -70,9 +70,10 @@ class CASFileSystem : public ThreadSafeFileSystem { Error initialize(ObjectRef Root); - CASFileSystem(std::shared_ptr DB) - : DB(*DB), OwnedDB(std::move(DB)) {} - CASFileSystem(ObjectStore &DB) : DB(DB) {} + CASFileSystem(std::shared_ptr DB, sys::path::Style PathStyle) + : DB(*DB), OwnedDB(std::move(DB)), PathStyle(PathStyle) {} + CASFileSystem(ObjectStore &DB, sys::path::Style PathStyle) + : DB(DB), PathStyle(PathStyle) {} IntrusiveRefCntPtr createThreadSafeProxyFS() final { return makeIntrusiveRefCnt(*this); @@ -87,6 +88,7 @@ class CASFileSystem : public ThreadSafeFileSystem { IntrusiveRefCntPtr Cache; WorkingDirectoryType WorkingDirectory; + sys::path::Style PathStyle; }; } // namespace @@ -128,10 +130,11 @@ class CASFileSystem::VFSFile : public vfs::File { }; Error CASFileSystem::initialize(ObjectRef Root) { - Cache = makeIntrusiveRefCnt(Root); + Cache = makeIntrusiveRefCnt(PathStyle); // Initial working directory is the root. - WorkingDirectory.Entry = &Cache->getRoot(); + StringRef path_separator = get_separator(PathStyle); + WorkingDirectory.Entry = &Cache->getRoot(path_separator, Root); WorkingDirectory.Path = WorkingDirectory.Entry->getTreePath().str(); // Load the root to confirm it's really a tree. @@ -139,9 +142,9 @@ Error CASFileSystem::initialize(ObjectRef Root) { } std::error_code CASFileSystem::setCurrentWorkingDirectory(const Twine &Path) { - SmallString<128> Storage; + PathStorage PathStorage(Path, PathStyle); StringRef CanonicalPath = FileSystemCache::canonicalizeWorkingDirectory( - Path, WorkingDirectory.Path, Storage); + PathStyle, WorkingDirectory.Path, PathStorage.Storage); // Read and cache all the symlinks in the path by looking it up. Return any // error encountered. @@ -164,7 +167,7 @@ Error CASFileSystem::loadDirectory(DirectoryEntry &Parent) { auto makeCachedEntry = [&](const NamedTreeEntry &NewEntry) -> DirectoryEntry & { Path.resize(ParentPathSize); - sys::path::append(Path, sys::path::Style::posix, NewEntry.getName()); + sys::path::append(Path, PathStyle, NewEntry.getName()); switch (NewEntry.getKind()) { case TreeEntry::Regular: case TreeEntry::Executable: @@ -230,8 +233,8 @@ Error CASFileSystem::loadSymlink(DirectoryEntry &Entry) { } ErrorOr CASFileSystem::status(const Twine &Path) { - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path, PathStyle); + StringRef PathRef = PathStorage.Path; // Lookup only returns an Error if there's a problem communicating with the // CAS, or there's data corruption. @@ -254,8 +257,8 @@ ErrorOr CASFileSystem::status(const Twine &Path) { Expected CASFileSystem::getDirectoryEntry(const Twine &Path, bool FollowSymlinks) const { - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path, PathStyle); + StringRef PathRef = PathStorage.Path; // It's not a const operation, but it's thread-safe. return const_cast(this)->lookupPath(PathRef, FollowSymlinks); @@ -263,8 +266,8 @@ CASFileSystem::getDirectoryEntry(const Twine &Path, bool FollowSymlinks) const { ErrorOr> CASFileSystem::openFileForRead(const Twine &Path) { - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path, PathStyle); + StringRef PathRef = PathStorage.Path; Expected ExpectedEntry = lookupPath(PathRef); if (!ExpectedEntry) @@ -283,8 +286,8 @@ CASFileSystem::openFileForRead(const Twine &Path) { ErrorOr CASFileSystem::getDirectoryIterator(const Twine &Path) { - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path, PathStyle); + StringRef PathRef = PathStorage.Path; Expected ExpectedEntry = lookupPath(PathRef); if (!ExpectedEntry) @@ -338,8 +341,10 @@ class DiscoveryInstanceImpl final : public FileSystemCache::DiscoveryInstance { Expected CASFileSystem::lookupPath(StringRef Path, bool FollowSymlinks) { + PathStorage PathStorage(Path, PathStyle); + StringRef PathRef = PathStorage.Path; DiscoveryInstanceImpl DI(*this); - return Cache->lookupPath(DI, Path, *WorkingDirectory.Entry, FollowSymlinks); + return Cache->lookupPath(DI, PathRef, *WorkingDirectory.Entry, FollowSymlinks); } static Expected> @@ -355,12 +360,17 @@ initializeCASFileSystem(std::unique_ptr FS, } Expected> -cas::createCASFileSystem(std::shared_ptr DB, const CASID &RootID) { - return initializeCASFileSystem(std::make_unique(std::move(DB)), - RootID); +cas::createCASFileSystem(std::shared_ptr DB, + const CASID &RootID, + sys::path::Style PathStyle) { + return initializeCASFileSystem( + std::make_unique(std::move(DB), PathStyle), + RootID); } Expected> -cas::createCASFileSystem(ObjectStore &DB, const CASID &RootID) { - return initializeCASFileSystem(std::make_unique(DB), RootID); +cas::createCASFileSystem(ObjectStore &DB, const CASID &RootID, + sys::path::Style PathStyle) { + return initializeCASFileSystem( + std::make_unique(DB, PathStyle), RootID); } diff --git a/llvm/lib/CAS/CachingOnDiskFileSystem.cpp b/llvm/lib/CAS/CachingOnDiskFileSystem.cpp index b0248c6dc4590..3cce95d02dbf1 100644 --- a/llvm/lib/CAS/CachingOnDiskFileSystem.cpp +++ b/llvm/lib/CAS/CachingOnDiskFileSystem.cpp @@ -13,6 +13,7 @@ #include "llvm/CAS/HashMappedTrie.h" #include "llvm/CAS/HierarchicalTreeBuilder.h" #include "llvm/CAS/ObjectStore.h" +#include "llvm/CAS/TreePath.h" #include "llvm/Config/config.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" @@ -110,10 +111,6 @@ class CachingOnDiskFileSystemImpl final : public CachingOnDiskFileSystem { return WorkingDirectory.Path; } - static StringRef canonicalizeWorkingDirectory(const Twine &Path, - StringRef WorkingDirectory, - SmallVectorImpl &Storage); - void trackNewAccesses() final; std::error_code excludeFromTracking(const Twine &Path) final; Expected @@ -158,6 +155,8 @@ class CachingOnDiskFileSystemImpl final : public CachingOnDiskFileSystem { } } + sys::path::Style getPathStyle() { return Cache->getPathStyle(); } + private: void initializeWorkingDirectory(); @@ -252,11 +251,12 @@ class CachingOnDiskFileSystemImpl::VFSFile : public vfs::File { }; void CachingOnDiskFileSystemImpl::initializeWorkingDirectory() { - Cache = makeIntrusiveRefCnt(); + Cache = makeIntrusiveRefCnt(sys::path::Style::native); // Start with root, and then initialize the current working directory to // match process state, ignoring errors if there's a problem. - WorkingDirectory.Entry = &Cache->getRoot(); + static std::string RootPath = get_separator(sys::path::Style::native).str(); + WorkingDirectory.Entry = &Cache->getRoot(RootPath); WorkingDirectory.Path = WorkingDirectory.Entry->getTreePath().str(); SmallString<128> CWD; @@ -270,9 +270,9 @@ void CachingOnDiskFileSystemImpl::initializeWorkingDirectory() { std::error_code CachingOnDiskFileSystemImpl::setCurrentWorkingDirectory(const Twine &Path) { - SmallString<128> Storage; - StringRef CanonicalPath = - canonicalizeWorkingDirectory(Path, WorkingDirectory.Path, Storage); + PathStorage PathStorage(Path); + StringRef CanonicalPath = FileSystemCache::canonicalizeWorkingDirectory( + sys::path::Style::native, WorkingDirectory.Path, PathStorage.Storage); // Read and cache all the symlinks in the path by looking it up. Return any // error encountered. @@ -285,49 +285,11 @@ CachingOnDiskFileSystemImpl::setCurrentWorkingDirectory(const Twine &Path) { return std::error_code(); } -StringRef CachingOnDiskFileSystemImpl::canonicalizeWorkingDirectory( - const Twine &Path, StringRef WorkingDirectory, - SmallVectorImpl &Storage) { - // Not portable. - assert(WorkingDirectory.starts_with("/")); - Path.toVector(Storage); - if (Storage.empty()) - return WorkingDirectory; - - if (Storage[0] != '/') { - SmallString<128> Prefix = StringRef(WorkingDirectory); - Prefix.push_back('/'); - Storage.insert(Storage.begin(), Prefix.begin(), Prefix.end()); - } - - // Remove ".." components based on working directory string, not based on - // real path. This matches shell behaviour. - sys::path::remove_dots(Storage, /*remove_dot_dot=*/true, - sys::path::Style::posix); - - // Remove double slashes. - int W = 0; - bool WasSlash = false; - for (int R = 0, E = Storage.size(); R != E; ++R) { - bool IsSlash = Storage[R] == '/'; - if (IsSlash && WasSlash) - continue; - WasSlash = IsSlash; - Storage[W++] = Storage[R]; - } - Storage.resize(W); - - // Remove final slash. - if (Storage.size() > 1 && Storage.back() == '/') - Storage.pop_back(); - - return StringRef(Storage.begin(), Storage.size()); -} - FileSystemCache::DirectoryEntry * CachingOnDiskFileSystemImpl::makeDirectory(DirectoryEntry &Parent, StringRef TreePath) { - return &Cache->makeDirectory(Parent, TreePath); + PathStorage TreePathStorage(TreePath); + return &Cache->makeDirectory(Parent, TreePathStorage.Path); } #if defined(HAVE_UNISTD_H) @@ -354,26 +316,48 @@ static Error readLink(const llvm::Twine &Path, SmallVectorImpl &Dest) { Expected CachingOnDiskFileSystemImpl::makeSymlink(DirectoryEntry &Parent, StringRef TreePath) { + PathStorage TreePathStorage(TreePath); SmallString<128> Target; - if (auto Err = readLink(TreePath, Target)) + if (auto Err = readLink( + llvm::cas::getFilePath(TreePathStorage.Path, Cache->getPathStyle()), + Target)) return std::move(Err); - return makeSymlinkTo(Parent, TreePath, Target); + return makeSymlinkTo(Parent, TreePathStorage.Path, Target); } Expected CachingOnDiskFileSystemImpl::makeSymlinkTo(DirectoryEntry &Parent, StringRef TreePath, StringRef Target) { - Expected Node = DB.storeFromString({}, Target); + PathStorage TreePathStorage(TreePath); + PathStorage TargetStorage(Target); + Expected Node = DB.storeFromString({}, TargetStorage.Path); if (!Node) return Node.takeError(); - return &Cache->makeSymlink(Parent, TreePath, *Node, Target); + return &Cache->makeSymlink(Parent, TreePathStorage.Path, *Node, + TargetStorage.Path); +} + +static bool is_executable(StringRef TreePath, sys::fs::file_status Status, + sys::path::Style PathStyle) { +#ifndef _WIN32 + return Status.permissions() & sys::fs::perms::owner_exe; +#else + // This isn't the most reliable way but does better than just + // checking owner_exe because most owned files have all_all + // permission regardless of they are executable files. + StringRef FilePath = llvm::cas::getFilePath(TreePath, PathStyle); + return (Status.permissions() & sys::fs::perms::owner_exe) && + (FilePath.ends_with_insensitive(".exe") || + sys::fs::exists(FilePath + ".exe")); +#endif } Expected CachingOnDiskFileSystemImpl::makeFile(DirectoryEntry &Parent, StringRef TreePath, sys::fs::file_t F, sys::fs::file_status Status) { + PathStorage TreePathStorage(TreePath); Expected Node = DB.storeFromOpenFile(F, Status); if (!Node) return Node.takeError(); @@ -383,8 +367,9 @@ CachingOnDiskFileSystemImpl::makeFile(DirectoryEntry &Parent, if (!Handle) return Handle.takeError(); // Do not trust Status.size() in case the file is volatile. - return &Cache->makeFile(Parent, TreePath, *Node, Handle->getData().size(), - Status.permissions() & sys::fs::perms::owner_exe); + return &Cache->makeFile(Parent, TreePathStorage.Path, *Node, + Handle->getData().size(), + is_executable(TreePath, Status, Cache->getPathStyle())); } Expected @@ -392,36 +377,40 @@ CachingOnDiskFileSystemImpl::makeEntry( DirectoryEntry &Parent, StringRef TreePath, std::optional KnownStatus) { assert(Parent.isDirectory() && "Expected a directory"); + PathStorage TreePathStorage(TreePath); + StringRef FilePath = llvm::cas::getFilePath(TreePathStorage.Path, + Cache->getPathStyle()); // lstat is extremely slow... sys::fs::file_status Status; if (KnownStatus) { Status = std::move(*KnownStatus); - } else if (auto EC = sys::fs::status(TreePath, Status, /*follow=*/false)) { + } else if (auto EC = sys::fs::status(FilePath, Status, + /*follow=*/false)) { return errorCodeToError(EC); } if (Status.type() == sys::fs::file_type::directory_file) - return makeDirectory(Parent, TreePath); + return makeDirectory(Parent, TreePathStorage.Path); if (Status.type() == sys::fs::file_type::symlink_file) - return makeSymlink(Parent, TreePath); + return makeSymlink(Parent, TreePathStorage.Path); - auto F = sys::fs::openNativeFile(TreePath, sys::fs::CD_OpenExisting, - sys::fs::FA_Read, sys::fs::OF_None); + auto F = sys::fs::openNativeFile(FilePath, + sys::fs::CD_OpenExisting, sys::fs::FA_Read, sys::fs::OF_None); if (!F) return F.takeError(); auto CloseOnExit = make_scope_exit([&F]() { sys::fs::closeFile(*F); }); - return makeFile(Parent, TreePath, *F, Status); + return makeFile(Parent, TreePathStorage.Path, *F, Status); } ErrorOr CachingOnDiskFileSystemImpl::statusAndFileID(const Twine &Path, std::optional &FileID) { FileID = std::nullopt; - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path); + StringRef PathRef = PathStorage.Path; // Lookup only returns an Error if there's a problem communicating with the // CAS, or there's data corruption. @@ -445,12 +434,11 @@ CachingOnDiskFileSystemImpl::statusAndFileID(const Twine &Path, Expected CachingOnDiskFileSystemImpl::getDirectoryEntry(const Twine &Path, bool FollowSymlinks) const { - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path); // It's not a const operation, but it's thread-safe. return const_cast(this)->lookupPath( - PathRef, FollowSymlinks); + PathStorage.Path, FollowSymlinks); } std::error_code @@ -462,9 +450,10 @@ CachingOnDiskFileSystemImpl::getRealPath(const Twine &Path, getDirectoryEntry(Path, /*FollowSymlinks=*/true).moveInto(Entry)) return errorToErrorCode(std::move(E)); - StringRef TreePath = Entry->getTreePath(); - Output.resize(TreePath.size()); - llvm::copy(TreePath, Output.begin()); + StringRef RealFilePath = llvm::cas::getFilePath(Entry->getTreePath(), + Cache->getPathStyle()); + Output.resize(RealFilePath.size()); + llvm::copy(RealFilePath, Output.begin()); return std::error_code(); } @@ -488,8 +477,8 @@ bool CachingOnDiskFileSystemImpl::exists(const Twine &Path) { ErrorOr> CachingOnDiskFileSystemImpl::openFileForRead(const Twine &Path) { - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path); + StringRef PathRef = PathStorage.Path; Expected ExpectedEntry = lookupPath(PathRef); if (!ExpectedEntry) @@ -504,8 +493,8 @@ CachingOnDiskFileSystemImpl::openFileForRead(const Twine &Path) { ErrorOr CachingOnDiskFileSystemImpl::getDirectoryIterator(const Twine &Path) { - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path); + StringRef PathRef = PathStorage.Path; Expected ExpectedEntry = lookupPath(PathRef); if (!ExpectedEntry) @@ -518,9 +507,13 @@ CachingOnDiskFileSystemImpl::getDirectoryIterator(const Twine &Path) { // Walk the directory on-disk to discover entries. std::error_code EC; SmallVector TreePaths; - for (sys::fs::directory_iterator I(Entry->getTreePath(), EC), E; - !EC && I != E; I.increment(EC)) - TreePaths.emplace_back(I->path()); + StringRef EntryFilePath = llvm::cas::getFilePath(Entry->getTreePath(), + Cache->getPathStyle()); + for (sys::fs::directory_iterator I(EntryFilePath, EC), E; + !EC && I != E; I.increment(EC)) { + TreePaths.emplace_back(llvm::cas::getTreePath(I->path(), + Cache->getPathStyle())); + } if (EC) return EC; @@ -551,9 +544,12 @@ CachingOnDiskFileSystemImpl::getDirectoryIterator(const Twine &Path) { Expected CachingOnDiskFileSystemImpl::preloadRealPath(DirectoryEntry &From, StringRef Remaining) { - SmallString<256> ExpectedRealPath; - ExpectedRealPath = From.getTreePath(); - sys::path::append(ExpectedRealPath, Remaining); + PathStorage RemainingStorage(Remaining); + SmallString<256> ExpectedRealTreePath; + ExpectedRealTreePath = From.getTreePath(); + sys::path::append(ExpectedRealTreePath, RemainingStorage.Path); + SmallString<256> ExpectedRealPath = llvm::cas::getFilePath( + ExpectedRealTreePath.str(), Cache->getPathStyle()); // Most paths don't exist. Start with a stat. Profiling says this is faster // on Darwin when running clang-scan-deps (looks like allocation traffic in @@ -571,21 +567,25 @@ CachingOnDiskFileSystemImpl::preloadRealPath(DirectoryEntry &From, } SmallString<256> RealPath; - auto FD = sys::fs::openNativeFileForRead(ExpectedRealPath, sys::fs::OF_None, - &RealPath); - if (!FD) - return FD.takeError(); - auto CloseOnExit = make_scope_exit([&FD]() { sys::fs::closeFile(*FD); }); + if (std::error_code EC = sys::fs::real_path(ExpectedRealPath, RealPath, + /* expand_tilde */false)) + return errorCodeToError(EC); - FileSystemCache::LookupPathState State(Cache->getRoot(), RealPath); + SmallString<256> RealTreePath = StringRef(llvm::cas::getTreePath(RealPath, + Cache->getPathStyle())); + FileSystemCache::LookupPathState State(Cache->getPathStyle(), + Cache->getRoot(get_separator(Cache->getPathStyle())), RealTreePath); // Advance through the cached directories. Note: no need to pass through // TrackNonRealPathEntries because we're navigating a real path. - StringRef ExpectedPrefix = - StringRef(ExpectedRealPath).drop_back(Remaining.size()); - if (RealPath.starts_with(ExpectedPrefix)) - State = FileSystemCache::LookupPathState( - From, RealPath.substr(ExpectedPrefix.size())); + StringRef ExpectedTreePrefix = + StringRef(ExpectedRealTreePath).drop_back(RemainingStorage.Path.size()); + if (((!is_style_windows(Cache->getPathStyle())) && + RealTreePath.str().starts_with(ExpectedTreePrefix)) || + ((is_style_windows(Cache->getPathStyle())) && + RealTreePath.str().starts_with_insensitive(ExpectedTreePrefix))) + State = FileSystemCache::LookupPathState(Cache->getPathStyle(), From, + RealTreePath.substr(ExpectedTreePrefix.size())); else State = Cache->lookupRealPathPrefixFromCached( State, /*TrackNonRealPathEntries=*/nullptr); @@ -596,8 +596,8 @@ CachingOnDiskFileSystemImpl::preloadRealPath(DirectoryEntry &From, // All but the last component must be directories. while (!State.AfterName.empty()) { - DirectoryEntry &Entry = Cache->makeDirectory( - *State.Entry, RealPath.substr(0, State.Name.end() - RealPath.begin())); + DirectoryEntry &Entry = Cache->makeDirectory(*State.Entry, + RealTreePath.substr(0, State.Name.end() - RealTreePath.begin())); // If we don't get back a directory, the disk state must have changed and // another thread raced. Give up on this endeavour. @@ -610,14 +610,26 @@ CachingOnDiskFileSystemImpl::preloadRealPath(DirectoryEntry &From, assert(!State.Name.empty()); // Skip all errors from here out. This is just priming the cache. + + // Check if it's a directory or not before opening because + // openNativeFileForRead will fail on directories on Windows. sys::fs::file_status Status; - if (/*std::error_code EC =*/sys::fs::status(*FD, Status)) + if (/*std::error_code EC =*/sys::fs::status(ExpectedRealPath, Status)) return nullptr; + const bool IsDir = sys::fs::is_directory(Status); - if (Status.type() == sys::fs::file_type::directory_file) - return makeDirectory(*State.Entry, RealPath); + if (IsDir) + return makeDirectory(*State.Entry, RealTreePath); - auto F = makeFile(*State.Entry, RealPath, *FD, Status); + auto FD = sys::fs::openNativeFileForRead(ExpectedRealPath, sys::fs::OF_None, + /*RealPath=*/nullptr); + if (!FD) { + llvm::consumeError(FD.takeError()); + return nullptr; + } + auto CloseOnExit = make_scope_exit([&FD]() { sys::fs::closeFile(*FD); }); + + auto F = makeFile(*State.Entry, RealTreePath, *FD, Status); if (F) return *F; llvm::consumeError(F.takeError()); @@ -630,11 +642,13 @@ CachingOnDiskFileSystemImpl::lookupPath( bool ForceDisableTracking, bool NeedsContent, function_ref TrackNonRealPathEntries) { + PathStorage PathStorage(Path); bool IsTrackingStats = ForceDisableTracking ? false : isTrackingAccess(); DiscoveryInstanceImpl DI(*this, TrackNonRealPathEntries, IsTrackingStats, LookupOnDisk); Expected ExpectedEntry = - Cache->lookupPath(DI, Path, *WorkingDirectory.Entry, FollowSymlinks); + Cache->lookupPath(DI, PathStorage.Path, *WorkingDirectory.Entry, + FollowSymlinks); if (IsTrackingStats && ExpectedEntry && *ExpectedEntry) trackAccess(**ExpectedEntry, NeedsContent); return ExpectedEntry; @@ -678,8 +692,8 @@ void CachingOnDiskFileSystemImpl::trackNewAccesses() { std::error_code CachingOnDiskFileSystemImpl::excludeFromTracking(const Twine &Path) { - SmallString<128> Storage; - StringRef PathRef = Path.toStringRef(Storage); + PathStorage PathStorage(Path); + StringRef PathRef = PathStorage.Path; DirectoryEntry *Entry = nullptr; if (auto Err = lookupPath(PathRef, /*FollowSymlinks=*/true, /*LookupOnDisk=*/true, @@ -749,10 +763,8 @@ Expected CachingOnDiskFileSystemImpl::createTreeFromAllAccesses() { std::unique_ptr Builder = createTreeBuilder(); - // FIXME: Not portable; only works for posix, not windows. - // // FIXME: don't know if we want this push to be recursive... - if (Error E = Builder->push("/")) + if (Error E = Builder->push(get_separator(sys::path::Style::native))) return std::move(E); return Builder->create(); } @@ -774,10 +786,11 @@ DiscoveryInstanceImpl::requestDirectoryEntry(DirectoryEntry &Parent, assert(Parent.isDirectory() && "Expected a directory"); SmallString<256> Path(Parent.getTreePath()); sys::path::append(Path, Name); + StringRef FilePath = llvm::cas::getFilePath(Path.str(), FS.getPathStyle()); // lstat is extremely slow... sys::fs::file_status Status; - if (std::error_code EC = sys::fs::status(Path, Status, /*follow=*/false)) + if (std::error_code EC = sys::fs::status(FilePath, Status, /*follow=*/false)) return errorCodeToError(EC); DirectoryEntry *Next = @@ -802,9 +815,11 @@ DiscoveryInstanceImpl::requestDirectoryEntry(DirectoryEntry &Parent, if (Name.equals_insensitive(NextName) || !isASCII(Name)) { // Might be a case-insensitive match, check if it's the same entity. // FIXME: put this unique id in the cache. + StringRef NextFilePath = llvm::cas::getFilePath(Next->getTreePath(), + FS.getPathStyle()); sys::fs::file_status StatNext; if (std::error_code EC = - sys::fs::status(Next->getTreePath(), StatNext, /*follow=*/false)) + sys::fs::status(NextFilePath, StatNext, /*follow=*/false)) return errorCodeToError(EC); if (Status.getUniqueID() == StatNext.getUniqueID()) { // Case-insensitive match! Create a fake symlink so that it will have @@ -868,11 +883,12 @@ class CachingOnDiskFileSystemImpl::TreeBuilder final // Push \p Entry to \a Builder if it's a file, to \a Worklist otherwise. void pushEntry(const DirectoryEntry &Entry); - explicit TreeBuilder(CachingOnDiskFileSystemImpl &FS) : FS(FS) {} + explicit TreeBuilder(CachingOnDiskFileSystemImpl &FS) + : Builder(HierarchicalTreeBuilder()), FS(FS) {} HierarchicalTreeBuilder Builder; CachingOnDiskFileSystemImpl &FS; - SmallString<128> PathStorage; + PathStorage Storage; SmallVector Worklist; DenseSet Seen; }; @@ -900,8 +916,8 @@ void CachingOnDiskFileSystemImpl::TreeBuilder::pushEntry( } Error CachingOnDiskFileSystemImpl::TreeBuilder::push(const Twine &Path) { - PathStorage.clear(); - StringRef PathRef = Path.toStringRef(PathStorage); + Storage = PathStorage(Path); + StringRef PathRef = Storage.Path; // Look for Path without following symlinks. Failure here indicates that Path // does not exist or has a broken symlink in its parent path. Keep track of diff --git a/llvm/lib/CAS/FileSystemCache.cpp b/llvm/lib/CAS/FileSystemCache.cpp index f235b7469d0c6..ad9c90f29ad26 100644 --- a/llvm/lib/CAS/FileSystemCache.cpp +++ b/llvm/lib/CAS/FileSystemCache.cpp @@ -22,41 +22,44 @@ using namespace llvm::cas; using DirectoryEntry = FileSystemCache::DirectoryEntry; -FileSystemCache::FileSystemCache(std::optional RootRef) { - // FIXME: Only correct for posix. To generalize this (for both posix and - // windows) we should refactor so that the root node has no name (instead of - // "/"). - Root = new (EntryAlloc.Allocate()) - DirectoryEntry(nullptr, "/", DirectoryEntry::Directory, RootRef); +DirectoryEntry &FileSystemCache::getRoot(StringRef root_path, + std::optional RootRef) { + auto it = Roots.find(root_path); + if (it != Roots.end()) { + return *it->second; + } + DirectoryEntry *Root = new (EntryAlloc.Allocate()) + DirectoryEntry(nullptr, root_path, DirectoryEntry::Directory, RootRef); Root->setDirectory(*new (DirectoryAlloc.Allocate()) Directory); + Roots[root_path] = Root; + return *Root; } StringRef -FileSystemCache::canonicalizeWorkingDirectory(const Twine &Path, +FileSystemCache::canonicalizeWorkingDirectory(sys::path::Style PathStyle, StringRef WorkingDirectory, SmallVectorImpl &Storage) { - // Not portable. - assert(WorkingDirectory.starts_with("/")); - Path.toVector(Storage); + const char PathSeparatorChar = get_separator(PathStyle)[0]; + StringRef Path = StringRef(Storage.begin(), Storage.size()); if (Storage.empty()) return WorkingDirectory; - if (Storage[0] != '/') { + if (!is_absolute(Path, PathStyle)) { + assert(is_absolute(WorkingDirectory, PathStyle)); SmallString<128> Prefix = StringRef(WorkingDirectory); - Prefix.push_back('/'); + Prefix.push_back(PathSeparatorChar); Storage.insert(Storage.begin(), Prefix.begin(), Prefix.end()); } // Remove ".." components based on working directory string, not based on // real path. This matches shell behaviour. - sys::path::remove_dots(Storage, /*remove_dot_dot=*/true, - sys::path::Style::posix); + sys::path::remove_dots(Storage, /*remove_dot_dot=*/true, PathStyle); // Remove double slashes. int W = 0; bool WasSlash = false; for (int R = 0, E = Storage.size(); R != E; ++R) { - bool IsSlash = Storage[R] == '/'; + bool IsSlash = Storage[R] == PathSeparatorChar; if (IsSlash && WasSlash) continue; WasSlash = IsSlash; @@ -65,7 +68,9 @@ FileSystemCache::canonicalizeWorkingDirectory(const Twine &Path, Storage.resize(W); // Remove final slash. - if (Storage.size() > 1 && Storage.back() == '/') + if (sys::path::root_path(StringRef(Storage.begin(), Storage.size()), PathStyle) + != StringRef(Storage.begin(), Storage.size()) && + Storage.back() == PathSeparatorChar) Storage.pop_back(); return StringRef(Storage.begin(), Storage.size()); @@ -84,8 +89,8 @@ static StringRef allocateTreePath( // Use constant strings when reasonable. if (TreePath.empty()) return ""; - if (TreePath == "/") - return "/"; + if (sys::path::root_path(TreePath) == TreePath) + return TreePath; char *AllocatedTreePath = TreePathAlloc.Allocate(TreePath.size() + 1); llvm::copy(TreePath, AllocatedTreePath); @@ -97,9 +102,14 @@ static DirectoryEntry &makeLazyEntry( ThreadSafeAllocator> &TreePathAlloc, ThreadSafeAllocator> &EntryAlloc, DirectoryEntry &Parent, FileSystemCache::Directory &D, StringRef TreePath, - DirectoryEntry::EntryKind Kind, std::optional Ref) { - assert(sys::path::parent_path(TreePath) == Parent.getTreePath()); - assert(!D.lookup(sys::path::filename(TreePath))); + DirectoryEntry::EntryKind Kind, std::optional Ref, + sys::path::Style PathStyle) { + if (!is_style_windows(PathStyle)) { + assert(sys::path::parent_path(TreePath, PathStyle) == Parent.getTreePath()); + } else { + assert(sys::path::parent_path(TreePath, PathStyle).equals_insensitive(Parent.getTreePath())); + } + assert(!D.lookup(sys::path::filename(TreePath, PathStyle))); assert(!D.isComplete()); TreePath = allocateTreePath(TreePathAlloc, TreePath); @@ -112,7 +122,7 @@ static DirectoryEntry &makeLazyEntry( DirectoryEntry &FileSystemCache::makeLazySymlinkAlreadyLocked( DirectoryEntry &Parent, StringRef TreePath, ObjectRef Ref) { return makeLazyEntry(TreePathAlloc, EntryAlloc, Parent, Parent.asDirectory(), - TreePath, DirectoryEntry::Symlink, Ref); + TreePath, DirectoryEntry::Symlink, Ref, PathStyle); } DirectoryEntry & @@ -121,7 +131,8 @@ FileSystemCache::makeLazyFileAlreadyLocked(DirectoryEntry &Parent, bool IsExecutable) { return makeLazyEntry( TreePathAlloc, EntryAlloc, Parent, Parent.asDirectory(), TreePath, - IsExecutable ? DirectoryEntry::Executable : DirectoryEntry::Regular, Ref); + IsExecutable ? DirectoryEntry::Executable : DirectoryEntry::Regular, Ref, + PathStyle); } DirectoryEntry &FileSystemCache::makeDirectory(DirectoryEntry &Parent, @@ -129,7 +140,7 @@ DirectoryEntry &FileSystemCache::makeDirectory(DirectoryEntry &Parent, std::optional Ref) { Directory &D = Parent.asDirectory(); Directory::Writer W(D); - if (DirectoryEntry *Existing = D.lookup(sys::path::filename(TreePath))) + if (DirectoryEntry *Existing = D.lookup(sys::path::filename(TreePath, PathStyle))) return *Existing; return makeDirectoryAlreadyLocked(Parent, TreePath, Ref); @@ -139,7 +150,7 @@ DirectoryEntry &FileSystemCache::makeDirectoryAlreadyLocked( DirectoryEntry &Parent, StringRef TreePath, std::optional Ref) { DirectoryEntry &Entry = makeLazyEntry(TreePathAlloc, EntryAlloc, Parent, Parent.asDirectory(), - TreePath, DirectoryEntry::Directory, Ref); + TreePath, DirectoryEntry::Directory, Ref, PathStyle); Entry.setDirectory(*new (DirectoryAlloc.Allocate()) Directory); return Entry; } @@ -149,7 +160,7 @@ DirectoryEntry &FileSystemCache::makeSymlink(DirectoryEntry &Parent, StringRef Target) { Directory &D = Parent.asDirectory(); Directory::Writer W(D); - if (DirectoryEntry *Existing = D.lookup(sys::path::filename(TreePath))) + if (DirectoryEntry *Existing = D.lookup(sys::path::filename(TreePath, PathStyle))) return *Existing; DirectoryEntry &Entry = makeLazySymlinkAlreadyLocked(Parent, TreePath, Ref); @@ -175,7 +186,7 @@ DirectoryEntry &FileSystemCache::makeFile(DirectoryEntry &Parent, size_t Size, bool IsExecutable) { Directory &D = Parent.asDirectory(); Directory::Writer W(D); - if (DirectoryEntry *Existing = D.lookup(sys::path::filename(TreePath))) + if (DirectoryEntry *Existing = D.lookup(sys::path::filename(TreePath, PathStyle))) return *Existing; DirectoryEntry &Entry = @@ -250,8 +261,6 @@ Expected FileSystemCache::lookupPath(DiscoveryInstance &DI, StringRef Path, DirectoryEntry &WorkingDirectory, bool FollowSymlinks) { - assert(Root && "Expected root filesystem to exist"); - struct WorklistNode { StringRef Remaining; unsigned SymlinkDepth; @@ -266,15 +275,23 @@ FileSystemCache::lookupPath(DiscoveryInstance &DI, StringRef Path, // Start at the current working directory, unless the path is absolute. DirectoryEntry *Current = &WorkingDirectory; - if (Path.consume_front("/")) - Current = Root; + if (is_absolute(Path, PathStyle)) { + if (is_style_windows(PathStyle)) { + Current = &getRoot(get_separator(PathStyle)); + // Pretend that we consumed the dummy root "\" + } else { + StringRef root_path = sys::path::root_path(Path, PathStyle); + Current = &getRoot(root_path); + Path.consume_front(root_path); + } + } pushWork(Path); while (!Worklist.empty()) { assert(Current); auto Work = Worklist.pop_back_val(); - Expected Found = - lookupRealPathPrefixFrom(DI, LookupPathState(*Current, Work.Remaining)); + Expected Found = lookupRealPathPrefixFrom(DI, + LookupPathState(PathStyle, *Current, Work.Remaining)); if (!Found) return createFileError(Path, Found.takeError()); Current = Found->Entry; @@ -307,9 +324,16 @@ FileSystemCache::lookupPath(DiscoveryInstance &DI, StringRef Path, if (Error E = DI.requestSymlinkTarget(*Current)) return createFileError(Path, std::move(E)); StringRef Target = Current->asSymlink().getTarget(); - if (Target.consume_front("/")) - Current = Root; - else + if (is_absolute(Target, PathStyle)) { + if (is_style_windows(PathStyle)) { + Current = &getRoot(get_separator(PathStyle)); + // Pretend that we consumed the dummy root "\" + } else { + StringRef root_path = sys::path::root_path(Target, PathStyle); + Current = &getRoot(root_path); + Target.consume_front(root_path); + } + } else Current = Current->getParent(); pushWork(Target, SymlinkDepth); } @@ -419,14 +443,14 @@ vfs::directory_iterator FileSystemCache::getCachedVFSDirIter( SmallString<128> Storage; if (RequestedName.empty()) { RequestedName = WorkingDirectory; - } else if (!RequestedName.starts_with("/")) { + } else if (!is_absolute(RequestedName, PathStyle)) { Storage.append(WorkingDirectory); - sys::path::append(Storage, sys::path::Style::posix, RequestedName); + sys::path::append(Storage, PathStyle, RequestedName); RequestedName = Storage; } - RequestedName = RequestedName.rtrim("/"); + RequestedName = RequestedName.rtrim(get_separator(PathStyle)); std::shared_ptr DirIter = VFSDirIterImpl::create( - std::move(LookupSymlinkPath), RequestedName, Entries); + this, std::move(LookupSymlinkPath), RequestedName, Entries); return vfs::directory_iterator(std::move(DirIter)); } @@ -436,7 +460,8 @@ void FileSystemCache::VFSDirIterImpl::setEntry() { return; } const DirectoryEntry &Entry = **I; - std::string Path = (ParentPath + "/" + Entry.getName()).str(); + std::string Path = + (ParentPath + get_separator(Cache->PathStyle) + Entry.getName()).str(); if (!Entry.isSymlink()) { CurrentEntry = vfs::directory_entry(std::move(Path), Entry.getFileType()); return; @@ -461,8 +486,8 @@ std::error_code FileSystemCache::VFSDirIterImpl::increment() { std::shared_ptr FileSystemCache::VFSDirIterImpl::create( - LookupSymlinkPathType LookupSymlinkPath, StringRef ParentPath, - ArrayRef Entries) { + FileSystemCache *Cache, LookupSymlinkPathType LookupSymlinkPath, + StringRef ParentPath, ArrayRef Entries) { // Compute where to put the entry pointers and allocate. size_t IterSize = sizeof(VFSDirIterImpl); IterSize = alignTo(IterSize, alignof(DirectoryEntry *)); @@ -488,6 +513,7 @@ FileSystemCache::VFSDirIterImpl::create( // Construct the iterator, pointing at the co-allocated entries. return std::shared_ptr(new (IterPtr) VFSDirIterImpl( + Cache, std::move(LookupSymlinkPath), StringRef(HungOffParentPath, ParentPath.size()), ArrayRef(HungOffEntries, Entries.size()))); diff --git a/llvm/lib/CAS/HierarchicalTreeBuilder.cpp b/llvm/lib/CAS/HierarchicalTreeBuilder.cpp index 8f348c07b25f5..6ef5bdfb91f53 100644 --- a/llvm/lib/CAS/HierarchicalTreeBuilder.cpp +++ b/llvm/lib/CAS/HierarchicalTreeBuilder.cpp @@ -19,25 +19,28 @@ using namespace llvm::cas; /// Critical to canonicalize components so that paths come up next to each /// other when sorted. static StringRef canonicalize(SmallVectorImpl &Path, - TreeEntry::EntryKind Kind) { - // Make absolute. - if (Path.empty() || Path.front() != '/') - Path.insert(Path.begin(), '/'); + TreeEntry::EntryKind Kind, + sys::path::Style PathStyle) { + const char PathSeparatorChar = get_separator(PathStyle)[0]; + // Make absolute. Use has_root_directory instead of is_absolute + // because we may not have the drive like C: for abstract tree + // structures on Windows. + if (Path.empty() || !has_root_directory(Path, PathStyle)) + Path.insert(Path.begin(), PathSeparatorChar); // FIXME: consider rejecting ".." instead of removing them. - sys::path::remove_dots(Path, /*remove_dot_dot=*/true, - sys::path::Style::posix); + sys::path::remove_dots(Path, /*remove_dot_dot=*/true, PathStyle); // Canonicalize slashes. bool PendingSlash = false; char *NewEnd = Path.begin(); for (int I = 0, E = Path.size(); I != E; ++I) { - if (Path[I] == '/') { + if (Path[I] == PathSeparatorChar) { PendingSlash = true; continue; } if (PendingSlash) - *NewEnd++ = '/'; + *NewEnd++ = PathSeparatorChar; PendingSlash = false; *NewEnd++ = Path[I]; } @@ -45,7 +48,7 @@ static StringRef canonicalize(SmallVectorImpl &Path, // For correct sorting, all explicit trees need to end with a '/'. if (Path.empty() || Kind == TreeEntry::Tree) - Path.push_back('/'); + Path.push_back(PathSeparatorChar); return StringRef(Path.begin(), Path.size()); } @@ -54,7 +57,7 @@ void HierarchicalTreeBuilder::pushImpl(std::optional Ref, const Twine &Path) { SmallVector CanonicalPath; Path.toVector(CanonicalPath); - Entries.emplace_back(Ref, Kind, canonicalize(CanonicalPath, Kind)); + Entries.emplace_back(Ref, Kind, canonicalize(CanonicalPath, Kind, PathStyle)); } void HierarchicalTreeBuilder::pushTreeContent(ObjectRef Ref, @@ -62,10 +65,12 @@ void HierarchicalTreeBuilder::pushTreeContent(ObjectRef Ref, SmallVector CanonicalPath; Path.toVector(CanonicalPath); TreeEntry::EntryKind Kind = TreeEntry::Tree; - TreeContents.emplace_back(Ref, Kind, canonicalize(CanonicalPath, Kind)); + TreeContents.emplace_back(Ref, Kind, canonicalize(CanonicalPath, Kind, PathStyle)); } Expected HierarchicalTreeBuilder::create(ObjectStore &CAS) { + StringRef PathSeparator = get_separator(PathStyle); + const char PathSeparatorChar = PathSeparator[0]; // FIXME: It is inefficient expanding the whole tree recursively like this, // use a more efficient algorithm to merge contents. TreeSchema Schema(CAS); @@ -150,11 +155,13 @@ Expected HierarchicalTreeBuilder::create(ObjectStore &CAS) { Tree *Current = &Root; StringRef Path = Entry.getPath(); { - bool Consumed = Path.consume_front("/"); - (void)Consumed; - assert(Consumed && "Expected canonical POSIX absolute paths"); + assert(has_root_directory(Path, PathStyle) && "Expected absolute paths"); + StringRef root_path = sys::path::root_path(Path, PathStyle); + assert(!root_path.empty() && "Expected canonical POSIX absolute paths"); + Path.consume_front(root_path); } - for (auto Slash = Path.find('/'); !Path.empty(); Slash = Path.find('/')) { + for (auto Slash = Path.find(PathSeparatorChar); !Path.empty(); + Slash = Path.find(PathSeparatorChar)) { StringRef Name; if (Slash == StringRef::npos) { Name = Path; @@ -173,7 +180,7 @@ Expected HierarchicalTreeBuilder::create(ObjectStore &CAS) { // Need to canonicalize first, or else the sorting trick doesn't work. assert(Name != ""); - assert(Name != "/"); + assert(Name != PathSeparator); assert(Name != "."); assert(Name != ".."); diff --git a/llvm/lib/CAS/MappedFileRegionBumpPtr.cpp b/llvm/lib/CAS/MappedFileRegionBumpPtr.cpp index ed94387143431..2ed691d03fe76 100644 --- a/llvm/lib/CAS/MappedFileRegionBumpPtr.cpp +++ b/llvm/lib/CAS/MappedFileRegionBumpPtr.cpp @@ -166,10 +166,8 @@ Expected MappedFileRegionBumpPtr::create( // We are initializing the file; it may be empty, or may have been shrunk // during a previous close. // FIXME: Detect a case where someone opened it with a smaller capacity. - // FIXME: On Windows we should use FSCTL_SET_SPARSE and FSCTL_SET_ZERO_DATA - // to make this a sparse region, if supported. assert(InitLock.Locked == FileLockRAII::Exclusive); - if (std::error_code EC = sys::fs::resize_file(FD, Capacity)) + if (std::error_code EC = sys::fs::resize_file_sparse(FD, Capacity)) return createFileError(Result.Path, EC); if (Result.Logger) @@ -230,7 +228,8 @@ void MappedFileRegionBumpPtr::destroyImpl() { assert(Size < Capacity); // sync to file system to make sure all contents are up-to-date. (void)Region.sync(); - (void)sys::fs::resize_file(*FD, size()); + Region.unmap(); + (void)sys::fs::resize_file(*FD, Size); (void)unlockFileThreadSafe(*SharedLockFD); if (Logger) @@ -338,4 +337,4 @@ ErrorOr FileSizeInfo::get(sys::fs::file_t File) { return EC; return FileSizeInfo{Status.getSize(), Status.getSize()}; #endif -} \ No newline at end of file +} diff --git a/llvm/lib/Support/PrefixMapper.cpp b/llvm/lib/Support/PrefixMapper.cpp index 7105301e539a3..2f06e1512c7cc 100644 --- a/llvm/lib/Support/PrefixMapper.cpp +++ b/llvm/lib/Support/PrefixMapper.cpp @@ -9,6 +9,8 @@ #include "llvm/Support/PrefixMapper.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/CAS/TreePath.h" #include "llvm/Support/StringSaver.h" #include "llvm/Support/VirtualFileSystem.h" @@ -102,6 +104,30 @@ static bool startsWith(StringRef Path, StringRef Prefix, return true; } +static bool equals(StringRef Prefix1, StringRef Prefix2, + sys::path::Style PathStyle) { + if (PathStyle == sys::path::Style::posix || + (PathStyle == sys::path::Style::native && + sys::path::is_style_posix(sys::path::Style::native))) + return Prefix1 == Prefix2; + + if (Prefix1.size() != Prefix2.size()) + return false; + + // Windows prefix matching : case and separator insensitive + for (size_t I = 0, E = Prefix1.size(); I != E; ++I) { + bool Sep1 = sys::path::is_separator(Prefix1[I], PathStyle); + bool Sep2 = sys::path::is_separator(Prefix2[I], PathStyle); + if (Sep1 != Sep2) + return false; + if (Sep1) + continue; + if (toLower(Prefix1[I]) != toLower(Prefix2[I])) + return false; + } + return true; +} + std::optional PrefixMapper::mapImpl(StringRef Path, SmallVectorImpl &Storage) { for (const MappedPrefix &Map : Mappings) { @@ -189,22 +215,24 @@ TreePathPrefixMapper::~TreePathPrefixMapper() = default; std::optional TreePathPrefixMapper::mapImpl(StringRef Path, SmallVectorImpl &Storage) { - StringRef TreePath = getTreePath(Path); - std::optional Mapped = PrefixMapper::mapImpl(TreePath, Storage); + std::optional TreePath = getTreePath(Path); + StringRef FilePath = TreePath ? + llvm::cas::getFilePath(TreePath.value(), getPathStyle()) : Path; + std::optional Mapped = PrefixMapper::mapImpl(FilePath, Storage); if (Mapped) return *Mapped; - if (TreePath != Path) - return TreePath; + if (FilePath != Path) + return FilePath; return std::nullopt; } -StringRef TreePathPrefixMapper::getTreePath(StringRef Path) { +std::optional TreePathPrefixMapper::getTreePath(StringRef Path) { if (Path.empty()) - return Path; + return std::nullopt; auto Entry = FS->getDirectoryEntry(Path, /*FollowSymlinks=*/false); if (!Entry) { consumeError(Entry.takeError()); - return Path; + return std::nullopt; } return (*Entry)->getTreePath(); } @@ -214,10 +242,12 @@ void TreePathPrefixMapper::add(const MappedPrefix &Mapping) { // only affect the behaviour when later mapping a path that cannot be // canonicalized, since a non-canonical prefix cannot match a canonical path. PrefixMapper::add(Mapping); - StringRef Old = getTreePath(Mapping.Old); + std::optional OldTreePath = getTreePath(Mapping.Old); + if (!OldTreePath) return; + StringRef Old = llvm::cas::getFilePath(OldTreePath.value(), getPathStyle()); StringRef New = Mapping.New; // Add the canonical prefix mapping, if different. - if (Old != Mapping.Old) + if (!equals(Old, Mapping.Old, getPathStyle())) PrefixMapper::add(MappedPrefix{Old, New}); } @@ -225,6 +255,13 @@ StringRef TreePathPrefixMapper::mapDirEntry(const vfs::CachedDirectoryEntry &Entry, SmallVectorImpl &Storage) { StringRef TreePath = Entry.getTreePath(); - std::optional Mapped = PrefixMapper::mapImpl(TreePath, Storage); - return Mapped ? *Mapped : TreePath; + StringRef FilePath = llvm::cas::getFilePath(TreePath, getPathStyle()); + std::optional Mapped = PrefixMapper::mapImpl(FilePath, Storage); + if (Mapped) { + std::string MappedTreePath = + llvm::cas::getTreePath(*Mapped, getPathStyle()); + Storage.assign(MappedTreePath.begin(), MappedTreePath.end()); + return StringRef(Storage.begin(), Storage.size()); + } + return TreePath; } diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc index 3fc3f59df1e37..362eec5ebee8f 100644 --- a/llvm/lib/Support/Unix/Path.inc +++ b/llvm/lib/Support/Unix/Path.inc @@ -600,6 +600,10 @@ std::error_code resize_file(int FD, uint64_t Size) { return std::error_code(); } +std::error_code resize_file_sparse(int FD, uint64_t Size) { + return resize_file(FD, Size); +} + static int convertAccessMode(AccessMode Mode) { switch (Mode) { case AccessMode::Exist: diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index bbd6417509a5b..32ff408ee8d31 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -27,6 +27,7 @@ #include "llvm/Support/Windows/WindowsSupport.h" #include #include +#include #undef max @@ -623,6 +624,22 @@ std::error_code resize_file(int FD, uint64_t Size) { return std::error_code(error, std::generic_category()); } +std::error_code resize_file_sparse(int FD, uint64_t Size) { + HANDLE hFile = reinterpret_cast(::_get_osfhandle(FD)); + DWORD temp; + if (!DeviceIoControl(hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &temp, + NULL)) { + return mapWindowsError(GetLastError()); + } + LARGE_INTEGER liSize; + liSize.QuadPart = Size; + if (!SetFilePointerEx(hFile, liSize, NULL, FILE_BEGIN) || + !SetEndOfFile(hFile)) { + return mapWindowsError(GetLastError()); + } + return std::error_code(); +} + std::error_code access(const Twine &Path, AccessMode Mode) { SmallVector PathUtf16; @@ -1190,6 +1207,12 @@ static DWORD nativeAccess(FileAccess Access, OpenFlags Flags) { Result |= DELETE; if (Flags & OF_UpdateAtime) Result |= FILE_WRITE_ATTRIBUTES; + // If a combination of FA_Write and OF_Append are used, the supposed + // intent is to enable atomic appends, which requires using + // FILE_APPEND_DATA without GENERIC_WRITE. Otherwise, atomicity + // isn't enabled. + if (Access == FA_Write && Flags == OF_Append) + Result = FILE_APPEND_DATA; return Result; } diff --git a/llvm/lib/Support/Windows/Program.inc b/llvm/lib/Support/Windows/Program.inc index 799af5559966c..d8d2e181aa337 100644 --- a/llvm/lib/Support/Windows/Program.inc +++ b/llvm/lib/Support/Windows/Program.inc @@ -220,6 +220,10 @@ static bool Execute(ProcessInfo &PI, StringRef Program, llvm::append_range(EnvBlock, EnvString); EnvBlock.push_back(0); } + // If an empty environment (*Env is size zero), we need to + // terminate with two nulls. + if (Env->size() == 0) + EnvBlock.push_back(0); EnvBlock.push_back(0); } diff --git a/llvm/test/tools/llvm-cas/ingest-remap.test b/llvm/test/tools/llvm-cas/ingest-remap.test index 3ae90b50bdbe2..898df0822bec5 100644 --- a/llvm/test/tools/llvm-cas/ingest-remap.test +++ b/llvm/test/tools/llvm-cas/ingest-remap.test @@ -1,3 +1,5 @@ +REQUIRES: symlinks + RUN: rm -rf %t && mkdir -p %t RUN: llvm-cas --cas %t/cas --ingest --prefix-map %S/Inputs=/^input %S/Inputs > %t/cas.id diff --git a/llvm/test/tools/llvm-cas/ingest.test b/llvm/test/tools/llvm-cas/ingest.test index 67094a6f6e279..c68850f331e74 100644 --- a/llvm/test/tools/llvm-cas/ingest.test +++ b/llvm/test/tools/llvm-cas/ingest.test @@ -1,3 +1,5 @@ +REQUIRES: symlinks + RUN: rm -rf %t RUN: mkdir %t diff --git a/llvm/unittests/CAS/ActionCacheTest.cpp b/llvm/unittests/CAS/ActionCacheTest.cpp index 6e79d9da922ea..49360fb4397cb 100644 --- a/llvm/unittests/CAS/ActionCacheTest.cpp +++ b/llvm/unittests/CAS/ActionCacheTest.cpp @@ -80,6 +80,12 @@ TEST(OnDiskActionCache, ActionCacheResultInvalid) { ASSERT_THAT_ERROR(CAS1->createProxy({}, "2").moveInto(ID2), Succeeded()); ASSERT_THAT_ERROR(CAS2->createProxy({}, "1").moveInto(ID3), Succeeded()); +#if !defined(LLVM_ENABLE_ONDISK_CAS) + // The following won't work without LLVM_ENABLE_ONDISK_CAS enabled. + // TODO: enable LLVM_ENABLE_ONDISK_CAS on windows + return; +#endif + std::unique_ptr Cache1 = cantFail(createOnDiskActionCache(Temp.path())); // Test put and get. diff --git a/llvm/unittests/CAS/CASFileSystemTest.cpp b/llvm/unittests/CAS/CASFileSystemTest.cpp index 45e90d22fe1a1..2c7b5f7534d8e 100644 --- a/llvm/unittests/CAS/CASFileSystemTest.cpp +++ b/llvm/unittests/CAS/CASFileSystemTest.cpp @@ -47,12 +47,12 @@ static ObjectRef createBlobUnchecked(ObjectStore &CAS, StringRef Content) { } static Expected createEmptyTree(ObjectStore &CAS) { - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); return Builder.create(CAS); } static Expected createFlatTree(ObjectStore &CAS) { - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(createBlobUnchecked(CAS, "1"), TreeEntry::Regular, "file1"); Builder.push(createBlobUnchecked(CAS, "1"), TreeEntry::Regular, "1"); Builder.push(createBlobUnchecked(CAS, "2"), TreeEntry::Regular, "2"); @@ -64,7 +64,7 @@ static Expected createNestedTree(ObjectStore &CAS) { ObjectRef Data2 = createBlobUnchecked(CAS, "blob2"); ObjectRef Data3 = createBlobUnchecked(CAS, "blob3"); - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(Data2, TreeEntry::Regular, "/d2"); Builder.push(Data1, TreeEntry::Regular, "/t1/d1"); Builder.push(Data3, TreeEntry::Regular, "/t3/d3"); @@ -77,7 +77,7 @@ static Expected createNestedTree(ObjectStore &CAS) { static Expected createSymlinksTree(ObjectStore &CAS) { auto make = [&](StringRef Bytes) { return createBlobUnchecked(CAS, Bytes); }; - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(make("broken"), TreeEntry::Symlink, "/s0"); Builder.push(make("b1"), TreeEntry::Symlink, "/s1"); Builder.push(make("blob1"), TreeEntry::Regular, "/b1"); @@ -97,7 +97,7 @@ static Expected createSymlinksTree(ObjectStore &CAS) { static Expected createSymlinkLoopsTree(ObjectStore &CAS) { auto make = [&](StringRef Bytes) { return createBlobUnchecked(CAS, Bytes); }; - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(make("s0"), TreeEntry::Symlink, "/s0"); Builder.push(make("s1"), TreeEntry::Symlink, "/s2"); Builder.push(make("s2"), TreeEntry::Symlink, "/s1"); @@ -111,7 +111,7 @@ static Expected> createFS(ObjectStore &CAS, Expected Tree) { if (!Tree) return Tree.takeError(); - return createCASFileSystem(CAS, Tree->getID()); + return createCASFileSystem(CAS, Tree->getID(), sys::path::Style::posix); } template diff --git a/llvm/unittests/CAS/CachingOnDiskFileSystemTest.cpp b/llvm/unittests/CAS/CachingOnDiskFileSystemTest.cpp index dda0e2256849d..bb10ad25e3742 100644 --- a/llvm/unittests/CAS/CachingOnDiskFileSystemTest.cpp +++ b/llvm/unittests/CAS/CachingOnDiskFileSystemTest.cpp @@ -61,6 +61,10 @@ TEST(CachingOnDiskFileSystemTest, BasicRealFSIteration) { EXPECT_EQ(vfs::directory_iterator(), I); } +#ifndef _WIN32 + // Disabled on Windows. As the create_link uses a hard link and a + // hard link cannot be a directory on Windows, this TempLink will + // fail. TEST(CachingOnDiskFileSystemTest, MultipleWorkingDirs) { // Our root contains a/aa, b/bb, c, where c is a link to a/. // Run tests both in root/b/ and root/c/ (to test "normal" and symlink dirs). @@ -134,7 +138,11 @@ TEST(CachingOnDiskFileSystemTest, MultipleWorkingDirs) { ASSERT_FALSE(EC); ASSERT_EQ(CIt, vfs::directory_iterator()); } +#endif +#ifndef _WIN32 +// Disabled on Windows. As the create_link uses a hard link on +// Windows, TempLink will fail if the target doesn't exist. TEST(CachingOnDiskFileSystemTest, BrokenSymlinkRealFSIteration) { TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); IntrusiveRefCntPtr FS = @@ -164,6 +172,7 @@ TEST(CachingOnDiskFileSystemTest, BrokenSymlinkRealFSIteration) { testing::Pair("c", std::make_error_code( std::errc::no_such_file_or_directory)))); } +#endif TEST(CachingOnDiskFileSystemTest, BasicRealFSRecursiveIteration) { TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); @@ -288,6 +297,9 @@ TEST(CachingOnDiskFileSystemTest, BasicRealFSRecursiveIterationNoPush) { } } +#ifndef _WIN32 +// Disabled on Windows. As the create_link uses a hard link on +// Windows, TempLink will fail if the target doesn't exist. TEST(CachingOnDiskFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) { TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); IntrusiveRefCntPtr FS = @@ -326,7 +338,12 @@ TEST(CachingOnDiskFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) { _d.path().str(), _dd.path().str(), _ddd.path().str())); } +#endif +#ifndef _WIN32 +// Disabled on Windows. As the create_link uses a hard link on +// Windows, the full path is required for the link target and TempLink +// will fail if the target doesn't exist. TEST(CachingOnDiskFileSystemTest, Exists) { TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); IntrusiveRefCntPtr FS = @@ -342,6 +359,7 @@ TEST(CachingOnDiskFileSystemTest, Exists) { EXPECT_TRUE(FS->exists(Link.path())); EXPECT_FALSE(FS->exists(BrokenLink.path())); } +#endif TEST(CachingOnDiskFileSystemTest, TrackNewAccesses) { TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); @@ -350,7 +368,8 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccesses) { ASSERT_FALSE(FS->setCurrentWorkingDirectory(TestDirectory.path())); TreePathPrefixMapper Remapper(FS); - Remapper.add(MappedPrefix{TestDirectory.path(), "/"}); + Remapper.add(MappedPrefix{TestDirectory.path(), + sys::path::root_path(TestDirectory.path())}); TempFile Extra(TestDirectory.path("Extra"), "", "content"); SmallVector Temps; @@ -383,6 +402,15 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccesses) { ASSERT_THAT_ERROR(Schema.load(Tree->getRef()).moveInto(TreeNode), Succeeded()); +#ifdef _WIN32 + ASSERT_NE(TreeNode, std::nullopt); + EXPECT_EQ(TreeNode->size(), 1u); + auto DriveNode = TreeNode->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + ASSERT_THAT_ERROR(Schema.load(DriveNode->getRef()).moveInto(TreeNode), + Succeeded()); +#endif + // Check that all the files are found. EXPECT_EQ(Files.size(), TreeNode->size()); for (const auto &F : Files) @@ -397,7 +425,8 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccessesStack) { ASSERT_FALSE(FS->setCurrentWorkingDirectory(TestDirectory.path())); TreePathPrefixMapper Remapper(FS); - Remapper.add(MappedPrefix{TestDirectory.path(), "/"}); + Remapper.add(MappedPrefix{TestDirectory.path(), + sys::path::root_path(TestDirectory.path())}); TempFile Extra(TestDirectory.path("Extra"), "", "content"); SmallVector Temps; @@ -431,6 +460,14 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccessesStack) { std::optional TreeNode; ASSERT_THAT_ERROR(Schema.load(Tree->getRef()).moveInto(TreeNode), Succeeded()); +#ifdef _WIN32 + ASSERT_NE(TreeNode, std::nullopt); + EXPECT_EQ(TreeNode->size(), 1u); + auto DriveNode = TreeNode->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + ASSERT_THAT_ERROR(Schema.load(DriveNode->getRef()).moveInto(TreeNode), + Succeeded()); +#endif ASSERT_EQ(TreeNode->size(), 2u); EXPECT_TRUE(TreeNode->lookup(sys::path::filename(Temps[2].path()))); EXPECT_TRUE(TreeNode->lookup(sys::path::filename(Temps[3].path()))); @@ -452,6 +489,14 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccessesStack) { std::optional TreeNode; ASSERT_THAT_ERROR(Schema.load(Tree->getRef()).moveInto(TreeNode), Succeeded()); +#ifdef _WIN32 + ASSERT_NE(TreeNode, std::nullopt); + EXPECT_EQ(TreeNode->size(), 1u); + auto DriveNode = TreeNode->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + ASSERT_THAT_ERROR(Schema.load(DriveNode->getRef()).moveInto(TreeNode), + Succeeded()); +#endif ASSERT_EQ(TreeNode->size(), 2u); EXPECT_TRUE(TreeNode->lookup(sys::path::filename(Temps[0].path()))); EXPECT_TRUE(TreeNode->lookup(sys::path::filename(Temps[1].path()))); @@ -467,7 +512,8 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccessesExists) { ASSERT_FALSE(FS->setCurrentWorkingDirectory(TestDirectory.path())); TreePathPrefixMapper Remapper(FS); - Remapper.add(MappedPrefix{TestDirectory.path(), "/"}); + Remapper.add(MappedPrefix{TestDirectory.path(), + sys::path::root_path(TestDirectory.path())}); SmallVector Temps; for (size_t I = 0, E = 4; I != E; ++I) @@ -513,6 +559,14 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccessesExists) { std::optional TreeNode; ASSERT_THAT_ERROR(Schema.load(Tree->getRef()).moveInto(TreeNode), Succeeded()); +#ifdef _WIN32 + ASSERT_NE(TreeNode, std::nullopt); + EXPECT_EQ(TreeNode->size(), 1u); + auto DriveNode = TreeNode->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + ASSERT_THAT_ERROR(Schema.load(DriveNode->getRef()).moveInto(TreeNode), + Succeeded()); +#endif auto Node0 = TreeNode->lookup(sys::path::filename(Temps[0].path())); auto Node1 = TreeNode->lookup(sys::path::filename(Temps[1].path())); ASSERT_TRUE(Node0); @@ -537,6 +591,14 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccessesExists) { std::optional TreeNode; ASSERT_THAT_ERROR(Schema.load(Tree->getRef()).moveInto(TreeNode), Succeeded()); +#ifdef _WIN32 + ASSERT_NE(TreeNode, std::nullopt); + EXPECT_EQ(TreeNode->size(), 1u); + auto DriveNode = TreeNode->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + ASSERT_THAT_ERROR(Schema.load(DriveNode->getRef()).moveInto(TreeNode), + Succeeded()); +#endif auto Node0 = TreeNode->lookup(sys::path::filename(Temps[0].path())); auto Node1 = TreeNode->lookup(sys::path::filename(Temps[1].path())); ASSERT_TRUE(Node0); @@ -561,6 +623,14 @@ TEST(CachingOnDiskFileSystemTest, TrackNewAccessesExists) { std::optional TreeNode; ASSERT_THAT_ERROR(Schema.load(Tree->getRef()).moveInto(TreeNode), Succeeded()); +#ifdef _WIN32 + ASSERT_NE(TreeNode, std::nullopt); + EXPECT_EQ(TreeNode->size(), 1u); + auto DriveNode = TreeNode->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + ASSERT_THAT_ERROR(Schema.load(DriveNode->getRef()).moveInto(TreeNode), + Succeeded()); +#endif auto Node0 = TreeNode->lookup(sys::path::filename(Temps[0].path())); auto Node1 = TreeNode->lookup(sys::path::filename(Temps[1].path())); ASSERT_TRUE(Node0); @@ -604,7 +674,8 @@ TEST(CachingOnDiskFileSystemTest, ExcludeFromTacking) { ASSERT_FALSE(FS->setCurrentWorkingDirectory(TestDirectory.path())); TreePathPrefixMapper Remapper(FS); - Remapper.add(MappedPrefix{TestDirectory.path(), "/"}); + Remapper.add(MappedPrefix{TestDirectory.path(), + sys::path::root_path(TestDirectory.path())}); TempDir D1(TestDirectory.path("d1")); TempDir D2(TestDirectory.path("d2")); @@ -662,6 +733,15 @@ TEST(CachingOnDiskFileSystemTest, ExcludeFromTacking) { EXPECT_EQ(FS->excludeFromTracking(F21.path()), std::error_code()); AccessAllFiles(); auto Tree = CreateTreeFromNewAccesses(); +#ifdef _WIN32 + ASSERT_NE(Tree, std::nullopt); + EXPECT_EQ(Tree->size(), 1u); + auto DriveNode = Tree->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + auto DriveDir = Schema.load(DriveNode->getRef()); + ASSERT_THAT_EXPECTED(DriveDir, Succeeded()); + Tree = *DriveDir; +#endif ASSERT_NE(Tree, std::nullopt); EXPECT_EQ(Tree->size(), 1u); EXPECT_FALSE(Tree->lookup("d1")); @@ -680,6 +760,15 @@ TEST(CachingOnDiskFileSystemTest, ExcludeFromTacking) { EXPECT_EQ(FS->excludeFromTracking(D1.path()), std::error_code()); EXPECT_EQ(FS->excludeFromTracking(F21.path()), std::error_code()); auto Tree = CreateTreeFromNewAccesses(); +#ifdef _WIN32 + ASSERT_NE(Tree, std::nullopt); + EXPECT_EQ(Tree->size(), 1u); + auto DriveNode = Tree->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + auto DriveDir = Schema.load(DriveNode->getRef()); + ASSERT_THAT_EXPECTED(DriveDir, Succeeded()); + Tree = *DriveDir; +#endif ASSERT_NE(Tree, std::nullopt); EXPECT_EQ(Tree->size(), 1u); EXPECT_FALSE(Tree->lookup("d1")); @@ -698,6 +787,15 @@ TEST(CachingOnDiskFileSystemTest, ExcludeFromTacking) { EXPECT_EQ(FS->excludeFromTracking(D1Sub.path()), std::error_code()); EXPECT_EQ(FS->excludeFromTracking(D2.path()), std::error_code()); auto Tree = CreateTreeFromNewAccesses(); +#ifdef _WIN32 + ASSERT_NE(Tree, std::nullopt); + EXPECT_EQ(Tree->size(), 1u); + auto DriveNode = Tree->lookup(sys::path::root_name(TestDirectory.path())); + ASSERT_TRUE(DriveNode); + auto DriveDir = Schema.load(DriveNode->getRef()); + ASSERT_THAT_EXPECTED(DriveDir, Succeeded()); + Tree = *DriveDir; +#endif ASSERT_NE(Tree, std::nullopt); EXPECT_EQ(Tree->size(), 1u); EXPECT_FALSE(Tree->lookup("d2")); @@ -711,6 +809,8 @@ TEST(CachingOnDiskFileSystemTest, ExcludeFromTacking) { } } +#ifndef _WIN32 +// As the create_link uses a hard link on Windows, the paths don't match. TEST(CachingOnDiskFileSystemTest, getRealPath) { TempDir D("caching-on-disk-file-system-test", /*Unique=*/true); IntrusiveRefCntPtr FS = @@ -725,6 +825,7 @@ TEST(CachingOnDiskFileSystemTest, getRealPath) { EXPECT_FALSE(FS->getRealPath(Link.path(), LinkPath)); EXPECT_EQ(FilePath, LinkPath); } +#endif TEST(CachingOnDiskFileSystemTest, caseSensitivityFile) { TempDir D("caching-on-disk-file-system-test", /*Unique=*/true); @@ -768,6 +869,9 @@ TEST(CachingOnDiskFileSystemTest, caseSensitivityFile) { } } +#ifndef _WIN32 +// On windows, create_link uses a hard link and cannot handle a link +// to a directory. TEST(CachingOnDiskFileSystemTest, caseSensitivityDir) { TempDir D("caching-on-disk-file-system-test", /*Unique=*/true); IntrusiveRefCntPtr FS = @@ -834,5 +938,6 @@ TEST(CachingOnDiskFileSystemTest, caseSensitivityDir) { EXPECT_EQ(StatF1.getUniqueID(), StatF2.getUniqueID()); } } +#endif } // namespace diff --git a/llvm/unittests/CAS/HierarchicalTreeBuilderTest.cpp b/llvm/unittests/CAS/HierarchicalTreeBuilderTest.cpp index dd7a4e854b129..3372d42b2cbc2 100644 --- a/llvm/unittests/CAS/HierarchicalTreeBuilderTest.cpp +++ b/llvm/unittests/CAS/HierarchicalTreeBuilderTest.cpp @@ -39,7 +39,7 @@ TEST(HierarchicalTreeBuilderTest, Flat) { return *expectedToOptional(CAS->storeFromString({}, Content)); }; - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(make("1"), TreeEntry::Regular, "/file1"); Builder.push(make("1"), TreeEntry::Regular, "/1"); Builder.push(make("2"), TreeEntry::Regular, "/2"); @@ -47,7 +47,8 @@ TEST(HierarchicalTreeBuilderTest, Flat) { ASSERT_TRUE(Root); std::unique_ptr CASFS = - expectedToPointer(createCASFileSystem(*CAS, Root->getID())); + expectedToPointer(createCASFileSystem(*CAS, Root->getID(), + sys::path::Style::posix)); ASSERT_TRUE(CASFS); std::unique_ptr F1 = @@ -74,7 +75,7 @@ TEST(HierarchicalTreeBuilderTest, Nested) { return *expectedToOptional(CAS->storeFromString({}, Content)); }; - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(make("blob2"), TreeEntry::Regular, "/d2"); Builder.push(make("blob1"), TreeEntry::Regular, "/t1/d1"); Builder.push(make("blob3"), TreeEntry::Regular, "/t3/d3"); @@ -85,7 +86,8 @@ TEST(HierarchicalTreeBuilderTest, Nested) { ASSERT_TRUE(Root); std::unique_ptr CASFS = - expectedToPointer(createCASFileSystem(*CAS, Root->getID())); + expectedToPointer(createCASFileSystem(*CAS, Root->getID(), + sys::path::Style::posix)); std::unique_ptr T1D1 = errorOrToPointer(CASFS->getBufferForFile("/t1/d1")); @@ -120,7 +122,7 @@ TEST(HierarchicalTreeBuilderTest, MergeDirectories) { auto createRoot = [&](StringRef Blob, StringRef Path, std::optional &Root) { - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(make(Blob), TreeEntry::Regular, Path); std::optional H; @@ -135,7 +137,7 @@ TEST(HierarchicalTreeBuilderTest, MergeDirectories) { std::optional Root3; createRoot("blob3", "/t1/nested/d1", Root3); - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.pushTreeContent(*Root1, "/"); Builder.pushTreeContent(*Root2, ""); Builder.pushTreeContent(*Root3, "/"); @@ -145,7 +147,8 @@ TEST(HierarchicalTreeBuilderTest, MergeDirectories) { ASSERT_THAT_ERROR(Builder.create(*CAS).moveInto(Root), Succeeded()); std::unique_ptr CASFS = - cantFail(createCASFileSystem(*CAS, Root->getID())); + cantFail(createCASFileSystem(*CAS, Root->getID(), + sys::path::Style::posix)); std::unique_ptr T1D1 = errorOrToPointer(CASFS->getBufferForFile("/t1/d1")); @@ -180,7 +183,7 @@ TEST(HierarchicalTreeBuilderTest, MergeDirectoriesConflict) { auto createRoot = [&](StringRef Blob, StringRef Path, std::optional &Root) { - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(make(Blob), TreeEntry::Regular, Path); ASSERT_THAT_ERROR(Builder.create(*CAS).moveInto(Root), Succeeded()); }; @@ -193,7 +196,7 @@ TEST(HierarchicalTreeBuilderTest, MergeDirectoriesConflict) { createRoot("blob3", "/t1/d1/nested", Root3); { - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.pushTreeContent(Root1->getRef(), ""); Builder.pushTreeContent(Root2->getRef(), ""); std::optional Root; @@ -202,7 +205,7 @@ TEST(HierarchicalTreeBuilderTest, MergeDirectoriesConflict) { FailedWithMessage("duplicate path '/t1/d1' with different ID")); } { - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.pushTreeContent(Root1->getRef(), ""); Builder.pushTreeContent(Root3->getRef(), ""); std::optional Root; diff --git a/llvm/unittests/CAS/ObjectStoreTest.cpp b/llvm/unittests/CAS/ObjectStoreTest.cpp index 79a19cfa42a64..dd61e9a819b7c 100644 --- a/llvm/unittests/CAS/ObjectStoreTest.cpp +++ b/llvm/unittests/CAS/ObjectStoreTest.cpp @@ -350,6 +350,7 @@ TEST_P(CASTest, BlobsBigParallel) { } #if LLVM_ENABLE_ONDISK_CAS +#ifndef _WIN32 // create_link won't work for directories on Windows TEST(OnDiskCASTest, BlobsParallelMultiCAS) { // This test intentionally uses symlinked paths to the same CAS to subvert the // shared memory mappings that would normally be created within a single @@ -405,8 +406,8 @@ TEST(OnDiskCASTest, BlobsBigParallelMultiCAS) { uint64_t Size = 100ULL * 1024; ASSERT_NO_FATAL_FAILURE(testBlobsParallel(*CAS1, *CAS2, *CAS3, *CAS4, Size)); } +#endif // _WIN32 -#ifndef _WIN32 // FIXME: resize support on Windows. TEST(OnDiskCASTest, DiskSize) { setMaxOnDiskCASMappingSize(); unittest::TempDir Temp("on-disk-cas", /*Unique=*/true); @@ -454,5 +455,4 @@ TEST(OnDiskCASTest, DiskSize) { CAS.reset(); CheckFileSizes(/*Mapped=*/false); } -#endif -#endif +#endif // LLVM_ENABLE_ONDISK_CAS diff --git a/llvm/unittests/CAS/PluginCASTest.cpp b/llvm/unittests/CAS/PluginCASTest.cpp index 30361aacb77b7..6584e6694e60a 100644 --- a/llvm/unittests/CAS/PluginCASTest.cpp +++ b/llvm/unittests/CAS/PluginCASTest.cpp @@ -30,8 +30,13 @@ static std::string getCASPluginPath() { sys::fs::getMainExecutable(TestMainArgv0, &TestStringArg1); llvm::SmallString<256> PathBuf(sys::path::parent_path( sys::path::parent_path(sys::path::parent_path(Executable)))); +#ifndef _WIN32 std::string LibName = "libCASPluginTest"; sys::path::append(PathBuf, "lib", LibName + LLVM_PLUGIN_EXT); +#else + std::string LibName = "CASPluginTest"; + sys::path::append(PathBuf, "bin", LibName + LLVM_PLUGIN_EXT); +#endif return std::string(PathBuf); } diff --git a/llvm/unittests/CAS/TreeSchemaTest.cpp b/llvm/unittests/CAS/TreeSchemaTest.cpp index 633a2f7f36c41..7916867ef87fd 100644 --- a/llvm/unittests/CAS/TreeSchemaTest.cpp +++ b/llvm/unittests/CAS/TreeSchemaTest.cpp @@ -231,7 +231,7 @@ TEST(TreeSchemaTest, walkFileTreeRecursively) { return cantFail(CAS->storeFromString({}, Content)); }; - HierarchicalTreeBuilder Builder; + HierarchicalTreeBuilder Builder(sys::path::Style::posix); Builder.push(make("blob2"), TreeEntry::Regular, "/d2"); Builder.push(make("blob1"), TreeEntry::Regular, "/t1/d1"); Builder.push(make("blob3"), TreeEntry::Regular, "/t3/d3"); diff --git a/llvm/unittests/Support/PrefixMapperTest.cpp b/llvm/unittests/Support/PrefixMapperTest.cpp index 251ba48082436..4f364e4ceef86 100644 --- a/llvm/unittests/Support/PrefixMapperTest.cpp +++ b/llvm/unittests/Support/PrefixMapperTest.cpp @@ -416,7 +416,7 @@ TEST(TreePathPrefixMapperTest, construct) { TEST(TreePathPrefixMapperTest, add) { auto FS = makeIntrusiveRefCnt(); - TreePathPrefixMapper PM(FS); + TreePathPrefixMapper PM(FS, sys::path::Style::posix); // Non-canonical paths create two map entries: one for the canonical and one // for the non-canonical path. @@ -440,7 +440,7 @@ TEST(TreePathPrefixMapperTest, add) { TEST(TreePathPrefixMapperTest, addRange) { auto FS = makeIntrusiveRefCnt(); - TreePathPrefixMapper PM(FS); + TreePathPrefixMapper PM(FS, sys::path::Style::posix); MappedPrefix MissingMapping[] = { {"missing", "/new"}, @@ -465,7 +465,7 @@ TEST(TreePathPrefixMapperTest, addRange) { TEST(TreePathPrefixMapperTest, addInverseRange) { auto FS = makeIntrusiveRefCnt(); - TreePathPrefixMapper PM(FS); + TreePathPrefixMapper PM(FS, sys::path::Style::posix); MappedPrefix MissingMapping[] = { {"/new", "missing"}, @@ -513,7 +513,7 @@ struct MapState { {"/missing/nested", "/missing/nested"}, {"/relative/nested", "/relative/nested"}, }; - MapState() : PM(FS) { + MapState() : PM(FS, sys::path::Style::posix) { PM.add(MappedPrefix{"relative", "/new1"}); PM.add(MappedPrefix{"/absolute", "/new2"}); } diff --git a/llvm/unittests/Support/ProgramTest.cpp b/llvm/unittests/Support/ProgramTest.cpp index 693b53b0a9781..a63f5895f55ad 100644 --- a/llvm/unittests/Support/ProgramTest.cpp +++ b/llvm/unittests/Support/ProgramTest.cpp @@ -597,4 +597,22 @@ TEST_F(ProgramEnvTest, TestExecuteWithNoStacktraceHandler) { ASSERT_EQ(0, RetCode); } +TEST_F(ProgramEnvTest, TestExecuteEmptyEnvironment) { + using namespace llvm::sys; + + std::string Executable = + sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); + StringRef argv[] = { + Executable, + "--gtest_filter=" // A null invocation to avoid infinite recursion + }; + + std::string Error; + bool ExecutionFailed; + int RetCode = ExecuteAndWait(Executable, argv, ArrayRef{}, {}, 0, + 0, &Error, &ExecutionFailed); + EXPECT_FALSE(ExecutionFailed) << Error; + ASSERT_EQ(0, RetCode); +} + } // end anonymous namespace diff --git a/llvm/unittests/Support/SourceMgrTest.cpp b/llvm/unittests/Support/SourceMgrTest.cpp index 15e8ce9684540..41d09ab5adc75 100644 --- a/llvm/unittests/Support/SourceMgrTest.cpp +++ b/llvm/unittests/Support/SourceMgrTest.cpp @@ -497,6 +497,13 @@ TEST_F(SourceMgrTest, FixitForTab) { Output); } +/// Replace back-slashes by front-slashes. +static std::string getPosixPath(const Twine &S) { + SmallString<128> Result; + llvm::sys::path::native(S, Result, llvm::sys::path::Style::posix); + return std::string(Result.str()); +} + TEST_F(SourceMgrTest, AddIncludedFile) { auto FS = makeIntrusiveRefCnt(); @@ -524,12 +531,16 @@ TEST_F(SourceMgrTest, AddIncludedFile) { ASSERT_TRUE(Include1.isValid()); std::string Included; ASSERT_EQ(2u, SM.AddIncludeFile(Filename.str(), Include1, Included)); - ASSERT_EQ(Filename, Included); + // When on Windows, we end up with a mixed-slash path. Convert to + // Posix path for the sake of the comparison. + ASSERT_EQ(Filename, getPosixPath(Included)); SMLoc Include2 = SM.FindLocForLineAndColumn(2u, 2, 1); ASSERT_TRUE(Include2.isValid()); ASSERT_EQ(3u, SM.AddIncludeFile(IncludesFilename.str(), Include2, Included)); - ASSERT_EQ(IncludesPath, Included); + // When on Windows, we end up with a mixed-slash path. Convert to + // Posix path for the sake of the comparison. + ASSERT_EQ(IncludesPath, getPosixPath(Included)); SMLoc Deepest = SM.FindLocForLineAndColumn(3u, 3, 1); ASSERT_TRUE(Deepest.isValid()); diff --git a/llvm/unittests/Support/VirtualOutputBackendsTest.cpp b/llvm/unittests/Support/VirtualOutputBackendsTest.cpp index abc8c996d7bc9..3e39f76021629 100644 --- a/llvm/unittests/Support/VirtualOutputBackendsTest.cpp +++ b/llvm/unittests/Support/VirtualOutputBackendsTest.cpp @@ -346,7 +346,7 @@ class OnDiskOutputBackendProvider : public OutputBackendProvider { StringRef Parent2) override { init(); SmallString<128> Path; - sys::path::append(Path, D->path(), Parent1, Parent2, getFilePathToCreate()); + sys::path::append(Path, D->path(), Parent1, Parent2, "file.data"); return Path.str().str(); } @@ -561,9 +561,18 @@ Error OnDiskOutputBackendProvider::checkKept(StringRef FilePath, sys::fs::UniqueID UID = shouldUseTemporaries(*Info) ? *Info->TempUID : *Info->UID; +#ifndef _WIN32 if (!Info->F->hasUniqueID(UID)) return createStringError(inconvertibleErrorCode(), "File not created by keep or changed UID"); +#else + // On Windows, the UID changes in a rename that happens in keep() + // because it's based on hash of file paths. Instead check that the + // file contents are the same. + if (!Info->F->equalsCurrentContent(Data)) + return createStringError(inconvertibleErrorCode(), + "File not created by keep"); +#endif if (std::optional Temp = Info->F->findTemp()) return createStringError(inconvertibleErrorCode(), @@ -796,8 +805,21 @@ TEST(OnDiskBackendTest, OnlyIfDifferent) { EXPECT_FALSE(O2.isOpen()); EXPECT_FALSE(sys::fs::status(FilePath, Status2, /*follow=*/false)); +#ifndef _WIN32 // Make sure the output path file is not modified with same content. EXPECT_EQ(Status1.getUniqueID(), Status2.getUniqueID()); +#else + // On Windows, UniqueIDs are currently hash of file paths and don't + // change on overwrites or depend on the file content. Check that + // the file content is what is expected instead. + auto EqualsCurrentContent = [](StringRef FilePath, StringRef Data) -> bool { + auto BufOrErr = MemoryBuffer::getFile(FilePath); + if (!BufOrErr) + return false; + return (*BufOrErr)->getBuffer() == Data; + }; + EXPECT_TRUE(EqualsCurrentContent(FilePath, Data)); +#endif // Write third with different content. EXPECT_THAT_ERROR(Backend->createFile(FilePath, Config).moveInto(O3), @@ -807,8 +829,15 @@ TEST(OnDiskBackendTest, OnlyIfDifferent) { EXPECT_FALSE(O3.isOpen()); EXPECT_FALSE(sys::fs::status(FilePath, Status3, /*follow=*/false)); +#ifndef _WIN32 // This should overwrite the file and create a different UniqueID. EXPECT_NE(Status1.getUniqueID(), Status3.getUniqueID()); +#else + // On Windows, UniqueIDs are currently hash of file paths and don't + // change on overwrites or depend on the file content. Check that + // the file content is what is expected instead. + EXPECT_TRUE(EqualsCurrentContent(FilePath, (Data + "\n").str())); +#endif } TEST(OnDiskBackendTest, Append) { diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py index 5ec8c7a50b5d5..4ca98f013fe7a 100644 --- a/llvm/utils/lit/lit/TestRunner.py +++ b/llvm/utils/lit/lit/TestRunner.py @@ -1443,6 +1443,7 @@ def getDefaultSubstitutions(test, tmpDir, tmpBase, normalize_slashes=False): ("%{fs-src-root}", pathlib.Path(sourcedir).anchor), ("%{fs-tmp-root}", pathlib.Path(tmpBase).anchor), ("%{fs-sep}", os.path.sep), + ("%{fs-sep-yaml}", "\\\\\\\\\\\\\\\\" if kIsWindows else "/"), ] ) @@ -1487,6 +1488,25 @@ def regex_escape(s): # a leading slash. substitutions.append(("%:" + letter, colonNormalizePath(path))) + substitutions.extend( + [ + # %t (tmpName) in tree path forms for Windows + ("%{t-tree}", "\\" + tmpName if kIsWindows else tmpName), + ("%{t-tree-/}", "/" + tmpName.replace("\\", "/") if kIsWindows else tmpName), + ] + ) + + substitutions.extend( + [ + # The filesystem root and their tree path forms for + # Windows for CAS prefix mapping. The t suffix stands for + # tree path. Those with suffixes need to use {} because + # lit macro names cannot be a prefix of another macro. + ("%/root", os.environ.get('SystemDrive') + "/" if kIsWindows else "/"), + ("%{/roott}", "/" + os.environ.get('SystemDrive') + "/" if kIsWindows else "/"), + ] + ) + return substitutions diff --git a/llvm/utils/lit/lit/llvm/config.py b/llvm/utils/lit/lit/llvm/config.py index 44119ec8c0eca..352e3c5a4191f 100644 --- a/llvm/utils/lit/lit/llvm/config.py +++ b/llvm/utils/lit/lit/llvm/config.py @@ -1,5 +1,6 @@ import itertools import os +import pathlib import platform import re import subprocess @@ -710,6 +711,9 @@ def use_clang( ToolSubst( "%clang", command=self.config.clang, extra_args=additional_flags ), + ToolSubst( + "%/clang", command=self.config.clang.replace("\\", "/"), extra_args=additional_flags + ), ToolSubst( "%clang_analyze_cc1", command="%clang_cc1", @@ -748,6 +752,17 @@ def use_clang( command=self.config.clang, extra_args=["--driver-mode=g++"] + additional_flags, ), + # A clang path with natural casing on Windows. Same as + # %/clang on non-Windows. + ToolSubst( + "%/ncclang", + command = ( + str(pathlib.Path(self.config.clang).resolve(strict=False)).replace("\\", "/") + if platform.system() == "Windows" + else self.config.clang.replace("\\", "/") + ), + extra_args=additional_flags + ), ] self.add_tool_substitutions(tool_substitutions) self.config.substitutions.append(("%resource_dir", builtin_include_dir))