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