Skip to content

Commit ab08fbd

Browse files
committed
[clang] Switch warning suppression multi-match rule to "last match takes precedence"
The current "longest match takes precedence" rule for warning suppression mappings can be confusing, especially in long suppression files where tracking the length relationship between globs is difficult. For example, with the following rules, it's not immediately obvious why the first one should currently take precedence: ``` src:*test/* src:*lld/*=emit ``` This commit changes the multi-match behavior so the last match takes precedence. This rule is easier to understand and consistent with the approach used by sanitizers, simplifying the mechanism by providing a uniform experience across different tools. This is potentially breaking, but very unlikely. An investigation of known uses showed they do not rely on the length. Reviewers: thurstond, kadircet, fmayer Pull Request: #162237
1 parent 1429628 commit ab08fbd

File tree

5 files changed

+13
-17
lines changed

5 files changed

+13
-17
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ Potentially Breaking Changes
6969
call the member ``operator delete`` instead of the expected global
7070
delete operator. The old behavior is retained under ``-fclang-abi-compat=21``
7171
flag.
72+
- Clang warning suppressions file, ``--warning-suppression-mappings=``, now will
73+
use the last matching entry instead of the longest one.
7274
- Trailing null statements in GNU statement expressions are no longer
7375
ignored by Clang; they now result in a void type. Clang previously
7476
matched GCC's behavior, which was recently clarified to be incorrect.

clang/docs/WarningSuppressionMappings.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Format
6363
Warning suppression mappings uses the same format as
6464
:doc:`SanitizerSpecialCaseList`.
6565

66-
Sections describe which diagnostic group's behaviour to change, e.g.
66+
Sections describe which diagnostic group's behavior to change, e.g.
6767
``[unused]``. When a diagnostic is matched by multiple sections, the latest
6868
section takes precedence.
6969

@@ -76,7 +76,7 @@ Source files are matched against these globs either:
7676
- as paths relative to the current working directory
7777
- as absolute paths.
7878

79-
When a source file matches multiple globs in a section, the longest one takes
79+
When a source file matches multiple globs in a section, the last one takes
8080
precedence.
8181

8282
.. code-block:: bash

clang/include/clang/Basic/Diagnostic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
971971
/// diagnostics in specific files.
972972
/// Mapping file is expected to be a special case list with sections denoting
973973
/// diagnostic groups and `src` entries for globs to suppress. `emit` category
974-
/// can be used to disable suppression. Longest glob that matches a filepath
974+
/// can be used to disable suppression. The last glob that matches a filepath
975975
/// takes precedence. For example:
976976
/// [unused]
977977
/// src:clang/*

clang/lib/Basic/Diagnostic.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,7 @@ std::unique_ptr<WarningsSpecialCaseList>
525525
WarningsSpecialCaseList::create(const llvm::MemoryBuffer &Input,
526526
std::string &Err) {
527527
auto WarningSuppressionList = std::make_unique<WarningsSpecialCaseList>();
528-
if (!WarningSuppressionList->createInternal(&Input, Err,
529-
/*OrderBySize=*/true))
528+
if (!WarningSuppressionList->createInternal(&Input, Err))
530529
return nullptr;
531530
return WarningSuppressionList;
532531
}
@@ -588,15 +587,12 @@ bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId,
588587

589588
StringRef F = llvm::sys::path::remove_leading_dotslash(PLoc.getFilename());
590589

591-
StringRef LongestSup = DiagSection->getLongestMatch("src", F, "");
592-
if (LongestSup.empty())
590+
unsigned LastSup = DiagSection->getLastMatch("src", F, "");
591+
if (LastSup == 0)
593592
return false;
594593

595-
StringRef LongestEmit = DiagSection->getLongestMatch("src", F, "emit");
596-
if (LongestEmit.empty())
597-
return true;
598-
599-
return LongestSup.size() > LongestEmit.size();
594+
unsigned LastEmit = DiagSection->getLastMatch("src", F, "emit");
595+
return LastSup > LastEmit;
600596
}
601597

602598
bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind DiagId,

clang/unittests/Basic/DiagnosticTest.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ TEST_F(SuppressionMappingTest, EmitCategoryIsExcluded) {
294294
locForFile("foo.cpp")));
295295
}
296296

297-
TEST_F(SuppressionMappingTest, LongestMatchWins) {
297+
TEST_F(SuppressionMappingTest, LastMatchWins) {
298298
llvm::StringLiteral SuppressionMappingFile = R"(
299299
[unused]
300300
src:*clang/*
@@ -327,10 +327,8 @@ TEST_F(SuppressionMappingTest, LongShortMatch) {
327327

328328
EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
329329
locForFile("test/t1.cpp")));
330-
331-
// FIXME: This is confusing.
332-
EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
333-
locForFile("lld/test/t2.cpp")));
330+
EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
331+
locForFile("lld/test/t2.cpp")));
334332
}
335333

336334
TEST_F(SuppressionMappingTest, ShortLongMatch) {

0 commit comments

Comments
 (0)