================
@@ -11,37 +11,113 @@
//===----------------------------------------------------------------------===//
#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 preproces`sor.
+ 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
----------------
AaronBallman wrote:
I think this should be addressed up front; this kind of failure is expected.
That said, I would imagine we'd want this failure before getting to the end of
the source file -- if we cannot create the file anyway, all the work we're
doing up to this point is basically wasted, so it'd be better to fail earlier
and not do that work.
I'm also wondering what kind of test coverage we might want here; inducing a
failure may be tricky in a platform independent manner though.
https://github.com/llvm/llvm-project/pull/185201
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits