diff --git a/loki/transform/transform_inline.py b/loki/transform/transform_inline.py index edf59e2e1..62974cf18 100644 --- a/loki/transform/transform_inline.py +++ b/loki/transform/transform_inline.py @@ -24,8 +24,10 @@ from loki.logging import warning, error from loki.pragma_utils import pragmas_attached, is_loki_pragma -from loki.transform.transform_utilities import single_variable_declaration - +from loki.transform.transform_utilities import ( + single_variable_declaration, + recursive_expression_map_update +) __all__ = [ 'inline_constant_parameters', 'inline_elemental_functions', @@ -208,9 +210,6 @@ def map_call_to_procedure_body(call, caller): Procedure (scope) into which the callee's body gets mapped """ - # pylint: disable=import-outside-toplevel,cyclic-import - from loki.transform import recursive_expression_map_update - def _map_unbound_dims(var, val): """ Maps all unbound dimension ranges in the passed array value @@ -339,6 +338,7 @@ def inline_subroutine_calls(routine, calls, callee, allowed_aliases=None): for v in FindVariables(unique=False).visit(callee.body): if v.name.lower() in duplicate_names: var_map[v] = v.clone(name=f'{callee.name}_{v.name}') + var_map = recursive_expression_map_update(var_map) callee.body = SubstituteExpressions(var_map).visit(callee.body) # Separate allowed aliases from other variables to ensure clean hoisting diff --git a/tests/test_transform_inline.py b/tests/test_transform_inline.py index ec70d1113..c7430b04d 100644 --- a/tests/test_transform_inline.py +++ b/tests/test_transform_inline.py @@ -569,6 +569,41 @@ def test_inline_internal_routines_aliasing_declaration(frontend): assert assigns[3].lhs == 'jg' and assigns[3].rhs == '2' assert assigns[4].lhs == 'z' and assigns[4].rhs == 'jlon + jg' +@pytest.mark.parametrize('frontend', available_frontends()) +def test_inline_member_routines_indexing_of_shadowed_array(frontend): + """ + Test special case of inlining of member subroutines when inlined routine contains + shadowed array and array indices. + In particular, this test checks that also the variables indexing + the array in the inlined result get renamed correctly. + """ + fcode = """ + subroutine outer(klon) + integer :: jg, jlon + integer :: arr(3, 3) + + jg = 70000 + call inner2() + + contains + + subroutine inner2() + integer :: jlon, jg + integer :: arr(3, 3) + do jg=1,3 + do jlon=1,3 + arr(jlon, jg) = 11 + end do + end do + end subroutine inner2 + + end subroutine outer + """ + routine = Subroutine.from_source(fcode, frontend=frontend) + inline_member_procedures(routine) + innerloop = FindNodes(Loop).visit(routine.body)[1] + innerloopvars = FindVariables().visit(innerloop) + assert 'inner2_arr(inner2_jlon,inner2_jg)' in innerloopvars @pytest.mark.parametrize('frontend', available_frontends()) def test_inline_member_routines_sequence_assoc(frontend):