Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r16-7206-gb5d5cab8e4b807.

gcc/analyzer/ChangeLog:
        PR analyzer/123880
        * engine.cc (throw_custom_edge::update_model): Gracefully handle
        not knowing the current exception in a rethrow.
        (exploded_node::on_throw): Likewise.

gcc/testsuite/ChangeLog:
        PR analyzer/123880
        * g++.dg/analyzer/exception-rethrow-3.C: New test.

Signed-off-by: David Malcolm <[email protected]>
---
 gcc/analyzer/engine.cc                        | 22 +++++++--
 .../g++.dg/analyzer/exception-rethrow-3.C     | 46 +++++++++++++++++++
 2 files changed, 63 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/analyzer/exception-rethrow-3.C

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 2d22abf05303..8dc9a8b78ce3 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -1575,9 +1575,14 @@ public:
   {
     if (m_is_rethrow)
       {
-       auto eh_node = model->get_current_caught_exception ();
-       gcc_assert (eh_node);
-       model->push_thrown_exception (*eh_node);
+       if (auto eh_node = model->get_current_caught_exception ())
+         model->push_thrown_exception (*eh_node);
+       else
+         {
+           /* We have a rethrow of some unknown exception.
+              We don't have a good way of representing this;
+              leave the exception stack empty.  */
+         }
       }
     else
       {
@@ -1811,8 +1816,15 @@ exploded_node::on_throw (exploded_graph &eg,
   if (is_rethrow)
     {
       const exception_node *eh_node = model->get_current_caught_exception ();
-      gcc_assert (eh_node);
-      type = eh_node->maybe_get_type ();
+      if (eh_node)
+       type = eh_node->maybe_get_type ();
+      else
+       {
+         /* We have a "throw;" but no exception to rethrow.
+            Presumably the top-level of the analysis is an
+            entrypoint for handling exceptions, so we will
+            simulate fully unwinding.  */
+       }
     }
   else
     {
diff --git a/gcc/testsuite/g++.dg/analyzer/exception-rethrow-3.C 
b/gcc/testsuite/g++.dg/analyzer/exception-rethrow-3.C
new file mode 100644
index 000000000000..652020c705b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/exception-rethrow-3.C
@@ -0,0 +1,46 @@
+#include "../../gcc.dg/analyzer/analyzer-decls.h"
+
+/* Top-level rethrow (PR analyzer/123880).  */
+
+void test_1 ()
+{
+    throw;
+}
+
+/* Intraprocedural leak involving a rethrow.  */
+
+void test_2 ()
+{
+  void *p = __builtin_malloc (1024);
+  throw; // { dg-warning "leak of 'p'" }
+  // { dg-message "rethrowing exception here\.\.\." "rethrow event" { target 
*-*-* } .-1 }
+}
+
+/* Interprocedural leak involving a rethrow.  */
+
+static void called_by_test_3 ()
+{
+  throw; // { dg-warning "leak of 'p'" }
+  // { dg-message "rethrowing exception here\.\.\." "rethrow event" { target 
*-*-* } .-1 }
+}
+
+void test_3 ()
+{
+  void *p = __builtin_malloc (1024); // { dg-message "allocated here" }
+  called_by_test_3 ();
+}
+
+/* Rethrow of a rethrow.  */
+
+void test_4 ()
+{
+  try
+    {
+      throw;
+    }
+  catch (...)
+    {
+      __analyzer_dump_path (); // { dg-message "path" "" { xfail *-*-* } }
+      throw;
+    }
+}
-- 
2.26.3

Reply via email to