https://github.com/DKLoehr updated https://github.com/llvm/llvm-project/pull/149886
>From 40745a6b7caf7fae4a84b2e819ba4e45d6df0112 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/2] 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 194f2fc5a7825..3aea40ce0715d 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 b0a034e9af1cd..3ab3cc918f5dc 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 bb1f88e8480f1..8a883b7329343 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -338,6 +338,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 999fed3f892b3582ee068e950b97a6f0e2c9a516 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/2] 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)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits