https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118574
--- Comment #17 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Note, even the D {} temporary goes into function local vars rather than in the narrower scope. While for the -std=c++20 case the temporary is created and pushdecl called on it #0 pushdecl (decl=<var_decl 0x7fffea2df5f0>, hiding=false) at ../../gcc/cp/name-lookup.cc:3893 #1 0x00000000004435fd in make_temporary_var_for_ref_to_temp (decl=<var_decl 0x7fffea2df558 __for_range >, type=<record_type 0x7fffea2e5000 A>) at ../../gcc/cp/call.cc:14154 #2 0x000000000044365c in set_up_extended_ref_temp (decl=<var_decl 0x7fffea2df558 __for_range >, expr=<target_expr 0x7fffea2e4700>, Python Exception <class 'RuntimeError'>: Null type cleanups=0x7fffffffcdd8, initp=0x7fffffffcbb0, cond_guard=0x0) at ../../gcc/cp/call.cc:14173 #3 0x00000000004464a6 in extend_ref_init_temps_1 (decl=<var_decl 0x7fffea2df558 __for_range >, init=<nop_expr 0x7fffea2f4ea0>, Python Exception <class 'RuntimeError'>: Null type nam cleanups=0x7fffffffcdd8, cond_guard=0x0) at ../../gcc/cp/call.cc:14804 #4 0x0000000000446639 in extend_ref_init_temps (decl=<var_decl 0x7fffea2df558 __for_range >, init=<nop_expr 0x7fffea2f4ea0>, Python Exception <class 'RuntimeError'>: Null type name. cleanups=0x7fffffffcdd8, cond_guard=0x0) at ../../gcc/cp/call.cc:14835 #5 0x00000000008c55cb in store_init_value (decl=<var_decl 0x7fffea2df558 __for_range >, init=<nop_expr 0x7fffea2f4ea0>, Python Exception <class 'RuntimeError'>: Null type name. cleanups=0x7fffffffcdd8, flags=8196) at ../../gcc/cp/typeck2.cc:867 #6 0x000000000054cc49 in check_initializer (decl=<var_decl 0x7fffea2df558 __for_range >, init=<nop_expr 0x7fffea2f4ea0>, flags=8196, Python Exception <class 'RuntimeError'>: Null ty cleanups=0x7fffffffcdd8) at ../../gcc/cp/decl.cc:8022 #7 0x0000000000554b0c in cp_finish_decl (decl=<var_decl 0x7fffea2df558 __for_range >, init=<target_expr 0x7fffea2e4700>, init_const_expr_p=false, asmspec_tree=<tree 0x0>, flags=4, decomp=0x0) at ../../gcc/cp/decl.cc:9200 #8 0x00000000006e575b in cp_convert_range_for (statement=<for_stmt 0x7fffea2d2948>, range_decl=<var_decl 0x7fffea2df428 item>, range_expr=<target_expr 0x7fffea2e4700>, decomp=0x0, ivdep=false, unroll=<tree 0x0>, novector=false) at ../../gcc/cp/parser.cc:14856 #9 0x00000000006e4e5a in cp_parser_range_for (parser=0x7fffea2cc2a0, scope=<statement_list 0x7fffea2f4bc0>, init=<tree 0x0>, range_decl=<var_decl 0x7fffea2df428 item>, ivdep=false, unroll=<tree 0x0>, novector=false, is_omp=false) at ../../gcc/cp/parser.cc:14643 in the ref init extension code, for -frange-for-ext-temps extend_ref_init_temps intentionally ignores it for __for_range: extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups, if (processing_template_decl) return init; + /* P2718R0 - ignore temporaries in C++23 for-range-initializer, those + have all extended lifetime. */ + if (DECL_NAME (decl) == for_range__identifier + && flag_range_for_ext_temps) + return init; + because in that case all the temporaries are extended until end of range for body, so treating __range_for differently would just mess up with the ordering. But it means that pushdecl on those isn't called. The corresponding temporary is in this case created by #1 0x000000000160b42d in build_decl (loc=4611686018427387914, code=VAR_DECL, name=<tree 0x0>, type=<record_type 0x7fffea300000 A>) at ../../gcc/tree.cc:5421 5421 t = make_node (code PASS_MEM_STAT); (gdb) #2 0x0000000000863fe5 in build_local_temp (type=<record_type 0x7fffea300000 A>) at ../../gcc/cp/tree.cc:579 579 tree slot = build_decl (input_location, (gdb) #3 0x000000000086451b in build_aggr_init_expr (type=<record_type 0x7fffea300000 A>, init=<call_expr 0x7fffea15ab70>) at ../../gcc/cp/tree.cc:689 689 slot = build_local_temp (type); (gdb) #4 0x0000000000864b3f in build_cplus_new (type=<record_type 0x7fffea300000 A>, init=<call_expr 0x7fffea15ab70>, complain=3) at ../../gcc/cp/tree.cc:741 741 tree rval = build_aggr_init_expr (type, init); (gdb) #5 0x0000000000438e56 in build_cxx_call (fn=<call_expr 0x7fffea15ab70>, nargs=0, argarray=0x7fffffffb6e0, complain=3, orig_fndecl=<function_decl 0x7fffea30a300 foo>) at ../../gcc/cp/call.cc:11463 11463 fn = build_cplus_new (TREE_TYPE (fn), fn, complain); (gdb) #6 0x0000000000436f26 in build_over_call (cand=0x43e0fb0, flags=1, complain=3) at ../../gcc/cp/call.cc:10933 10933 tree call = build_cxx_call (fn, nargs, argarray, complain|decltype_flag); (gdb) #7 0x000000000042002b in build_new_function_call (fn=<function_decl 0x7fffea30a300 foo>, Python Exception <class 'RuntimeError'>: Null type name. args=0x7fffffffbc58, complain=3) at ../../gcc/cp/call.cc:5243 5243 result = build_over_call (cand, LOOKUP_NORMAL, complain); (gdb) #8 0x0000000000826e19 in finish_call_expr (fn=<function_decl 0x7fffea30a300 foo>, Python Exception <class 'RuntimeError'>: Null type name. args=0x7fffffffbc58, disallow_virtual=false, koenig_p=false, complain=3) at ../../gcc/cp/semantics.cc:3457 3457 result = build_new_function_call (fn, args, complain); (gdb) #9 0x00000000006d5635 in cp_parser_postfix_expression (parser=0x7fffea2e62a0, address_p=false, cast_p=false, member_access_only_p=false, decltype_p=false, pidk_return=0x0) at ../../gcc/cp/parser.cc:8474 8474 = finish_call_expr (postfix_expression, &args, (gdb) #10 0x00000000006d8d0d in cp_parser_unary_expression (parser=0x7fffea2e62a0, pidk=0x0, address_p=false, cast_p=false, decltype_p=false) at ../../gcc/cp/parser.cc:9733 9733 return cp_parser_postfix_expression (parser, address_p, cast_p, (gdb) #11 0x00000000006da4f0 in cp_parser_cast_expression (parser=0x7fffea2e62a0, address_p=false, cast_p=false, decltype_p=false, pidk=0x0) at ../../gcc/cp/parser.cc:10648 10648 return cp_parser_unary_expression (parser, pidk, address_p, (gdb) #12 0x00000000006da5f3 in cp_parser_binary_expression (parser=0x7fffea2e62a0, cast_p=false, no_toplevel_fold_p=false, decltype_p=false, prec=PREC_NOT_OPERATOR, pidk=0x0) at ../../gcc/cp/parser.cc:10751 10751 current.lhs = cp_parser_cast_expression (parser, /*address_p=*/false, (gdb) #13 0x00000000006db7a1 in cp_parser_assignment_expression (parser=0x7fffea2e62a0, pidk=0x0, cast_p=false, decltype_p=false) at ../../gcc/cp/parser.cc:11096 11096 expr = cp_parser_binary_expression (parser, cast_p, false, (gdb) #14 0x00000000006dbcdd in cp_parser_expression (parser=0x7fffea2e62a0, pidk=0x0, cast_p=false, decltype_p=false, warn_comma_p=false) at ../../gcc/cp/parser.cc:11279 11279 = cp_parser_assignment_expression (parser, pidk, cast_p, decltype_p); (gdb) #15 0x00000000006e4b3c in cp_parser_range_for (parser=0x7fffea2e62a0, scope=<statement_list 0x7fffea30fe80>, init=<tree 0x0>, range_decl=<var_decl 0x7fffea2fc428 item>, ivdep=false, unroll=<tree 0x0>, novector=false, is_omp=false) at ../../gcc/cp/parser.cc:14606 14606 range_expr = cp_parser_expression (parser); So, can coro handle even such temporaries which didn't have pushdecl called on them, or would we need to somehow find out all such temporaries and call pushdecl on them at some point?