On Sat, Nov 15, 2025 at 08:23:50AM +0100, Jakub Jelinek wrote:
> Hi!
> 
> For the https://gcc.gnu.org/pipermail/gcc/2025-November/246977.html
> issues I've filed https://github.com/cplusplus/CWG/issues/805
> and got there some responses.  One possibility is to change
> the iterating expansion statement http://eel.is/c++draft/stmt.expand#5.2
> line from
> constexpr auto&& range = expansion-initializer;
> to
> constexpr decltype(auto) range = (expansion-initializer);
> (for our partly pre-CWG3044 implementation with static before it).
> 
> The following patch on top of the 2 earlier expansion-stmt patches
> attempts to implement it, though not sure if it should be committed
> until at least a CWG is filed for it with some proposed resolution.

FWIW, I think we should wait a little.

> It does affect some of our tests because they weren't using const
> for the begin/end functions but bet real-world C++ code doesn't suffer
> from that.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux.
> 
> BTW, I'd still like to understand which of the compilers is right for
>   static constexpr const auto && var = foo ();
> where foo () is non-const prvalue like std::span<const int>, whether
> the lifetime extended temporary is static std::span<const int>
> in that case or static constexpr std::span<const int>, i.e. whether
> what var refers to can be then used in constant expressions or not.
> I think from reading [class.temp] and [conv.rval] I lean towards gcc
> being right, but maybe I'm missing something important.

This sounds like CWG 2126 which we partially implement (PR101588):

"a temporary object of non-volatile const-qualified literal type whose
lifetime is extended to that of a variable that is usable in constant
expressions" is usable in a constant expression
 
std::span<const int> is a literal type so it should work? 

> 2025-11-15  Jakub Jelinek  <[email protected]>
> 
>       * parser.cc (cp_build_range_for_decls): For expansion stmts
>       build __for_range as
>       static constexpr decltype(auto) __for_range = (range_expr);
>       rather than static constexpr auto&& __for_range = range_expr;
>       as per https://github.com/cplusplus/CWG/issues/805.
> 
>       * g++.dg/cpp26/expansion-stmt1.C (N::begin, N::end, O::begin,
>       O::end): Change argument type from B & to const B & or from
>       D & to const D &.
>       * g++.dg/cpp26/expansion-stmt2.C (N::begin, N::end, O::begin,
>       O::end): Likewise.
>       * g++.dg/cpp26/expansion-stmt3.C (N::begin, N::end, O::begin,
>       O::end): Likewise.
>       * g++.dg/cpp26/expansion-stmt16.C: Expect different diagnostics
>       for C++11.
>       * g++.dg/cpp26/expansion-stmt18.C (N::begin, N::end): Change
>       argument type from B & to const B &.
>       * g++.dg/cpp26/expansion-stmt25.C (N::begin, N::end): Likewise.
>       * g++.dg/cpp26/expansion-stmt26.C: New test.
> 
> --- gcc/cp/parser.cc.jj       2025-11-14 16:40:33.882192102 +0100
> +++ gcc/cp/parser.cc  2025-11-14 17:56:20.854087295 +0100
> @@ -15205,9 +15205,24 @@ cp_build_range_for_decls (location_t loc
>       range_temp = range_expr;
>        else
>       {
> -       range_temp = build_range_temp (range_expr);
>         if (expansion_stmt_p)
>           {
> +           /* Build constexpr decltype(auto) __for_range = (range_expr);  */
> +           location_t range_loc = cp_expr_loc_or_loc (range_expr, loc);
> +           range_expr
> +             = finish_parenthesized_expr (cp_expr (range_expr, range_loc));
> +           tree auto_node = make_decltype_auto ();
> +           tree range_type
> +             = cp_build_qualified_type (auto_node, TYPE_QUAL_CONST);
> +           range_type = do_auto_deduction (range_type, range_expr,
> +                                           auto_node);
> +
> +           /* Create the __range variable.  */
> +           range_temp = build_decl (input_location, VAR_DECL,
> +                                    for_range__identifier, range_type);
> +           TREE_USED (range_temp) = 1;
> +           DECL_ARTIFICIAL (range_temp) = 1;

This is so close to build_range_temp that I think it should get
a "bool expansion_stmt_p" parm so that we can reuse the do_auto_deduction
and further code.

Marek

Reply via email to