On 12/1/22 05:32, Jakub Jelinek wrote:
On Wed, Nov 30, 2022 at 01:52:08PM -0500, Jason Merrill wrote:
It looks like we're already deducing the type for the underlying S variable
in cp_convert_omp_range_for, we just aren't updating the types of the
individual bindings.

You're right.  With this patch (still incremental against the base PR84469
patch) we get the nicer diagnostics in all cases.

Regtested successfully on x86_64-linux (g++ gomp.exp/goacc.exp/goacc-gomp.exp
and libgomp's c++.exp), ok for trunk (including the base patch)
if it passes full bootstrap/regtest?

OK, thanks.

2022-12-01  Jakub Jelinek  <ja...@redhat.com>

        PR c++/84469
gcc/c-family/
        * c-omp.cc (c_omp_is_loop_iterator): For range for with structured
        binding return TREE_VEC_LENGTH (d->declv) even if decl is equal
        to any of the structured binding decls.
gcc/cp/
        * parser.cc (cp_convert_omp_range_for): After do_auto_deduction if
        !processing_template_decl call cp_finish_decomp with
        processing_template_decl temporarily incremented.
gcc/testsuite/
        * g++.dg/gomp/for-21.C (f3, f6, f9): Adjust expected diagnostics.
        * g++.dg/gomp/for-22.C: New test.

--- gcc/c-family/c-omp.cc.jj    2022-10-04 10:36:46.515414485 +0200
+++ gcc/c-family/c-omp.cc       2022-12-01 10:57:56.365253302 +0100
@@ -1311,10 +1311,11 @@ c_omp_is_loop_iterator (tree decl, struc
      else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
             && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
             && (TREE_CODE (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)))
-                == TREE_VEC)
-            && decl == TREE_VEC_ELT (TREE_CHAIN (TREE_VEC_ELT (d->declv,
-                                                 i)), 2))
-      return TREE_VEC_LENGTH (d->declv);
+                == TREE_VEC))
+      for (int j = 2;
+          j < TREE_VEC_LENGTH (TREE_CHAIN (TREE_VEC_ELT (d->declv, i))); j++)
+       if (decl == TREE_VEC_ELT (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)), j))
+         return TREE_VEC_LENGTH (d->declv);
    return -1;
  }
--- gcc/cp/parser.cc.jj 2022-12-01 10:19:27.000000000 +0100
+++ gcc/cp/parser.cc    2022-12-01 10:21:30.760450093 +0100
@@ -43126,8 +43126,16 @@ cp_convert_omp_range_for (tree &this_pre
        tree t = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
                                     NULL_TREE, tf_none);
        if (!error_operand_p (t))
-       TREE_TYPE (orig_decl) = do_auto_deduction (TREE_TYPE (orig_decl),
-                                                  t, auto_node);
+       {
+         TREE_TYPE (orig_decl) = do_auto_deduction (TREE_TYPE (orig_decl),
+                                                    t, auto_node);
+         if (decomp_first_name)
+           {
+             ++processing_template_decl;
+             cp_finish_decomp (orig_decl, decomp_first_name, decomp_cnt);
+             --processing_template_decl;
+           }
+       }
      }
tree v = make_tree_vec (decomp_cnt + 3);
--- gcc/testsuite/g++.dg/gomp/for-21.C.jj       2022-11-30 10:29:09.332186135 
+0100
+++ gcc/testsuite/g++.dg/gomp/for-21.C  2022-12-01 11:05:40.888414600 +0100
@@ -24,9 +24,9 @@ void
  f3 (S (&a)[10])
  {
    #pragma omp for collapse (2)
-  for (auto [i, j, k] : a)                     // { dg-error "use of 'i' before deduction of 
'auto'" "" { target *-*-* } .+1 }
-    for (int l = i; l < j; l += k)          // { dg-error "use of 'j' before 
deduction of 'auto'" }
-      ;                                                // { dg-error "use of 'k' before 
deduction of 'auto'" "" { target *-*-* } .-1 }
+  for (auto [i, j, k] : a)                     // { dg-error "initializer 
expression refers to iteration variable 'i'" }
+    for (int l = i; l < j; l += k)          // { dg-error "condition expression 
refers to iteration variable 'j'" }
+      ;                                                // { dg-error "increment expression 
refers to iteration variable 'k'" "" { target *-*-* } .-2 }
  }
template <int N>
@@ -54,9 +54,9 @@ void
  f6 (S (&a)[10])
  {
    #pragma omp for collapse (2)
-  for (auto [i, j, k] : a)                     // { dg-error "use of 'i' before deduction of 
'auto'" "" { target *-*-* } .-1 }
-    for (int l = i; l < j; l += k)          // { dg-error "use of 'j' before 
deduction of 'auto'" }
-      ;                                                // { dg-error "use of 'k' before 
deduction of 'auto'" "" { target *-*-* } .-3 }
+  for (auto [i, j, k] : a)                     // { dg-error "initializer expression refers 
to iteration variable 'i'" "" { target *-*-* } .-1 }
+    for (int l = i; l < j; l += k)          // { dg-error "condition expression 
refers to iteration variable 'j'" }
+      ;                                                // { dg-error "increment expression 
refers to iteration variable 'k'" "" { target *-*-* } .-3 }
  }
template <typename T>
@@ -84,9 +84,9 @@ void
  f9 (U (&a)[10])
  {
    #pragma omp for collapse (2)
-  for (auto [i, j, k] : a)                     // { dg-error "use of 'i' before deduction of 
'auto'" "" { target *-*-* } .-1 }
-    for (T l = i; l < j; l += k)            // { dg-error "use of 'j' before 
deduction of 'auto'" }
-      ;                                                // { dg-error "use of 'k' before 
deduction of 'auto'" "" { target *-*-* } .-3 }
+  for (auto [i, j, k] : a)                     // { dg-error "initializer expression refers 
to iteration variable 'i'" "" { target *-*-* } .-1 }
+    for (T l = i; l < j; l += k)            // { dg-error "condition expression 
refers to iteration variable 'j'" }
+      ;                                                // { dg-error "increment expression 
refers to iteration variable 'k'" "" { target *-*-* } .-3 }
  }
void
--- gcc/testsuite/g++.dg/gomp/for-22.C.jj       2022-12-01 10:17:47.117785354 
+0100
+++ gcc/testsuite/g++.dg/gomp/for-22.C  2022-12-01 11:08:19.578078371 +0100
@@ -0,0 +1,57 @@
+// { dg-do compile { target c++17 } }
+
+namespace std {
+  template<typename T> struct tuple_size;
+  template<int, typename> struct tuple_element;
+}
+
+struct A {
+  int i;
+  template <int I> int& get() { return i; }
+};
+
+template<> struct std::tuple_size<A> { static const int value = 3; };
+template<int I> struct std::tuple_element<I,A> { using type = int; };
+
+struct B {
+  A *begin();
+  A *end();
+};
+
+void
+f1 (B a)
+{
+  #pragma omp for collapse (2)
+  for (auto [i, j, k] : a)                     // { dg-error "initializer expression refers 
to iteration variable 'i'" "" { target *-*-* } .+1 }
+    for (int l = i; l < j; l += k)          // { dg-error "condition expression 
refers to iteration variable 'j'" }
+      ;                                                // { dg-error "increment expression 
refers to iteration variable 'k'" "" { target *-*-* } .-1 }
+}
+
+template <int N>
+void
+f2 (B a)
+{
+  #pragma omp for collapse (2)
+  for (auto [i, j, k] : a)                     // { dg-error "initializer expression refers 
to iteration variable 'i'" "" { target *-*-* } .-1 }
+    for (int l = i; l < j; l += k)          // { dg-error "condition expression 
refers to iteration variable 'j'" }
+      ;                                                // { dg-error "increment expression 
refers to iteration variable 'k'" "" { target *-*-* } .-3 }
+}
+
+template <typename T>
+void
+f3 (T a)
+{
+  #pragma omp for collapse (2)
+  for (auto [i, j, k] : a)                     // { dg-error "initializer expression refers 
to iteration variable 'i'" "" { target *-*-* } .-1 }
+    for (int l = i; l < j; l += k)          // { dg-error "condition expression 
refers to iteration variable 'j'" }
+      ;                                                // { dg-error "increment expression 
refers to iteration variable 'k'" "" { target *-*-* } .-3 }
+}
+
+void
+test ()
+{
+  B b;
+  f1 (b);
+  f2 <0> (b);
+  f3 <B> (b);
+}


        Jakub


Reply via email to