================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits