[clang] [clang] [diagnostics] Add `-fdiagnostics-add-output` switch for SARIF (PR #185201)

Dave Bartolomeo via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 9 08:37:33 PDT 2026


================
@@ -11,37 +11,116 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Frontend/SARIFDiagnosticPrinter.h"
+#include "clang/Basic/DiagnosticDriver.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/Sarif.h"
 #include "clang/Frontend/DiagnosticRenderer.h"
 #include "clang/Frontend/SARIFDiagnostic.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace clang {
 
-SARIFDiagnosticPrinter::SARIFDiagnosticPrinter(raw_ostream &OS,
+SARIFDiagnosticPrinter::SARIFDiagnosticPrinter(llvm::StringRef FilePath,
                                                DiagnosticOptions &DiagOpts)
-    : OS(OS), DiagOpts(DiagOpts) {}
+    : FilePath(FilePath), DiagOpts(DiagOpts) {}
+
+std::unique_ptr<SARIFDiagnosticPrinter>
+SARIFDiagnosticPrinter::create(ArrayRef<std::pair<StringRef, StringRef>> Config,
+                               DiagnosticOptions &DiagOpts,
+                               DiagnosticsEngine &Diags) {
+  std::optional<std::string> FilePath;
+  SarifVersion Version = SarifDocumentWriter::getDefaultVersion();
+
+  for (const auto &Pair : Config) {
+    if (Pair.first == "file") {
+      FilePath = Pair.second;
+    } else if (Pair.first == "version") {
+      auto SupportedVersions = SarifDocumentWriter::getSupportedVersions();
+      auto FoundVersion =
+          std::find_if(SupportedVersions.begin(), SupportedVersions.end(),
+                       [=](const SarifVersion &V) {
+                         return V.CommandLineVersion == Pair.second;
+                       });
+      if (FoundVersion != SupportedVersions.end()) {
+        Version = *FoundVersion;
+      } else {
+        SmallString<64> SupportedList;
+        bool First = true;
+        for (const auto &V : SupportedVersions) {
+          if (First) {
+            First = false;
+          } else {
+            SupportedList.append(", ");
+          }
+          SupportedList.append("'");
+          SupportedList.append(V.CommandLineVersion);
+          SupportedList.append("'");
+        }
+        Diags.Report(SourceLocation(), diag::err_invalid_sarif_version)
+            << Pair.second << SupportedList;
+      }
+    } else {
+      Diags.Report(SourceLocation(), diag::err_diagnostic_output_unknown_key)
+          << "sarif" << Pair.second;
+    }
+  }
+
+  if (!FilePath) {
+    // We should probably have a default here based on the input file name or
+    // the output object file name, but I'm not sure how to get that information
+    // here.
+    Diags.Report(SourceLocation(), diag::err_missing_sarif_file_name);
+    return {};
+  }
+
+  return std::make_unique<SARIFDiagnosticPrinter>(*FilePath, DiagOpts);
+}
 
 void SARIFDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
                                              const Preprocessor *PP) {
   // Build the SARIFDiagnostic utility.
+  if (!hasSarifWriter() && PP) {
+    // Use the SourceManager from the preprocessor.
+    // REVIEW: Are there cases where we won't have a preprocessor but we will
+    // have a SourceManager? If so, we should pass the SourceManager directly to
+    // the BeginSourceFile call.
+    setSarifWriter(
+        std::make_unique<SarifDocumentWriter>(PP->getSourceManager()));
+  }
----------------
dbartol wrote:

I've just removed the comment, since that possibly hasn't showed up in a few months of usage downstream.

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


More information about the cfe-commits mailing list