From f13305518558f20ef2d460a74eb29dad5fce1350 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 2 Dec 2022 10:30:16 +0100 Subject: [PATCH] c++: Incremental fix for g++.dg/gomp/for-21.C [PR84469] The PR84469 patch I've just posted regresses the for-21.C testcase, when in OpenMP loop there are at least 2 associated loops and in a template outer structured binding with non type dependent expression is used in the expressions of some inner loop, we don't diagnose those any longer, as the (weirdly worded) diagnostics was only done during finish_id_expression -> mark_used which for the inner loop expressions happens before the structured bindings are finalized. When in templates, mark_used doesn't diagnose uses of non-deduced variables, and if the range for expression is type dependent, it is similarly diagnosed during instantiation. But newly with the PR84469 fix if the range for expression is not type dependent, there is no place that would diagnose it, as during instantiation the structured bindings are already deduced. This patch ensures that the bug of using structured bindings from one associated loop in other associated loops is diagnosed by the c_omp_check_loop_iv code by ensuring that cp_finish_decomp is called already during cp_convert_omp_range_for if the artificial iterator has been successfully auto-deduced. 2022-12-02 Jakub Jelinek 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 | 9 +++--- gcc/cp/parser.cc | 12 ++++++-- gcc/testsuite/g++.dg/gomp/for-21.C | 18 ++++++------ gcc/testsuite/g++.dg/gomp/for-22.C | 57 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/for-22.C diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index 5bb1035..2ab9911 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -1311,10 +1311,11 @@ c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d) 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; } diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index e69097d..e8a5090 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -43126,8 +43126,16 @@ cp_convert_omp_range_for (tree &this_pre_body, vec *for_block, 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); diff --git a/gcc/testsuite/g++.dg/gomp/for-21.C b/gcc/testsuite/g++.dg/gomp/for-21.C index fbdaa71..f5a7bf7 100644 --- a/gcc/testsuite/g++.dg/gomp/for-21.C +++ b/gcc/testsuite/g++.dg/gomp/for-21.C @@ -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 @@ -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 @@ -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 diff --git a/gcc/testsuite/g++.dg/gomp/for-22.C b/gcc/testsuite/g++.dg/gomp/for-22.C new file mode 100644 index 0000000..40802a0 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/for-22.C @@ -0,0 +1,57 @@ +// { dg-do compile { target c++17 } } + +namespace std { + template struct tuple_size; + template struct tuple_element; +} + +struct A { + int i; + template int& get() { return i; } +}; + +template<> struct std::tuple_size { static const int value = 3; }; +template struct std::tuple_element { 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 +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 +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); +} -- 2.7.4