Hi! This fixes Fortran !$omp atomic handling to match C/C++, goa_lhs_expr_p is not able to find out matches of more complex expressions after tree unsharing, so this patch helps it find what it needs.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. Will backport soon. 2014-11-24 Jakub Jelinek <ja...@redhat.com> PR fortran/63938 * trans-openmp.c (gfc_trans_omp_atomic): Make sure lhsaddr is simple enough for goa_lhs_expr_p. * libgomp.fortran/pr63938-1.f90: New test. * libgomp.fortran/pr63938-2.f90: New test. --- gcc/fortran/trans-openmp.c.jj 2014-10-10 13:07:42.000000000 +0200 +++ gcc/fortran/trans-openmp.c 2014-11-24 11:25:40.157171398 +0100 @@ -2683,6 +2683,18 @@ gfc_trans_omp_atomic (gfc_code *code) } lhsaddr = save_expr (lhsaddr); + if (TREE_CODE (lhsaddr) != SAVE_EXPR + && (TREE_CODE (lhsaddr) != ADDR_EXPR + || TREE_CODE (TREE_OPERAND (lhsaddr, 0)) != VAR_DECL)) + { + /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize + it even after unsharing function body. */ + tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr), NULL); + DECL_CONTEXT (var) = current_function_decl; + lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, + NULL_TREE, NULL_TREE); + } + rhs = gfc_evaluate_now (rse.expr, &block); if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK) --- libgomp/testsuite/libgomp.fortran/pr63938-1.f90.jj 2014-11-24 11:27:33.060113895 +0100 +++ libgomp/testsuite/libgomp.fortran/pr63938-1.f90 2014-11-24 11:28:13.339379860 +0100 @@ -0,0 +1,14 @@ +! PR fortran/63938 +! { dg-do run } + +program pr63938_1 + integer :: i, x(1) + x(1) = 0 +!$omp parallel do + do i = 1, 1000 + !$omp atomic + x(1) = x(1) + 1 + end do +!$omp end parallel do + if (x(1) .ne. 1000) call abort +end program pr63938_1 --- libgomp/testsuite/libgomp.fortran/pr63938-2.f90.jj 2014-11-24 11:28:22.836206793 +0100 +++ libgomp/testsuite/libgomp.fortran/pr63938-2.f90 2014-11-24 11:28:53.217653132 +0100 @@ -0,0 +1,18 @@ +! PR fortran/63938 +! { dg-do run } + +program pr63938_2 + type t + integer :: x + end type + integer :: i + type(t) :: x + x%x = 0 +!$omp parallel do + do i = 1, 1000 + !$omp atomic + x%x = x%x + 1 + end do +!$omp end parallel do + if (x%x .ne. 1000) call abort +end program pr63938_2 Jakub