From dd8769cb92f1f9a7b27476be0d836e621f78c40b Mon Sep 17 00:00:00 2001 From: Hiroshi Yamauchi Date: Thu, 28 Aug 2025 14:02:21 -0700 Subject: [PATCH] Fix the following CAS-related tests on Windows Clang :: ClangScanDeps/cas-trees.c Clang :: ClangScanDeps/modules-availability-check.c Clang :: ClangScanDeps/modules-cas-fs-vfsoverlay.c Clang :: ClangScanDeps/modules-cas-implicit-module-cache.c Clang :: ClangScanDeps/modules-cas-trees-cwd.c Clang :: ClangScanDeps/modules-cas-trees-input-files.c Clang :: ClangScanDeps/modules-cas-trees-with-pch.c Clang :: ClangScanDeps/modules-cas-trees.c --- clang/test/ClangScanDeps/cas-trees.c | 40 +++---- .../ClangScanDeps/modules-cas-trees-cwd.c | 6 +- .../modules-cas-trees-with-pch.c | 32 +++--- clang/test/ClangScanDeps/modules-cas-trees.c | 24 ++--- llvm/include/llvm/CAS/FileSystemCache.h | 1 - llvm/lib/CAS/CachingOnDiskFileSystem.cpp | 100 ++++++++++++------ llvm/lib/CAS/FileSystemCache.cpp | 39 +++---- 7 files changed, 139 insertions(+), 103 deletions(-) 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/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/llvm/include/llvm/CAS/FileSystemCache.h b/llvm/include/llvm/CAS/FileSystemCache.h index 97ceccc04d1a2..d3fd3387c20fe 100644 --- a/llvm/include/llvm/CAS/FileSystemCache.h +++ b/llvm/include/llvm/CAS/FileSystemCache.h @@ -223,7 +223,6 @@ class FileSystemCache : public ThreadSafeRefCountedBase { DirectoryEntry &getRoot(StringRef root_path, std::optional RootRef = std::nullopt); - StringRef getRootPathFor(StringRef Path) const; sys::path::Style getPathStyle() const { return PathStyle; } using LookupSymlinkPathType = diff --git a/llvm/lib/CAS/CachingOnDiskFileSystem.cpp b/llvm/lib/CAS/CachingOnDiskFileSystem.cpp index 83b1b97601be0..bc7635b32760a 100644 --- a/llvm/lib/CAS/CachingOnDiskFileSystem.cpp +++ b/llvm/lib/CAS/CachingOnDiskFileSystem.cpp @@ -24,6 +24,31 @@ void CachingOnDiskFileSystem::anchor() {} namespace { +// 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. +static 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(); +} + +static 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; +} + class CachingOnDiskFileSystemImpl final : public CachingOnDiskFileSystem { struct WorkingDirectoryType { FileSystemCache::DirectoryEntry *Entry; @@ -151,6 +176,8 @@ class CachingOnDiskFileSystemImpl final : public CachingOnDiskFileSystem { } } + sys::path::Style getPathStyle() { return Cache->getPathStyle(); } + private: void initializeWorkingDirectory(); @@ -247,12 +274,7 @@ void CachingOnDiskFileSystemImpl::initializeWorkingDirectory() { // Start with root, and then initialize the current working directory to // match process state, ignoring errors if there's a problem. -#ifndef _WIN32 static std::string RootPath = get_separator(sys::path::Style::native).str(); -#else - static std::string RootPath = const_cast(getenv("SYSTEMDRIVE")) + - get_separator(sys::path::Style::native).str(); -#endif WorkingDirectory.Entry = &Cache->getRoot(RootPath); WorkingDirectory.Path = WorkingDirectory.Entry->getTreePath().str(); @@ -315,7 +337,8 @@ CachingOnDiskFileSystemImpl::makeSymlink(DirectoryEntry &Parent, StringRef TreePath) { PathStorage TreePathStorage(TreePath); SmallString<128> Target; - if (auto Err = readLink(TreePathStorage.Path, Target)) + if (auto Err = readLink( + getFilePath(TreePathStorage.Path, Cache->getPathStyle()), Target)) return std::move(Err); return makeSymlinkTo(Parent, TreePathStorage.Path, Target); } @@ -358,12 +381,13 @@ CachingOnDiskFileSystemImpl::makeEntry( std::optional KnownStatus) { assert(Parent.isDirectory() && "Expected a directory"); PathStorage TreePathStorage(TreePath); + StringRef FilePath = 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(TreePathStorage.Path, Status, + } else if (auto EC = sys::fs::status(FilePath, Status, /*follow=*/false)) { return errorCodeToError(EC); } @@ -374,7 +398,7 @@ CachingOnDiskFileSystemImpl::makeEntry( if (Status.type() == sys::fs::file_type::symlink_file) return makeSymlink(Parent, TreePathStorage.Path); - auto F = sys::fs::openNativeFile(TreePathStorage.Path, + auto F = sys::fs::openNativeFile(FilePath, sys::fs::CD_OpenExisting, sys::fs::FA_Read, sys::fs::OF_None); if (!F) return F.takeError(); @@ -428,9 +452,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 = getFilePath(Entry->getTreePath(), + Cache->getPathStyle()); + Output.resize(RealFilePath.size()); + llvm::copy(RealFilePath, Output.begin()); return std::error_code(); } @@ -485,9 +510,12 @@ 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 = getFilePath(Entry->getTreePath(), + Cache->getPathStyle()); + for (sys::fs::directory_iterator I(EntryFilePath, EC), E; + !EC && I != E; I.increment(EC)) { + TreePaths.emplace_back(getTreePath(I->path(), Cache->getPathStyle())); + } if (EC) return EC; @@ -519,9 +547,11 @@ Expected CachingOnDiskFileSystemImpl::preloadRealPath(DirectoryEntry &From, StringRef Remaining) { PathStorage RemainingStorage(Remaining); - SmallString<256> ExpectedRealPath; - ExpectedRealPath = From.getTreePath(); - sys::path::append(ExpectedRealPath, RemainingStorage.Path); + SmallString<256> ExpectedRealTreePath; + ExpectedRealTreePath = From.getTreePath(); + sys::path::append(ExpectedRealTreePath, RemainingStorage.Path); + SmallString<256> ExpectedRealPath = 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 @@ -543,20 +573,21 @@ CachingOnDiskFileSystemImpl::preloadRealPath(DirectoryEntry &From, /* expand_tilde */false)) return errorCodeToError(EC); + SmallString<256> RealTreePath = StringRef(getTreePath(RealPath, + Cache->getPathStyle())); FileSystemCache::LookupPathState State(Cache->getPathStyle(), - Cache->getRoot(Cache->getRootPathFor(RealPath)), RealPath); + 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(RemainingStorage.Path.size()); -#ifndef _WIN32 - if (RealPath.str().starts_with(ExpectedPrefix)) -#else - if (RealPath.str().starts_with_insensitive(ExpectedPrefix)) -#endif - State = FileSystemCache::LookupPathState( - Cache->getPathStyle(), 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); @@ -567,8 +598,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. @@ -590,7 +621,7 @@ CachingOnDiskFileSystemImpl::preloadRealPath(DirectoryEntry &From, const bool IsDir = sys::fs::is_directory(Status); if (IsDir) - return makeDirectory(*State.Entry, RealPath); + return makeDirectory(*State.Entry, RealTreePath); auto FD = sys::fs::openNativeFileForRead(ExpectedRealPath, sys::fs::OF_None, /*RealPath=*/nullptr); @@ -600,7 +631,7 @@ CachingOnDiskFileSystemImpl::preloadRealPath(DirectoryEntry &From, } auto CloseOnExit = make_scope_exit([&FD]() { sys::fs::closeFile(*FD); }); - auto F = makeFile(*State.Entry, RealPath, *FD, Status); + auto F = makeFile(*State.Entry, RealTreePath, *FD, Status); if (F) return *F; llvm::consumeError(F.takeError()); @@ -757,10 +788,11 @@ DiscoveryInstanceImpl::requestDirectoryEntry(DirectoryEntry &Parent, assert(Parent.isDirectory() && "Expected a directory"); SmallString<256> Path(Parent.getTreePath()); sys::path::append(Path, Name); + StringRef FilePath = 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 = @@ -785,9 +817,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 = 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 diff --git a/llvm/lib/CAS/FileSystemCache.cpp b/llvm/lib/CAS/FileSystemCache.cpp index c52258460a51d..6b10f83fc8050 100644 --- a/llvm/lib/CAS/FileSystemCache.cpp +++ b/llvm/lib/CAS/FileSystemCache.cpp @@ -28,13 +28,6 @@ DirectoryEntry &FileSystemCache::getRoot(StringRef root_path, return *Root; } -StringRef FileSystemCache::getRootPathFor(StringRef Path) const { - if (is_absolute(Path, PathStyle)) - return sys::path::root_path(Path, PathStyle); - else - return sys::path::root_path(WorkingDirectory.Path, PathStyle); -} - StringRef FileSystemCache::canonicalizeWorkingDirectory(sys::path::Style PathStyle, StringRef WorkingDirectory, @@ -104,11 +97,11 @@ static DirectoryEntry &makeLazyEntry( DirectoryEntry &Parent, FileSystemCache::Directory &D, StringRef TreePath, DirectoryEntry::EntryKind Kind, std::optional Ref, sys::path::Style PathStyle) { -#ifndef _WIN32 - assert(sys::path::parent_path(TreePath, PathStyle) == Parent.getTreePath()); -#else - assert(sys::path::parent_path(TreePath, PathStyle).equals_insensitive(Parent.getTreePath())); -#endif + 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()); @@ -276,9 +269,14 @@ FileSystemCache::lookupPath(DiscoveryInstance &DI, StringRef Path, // Start at the current working directory, unless the path is absolute. DirectoryEntry *Current = &WorkingDirectory; if (is_absolute(Path, PathStyle)) { - StringRef root_path = sys::path::root_path(Path, PathStyle); - Current = &getRoot(root_path); - Path.consume_front(root_path); + 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); @@ -320,9 +318,14 @@ FileSystemCache::lookupPath(DiscoveryInstance &DI, StringRef Path, return createFileError(Path, std::move(E)); StringRef Target = Current->asSymlink().getTarget(); if (is_absolute(Target, PathStyle)) { - StringRef root_path = sys::path::root_path(Target, PathStyle); - Current = &getRoot(root_path); - Target.consume_front(root_path); + 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);