Hi All, The breakage was caused by the patch for PR109345. As it happens, this part of the patch was not required to fix the PR and looked to be a considerable simplification of the condition. Although correct that all is left are class dummies, it caused the regression by not checking that it is a class array reference.
Regtested on mainline. OK to apply to all affected branches after regtesting the backports? Regards Paul Fortran: Partial reversion of patch for pr109345 [PR117763] 2024-11-25 Paul Thomas <pa...@gcc.gnu.org> gcc/fortran PR fortran/117763 * trans-array.cc (gfc_get_array_span): Guard against derefences of 'expr'. Clean up some typos. Use 'gfc_get_vptr_from_expr' for clarity and apply a functional reversion of last section that deals with class dummies. gcc/testsuite/ PR fortran/117763 * gfortran.dg/pr117763.f90: New test.
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 32dcd4cb0c7..a458af322ce 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -961,8 +961,8 @@ tree gfc_get_array_span (tree desc, gfc_expr *expr) { tree tmp; - gfc_symbol *sym = expr->expr_type == EXPR_VARIABLE - ? expr->symtree->n.sym : NULL; + gfc_symbol *sym = (expr && expr->expr_type == EXPR_VARIABLE) ? + expr->symtree->n.sym : NULL; if (is_pointer_array (desc) || (get_CFI_desc (NULL, expr, &desc, NULL) @@ -989,7 +989,7 @@ gfc_get_array_span (tree desc, gfc_expr *expr) { /* Treat unlimited polymorphic expressions separately because the element size need not be the same as the span. Obtain - the class container, which is simplified here by their being + the class container, which is simplified here by there being no component references. */ if (sym && sym->attr.dummy) { @@ -1013,12 +1013,16 @@ gfc_get_array_span (tree desc, gfc_expr *expr) /* The descriptor is a class _data field. Use the vtable size since it is guaranteed to have been set and is always OK for class array descriptors that are not unlimited. */ - tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0)); + tmp = gfc_get_vptr_from_expr (desc); tmp = gfc_vptr_size_get (tmp); } - else if (sym && sym->ts.type == BT_CLASS && sym->attr.dummy) + else if (sym && sym->ts.type == BT_CLASS + && expr->ref->type == REF_COMPONENT + && expr->ref->next->type == REF_ARRAY + && expr->ref->next->next == NULL + && CLASS_DATA (sym)->attr.dimension) { - /* Class dummys usually requires extraction from the saved + /* Class dummys usually require extraction from the saved descriptor, which gfc_class_vptr_get does for us. */ tmp = gfc_class_vptr_get (sym->backend_decl); tmp = gfc_vptr_size_get (tmp); diff --git a/gcc/testsuite/gfortran.dg/pr117763.f90 b/gcc/testsuite/gfortran.dg/pr117763.f90 new file mode 100644 index 00000000000..1c127104d53 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr117763.f90 @@ -0,0 +1,279 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +! +! Test the fix for PR117763, which was a regression caused by the patch for +! PR109345. +! +! Contributed by Juergen Reuter <juergen.reu...@desy.de> +! +module iso_varying_string + implicit none + integer, parameter, private :: GET_BUFFER_LEN = 1 + + type, public :: varying_string + private + character(LEN=1), dimension(:), allocatable :: chars + end type varying_string + + interface assignment(=) + module procedure op_assign_CH_VS + module procedure op_assign_VS_CH + end interface assignment(=) + + interface char + module procedure char_auto + module procedure char_fixed + end interface char + + interface len + module procedure len_ + end interface len + + interface var_str + module procedure var_str_ + end interface var_str + + public :: assignment(=) + public :: char + public :: len + public :: var_str + + private :: op_assign_CH_VS + private :: op_assign_VS_CH + private :: char_auto + private :: char_fixed + private :: len_ + private :: var_str_ + +contains + + elemental function len_ (string) result (length) + type(varying_string), intent(in) :: string + integer :: length + if(ALLOCATED(string%chars)) then + length = SIZE(string%chars) + else + length = 0 + endif + end function len_ + + elemental subroutine op_assign_CH_VS (var, exp) + character(LEN=*), intent(out) :: var + type(varying_string), intent(in) :: exp + var = char(exp) + end subroutine op_assign_CH_VS + + elemental subroutine op_assign_VS_CH (var, exp) + type(varying_string), intent(out) :: var + character(LEN=*), intent(in) :: exp + var = var_str(exp) + end subroutine op_assign_VS_CH + + pure function char_auto (string) result (char_string) + type(varying_string), intent(in) :: string + character(LEN=len(string)) :: char_string + integer :: i_char + forall(i_char = 1:len(string)) + char_string(i_char:i_char) = string%chars(i_char) + end forall + end function char_auto + + pure function char_fixed (string, length) result (char_string) + type(varying_string), intent(in) :: string + integer, intent(in) :: length + character(LEN=length) :: char_string + char_string = char(string) + end function char_fixed + + elemental function var_str_ (char) result (string) + character(LEN=*), intent(in) :: char + type(varying_string) :: string + integer :: length + integer :: i_char + length = LEN(char) + ALLOCATE(string%chars(length)) + forall(i_char = 1:length) + string%chars(i_char) = char(i_char:i_char) + end forall + end function var_str_ + +end module iso_varying_string + +module model_data + use, intrinsic :: iso_c_binding !NODEP! + use iso_varying_string, string_t => varying_string + + implicit none + private + + public :: field_data_t + public :: model_data_t + + type :: field_data_t + private + type(string_t) :: longname + integer :: pdg = 0 + logical :: has_anti = .false. + type(string_t), dimension(:), allocatable :: name, anti + type(string_t) :: tex_name + integer :: multiplicity = 1 + contains + procedure :: init => field_data_init + procedure :: set => field_data_set + procedure :: get_longname => field_data_get_longname + procedure :: get_name_array => field_data_get_name_array + end type field_data_t + + type :: model_data_t + private + type(field_data_t), dimension(:), allocatable :: field + contains + generic :: init => model_data_init + procedure, private :: model_data_init + procedure :: get_field_array_ptr => model_data_get_field_array_ptr + procedure :: get_field_ptr_by_index => model_data_get_field_ptr_index + procedure :: init_sm_test => model_data_init_sm_test + end type model_data_t + + +contains + + subroutine field_data_init (prt, longname, pdg) + class(field_data_t), intent(out) :: prt + type(string_t), intent(in) :: longname + integer, intent(in) :: pdg + prt%longname = longname + prt%pdg = pdg + prt%tex_name = "" + end subroutine field_data_init + + subroutine field_data_set (prt, & + name, anti, tex_name) + class(field_data_t), intent(inout) :: prt + type(string_t), dimension(:), intent(in), optional :: name, anti + type(string_t), intent(in), optional :: tex_name + if (present (name)) then + if (allocated (prt%name)) deallocate (prt%name) + allocate (prt%name (size (name)), source = name) + end if + if (present (anti)) then + if (allocated (prt%anti)) deallocate (prt%anti) + allocate (prt%anti (size (anti)), source = anti) + prt%has_anti = .true. + end if + if (present (tex_name)) prt%tex_name = tex_name + end subroutine field_data_set + + pure function field_data_get_longname (prt) result (name) + type(string_t) :: name + class(field_data_t), intent(in) :: prt + name = prt%longname + end function field_data_get_longname + + subroutine field_data_get_name_array (prt, is_antiparticle, name) + class(field_data_t), intent(in) :: prt + logical, intent(in) :: is_antiparticle + type(string_t), dimension(:), allocatable, intent(inout) :: name + if (allocated (name)) deallocate (name) + if (is_antiparticle) then + if (prt%has_anti) then + allocate (name (size (prt%anti))) + name = prt%anti + else + allocate (name (0)) + end if + else + allocate (name (size (prt%name))) + name = prt%name + end if + end subroutine field_data_get_name_array + + subroutine model_data_init (model, n_field) + class(model_data_t), intent(out) :: model + integer, intent(in) :: n_field + allocate (model%field (n_field)) + end subroutine model_data_init + + function model_data_get_field_array_ptr (model) result (ptr) + class(model_data_t), intent(in), target :: model + type(field_data_t), dimension(:), pointer :: ptr + ptr => model%field + end function model_data_get_field_array_ptr + + function model_data_get_field_ptr_index (model, i) result (ptr) + class(model_data_t), intent(in), target :: model + integer, intent(in) :: i + type(field_data_t), pointer :: ptr + ptr => model%field(i) + end function model_data_get_field_ptr_index + + subroutine model_data_init_sm_test (model) + class(model_data_t), intent(out) :: model + type(field_data_t), pointer :: field + integer :: i + call model%init (2) + i = 0 + i = i + 1 + field => model%get_field_ptr_by_index (i) + call field%init (var_str ("W_BOSON"), 24) + call field%set (name = [var_str ("W+")], anti = [var_str ("W-")]) + i = i + 1 + field => model%get_field_ptr_by_index (i) + call field%init (var_str ("HIGGS"), 25) + call field%set (name = [var_str ("H")]) + end subroutine model_data_init_sm_test + +end module model_data + + +module models + use, intrinsic :: iso_c_binding !NODEP! + use iso_varying_string, string_t => varying_string + use model_data +! use parser +! use variables + implicit none + private + public :: model_t + + type, extends (model_data_t) :: model_t + private + contains + procedure :: append_field_vars => model_append_field_vars + end type model_t + +contains + + subroutine model_append_field_vars (model) + class(model_t), intent(inout) :: model + type(field_data_t), dimension(:), pointer :: field_array + type(field_data_t), pointer :: field + type(string_t) :: name + type(string_t), dimension(:), allocatable :: name_array + integer :: i, j + field_array => model%get_field_array_ptr () + do i = 1, size (field_array) + name = field_array(i)%get_longname () + call field_array(i)%get_name_array (.false., name_array) + end do + end subroutine model_append_field_vars + +end module models + + +program main_ut + use iso_varying_string, string_t => varying_string + use model_data + use models + implicit none + + class(model_data_t), pointer :: model + model => null () + allocate (model_t :: model) + select type (model) + type is (model_t) + call model%init_sm_test () + call model%append_field_vars () + end select +end program main_ut +! { dg-final { scan-tree-dump-times "__result->span = 272" 1 "original" } } diff --git a/gcc/testsuite/gfortran.dg/pr85869.f90 b/gcc/testsuite/gfortran.dg/pr84869.f90 similarity index 89% rename from gcc/testsuite/gfortran.dg/pr85869.f90 rename to gcc/testsuite/gfortran.dg/pr84869.f90 index 24caeb486f2..fe40b620804 100644 --- a/gcc/testsuite/gfortran.dg/pr85869.f90 +++ b/gcc/testsuite/gfortran.dg/pr84869.f90 @@ -1,6 +1,6 @@ ! { dg-do compile } ! -! Test the fix for PR85869, where line 19 segfaulted. +! Test the fix for PR84869, where line 19 segfaulted. ! ! Contributed by Gerhard Steinmetz <gs...@t-online.de> !