]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
analyzer: fix ICE on rethrow without throw [PR123880]
authorDavid Malcolm <dmalcolm@redhat.com>
Sat, 31 Jan 2026 04:27:40 +0000 (23:27 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Sat, 31 Jan 2026 04:27:40 +0000 (23:27 -0500)
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 <dmalcolm@redhat.com>
gcc/analyzer/engine.cc
gcc/testsuite/g++.dg/analyzer/exception-rethrow-3.C [new file with mode: 0644]

index 2d22abf05303337f728f576d4f75bbc53fdff011..8dc9a8b78ce32e4a2f8297d1981af25448d62e91 100644 (file)
@@ -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 (file)
index 0000000..652020c
--- /dev/null
@@ -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;
+    }
+}