https://github.com/grqz updated https://github.com/llvm/llvm-project/pull/178585
>From 024e3b5f3cb938f5d8fb957b739ebc21173b4344 Mon Sep 17 00:00:00 2001 From: Hans Wennborg <[email protected]> Date: Thu, 29 Jan 2026 14:10:14 +1300 Subject: [PATCH 1/2] Add support for case-insensitive path lookup This is a port of <https://reviews.llvm.org/D21113>. Adds clang/cc1 option -fcase-insensitive-paths. (wiNdoWS.H -> Windows.h) This commit also adds a COFF lld-link flag --case-insensitive-paths for case-insensitive library lookup (uuid.lib -> Uuid.lib). --case-insensitive-paths is NOT automatically passed to the linker when -fcase-insensitive-paths is passed. Co-authored-by: Hans Wennborg <[email protected]> Co-authored-by: grqz <[email protected]> --- .../clang/Frontend/CompilerInvocation.h | 5 +- clang/include/clang/Lex/HeaderSearchOptions.h | 6 +- clang/include/clang/Options/Options.td | 5 + clang/lib/Driver/ToolChains/Clang.cpp | 3 + clang/lib/Frontend/ASTUnit.cpp | 3 +- clang/lib/Frontend/CompilerInvocation.cpp | 26 +++-- clang/lib/Lex/HeaderSearch.cpp | 4 +- clang/test/Driver/cl-options.c | 1 + clang/test/Frontend/case-insensitive-paths.c | 8 ++ lld/COFF/Driver.cpp | 34 +++--- lld/COFF/Options.td | 2 + lld/test/COFF/case-insensitive-paths.test | 2 + llvm/include/llvm/Support/VirtualFileSystem.h | 36 ++++++ llvm/lib/Support/VirtualFileSystem.cpp | 104 ++++++++++++++++++ .../Support/VirtualFileSystemTest.cpp | 56 +++++++++- 15 files changed, 262 insertions(+), 33 deletions(-) create mode 100644 clang/test/Frontend/case-insensitive-paths.c create mode 100644 lld/test/COFF/case-insensitive-paths.test diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h index 6fa6cd5d95534..dae212c782fab 100644 --- a/clang/include/clang/Frontend/CompilerInvocation.h +++ b/clang/include/clang/Frontend/CompilerInvocation.h @@ -404,9 +404,8 @@ IntrusiveRefCntPtr<llvm::vfs::FileSystem> createVFSFromCompilerInvocation( IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS); IntrusiveRefCntPtr<llvm::vfs::FileSystem> -createVFSFromOverlayFiles(ArrayRef<std::string> VFSOverlayFiles, - DiagnosticsEngine &Diags, - IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS); +createVFSFromHSOpts(const HeaderSearchOptions &HSOpts, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS); } // namespace clang diff --git a/clang/include/clang/Lex/HeaderSearchOptions.h b/clang/include/clang/Lex/HeaderSearchOptions.h index 2f33c0749f02a..901ab7a4fb3fc 100644 --- a/clang/include/clang/Lex/HeaderSearchOptions.h +++ b/clang/include/clang/Lex/HeaderSearchOptions.h @@ -207,6 +207,10 @@ class HeaderSearchOptions { LLVM_PREFERRED_TYPE(bool) unsigned Verbose : 1; + /// Whether header search should be case-insensitive. + LLVM_PREFERRED_TYPE(bool) + unsigned CaseInsensitive : 1; + /// If true, skip verifying input files used by modules if the /// module was already verified during this build session (see /// \c BuildSessionTimestamp). @@ -289,7 +293,7 @@ class HeaderSearchOptions { ModuleFileHomeIsCwd(false), EnablePrebuiltImplicitModules(false), UseBuiltinIncludes(true), UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false), - ModulesValidateOncePerBuildSession(false), + CaseInsensitive(false), ModulesValidateOncePerBuildSession(false), ModulesValidateSystemHeaders(false), ModulesForceValidateUserHeaders(true), ValidateASTInputFilesContent(false), diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 43727236ed5a4..384c7bdf8fee5 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -2034,6 +2034,11 @@ def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group<f_Group>, Visibility<[ClangOption, CLOption, DXCOption, CC1Option]>, HelpText<"Use ANSI escape codes for diagnostics">, MarshallingInfoFlag<DiagnosticOpts<"UseANSIEscapeCodes">>; +def fcase_insensitive_paths + : Flag<["-"], "fcase-insensitive-paths">, + Group<f_Group>, + Visibility<[ClangOption, CLOption, DXCOption, CC1Option]>, + HelpText<"Treat file paths as case-insensitive">; def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Group<f_clang_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Treat each comma separated argument in <arg> as a documentation comment block command">, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index ab671d032644b..c40ab4f73f383 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1186,6 +1186,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, Args.addOptInFlag(CmdArgs, options::OPT_fdefine_target_os_macros, options::OPT_fno_define_target_os_macros); + + if (Args.hasArg(options::OPT_fcase_insensitive_paths)) + CmdArgs.push_back("-fcase-insensitive-paths"); } // FIXME: Move to target hook. diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index ee22e16bc202d..faeb89f1e43c1 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -749,8 +749,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( return nullptr; } - VFS = createVFSFromOverlayFiles(AST->HSOpts->VFSOverlayFiles, - *AST->Diagnostics, std::move(VFS)); + VFS = createVFSFromHSOpts(*AST->HSOpts, *AST->Diagnostics, std::move(VFS)); AST->FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOpts, VFS); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5a79634773866..0256ee07f5810 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3382,6 +3382,9 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts, for (const std::string &F : Opts.VFSOverlayFiles) GenerateArg(Consumer, OPT_ivfsoverlay, F); + + if (Opts.CaseInsensitive) + GenerateArg(Consumer, OPT_fcase_insensitive_paths); } static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, @@ -3502,6 +3505,8 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay)) Opts.AddVFSOverlayFile(A->getValue()); + Opts.CaseInsensitive = Args.hasArg(OPT_fcase_insensitive_paths); + return Diags.getNumErrors() == NumErrorsBefore; } @@ -5440,19 +5445,17 @@ IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromCompilerInvocation( const CompilerInvocation &CI, DiagnosticsEngine &Diags, IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) { - return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles, - Diags, std::move(BaseFS)); + return createVFSFromHSOpts(CI.getHeaderSearchOpts(), Diags, + std::move(BaseFS)); } -IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles( - ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags, - IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) { - if (VFSOverlayFiles.empty()) - return BaseFS; - +IntrusiveRefCntPtr<llvm::vfs::FileSystem> +clang::createVFSFromHSOpts(const HeaderSearchOptions &HSOpts, + DiagnosticsEngine &Diags, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) { IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS; // earlier vfs files are on the bottom - for (const auto &File : VFSOverlayFiles) { + for (const auto &File : HSOpts.VFSOverlayFiles) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer = Result->getBufferForFile(File); if (!Buffer) { @@ -5470,5 +5473,10 @@ IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles( Result = FS; } + + if (HSOpts.CaseInsensitive) + return llvm::makeIntrusiveRefCnt<llvm::vfs::CaseInsensitiveFileSystem>( + std::move(Result)); + return Result; } diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 5f52d62bd36ed..e20180e3f8611 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -148,12 +148,12 @@ std::vector<bool> HeaderSearch::collectVFSUsageAndClear() const { llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem(); // TODO: This only works if the `RedirectingFileSystem`s were all created by - // `createVFSFromOverlayFiles`. But at least exclude the ones with null + // `createVFSFromHSOpts`. But at least exclude the ones with null // OverlayFileDir. RootFS.visit([&](llvm::vfs::FileSystem &FS) { if (auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) { // Skip a `RedirectingFileSystem` with null OverlayFileDir which indicates - // that they aren't created by createVFSFromOverlayFiles from the overlays + // that they aren't created by createVFSFromHSOpts from the overlays // in HeaderSearchOption::VFSOverlayFiles. if (!RFS->getOverlayFileDir().empty()) { VFSUsage.push_back(RFS->hasBeenUsed()); diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 611d0d2927c43..3b8e563807017 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -762,6 +762,7 @@ // RUN: -fno-wrapv \ // RUN: -fwrapv-pointer \ // RUN: -fno-wrapv-pointer \ +// RUN: -fcase-insensitive-paths \ // RUN: --version \ // RUN: --warning-suppression-mappings=foo \ // RUN: -Werror /Zs -- %s 2>&1 diff --git a/clang/test/Frontend/case-insensitive-paths.c b/clang/test/Frontend/case-insensitive-paths.c new file mode 100644 index 0000000000000..0b99ce671d9eb --- /dev/null +++ b/clang/test/Frontend/case-insensitive-paths.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -E -P -verify --show-includes -Wno-nonportable-include-path \ +// RUN: -fcase-insensitive-paths %s 2>&1 | FileCheck %s + +#include "inPuts/eMptY.H" // expected-no-diagnostics + +// Make sure the exact spelling used in the #include directive is preserved +// when printing header dependencies (consistent with MSVC /showIncludes). +// CHECK: Note: including file: {{.*}}inPuts/eMptY.H diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 3bc9c98bcdbc3..a2e7a91e494cd 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1523,24 +1523,28 @@ std::optional<std::string> getReproduceFile(const opt::InputArgList &args) { static std::unique_ptr<llvm::vfs::FileSystem> getVFS(COFFLinkerContext &ctx, const opt::InputArgList &args) { - using namespace llvm::vfs; - - const opt::Arg *arg = args.getLastArg(OPT_vfsoverlay); - if (!arg) - return nullptr; + auto overlayFs = [&]() -> std::unique_ptr<vfs::FileSystem> { + const opt::Arg *arg = args.getLastArg(OPT_vfsoverlay); + if (!arg) + return nullptr; - auto bufOrErr = llvm::MemoryBuffer::getFile(arg->getValue()); - if (!bufOrErr) { - checkError(errorCodeToError(bufOrErr.getError())); - return nullptr; - } + auto bufOrErr = llvm::MemoryBuffer::getFile(arg->getValue()); + if (!bufOrErr) { + checkError(errorCodeToError(bufOrErr.getError())); + return nullptr; + } - if (auto ret = vfs::getVFSFromYAML(std::move(*bufOrErr), - /*DiagHandler*/ nullptr, arg->getValue())) - return ret; + if (auto ret = vfs::getVFSFromYAML( + std::move(*bufOrErr), /*DiagHandler*/ nullptr, arg->getValue())) + return ret; - Err(ctx) << "Invalid vfs overlay"; - return nullptr; + Err(ctx) << "Invalid vfs overlay"; + return nullptr; + }(); + if (args.hasArg(OPT_case_insensitive_paths)) + return std::make_unique<vfs::CaseInsensitiveFileSystem>( + overlayFs ? std::move(overlayFs) : vfs::getRealFileSystem()); + return overlayFs; } static StringRef DllDefaultEntryPoint(MachineTypes machine, bool mingw) { diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index fb762b880c2cb..8326f9fe0d7e4 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -35,6 +35,8 @@ def arm64xsameaddress : P<"arm64xsameaddress", "Generate a thunk for the symbol with the same " "address in both native and EC views on ARM64X.">; def base : P<"base", "Base address of the program">; +def case_insensitive_paths : Flag<["--"], "case-insensitive-paths">, + HelpText<"Treat file paths as case-insensitive">; def color_diagnostics: Flag<["--"], "color-diagnostics">, HelpText<"Alias for --color-diagnostics=always">; def no_color_diagnostics: Flag<["--"], "no-color-diagnostics">, diff --git a/lld/test/COFF/case-insensitive-paths.test b/lld/test/COFF/case-insensitive-paths.test new file mode 100644 index 0000000000000..74d6871b5c88d --- /dev/null +++ b/lld/test/COFF/case-insensitive-paths.test @@ -0,0 +1,2 @@ +# RUN: lld-link %S/Inputs/hello64.obj /out:%t.exe /entry:main \ +# RUN: /libpath:%p/inPutS /defaultlib:StD64 --case-insensitive-paths diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 5b8871b8f3db5..056d601da8cc6 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -17,6 +17,7 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/Compiler.h" @@ -500,6 +501,41 @@ class LLVM_ABI ProxyFileSystem void anchor() override; }; +class LLVM_ABI CaseInsensitiveFileSystem + : public RTTIExtends<CaseInsensitiveFileSystem, FileSystem> { + IntrusiveRefCntPtr<FileSystem> FS; + + /// Map from directory to map from lowercase to real-case filename. + StringMap<StringMap<std::string>> Maps; + +public: + static const char ID; + CaseInsensitiveFileSystem(IntrusiveRefCntPtr<FileSystem> FS) + : FS(std::move(FS)) {} + + llvm::ErrorOr<Status> status(const Twine &Path) override; + llvm::ErrorOr<std::unique_ptr<File>> + openFileForRead(const Twine &Path) override; + directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; + llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override { + return FS->getCurrentWorkingDirectory(); + } + std::error_code setCurrentWorkingDirectory(const Twine &Path) override { + Maps.clear(); + return FS->setCurrentWorkingDirectory(Path); + } + +protected: + /// Attempt to exclude the possibility that File exists in Dir based on + /// previous information. + bool exclude(StringRef Dir, uint32_t DirHash, StringRef File); + + /// Try to find Path by means of case-insensitive lookup. Stores the result in + /// FoundPath on success, or returns an error code otherwise. + std::error_code findCaseInsensitivePath(StringRef Path, + SmallVectorImpl<char> &FoundPath); +}; + namespace detail { class InMemoryDirectory; diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 49a5cefe6a7d7..a831061f62816 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -658,6 +658,109 @@ directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir, void ProxyFileSystem::anchor() {} +//===-----------------------------------------------------------------------===/ +// CaseInsensitiveFileSystem implementation +//===-----------------------------------------------------------------------===/ + +bool CaseInsensitiveFileSystem::exclude(StringRef Dir, uint32_t DirHash, + StringRef File) { + if (auto I = Maps.find(Dir, DirHash); I != Maps.end()) + return !I->second.contains(File.lower()); + // We have no map for this Dir, but see if we can exclude the file by + // excluding Dir from its parent. + StringRef Parent = llvm::sys::path::parent_path(Dir); + return (!Parent.empty() && + exclude(Parent, Maps.hash(Parent), llvm::sys::path::filename(Dir))); +} + +std::error_code CaseInsensitiveFileSystem::findCaseInsensitivePath( + StringRef Path, SmallVectorImpl<char> &FoundPath) { + StringRef FileName = llvm::sys::path::filename(Path); + StringRef Dir = llvm::sys::path::parent_path(Path); + + if (Dir.empty()) + Dir = "."; + + auto DirHash = Maps.hash(Dir); + if (exclude(Dir, DirHash, FileName)) + return llvm::errc::no_such_file_or_directory; + + if (auto It = Maps.find(Dir, DirHash); It != Maps.end()) { + // If we have a map for this Dir and File wasn't excluded above, it must + // exist. + llvm::sys::path::append(FoundPath, Dir, It->second.at(FileName.lower())); + return {}; + } + + std::error_code EC; + directory_iterator I = FS->dir_begin(Dir, EC); + if (EC == errc::no_such_file_or_directory) { + // If the dir doesn't exist, try to find it and try again. + SmallString<512> NewDir; + if (llvm::sys::path::parent_path(Dir).empty() || + (EC = findCaseInsensitivePath(Dir, NewDir))) { + // Insert a dummy map value to mark the dir as non-existent. + Maps.try_emplace_with_hash(Dir, DirHash); + return EC; + } + llvm::sys::path::append(NewDir, FileName); + return findCaseInsensitivePath(StringRef(NewDir.data(), NewDir.size()), + FoundPath); + } + + // These special entries always exist, but won't show up in the listing below. + StringMap<std::string> DirMap = {{".", "."}, {"..", ".."}}; + + directory_iterator E; + while (I != E) { + StringRef DirEntry = llvm::sys::path::filename(I->path()); + // Keep the first match. + DirMap.try_emplace(DirEntry.lower(), DirEntry); + I.increment(EC); + if (EC) + return EC; + } + + // If there were no problems, insert the map. + auto [DirMapIt, Inserted] = + Maps.try_emplace_with_hash(Dir, DirHash, std::move(DirMap)); + assert(Inserted && "Maps[Dir] shouldn't exist"); + const auto &DirMapRef = DirMapIt->second; + + if (auto MI = DirMapRef.find(FileName.lower()); MI != DirMapRef.end()) { + llvm::sys::path::append(FoundPath, Dir, MI->second); + return {}; + } + + return llvm::errc::no_such_file_or_directory; +} + +llvm::ErrorOr<Status> CaseInsensitiveFileSystem::status(const Twine &Path) { + SmallString<512> NewPath; + if (auto EC = findCaseInsensitivePath(Path.str(), NewPath)) + return EC; + + return FS->status(NewPath); +} + +llvm::ErrorOr<std::unique_ptr<File>> +CaseInsensitiveFileSystem::openFileForRead(const Twine &Path) { + SmallString<512> NewPath; + if (auto EC = findCaseInsensitivePath(Path.str(), NewPath)) + return EC; + + return FS->openFileForRead(NewPath); +} + +directory_iterator CaseInsensitiveFileSystem::dir_begin(const Twine &Path, + std::error_code &EC) { + SmallString<512> NewPath; + if ((EC = findCaseInsensitivePath(Path.str(), NewPath))) + return {}; + + return FS->dir_begin(NewPath, EC); +} + namespace llvm { namespace vfs { @@ -3019,6 +3122,7 @@ void TracingFileSystem::printImpl(raw_ostream &OS, PrintType Type, const char FileSystem::ID = 0; const char OverlayFileSystem::ID = 0; const char ProxyFileSystem::ID = 0; +const char CaseInsensitiveFileSystem::ID = 0; const char InMemoryFileSystem::ID = 0; const char RedirectingFileSystem::ID = 0; const char TracingFileSystem::ID = 0; diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp index bb0172b28e373..8953923d0f5d2 100644 --- a/llvm/unittests/Support/VirtualFileSystemTest.cpp +++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp @@ -137,8 +137,15 @@ class DummyFileSystem : public vfs::FileSystem { vfs::directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override { - return vfs::directory_iterator( + auto I = vfs::directory_iterator( std::make_shared<DirIterImpl>(FilesAndDirs, Dir)); + + // Even if there is no entry for /foo, /foo/bar may exist, so only set the + // error code if /foo returns an empty iterator. + if (I == vfs::directory_iterator()) + EC = status(Dir).getError(); + + return I; } void addEntry(StringRef Path, const vfs::Status &Status) { @@ -3732,3 +3739,50 @@ TEST(TracingFileSystemTest, PrintOutput) { " InMemoryFileSystem\n", Output); } + +class CaseInsensitiveFileSystemTest : public ::testing::Test { +protected: + vfs::CaseInsensitiveFileSystem FS; + + CaseInsensitiveFileSystemTest() + : FS([] { + auto Base = makeIntrusiveRefCnt<DummyFileSystem>(); + Base->addRegularFile("/foo"); + Base->addDirectory("/bar"); + Base->addRegularFile("/bar/baz"); + return Base; + }()) {} +}; + +TEST_F(CaseInsensitiveFileSystemTest, Basic) { + // Not just accepting anything. + auto Status = FS.status("/F00"); + ASSERT_EQ(llvm::errc::no_such_file_or_directory, Status.getError()); + + // Case-insensitive file is found. + Status = FS.status("/FoO"); + ASSERT_FALSE(Status.getError()); + + // Case-insensitive dir works too. + Status = FS.status("/bAr/baZ"); + ASSERT_FALSE(Status.getError()); + + // Test openFileForRead. + auto File = FS.openFileForRead("/F00"); + ASSERT_EQ(llvm::errc::no_such_file_or_directory, File.getError()); + File = FS.openFileForRead("/Foo"); + ASSERT_FALSE(File.getError()); + File = FS.openFileForRead("/Bar/Baz"); + ASSERT_FALSE(File.getError()); + + // Test directory listing. + std::error_code EC; + auto Dir = FS.dir_begin("/b4r", EC); + ASSERT_EQ(llvm::errc::no_such_file_or_directory, EC); + Dir = FS.dir_begin("/bAr", EC); + ASSERT_FALSE(EC); + ASSERT_EQ("/bar/baz", Dir->path()); + Dir.increment(EC); + ASSERT_FALSE(EC); + ASSERT_EQ(vfs::directory_iterator(), Dir); +} >From 8f3d1a3ea4ae2e8b48747156825d560772a74256 Mon Sep 17 00:00:00 2001 From: grchz <[email protected]> Date: Thu, 29 Jan 2026 17:32:35 +1300 Subject: [PATCH 2/2] Expect -Wnonportable-include-path warning --- clang/test/Frontend/case-insensitive-paths.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/clang/test/Frontend/case-insensitive-paths.c b/clang/test/Frontend/case-insensitive-paths.c index 0b99ce671d9eb..fc75d9d24a104 100644 --- a/clang/test/Frontend/case-insensitive-paths.c +++ b/clang/test/Frontend/case-insensitive-paths.c @@ -1,8 +1,10 @@ -// RUN: %clang_cc1 -E -P -verify --show-includes -Wno-nonportable-include-path \ -// RUN: -fcase-insensitive-paths %s 2>&1 | FileCheck %s - -#include "inPuts/eMptY.H" // expected-no-diagnostics - +// RUN: %clang_cc1 -E -P --show-includes -verify=suppressed \ +// RUN: -fcase-insensitive-paths -Wno-nonportable-include-path %s 2>&1 \ +// RUN: | FileCheck %s // Make sure the exact spelling used in the #include directive is preserved // when printing header dependencies (consistent with MSVC /showIncludes). // CHECK: Note: including file: {{.*}}inPuts/eMptY.H +// suppressed-no-diagnostics@+1 +#include "inPuts/eMptY.H" +// expected-warning@-1 {{non-portable path to file '"Inputs/empty.h"'; specified path differs in case from file name on disk}} +// RUN: %clang_cc1 -E -P -verify -fcase-insensitive-paths %s _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
