================ @@ -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) { ---------------- bricknerb wrote:
Performance isn't my main concern here, just API consistency. Given that there are no exclusions in other use cases, I think no inconsistency can happen, so we should be good. https://github.com/llvm/llvm-project/pull/112517 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits