Hi!

When implementing expansion statements, cp_perform_range_for_lookup
does for the non-method begin/end:
          /* Use global functions with ADL.  */
          releasing_vec vec;

          vec_safe_push (vec, range);

          member_begin = perform_koenig_lookup (id_begin, vec,
                                                complain);
          if ((complain & tf_error) == 0 && member_begin == id_begin)
            return error_mark_node;
          *begin = finish_call_expr (member_begin, &vec, false, true,
                                     complain);
          member_end = perform_koenig_lookup (id_end, vec,
                                              tf_warning_or_error);
          if ((complain & tf_error) == 0 && member_end == id_end)
            {
              *begin = error_mark_node;
              return error_mark_node;
            }
          *end = finish_call_expr (member_end, &vec, false, true,
                                   complain);
        }

      /* Last common checks.  */
      if (*begin == error_mark_node || *end == error_mark_node)
        {
          /* If one of the expressions is an error do no more checks.  */
          *begin = *end = error_mark_node;
          return error_mark_node;
        }
and finish_expansion_stmt uses
      iter_type = cp_perform_range_for_lookup (range_temp, &begin_expr,
                                               &end_expr, tf_none);
      if (begin_expr != error_mark_node && end_expr != error_mark_node)
        {
          kind = esk_iterating;
          gcc_assert (iter_type);
        }
to select iterating over destructuring only if both are
non-error_mark_nodes.
This is not what the standard says right now, but is what
the proposed resolution of CWG 3123 says:
https://cplusplus.github.io/CWG/issues/3123.html
I think for the pre-CWG 3123 wording I'd need to propagate to the
caller whether perform_koenig_lookup was successfull but whether
finish_call_expr succeeded or not should then be done without tf_none
after choosing esk_iterating.

Anyway, with the hope that CWG 3123 is voted in, this patch adds
a testcase for it.

Regtested on x86_64-linux and i686-linux, ok for trunk?

2026-02-11  Jakub Jelinek  <[email protected]>

        * g++.dg/cpp26/expansion-stmt29.C: New test.

--- gcc/testsuite/g++.dg/cpp26/expansion-stmt29.C.jj    2026-02-10 
15:40:47.794903075 +0100
+++ gcc/testsuite/g++.dg/cpp26/expansion-stmt29.C       2026-02-10 
15:40:41.132016293 +0100
@@ -0,0 +1,15 @@
+// CWG 3123
+// { dg-do run { target c++26 } }
+
+#include <tuple>
+
+int
+main ()
+{
+  long l = 0;
+  std::tuple <int, long, unsigned> t = { 1, 2L, 3U };
+  template for (auto &&x : t)
+    l += x;
+  if (l != 6L)
+    __builtin_abort ();
+}

        Jakub

Reply via email to