]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix up iterating expansion stmt b and e var handling [PR124927]
authorJakub Jelinek <jakub@redhat.com>
Tue, 21 Apr 2026 16:31:36 +0000 (18:31 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 21 Apr 2026 16:31:36 +0000 (18:31 +0200)
The following testcase ICEs, because the TARGET_EXPR it had has VOID_TYPE
TARGET_EXPR_INITIAL and force_target_expr obviously ICEs when trying to
create a VOID_TYPE TARGET_EXPR.

This patch fixes it by taking the cv_unqualified type of the TARGET_EXPRs
before we extract their TARGET_EXPR_INITIAL, so it does the desirable thing
of recreating the TARGET_EXPRs with cv unqualified types.

2026-04-21  Jakub Jelinek  <jakub@redhat.com>

PR c++/124927
* pt.cc (finish_expansion_stmt): Compute types for force_target_expr
from b and e before extracting TARGET_EXPR_INITIAL from it.

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

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp26/expansion-stmt41.C [new file with mode: 0644]

index 2cf14e2c801097554efcc019a51f870c2baebf07..5d97ca7997f4eda90aa39b65e28b28e2e15960ca 100644 (file)
@@ -33501,14 +33501,14 @@ finish_expansion_stmt (tree expansion_stmt, tree args,
             so that e.g. b can be incremented, so unwrap the TARGET_EXPRs
             and force TARGET_EXPR with the cv-unqualified type which is
             a hack replacement for a VAR_DECL in a lambda.  */
+         tree btype = cv_unqualified (TREE_TYPE (b));
+         tree etype = cv_unqualified (TREE_TYPE (e));
          if (TREE_CODE (b) == TARGET_EXPR)
            b = TARGET_EXPR_INITIAL (b);
          if (TREE_CODE (e) == TARGET_EXPR)
            e = TARGET_EXPR_INITIAL (e);
-         b = force_target_expr (cv_unqualified (TREE_TYPE (b)), b,
-                                tf_warning_or_error);
-         e = force_target_expr (cv_unqualified (TREE_TYPE (e)), e,
-                                tf_warning_or_error);
+         b = force_target_expr (btype, b, tf_warning_or_error);
+         e = force_target_expr (etype, e, tf_warning_or_error);
          tree w = build_stmt (loc, WHILE_STMT, NULL_TREE, NULL_TREE,
                               NULL_TREE, NULL_TREE, NULL_TREE);
          tree r = get_target_expr (build_zero_cst (ptrdiff_type_node));
diff --git a/gcc/testsuite/g++.dg/cpp26/expansion-stmt41.C b/gcc/testsuite/g++.dg/cpp26/expansion-stmt41.C
new file mode 100644 (file)
index 0000000..891e071
--- /dev/null
@@ -0,0 +1,28 @@
+// PR c++/124927
+// { dg-do run { target c++23 } }
+// { dg-options "" }
+
+#include <array>
+#include <ranges>
+
+constexpr std::array a { 1, 2, 3, 4, 5 };
+constexpr std::array b { 5, 4, 3, 2, 1 };
+
+int
+foo (int i)
+{
+  template for (constexpr auto z : std::views::zip (a, b)) // { dg-warning "'template for' only available with" "" { target c++23_down } }
+    if (i == get <0> (z))
+      return get <1> (z);
+  return 0;
+}
+
+int
+main ()
+{
+  for (int i = 1; i <= 5; ++i)
+    if (foo (i) != 6 - i)
+      __builtin_abort ();
+  if (foo (0) != 0 || foo (6) != 0)
+    __builtin_abort ();
+}