https://github.com/DKLoehr updated 
https://github.com/llvm/llvm-project/pull/149886

>From 028be83a047f7dc3e5ff7d89f62ce4bd7452ff1b Mon Sep 17 00:00:00 2001
From: Devon Loehr <dlo...@google.com>
Date: Mon, 21 Jul 2025 19:07:23 +0000
Subject: [PATCH 1/4] Make special case matcher slash-agnostic

---
 clang/docs/SanitizerSpecialCaseList.rst  |  1 +
 clang/unittests/Basic/DiagnosticTest.cpp | 23 +++++++++++++++++++++++
 llvm/docs/ReleaseNotes.md                |  4 ++++
 llvm/include/llvm/Support/GlobPattern.h  |  1 +
 llvm/lib/Support/GlobPattern.cpp         |  4 ++++
 5 files changed, 33 insertions(+)

diff --git a/clang/docs/SanitizerSpecialCaseList.rst 
b/clang/docs/SanitizerSpecialCaseList.rst
index 307c001664fba..f2a04dc9adcf1 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -174,6 +174,7 @@ tool-specific docs.
     # Lines starting with # are ignored.
     # Turn off checks for the source file
     # Entries without sections are placed into [*] and apply to all sanitizers
+    # "/" matches both windows and unix path separators ("/" and "\")
     src:path/to/source/file.c
     src:*/source/file.c
     # Turn off checks for this main file, including files included by it.
diff --git a/clang/unittests/Basic/DiagnosticTest.cpp 
b/clang/unittests/Basic/DiagnosticTest.cpp
index 4b3af00c3b0ce..a6557b1e35c4b 100644
--- a/clang/unittests/Basic/DiagnosticTest.cpp
+++ b/clang/unittests/Basic/DiagnosticTest.cpp
@@ -360,4 +360,27 @@ TEST_F(SuppressionMappingTest, 
ParsingRespectsOtherWarningOpts) {
   clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
   EXPECT_THAT(diags(), IsEmpty());
 }
+
+TEST_F(SuppressionMappingTest, ForwardSlashMatchesBothDirections) {
+  llvm::StringLiteral SuppressionMappingFile = R"(
+  [unused]
+  src:*clang/*
+  src:*clang/lib/Sema/*=emit
+  src:*clang/lib\\Sema/foo*)";
+  Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+  FS->addFile("foo.txt", /*ModificationTime=*/{},
+              llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile));
+  clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+  EXPECT_THAT(diags(), IsEmpty());
+
+  EXPECT_TRUE(Diags.isSuppressedViaMapping(
+      diag::warn_unused_function, locForFile(R"(clang/lib/Basic/foo.h)")));
+  EXPECT_FALSE(Diags.isSuppressedViaMapping(
+      diag::warn_unused_function, locForFile(R"(clang/lib/Sema\bar.h)")));
+  EXPECT_TRUE(Diags.isSuppressedViaMapping(
+      diag::warn_unused_function, locForFile(R"(clang\lib\Sema/foo.h)")));
+  // The third pattern requires a literal backslash before Sema
+  EXPECT_FALSE(Diags.isSuppressedViaMapping(
+      diag::warn_unused_function, locForFile(R"(clang/lib/Sema/foo.h)")));
+}
 } // namespace
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 5640c72c1d7a0..d677ce865dc69 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -165,6 +165,10 @@ Changes to BOLT
 Changes to Sanitizers
 ---------------------
 
+* The [sanitizer special case list 
format](https://clang.llvm.org/docs/SanitizerSpecialCaseList.html#format)
+  now treats forward slashes as either a forward or a backslash, to handle
+  paths with mixed unix and window styles.
+
 Other Changes
 -------------
 
diff --git a/llvm/include/llvm/Support/GlobPattern.h 
b/llvm/include/llvm/Support/GlobPattern.h
index 62ed4a0f23fd9..af92c63331282 100644
--- a/llvm/include/llvm/Support/GlobPattern.h
+++ b/llvm/include/llvm/Support/GlobPattern.h
@@ -35,6 +35,7 @@ namespace llvm {
 ///   expansions are not supported. If \p MaxSubPatterns is empty then
 ///   brace expansions are not supported and characters `{,}` are treated as
 ///   literals.
+/// * `/` matches both unix and windows path separators: `/` and `\`.
 /// * `\` escapes the next character so it is treated as a literal.
 ///
 /// Some known edge cases are:
diff --git a/llvm/lib/Support/GlobPattern.cpp b/llvm/lib/Support/GlobPattern.cpp
index 7004adf461a0c..26b3724863ee8 100644
--- a/llvm/lib/Support/GlobPattern.cpp
+++ b/llvm/lib/Support/GlobPattern.cpp
@@ -231,6 +231,10 @@ bool GlobPattern::SubGlobPattern::match(StringRef Str) 
const {
         ++S;
         continue;
       }
+    } else if (*P == '/' && (*S == '/' || *S == '\\')) {
+      ++P;
+      ++S;
+      continue;
     } else if (*P == *S || *P == '?') {
       ++P;
       ++S;

>From e9820cb21b139e372dacfda0e83eab5cff214338 Mon Sep 17 00:00:00 2001
From: Devon Loehr <dlo...@google.com>
Date: Tue, 22 Jul 2025 14:57:34 +0000
Subject: [PATCH 2/4] Enable only for special case list

---
 llvm/include/llvm/Support/GlobPattern.h |  9 +++++++--
 llvm/lib/Support/GlobPattern.cpp        | 12 +++++++-----
 llvm/lib/Support/SpecialCaseList.cpp    |  3 ++-
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Support/GlobPattern.h 
b/llvm/include/llvm/Support/GlobPattern.h
index af92c63331282..2729ba9a56649 100644
--- a/llvm/include/llvm/Support/GlobPattern.h
+++ b/llvm/include/llvm/Support/GlobPattern.h
@@ -56,8 +56,10 @@ class GlobPattern {
   /// \param MaxSubPatterns if provided limit the number of allowed subpatterns
   ///                       created from expanding braces otherwise disable
   ///                       brace expansion
+  /// \param IsSlashAgnostic whether to treat '/' as matching '\\' as well
   LLVM_ABI static Expected<GlobPattern>
-  create(StringRef Pat, std::optional<size_t> MaxSubPatterns = {});
+  create(StringRef Pat, std::optional<size_t> MaxSubPatterns = {},
+         bool IsSlashAgnostic = false);
   /// \returns \p true if \p S matches this glob pattern
   LLVM_ABI bool match(StringRef S) const;
 
@@ -76,7 +78,9 @@ class GlobPattern {
 
   struct SubGlobPattern {
     /// \param Pat the pattern to match against
-    LLVM_ABI static Expected<SubGlobPattern> create(StringRef Pat);
+    /// \param SlashAgnostic whether to treat '/' as matching '\\' as well
+    LLVM_ABI static Expected<SubGlobPattern> create(StringRef Pat,
+                                                    bool SlashAgnostic);
     /// \returns \p true if \p S matches this glob pattern
     LLVM_ABI bool match(StringRef S) const;
     StringRef getPat() const { return StringRef(Pat.data(), Pat.size()); }
@@ -88,6 +92,7 @@ class GlobPattern {
     };
     SmallVector<Bracket, 0> Brackets;
     SmallVector<char, 0> Pat;
+    bool IsSlashAgnostic;
   };
   SmallVector<SubGlobPattern, 1> SubGlobs;
 };
diff --git a/llvm/lib/Support/GlobPattern.cpp b/llvm/lib/Support/GlobPattern.cpp
index 26b3724863ee8..4aa30a81c3fbf 100644
--- a/llvm/lib/Support/GlobPattern.cpp
+++ b/llvm/lib/Support/GlobPattern.cpp
@@ -132,8 +132,9 @@ parseBraceExpansions(StringRef S, std::optional<size_t> 
MaxSubPatterns) {
   return std::move(SubPatterns);
 }
 
-Expected<GlobPattern>
-GlobPattern::create(StringRef S, std::optional<size_t> MaxSubPatterns) {
+Expected<GlobPattern> GlobPattern::create(StringRef S,
+                                          std::optional<size_t> MaxSubPatterns,
+                                          bool IsSlashAgnostic) {
   GlobPattern Pat;
 
   // Store the prefix that does not contain any metacharacter.
@@ -147,7 +148,7 @@ GlobPattern::create(StringRef S, std::optional<size_t> 
MaxSubPatterns) {
   if (auto Err = parseBraceExpansions(S, MaxSubPatterns).moveInto(SubPats))
     return std::move(Err);
   for (StringRef SubPat : SubPats) {
-    auto SubGlobOrErr = SubGlobPattern::create(SubPat);
+    auto SubGlobOrErr = SubGlobPattern::create(SubPat, IsSlashAgnostic);
     if (!SubGlobOrErr)
       return SubGlobOrErr.takeError();
     Pat.SubGlobs.push_back(*SubGlobOrErr);
@@ -157,8 +158,9 @@ GlobPattern::create(StringRef S, std::optional<size_t> 
MaxSubPatterns) {
 }
 
 Expected<GlobPattern::SubGlobPattern>
-GlobPattern::SubGlobPattern::create(StringRef S) {
+GlobPattern::SubGlobPattern::create(StringRef S, bool SlashAgnostic) {
   SubGlobPattern Pat;
+  Pat.IsSlashAgnostic = SlashAgnostic;
 
   // Parse brackets.
   Pat.Pat.assign(S.begin(), S.end());
@@ -231,7 +233,7 @@ bool GlobPattern::SubGlobPattern::match(StringRef Str) 
const {
         ++S;
         continue;
       }
-    } else if (*P == '/' && (*S == '/' || *S == '\\')) {
+    } else if (IsSlashAgnostic && *P == '/' && (*S == '/' || *S == '\\')) {
       ++P;
       ++S;
       continue;
diff --git a/llvm/lib/Support/SpecialCaseList.cpp 
b/llvm/lib/Support/SpecialCaseList.cpp
index 8d4e043bc1c9f..c597f03188507 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -59,7 +59,8 @@ Error SpecialCaseList::Matcher::insert(StringRef Pattern, 
unsigned LineNumber,
   Glob->LineNo = LineNumber;
   // We must be sure to use the string in `Glob` rather than the provided
   // reference which could be destroyed before match() is called
-  if (auto Err = GlobPattern::create(Glob->Name, /*MaxSubPatterns=*/1024)
+  if (auto Err = GlobPattern::create(Glob->Name, /*MaxSubPatterns=*/1024,
+                                     /*IsSlashAgnostic=*/true)
                      .moveInto(Glob->Pattern))
     return Err;
   Globs.push_back(std::move(Glob));

>From d3d4c664e3bc958dc6f5e5597d130f478f5b7f29 Mon Sep 17 00:00:00 2001
From: Devon Loehr <dlo...@google.com>
Date: Fri, 5 Sep 2025 16:48:17 +0000
Subject: [PATCH 3/4] Enable only on windows

---
 clang/docs/SanitizerSpecialCaseList.rst  | 2 +-
 clang/unittests/Basic/DiagnosticTest.cpp | 3 +++
 llvm/docs/ReleaseNotes.md                | 4 ++--
 llvm/include/llvm/Support/GlobPattern.h  | 3 ++-
 llvm/lib/Support/SpecialCaseList.cpp     | 6 +++++-
 5 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/clang/docs/SanitizerSpecialCaseList.rst 
b/clang/docs/SanitizerSpecialCaseList.rst
index f2a04dc9adcf1..e14b654536b8a 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -174,7 +174,7 @@ tool-specific docs.
     # Lines starting with # are ignored.
     # Turn off checks for the source file
     # Entries without sections are placed into [*] and apply to all sanitizers
-    # "/" matches both windows and unix path separators ("/" and "\")
+    # On windows, "/" matches both styles of path separator ("/" and "\")
     src:path/to/source/file.c
     src:*/source/file.c
     # Turn off checks for this main file, including files included by it.
diff --git a/clang/unittests/Basic/DiagnosticTest.cpp 
b/clang/unittests/Basic/DiagnosticTest.cpp
index a6557b1e35c4b..7e9653bdd3c7e 100644
--- a/clang/unittests/Basic/DiagnosticTest.cpp
+++ b/clang/unittests/Basic/DiagnosticTest.cpp
@@ -361,6 +361,8 @@ TEST_F(SuppressionMappingTest, 
ParsingRespectsOtherWarningOpts) {
   EXPECT_THAT(diags(), IsEmpty());
 }
 
+#ifdef _WIN32
+// We're only slash-agnostic on windows hosts
 TEST_F(SuppressionMappingTest, ForwardSlashMatchesBothDirections) {
   llvm::StringLiteral SuppressionMappingFile = R"(
   [unused]
@@ -383,4 +385,5 @@ TEST_F(SuppressionMappingTest, 
ForwardSlashMatchesBothDirections) {
   EXPECT_FALSE(Diags.isSuppressedViaMapping(
       diag::warn_unused_function, locForFile(R"(clang/lib/Sema/foo.h)")));
 }
+#endif
 } // namespace
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index d677ce865dc69..1f7b96582e701 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -165,9 +165,9 @@ Changes to BOLT
 Changes to Sanitizers
 ---------------------
 
-* The [sanitizer special case list 
format](https://clang.llvm.org/docs/SanitizerSpecialCaseList.html#format)
+* On windows hosts, the [sanitizer special case list 
format](https://clang.llvm.org/docs/SanitizerSpecialCaseList.html#format)
   now treats forward slashes as either a forward or a backslash, to handle
-  paths with mixed unix and window styles.
+  paths with mixed unix and windows styles.
 
 Other Changes
 -------------
diff --git a/llvm/include/llvm/Support/GlobPattern.h 
b/llvm/include/llvm/Support/GlobPattern.h
index 2729ba9a56649..4abd6b1874593 100644
--- a/llvm/include/llvm/Support/GlobPattern.h
+++ b/llvm/include/llvm/Support/GlobPattern.h
@@ -35,7 +35,8 @@ namespace llvm {
 ///   expansions are not supported. If \p MaxSubPatterns is empty then
 ///   brace expansions are not supported and characters `{,}` are treated as
 ///   literals.
-/// * `/` matches both unix and windows path separators: `/` and `\`.
+/// * If IsSlashAgnostic is passed, `/` matches both unix and windows path
+///   separators: `/` and `\`.
 /// * `\` escapes the next character so it is treated as a literal.
 ///
 /// Some known edge cases are:
diff --git a/llvm/lib/Support/SpecialCaseList.cpp 
b/llvm/lib/Support/SpecialCaseList.cpp
index c597f03188507..89ec193e1991c 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -18,6 +18,8 @@
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
 #include <stdio.h>
 #include <string>
 #include <system_error>
@@ -57,10 +59,12 @@ Error SpecialCaseList::Matcher::insert(StringRef Pattern, 
unsigned LineNumber,
   auto Glob = std::make_unique<Matcher::Glob>();
   Glob->Name = Pattern.str();
   Glob->LineNo = LineNumber;
+  // Backslashes are valid in posix-style filenames.
+  bool IsSlashAgnostic = Triple(sys::getDefaultTargetTriple()).isOSWindows();
   // We must be sure to use the string in `Glob` rather than the provided
   // reference which could be destroyed before match() is called
   if (auto Err = GlobPattern::create(Glob->Name, /*MaxSubPatterns=*/1024,
-                                     /*IsSlashAgnostic=*/true)
+                                     /*IsSlashAgnostic=*/IsSlashAgnostic)
                      .moveInto(Glob->Pattern))
     return Err;
   Globs.push_back(std::move(Glob));

>From e3f8b08fab7c3a0a05c92080201061ae8cab288d Mon Sep 17 00:00:00 2001
From: Devon Loehr <dlo...@google.com>
Date: Mon, 8 Sep 2025 15:00:04 +0000
Subject: [PATCH 4/4] Incorporate review feedback

---
 clang/docs/SanitizerSpecialCaseList.rst      |  2 +-
 clang/lib/Basic/Diagnostic.cpp               |  5 ++++-
 clang/lib/Basic/SanitizerSpecialCaseList.cpp |  2 +-
 clang/unittests/Basic/DiagnosticTest.cpp     | 12 ++++++-----
 llvm/docs/ReleaseNotes.md                    |  4 ++--
 llvm/include/llvm/Support/GlobPattern.h      | 19 +++++++----------
 llvm/include/llvm/Support/SpecialCaseList.h  |  5 +++--
 llvm/lib/Support/GlobPattern.cpp             | 21 +++++++++----------
 llvm/lib/Support/SpecialCaseList.cpp         | 22 +++++++++++---------
 9 files changed, 48 insertions(+), 44 deletions(-)

diff --git a/clang/docs/SanitizerSpecialCaseList.rst 
b/clang/docs/SanitizerSpecialCaseList.rst
index e14b654536b8a..752602c1b3093 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -174,7 +174,7 @@ tool-specific docs.
     # Lines starting with # are ignored.
     # Turn off checks for the source file
     # Entries without sections are placed into [*] and apply to all sanitizers
-    # On windows, "/" matches both styles of path separator ("/" and "\")
+    # On windows, "/" also matches "\" in filenames
     src:path/to/source/file.c
     src:*/source/file.c
     # Turn off checks for this main file, including files included by it.
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index dc3778bbf339c..9dd133cb4c03e 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -622,6 +622,8 @@ bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind 
DiagId,
 bool WarningsSpecialCaseList::globsMatches(
     const llvm::StringMap<Matcher> &CategoriesToMatchers,
     StringRef FilePath) const {
+  static bool HaveWindowsPathStyle =
+      llvm::sys::path::is_style_windows(llvm::sys::path::Style::native);
   StringRef LongestMatch;
   bool LongestIsPositive = false;
   for (const auto &Entry : CategoriesToMatchers) {
@@ -631,7 +633,8 @@ bool WarningsSpecialCaseList::globsMatches(
     for (const auto &Glob : Matcher.Globs) {
       if (Glob->Name.size() < LongestMatch.size())
         continue;
-      if (!Glob->Pattern.match(FilePath))
+      if (!Glob->Pattern.match(FilePath,
+                               /*IsSlashAgnostic=*/HaveWindowsPathStyle))
         continue;
       LongestMatch = Glob->Name;
       LongestIsPositive = IsPositive;
diff --git a/clang/lib/Basic/SanitizerSpecialCaseList.cpp 
b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
index f7bc1d5545d75..4ad35d4d73fdd 100644
--- a/clang/lib/Basic/SanitizerSpecialCaseList.cpp
+++ b/clang/lib/Basic/SanitizerSpecialCaseList.cpp
@@ -42,7 +42,7 @@ void SanitizerSpecialCaseList::createSanitizerSections() {
     SanitizerMask Mask;
 
 #define SANITIZER(NAME, ID)                                                    
\
-  if (S.SectionMatcher->match(NAME))                                           
\
+  if (S.SectionMatcher->match(NAME, /*IsFilename=*/false))                     
\
     Mask |= SanitizerKind::ID;
 #define SANITIZER_GROUP(NAME, ID, ALIAS) SANITIZER(NAME, ID)
 
diff --git a/clang/unittests/Basic/DiagnosticTest.cpp 
b/clang/unittests/Basic/DiagnosticTest.cpp
index 7e9653bdd3c7e..2af86b6a5ef38 100644
--- a/clang/unittests/Basic/DiagnosticTest.cpp
+++ b/clang/unittests/Basic/DiagnosticTest.cpp
@@ -363,12 +363,13 @@ TEST_F(SuppressionMappingTest, 
ParsingRespectsOtherWarningOpts) {
 
 #ifdef _WIN32
 // We're only slash-agnostic on windows hosts
-TEST_F(SuppressionMappingTest, ForwardSlashMatchesBothDirections) {
+TEST_F(SuppressionMappingTest, TreatsFilesAsSlashAgnosticOnWindows) {
   llvm::StringLiteral SuppressionMappingFile = R"(
   [unused]
   src:*clang/*
   src:*clang/lib/Sema/*=emit
-  src:*clang/lib\\Sema/foo*)";
+  src:*clang/lib\\Sema/foo*
+  fun:suppress/me)";
   Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
   FS->addFile("foo.txt", /*ModificationTime=*/{},
               llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile));
@@ -376,12 +377,13 @@ TEST_F(SuppressionMappingTest, 
ForwardSlashMatchesBothDirections) {
   EXPECT_THAT(diags(), IsEmpty());
 
   EXPECT_TRUE(Diags.isSuppressedViaMapping(
-      diag::warn_unused_function, locForFile(R"(clang/lib/Basic/foo.h)")));
+      diag::warn_unused_function, locForFile(R"(clang/lib/Basic/bar.h)")));
   EXPECT_FALSE(Diags.isSuppressedViaMapping(
-      diag::warn_unused_function, locForFile(R"(clang/lib/Sema\bar.h)")));
+      diag::warn_unused_function, locForFile(R"(clang/lib/Sema\baz.h)")));
+
+  // We require a literal backslash before "Sema"
   EXPECT_TRUE(Diags.isSuppressedViaMapping(
       diag::warn_unused_function, locForFile(R"(clang\lib\Sema/foo.h)")));
-  // The third pattern requires a literal backslash before Sema
   EXPECT_FALSE(Diags.isSuppressedViaMapping(
       diag::warn_unused_function, locForFile(R"(clang/lib/Sema/foo.h)")));
 }
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 1f7b96582e701..b530a66b7abc6 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -166,8 +166,8 @@ Changes to Sanitizers
 ---------------------
 
 * On windows hosts, the [sanitizer special case list 
format](https://clang.llvm.org/docs/SanitizerSpecialCaseList.html#format)
-  now treats forward slashes as either a forward or a backslash, to handle
-  paths with mixed unix and windows styles.
+  now treats forward slashes in filenames as matching either a forward or a
+  backslash, to accommodate paths with mixed unix and windows styles.
 
 Other Changes
 -------------
diff --git a/llvm/include/llvm/Support/GlobPattern.h 
b/llvm/include/llvm/Support/GlobPattern.h
index 4abd6b1874593..5fd1e0764cc7a 100644
--- a/llvm/include/llvm/Support/GlobPattern.h
+++ b/llvm/include/llvm/Support/GlobPattern.h
@@ -35,9 +35,9 @@ namespace llvm {
 ///   expansions are not supported. If \p MaxSubPatterns is empty then
 ///   brace expansions are not supported and characters `{,}` are treated as
 ///   literals.
-/// * If IsSlashAgnostic is passed, `/` matches both unix and windows path
-///   separators: `/` and `\`.
 /// * `\` escapes the next character so it is treated as a literal.
+/// * If \p IsSlashAgnostic is passed to the match function, then forward
+///   slashes `/` also match backslashes `\`.
 ///
 /// Some known edge cases are:
 /// * The literal `]` is allowed as the first character in a character class,
@@ -57,12 +57,11 @@ class GlobPattern {
   /// \param MaxSubPatterns if provided limit the number of allowed subpatterns
   ///                       created from expanding braces otherwise disable
   ///                       brace expansion
-  /// \param IsSlashAgnostic whether to treat '/' as matching '\\' as well
   LLVM_ABI static Expected<GlobPattern>
-  create(StringRef Pat, std::optional<size_t> MaxSubPatterns = {},
-         bool IsSlashAgnostic = false);
+  create(StringRef Pat, std::optional<size_t> MaxSubPatterns = {});
+  /// \param IsSlashAgnostic whether to treat '/' as also matching '\'
   /// \returns \p true if \p S matches this glob pattern
-  LLVM_ABI bool match(StringRef S) const;
+  LLVM_ABI bool match(StringRef S, bool IsSlashAgnostic = false) const;
 
   // Returns true for glob pattern "*". Can be used to avoid expensive
   // preparation/acquisition of the input for match().
@@ -79,11 +78,10 @@ class GlobPattern {
 
   struct SubGlobPattern {
     /// \param Pat the pattern to match against
-    /// \param SlashAgnostic whether to treat '/' as matching '\\' as well
-    LLVM_ABI static Expected<SubGlobPattern> create(StringRef Pat,
-                                                    bool SlashAgnostic);
+    LLVM_ABI static Expected<SubGlobPattern> create(StringRef Pat);
+    /// \param IsSlashAgnostic whether to treat '/' as also matching '\'
     /// \returns \p true if \p S matches this glob pattern
-    LLVM_ABI bool match(StringRef S) const;
+    LLVM_ABI bool match(StringRef S, bool IsSlashAgnostic) const;
     StringRef getPat() const { return StringRef(Pat.data(), Pat.size()); }
 
     // Brackets with their end position and matched bytes.
@@ -93,7 +91,6 @@ class GlobPattern {
     };
     SmallVector<Bracket, 0> Brackets;
     SmallVector<char, 0> Pat;
-    bool IsSlashAgnostic;
   };
   SmallVector<SubGlobPattern, 1> SubGlobs;
 };
diff --git a/llvm/include/llvm/Support/SpecialCaseList.h 
b/llvm/include/llvm/Support/SpecialCaseList.h
index 22a62eac9e01a..951f27eed8ee8 100644
--- a/llvm/include/llvm/Support/SpecialCaseList.h
+++ b/llvm/include/llvm/Support/SpecialCaseList.h
@@ -124,8 +124,9 @@ class SpecialCaseList {
     LLVM_ABI Error insert(StringRef Pattern, unsigned LineNumber,
                           bool UseRegex);
     // Returns the line number in the source file that this query matches to.
-    // Returns zero if no match is found.
-    LLVM_ABI unsigned match(StringRef Query) const;
+    // On windows, treat '/' as also matching '\' in filenames when using 
globs.
+    // Returns zero if no match is found
+    LLVM_ABI unsigned match(StringRef Query, bool IsFilename) const;
 
     struct Glob {
       std::string Name;
diff --git a/llvm/lib/Support/GlobPattern.cpp b/llvm/lib/Support/GlobPattern.cpp
index 4aa30a81c3fbf..578c0dd0760d2 100644
--- a/llvm/lib/Support/GlobPattern.cpp
+++ b/llvm/lib/Support/GlobPattern.cpp
@@ -132,9 +132,8 @@ parseBraceExpansions(StringRef S, std::optional<size_t> 
MaxSubPatterns) {
   return std::move(SubPatterns);
 }
 
-Expected<GlobPattern> GlobPattern::create(StringRef S,
-                                          std::optional<size_t> MaxSubPatterns,
-                                          bool IsSlashAgnostic) {
+Expected<GlobPattern>
+GlobPattern::create(StringRef S, std::optional<size_t> MaxSubPatterns) {
   GlobPattern Pat;
 
   // Store the prefix that does not contain any metacharacter.
@@ -148,7 +147,7 @@ Expected<GlobPattern> GlobPattern::create(StringRef S,
   if (auto Err = parseBraceExpansions(S, MaxSubPatterns).moveInto(SubPats))
     return std::move(Err);
   for (StringRef SubPat : SubPats) {
-    auto SubGlobOrErr = SubGlobPattern::create(SubPat, IsSlashAgnostic);
+    auto SubGlobOrErr = SubGlobPattern::create(SubPat);
     if (!SubGlobOrErr)
       return SubGlobOrErr.takeError();
     Pat.SubGlobs.push_back(*SubGlobOrErr);
@@ -158,9 +157,8 @@ Expected<GlobPattern> GlobPattern::create(StringRef S,
 }
 
 Expected<GlobPattern::SubGlobPattern>
-GlobPattern::SubGlobPattern::create(StringRef S, bool SlashAgnostic) {
+GlobPattern::SubGlobPattern::create(StringRef S) {
   SubGlobPattern Pat;
-  Pat.IsSlashAgnostic = SlashAgnostic;
 
   // Parse brackets.
   Pat.Pat.assign(S.begin(), S.end());
@@ -192,21 +190,22 @@ GlobPattern::SubGlobPattern::create(StringRef S, bool 
SlashAgnostic) {
   return Pat;
 }
 
-bool GlobPattern::match(StringRef S) const {
+bool GlobPattern::match(StringRef S, bool IsSlashAgnostic) const {
   if (!S.consume_front(Prefix))
     return false;
   if (SubGlobs.empty() && S.empty())
     return true;
   for (auto &Glob : SubGlobs)
-    if (Glob.match(S))
+    if (Glob.match(S, IsSlashAgnostic))
       return true;
   return false;
 }
 
 // Factor the pattern into segments split by '*'. The segment is matched
-// sequentianlly by finding the first occurrence past the end of the previous
+// sequentially by finding the first occurrence past the end of the previous
 // match.
-bool GlobPattern::SubGlobPattern::match(StringRef Str) const {
+bool GlobPattern::SubGlobPattern::match(StringRef Str,
+                                        bool IsSlashAgnostic) const {
   const char *P = Pat.data(), *SegmentBegin = nullptr, *S = Str.data(),
              *SavedS = S;
   const char *const PEnd = P + Pat.size(), *const End = S + Str.size();
@@ -233,7 +232,7 @@ bool GlobPattern::SubGlobPattern::match(StringRef Str) 
const {
         ++S;
         continue;
       }
-    } else if (IsSlashAgnostic && *P == '/' && (*S == '/' || *S == '\\')) {
+    } else if (IsSlashAgnostic && *P == '/' && *S == '\\') {
       ++P;
       ++S;
       continue;
diff --git a/llvm/lib/Support/SpecialCaseList.cpp 
b/llvm/lib/Support/SpecialCaseList.cpp
index 89ec193e1991c..6e569768e2856 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -17,9 +17,8 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/VirtualFileSystem.h"
-#include "llvm/TargetParser/Host.h"
-#include "llvm/TargetParser/Triple.h"
 #include <stdio.h>
 #include <string>
 #include <system_error>
@@ -59,21 +58,22 @@ Error SpecialCaseList::Matcher::insert(StringRef Pattern, 
unsigned LineNumber,
   auto Glob = std::make_unique<Matcher::Glob>();
   Glob->Name = Pattern.str();
   Glob->LineNo = LineNumber;
-  // Backslashes are valid in posix-style filenames.
-  bool IsSlashAgnostic = Triple(sys::getDefaultTargetTriple()).isOSWindows();
   // We must be sure to use the string in `Glob` rather than the provided
   // reference which could be destroyed before match() is called
-  if (auto Err = GlobPattern::create(Glob->Name, /*MaxSubPatterns=*/1024,
-                                     /*IsSlashAgnostic=*/IsSlashAgnostic)
+  if (auto Err = GlobPattern::create(Glob->Name, /*MaxSubPatterns=*/1024)
                      .moveInto(Glob->Pattern))
     return Err;
   Globs.push_back(std::move(Glob));
   return Error::success();
 }
 
-unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
+unsigned SpecialCaseList::Matcher::match(StringRef Query,
+                                         bool IsFilename) const {
+  static bool HaveWindowsPathStyle =
+      llvm::sys::path::is_style_windows(llvm::sys::path::Style::native);
   for (const auto &Glob : reverse(Globs))
-    if (Glob->Pattern.match(Query))
+    if (Glob->Pattern.match(Query, /*IsSlashAgnostic=*/(HaveWindowsPathStyle &&
+                                                        IsFilename)))
       return Glob->LineNo;
   for (const auto &[Regex, LineNumber] : reverse(RegExes))
     if (Regex->match(Query))
@@ -223,7 +223,8 @@ std::pair<unsigned, unsigned>
 SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
                                 StringRef Query, StringRef Category) const {
   for (const auto &S : reverse(Sections)) {
-    if (S.SectionMatcher->match(Section)) {
+    bool IsFilename = Prefix == "src" || Prefix == "mainfile";
+    if (S.SectionMatcher->match(Section, IsFilename)) {
       unsigned Blame = inSectionBlame(S.Entries, Prefix, Query, Category);
       if (Blame)
         return {S.FileIdx, Blame};
@@ -242,7 +243,8 @@ unsigned SpecialCaseList::inSectionBlame(const 
SectionEntries &Entries,
   if (II == I->second.end())
     return 0;
 
-  return II->getValue().match(Query);
+  bool IsFilename = Prefix == "src" || Prefix == "mainfile";
+  return II->getValue().match(Query, IsFilename);
 }
 
 } // namespace llvm

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to