analyzer: fix ICE on certain longjmp calls [PR109094]
[platform/upstream/gcc.git] / gcc / analyzer / region-model.cc
index 56beaa8..fb81d43 100644 (file)
@@ -1952,7 +1952,7 @@ region_model::on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call,
      setjmp was called.  */
   gcc_assert (get_stack_depth () >= setjmp_stack_depth);
   while (get_stack_depth () > setjmp_stack_depth)
-    pop_frame (NULL, NULL, ctxt);
+    pop_frame (NULL, NULL, ctxt, false);
 
   gcc_assert (get_stack_depth () == setjmp_stack_depth);
 
@@ -4679,6 +4679,10 @@ region_model::get_current_function () const
    If OUT_RESULT is non-null, copy any return value from the frame
    into *OUT_RESULT.
 
+   If EVAL_RETURN_SVALUE is false, then don't evaluate the return value.
+   This is for use when unwinding frames e.g. due to longjmp, to suppress
+   erroneously reporting uninitialized return values.
+
    Purge the frame region and all its descendent regions.
    Convert any pointers that point into such regions into
    POISON_KIND_POPPED_STACK svalues.  */
@@ -4686,7 +4690,8 @@ region_model::get_current_function () const
 void
 region_model::pop_frame (tree result_lvalue,
                         const svalue **out_result,
-                        region_model_context *ctxt)
+                        region_model_context *ctxt,
+                        bool eval_return_svalue)
 {
   gcc_assert (m_current_frame);
 
@@ -4700,7 +4705,9 @@ region_model::pop_frame (tree result_lvalue,
   tree fndecl = m_current_frame->get_function ()->decl;
   tree result = DECL_RESULT (fndecl);
   const svalue *retval = NULL;
-  if (result && TREE_TYPE (result) != void_type_node)
+  if (result
+      && TREE_TYPE (result) != void_type_node
+      && eval_return_svalue)
     {
       retval = get_rvalue (result, ctxt);
       if (out_result)
@@ -4712,6 +4719,8 @@ region_model::pop_frame (tree result_lvalue,
 
   if (result_lvalue && retval)
     {
+      gcc_assert (eval_return_svalue);
+
       /* Compute result_dst_reg using RESULT_LVALUE *after* popping
         the frame, but before poisoning pointers into the old frame.  */
       const region *result_dst_reg = get_lvalue (result_lvalue, ctxt);