diff --git a/changelog b/changelog index 716580bcbe..c2f3bc4410 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,6 @@ + 3) PR #3456 for #3446. Fix issues with CodeBlocks and routine names + in the presence of comments. + 2) PR #3450 for #3262. Updates the LFRic GPU scripts and aggregates the transformation statistics. diff --git a/src/psyclone/psyir/nodes/routine.py b/src/psyclone/psyir/nodes/routine.py index 8adbec14a2..a5f44c8b58 100644 --- a/src/psyclone/psyir/nodes/routine.py +++ b/src/psyclone/psyir/nodes/routine.py @@ -354,7 +354,12 @@ def update_parent_symbol_table(self, new_parent): (Fortran2003.Subroutine_Subprogram, Fortran2003.Function_Subprogram)) for routine in routines: - name = str(routine.children[0].children[1]) + # Have to walk to find the subroutine_stmt as + # comments can appear before the subroutine stmt. + subroutine_stmt = walk(routine, + (Fortran2003.Subroutine_Stmt, + Fortran2003.Function_Stmt)) + name = str(subroutine_stmt[0].children[1]) if name == self.name: raise GenerationError( f"Can't add routine '{self.name}' into" diff --git a/src/psyclone/tests/psyir/nodes/routine_test.py b/src/psyclone/tests/psyir/nodes/routine_test.py index 7123e1b1d8..ba93006a1b 100644 --- a/src/psyclone/tests/psyir/nodes/routine_test.py +++ b/src/psyclone/tests/psyir/nodes/routine_test.py @@ -43,6 +43,7 @@ from psyclone.errors import GenerationError from psyclone.psyGen import CodedKern +from psyclone.psyir.frontend.fortran import FortranReader from psyclone.psyir.nodes import (Assignment, Call, CodeBlock, Container, Literal, Reference, Routine, ScopingNode) from psyclone.psyir.symbols import ( @@ -400,6 +401,47 @@ def test_routine_update_parent_symbol_table_illegal_parent(fortran_reader): in str(excinfo.value)) +@pytest.mark.parametrize("routine_type", ["function", "subroutine"]) +def test_routine_update_parent_symbol_table_with_comments(routine_type): + ''' Test when we have a CodeBlock representing a routine that + if there are also comments before it in the tree we can still + check the name of the subroutine without failing inside + update_parent_symbol_table. ''' + + code = f"""module test + + contains + + ! This routine will be a codeblock. + {routine_type} routine() + procedure (halo_exchange_routine) :: exchange_halo_group + end {routine_type} + + subroutine routine1(a, b, c) + integer, intent(inout) :: a, b, c + + call routine2() + end subroutine + + subroutine routine2() + + end subroutine + +end module""" + + fortran_reader = FortranReader(ignore_comments=False) + psyir = fortran_reader.psyir_from_source(code) + alt_routine = Routine.create("routine") + + module = psyir.walk(Container)[1] + assert isinstance(module.children[0], CodeBlock) + with pytest.raises(GenerationError) as excinfo: + module.addchild(alt_routine) + assert ("Can't add routine 'routine' into a scope that already contains " + "a resolved symbol with the same name." + in str(excinfo.value)) + + def test_routine_update_parent_symbol_table(): ''' Test the update_parent_symbol_table function of the Routine class. Some of the tests here are accessed through addchild of a container. '''