[Bug c++/126918] constexpr exceptions and nullptr vs. pointer-to-member

"jakub at gcc dot gnu.org via Gcc-bugs" <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.