[clang] [clang-tools-extra] [llvm] [clang] Introduce diagnostics suppression mappings (PR #112517)
kadir çetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 7 05:16:37 PST 2024
================
@@ -477,6 +486,136 @@ void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
setSeverity(Diag, Map, Loc);
}
+namespace {
+// FIXME: We should isolate the parser from SpecialCaseList and just use it
+// here.
+class WarningsSpecialCaseList : public llvm::SpecialCaseList {
+public:
+ static std::unique_ptr<WarningsSpecialCaseList>
+ create(const llvm::MemoryBuffer &Input, std::string &Err);
+
+ // 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);
+
+ bool isDiagSuppressed(diag::kind DiagId, llvm::StringRef FilePath) 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,
+ llvm::StringRef FilePath) const;
+
+ llvm::DenseMap<diag::kind, const Section *> DiagToSection;
+};
+} // namespace
+
+std::unique_ptr<WarningsSpecialCaseList>
+WarningsSpecialCaseList::create(const llvm::MemoryBuffer &Input,
+ std::string &Err) {
+ auto WarningSuppressionList = std::make_unique<WarningsSpecialCaseList>();
+ if (!WarningSuppressionList->createInternal(&Input, Err))
+ return nullptr;
+ return WarningSuppressionList;
+}
+
+void WarningsSpecialCaseList::processSections(DiagnosticsEngine &Diags) {
+ // Drop the default section introduced by special case list, we only support
+ // exact diagnostic group names.
+ // FIXME: We should make this configurable in the parser instead.
+ 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) {
+ llvm::StringRef DiagName = Entry.first();
+ // Each section has a matcher with that section's name, attached to that
+ // line.
+ const auto &DiagSectionMatcher = Entry.second.SectionMatcher;
+ unsigned DiagLine = DiagSectionMatcher->Globs.at(DiagName).second;
+ LineAndSectionEntry.emplace_back(DiagLine, &Entry);
+ }
+ llvm::sort(LineAndSectionEntry);
+ static constexpr auto WarningFlavor = clang::diag::Flavor::WarningOrError;
+ for (const auto &[_, SectionEntry] : LineAndSectionEntry) {
+ SmallVector<diag::kind> GroupDiags;
+ llvm::StringRef DiagGroup = SectionEntry->getKey();
+ if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup(
+ WarningFlavor, DiagGroup, GroupDiags)) {
+ StringRef Suggestion =
+ DiagnosticIDs::getNearestOption(WarningFlavor, DiagGroup);
+ Diags.Report(diag::warn_unknown_diag_option)
+ << static_cast<unsigned>(WarningFlavor) << DiagGroup
+ << !Suggestion.empty() << Suggestion;
+ continue;
+ }
+ for (diag::kind Diag : GroupDiags)
+ // We're intentionally overwriting any previous mappings here to make sure
+ // latest one takes precedence.
+ DiagToSection[Diag] = &SectionEntry->getValue();
+ }
+}
+
+void DiagnosticsEngine::setDiagSuppressionMapping(llvm::MemoryBuffer &Input) {
+ std::string Err;
+ auto WarningSuppressionList = WarningsSpecialCaseList::create(Input, Err);
+ if (!WarningSuppressionList) {
+ Report(diag::err_drv_malformed_warning_suppression_mapping)
+ << Input.getBufferIdentifier() << Err;
+ return;
+ }
+ WarningSuppressionList->processSections(*this);
+ DiagSuppressionMapping =
+ [WarningSuppressionList(std::move(WarningSuppressionList))](
+ diag::kind DiagId, llvm::StringRef Path) {
+ return WarningSuppressionList->isDiagSuppressed(DiagId, Path);
+ };
+}
+
+bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId,
+ llvm::StringRef FilePath) const {
+ const Section *DiagSection = DiagToSection.lookup(DiagId);
+ if (!DiagSection)
+ return false;
+ const SectionEntries &EntityTypeToCategories = DiagSection->Entries;
+ auto SrcEntriesIt = EntityTypeToCategories.find("src");
+ if (SrcEntriesIt == EntityTypeToCategories.end())
+ return false;
+ const llvm::StringMap<llvm::SpecialCaseList::Matcher> &CategoriesToMatchers =
+ SrcEntriesIt->second;
----------------
kadircet wrote:
lookup returns by value (because it needs to return a default-constructed object when key doesn't exist), hence can't bind it to a reference.
https://github.com/llvm/llvm-project/pull/112517
More information about the cfe-commits
mailing list