diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc
index 2000db972d68f93bcbd572fdb04f05f9eb975552..3ff3aea6a8671975b5dbf7578c64a9c73b625056 100644
--- a/gcc/analyzer/checker-event.cc
+++ b/gcc/analyzer/checker-event.cc
@@ -55,6 +55,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "analyzer/constraint-manager.h"
 #include "analyzer/checker-event.h"
 #include "analyzer/exploded-graph.h"
+#include "diagnostic-format-sarif.h"
+#include "tree-logical-location.h"
 
 #if ENABLE_ANALYZER
 
@@ -142,6 +144,30 @@ checker_event::get_meaning () const
   return meaning ();
 }
 
+/* Implementation of diagnostic_event::maybe_add_sarif_properties
+   for checker_event.  */
+
+void
+checker_event::
+maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) const
+{
+  sarif_property_bag &props = thread_flow_loc_obj.get_or_create_properties ();
+#define PROPERTY_PREFIX "gcc/analyzer/checker_event/"
+  props.set (PROPERTY_PREFIX "emission_id",
+	     diagnostic_event_id_to_json  (m_emission_id));
+  props.set_string (PROPERTY_PREFIX "kind", event_kind_to_string (m_kind));
+
+  if (m_original_fndecl != m_effective_fndecl)
+    {
+      tree_logical_location logical_loc (m_original_fndecl);
+      props.set (PROPERTY_PREFIX "original_fndecl",
+		 make_sarif_logical_location_object (logical_loc));
+    }
+  if (m_original_depth != m_effective_depth)
+    props.set_integer (PROPERTY_PREFIX "original_depth", m_original_depth);
+#undef PROPERTY_PREFIX
+}
+
 /* Dump this event to PP (for debugging/logging purposes).  */
 
 void
@@ -498,6 +524,21 @@ state_change_event::get_meaning () const
 
 /* class superedge_event : public checker_event.  */
 
+/* Implementation of diagnostic_event::maybe_add_sarif_properties
+   for superedge_event.  */
+
+void
+superedge_event::maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj)
+  const
+{
+  checker_event::maybe_add_sarif_properties (thread_flow_loc_obj);
+  sarif_property_bag &props = thread_flow_loc_obj.get_or_create_properties ();
+#define PROPERTY_PREFIX "gcc/analyzer/superedge_event/"
+  if (m_sedge)
+    props.set (PROPERTY_PREFIX "superedge", m_sedge->to_json ());
+#undef PROPERTY_PREFIX
+}
+
 /* Get the callgraph_superedge for this superedge_event, which must be
    for an interprocedural edge, rather than a CFG edge.  */
 
@@ -548,6 +589,8 @@ superedge_event::superedge_event (enum event_kind kind,
   m_eedge (eedge), m_sedge (eedge.m_sedge),
   m_var (NULL_TREE), m_critical_state (0)
 {
+  /* Note that m_sedge can be nullptr for e.g. jumps through
+     function pointers.  */
 }
 
 /* class cfg_edge_event : public superedge_event.  */
diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index 01300ef84a014da18bbe9751c330124aa1617409..7d8915c8e53013112905af67a7cbc90ea5f93923 100644
--- a/gcc/analyzer/checker-event.h
+++ b/gcc/analyzer/checker-event.h
@@ -118,6 +118,9 @@ public:
     return 0;
   }
 
+  void
+  maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) const override;
+
   /* Additional functionality.  */
 
   int get_original_stack_depth () const { return m_original_depth; }
@@ -391,6 +394,9 @@ public:
 class superedge_event : public checker_event
 {
 public:
+  void maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj)
+    const override;
+
   /* Mark this edge event as being either an interprocedural call or
      return in which VAR is in STATE, and that this is critical to the
      diagnostic (so that get_desc can attempt to get a better description
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 161a6b76b330641b79e9c7c06133f2328e5da4aa..307b2f56c2801053a898960d5011b44e75a3cebb 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -184,8 +184,6 @@ private:
   void set_any_logical_locs_arr (json::object *location_obj,
 				 const logical_location *logical_loc);
   json::object *make_location_object (const diagnostic_event &event);
-  json::object *
-  make_logical_location_object (const logical_location &logical_loc) const;
   json::object *make_code_flow_object (const diagnostic_path &path);
   json::object *
   make_thread_flow_location_object (const diagnostic_event &event,
@@ -754,7 +752,7 @@ set_any_logical_locs_arr (json::object *location_obj,
 {
   if (!logical_loc)
     return;
-  json::object *logical_loc_obj = make_logical_location_object (*logical_loc);
+  json::object *logical_loc_obj = make_sarif_logical_location_object (*logical_loc);
   json::array *location_locs_arr = new json::array ();
   location_locs_arr->append (logical_loc_obj);
   location_obj->set ("logicalLocations", location_locs_arr);
@@ -1092,8 +1090,7 @@ maybe_get_sarif_kind (enum logical_location_kind kind)
    or return NULL.  */
 
 json::object *
-sarif_builder::
-make_logical_location_object (const logical_location &logical_loc) const
+make_sarif_logical_location_object (const logical_location &logical_loc)
 {
   json::object *logical_loc_obj = new json::object ();
 
@@ -1163,7 +1160,11 @@ json::object *
 sarif_builder::make_thread_flow_location_object (const diagnostic_event &ev,
 						 int path_event_idx)
 {
-  json::object *thread_flow_loc_obj = new json::object ();
+  sarif_object *thread_flow_loc_obj = new sarif_object ();
+
+  /* Give diagnostic_event subclasses a chance to add custom properties
+     via a property bag.  */
+  ev.maybe_add_sarif_properties (*thread_flow_loc_obj);
 
   /* "location" property (SARIF v2.1.0 section 3.38.3).  */
   json::object *location_obj = make_location_object (ev);
diff --git a/gcc/diagnostic-format-sarif.h b/gcc/diagnostic-format-sarif.h
index 1ee49d4c3021d161cec2572b4fa6445b7da177be..fdbbd93de7a74faf2b035675857555b7b65fb2de 100644
--- a/gcc/diagnostic-format-sarif.h
+++ b/gcc/diagnostic-format-sarif.h
@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "json.h"
 
+class logical_location;
+
 /* Concrete subclass of json::object for SARIF property bags
    (SARIF v2.1.0 section 3.8).  */
 
@@ -42,4 +44,7 @@ public:
   sarif_property_bag &get_or_create_properties ();
 };
 
+extern json::object *
+make_sarif_logical_location_object (const logical_location &logical_loc);
+
 #endif /* ! GCC_DIAGNOSTIC_FORMAT_SARIF_H */
diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index 7f271ef3f926697dea9e6d266c29a183b3076890..fb7abe88ed32714180b3629cc6bb0269212c64b2 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -24,6 +24,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h" /* for ATTRIBUTE_GCC_DIAG.  */
 #include "diagnostic-event-id.h"
 
+class sarif_object;
+
 /* A diagnostic_path is an optional additional piece of metadata associated
    with a diagnostic (via its rich_location).
 
@@ -157,6 +159,13 @@ class diagnostic_event
   virtual meaning get_meaning () const = 0;
 
   virtual diagnostic_thread_id_t get_thread_id () const = 0;
+
+  /* Hook for SARIF output to allow for adding diagnostic-specific
+     properties to the threadFlowLocation object's property bag.  */
+  virtual void
+  maybe_add_sarif_properties (sarif_object &/*thread_flow_loc_obj*/) const
+  {
+  }
 };
 
 /* Abstract base class representing a thread of execution within