diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc
index 5091fb7a583..b27d8e359db 100644
--- a/gcc/analyzer/analyzer.cc
+++ b/gcc/analyzer/analyzer.cc
@@ -274,7 +274,7 @@ is_named_call_p (const_tree fndecl, const char
*funcname)
    Compare with cp/typeck.cc: decl_in_std_namespace_p, but this doesn't
    rely on being the C++ FE (or handle inline namespaces inside of std).
 */

-static inline bool
+bool
 is_std_function_p (const_tree fndecl)
 {
   tree name_decl = DECL_NAME (fndecl);
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index 579517c23e6..31597079153 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -386,6 +386,7 @@ extern bool is_special_named_call_p (const gcall *call,
const char *funcname,
 extern bool is_named_call_p (const_tree fndecl, const char *funcname);
 extern bool is_named_call_p (const_tree fndecl, const char *funcname,
      const gcall *call, unsigned int num_args);
+extern bool is_std_function_p (const_tree fndecl);
 extern bool is_std_named_call_p (const_tree fndecl, const char *funcname);
 extern bool is_std_named_call_p (const_tree fndecl, const char *funcname,
  const gcall *call, unsigned int num_args);
diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index 2760aaa8151..78ff2c07483 100644
--- a/gcc/analyzer/analyzer.opt
+++ b/gcc/analyzer/analyzer.opt
@@ -362,4 +362,8 @@ fdump-analyzer-untracked
 Common RejectNegative Var(flag_dump_analyzer_untracked)
 Emit custom warnings with internal details intended for analyzer
developers.

+fanalyzer-trim-diagnostics=
+Common Joined RejectNegative ToLower Var(flag_analyzer_trim_diagnostics)
Init("system")
+-fanalyzer-trim-diagnostics=[never|system|<maxdepth>] Trim diagnostics
path that are too long before emission.
+
 ; This comment is to ensure we retain the blank line above.
diff --git a/gcc/analyzer/diagnostic-manager.cc
b/gcc/analyzer/diagnostic-manager.cc
index cfca305d552..d946ad5bac7 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -20,9 +20,11 @@ along with GCC; see the file COPYING3.  If not see

 #include "config.h"
 #define INCLUDE_MEMORY
+#define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
 #include "tree.h"
+#include "input.h"
 #include "pretty-print.h"
 #include "gcc-rich-location.h"
 #include "gimple-pretty-print.h"
@@ -60,6 +62,37 @@ along with GCC; see the file COPYING3.  If not see

 #if ENABLE_ANALYZER

+/* Return positive value of fanalyzer-trim-diagnostics if a depth was given
+  or a negative value otherwise.  */
+
+long trim_diagnostics_depth ()
+{
+  if (trim_diagnostics_system_p () ||  trim_diagnostics_never_p ())
+    return -1;
+
+  char *end = NULL;
+  long depth = strtol (flag_analyzer_trim_diagnostics, &end, 10);
+  gcc_assert (end == NULL || *end == '\0');
+  gcc_assert (!(end == flag_analyzer_trim_diagnostics && depth == 0));
+  return depth;
+}
+
+/* Return true if fanalyzer-trim-diagnostics is set to "system".  */
+
+bool trim_diagnostics_system_p ()
+{
+  int len = strlen (flag_analyzer_trim_diagnostics);
+  return len == 6 && strcmp (flag_analyzer_trim_diagnostics, "system") ==
0;
+}
+
+/* Return true if fanalyzer-trim-diagnostics is set to "never".  */
+
+bool trim_diagnostics_never_p ()
+{
+  int len = strlen (flag_analyzer_trim_diagnostics);
+  return len == 5 && strcmp (flag_analyzer_trim_diagnostics, "never") == 0;
+}
+
 namespace ana {

 class feasible_worklist;
@@ -2281,6 +2314,8 @@ diagnostic_manager::prune_path (checker_path *path,
   path->maybe_log (get_logger (), "path");
   prune_for_sm_diagnostic (path, sm, sval, state);
   prune_interproc_events (path);
+  if (! trim_diagnostics_never_p ())
+    trim_diagnostic_path (path);
   consolidate_conditions (path);
   finish_pruning (path);
   path->maybe_log (get_logger (), "pruned");
@@ -2667,6 +2702,103 @@ diagnostic_manager::prune_interproc_events
(checker_path *path) const
   while (changed);
 }

+void
+diagnostic_manager::trim_diagnostic_path (checker_path *path) const
+{
+  if (trim_diagnostics_system_p ())
+    prune_system_headers (path);
+  else
+    prune_events_too_deep (path);
+}
+
+/* Remove everything within ]callsite, IDX].  */
+static void
+prune_within_frame (checker_path *path, int &idx)
+{
+  int nesting = 1;
+  while (idx >= 0 && nesting != 0)
+    {
+      if (path->get_checker_event (idx)->is_call_p ())
+        nesting--;
+      else if (path->get_checker_event (idx)->is_return_p ())
+        nesting++;
+
+      path->delete_event (idx--);
+    }
+}
+
+void
+diagnostic_manager::prune_system_headers (checker_path *path) const
+{
+  int idx = (signed)path->num_events () - 1;
+  while (idx >= 0)
+    {
+      const checker_event *event = path->get_checker_event (idx);
+      /* Prune everything between [..., system call, (...), system return,
...].  */
+      if (event->is_return_p ()
+          && in_system_header_at (event->get_location ()))
+      {
+        int ret_idx = idx;
+        prune_within_frame (path, idx);
+
+        if (get_logger ())
+        {
+          label_text desc
+            (path->get_checker_event (idx)->get_desc (false));
+          log ("filtering event %i-%i:"
+              " system header event: %s",
+              idx, ret_idx, desc.get ());
+        }
+        // delete callsite
+        if (idx >= 0)
+          path->delete_event (idx);
+      }
+
+      idx--;
+    }
+}
+
+void
+diagnostic_manager::prune_events_too_deep (checker_path *path) const
+{
+  long depth = 0;
+  long maxdepth = trim_diagnostics_depth ();
+  gcc_assert (maxdepth >= 0);
+  int idx = (signed)path->num_events () - 1;
+  if (idx >= 0)
+  {
+    depth = path->get_checker_event (0)->get_stack_depth ();
+    maxdepth += depth;
+  }
+
+  while (idx >= 0)
+    {
+      const checker_event *event = path->get_checker_event (idx);
+      /* Prune everything between [..., call too deep, (...), return too
deep, ...].  */
+      if (event->is_return_p ()
+          && event->get_stack_depth () > maxdepth)
+      {
+        int ret_idx = idx;
+        prune_within_frame (path, idx);
+
+        if (get_logger ())
+        {
+          label_text desc
+            (path->get_checker_event (idx)->get_desc (false));
+          log ("filtering event %i-%i:"
+              " event too deep: %s",
+              idx, ret_idx, desc.get ());
+        }
+        // delete callsite
+        if (idx >= 0)
+          path->delete_event (idx);
+      }
+
+      idx--;
+    }
+
+}
+
 /* Return true iff event IDX within PATH is on the same line as
REF_EXP_LOC.  */

 static bool
diff --git a/gcc/analyzer/diagnostic-manager.h
b/gcc/analyzer/diagnostic-manager.h
index 9b3e903fc5d..9afef0975be 100644
--- a/gcc/analyzer/diagnostic-manager.h
+++ b/gcc/analyzer/diagnostic-manager.h
@@ -21,6 +21,10 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
 #define GCC_ANALYZER_DIAGNOSTIC_MANAGER_H

+long trim_diagnostics_depth ();
+bool trim_diagnostics_system_p ();
+bool trim_diagnostics_never_p ();
+
 namespace ana {

 class epath_finder;
@@ -180,6 +184,9 @@ private:
  state_machine::state_t state) const;
   void update_for_unsuitable_sm_exprs (tree *expr) const;
   void prune_interproc_events (checker_path *path) const;
+  void trim_diagnostic_path (checker_path *path) const;
+  void prune_system_headers (checker_path *path) const;
+  void prune_events_too_deep (checker_path *path) const;
   void consolidate_conditions (checker_path *path) const;
   void finish_pruning (checker_path *path) const;

diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-0.C
b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-0.C
new file mode 100644
index 00000000000..ddf39ed1690
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-0.C
@@ -0,0 +1,19 @@
+/* { dg-additional-options "-fdiagnostics-plain-output
-fdiagnostics-path-format=inline-events -fanalyzer-trim-diagnostics=0" } */
+/* { dg-skip-if "" { c++98_only }  } */
+
+#include <memory>
+
+struct A {int x; int y;};
+
+int main () {
+  std::shared_ptr<A> a;
+  a->x = 4; /* { dg-line deref_a } */
+  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */
+
+  return 0;
+}
+/* { dg-begin-multiline-output "" }
+  'int main()': events 1-2
+    |
+    |
+   { dg-end-multiline-output "" } */
\ No newline at end of file
diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-1.C
b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-1.C
new file mode 100644
index 00000000000..83a132078a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-1.C
@@ -0,0 +1,28 @@
+/* { dg-additional-options "-fdiagnostics-plain-output
-fdiagnostics-path-format=inline-events -fanalyzer-trim-diagnostics=1" } */
+/* { dg-skip-if "" { c++98_only }  } */
+
+#include <memory>
+
+struct A {int x; int y;};
+
+int main () {
+  std::shared_ptr<A> a;
+  a->x = 4; /* { dg-line deref_a } */
+  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */
+
+  return 0;
+}
+
+/* { dg-begin-multiline-output "" }
+  'int main()': events 1-2
+    |
+    |
+    +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>, <anonymous>
>::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
_Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool <anonymous> =
false]': event 3
+           |
+           |
+    <------+
+    |
+  'int main()': events 4-5
+    |
+    |
+   { dg-end-multiline-output "" } */
\ No newline at end of file
diff --git a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-2.C
b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-2.C
new file mode 100644
index 00000000000..cf065929ec9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-2.C
@@ -0,0 +1,44 @@
+/* { dg-additional-options "-fdiagnostics-plain-output
-fdiagnostics-path-format=inline-events -fanalyzer-trim-diagnostics=2" } */
+/* { dg-skip-if "" { c++98_only }  } */
+
+#include <memory>
+
+struct A {int x; int y;};
+
+int main () {
+  std::shared_ptr<A> a;
+  a->x = 4; /* { dg-line deref_a } */
+  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */
+
+  return 0;
+}
+
+/* { dg-begin-multiline-output "" }
+  'int main()': events 1-2
+    |
+    |
+    +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>, <anonymous>
>::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
_Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool <anonymous> =
false]': events 3-4
+           |
+           |
+           +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
<anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
__gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool <anonymous> =
false; bool <anonymous> = false]': events 5-6
+                  |
+                  |
+                  +--> 'std::__shared_ptr<_Tp, _Lp>::element_type*
std::__shared_ptr<_Tp, _Lp>::get() const [with _Tp = A;
__gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]': events 7-8
+                         |
+                         |
+                  <------+
+                  |
+                'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
<anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
__gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool <anonymous> =
false; bool <anonymous> = false]': event 9
+                  |
+                  |
+           <------+
+           |
+         'std::__shared_ptr_access<_Tp, _Lp, <anonymous>, <anonymous>
>::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
_Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool <anonymous> =
false]': event 10
+           |
+           |
+    <------+
+    |
+  'int main()': events 11-12
+    |
+    |
+   { dg-end-multiline-output "" } */
\ No newline at end of file
diff --git
a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-default.C
b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-default.C
new file mode 100644
index 00000000000..fc271309d4e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-default.C
@@ -0,0 +1,21 @@
+/* { dg-additional-options "-O0 -fdiagnostics-plain-output
-fdiagnostics-path-format=inline-events" } */
+/* { dg-skip-if "" { c++98_only }  } */
+
+// Must behave like -fanalyzer-trim-diagnostics=system
+
+#include <memory>
+
+struct A {int x; int y;};
+
+int main () {
+  std::shared_ptr<A> a;
+  a->x = 4; /* { dg-line deref_a } */
+  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */
+
+  return 0;
+}
+/* { dg-begin-multiline-output "" }
+  'int main()': events 1-2
+    |
+    |
+   { dg-end-multiline-output "" } */
\ No newline at end of file
diff --git
a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-never.C
b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-never.C
new file mode 100644
index 00000000000..a69416608da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-never.C
@@ -0,0 +1,44 @@
+/* { dg-additional-options "-fdiagnostics-plain-output
-fdiagnostics-path-format=inline-events -fanalyzer-trim-diagnostics=never"
} */
+/* { dg-skip-if "" { c++98_only }  } */
+
+#include <memory>
+
+struct A {int x; int y;};
+
+int main () {
+  std::shared_ptr<A> a;
+  a->x = 4; /* { dg-line deref_a } */
+  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */
+
+  return 0;
+}
+
+/* { dg-begin-multiline-output "" }
+  'int main()': events 1-2
+    |
+    |
+    +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>, <anonymous>
>::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
_Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool <anonymous> =
false]': events 3-4
+           |
+           |
+           +--> 'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
<anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
__gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool <anonymous> =
false; bool <anonymous> = false]': events 5-6
+                  |
+                  |
+                  +--> 'std::__shared_ptr<_Tp, _Lp>::element_type*
std::__shared_ptr<_Tp, _Lp>::get() const [with _Tp = A;
__gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]': events 7-8
+                         |
+                         |
+                  <------+
+                  |
+                'std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::element_type* std::__shared_ptr_access<_Tp, _Lp,
<anonymous>, <anonymous> >::_M_get() const [with _Tp = A;
__gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool <anonymous> =
false; bool <anonymous> = false]': event 9
+                  |
+                  |
+           <------+
+           |
+         'std::__shared_ptr_access<_Tp, _Lp, <anonymous>, <anonymous>
>::element_type* std::__shared_ptr_access<_Tp, _Lp, <anonymous>,
<anonymous> >::operator->() const [with _Tp = A; __gnu_cxx::_Lock_policy
_Lp = __gnu_cxx::_S_atomic; bool <anonymous> = false; bool <anonymous> =
false]': event 10
+           |
+           |
+    <------+
+    |
+  'int main()': events 11-12
+    |
+    |
+   { dg-end-multiline-output "" } */
\ No newline at end of file
diff --git
a/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-system.C
b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-system.C
new file mode 100644
index 00000000000..22fadc84e75
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/fanalyzer-trim-diagnostics-system.C
@@ -0,0 +1,19 @@
+/* { dg-additional-options "-fdiagnostics-plain-output
-fdiagnostics-path-format=inline-events -fanalyzer-trim-diagnostics=system"
} */
+/* { dg-skip-if "" { c++98_only }  } */
+
+#include <memory>
+
+struct A {int x; int y;};
+
+int main () {
+  std::shared_ptr<A> a;
+  a->x = 4; /* { dg-line deref_a } */
+  /* { dg-warning "dereference of NULL" "" { target *-*-* } deref_a } */
+
+  return 0;
+}
+/* { dg-begin-multiline-output "" }
+  'int main()': events 1-2
+    |
+    |
