[clang] [clang] [diagnostics] Add `-fdiagnostics-add-output` switch for SARIF (PR #185201)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Mar 7 08:27:16 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Dave Bartolomeo (dbartol)
<details>
<summary>Changes</summary>
This change introduces the new `-fdiagnostics-add-output=` switch, which adds an additional output file for diagnostics. The syntax of the switch, which matches an existing GCC switch, is `-fdiagnostics-add-output=format:key1=value1,key2=value2...`. `format` specifies the format of the diagnostics; currently, only `sarif` is supported, but it would be easy enough to add other formats. The optional key-value pairs specify options specific to that format. For `sarif`, the valid options are:
- `file=<path>` - Specifies the path to the generated SARIF file. Unlike GCC, this property is required. We could make it optional by providing a default based on the input filename, but plumbing that through would have made the implementation more complex.
- `version=<version>` - Specifies the SARIF schema version. Only `2.1` is currently supported.
The `-fdiagnostics-add-output=` switch can be specified multiple times. Each occurrence adds an additional output sink, so multiple SARIF logs are possible with different file paths.
- I've added a positive test for the new switch, including specifying it multiple times.
- I've added a negative test for various malformed format/key/value strings.
- I've updated our existing SARIF test to use the same normalize_sarif filter that the Static Analyzer's SARIF tests use, rather than a complicated set of CHECK directives.
rdar://160939516
---
Patch is 23.98 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/185201.diff
15 Files Affected:
- (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (+14)
- (modified) clang/include/clang/Basic/DiagnosticOptions.h (+3)
- (modified) clang/include/clang/Basic/Sarif.h (+17-8)
- (modified) clang/include/clang/Frontend/SARIFDiagnostic.h (+2-3)
- (modified) clang/include/clang/Frontend/SARIFDiagnosticPrinter.h (+7-2)
- (modified) clang/include/clang/Options/Options.td (+6)
- (modified) clang/lib/Basic/Sarif.cpp (+21-5)
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+6)
- (modified) clang/lib/Frontend/CompilerInstance.cpp (+50-1)
- (modified) clang/lib/Frontend/FrontendAction.cpp (-5)
- (modified) clang/lib/Frontend/SARIFDiagnostic.cpp (+1-1)
- (modified) clang/lib/Frontend/SARIFDiagnosticPrinter.cpp (+85-6)
- (added) clang/test/Frontend/Inputs/expected-sarif/sarif-log.cpp.sarif (+105)
- (added) clang/test/Frontend/sarif-log-invalid.cpp (+9)
- (added) clang/test/Frontend/sarif-log.cpp (+12)
``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 972cc87464769..745d7e2e07be8 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -586,6 +586,20 @@ def err_analyzer_not_built_with_z3 : Error<
"analyzer constraint manager 'z3' is only available if LLVM was built with "
"-DLLVM_ENABLE_Z3_SOLVER=ON">;
+def err_diagnostic_output_no_value
+ : Error<"'-fdiagnostics-add-output' key '%0' has no value">;
+def err_diagnostic_output_unknown_format
+ : Error<"'-fdiagnostics-add-output' uses unrecognized format '%0'">;
+def err_diagnostic_output_unknown_key
+ : Error<"'-fdiagnostics-add-output' with format '%0' uses unrecognized key "
+ "'%1'">;
+def err_invalid_sarif_version
+ : Error<"'-fdiagnostics-add-output' specifies unsupported SARIF version "
+ "'%0'. Supported versions are: %1">;
+def err_missing_sarif_file_name
+ : Error<"'-fdiagnostics-add-output' with format 'sarif' is missing "
+ "required key 'file'">;
+
def warn_drv_needs_hvx : Warning<
"%0 requires HVX, use -mhvx/-mhvx= to enable it">,
InGroup<OptionIgnored>;
diff --git a/clang/include/clang/Basic/DiagnosticOptions.h b/clang/include/clang/Basic/DiagnosticOptions.h
index a230022224de5..47f3135f9237a 100644
--- a/clang/include/clang/Basic/DiagnosticOptions.h
+++ b/clang/include/clang/Basic/DiagnosticOptions.h
@@ -107,6 +107,9 @@ class DiagnosticOptions {
/// The file to serialize diagnostics to (non-appending).
std::string DiagnosticSerializationFile;
+ /// List of arguments to `-fdiagnostics-add-output=`
+ std::vector<std::string> AdditionalOutputConfigs;
+
/// Path for the file that defines diagnostic suppression mappings.
std::string DiagnosticSuppressionMappingsFile;
diff --git a/clang/include/clang/Basic/Sarif.h b/clang/include/clang/Basic/Sarif.h
index 7651d2ac7a768..c7610794e2163 100644
--- a/clang/include/clang/Basic/Sarif.h
+++ b/clang/include/clang/Basic/Sarif.h
@@ -50,6 +50,13 @@ namespace clang {
class SarifDocumentWriter;
class SourceManager;
+struct SarifVersion {
+ StringRef SchemaVersion;
+ StringRef CommandLineVersion;
+ StringRef SchemaURI;
+ bool IsDefault;
+};
+
namespace detail {
/// \internal
@@ -413,10 +420,7 @@ class SarifResult {
/// aggregation methods such as SarifDocumentWriter::appendResult etc.
class SarifDocumentWriter {
private:
- const llvm::StringRef SchemaURI{
- "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/"
- "sarif-schema-2.1.0.json"};
- const llvm::StringRef SchemaVersion{"2.1.0"};
+ const SarifVersion Version;
/// \internal
/// Return a pointer to the current tool. Asserts that a run exists.
@@ -460,16 +464,17 @@ class SarifDocumentWriter {
SarifDocumentWriter() = delete;
/// Create a new empty SARIF document with the given source manager.
- SarifDocumentWriter(const SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
+ SarifDocumentWriter(const SourceManager &SourceMgr,
+ const SarifVersion &Version = getDefaultVersion())
+ : Version(Version), SourceMgr(SourceMgr) {}
/// Release resources held by this SARIF document.
~SarifDocumentWriter() = default;
/// Create a new run with which any upcoming analysis will be associated.
/// Each run requires specifying the tool that is generating reporting items.
- void createRun(const llvm::StringRef ShortToolName,
- const llvm::StringRef LongToolName,
- const llvm::StringRef ToolVersion = CLANG_VERSION_STRING);
+ void createRun(std::string ShortToolName, std::string LongToolName,
+ std::string ToolVersion = CLANG_VERSION_STRING);
/// If there is a current run, end it.
///
@@ -511,6 +516,10 @@ class SarifDocumentWriter {
static std::string fileNameToURI(llvm::StringRef Filename);
+ static ArrayRef<SarifVersion> getSupportedVersions();
+
+ static const SarifVersion &getDefaultVersion();
+
private:
/// Source Manager to use for the current SARIF document.
const SourceManager &SourceMgr;
diff --git a/clang/include/clang/Frontend/SARIFDiagnostic.h b/clang/include/clang/Frontend/SARIFDiagnostic.h
index 7a6f27eb3b9fa..f2933ec832f43 100644
--- a/clang/include/clang/Frontend/SARIFDiagnostic.h
+++ b/clang/include/clang/Frontend/SARIFDiagnostic.h
@@ -22,9 +22,8 @@ namespace clang {
class SARIFDiagnostic : public DiagnosticRenderer {
public:
- SARIFDiagnostic(raw_ostream &OS, const LangOptions &LangOpts,
- DiagnosticOptions &DiagOpts, SarifDocumentWriter *Writer);
-
+ SARIFDiagnostic(const LangOptions &LangOpts, DiagnosticOptions &DiagOpts,
+ SarifDocumentWriter *Writer);
~SARIFDiagnostic() = default;
SARIFDiagnostic &operator=(const SARIFDiagnostic &&) = delete;
diff --git a/clang/include/clang/Frontend/SARIFDiagnosticPrinter.h b/clang/include/clang/Frontend/SARIFDiagnosticPrinter.h
index 3406ed16c2fba..0877867757bbe 100644
--- a/clang/include/clang/Frontend/SARIFDiagnosticPrinter.h
+++ b/clang/include/clang/Frontend/SARIFDiagnosticPrinter.h
@@ -29,7 +29,7 @@ class SarifDocumentWriter;
class SARIFDiagnosticPrinter : public DiagnosticConsumer {
public:
- SARIFDiagnosticPrinter(raw_ostream &OS, DiagnosticOptions &DiagOpts);
+ SARIFDiagnosticPrinter(llvm::StringRef FilePath, DiagnosticOptions &DiagOpts);
~SARIFDiagnosticPrinter() = default;
SARIFDiagnosticPrinter &operator=(const SARIFDiagnosticPrinter &&) = delete;
@@ -58,8 +58,13 @@ class SARIFDiagnosticPrinter : public DiagnosticConsumer {
void HandleDiagnostic(DiagnosticsEngine::Level Level,
const Diagnostic &Info) override;
+ static std::unique_ptr<SARIFDiagnosticPrinter>
+ create(ArrayRef<std::pair<StringRef, StringRef>> Config,
+ DiagnosticOptions &DiagOpts, DiagnosticsEngine &Diags);
+
private:
- raw_ostream &OS;
+ std::string FilePath;
+
DiagnosticOptions &DiagOpts;
/// Handle to the currently active SARIF diagnostic emitter.
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index cc05fb71c84e4..9927782e2768a 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6729,6 +6729,12 @@ def _profile : Flag<["--"], "profile">, Alias<p>;
def _resource_EQ : Joined<["--"], "resource=">, Alias<fcompile_resource_EQ>;
def _resource : Separate<["--"], "resource">, Alias<fcompile_resource_EQ>;
def _rtlib : Separate<["--"], "rtlib">, Alias<rtlib_EQ>;
+def fdiagnostics_add_output_EQ
+ : Joined<["-"], "fdiagnostics-add-output=">,
+ Group<f_clang_Group>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Generate additional diagnostics log file">,
+ MarshallingInfoStringVector<DiagnosticOpts<"AdditionalOutputConfigs">>;
def _serialize_diags : Separate<["-", "--"], "serialize-diagnostics">,
Flags<[NoXarchOption]>,
HelpText<"Serialize compiler diagnostics to a file">;
diff --git a/clang/lib/Basic/Sarif.cpp b/clang/lib/Basic/Sarif.cpp
index e829b9bb47ad9..fd1800bdbf30a 100644
--- a/clang/lib/Basic/Sarif.cpp
+++ b/clang/lib/Basic/Sarif.cpp
@@ -342,9 +342,9 @@ SarifDocumentWriter::createCodeFlow(ArrayRef<ThreadFlow> ThreadFlows) {
return json::Object{{"threadFlows", createThreadFlows(ThreadFlows)}};
}
-void SarifDocumentWriter::createRun(StringRef ShortToolName,
- StringRef LongToolName,
- StringRef ToolVersion) {
+void SarifDocumentWriter::createRun(std::string ShortToolName,
+ std::string LongToolName,
+ std::string ToolVersion) {
// Clear resources associated with a previous run.
endRun();
@@ -439,10 +439,26 @@ json::Object SarifDocumentWriter::createDocument() {
endRun();
json::Object Doc{
- {"$schema", SchemaURI},
- {"version", SchemaVersion},
+ {"$schema", Version.SchemaURI},
+ {"version", Version.SchemaVersion},
};
if (!Runs.empty())
Doc["runs"] = json::Array(Runs);
return Doc;
}
+
+ArrayRef<SarifVersion> SarifDocumentWriter::getSupportedVersions() {
+ static const SarifVersion Versions[] = {
+ {"2.1.0", "2.1",
+ "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/"
+ "sarif-schema-2.1.0.json",
+ true}};
+
+ return Versions;
+}
+
+const SarifVersion &SarifDocumentWriter::getDefaultVersion() {
+ const auto Versions = getSupportedVersions();
+ return *std::find_if(Versions.begin(), Versions.end(),
+ [](const SarifVersion &V) { return V.IsDefault; });
+}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 36ba3d35ed012..9f4b077a62132 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7700,6 +7700,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(A->getValue()));
}
+ // Create additional diagnostic logs
+ for (Arg *A : Args.filtered(options::OPT_fdiagnostics_add_output_EQ)) {
+ A->render(Args, CmdArgs);
+ A->claim();
+ }
+
if (Args.hasArg(options::OPT_fretain_comments_from_system_headers))
CmdArgs.push_back("-fretain-comments-from-system-headers");
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 60914d9b2cbc7..98bd89c507e2e 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/Decl.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
@@ -26,6 +27,7 @@
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/LogDiagnosticPrinter.h"
+#include "clang/Frontend/SARIFDiagnostic.h"
#include "clang/Frontend/SARIFDiagnosticPrinter.h"
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
@@ -342,6 +344,47 @@ static void SetupSerializedDiagnostics(DiagnosticOptions &DiagOpts,
}
}
+static void SetupAdditionalLogs(DiagnosticOptions &DiagOpts,
+ DiagnosticsEngine &Diags) {
+ for (StringRef Config : DiagOpts.AdditionalOutputConfigs) {
+ auto [Format, PairsString] = Config.split(":");
+
+ SmallVector<StringRef, 4> PairStrings;
+ PairsString.split(PairStrings, ",", -1, /* KeepEmpty = */ false);
+ SmallVector<std::pair<StringRef, StringRef>, 4> Pairs;
+ for (const auto &PairString : PairStrings) {
+ std::pair<StringRef, StringRef> Pair = PairString.split("=");
+ if (Pair.second.empty()) {
+ Diags.Report(SourceLocation(), diag::err_diagnostic_output_no_value)
+ << Pair.first;
+ break;
+ }
+
+ Pairs.push_back(PairString.split("="));
+ }
+
+ std::unique_ptr<DiagnosticConsumer> Consumer;
+ if (Format == "sarif") {
+ Consumer = SARIFDiagnosticPrinter::create(Pairs, DiagOpts, Diags);
+
+ } else {
+ // Only support "sarif" for now.
+ Diags.Report(SourceLocation(), diag::err_diagnostic_output_unknown_format)
+ << Format;
+ }
+
+ if (Consumer) {
+ if (Diags.ownsClient()) {
+ Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(),
+ std::move(Consumer)));
+ } else {
+ Diags.setClient(new ChainedDiagnosticConsumer(Diags.getClient(),
+ std::move(Consumer)));
+ }
+ }
+ }
+}
+
void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
bool ShouldOwnClient) {
Diagnostics = createDiagnostics(getVirtualFileSystem(), getDiagnosticOpts(),
@@ -360,7 +403,9 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
if (Client) {
Diags->setClient(Client, ShouldOwnClient);
} else if (Opts.getFormat() == DiagnosticOptions::SARIF) {
- Diags->setClient(new SARIFDiagnosticPrinter(llvm::errs(), Opts));
+ /* TO_UPSTREAM(SARIF) ON */
+ Diags->setClient(new SARIFDiagnosticPrinter("", Opts));
+ /* TO_UPSTREAM(SARIF) OFF */
} else
Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
@@ -375,6 +420,10 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
if (!Opts.DiagnosticSerializationFile.empty())
SetupSerializedDiagnostics(Opts, *Diags, Opts.DiagnosticSerializationFile);
+ /* TO_UPSTREAM(SARIF) ON */
+ SetupAdditionalLogs(Opts, *Diags);
+ /* TO_UPSTREAM(SARIF) OFF */
+
// Configure our handling of diagnostics.
ProcessWarningOptions(*Diags, Opts, VFS);
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 73f092521546f..78fe306d1579e 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -977,11 +977,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.createFileManager();
if (!CI.hasSourceManager()) {
CI.createSourceManager();
- if (CI.getDiagnosticOpts().getFormat() == DiagnosticOptions::SARIF) {
- static_cast<SARIFDiagnosticPrinter *>(&CI.getDiagnosticClient())
- ->setSarifWriter(
- std::make_unique<SarifDocumentWriter>(CI.getSourceManager()));
- }
}
// Set up embedding for any specified files. Do this before we load any
diff --git a/clang/lib/Frontend/SARIFDiagnostic.cpp b/clang/lib/Frontend/SARIFDiagnostic.cpp
index 04ee14edfe74c..c96dc03552f31 100644
--- a/clang/lib/Frontend/SARIFDiagnostic.cpp
+++ b/clang/lib/Frontend/SARIFDiagnostic.cpp
@@ -30,7 +30,7 @@
namespace clang {
-SARIFDiagnostic::SARIFDiagnostic(raw_ostream &OS, const LangOptions &LangOpts,
+SARIFDiagnostic::SARIFDiagnostic(const LangOptions &LangOpts,
DiagnosticOptions &DiagOpts,
SarifDocumentWriter *Writer)
: DiagnosticRenderer(LangOpts, DiagOpts), Writer(Writer) {}
diff --git a/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp b/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
index 72b796f8db798..d05bd33efbcc2 100644
--- a/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
@@ -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()));
+ }
assert(hasSarifWriter() && "Writer not set!");
assert(!SARIFDiag && "SARIFDiagnostic already set.");
- SARIFDiag = std::make_unique<SARIFDiagnostic>(OS, LO, DiagOpts, &*Writer);
+ SARIFDiag = std::make_unique<SARIFDiagnostic>(LO, DiagOpts, &*Writer);
// Initialize the SARIF object.
- Writer->createRun("clang", Prefix);
+ Writer->createRun("clang", Prefix, getClangFullVersion());
}
void SARIFDiagnosticPrinter::EndSourceFile() {
assert(SARIFDiag && "SARIFDiagnostic has not been set.");
Writer->endRun();
llvm::json::Value Value(Writer->createDocument());
- OS << llvm::formatv("\n{0:2}\n\n", Value);
- OS.flush();
+ if (FilePath.empty()) {
+ // Write to console.
+ llvm::errs() << llvm::formatv("\n{0:2}\n\n", Value);
+ llvm::errs().flush();
+ } else {
+ // Write to file.
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(FilePath, EC, llvm::sys::fs::OF_TextWithCRLF);
+ if (EC) {
+ // FIXME: Emit a real diagnostic, similar to how the serialized diagnostic
+ // log does via getMetaDiags().
+ llvm::errs() << "warning: could not create file: " << EC.message()
+ << '\n';
+ } else {
+ OS << llvm::formatv("{0:2}\n", Value);
+ }
+ }
+
SARIFDiag.reset();
}
diff --git a/clang/test/Frontend/Inputs/expected-sarif/sarif-log.cpp.sarif b/clang/test/Frontend/Inputs/expected-sarif/sarif-log.cpp.sarif
new file mode 100644
index 0000000000000..811d70a3eeed0
--- /dev/null
+++ b/clang/test/Frontend/Inputs/expected-sarif/sarif-log.cpp.sarif
@@ -0,0 +1,105 @@
+{
+ "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
+ "runs": [
+ {
+ "artifacts": [
+ {
+ "length": -1,
+ "location": {
+ "index": 0,
+ "uri": "file:///[...]/sarif-log.cpp"
+ },
+ "mimeType": "text/plain",
+ "roles": [
+ "resultFile"
+ ]
+ }
+ ],
+ "columnKind": "unicodeCodePoints",
+ "results": [
+ {
+ "level": "warning",
+ "locations": [
+ {
+ "physicalLocation": {
+ "artifactLocation": {
+ "index": 0,
+ "uri": "file:///[...]/sarif-log.cpp"
+ },
+ "region": {
+ "endColumn": 3,
+ "startColumn": 3,
+ ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/185201
More information about the cfe-commits
mailing list