[gcc r16-7206] analyzer: fix ICE on rethrow without throw [PR123880]

David Malcolm dmalcolm@gcc.gnu.org
Sat Jan 31 04:35:12 GMT 2026


https://gcc.gnu.org/g:b5d5cab8e4b8077386b820a5b6c25b5fe632fa6d

commit r16-7206-gb5d5cab8e4b8077386b820a5b6c25b5fe632fa6d
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Fri Jan 30 23:27:40 2026 -0500

    analyzer: fix ICE on rethrow without throw [PR123880]
    
    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>

Diff:
---
 gcc/analyzer/engine.cc                             | 22 ++++++++---
 .../g++.dg/analyzer/exception-rethrow-3.C          | 46 ++++++++++++++++++++++
 2 files changed, 63 insertions(+), 5 deletions(-)

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;
+    }
+}


More information about the Gcc-cvs mailing list