[2/2] fortran: Add bounds checking code to the scalarizer block [PR125192]
Commit Message
From: Mikael Morin <mikael@gcc.gnu.org>
With the previous refactoring patch, the fix becomes trivial.
The testcase includes the examples from both PR125192 and PR125198.
For some reason, the testcase with an unpatched compiler causes a
segmentation fault when run with the test harness, and the out of bounds
runtime error as in the PR when executed manually. As I could reliably
get a testsuite FAIL that is fixed by the patch, I haven't investigated
further. The code generated by the front-end was invalid anyway.
Regression-tested on powerpc64le-unknown-linux-gnu.
OK for master and 16 backport?
-- >8 --
In gfc_conv_expr_descriptor, the array bounds checking code is added
to the root block, which is a different block from the scalarizer block
used to generate the array descriptor reference. This causes the array
bounds checking code to come before, which can be problematic if the
descriptor reference uses variables generated by the scalarizer, as they
are used in bounds checking code before their definition in that case.
This change adds the bounds checking code to the same block the
scalarizer uses to generate the array descriptor reference, solving the
use before definition problem.
PR fortran/125192
PR fortran/125198
gcc/fortran/ChangeLog:
* trans-array.cc (gfc_conv_expr_descriptor): Add bounds checking
code to the outermost loop's preliminary block.
gcc/testsuite/ChangeLog:
* gfortran.dg/bounds_check_29.f90: New test.
---
gcc/fortran/trans-array.cc | 2 +-
gcc/testsuite/gfortran.dg/bounds_check_29.f90 | 62 +++++++++++++++++++
2 files changed, 63 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gfortran.dg/bounds_check_29.f90
Comments
Hello Mikae,
This together with the first part are good to go. I leave it to you as
to when to backport to 16-branch.
Thanks for both the patches.
Regards
Paul
Paul
On Wed, 6 May 2026 at 21:49, Mikael Morin <morin-mikael@orange.fr> wrote:
>
> From: Mikael Morin <mikael@gcc.gnu.org>
>
> With the previous refactoring patch, the fix becomes trivial.
>
> The testcase includes the examples from both PR125192 and PR125198.
> For some reason, the testcase with an unpatched compiler causes a
> segmentation fault when run with the test harness, and the out of bounds
> runtime error as in the PR when executed manually. As I could reliably
> get a testsuite FAIL that is fixed by the patch, I haven't investigated
> further. The code generated by the front-end was invalid anyway.
>
> Regression-tested on powerpc64le-unknown-linux-gnu.
> OK for master and 16 backport?
>
> -- >8 --
>
> In gfc_conv_expr_descriptor, the array bounds checking code is added
> to the root block, which is a different block from the scalarizer block
> used to generate the array descriptor reference. This causes the array
> bounds checking code to come before, which can be problematic if the
> descriptor reference uses variables generated by the scalarizer, as they
> are used in bounds checking code before their definition in that case.
>
> This change adds the bounds checking code to the same block the
> scalarizer uses to generate the array descriptor reference, solving the
> use before definition problem.
>
> PR fortran/125192
> PR fortran/125198
>
> gcc/fortran/ChangeLog:
>
> * trans-array.cc (gfc_conv_expr_descriptor): Add bounds checking
> code to the outermost loop's preliminary block.
>
> gcc/testsuite/ChangeLog:
>
> * gfortran.dg/bounds_check_29.f90: New test.
> ---
> gcc/fortran/trans-array.cc | 2 +-
> gcc/testsuite/gfortran.dg/bounds_check_29.f90 | 62 +++++++++++++++++++
> 2 files changed, 63 insertions(+), 1 deletion(-)
> create mode 100644 gcc/testsuite/gfortran.dg/bounds_check_29.f90
>
> diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
> index 4f86ae2889b..cb55e5082d4 100644
> --- a/gcc/fortran/trans-array.cc
> +++ b/gcc/fortran/trans-array.cc
> @@ -8652,7 +8652,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
>
> /* Add bounds-checking for elemental dimensions. */
> if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !expr->no_bounds_check)
> - array_bound_check_elemental (&se->pre, ss, expr);
> + array_bound_check_elemental (&outermost_loop (&loop)->pre, ss, expr);
>
> if (need_tmp)
> {
> diff --git a/gcc/testsuite/gfortran.dg/bounds_check_29.f90 b/gcc/testsuite/gfortran.dg/bounds_check_29.f90
> new file mode 100644
> index 00000000000..42ab7afaa47
> --- /dev/null
> +++ b/gcc/testsuite/gfortran.dg/bounds_check_29.f90
> @@ -0,0 +1,62 @@
> +! { dg-do run }
> +! { dg-additional-options "-fcheck=bounds" }
> +!
> +! Check that if an array descriptor reference uses variables, they are
> +! not used uninitialized by the bounds-checking code.
> +
> +
> +! PR fortran/125192
> +! Original example from Philippe Wautelet <philippe.wautelet at cnrs dot fr>
> +
> +subroutine boundcheck_bug
> + implicit none
> +
> + type isba_pe_t
> + real, pointer, dimension(:,:) :: xwg
> + end type isba_pe_t
> + type isba_npe_t
> + type(isba_pe_t), dimension(:), pointer :: al=>null()
> + end type isba_npe_t
> + type(isba_npe_t) :: npe
> +
> + allocate(npe%al(10))
> + allocate(npe%al(1)%xwg(3,4))
> +
> + call random_number( npe%al(1)%xwg(:,3) )
> +end subroutine boundcheck_bug
> +
> +
> +! PR fortran/125198
> +! Original example from Neil Carlson <neil.n.carlson at gmail dot com>
> +
> +module unstr_mesh_type
> + type unstr_mesh
> + real, allocatable :: normal(:,:)
> + contains
> + procedure :: compute_geometry
> + end type
> +contains
> + subroutine compute_geometry(this)
> + class(unstr_mesh), intent(inout) :: this
> + character(64) :: buf
> + !print *, this%normal(1,1) ! THIS IS OKAY
> + write(buf,*) this%normal(1,1)
> + if (trim(buf) /= ' 0.00000000') error stop 1
> + !print *, this%normal(:,1) ! SPURIOUS BOUNDS ERROR HERE
> + write(buf,*) this%normal(:,1)
> + if (trim(buf) /= ' 0.00000000 0.00000000 0.00000000') error stop 2
> + !if (any(this%normal(:,1) /= 0.0)) error stop 2
> + end subroutine
> +end module
> +
> +subroutine test_pr125198
> +use unstr_mesh_type
> +type(unstr_mesh) :: mesh
> +allocate(mesh%normal(3,10), source=0.0)
> +call mesh%compute_geometry
> +end subroutine
> +
> +
> +call boundcheck_bug
> +call test_pr125198
> +end
> --
> 2.53.0
>
@@ -8652,7 +8652,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
/* Add bounds-checking for elemental dimensions. */
if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !expr->no_bounds_check)
- array_bound_check_elemental (&se->pre, ss, expr);
+ array_bound_check_elemental (&outermost_loop (&loop)->pre, ss, expr);
if (need_tmp)
{
new file mode 100644
@@ -0,0 +1,62 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=bounds" }
+!
+! Check that if an array descriptor reference uses variables, they are
+! not used uninitialized by the bounds-checking code.
+
+
+! PR fortran/125192
+! Original example from Philippe Wautelet <philippe.wautelet at cnrs dot fr>
+
+subroutine boundcheck_bug
+ implicit none
+
+ type isba_pe_t
+ real, pointer, dimension(:,:) :: xwg
+ end type isba_pe_t
+ type isba_npe_t
+ type(isba_pe_t), dimension(:), pointer :: al=>null()
+ end type isba_npe_t
+ type(isba_npe_t) :: npe
+
+ allocate(npe%al(10))
+ allocate(npe%al(1)%xwg(3,4))
+
+ call random_number( npe%al(1)%xwg(:,3) )
+end subroutine boundcheck_bug
+
+
+! PR fortran/125198
+! Original example from Neil Carlson <neil.n.carlson at gmail dot com>
+
+module unstr_mesh_type
+ type unstr_mesh
+ real, allocatable :: normal(:,:)
+ contains
+ procedure :: compute_geometry
+ end type
+contains
+ subroutine compute_geometry(this)
+ class(unstr_mesh), intent(inout) :: this
+ character(64) :: buf
+ !print *, this%normal(1,1) ! THIS IS OKAY
+ write(buf,*) this%normal(1,1)
+ if (trim(buf) /= ' 0.00000000') error stop 1
+ !print *, this%normal(:,1) ! SPURIOUS BOUNDS ERROR HERE
+ write(buf,*) this%normal(:,1)
+ if (trim(buf) /= ' 0.00000000 0.00000000 0.00000000') error stop 2
+ !if (any(this%normal(:,1) /= 0.0)) error stop 2
+ end subroutine
+end module
+
+subroutine test_pr125198
+use unstr_mesh_type
+type(unstr_mesh) :: mesh
+allocate(mesh%normal(3,10), source=0.0)
+call mesh%compute_geometry
+end subroutine
+
+
+call boundcheck_bug
+call test_pr125198
+end