https://github.com/compnerd updated 
https://github.com/llvm/llvm-project/pull/181306

>From bca3253f08d2bc4551451ba3cd00bbd59555f668 Mon Sep 17 00:00:00 2001
From: Saleem Abdulrasool <[email protected]>
Date: Thu, 12 Feb 2026 20:35:34 -0800
Subject: [PATCH] clang: normalise inputs for Windows more aggresively

Normalise the input sources and header search paths. This is important
as the work on the LLVM CAS progresses. The CAS stores the normalised
paths and without normalisation in this path, we often end up with
different path representations which causes mismatches.

Additionally, adjust the `FileManager` by extracting the key
normalization logic and apply it at a second site. This is important to
ensure that we use the same key everywhere.
---
 clang/lib/Basic/FileManager.cpp               | 43 +++++++++++--------
 clang/lib/Frontend/CompilerInvocation.cpp     | 16 +++++++
 clang/test/CodeGen/linker-diagnostic.ll       |  2 +-
 .../test/Frontend/include-duplicate-removal.c |  6 +--
 clang/test/Preprocessor/headermap-rel2.c      |  4 +-
 clang/test/Preprocessor/iwithprefix.c         |  4 +-
 6 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index 6d6ea5b84369b..3ad9c79c8969a 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -38,6 +38,27 @@ using namespace clang;
 
 #define DEBUG_TYPE "file-search"
 
+static void normalizeCacheKey(StringRef &Path,
+                              std::optional<std::string> &Storage) {
+  using namespace llvm::sys::path;
+
+  // Drop trailing separators for non-root paths so that cache keys and `stat`
+  // queries use a single spelling. Keep root paths (`/`, `[A-Z]:\`) unchanged.
+  if (Path.size() > 1 && root_path(Path) != Path && is_separator(Path.back()))
+    Path = Path.drop_back();
+
+  // A bare drive path like "[A-Z:" is drive-relative (current directory on the
+  // drive).  As `[A-Z]:` is not a path specification, we must canonicalise it
+  // to `[A-Z]:.`.
+  if (is_style_windows(Style::native)) {
+    if (Path.size() > 1 && Path.back() == ':' &&
+        Path.equals_insensitive(root_path(Path))) {
+      Storage = Path.str() + ".";
+      Path = *Storage;
+    }
+  }
+}
+
 
//===----------------------------------------------------------------------===//
 // Common logic.
 
//===----------------------------------------------------------------------===//
@@ -104,6 +125,9 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) 
{
   if (DirName.empty())
     DirName = ".";
 
+  std::optional<std::string> Storage;
+  normalizeCacheKey(DirName, Storage);
+
   auto &NamedDirEnt = *SeenDirEntries.insert(
         {DirName, std::errc::no_such_file_or_directory}).first;
 
@@ -136,23 +160,8 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef 
Path) {
 
 llvm::Expected<DirectoryEntryRef>
 FileManager::getDirectoryRef(StringRef DirName, bool CacheFailure) {
-  // stat doesn't like trailing separators except for root directory.
-  // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'.
-  // (though it can strip '\\')
-  if (DirName.size() > 1 &&
-      DirName != llvm::sys::path::root_path(DirName) &&
-      llvm::sys::path::is_separator(DirName.back()))
-    DirName = DirName.drop_back();
-  std::optional<std::string> DirNameStr;
-  if (is_style_windows(llvm::sys::path::Style::native)) {
-    // Fixing a problem with "clang C:test.c" on Windows.
-    // Stat("C:") does not recognize "C:" as a valid directory
-    if (DirName.size() > 1 && DirName.back() == ':' &&
-        DirName.equals_insensitive(llvm::sys::path::root_name(DirName))) {
-      DirNameStr = DirName.str() + '.';
-      DirName = *DirNameStr;
-    }
-  }
+  std::optional<std::string> Storage;
+  normalizeCacheKey(DirName, Storage);
 
   ++NumDirLookups;
 
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 6aa2afb6f5918..b460ebf288293 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3243,6 +3243,14 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, 
ArgList &Args,
   if (Inputs.empty())
     Inputs.push_back("-");
 
+  for (std::string &Input : Inputs) {
+    if (llvm::sys::path::has_root_name(Input)) {
+      llvm::SmallString<261> Normalized(Input);
+      llvm::sys::path::native(Normalized);
+      Input = Normalized.str();
+    }
+  }
+
   if (DashX.getHeaderUnitKind() != InputKind::HeaderUnit_None &&
       Inputs.size() > 1)
     Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1];
@@ -3507,6 +3515,14 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions 
&Opts, ArgList &Args,
   for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay))
     Opts.AddVFSOverlayFile(A->getValue());
 
+  for (auto &Entry : Opts.UserEntries) {
+    if (llvm::sys::path::has_root_name(Entry.Path)) {
+      llvm::SmallString<261> Normalized(Entry.Path);
+      llvm::sys::path::native(Normalized);
+      Entry.Path = Normalized.str();
+    }
+  }
+
   return Diags.getNumErrors() == NumErrorsBefore;
 }
 
diff --git a/clang/test/CodeGen/linker-diagnostic.ll 
b/clang/test/CodeGen/linker-diagnostic.ll
index c8406314f8d6f..afb3ecaaa73fa 100644
--- a/clang/test/CodeGen/linker-diagnostic.ll
+++ b/clang/test/CodeGen/linker-diagnostic.ll
@@ -7,7 +7,7 @@
 ; RUN: %clang -c -o %t/lto.bar.o --target=armv4-none-unknown-eabi -O2 \
 ; RUN:   -fthinlto-index=%t/bar.o.thinlto.bc %t/bar.o -Wno-override-module 
2>&1 | FileCheck %s
 
-; CHECK: linking module '{{.*}}/bar.o': Linking two modules of different 
target triples: '{{.*}}/foo.o' is 'thumbv6-unknown-linux-gnueabihf' whereas 
'{{.*}}/bar.o' is 'armv4-none-unknown-eabi'
+; CHECK: linking module '{{.*}}{{/|\\}}bar.o': Linking two modules of 
different target triples: '{{.*}}/foo.o' is 'thumbv6-unknown-linux-gnueabihf' 
whereas '{{.*}}{{/|\\}}bar.o' is 'armv4-none-unknown-eabi'
 
 target triple = "thumbv6-unknown-linux-gnueabihf"
 target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
diff --git a/clang/test/Frontend/include-duplicate-removal.c 
b/clang/test/Frontend/include-duplicate-removal.c
index fb02cd7e48c3a..578a1f20f9474 100644
--- a/clang/test/Frontend/include-duplicate-removal.c
+++ b/clang/test/Frontend/include-duplicate-removal.c
@@ -3,10 +3,10 @@
 #include <test.h>
 
 // CHECK: ignoring duplicate directory
-// CHECK-SAME: Inputs/SystemHeaderPrefix"{{$}}
+// CHECK-SAME: Inputs{{/|\\}}SystemHeaderPrefix"{{$}}
 
 // CHECK:      #include "..."
-// CHECK-NEXT: {{.*}}Inputs/SystemHeaderPrefix{{$}}
+// CHECK-NEXT: {{.*}}Inputs{{/|\\}}SystemHeaderPrefix{{$}}
 // CHECK-NEXT: #include <...>
 // CHECK-NEXT: {{.*}}Inputs{{$}}
-// CHECK-NEXT: {{.*}}Inputs/SystemHeaderPrefix{{$}}
+// CHECK-NEXT: {{.*}}Inputs{{/|\\}}SystemHeaderPrefix{{$}}
diff --git a/clang/test/Preprocessor/headermap-rel2.c 
b/clang/test/Preprocessor/headermap-rel2.c
index 611ddd8356a1d..1f8320f28e1dc 100644
--- a/clang/test/Preprocessor/headermap-rel2.c
+++ b/clang/test/Preprocessor/headermap-rel2.c
@@ -8,8 +8,8 @@
 // RUN: FileCheck %s -input-file %t.out
 
 // CHECK: Product/someheader.h
-// CHECK: system/usr/include{{[/\\]+}}someheader.h
-// CHECK: system/usr/include{{[/\\]+}}someheader.h
+// CHECK: system{{[/\\]+}}usr{{[/\\]+}}include{{[/\\]+}}someheader.h
+// CHECK: system{{[/\\]+}}usr{{[/\\]+}}include{{[/\\]+}}someheader.h
 
 #include "someheader.h"
 #include <someheader.h>
diff --git a/clang/test/Preprocessor/iwithprefix.c 
b/clang/test/Preprocessor/iwithprefix.c
index 70d2abcd374ca..5ab209dd8959f 100644
--- a/clang/test/Preprocessor/iwithprefix.c
+++ b/clang/test/Preprocessor/iwithprefix.c
@@ -8,7 +8,7 @@
 // RUN: FileCheck %s < %t.out
 
 // CHECK: #include <...> search starts here:
-// CHECK: {{.*}}.tmps/first
+// CHECK: {{.*}}.tmps{{/|\\}}first
 // CHECK: {{/|\\}}clang{{/|\\}}{{[.0-9]+}}{{/|\\}}include
-// CHECK: {{.*}}.tmps/second
+// CHECK: {{.*}}.tmps{{/|\\}}second
 // CHECK-NOT: {{.*}}.tmps

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to