[clang] [clang-tools-extra] [llvm] [clang] Introduce diagnostics suppression mappings (PR #112517)
kadir çetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 4 07:35:12 PST 2024
================
@@ -477,6 +486,109 @@ void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
setSeverity(Diag, Map, Loc);
}
+namespace {
+class WarningsSpecialCaseList : public llvm::SpecialCaseList {
+public:
+ static std::unique_ptr<WarningsSpecialCaseList>
+ create(const llvm::MemoryBuffer &MB, std::string &Err) {
+ auto SCL = std::make_unique<WarningsSpecialCaseList>();
+ if (!SCL->createInternal(&MB, Err))
+ return nullptr;
+ return SCL;
+ }
+
+ // Section names refer to diagnostic groups, which cover multiple individual
+ // diagnostics. Expand diagnostic groups here to individual diagnostics.
+ // A diagnostic can have multiple diagnostic groups associated with it, we let
+ // the last section take precedence in such cases.
+ void processSections(DiagnosticsEngine &Diags) {
+ // Drop the default section introduced by special case list, we only support
+ // exact diagnostic group names.
+ Sections.erase("*");
+ // Make sure we iterate sections by their line numbers.
+ std::vector<std::pair<unsigned, const llvm::StringMapEntry<Section> *>>
+ LineAndSectionEntry;
+ LineAndSectionEntry.reserve(Sections.size());
+ for (const auto &Entry : Sections) {
+ LineAndSectionEntry.emplace_back(
+ Entry.second.SectionMatcher->Globs.at(Entry.first()).second, &Entry);
+ }
+ llvm::sort(LineAndSectionEntry);
+ static constexpr auto kFlavor = clang::diag::Flavor::WarningOrError;
+ for (const auto &[_, SectionEntry] : LineAndSectionEntry) {
+ SmallVector<diag::kind, 256> GroupDiags;
+ llvm::StringRef DiagGroup = SectionEntry->getKey();
+ if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup(kFlavor, DiagGroup,
+ GroupDiags)) {
+ StringRef Suggestion =
+ DiagnosticIDs::getNearestOption(kFlavor, DiagGroup);
+ Diags.Report(diag::warn_unknown_diag_option)
+ << static_cast<unsigned>(kFlavor) << DiagGroup
+ << !Suggestion.empty() << Suggestion;
+ continue;
+ }
+ for (diag::kind D : GroupDiags)
+ DiagToSection[D] = &SectionEntry->getValue();
+ }
+ }
+
+ bool isDiagSuppressed(diag::kind DiagId, llvm::StringRef FilePath) const {
+ auto Section = DiagToSection.find(DiagId);
+ if (Section == DiagToSection.end())
+ return false;
+ auto &DiagEntries = Section->second->Entries;
+ auto SrcEntries = DiagEntries.find("src");
+ if (SrcEntries == DiagEntries.end())
+ return false;
+ return globsMatches(SrcEntries->second, FilePath);
+ }
+
+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(llvm::StringMap<Matcher> CategoriesToMatchers,
+ llvm::StringRef FilePath) const {
+ llvm::StringRef LongestMatch;
+ bool LongestIsPositive = false;
+ for (const auto &[Category, Matcher] : CategoriesToMatchers) {
+ bool IsPositive = Category != "emit";
+ for (const auto &[Pattern, Glob] : Matcher.Globs) {
----------------
kadircet wrote:
> RE: "rest of the speical-case-list actually match entries in line order",
sorry I think I was confused while writing this one. I was trying to say, rest of the SpecialCaseList users can observe which line matched first. Hence performing a re-ordering of patterns would result in behavioral changes for these users (I can't say if it'll be a regression or not, as I don't fully understand their use cases).
> do you mean that the behavior here is significantly different. Would this be confusing?
not sure what you mean here exactly. overall we don't have a different matching behavior in a "user-visible" manner. implementation-wise it's slightly different than other sanitizer-list matching, as we keep searching for longest matching glob, rather than stopping at first match. it's documented as such and I think is intuitive for users (that the most specific entry takes precedence).
https://github.com/llvm/llvm-project/pull/112517
More information about the cfe-commits
mailing list