Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Potentially Breaking Changes
call the member ``operator delete`` instead of the expected global
delete operator. The old behavior is retained under ``-fclang-abi-compat=21``
flag.
- Clang warning suppressions file, ``--warning-suppression-mappings=``, now will
use the last matching entry instead of the longest one.

C/C++ Language Potentially Breaking Changes
-------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions clang/docs/WarningSuppressionMappings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Format
Warning suppression mappings uses the same format as
:doc:`SanitizerSpecialCaseList`.

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

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

When a source file matches multiple globs in a section, the longest one takes
When a source file matches multiple globs in a section, the last one takes
precedence.

.. code-block:: bash
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Diagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,7 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
/// diagnostics in specific files.
/// Mapping file is expected to be a special case list with sections denoting
/// diagnostic groups and `src` entries for globs to suppress. `emit` category
/// can be used to disable suppression. Longest glob that matches a filepath
/// can be used to disable suppression. THe last glob that matches a filepath
/// takes precedence. For example:
/// [unused]
/// src:clang/*
Expand Down
53 changes: 15 additions & 38 deletions clang/lib/Basic/Diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,12 +517,6 @@ class WarningsSpecialCaseList : public llvm::SpecialCaseList {
const SourceManager &SM) const;

private:
// Find the longest glob pattern that matches FilePath amongst
// CategoriesToMatchers, return true iff the match exists and belongs to a
// positive category.
bool globsMatches(const llvm::StringMap<Matcher> &CategoriesToMatchers,
StringRef FilePath) const;

llvm::DenseMap<diag::kind, const Section *> DiagToSection;
};
} // namespace
Expand Down Expand Up @@ -584,43 +578,26 @@ void DiagnosticsEngine::setDiagSuppressionMapping(llvm::MemoryBuffer &Input) {
bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId,
SourceLocation DiagLoc,
const SourceManager &SM) const {
PresumedLoc PLoc = SM.getPresumedLoc(DiagLoc);
if (!PLoc.isValid())
return false;
const Section *DiagSection = DiagToSection.lookup(DiagId);
if (!DiagSection)
return false;
const SectionEntries &EntityTypeToCategories = DiagSection->Entries;
auto SrcEntriesIt = EntityTypeToCategories.find("src");
if (SrcEntriesIt == EntityTypeToCategories.end())

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

unsigned SuppressLineNo =
llvm::SpecialCaseList::inSectionBlame(DiagSection->Entries, "src", F, "");
if (!SuppressLineNo)
return false;
const llvm::StringMap<llvm::SpecialCaseList::Matcher> &CategoriesToMatchers =
SrcEntriesIt->getValue();
// We also use presumed locations here to improve reproducibility for
// preprocessed inputs.
if (PresumedLoc PLoc = SM.getPresumedLoc(DiagLoc); PLoc.isValid())
return globsMatches(
CategoriesToMatchers,
llvm::sys::path::remove_leading_dotslash(PLoc.getFilename()));
return false;
}

bool WarningsSpecialCaseList::globsMatches(
const llvm::StringMap<Matcher> &CategoriesToMatchers,
StringRef FilePath) const {
StringRef LongestMatch;
bool LongestIsPositive = false;
for (const auto &Entry : CategoriesToMatchers) {
StringRef Category = Entry.getKey();
const llvm::SpecialCaseList::Matcher &Matcher = Entry.getValue();
bool IsPositive = Category != "emit";
for (const auto &Glob : Matcher.Globs) {
if (Glob->Name.size() < LongestMatch.size())
continue;
if (!Glob->Pattern.match(FilePath))
continue;
LongestMatch = Glob->Name;
LongestIsPositive = IsPositive;
}
}
return LongestIsPositive;
unsigned EmitLineNo = llvm::SpecialCaseList::inSectionBlame(
DiagSection->Entries, "src", F, "emit");
if (!EmitLineNo)
return true;

return SuppressLineNo > EmitLineNo;
}

bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind DiagId,
Expand Down
8 changes: 3 additions & 5 deletions clang/unittests/Basic/DiagnosticTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ TEST_F(SuppressionMappingTest, EmitCategoryIsExcluded) {
locForFile("foo.cpp")));
}

TEST_F(SuppressionMappingTest, LongestMatchWins) {
TEST_F(SuppressionMappingTest, LastMatchWins) {
llvm::StringLiteral SuppressionMappingFile = R"(
[unused]
src:*clang/*
Expand Down Expand Up @@ -327,10 +327,8 @@ TEST_F(SuppressionMappingTest, LongShortMatch) {

EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
locForFile("test/t1.cpp")));

// FIXME: This is confusing.
EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
locForFile("lld/test/t2.cpp")));
EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
locForFile("lld/test/t2.cpp")));
}

TEST_F(SuppressionMappingTest, ShortLongMatch) {
Expand Down
Loading