Hi! allocatable privatized vars need access to the outer var for sizing, but unlike e.g. firstprivate the standard allows them on orphaned worksharing constructs or when the var is already private outside of the worksharing construct. Therefore, we should treat it similarly to outer refs on simd construct.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. 2016-11-23 Jakub Jelinek <ja...@redhat.com> PR middle-end/69183 * omp-low.c (build_outer_var_ref): Change lastprivate argument to code, pass it recursively, adjust uses. For OMP_CLAUSE_PRIVATE on worksharing constructs, treat it like clauses on simd construct. Formatting fix. (lower_rec_input_clauses): For OMP_CLAUSE_PRIVATE_OUTER_REF pass OMP_CLAUSE_PRIVATE as last argument to build_outer_var_ref. (lower_lastprivate_clauses): Pass OMP_CLAUSE_LASTPRIVATE instead of true as last argument to build_outer_var_ref. * gfortran.dg/gomp/pr69183.f90: New test. --- gcc/omp-low.c.jj 2016-11-22 21:31:49.000000000 +0100 +++ gcc/omp-low.c 2016-11-23 16:20:31.830429649 +0100 @@ -1283,7 +1283,8 @@ build_receiver_ref (tree var, bool by_re this is some variable. */ static tree -build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false) +build_outer_var_ref (tree var, omp_context *ctx, + enum omp_clause_code code = OMP_CLAUSE_ERROR) { tree x; @@ -1292,7 +1293,7 @@ build_outer_var_ref (tree var, omp_conte else if (is_variable_sized (var)) { x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0); - x = build_outer_var_ref (x, ctx, lastprivate); + x = build_outer_var_ref (x, ctx, code); x = build_simple_mem_ref (x); } else if (is_taskreg_ctx (ctx)) @@ -1300,11 +1301,17 @@ build_outer_var_ref (tree var, omp_conte bool by_ref = use_pointer_for_field (var, NULL); x = build_receiver_ref (var, by_ref, ctx); } - else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) - { - /* #pragma omp simd isn't a worksharing construct, and can reference even - private vars in its linear etc. clauses. */ + else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR + && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) + || (code == OMP_CLAUSE_PRIVATE + && (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR + || gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS + || gimple_code (ctx->stmt) == GIMPLE_OMP_SINGLE))) + { + /* #pragma omp simd isn't a worksharing construct, and can reference + even private vars in its linear etc. clauses. + Similarly for OMP_CLAUSE_PRIVATE with outer ref, that can refer + to private vars in all worksharing constructs. */ x = NULL_TREE; if (ctx->outer && is_taskreg_ctx (ctx)) x = lookup_decl (var, ctx->outer); @@ -1313,7 +1320,7 @@ build_outer_var_ref (tree var, omp_conte if (x == NULL_TREE) x = var; } - else if (lastprivate && is_taskloop_ctx (ctx)) + else if (code == OMP_CLAUSE_LASTPRIVATE && is_taskloop_ctx (ctx)) { gcc_assert (ctx->outer); splay_tree_node n @@ -1350,7 +1357,7 @@ build_outer_var_ref (tree var, omp_conte gcc_assert (outer && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY); } - x = lookup_decl (var, outer); + x = lookup_decl (var, outer); } else if (is_reference (var)) /* This can happen with orphaned constructs. If var is reference, it is @@ -5031,7 +5038,7 @@ lower_rec_input_clauses (tree clauses, g if (is_task_ctx (ctx)) x = build_receiver_ref (var, false, ctx); else - x = build_outer_var_ref (var, ctx); + x = build_outer_var_ref (var, ctx, OMP_CLAUSE_PRIVATE); } else x = NULL; @@ -5687,7 +5694,7 @@ lower_lastprivate_clauses (tree clauses, x = ovar; } if (!x) - x = build_outer_var_ref (var, ctx, true); + x = build_outer_var_ref (var, ctx, OMP_CLAUSE_LASTPRIVATE); if (is_reference (var)) new_var = build_simple_mem_ref_loc (clause_loc, new_var); x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var); --- gcc/testsuite/gfortran.dg/gomp/pr69183.f90.jj 2016-11-23 16:18:55.801635373 +0100 +++ gcc/testsuite/gfortran.dg/gomp/pr69183.f90 2016-11-23 16:18:41.000000000 +0100 @@ -0,0 +1,11 @@ +! PR middle-end/69183 +! { dg-do compile } + +program pr69183 + integer, allocatable :: z + integer :: i + !$omp do private(z) + do i = 1, 2 + z = i + end do +end Jakub