cjdb updated this revision to Diff 502305.
cjdb edited the summary of this revision.
cjdb added a comment.

adds dependency


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D145284/new/

https://reviews.llvm.org/D145284

Files:
  clang/include/clang/Basic/DiagnosticOptions.def
  clang/include/clang/Basic/DiagnosticOptions.h
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CompilerInstance.h
  clang/include/clang/Frontend/SARIFDiagnosticPrinter.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInstance.cpp
  clang/lib/Frontend/FrontendAction.cpp
  clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
  clang/lib/Frontend/TextDiagnostic.cpp
  clang/lib/Tooling/Tooling.cpp
  clang/test/Driver/fdiagnostics-format-sarif.cpp
  clang/tools/driver/cc1_main.cpp

Index: clang/tools/driver/cc1_main.cpp
===================================================================
--- clang/tools/driver/cc1_main.cpp
+++ clang/tools/driver/cc1_main.cpp
@@ -230,7 +230,12 @@
       CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
 
   // Create the actual diagnostics engine.
-  Clang->createDiagnostics();
+  auto diagnostics_format_option =
+      llvm::find(Argv, StringRef("-fdiagnostics-format"));
+  bool IsSarifFile =
+      std::distance(diagnostics_format_option, Argv.end()) > 1 &&
+      *std::next(diagnostics_format_option) == StringRef("sarif-file");
+  Clang->createDiagnostics(nullptr, true, IsSarifFile);
   if (!Clang->hasDiagnostics())
     return 1;
 
Index: clang/test/Driver/fdiagnostics-format-sarif.cpp
===================================================================
--- clang/test/Driver/fdiagnostics-format-sarif.cpp
+++ clang/test/Driver/fdiagnostics-format-sarif.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang -fsyntax-only -fdiagnostics-format=sarif %s -### 2>&1 | FileCheck %s --check-prefix=WARN
+// RUN: %clang -fsyntax-only -fdiagnostics-format=sarif-stderr %s -### 2>&1 | FileCheck %s --check-prefix=WARN
 // WARN: warning: diagnostic formatting in SARIF mode is currently unstable [-Wsarif-format-unstable]
 
-// RUN: %clang -fsyntax-only -fdiagnostics-format=SARIF %s -### 2>&1 | FileCheck %s --check-prefix=WARN2
+// RUN: %clang -fsyntax-only -fdiagnostics-format=sarif-file %s -### 2>&1 | FileCheck %s --check-prefix=WARN2
 // WARN2: warning: diagnostic formatting in SARIF mode is currently unstable [-Wsarif-format-unstable]
Index: clang/lib/Tooling/Tooling.cpp
===================================================================
--- clang/lib/Tooling/Tooling.cpp
+++ clang/lib/Tooling/Tooling.cpp
@@ -425,7 +425,9 @@
   std::unique_ptr<FrontendAction> ScopedToolAction(create());
 
   // Create the compiler's actual diagnostics engine.
-  Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
+  Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false,
+                             Invocation->DiagnosticOpts->getFormat() ==
+                                 DiagnosticOptions::SARIFFile);
   if (!Compiler.hasDiagnostics())
     return false;
 
@@ -684,7 +686,7 @@
 
   if (!Invocation.run())
     return nullptr;
- 
+
   assert(ASTs.size() == 1);
   return std::move(ASTs[0]);
 }
Index: clang/lib/Frontend/TextDiagnostic.cpp
===================================================================
--- clang/lib/Frontend/TextDiagnostic.cpp
+++ clang/lib/Frontend/TextDiagnostic.cpp
@@ -815,7 +815,8 @@
 
   emitFilename(PLoc.getFilename(), Loc.getManager());
   switch (DiagOpts->getFormat()) {
-  case DiagnosticOptions::SARIF:
+  case DiagnosticOptions::SARIFStderr:
+  case DiagnosticOptions::SARIFFile:
   case DiagnosticOptions::Clang:
     if (DiagOpts->ShowLine)
       OS << ':' << LineNo;
@@ -838,7 +839,8 @@
       OS << ColNo;
     }
   switch (DiagOpts->getFormat()) {
-  case DiagnosticOptions::SARIF:
+  case DiagnosticOptions::SARIFStderr:
+  case DiagnosticOptions::SARIFFile:
   case DiagnosticOptions::Clang:
   case DiagnosticOptions::Vi:    OS << ':';    break;
   case DiagnosticOptions::MSVC:
Index: clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
===================================================================
--- clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
+++ clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
@@ -22,19 +22,37 @@
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
+#include <memory>
 
 namespace clang {
 
 SARIFDiagnosticPrinter::SARIFDiagnosticPrinter(raw_ostream &OS,
                                                DiagnosticOptions *Diags)
-    : OS(OS), DiagOpts(Diags) {}
+    : OS(&OS), DiagOpts(Diags) {}
+
+static std::unique_ptr<llvm::raw_ostream>
+OpenDiagnosticFile(StringRef TargetPath, std::error_code &EC) {
+  assert(!TargetPath.empty());
+  return std::make_unique<llvm::raw_fd_ostream>(
+      std::string(TargetPath) + ".sarif", EC);
+}
+
+SARIFDiagnosticPrinter::SARIFDiagnosticPrinter(StringRef TargetPath,
+                                               DiagnosticOptions *Diags)
+    : EC(std::error_code()), OS(OpenDiagnosticFile(TargetPath, *EC)),
+      DiagOpts(Diags) {
+  if (*EC) {
+    assert(false and "not implemented yet: not even sure what to do");
+  }
+}
 
 void SARIFDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
                                              const Preprocessor *PP) {
   // Build the SARIFDiagnostic utility.
   assert(hasSarifWriter() && "Writer not set!");
   assert(!SARIFDiag && "SARIFDiagnostic already set.");
-  SARIFDiag = std::make_unique<SARIFDiagnostic>(OS, LO, &*DiagOpts, &*Writer);
+  SARIFDiag =
+      std::make_unique<SARIFDiagnostic>(getOS(), LO, &*DiagOpts, &*Writer);
   // Initialize the SARIF object.
   Writer->createRun("clang", Prefix);
 }
@@ -43,8 +61,13 @@
   assert(SARIFDiag && "SARIFDiagnostic has not been set.");
   Writer->endRun();
   llvm::json::Value Value(Writer->createDocument());
-  OS << "\n" << Value << "\n\n";
-  OS.flush();
+  getOS() << '\n' << Value << '\n';
+  getOS().flush();
+  if (EC and *EC) {
+    llvm::errs() << "error: " << EC->message() << '\n';
+    llvm::errs() << "outputting to stderr as a backup\n";
+    llvm::errs() << Value << '\n';
+  }
   SARIFDiag.reset();
 }
 
Index: clang/lib/Frontend/FrontendAction.cpp
===================================================================
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -724,7 +724,9 @@
   }
   if (!CI.hasSourceManager()) {
     CI.createSourceManager(CI.getFileManager());
-    if (CI.getDiagnosticOpts().getFormat() == DiagnosticOptions::SARIF) {
+    if (TextDiagnosticFormat Format = CI.getDiagnosticOpts().getFormat();
+        Format == DiagnosticOptions::SARIFStderr ||
+        Format == DiagnosticOptions::SARIFFile) {
       static_cast<SARIFDiagnosticPrinter *>(&CI.getDiagnosticClient())
           ->setSarifWriter(
               std::make_unique<SarifDocumentWriter>(CI.getSourceManager()));
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -333,16 +333,18 @@
 }
 
 void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
-                                         bool ShouldOwnClient) {
-  Diagnostics = createDiagnostics(&getDiagnosticOpts(), Client,
-                                  ShouldOwnClient, &getCodeGenOpts());
-}
-
-IntrusiveRefCntPtr<DiagnosticsEngine>
-CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
-                                    DiagnosticConsumer *Client,
-                                    bool ShouldOwnClient,
-                                    const CodeGenOptions *CodeGenOpts) {
+                                         bool ShouldOwnClient, bool ToFile) {
+  StringRef Input =
+      llvm::sys::path::filename(getFrontendOpts().Inputs.front().getFile());
+  StringRef Output = getFrontendOpts().OutputFile;
+  Diagnostics =
+      createDiagnostics(&getDiagnosticOpts(), Client, ShouldOwnClient,
+                        &getCodeGenOpts(), Output.empty() ? Input : Output);
+}
+
+IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
+    DiagnosticOptions *Opts, DiagnosticConsumer *Client, bool ShouldOwnClient,
+    const CodeGenOptions *CodeGenOpts, StringRef TargetPath) {
   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
   IntrusiveRefCntPtr<DiagnosticsEngine>
       Diags(new DiagnosticsEngine(DiagID, Opts));
@@ -351,8 +353,10 @@
   // implementing -verify.
   if (Client) {
     Diags->setClient(Client, ShouldOwnClient);
-  } else if (Opts->getFormat() == DiagnosticOptions::SARIF) {
+  } else if (Opts->getFormat() == DiagnosticOptions::SARIFStderr) {
     Diags->setClient(new SARIFDiagnosticPrinter(llvm::errs(), Opts));
+  } else if (Opts->getFormat() == DiagnosticOptions::SARIFFile) {
+    Diags->setClient(new SARIFDiagnosticPrinter(TargetPath, Opts));
   } else
     Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
 
@@ -1221,7 +1225,6 @@
                             &ImportingInstance.getModuleCache());
   auto &Inv = *Invocation;
   Instance.setInvocation(std::move(Invocation));
-
   Instance.createDiagnostics(new ForwardingDiagnosticConsumer(
                                    ImportingInstance.getDiagnosticClient()),
                              /*ShouldOwnClient=*/true);
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4032,8 +4032,7 @@
   if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
     CmdArgs.push_back("-fdiagnostics-format");
     CmdArgs.push_back(A->getValue());
-    if (StringRef(A->getValue()) == "sarif" ||
-        StringRef(A->getValue()) == "SARIF")
+    if (StringRef(A->getValue()).starts_with("sarif"))
       D.Diag(diag::warn_drv_sarif_format_unstable);
   }
 
Index: clang/include/clang/Frontend/SARIFDiagnosticPrinter.h
===================================================================
--- clang/include/clang/Frontend/SARIFDiagnosticPrinter.h
+++ clang/include/clang/Frontend/SARIFDiagnosticPrinter.h
@@ -20,6 +20,8 @@
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
 #include <memory>
+#include <optional>
+#include <variant>
 
 namespace clang {
 class DiagnosticOptions;
@@ -30,6 +32,12 @@
 class SARIFDiagnosticPrinter : public DiagnosticConsumer {
 public:
   SARIFDiagnosticPrinter(raw_ostream &OS, DiagnosticOptions *Diags);
+
+  /// Constructs a SARIFDiagnosticPrinter so that it writes to a file mimicing
+  /// Clang's current output target. The diagnostics file target has the same
+  /// name suffixed with `.sarif`.
+  SARIFDiagnosticPrinter(StringRef TargetPath, DiagnosticOptions *Diags);
+
   ~SARIFDiagnosticPrinter() = default;
 
   SARIFDiagnosticPrinter &operator=(const SARIFDiagnosticPrinter &&) = delete;
@@ -59,7 +67,8 @@
                         const Diagnostic &Info) override;
 
 private:
-  raw_ostream &OS;
+  std::optional<std::error_code> EC;
+  std::variant<raw_ostream *, std::unique_ptr<raw_ostream>> OS;
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
 
   /// Handle to the currently active SARIF diagnostic emitter.
@@ -69,6 +78,16 @@
   std::string Prefix;
 
   std::unique_ptr<SarifDocumentWriter> Writer;
+
+  raw_ostream &getOS() {
+    // Deliberately not using std::visit due to there being exactly two known
+    // types.
+    if (std::holds_alternative<raw_ostream *>(OS)) {
+      return *std::get<raw_ostream *>(OS);
+    } else {
+      return *std::get<std::unique_ptr<raw_ostream>>(OS);
+    }
+  }
 };
 
 } // end namespace clang
Index: clang/include/clang/Frontend/CompilerInstance.h
===================================================================
--- clang/include/clang/Frontend/CompilerInstance.h
+++ clang/include/clang/Frontend/CompilerInstance.h
@@ -606,8 +606,12 @@
   ///
   /// \param ShouldOwnClient If Client is non-NULL, specifies whether
   /// the diagnostic object should take ownership of the client.
+  ///
+  /// \param ToFile Determines if Clang should write diagnostics to a file.
   void createDiagnostics(DiagnosticConsumer *Client = nullptr,
-                         bool ShouldOwnClient = true);
+                         bool ShouldOwnClient = true, bool ToFile = false);
+
+  std::string MakeInputPath() const;
 
   /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
   ///
@@ -626,12 +630,16 @@
   /// \param CodeGenOpts If non-NULL, the code gen options in use, which may be
   /// used by some diagnostics printers (for logging purposes only).
   ///
+  /// \param TargetPath Path to the target that Clang is currently producing.
+  /// This will be used as the prefix of any file that Clang may write
+  /// diagnostics to (e.g. `-fdiagnostics-format=sarif-file -o /tmp/hello` would
+  /// lead to there being a file called `/tmp/hello.sarif`).
+  ///
   /// \return The new object on success, or null on failure.
-  static IntrusiveRefCntPtr<DiagnosticsEngine>
-  createDiagnostics(DiagnosticOptions *Opts,
-                    DiagnosticConsumer *Client = nullptr,
-                    bool ShouldOwnClient = true,
-                    const CodeGenOptions *CodeGenOpts = nullptr);
+  static IntrusiveRefCntPtr<DiagnosticsEngine> createDiagnostics(
+      DiagnosticOptions *Opts, DiagnosticConsumer *Client = nullptr,
+      bool ShouldOwnClient = true, const CodeGenOptions *CodeGenOpts = nullptr,
+      StringRef TargetPath = "");
 
   /// Create the file manager and replace any existing one with it.
   ///
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -5843,8 +5843,8 @@
 
 def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">,
   HelpText<"Change diagnostic formatting to match IDE and command line tools">,
-  Values<"clang,msvc,vi,sarif,SARIF">,
-  NormalizedValuesScope<"DiagnosticOptions">, NormalizedValues<["Clang", "MSVC", "Vi", "SARIF", "SARIF"]>,
+  Values<"clang,msvc,vi,sarif-stderr,sarif-file">,
+  NormalizedValuesScope<"DiagnosticOptions">, NormalizedValues<["Clang", "MSVC", "Vi", "SARIFStderr", "SARIFFile"]>,
   MarshallingInfoEnum<DiagnosticOpts<"Format">, "Clang">;
 def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">,
   HelpText<"Print diagnostic category">,
Index: clang/include/clang/Basic/DiagnosticOptions.h
===================================================================
--- clang/include/clang/Basic/DiagnosticOptions.h
+++ clang/include/clang/Basic/DiagnosticOptions.h
@@ -74,7 +74,7 @@
   friend class CompilerInvocation;
 
 public:
-  enum TextDiagnosticFormat { Clang, MSVC, Vi, SARIF };
+  enum TextDiagnosticFormat { Clang, MSVC, Vi, SARIFStderr, SARIFFile };
 
   // Default values.
   enum {
Index: clang/include/clang/Basic/DiagnosticOptions.def
===================================================================
--- clang/include/clang/Basic/DiagnosticOptions.def
+++ clang/include/clang/Basic/DiagnosticOptions.def
@@ -63,7 +63,7 @@
 VALUE_DIAGOPT(ShowCategories, 2, 0) /// Show categories: 0 -> none, 1 -> Number,
                                     /// 2 -> Full Name.
 
-ENUM_DIAGOPT(Format, TextDiagnosticFormat, 2, Clang) /// Format for diagnostics:
+ENUM_DIAGOPT(Format, TextDiagnosticFormat, 3, Clang) /// Format for diagnostics:
 
 DIAGOPT(ShowColors, 1, 0)       /// Show diagnostics with ANSI color sequences.
 DIAGOPT(UseANSIEscapeCodes, 1, 0)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to