https://gcc.gnu.org/g:7810623e8cfa82e5d0d1952e8443a0c88f140690
commit r16-9103-g7810623e8cfa82e5d0d1952e8443a0c88f140690 Author: Jerry DeLisle <[email protected]> Date: Sat Jun 6 10:06:17 2026 -0700 fortran: wrong-code in DO CONCURRENT with ASSOCIATE When an ASSOCIATE body references inline type-spec iterator, replace_in_code_recursive lacked a case for EXEC_BLOCK (associate constructs). So, it silently skipped both the ASSOCIATE selector expressions and the body when replacing shadow iterator references. Add case EXEC_BLOCK to iterate over each selector's target expression via replace_in_expr_recursive and recurse into the body namespace's code list via replace_in_code_recursive. Assisted-by: Claude Sonnet 4.6 PR fortran/125532 gcc/fortran/ChangeLog: * resolve.cc (replace_in_code_recursive): Add EXEC_BLOCK case to replace shadow iterator references in ASSOCIATE selector expressions and the ASSOCIATE body namespace. gcc/testsuite/ChangeLog: * gfortran.dg/do_concurrent_assoc_iter_1.f90: New test. (cherry picked from commit e363588d7386e54fdaa8910df52f3cddfe062cb4) Diff: --- gcc/fortran/resolve.cc | 16 +++++++++++++- .../gfortran.dg/do_concurrent_assoc_iter_1.f90 | 25 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index a5d9add9d2fa..eca35ef4b633 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -12588,7 +12588,8 @@ gfc_count_forall_iterators (gfc_code *code) 3) call gfc_resolve_forall_body to resolve the FORALL body. */ /* Custom recursive expression walker that replaces symbols. - This ensures we visit ALL expressions including those in array subscripts. */ + Visits all expressions including array subscripts. Also called from + replace_in_code_recursive to handle ASSOCIATE selector expressions. */ static void replace_in_expr_recursive (gfc_expr *expr, gfc_symbol *old_sym, gfc_symtree *new_st) @@ -12715,6 +12716,19 @@ replace_in_code_recursive (gfc_code *code, gfc_symbol *old_sym, gfc_symtree *new they'll be handled separately */ break; + case EXEC_BLOCK: + /* Replace in ASSOCIATE selector expressions and the body. + The body of an EXEC_BLOCK lives in c->ext.block.ns->code, not + c->block->next, so without this case both selectors and body + are silently skipped, leaving shadow iterator references unreplaced + and producing wrong values at runtime. */ + for (gfc_association_list *alist = c->ext.block.assoc; + alist; alist = alist->next) + replace_in_expr_recursive (alist->target, old_sym, new_st); + if (c->ext.block.ns) + replace_in_code_recursive (c->ext.block.ns->code, old_sym, new_st); + break; + default: break; } diff --git a/gcc/testsuite/gfortran.dg/do_concurrent_assoc_iter_1.f90 b/gcc/testsuite/gfortran.dg/do_concurrent_assoc_iter_1.f90 new file mode 100644 index 000000000000..5b7e4f9b2053 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/do_concurrent_assoc_iter_1.f90 @@ -0,0 +1,25 @@ +! { dg-do run } +! PR fortran/125532 +! DO CONCURRENT with inline type-spec iterator used inside an ASSOCIATE body +! produced wrong values: replace_in_code_recursive lacked an EXEC_BLOCK case +! so shadow iterator references were not replaced. +program do_concurrent_assoc_iter_1 + implicit none + integer :: a(5), b(5) + a = 0 + b = 0 + ! Iterator k used in the ASSOCIATE selector and in the body. + do concurrent (integer :: k = 1:5) + associate (sq => k * k) + a(k) = sq + end associate + end do + ! Iterator k used only inside the body (not in selector). + do concurrent (integer :: k = 1:5) + associate (v => k) + b(v) = k + 10 + end associate + end do + if (any (a /= [1, 4, 9, 16, 25])) stop 1 + if (any (b /= [11, 12, 13, 14, 15])) stop 2 +end program
