================
@@ -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

Reply via email to