https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126918

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, I've tried to use TARGET_EXPR here:
--- gcc/cp/constexpr.cc.jj      2026-08-17 10:00:21.701856524 +0200
+++ gcc/cp/constexpr.cc 2026-08-18 12:49:47.511735722 +0200
@@ -1974,12 +1974,13 @@ cxx_eval_cxa_builtin_fn (const constexpr
            {
              /* Used for catch of a non-pointer type.  */
              tree exc_type = strip_array_types (TREE_TYPE (arg));
-             tree exc_ptr_type = build_pointer_type (exc_type);
-             arg = build_fold_addr_expr_with_type (arg, exc_ptr_type);
-             if (CLASS_TYPE_P (handler_type))
+             if (TYPE_PTRMEM_P (handler_type)
+                 && NULLPTR_TYPE_P (exc_type))
                {
-                 tree ptr_type = build_pointer_type (handler_type);
-                 arg = cp_convert (ptr_type, arg,
+                 if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE)
+                   arg = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (arg)), arg,
+                                 size_zero_node, NULL_TREE, NULL_TREE);
+                 arg = cp_convert (handler_type, arg,
                                    ctx->quiet ? tf_none
                                    : tf_warning_or_error);
                  if (arg == error_mark_node)
@@ -1987,6 +1988,25 @@ cxx_eval_cxa_builtin_fn (const constexpr
                      *non_constant_p = true;
                      return call;
                    }
+                 arg = force_target_expr (handler_type, arg, tf_none);
+                 arg = cp_build_addr_expr (arg, tf_none);
+               }
+             else
+               {
+                 tree exc_ptr_type = build_pointer_type (exc_type);
+                 arg = build_fold_addr_expr_with_type (arg, exc_ptr_type);
+                 if (CLASS_TYPE_P (handler_type))
+                   {
+                     tree ptr_type = build_pointer_type (handler_type);
+                     arg = cp_convert (ptr_type, arg,
+                                       ctx->quiet ? tf_none
+                                       : tf_warning_or_error);
+                     if (arg == error_mark_node)
+                       {
+                         *non_constant_p = true;
+                         return call;
+                       }
+                   }
                }
            }
          return cxx_eval_constant_expression (ctx, arg, vc_prvalue,

(just trying to deal with the nullptr -> pointer-to-member right now, the
pointer-to-member cases which need conversion are unhandled yet), but
unfortunately it doesn't work.
The IL in original dump is
<<< Unknown tree: handler

      {
        <<< Unknown tree: offset_type >>> p = *(<<< Unknown tree: offset_type
>>> &) D.2709;

        try
          {
                        register <<< Unknown tree: offset_type >>> * D.2709;
            <<cleanup_point <<< Unknown tree: expr_stmt
              (void) (D.2709 = (<<< Unknown tree: offset_type >>> *)
__cxa_begin_catch (__builtin_eh_pointer (0))) >>>>>;
                        <<< Unknown tree: offset_type >>> p = *(<<< Unknown
tree: offset_type >>> &) D.2709;
            return <retval> = p;
          }
        finally
          {
            __cxa_end_catch ();
          }
      } >>>
so when I create a TARGET_EXPR when evaluating __cxa_begin_catch magic call, it
gets out of scope at the end of the CLEANUP_POINT_EXPR it surrounds.
That CLEANUP_POINT_EXPR is created in
#1  0x000000000177aef6 in build1 (code=CLEANUP_POINT_EXPR, type=<void_type
0x7fffe9823f18 void>, node=<expr_stmt 0x7fffe99c0780>) at
../../gcc/tree.cc:5204
#2  0x00000000004400bc in build1_loc (loc=1249152, code=CLEANUP_POINT_EXPR,
type=<void_type 0x7fffe9823f18 void>, arg1=<expr_stmt 0x7fffe99c0780>) at
../../gcc/tree.h:4961
#3  0x0000000000d45db3 in fold_build_cleanup_point_expr (type=<void_type
0x7fffe9823f18 void>, expr=<expr_stmt 0x7fffe99c0780>) at
../../gcc/fold-const.cc:15825
#4  0x00000000008aeef1 in maybe_cleanup_point_expr_void (expr=<expr_stmt
0x7fffe99c0780>) at ../../gcc/cp/semantics.cc:588
#5  0x00000000008b1265 in finish_expr_stmt (expr=<expr_stmt 0x7fffe99c0780>) at
../../gcc/cp/semantics.cc:1197
#6  0x0000000000568637 in initialize_local_var (decl=<var_decl 0x7fffe99c34c0>,
init=<init_expr 0x7fffe99c6758>, decomp=false) at ../../gcc/cp/decl.cc:9085
#7  0x000000000057075d in cp_finish_decl (decl=<var_decl 0x7fffe99c34c0>,
init=<init_expr 0x7fffe99c6758>, init_const_expr_p=false, asmspec_tree=<tree
0x0>, flags=4, decomp=0x0) at ../../gcc/cp/decl.cc:10216
#8  0x00000000005ee88d in expand_start_catch_block (decl=<var_decl
0x7fffe99c3390 p>) at ../../gcc/cp/except.cc:463
#9  0x00000000008b56d8 in finish_handler_parms (decl=<var_decl 0x7fffe99c3390
p>, handler=<handler 0x7fffe99c66b8>) at ../../gcc/cp/semantics.cc:2117
so avoiding it would mean nasty hacks like those which were needed for
CWG2867/PR115769, plus also figuring out what CLEANUP_POINT_EXPR will surround
the whole handler body.
So I wonder if it wouldn't be better to just create a local temp VAR_DECL and
"destroy" it on the corresponding __cxa_end_catch.

Reply via email to