Skip to content

Commit a446ad8

Browse files
committed
Merge commit '5a8a7ee9d12d' from llvm.org/main into next
2 parents c7973aa + 5a8a7ee commit a446ad8

File tree

3 files changed

+112
-49
lines changed

3 files changed

+112
-49
lines changed

llvm/include/llvm/Support/VirtualFileSystem.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -993,12 +993,12 @@ class RedirectingFileSystem
993993
/// Canonicalize path by removing ".", "..", "./", components. This is
994994
/// a VFS request, do not bother about symlinks in the path components
995995
/// but canonicalize in order to perform the correct entry search.
996-
std::error_code makeCanonical(SmallVectorImpl<char> &Path) const;
996+
std::error_code makeCanonicalForLookup(SmallVectorImpl<char> &Path) const;
997997

998998
/// Get the File status, or error, from the underlying external file system.
999999
/// This returns the status with the originally requested name, while looking
1000-
/// up the entry using the canonical path.
1001-
ErrorOr<Status> getExternalStatus(const Twine &CanonicalPath,
1000+
/// up the entry using a potentially different path.
1001+
ErrorOr<Status> getExternalStatus(const Twine &LookupPath,
10021002
const Twine &OriginalPath) const;
10031003

10041004
/// Make \a Path an absolute path.
@@ -1086,7 +1086,7 @@ class RedirectingFileSystem
10861086
llvm::SmallVectorImpl<Entry *> &Entries) const;
10871087

10881088
/// Get the status for a path with the provided \c LookupResult.
1089-
ErrorOr<Status> status(const Twine &CanonicalPath, const Twine &OriginalPath,
1089+
ErrorOr<Status> status(const Twine &LookupPath, const Twine &OriginalPath,
10901090
const LookupResult &Result);
10911091

10921092
public:

llvm/lib/Support/VirtualFileSystem.cpp

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ std::error_code RedirectingFileSystem::isLocal(const Twine &Path_,
13731373
SmallString<256> Path;
13741374
Path_.toVector(Path);
13751375

1376-
if (makeCanonical(Path))
1376+
if (makeAbsolute(Path))
13771377
return {};
13781378

13791379
return ExternalFS->isLocal(Path, Result);
@@ -1440,7 +1440,7 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
14401440
SmallString<256> Path;
14411441
Dir.toVector(Path);
14421442

1443-
EC = makeCanonical(Path);
1443+
EC = makeAbsolute(Path);
14441444
if (EC)
14451445
return {};
14461446

@@ -2290,8 +2290,8 @@ void RedirectingFileSystem::LookupResult::getPath(
22902290
llvm::sys::path::append(Result, E->getName());
22912291
}
22922292

2293-
std::error_code
2294-
RedirectingFileSystem::makeCanonical(SmallVectorImpl<char> &Path) const {
2293+
std::error_code RedirectingFileSystem::makeCanonicalForLookup(
2294+
SmallVectorImpl<char> &Path) const {
22952295
if (std::error_code EC = makeAbsolute(Path))
22962296
return EC;
22972297

@@ -2306,12 +2306,16 @@ RedirectingFileSystem::makeCanonical(SmallVectorImpl<char> &Path) const {
23062306

23072307
ErrorOr<RedirectingFileSystem::LookupResult>
23082308
RedirectingFileSystem::lookupPath(StringRef Path) const {
2309+
llvm::SmallString<128> CanonicalPath(Path);
2310+
if (std::error_code EC = makeCanonicalForLookup(CanonicalPath))
2311+
return EC;
2312+
23092313
// RedirectOnly means the VFS is always used.
23102314
if (UsageTrackingActive && Redirection == RedirectKind::RedirectOnly)
23112315
HasBeenUsed = true;
23122316

2313-
sys::path::const_iterator Start = sys::path::begin(Path);
2314-
sys::path::const_iterator End = sys::path::end(Path);
2317+
sys::path::const_iterator Start = sys::path::begin(CanonicalPath);
2318+
sys::path::const_iterator End = sys::path::end(CanonicalPath);
23152319
llvm::SmallVector<Entry *, 32> Entries;
23162320
for (const auto &Root : Roots) {
23172321
ErrorOr<RedirectingFileSystem::LookupResult> Result =
@@ -2387,14 +2391,14 @@ static Status getRedirectedFileStatus(const Twine &OriginalPath,
23872391
}
23882392

23892393
ErrorOr<Status> RedirectingFileSystem::status(
2390-
const Twine &CanonicalPath, const Twine &OriginalPath,
2394+
const Twine &LookupPath, const Twine &OriginalPath,
23912395
const RedirectingFileSystem::LookupResult &Result) {
23922396
if (std::optional<StringRef> ExtRedirect = Result.getExternalRedirect()) {
2393-
SmallString<256> CanonicalRemappedPath((*ExtRedirect).str());
2394-
if (std::error_code EC = makeCanonical(CanonicalRemappedPath))
2397+
SmallString<256> RemappedPath((*ExtRedirect).str());
2398+
if (std::error_code EC = makeAbsolute(RemappedPath))
23952399
return EC;
23962400

2397-
ErrorOr<Status> S = ExternalFS->status(CanonicalRemappedPath);
2401+
ErrorOr<Status> S = ExternalFS->status(RemappedPath);
23982402
if (!S)
23992403
return S;
24002404
S = Status::copyWithNewName(*S, *ExtRedirect);
@@ -2404,13 +2408,13 @@ ErrorOr<Status> RedirectingFileSystem::status(
24042408
}
24052409

24062410
auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(Result.E);
2407-
return Status::copyWithNewName(DE->getStatus(), CanonicalPath);
2411+
return Status::copyWithNewName(DE->getStatus(), LookupPath);
24082412
}
24092413

24102414
ErrorOr<Status>
2411-
RedirectingFileSystem::getExternalStatus(const Twine &CanonicalPath,
2415+
RedirectingFileSystem::getExternalStatus(const Twine &LookupPath,
24122416
const Twine &OriginalPath) const {
2413-
auto Result = ExternalFS->status(CanonicalPath);
2417+
auto Result = ExternalFS->status(LookupPath);
24142418

24152419
// The path has been mapped by some nested VFS, don't override it with the
24162420
// original path.
@@ -2420,38 +2424,37 @@ RedirectingFileSystem::getExternalStatus(const Twine &CanonicalPath,
24202424
}
24212425

24222426
ErrorOr<Status> RedirectingFileSystem::status(const Twine &OriginalPath) {
2423-
SmallString<256> CanonicalPath;
2424-
OriginalPath.toVector(CanonicalPath);
2427+
SmallString<256> Path;
2428+
OriginalPath.toVector(Path);
24252429

2426-
if (std::error_code EC = makeCanonical(CanonicalPath))
2430+
if (std::error_code EC = makeAbsolute(Path))
24272431
return EC;
24282432

24292433
if (Redirection == RedirectKind::Fallback) {
24302434
// Attempt to find the original file first, only falling back to the
24312435
// mapped file if that fails.
2432-
ErrorOr<Status> S = getExternalStatus(CanonicalPath, OriginalPath);
2436+
ErrorOr<Status> S = getExternalStatus(Path, OriginalPath);
24332437
if (S)
24342438
return S;
24352439
}
24362440

2437-
ErrorOr<RedirectingFileSystem::LookupResult> Result =
2438-
lookupPath(CanonicalPath);
2441+
ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path);
24392442
if (!Result) {
24402443
// Was not able to map file, fallthrough to using the original path if
24412444
// that was the specified redirection type.
24422445
if (Redirection == RedirectKind::Fallthrough &&
24432446
isFileNotFound(Result.getError()))
2444-
return getExternalStatus(CanonicalPath, OriginalPath);
2447+
return getExternalStatus(Path, OriginalPath);
24452448
return Result.getError();
24462449
}
24472450

2448-
ErrorOr<Status> S = status(CanonicalPath, OriginalPath, *Result);
2451+
ErrorOr<Status> S = status(Path, OriginalPath, *Result);
24492452
if (!S && Redirection == RedirectKind::Fallthrough &&
24502453
isFileNotFound(S.getError(), Result->E)) {
24512454
// Mapped the file but it wasn't found in the underlying filesystem,
24522455
// fallthrough to using the original path if that was the specified
24532456
// redirection type.
2454-
return getExternalStatus(CanonicalPath, OriginalPath);
2457+
return getExternalStatus(Path, OriginalPath);
24552458
}
24562459

24572460
return S;
@@ -2548,53 +2551,49 @@ File::getWithPath(ErrorOr<std::unique_ptr<File>> Result, const Twine &P) {
25482551

25492552
ErrorOr<std::unique_ptr<File>>
25502553
RedirectingFileSystem::openFileForRead(const Twine &OriginalPath) {
2551-
SmallString<256> CanonicalPath;
2552-
OriginalPath.toVector(CanonicalPath);
2554+
SmallString<256> Path;
2555+
OriginalPath.toVector(Path);
25532556

2554-
if (std::error_code EC = makeCanonical(CanonicalPath))
2557+
if (std::error_code EC = makeAbsolute(Path))
25552558
return EC;
25562559

25572560
if (Redirection == RedirectKind::Fallback) {
25582561
// Attempt to find the original file first, only falling back to the
25592562
// mapped file if that fails.
2560-
auto F = File::getWithPath(ExternalFS->openFileForRead(CanonicalPath),
2561-
OriginalPath);
2563+
auto F = File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
25622564
if (F)
25632565
return F;
25642566
}
25652567

2566-
ErrorOr<RedirectingFileSystem::LookupResult> Result =
2567-
lookupPath(CanonicalPath);
2568+
ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path);
25682569
if (!Result) {
25692570
// Was not able to map file, fallthrough to using the original path if
25702571
// that was the specified redirection type.
25712572
if (Redirection == RedirectKind::Fallthrough &&
25722573
isFileNotFound(Result.getError()))
2573-
return File::getWithPath(ExternalFS->openFileForRead(CanonicalPath),
2574-
OriginalPath);
2574+
return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
25752575
return Result.getError();
25762576
}
25772577

25782578
if (!Result->getExternalRedirect()) // FIXME: errc::not_a_file?
25792579
return make_error_code(llvm::errc::invalid_argument);
25802580

25812581
StringRef ExtRedirect = *Result->getExternalRedirect();
2582-
SmallString<256> CanonicalRemappedPath(ExtRedirect.str());
2583-
if (std::error_code EC = makeCanonical(CanonicalRemappedPath))
2582+
SmallString<256> RemappedPath(ExtRedirect.str());
2583+
if (std::error_code EC = makeAbsolute(RemappedPath))
25842584
return EC;
25852585

25862586
auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
25872587

2588-
auto ExternalFile = File::getWithPath(
2589-
ExternalFS->openFileForRead(CanonicalRemappedPath), ExtRedirect);
2588+
auto ExternalFile =
2589+
File::getWithPath(ExternalFS->openFileForRead(RemappedPath), ExtRedirect);
25902590
if (!ExternalFile) {
25912591
if (Redirection == RedirectKind::Fallthrough &&
25922592
isFileNotFound(ExternalFile.getError(), Result->E)) {
25932593
// Mapped the file but it wasn't found in the underlying filesystem,
25942594
// fallthrough to using the original path if that was the specified
25952595
// redirection type.
2596-
return File::getWithPath(ExternalFS->openFileForRead(CanonicalPath),
2597-
OriginalPath);
2596+
return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
25982597
}
25992598
return ExternalFile;
26002599
}
@@ -2614,28 +2613,27 @@ RedirectingFileSystem::openFileForRead(const Twine &OriginalPath) {
26142613
std::error_code
26152614
RedirectingFileSystem::getRealPath(const Twine &OriginalPath,
26162615
SmallVectorImpl<char> &Output) const {
2617-
SmallString<256> CanonicalPath;
2618-
OriginalPath.toVector(CanonicalPath);
2616+
SmallString<256> Path;
2617+
OriginalPath.toVector(Path);
26192618

2620-
if (std::error_code EC = makeCanonical(CanonicalPath))
2619+
if (std::error_code EC = makeAbsolute(Path))
26212620
return EC;
26222621

26232622
if (Redirection == RedirectKind::Fallback) {
26242623
// Attempt to find the original file first, only falling back to the
26252624
// mapped file if that fails.
2626-
std::error_code EC = ExternalFS->getRealPath(CanonicalPath, Output);
2625+
std::error_code EC = ExternalFS->getRealPath(Path, Output);
26272626
if (!EC)
26282627
return EC;
26292628
}
26302629

2631-
ErrorOr<RedirectingFileSystem::LookupResult> Result =
2632-
lookupPath(CanonicalPath);
2630+
ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path);
26332631
if (!Result) {
26342632
// Was not able to map file, fallthrough to using the original path if
26352633
// that was the specified redirection type.
26362634
if (Redirection == RedirectKind::Fallthrough &&
26372635
isFileNotFound(Result.getError()))
2638-
return ExternalFS->getRealPath(CanonicalPath, Output);
2636+
return ExternalFS->getRealPath(Path, Output);
26392637
return Result.getError();
26402638
}
26412639

@@ -2648,7 +2646,7 @@ RedirectingFileSystem::getRealPath(const Twine &OriginalPath,
26482646
// Mapped the file but it wasn't found in the underlying filesystem,
26492647
// fallthrough to using the original path if that was the specified
26502648
// redirection type.
2651-
return ExternalFS->getRealPath(CanonicalPath, Output);
2649+
return ExternalFS->getRealPath(Path, Output);
26522650
}
26532651
return P;
26542652
}

llvm/unittests/Support/VirtualFileSystemTest.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Support/VirtualFileSystem.h"
10+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
1011
#include "llvm/ADT/ScopeExit.h"
1112
#include "llvm/Config/llvm-config.h"
1213
#include "llvm/Support/Errc.h"
14+
#include "llvm/Support/FileSystem.h"
1315
#include "llvm/Support/MemoryBuffer.h"
1416
#include "llvm/Support/Path.h"
1517
#include "llvm/Support/SourceMgr.h"
@@ -3491,3 +3493,66 @@ TEST(RedirectingFileSystemTest, Used) {
34913493
EXPECT_TRUE(Redirecting1->hasBeenUsed());
34923494
EXPECT_FALSE(Redirecting2->hasBeenUsed());
34933495
}
3496+
3497+
// Check that paths looked up in the external filesystem are unmodified, except
3498+
// potentially to add the working directory. We cannot canonicalize away ..
3499+
// in the presence of symlinks in the external filesystem.
3500+
TEST(RedirectingFileSystemTest, ExternalPaths) {
3501+
struct InterceptorFS : llvm::vfs::ProxyFileSystem {
3502+
std::vector<std::string> SeenPaths;
3503+
3504+
InterceptorFS(IntrusiveRefCntPtr<FileSystem> UnderlyingFS)
3505+
: ProxyFileSystem(UnderlyingFS) {}
3506+
3507+
llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override {
3508+
SeenPaths.push_back(Path.str());
3509+
return ProxyFileSystem::status(Path);
3510+
}
3511+
3512+
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
3513+
openFileForRead(const Twine &Path) override {
3514+
SeenPaths.push_back(Path.str());
3515+
return ProxyFileSystem::openFileForRead(Path);
3516+
}
3517+
3518+
std::error_code isLocal(const Twine &Path, bool &Result) override {
3519+
SeenPaths.push_back(Path.str());
3520+
return ProxyFileSystem::isLocal(Path, Result);
3521+
}
3522+
3523+
vfs::directory_iterator dir_begin(const Twine &Dir,
3524+
std::error_code &EC) override {
3525+
SeenPaths.push_back(Dir.str());
3526+
return ProxyFileSystem::dir_begin(Dir, EC);
3527+
}
3528+
};
3529+
3530+
std::error_code EC;
3531+
auto BaseFS = makeIntrusiveRefCnt<DummyFileSystem>();
3532+
BaseFS->setCurrentWorkingDirectory("/cwd");
3533+
auto CheckFS = makeIntrusiveRefCnt<InterceptorFS>(BaseFS);
3534+
auto FS = vfs::RedirectingFileSystem::create({}, /*UseExternalNames=*/false,
3535+
*CheckFS);
3536+
3537+
FS->status("/a/../b");
3538+
FS->openFileForRead("c");
3539+
FS->exists("./d");
3540+
bool IsLocal = false;
3541+
FS->isLocal("/e/./../f", IsLocal);
3542+
FS->dir_begin(".././g", EC);
3543+
3544+
std::vector<std::string> Expected{"/a/../b", "/cwd/c", "/cwd/./d",
3545+
"/e/./../f", "/cwd/.././g"};
3546+
3547+
EXPECT_EQ(CheckFS->SeenPaths, Expected);
3548+
3549+
CheckFS->SeenPaths.clear();
3550+
FS->setRedirection(vfs::RedirectingFileSystem::RedirectKind::Fallback);
3551+
FS->status("/a/../b");
3552+
FS->openFileForRead("c");
3553+
FS->exists("./d");
3554+
FS->isLocal("/e/./../f", IsLocal);
3555+
FS->dir_begin(".././g", EC);
3556+
3557+
EXPECT_EQ(CheckFS->SeenPaths, Expected);
3558+
}

0 commit comments

Comments
 (0)