Hi! As can be seen on the testcase, when array_expr is type dependent, assuming it has non-NULL TREE_TYPE is just wrong, it can often have NULL type, and even if not, blindly assuming it is a pointer or array type is also wrong.
So, like in many other spots in the C++ FE, for type dependent expressions we want to create something which will survive until instantiation and can be redone at that point. Unfortunately, build_omp_array_section is called before we actually do any kind of checking what array_expr really is, and on invalid code it can be e.g. a TYPE_DECL on which type_dependent_expression_p ICEs (as can be seen on the pr67522.C testcase). So, I've hacked this by checking it is not TYPE_DECL, I hope a TYPE_P can't make it through there when we just lookup an identifier. Anyway, this patch is not enough, we can ICE e.g. on __uint128_t[0:something] during instantiation, so I think something needs to be done for this in pt.cc as well. Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. 2025-01-23 Jakub Jelinek <ja...@redhat.com> PR c++/118590 * typeck.cc (build_omp_array_section): If array_expr is type dependent or a TYPE_DECL, build OMP_ARRAY_SECTION with NULL type. * g++.dg/goacc/pr118590.C: New test. --- gcc/cp/typeck.cc.jj 2025-01-21 16:26:04.154690509 +0100 +++ gcc/cp/typeck.cc 2025-01-22 15:09:09.487161968 +0100 @@ -4867,6 +4867,11 @@ tree build_omp_array_section (location_t loc, tree array_expr, tree index, tree length) { + if (TREE_CODE (array_expr) == TYPE_DECL + || type_dependent_expression_p (array_expr)) + return build3_loc (loc, OMP_ARRAY_SECTION, NULL_TREE, array_expr, index, + length); + tree type = TREE_TYPE (array_expr); gcc_assert (type); type = non_reference (type); --- gcc/testsuite/g++.dg/goacc/pr118590.C.jj 2025-01-22 16:11:29.167592421 +0100 +++ gcc/testsuite/g++.dg/goacc/pr118590.C 2025-01-22 16:09:53.901933174 +0100 @@ -0,0 +1,29 @@ +// PR c++/118590 +// { dg-do compile } + +template <typename T> +struct A +{ + int z; +}; + +template <typename T, typename U> +struct B +{ + char *w; + A<T> y; +}; + +template <typename T, typename U> +void +foo (B<T, U> &x) +{ + A<T> c = x.y; + #pragma acc enter data copyin(x.w[0 : c.z]) +} + +void +bar (B<int, int> &x) +{ + foo (x); +} Jakub