[clang] [clang-tools-extra] [clang-tidy] Add SARIF output to clang-tidy (PR #219182)

Zeyi Xu via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 7 05:24:25 PDT 2026


================
@@ -195,6 +211,98 @@ class ErrorReporter {
     }
     for (const auto &Note : Error.Notes)
       reportNote(Note);
+
+    if (SarifWriter)
+      exportSarifResult(Error, Loc);
+  }
+
+  CharSourceRange getNoteRange(const tooling::DiagnosticMessage &Note) {
+    if (!Note.Ranges.empty())
+      return getRange(Note.Ranges.front());
+    const SourceLocation Loc = getLocation(Note.FilePath, Note.FileOffset);
+    if (Loc.isInvalid())
+      return {};
+    return getOffsetRange(SourceMgr, Loc);
+  }
+
+  SmallVector<ThreadFlow, 8> createThreadFlows(const ClangTidyError &Error) {
+    SmallVector<ThreadFlow, 8> Flows;
+    if (!StringRef(Error.DiagnosticName).starts_with("clang-analyzer-"))
+      return Flows;
+
+    Flows.reserve(Error.Notes.size());
+    for (const tooling::DiagnosticMessage &Note : Error.Notes) {
+      Flows.push_back(ThreadFlow::create()
+                          .setRange(getNoteRange(Note))
+                          .setMessage(Note.Message));
+    }
+    return Flows;
+  }
+
+  void exportSarifResult(const ClangTidyError &Error,
+                         const SourceLocation Loc) {
+    assert(SarifWriter &&
+           "SarifWriter must be initialized to export SARIF results");
+
+    const auto [RuleIndexEntryIt, Inserted] =
+        SarifRuleIdx.try_emplace(Error.DiagnosticName, 0);
+    size_t &RuleIndex = RuleIndexEntryIt->second;
+
+    const DiagnosticsEngine::Level EffectiveLevel =
+        Error.IsWarningAsError
+            ? DiagnosticsEngine::Error
+            : static_cast<DiagnosticsEngine::Level>(Error.DiagLevel);
+
+    if (Inserted) {
+      const StringRef Name = Error.DiagnosticName;
----------------
zeyi2 wrote:

Could we also preserve `Error.EnabledDiagnosticAliases` in the SARIF output?

For `struct A { A(int) {} };`, enabling both `google-explicit-constructor` and `cppcoreguidelines-explicit-constructor` gives a single text diagnostic with both check names.

The SARIF result only retains `cppcoreguidelines-explicit-constructor`. We probably should not lose the other enabled check names entirely. 

While doing the review, I noticed that the object can contain a property (link: https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317449). Is it possible to retain the enabled aliases in the result's `properties`?

https://github.com/llvm/llvm-project/pull/219182


More information about the cfe-commits mailing list