diff options
author | Paul Thomas <pault@gcc.gnu.org> | 2019-04-22 06:50:33 +0000 |
---|---|---|
committer | Paul Thomas <pault@gcc.gnu.org> | 2019-04-22 06:50:33 +0000 |
commit | 16a51cf5491b642639b60ea12c0fff12a5403934 (patch) | |
tree | 3df2343a26f4954033b65ca19113ed070fefedfd /gcc | |
parent | 76a86e861665f8fc9595969112eb5a08590b5a29 (diff) | |
download | gcc-16a51cf5491b642639b60ea12c0fff12a5403934.zip gcc-16a51cf5491b642639b60ea12c0fff12a5403934.tar.gz gcc-16a51cf5491b642639b60ea12c0fff12a5403934.tar.bz2 |
re PR fortran/57284 ([OOP] ICE with find_array_spec for polymorphic arrays)
2019-04-22 Paul Thomas <pault@gcc.gnu.org>
PR fortran/57284
* resolve.c (find_array_spec): If this is a class expression
and the symbol and component array specs are the same, this is
not an error.
*trans-intrinsic.c (gfc_conv_intrinsic_size): If a class symbol
argument, has no namespace, it has come from the interface
mapping and the _data component must be accessed directly.
2019-04-22 Paul Thomas <pault@gcc.gnu.org>
PR fortran/57284
* gfortran.dg/class_70.f03
From-SVN: r270489
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/fortran/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/fortran/resolve.c | 8 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/class_70.f03 | 38 |
5 files changed, 82 insertions, 4 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 1ff03e1..6a11bf5 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,13 @@ +2019-04-22 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/57284 + * resolve.c (find_array_spec): If this is a class expression + and the symbol and component array specs are the same, this is + not an error. + *trans-intrinsic.c (gfc_conv_intrinsic_size): If a class symbol + argument, has no namespace, it has come from the interface + mapping and the _data component must be accessed directly. + 2019-04-17 Thomas Schwinge <thomas@codesourcery.com> PR fortran/90048 diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index cb41da0..8232deb 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -4712,9 +4712,13 @@ find_array_spec (gfc_expr *e) gfc_array_spec *as; gfc_component *c; gfc_ref *ref; + bool class_as = false; if (e->symtree->n.sym->ts.type == BT_CLASS) - as = CLASS_DATA (e->symtree->n.sym)->as; + { + as = CLASS_DATA (e->symtree->n.sym)->as; + class_as = true; + } else as = e->symtree->n.sym->as; @@ -4733,7 +4737,7 @@ find_array_spec (gfc_expr *e) c = ref->u.c.component; if (c->attr.dimension) { - if (as != NULL) + if (as != NULL && !(class_as && as == c->as)) gfc_internal_error ("find_array_spec(): unused as(1)"); as = c->as; } diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 2eb5d1a..e0a4c67 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -7446,6 +7446,8 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr) tree fncall0; tree fncall1; gfc_se argse; + gfc_expr *e; + gfc_symbol *sym = NULL; gfc_init_se (&argse, NULL); actual = expr->value.function.actual; @@ -7453,12 +7455,31 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr) if (actual->expr->ts.type == BT_CLASS) gfc_add_class_array_ref (actual->expr); + e = actual->expr; + + /* These are emerging from the interface mapping, when a class valued + function appears as the rhs in a realloc on assign statement, where + the size of the result is that of one of the actual arguments. */ + if (e->expr_type == EXPR_VARIABLE + && e->symtree->n.sym->ns == NULL /* This is distinctive! */ + && e->symtree->n.sym->ts.type == BT_CLASS + && e->ref && e->ref->type == REF_COMPONENT + && strcmp (e->ref->u.c.component->name, "_data") == 0) + sym = e->symtree->n.sym; + argse.data_not_needed = 1; - if (gfc_is_class_array_function (actual->expr)) + if (gfc_is_class_array_function (e)) { /* For functions that return a class array conv_expr_descriptor is not able to get the descriptor right. Therefore this special case. */ - gfc_conv_expr_reference (&argse, actual->expr); + gfc_conv_expr_reference (&argse, e); + argse.expr = gfc_build_addr_expr (NULL_TREE, + gfc_class_data_get (argse.expr)); + } + else if (sym && sym->backend_decl) + { + gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym->backend_decl))); + argse.expr = sym->backend_decl; argse.expr = gfc_build_addr_expr (NULL_TREE, gfc_class_data_get (argse.expr)); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9833824..4d10bfd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-04-22 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/57284 + * gfortran.dg/class_70.f03 + 2019-04-21 H.J. Lu <hongjiu.lu@intel.com> PR target/90178 diff --git a/gcc/testsuite/gfortran.dg/class_70.f03 b/gcc/testsuite/gfortran.dg/class_70.f03 new file mode 100644 index 0000000..b689563 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/class_70.f03 @@ -0,0 +1,38 @@ +! { dg-do run } +! +! Test the fix for PR57284 - [OOP] ICE with find_array_spec for polymorphic +! arrays. Once thw ICE was fixed, work was needed to fix a segfault while +! determining the size of 'z'. +! +! Contributed by Lorenz Huedepohl <bugs@stellardeath.org> +! +module testmod + type type_t + integer :: idx + end type type_t + type type_u + type(type_t), allocatable :: cmp(:) + end type +contains + function foo(a, b) result(add) + class(type_t), intent(in) :: a(:), b(size(a)) + type(type_t) :: add(size(a)) + add%idx = a%idx + b%idx + end function +end module testmod +program p + use testmod + class(type_t), allocatable, dimension(:) :: x, y, z + class(type_u), allocatable :: w + allocate (x, y, source = [type_t (1), type_t(2)]) + z = foo (x, y) + if (any (z%idx .ne. [2, 4])) stop 1 + +! Try something a bit more complicated than the original. + + allocate (w) + allocate (w%cmp, source = [type_t (2), type_t(3)]) + z = foo (w%cmp, y) + if (any (z%idx .ne. [3, 5])) stop 2 + deallocate (w, x, y, z) +end program |