llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-driver

Author: anonymous (anonymouspc)

<details>
<summary>Changes</summary>

# New feature

This PR introduces **nested/indented** diagnostic message when calling with 
`clang++ -fdiagnostics-format=sarif`.

In general, the user can now see a nested tree-like diagnositc, where one 
`warning`/`error` mounts several `notes` (and might recursively mount more 
`notes`, which seems like a tree). User may even fold the diagnostics through 
some sarif viewer.

In detail, in the `.sarif` output, `runs.results.relatedLocations` originally 
only represents some `In file included from...` information, but now can 
`variantly` represents child notes with diagnostics.

*(Note that now the `.sarif` format of `clang++ -fdiagnostics-format=sarif` is 
same to `g++ -fdiagnostics-format=sarif`).*



# Changes to codes

### `clang/include/clang/Frontend/SARIFDiagnostic.h`, 
`clang/lib/Frontend/SARIFDiagnostic.cpp`
- Logically define sarif-tree.
  - We know that the `clang++` diagnostics is **logically** a tree, which means 
that one error/warning often corresponds to several notes (and maybe 
recursively more notes). Let's take an example, a typical `clang++` diagnostics 
might looks like:
  ```
    error: invalid binary operand '+' to A and B.
      note: candidate 1
        note: why candidate 1 is invalid
      note: candidate 2
        note: why candidate 2 is invalid
    error: static assertion failed.
      note: in instantiation of C
        note: in instantiation of D
          note: concept/constraints not satisfied.
    ```

  - Here we rewrites the logical-data-structure of sarif into a tree (see 
`SARIFDiagnostic::Node`), that is:
    - when the `DiagnosticRenderer` emits diagnostics, `SARIFDiagnostic` 
organize them into a recursive tree;
    - when the `SARIFDiagnostic` destructs, it flush them all into the 
`SarifDocumentWriter`.

### `clang/include/clang/Basic/Sarif.h`, `clang/lib/Basic/Sarif.cpp` 
- Physically define sarif-tree.
  - **Physically**, the sarif diagnostics format has a plain structure, that is:
      - one `result` may carry several `Location`s and several 
`relatedLocation`s
        - a `Location` is the place where error occurs, e.g. `main.cpp:3:4`,
        - a `relatedLocation` is either a
          - `In file included from...` location, or a
          - *`child-result`*, who takes message, location, and **nesting**.
            - which **logically** corresponds a `clang++` note diagnostic.

 - Here, we expand the definition of `SarifResult::RelatedLocations` from 
`vector&lt;CharSourceRange&gt;` into `vector&lt;variant&lt;SarifChildResult, 
CharSourceRange&gt;&gt;`, and, at the same time update the corresponding 
serialization function for `relatedLocations`.

 - *(Note that GCC also makes sarif output in the same way: put child `results` 
into `relatedLocations` and then mark them with `properties.nestingLevel`)*.

### `clang/lib/Frontend/SARIFDiagnosticPrinter.cpp`
- Adjust the printer logic.
  - Now the `SARIFDiagnotic` flushes all the diagnostics (at one time) when it 
destructs, so we need to adjust the sequence of `SARIFDiagnosticPrinter` in 
order that the `Writer-&gt;endRun()` happens **after** the `SARIFDiagnostic` 
flushes.

### `clang/include/clang/Basic/DiagnosticDriverKinds.td`, 
`clang/lib/Driver/ToolChains/Clang.cpp`
- Disable sarif warnings.
  - Currently the `-Wsarif-format-unstable` warning happens **before** the 
`SARIFDiagnostic` works, This warning message will not appear in the `json` 
output, instead, it triggers in text-mode before the json output. To make the 
`clang++` output machine-parsable, let's remove this warning (or move this 
warning into the json).

  - In my perspective, after many efforts, now the sarif mode seems ok to be 
used. Let's remove the `-Wsarif-format-unstable` warning.

### `clang/unittests/Basic/SarifTest.cpp`
- Update test.
  - Update these corresponding test for `SARIFDiagnostic` and the 
`relatedLocations` (with child results).


---

Patch is 31.78 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/174106.diff


8 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (-4) 
- (modified) clang/include/clang/Basic/Sarif.h (+42-1) 
- (modified) clang/include/clang/Frontend/SARIFDiagnostic.h (+64-25) 
- (modified) clang/lib/Basic/Sarif.cpp (+16-2) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (-3) 
- (modified) clang/lib/Frontend/SARIFDiagnostic.cpp (+194-120) 
- (modified) clang/lib/Frontend/SARIFDiagnosticPrinter.cpp (+2-2) 
- (modified) clang/unittests/Basic/SarifTest.cpp (+9-3) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 5cae8fb86347f..b0a31905c1930 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -851,10 +851,6 @@ def err_drv_invalid_empty_dxil_validator_version : Error<
   "invalid validator version : %0; if validator major version is 0, minor "
   "version must also be 0">;
 
-def warn_drv_sarif_format_unstable : Warning<
-  "diagnostic formatting in SARIF mode is currently unstable">,
-  InGroup<DiagGroup<"sarif-format-unstable">>;
-
 def warn_drv_loongarch_conflicting_implied_val : Warning<
   "ignoring '%0' as it conflicts with that implied by '%1' (%2)">,
   InGroup<OptionIgnored>;
diff --git a/clang/include/clang/Basic/Sarif.h 
b/clang/include/clang/Basic/Sarif.h
index 6f82d253876d9..56080f69a3a1d 100644
--- a/clang/include/clang/Basic/Sarif.h
+++ b/clang/include/clang/Basic/Sarif.h
@@ -295,6 +295,42 @@ class SarifRule {
   }
 };
 
+/// A SARIF child-result is
+/// - logically, a sub-result (e.g. note) belonging to a SARIF result (e.g. 
error, warning)
+/// - physically, a RelatedLocation in a SARIF result (same level as "in file 
included from..." locations)
+class SarifChildResult {
+  friend class clang::SarifDocumentWriter;
+
+  std::string DiagnosticMessage;
+  llvm::SmallVector<CharSourceRange> Locations;
+  int Nesting;
+  std::optional<SarifResultLevel> LevelOverride;
+
+public:
+  static SarifChildResult create() { return SarifChildResult(); }
+
+  SarifChildResult setDiagnosticMessage(llvm::StringRef Message) {
+    DiagnosticMessage = Message.str();
+    return *this;
+  }
+
+  SarifChildResult addLocations(llvm::ArrayRef<CharSourceRange> DiagLocs) {
+#ifndef NDEBUG
+    for (const auto &Loc : DiagLocs) {
+      assert(Loc.isCharRange() &&
+             "SARIF Child Results require character granular source ranges!");
+    }
+#endif
+    Locations.append(DiagLocs.begin(), DiagLocs.end());
+    return *this;
+  }
+
+  SarifChildResult setNesting(int Nest) {
+    Nesting = Nest;
+    return *this;
+  }
+};
+
 /// A SARIF result (also called a "reporting item") is a unit of output
 /// produced when one of the tool's \c reportingDescriptor encounters a match
 /// on the file being analysed by the tool.
@@ -325,7 +361,7 @@ class SarifResult {
   std::string HostedViewerURI;
   llvm::SmallDenseMap<StringRef, std::string, 4> PartialFingerprints;
   llvm::SmallVector<CharSourceRange, 8> Locations;
-  llvm::SmallVector<CharSourceRange, 8> RelatedLocations;
+  llvm::SmallVector<std::variant<SarifChildResult, CharSourceRange>, 8> 
RelatedLocations; // A RelatedLocation is either a ChildResult or a plain "in 
file included from..." Location.
   llvm::SmallVector<ThreadFlow, 8> ThreadFlows;
   std::optional<SarifResultLevel> LevelOverride;
 
@@ -378,6 +414,11 @@ class SarifResult {
     return *this;
   }
 
+  SarifResult addRelatedLocations(llvm::ArrayRef<SarifChildResult> 
ChildResults) {
+    RelatedLocations.append(ChildResults.begin(), ChildResults.end());
+    return *this;
+  }
+
   SarifResult setThreadFlows(llvm::ArrayRef<ThreadFlow> ThreadFlowResults) {
     ThreadFlows.assign(ThreadFlowResults.begin(), ThreadFlowResults.end());
     return *this;
diff --git a/clang/include/clang/Frontend/SARIFDiagnostic.h 
b/clang/include/clang/Frontend/SARIFDiagnostic.h
index 7a6f27eb3b9fa..70b5c80b68812 100644
--- a/clang/include/clang/Frontend/SARIFDiagnostic.h
+++ b/clang/include/clang/Frontend/SARIFDiagnostic.h
@@ -14,9 +14,13 @@
 #ifndef LLVM_CLANG_FRONTEND_SARIFDIAGNOSTIC_H
 #define LLVM_CLANG_FRONTEND_SARIFDIAGNOSTIC_H
 
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/Sarif.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Frontend/DiagnosticRenderer.h"
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
 
 namespace clang {
 
@@ -25,7 +29,7 @@ class SARIFDiagnostic : public DiagnosticRenderer {
   SARIFDiagnostic(raw_ostream &OS, const LangOptions &LangOpts,
                   DiagnosticOptions &DiagOpts, SarifDocumentWriter *Writer);
 
-  ~SARIFDiagnostic() = default;
+  ~SARIFDiagnostic();
 
   SARIFDiagnostic &operator=(const SARIFDiagnostic &&) = delete;
   SARIFDiagnostic(SARIFDiagnostic &&) = delete;
@@ -36,7 +40,7 @@ class SARIFDiagnostic : public DiagnosticRenderer {
   void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
                              DiagnosticsEngine::Level Level, StringRef Message,
                              ArrayRef<CharSourceRange> Ranges,
-                             DiagOrStoredDiag D) override;
+                             DiagOrStoredDiag Diag) override;
 
   void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
                          DiagnosticsEngine::Level Level,
@@ -55,28 +59,63 @@ class SARIFDiagnostic : public DiagnosticRenderer {
                                   StringRef ModuleName) override;
 
 private:
-  // Shared between SARIFDiagnosticPrinter and this renderer.
-  SarifDocumentWriter *Writer;
-
-  SarifResult addLocationToResult(SarifResult Result, FullSourceLoc Loc,
-                                  PresumedLoc PLoc,
-                                  ArrayRef<CharSourceRange> Ranges,
-                                  const Diagnostic &Diag);
-
-  SarifResult addRelatedLocationToResult(SarifResult Result, FullSourceLoc Loc,
-                                         PresumedLoc PLoc);
-
-  llvm::SmallVector<CharSourceRange>
-  getSarifLocation(FullSourceLoc Loc, PresumedLoc PLoc,
-                   ArrayRef<CharSourceRange> Ranges);
-
-  SarifRule addDiagnosticLevelToRule(SarifRule Rule,
-                                     DiagnosticsEngine::Level Level);
-
-  llvm::StringRef emitFilename(StringRef Filename, const SourceManager &SM);
-
-  llvm::SmallVector<std::pair<FullSourceLoc, PresumedLoc>>
-      RelatedLocationsCache;
+  class Node {
+    public:
+      // Subclasses
+      struct Result {
+        DiagnosticsEngine::Level Level;
+        std::string Message;
+        DiagOrStoredDiag Diag;
+      };
+
+      struct Option {
+        const LangOptions* LangOptsPtr;
+        const DiagnosticOptions* DiagnosticOptsPtr;
+      };
+
+      struct Location {
+        FullSourceLoc Loc;
+        PresumedLoc PLoc;
+        llvm::SmallVector<CharSourceRange> Ranges;
+
+        // Methods to construct a llvm-style location.
+        llvm::SmallVector<CharSourceRange> 
getCharSourceRangesWithOption(Option);
+      };
+
+      // Constructor
+      Node(Result Result_, Option Option_, int Nesting);
+
+      // Operations on building a node-tree. 
+      // Arguments and results are all in node-style.
+      Node& getParent(); 
+      Node& getForkableParent();
+      llvm::SmallVector<std::unique_ptr<Node>>& getChildrenPtrs();   
+      Node& addChildResult(Result);
+      Node& addLocation(Location);
+      Node& addRelatedLocation(Location);
+
+      // Methods to access underlying data for other llvm-components to read 
from it.
+      // Arguments and results are all in llvm-style.
+      unsigned getDiagID();
+      DiagnosticsEngine::Level getLevel();
+      std::string getDiagnosticMessage();
+      llvm::SmallVector<CharSourceRange> getLocations();
+      llvm::SmallVector<CharSourceRange> getRelatedLocations();
+      int getNesting();
+
+    private:
+      Result Result_;
+      llvm::SmallVector<Location> Locations;
+      llvm::SmallVector<Location> RelatedLocations;
+      Option Option_;
+      int Nesting;
+      Node* ParentPtr = nullptr;
+      llvm::SmallVector<std::unique_ptr<Node>> ChildrenPtrs = {};
+  };
+
+  Node Root;
+  Node* Current = &Root;
+  SarifDocumentWriter *Writer; // Shared between SARIFDiagnosticPrinter and 
this renderer.
 };
 
 } // end namespace clang
diff --git a/clang/lib/Basic/Sarif.cpp b/clang/lib/Basic/Sarif.cpp
index 448de96d474af..1da7c6731d650 100644
--- a/clang/lib/Basic/Sarif.cpp
+++ b/clang/lib/Basic/Sarif.cpp
@@ -406,8 +406,22 @@ void SarifDocumentWriter::appendResult(const SarifResult 
&Result) {
 
   if (!Result.RelatedLocations.empty()) {
     json::Array ReLocs;
-    for (auto &Range : Result.RelatedLocations) {
-      ReLocs.emplace_back(createLocation(createPhysicalLocation(Range)));
+    for (auto &RelatedLocation : Result.RelatedLocations) {
+      if (RelatedLocation.index() == 0) { // variant is a SarifChildResult
+        const SarifChildResult& ChildResult = std::get<0>(RelatedLocation);
+        json::Object Object;
+        Object.insert({"message", 
createMessage(ChildResult.DiagnosticMessage)});
+        if (ChildResult.Locations.size() >= 1)
+          for (auto& kv : 
createLocation(createPhysicalLocation(ChildResult.Locations[0])))
+            Object.insert({kv.getFirst(), kv.getSecond()});
+        Object.insert({
+          "properties", json::Object{{"nestingLevel", ChildResult.Nesting}}
+        });
+        ReLocs.emplace_back(std::move(Object));
+      } else { // variant is a CharSourceRange
+        const CharSourceRange& Range = std::get<1>(RelatedLocation);
+        ReLocs.emplace_back(createLocation(createPhysicalLocation(Range)));
+      }
     }
     Ret["relatedLocations"] = std::move(ReLocs);
   }
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 310f3b58a211e..38bcc12171143 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4230,9 +4230,6 @@ static void RenderDiagnosticsOptions(const Driver &D, 
const ArgList &Args,
   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")
-      D.Diag(diag::warn_drv_sarif_format_unstable);
   }
 
   if (const Arg *A = Args.getLastArg(
diff --git a/clang/lib/Frontend/SARIFDiagnostic.cpp 
b/clang/lib/Frontend/SARIFDiagnostic.cpp
index 2cd32ce97ea85..930d1b1383ddb 100644
--- a/clang/lib/Frontend/SARIFDiagnostic.cpp
+++ b/clang/lib/Frontend/SARIFDiagnostic.cpp
@@ -7,108 +7,210 @@
 
//===----------------------------------------------------------------------===//
 
 #include "clang/Frontend/SARIFDiagnostic.h"
-#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/FileManager.h"
+#include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/Sarif.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/Locale.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <string>
 
 namespace clang {
 
+// In sarif mode, 
+// a diagnostics 'group' have 1 top-level error/warning and several sub-level 
notes.
+// For example:
+//
+// error: static assertion failed.
+//   note: in instantiation of 'cat::meow'.
+//     note: because concept 'paper_tiger' would be invalid.
+// error: invalid operands to binary expression 'cat::meow' and 'dog::wolf'.
+//   note: candidate function not viable.
+//     note: no known conversion from 'tiger::meooooow' to 'cat::meow'
+//   note: candidate function ignored.
+//     note: constraints not satisfied.
+//   note: ... (candidates)
+//     note: ... (reasons)
+//   note: too many candidates.
+// error: too many errors occured, stopping now.
+
 SARIFDiagnostic::SARIFDiagnostic(raw_ostream &OS, const LangOptions &LangOpts,
                                  DiagnosticOptions &DiagOpts,
                                  SarifDocumentWriter *Writer)
-    : DiagnosticRenderer(LangOpts, DiagOpts), Writer(Writer) {}
+    : DiagnosticRenderer(LangOpts, DiagOpts), 
+      Root(Node::Result(), Node::Option{&LangOpts, &DiagOpts}, 
/*Nesting=*/-1), // The root does not represents a diagnostic.
+      Current(&Root),
+      Writer(Writer) 
+{
+  // Don't print 'X warnings and Y errors generated'.
+  DiagOpts.ShowCarets = false;
+}
+
+// helper function
+namespace {
+  template <class NodeType, class IterateFuncType, class ApplyFuncType>
+  void RecursiveFor (NodeType&& Node, IterateFuncType&& IterateFunc, 
ApplyFuncType&& ApplyFunc) {
+    for (auto&& Child : IterateFunc(Node)) {
+      ApplyFunc(*Child);
+      RecursiveFor(*Child, IterateFunc, ApplyFunc);
+    }
+  }
+} // namespace
+
+SARIFDiagnostic::~SARIFDiagnostic() {
+  // clang-format off
+  for (auto& TopLevelDiagnosticsPtr : Root.getChildrenPtrs()) { // For each 
top-level error/warnings.
+    unsigned DiagID = TopLevelDiagnosticsPtr->getDiagID();
+    SarifRule Rule = SarifRule::create() // Each top-level error/warning has a 
corresponding Rule.
+      .setRuleId(std::to_string(DiagID))
+      .setDefaultConfiguration(
+        SarifReportingConfiguration::create()
+          .setLevel(
+            TopLevelDiagnosticsPtr->getLevel() == 
DiagnosticsEngine::Level::Note    ? SarifResultLevel::Note :
+            TopLevelDiagnosticsPtr->getLevel() == 
DiagnosticsEngine::Level::Remark  ? SarifResultLevel::Note :
+            TopLevelDiagnosticsPtr->getLevel() == 
DiagnosticsEngine::Level::Warning ? SarifResultLevel::Warning :
+            TopLevelDiagnosticsPtr->getLevel() == 
DiagnosticsEngine::Level::Error   ? SarifResultLevel::Error :
+            TopLevelDiagnosticsPtr->getLevel() == 
DiagnosticsEngine::Level::Fatal   ? SarifResultLevel::Error :
+                                         (assert(false && "Invalid diagnostic 
type"), SarifResultLevel::None)
+          )
+          .setRank(
+            TopLevelDiagnosticsPtr->getLevel() <= 
DiagnosticsEngine::Level::Warning ? 0  :
+            TopLevelDiagnosticsPtr->getLevel() == 
DiagnosticsEngine::Level::Error   ? 50 :
+            TopLevelDiagnosticsPtr->getLevel() == 
DiagnosticsEngine::Level::Fatal   ? 100 :
+                                         (assert(false && "Invalid diagnostic 
type"), 0)
+          )
+      );
+    unsigned RuleIndex = Writer->createRule(Rule); // Write into Writer.
+
+    SarifResult Result = SarifResult::create(RuleIndex)
+      .setDiagnosticMessage(TopLevelDiagnosticsPtr->getDiagnosticMessage())
+      .addLocations(TopLevelDiagnosticsPtr->getLocations())
+      .addRelatedLocations(TopLevelDiagnosticsPtr->getRelatedLocations());
+    RecursiveFor(*TopLevelDiagnosticsPtr, [] (Node& Node) -> auto& { return 
Node.getChildrenPtrs(); }, [&] (Node& Node) { // For each (recursive) 
ChildResults.
+      Result.addRelatedLocations({
+        SarifChildResult::create()
+          .setDiagnosticMessage(Node.getDiagnosticMessage())
+          .addLocations(Node.getLocations())
+          .setNesting(Node.getNesting())
+      });
+      Result.addRelatedLocations(Node.getRelatedLocations());
+    });
+    Writer->appendResult(Result); // Write into Writer
+  }
+  // clang-format on
+}
 
-// FIXME(llvm-project/issues/57323): Refactor Diagnostic classes.
 void SARIFDiagnostic::emitDiagnosticMessage(
     FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level,
     StringRef Message, ArrayRef<clang::CharSourceRange> Ranges,
-    DiagOrStoredDiag D) {
+    DiagOrStoredDiag Diag) {
 
-  const auto *Diag = D.dyn_cast<const Diagnostic *>();
+  if (Level >= DiagnosticsEngine::Level::Warning) {
+    Current = &Root; // If this is a top-level error/warning, repoint Current 
to Root.
+  } else {
+    if (Message.starts_with("candidate"))
+      Current = &Current->getForkableParent(); // If this is an forked-case 
note, repoint Current to the nearest forkable Node.
+  }
+  Current = &Current->addChildResult(Node::Result{Level, std::string(Message), 
Diag}); // add child to the parent error/warning/note Node.
+  Current = &Current->addLocation(Node::Location{Loc, PLoc, 
llvm::SmallVector<CharSourceRange>(Ranges)});
+}
 
-  if (!Diag)
-    return;
+void SARIFDiagnostic::emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) 
{
+  Current = &Current->addRelatedLocation(Node::Location{Loc, PLoc, {}});
+}
 
-  SarifRule Rule = 
SarifRule::create().setRuleId(std::to_string(Diag->getID()));
+void SARIFDiagnostic::emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, 
StringRef ModuleName) {
+  Current = &Current->addRelatedLocation(Node::Location{Loc, PLoc, {}});
+}
 
-  Rule = addDiagnosticLevelToRule(Rule, Level);
+SARIFDiagnostic::Node::Node(Result Result_, Option Option_, int Nesting)
+  : Result_(std::move(Result_)), Option_(std::move(Option_)), Nesting(Nesting) 
{}
 
-  unsigned RuleIdx = Writer->createRule(Rule);
+SARIFDiagnostic::Node& SARIFDiagnostic::Node::getParent() {
+  assert(ParentPtr && "getParent() of SARIFDiagnostic::Root!");
+  return *ParentPtr;
+}
 
-  SarifResult Result =
-      SarifResult::create(RuleIdx).setDiagnosticMessage(Message);
+SARIFDiagnostic::Node& SARIFDiagnostic::Node::getForkableParent() {
+  Node* Ptr = this;
+  while (Ptr->getLevel() <= DiagnosticsEngine::Note) // The forkable node here 
"is and only is" warning/error/fatal.
+    Ptr = &Ptr->getParent();
+  return *Ptr;
+}
 
-  if (Loc.isValid())
-    Result = addLocationToResult(Result, Loc, PLoc, Ranges, *Diag);
+llvm::SmallVector<std::unique_ptr<SARIFDiagnostic::Node>>& 
SARIFDiagnostic::Node::getChildrenPtrs() {
+  return ChildrenPtrs;
+}
 
-  for (auto &[RelLoc, RelPLoc] : RelatedLocationsCache)
-    Result = addRelatedLocationToResult(Result, RelLoc, RelPLoc);
-  RelatedLocationsCache.clear();
+SARIFDiagnostic::Node& SARIFDiagnostic::Node::addChildResult(Result 
ChildResult) {
+  
ChildrenPtrs.push_back(std::make_unique<Node>(Node::Result(std::move(ChildResult)),
 Node::Option(std::move(Option_)), Nesting + 1));
+  ChildrenPtrs.back()->ParentPtr = this; // I am the parent of this new child.
+  return *ChildrenPtrs.back();
+}
 
-  Writer->appendResult(Result);
+SARIFDiagnostic::Node& SARIFDiagnostic::Node::addLocation(Location Location) {
+  Locations.push_back(std::move(Location));
+  return *this;
 }
 
-void SARIFDiagnostic::emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) 
{
-  // We always emit include location before results, for example:
-  //
-  // In file included from ...
-  // In file included from ...
-  // error: ...
-  //
-  // At this time We cannot peek the SarifRule. But what we
-  // do is to push it into a cache and wait for next time
-  // \ref SARIFDiagnostic::emitDiagnosticMessage to pick it up.
-  RelatedLocationsCache.push_back({Loc, PLoc});
+SARIFDiagnostic::Node& SARIFDiagnostic::Node::addRelatedLocation(Location 
Location) {
+  RelatedLocations.push_back(std::move(Location));
+  return *this;
 }
 
-void SARIFDiagnostic::emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
-                                         StringRef ModuleName) {
-  RelatedLocationsCache.push_back({Loc, PLoc});
+unsigned SARIFDiagnostic::Node::getDiagID() {
+  return llvm::isa<const Diagnostic*>(Result_.Diag) ? 
+    Result_.Diag.dyn_cast<const Diagnostic*>()->getID() :
+    Result_.Diag.dyn_cast<const StoredDiagnostic*>()->getID();
 }
 
-SarifResult SARIFDiagnostic::addLocationToResult(
-    SarifResult Result, FullSourceLoc Loc, PresumedLoc PLoc,
-    ArrayRef<CharSourceRange> Ranges, const Diagnostic &Diag) {
-  auto Locations = getSarifLocation(Loc, PLoc, Ranges);
-  return Result.addLocations(Locations);
+DiagnosticsEngine::Level SARIFDiagnostic::Node::getLevel() {
+  return Result_.Level;
 }
 
-SarifResult SARIFDiagnostic::addRelatedLocationToResult(SarifResult Result,
-                                                        FullSourceLoc Loc,
-                                                        PresumedLoc PLoc) {
-  auto Locations = getSarifLocation(Loc, PLoc, {});
-  return Result.addRelatedLocations(Locations);
+std::string SARIFDiagnostic::Node::getDiagnosticMessage() {
+  return Result_.Message;
 }
 
-llvm::SmallVector<CharSourceRange>
-SARIFDiagnostic::getSarifLocation(FullSourceLoc Loc, PresumedLoc PLoc,
-                                  ArrayRef<CharSourceRange> Ranges) {
-  SmallVector<CharSourceRange> Locations = {};
+llvm::SmallVector<CharSourceRan...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/174106
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to