@@ -972,6 +972,7 @@ find_combined_omp_for (tree *tp, int *wa
*walk_subtrees = 1;
break;
case TRY_FINALLY_EXPR:
+ case CLEANUP_POINT_EXPR:
pdata[0] = tp;
*walk_subtrees = 1;
break;
@@ -4105,6 +4106,7 @@ find_nested_loop_xform (tree *tp, int *w
*walk_subtrees = 1;
break;
case TRY_FINALLY_EXPR:
+ case CLEANUP_POINT_EXPR:
pdata[0] = tp;
*walk_subtrees = 1;
break;
@@ -1034,7 +1034,8 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_fold_expressions=201603L");
if (cxx_dialect <= cxx17)
cpp_define (pfile, "__cpp_nontype_template_args=201411L");
- cpp_define (pfile, "__cpp_range_based_for=201603L");
+ if (cxx_dialect <= cxx20)
+ cpp_define (pfile, "__cpp_range_based_for=201603L");
if (cxx_dialect <= cxx17)
cpp_define (pfile, "__cpp_constexpr=201603L");
cpp_define (pfile, "__cpp_if_constexpr=201606L");
@@ -1087,6 +1088,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_static_call_operator=202207L");
cpp_define (pfile, "__cpp_implicit_move=202207L");
cpp_define (pfile, "__cpp_explicit_this_parameter=202110L");
+ cpp_define (pfile, "__cpp_range_based_for=202211L");
}
if (cxx_dialect > cxx23)
{
@@ -1617,6 +1617,7 @@ c_find_nested_loop_xform_r (tree *tp, in
*walk_subtrees = 1;
break;
case TRY_FINALLY_EXPR:
+ case CLEANUP_POINT_EXPR:
*walk_subtrees = 1;
break;
default:
@@ -14440,6 +14440,15 @@ cp_convert_range_for (tree statement, tr
{
range_temp = build_range_temp (range_expr);
pushdecl (range_temp);
+ if (cxx_dialect >= cxx23)
+ {
+ /* P2718R0 - put the range_temp declaration and everything
+ until end of the range for body into an extra STATEMENT_LIST
+ which will have CLEANUP_POINT_EXPR around it, so that all
+ temporaries are destroyed at the end of it. */
+ gcc_assert (FOR_INIT_STMT (statement) == NULL_TREE);
+ FOR_INIT_STMT (statement) = push_stmt_list ();
+ }
cp_finish_decl (range_temp, range_expr,
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
@@ -44600,11 +44609,14 @@ cp_convert_omp_range_for (tree &this_pre
else
{
range_temp = build_range_temp (init);
+ tree name = DECL_NAME (range_temp);
DECL_NAME (range_temp) = NULL_TREE;
pushdecl (range_temp);
+ DECL_NAME (range_temp) = name;
cp_finish_decl (range_temp, init,
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
+ DECL_NAME (range_temp) = NULL_TREE;
range_temp_decl = range_temp;
range_temp = convert_from_reference (range_temp);
}
@@ -45538,7 +45550,15 @@ cp_parser_omp_loop_nest (cp_parser *pars
/* Pop and remember the init block. */
if (sl)
- add_stmt (pop_stmt_list (sl));
+ {
+ sl = pop_stmt_list (sl);
+ /* P2718R0 - Add CLEANUP_POINT_EXPR so that temporaries in
+ for-range-initializer whose lifetime is extended are destructed
+ here. */
+ if (cxx_dialect >= cxx23 && is_range_for && !processing_template_decl)
+ sl = maybe_cleanup_point_expr_void (sl);
+ add_stmt (sl);
+ }
finish_compound_stmt (init_scope);
init_block = pop_stmt_list (init_block);
omp_for_parse_state->init_blockv[depth] = init_block;
@@ -8111,7 +8111,13 @@ initialize_local_var (tree decl, tree in
gcc_assert (building_stmt_list_p ());
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
- current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+ /* P2718R0 - avoid CLEANUP_POINT_EXPR for range-for-initializer,
+ temporaries from there should have lifetime extended. */
+ if (DECL_NAME (decl) == for_range__identifier
+ && cxx_dialect >= cxx23)
+ current_stmt_tree ()->stmts_are_full_exprs_p = 0;
+ else
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (init);
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
@@ -14514,6 +14514,12 @@ extend_ref_init_temps (tree decl, tree i
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
+ && cxx_dialect >= cxx23)
+ return init;
+
maybe_warn_dangling_reference (decl, init);
if (TYPE_REF_P (type))
@@ -1601,6 +1601,20 @@ finish_for_stmt (tree for_stmt)
}
}
+ /* P2718R0 - Add CLEANUP_POINT_EXPR so that temporaries in
+ for-range-initializer whose lifetime is extended are destructed
+ here. */
+ if (cxx_dialect >= cxx23
+ && range_for_decl[0]
+ && FOR_INIT_STMT (for_stmt))
+ {
+ tree stmt = pop_stmt_list (FOR_INIT_STMT (for_stmt));
+ FOR_INIT_STMT (for_stmt) = NULL_TREE;
+ stmt = build_stmt (EXPR_LOCATION (for_stmt), EXPR_STMT, stmt);
+ stmt = maybe_cleanup_point_expr_void (stmt);
+ add_stmt (stmt);
+ }
+
add_stmt (do_poplevel (scope));
/* If we're being called from build_vec_init, don't mess with the names of
@@ -19099,6 +19099,18 @@ tsubst_stmt (tree t, tree args, tsubst_f
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
+ tree sl = NULL_TREE;
+ if (cxx_dialect >= cxx23
+ && OMP_FOR_INIT (t) != NULL_TREE
+ && !processing_template_decl)
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
+ if (TREE_VEC_ELT (OMP_FOR_INIT (t), i)
+ && TREE_VEC_ELT (OMP_FOR_COND (t), i) == global_namespace)
+ {
+ sl = push_stmt_list ();
+ break;
+ }
+
if (OMP_FOR_INIT (t) != NULL_TREE)
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
{
@@ -19154,6 +19166,16 @@ tsubst_stmt (tree t, tree args, tsubst_f
add_stmt (t);
}
+ if (sl)
+ {
+ /* P2718R0 - Add CLEANUP_POINT_EXPR so that temporaries in
+ for-range-initializer whose lifetime is extended are destructed
+ here. */
+ sl = pop_stmt_list (sl);
+ sl = maybe_cleanup_point_expr_void (sl);
+ add_stmt (sl);
+ }
+
add_stmt (finish_omp_for_block (finish_omp_structured_block (stmt),
t));
pop_omp_privatization_clauses (r);
@@ -0,0 +1,206 @@
+// P2718R0 - Wording for P2644R1 Fix for Range-based for Loop
+// { dg-do run { target c++11 } }
+
+extern "C" void abort ();
+void check (bool);
+
+struct S
+{
+ S () { ++s; }
+ S (const S &) { ++s; }
+ ~S () { check (true); --s; }
+ static int s;
+};
+
+int S::s = -1;
+S sv;
+
+struct T
+{
+ T (const S &, const S &) { ++t; }
+ T (const T &) { ++t; }
+ ~T () { check (false); --t; }
+ static int t;
+};
+
+int T::t = -1;
+T tv (sv, sv);
+int a[4];
+int c;
+
+void
+check (bool is_s)
+{
+ if (c)
+ {
+ if (is_s)
+ {
+ if (T::t != (c == 1))
+ abort ();
+ }
+ else
+ {
+ if (S::s != (c == 1 ? 0 : 2))
+ abort ();
+ }
+ }
+}
+
+template <typename T>
+int *
+begin (const T &)
+{
+ return &a[0];
+}
+
+template <typename T>
+int *
+end (const T &)
+{
+ return &a[4];
+}
+
+const S &
+foo (const S &)
+{
+ return sv;
+}
+
+const T &
+foo (const T &)
+{
+ return tv;
+}
+
+void
+bar ()
+{
+ if (S::s != 0)
+ abort ();
+ for (auto x : S ())
+ {
+ if (S::s != 1)
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : foo (S ()))
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ if (T::t != 0)
+ abort ();
+ c = 1 + (__cpp_range_based_for >= 202211L);
+ for (auto x : T (S (), S ()))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L) || T::t != 1)
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ c = 2;
+ for (auto x : foo (T (S (), S ())))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L)
+ || T::t != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ c = 0;
+}
+
+template <int N>
+void
+baz ()
+{
+ if (S::s != 0)
+ abort ();
+ for (auto x : S ())
+ {
+ if (S::s != 1)
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : foo (S ()))
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ if (T::t != 0)
+ abort ();
+ c = 1 + (__cpp_range_based_for >= 202211L);
+ for (auto x : T (S (), S ()))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L) || T::t != 1)
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ c = 2;
+ for (auto x : foo (T (S (), S ())))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L)
+ || T::t != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ c = 0;
+}
+
+template <typename S, typename T>
+void
+qux ()
+{
+ if (S::s != 0)
+ abort ();
+ for (auto x : S ())
+ {
+ if (S::s != 1)
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : foo (S ()))
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ if (T::t != 0)
+ abort ();
+ c = 1 + (__cpp_range_based_for >= 202211L);
+ for (auto x : T (S (), S ()))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L) || T::t != 1)
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ c = 2;
+ for (auto x : foo (T (S (), S ())))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L)
+ || T::t != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ c = 0;
+}
+
+int
+main ()
+{
+ bar ();
+ baz <0> ();
+ qux <S, T> ();
+}
@@ -0,0 +1,230 @@
+// P2718R0 - Wording for P2644R1 Fix for Range-based for Loop
+// { dg-do run { target c++11 } }
+
+extern "C" void abort ();
+
+int a[4];
+
+template <typename T>
+int *
+begin (const T &)
+{
+ return &a[0];
+}
+
+template <typename T>
+int *
+end (const T &)
+{
+ return &a[4];
+}
+
+struct S
+{
+ S () { ++s; }
+ S (const S &) { ++s; }
+ ~S () { --s; }
+ static int s;
+};
+
+int S::s;
+
+template <typename T>
+struct U
+{
+ T t;
+ U () { ++u; }
+ U (const U &) { ++u; }
+ ~U () { --u; }
+ const int *begin () const { return ::begin (t); }
+ const int *end () const { return ::end (t); }
+ U &foo () { return *this; }
+ U bar () { return U (); }
+ static int u;
+};
+
+template <typename T>
+int U<T>::u;
+
+template <typename T>
+U<T>
+foo ()
+{
+ return U<T> {};
+}
+
+template <typename T>
+T
+fred (const T &, const T & = T{}, const T & = T{})
+{
+ return T {};
+}
+
+void
+bar ()
+{
+ int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ if (S::s != 0)
+ abort ();
+ for (auto x : S (), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : (void) S (), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : static_cast<void> (S ()), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : foo <S> ().foo ().bar ().foo ().bar ().foo ().bar ())
+ {
+ if (S::s != 1 + 3 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ if (U<S>::u != S::s)
+ abort ();
+ }
+ if (S::s != 0 || U<S>::u != 0)
+ abort ();
+ for (auto x : fred (S {}))
+ {
+ if (S::s != 1 + 3 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : fred (fred (S {}, S {})))
+ {
+ __builtin_printf ("%d\n", S::s);
+ if (S::s != 1 + 6 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+}
+
+template <int N>
+void
+baz ()
+{
+ int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ if (S::s != 0)
+ abort ();
+ for (auto x : S (), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : (void) S (), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : static_cast<void> (S ()), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : foo <S> ().foo ().bar ().foo ().bar ().foo ().bar ())
+ {
+ if (S::s != 1 + 3 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ if (U<S>::u != S::s)
+ abort ();
+ }
+ if (S::s != 0 || U<S>::u != 0)
+ abort ();
+ for (auto x : fred (S {}))
+ {
+ if (S::s != 1 + 3 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : fred (fred (S {}, S {})))
+ {
+ __builtin_printf ("%d\n", S::s);
+ if (S::s != 1 + 6 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+}
+
+template <typename S>
+void
+qux ()
+{
+ int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ if (S::s != 0)
+ abort ();
+ for (auto x : S (), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : (void) S (), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : static_cast<void> (S ()), a)
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : foo <S> ().foo ().bar ().foo ().bar ().foo ().bar ())
+ {
+ if (S::s != 1 + 3 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ if (U<S>::u != S::s)
+ abort ();
+ }
+ if (S::s != 0 || U<S>::u != 0)
+ abort ();
+ for (auto x : fred (S {}))
+ {
+ if (S::s != 1 + 3 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ for (auto x : fred (fred (S {}, S {})))
+ {
+ __builtin_printf ("%d\n", S::s);
+ if (S::s != 1 + 6 * (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+}
+
+int
+main ()
+{
+ bar ();
+ baz <0> ();
+ qux <S> ();
+}
@@ -42,8 +42,8 @@
#ifndef __cpp_range_based_for
# error "__cpp_range_based_for"
-#elif __cpp_range_based_for != 201603
-# error "__cpp_range_based_for != 201603"
+#elif __cpp_range_based_for != 202211
+# error "__cpp_range_based_for != 202211"
#endif
#ifndef __cpp_decltype
@@ -42,8 +42,8 @@
#ifndef __cpp_range_based_for
# error "__cpp_range_based_for"
-#elif __cpp_range_based_for != 201603
-# error "__cpp_range_based_for != 201603"
+#elif __cpp_range_based_for != 202211
+# error "__cpp_range_based_for != 202211"
#endif
#ifndef __cpp_decltype
@@ -10,5 +10,5 @@ auto f() -> std::optional<std::string>;
void
g ()
{
- for (char c : f().value()) { (void) c; } // { dg-warning "dangling reference" }
+ for (char c : f().value()) { (void) c; } // { dg-warning "dangling reference" "" { target c++20_down } }
}
@@ -0,0 +1,246 @@
+// P2718R0 - Wording for P2644R1 Fix for Range-based for Loop
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+// { dg-require-effective-target tls_runtime }
+
+extern "C" void abort ();
+void check (bool);
+
+struct S
+{
+ S () { ++s; }
+ S (const S &) { ++s; }
+ ~S () { check (true); --s; }
+ [[omp::decl (threadprivate)]] static int s;
+};
+int S::s;
+S sv;
+struct T
+{
+ T (const S &, const S &) { ++t; }
+ T (const T &) { ++t; }
+ ~T () { check (false); --t; }
+ [[omp::decl (threadprivate)]] static int t;
+};
+int T::t;
+T tv (sv, sv);
+int a[4];
+int c;
+
+void
+check (bool is_s)
+{
+ if (c)
+ {
+ if (is_s)
+ {
+ if (T::t != (c == 1))
+ abort ();
+ }
+ else
+ {
+ if (S::s != (c == 1 ? 0 : 2))
+ abort ();
+ }
+ }
+}
+
+template <typename T>
+int *
+begin (const T &)
+{
+ return &a[0];
+}
+
+template <typename T>
+int *
+end (const T &)
+{
+ return &a[4];
+}
+
+const S &
+foo (const S &)
+{
+ return sv;
+}
+
+const T &
+foo (const T &)
+{
+ return tv;
+}
+
+void
+bar ()
+{
+ #pragma omp parallel num_threads (4)
+ {
+ if (S::s != 0)
+ abort ();
+ #pragma omp for
+ for (auto x : S ())
+ {
+ if (S::s != 1)
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ #pragma omp for
+ for (auto x : foo (S ()))
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ if (T::t != 0)
+ abort ();
+ }
+ c = 1 + (__cpp_range_based_for >= 202211L);
+ #pragma omp parallel num_threads (4)
+ {
+ #pragma omp for
+ for (auto x : T (S (), S ()))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L) || T::t != 1)
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ }
+ c = 2;
+ #pragma omp parallel num_threads (4)
+ {
+ #pragma omp for
+ for (auto x : foo (T (S (), S ())))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L)
+ || T::t != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ }
+ c = 0;
+}
+
+template <int N>
+void
+baz ()
+{
+ #pragma omp parallel num_threads (4)
+ {
+ if (S::s != 0)
+ abort ();
+ #pragma omp for
+ for (auto x : S ())
+ {
+ if (S::s != 1)
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ #pragma omp for
+ for (auto x : foo (S ()))
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ if (T::t != 0)
+ abort ();
+ }
+ c = 1 + (__cpp_range_based_for >= 202211L);
+ #pragma omp parallel num_threads (4)
+ {
+ #pragma omp for
+ for (auto x : T (S (), S ()))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L) || T::t != 1)
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ }
+ c = 2;
+ #pragma omp parallel num_threads (4)
+ {
+ #pragma omp for
+ for (auto x : foo (T (S (), S ())))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L)
+ || T::t != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ }
+ c = 0;
+}
+
+template <typename S, typename T>
+void
+qux ()
+{
+ #pragma omp parallel num_threads (4)
+ {
+ if (S::s != 0)
+ abort ();
+ #pragma omp for
+ for (auto x : S ())
+ {
+ if (S::s != 1)
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ #pragma omp for
+ for (auto x : foo (S ()))
+ {
+ if (S::s != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0)
+ abort ();
+ if (T::t != 0)
+ abort ();
+ }
+ c = 1 + (__cpp_range_based_for >= 202211L);
+ #pragma omp parallel num_threads (4)
+ {
+ #pragma omp for
+ for (auto x : T (S (), S ()))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L) || T::t != 1)
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ }
+ c = 2;
+ #pragma omp parallel num_threads (4)
+ {
+ #pragma omp for
+ for (auto x : foo (T (S (), S ())))
+ {
+ if (S::s != 2 * (__cpp_range_based_for >= 202211L)
+ || T::t != (__cpp_range_based_for >= 202211L))
+ abort ();
+ }
+ if (S::s != 0 || T::t != 0)
+ abort ();
+ }
+ c = 0;
+}
+
+int
+main ()
+{
+ S::s--;
+ T::t--;
+ bar ();
+ baz <0> ();
+ qux <S, T> ();
+}
@@ -0,0 +1,6 @@
+// P2718R0 - Wording for P2644R1 Fix for Range-based for Loop
+// { dg-do run }
+// { dg-additional-options "-std=c++23" }
+// { dg-require-effective-target tls_runtime }
+
+#include "range-for-1.C"