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.