Assumes that patch http://gcc.gnu.org/ml/fortran/2009-10/msg00049.html is already committed. As written in http://gcc.gnu.org/ml/fortran/2009-10/msg00047.html, array valued expressions do not work; presumably some other attributes need also to be copied/honored. (cf. also PR 41599.) implicit none type t0 integer :: j = 42 end type t0 type t integer :: i class(t0), allocatable :: foo(:) end type t type(t) :: m allocate(t0 :: m%foo(3)) m%i = 5 select type(bar => m%foo) type is(t0) print *, bar end select end
Related example (PR42888 comment #17): implicit none type t integer :: X = -999.0 end type t class(t), allocatable :: y(:) allocate (t::y(1)) ! ICE end
The tests in comments #0 and #1 give a "Segmentation fault" with trunk or fortran-dev.
(Those comments are for the example in comment 1) The ICE happens for: integer :: X = -999.0 where one calls gfc_trans_scalar_assign with ts.type == BT_INTEGER and fold convert fails to convert the constant 999.0 to an integer. Without type spec, one uses the _vtab->__def_init while with type spec, one directly assigns. That's toggled in resolve.c:7018 (resolve_allocate_expr). With type spec, one has a call to gfc_default_initializer. In principle, the FE should convert 999.0 into 999. This happens twice via gfc_convert_type_warn, which is called via: resolve_types -> resolve_values -> resolve_structure_cons. But seemingly there is still some loop whole where it does not happen. Draft: --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -3776,3 +3782,8 @@ gfc_default_initializer (gfc_typespec *ts) if (comp->initializer) - ctor->expr = gfc_copy_expr (comp->initializer); + { + ctor->expr = gfc_copy_expr (comp->initializer); + if (comp->ts.type != comp->initializer->ts.type + || comp->ts.kind != comp->initializer->ts.kind) + gfc_convert_type_warn (ctor->expr, &comp->ts, 2, false); + } * * * OK, that fixed comment 1. But comment 0 still has issues: a) As is, it fails at: hfj3af.f90:1:0: internal compiler error: in gfc_conv_component_ref, at fortran/trans-expr.c:997 Breakpoint 1, gfc_conv_component_ref 997 gcc_assert (f2); (gdb) p f2 $1 = (tree_node *) 0x0 #1 0x00000000005d484e in gfc_conv_variable (se=0x7fffffffd130, expr=0x16c4280) at fortran/trans-expr.c:1238 #2 0x00000000005d4154 in gfc_conv_expr_val (se=0x7fffffffd130, expr=<optimized out>) at fortran/trans-expr.c:5450 #3 0x00000000005ffb96 in gfc_trans_integer_select (code=<optimized out>) at fortran/trans-stmt.c:1821 #4 gfc_trans_select (code=0x16cb9a0) at fortran/trans-stmt.c:2380 If one looks in gfc_conv_variable just before the ICEing gfc_conv_component_ref at the values, one finds: One has an EXPR_VARIABLE ("bar") which points to ("ref") to _vptr->_hash. The issue already occurs for expr->ref where one has in gfc_conv_component_ref: 991 tree f2 = c->norestrict_decl; But that's NULL. If one sets f2 to c->backend_decl, one now iterates through f2 = DECL_CHAIN (f2), does not find the suitable field, and fails at the same assert line. b) If one comments the type is(t0) line and the print line, one gets a segfault. Invalid read of size 8 at 0x5ABD0B: gfc_conv_scalarized_array_ref(gfc_se*, gfc_array_ref*) (trans-array.c:3016) by 0x5AC7A1: gfc_conv_array_ref(gfc_se*, gfc_array_ref*, gfc_symbol*, locus*) (trans-array.c:3112) by 0x5D47B7: gfc_conv_variable(gfc_se*, gfc_expr*) (trans-expr.c:1230) That's the line: expr = ss->info->expr; For some reason, this empty select type wants to get scalarized. The cally has: /* Handle scalarized references separately. */ if (ar->type != AR_ELEMENT) { gfc_conv_scalarized_array_ref (se, ar);
(In reply to comment #3) > For some reason, this empty select type wants to get scalarized. I guess the assignment to bar is what needs to be scalarized (m%foo is an array).
(In reply to comment #3) > --- a/gcc/fortran/expr.c > +++ b/gcc/fortran/expr.c > @@ -3776,3 +3782,8 @@ gfc_default_initializer (gfc_typespec *ts) > if (comp->initializer) > - ctor->expr = gfc_copy_expr (comp->initializer); > + { > + ctor->expr = gfc_copy_expr (comp->initializer); > + if (comp->ts.type != comp->initializer->ts.type > + || comp->ts.kind != comp->initializer->ts.kind) > + gfc_convert_type_warn (ctor->expr, &comp->ts, 2, false); > + } Isn't gfc_compare_types() more appropriate or are derived types not allowed?
The patch (cf. comment 3) for the issue in comment 1 has been submitted at: http://gcc.gnu.org/ml/fortran/2012-01/msg00197.html * * * Patchlet for an unrelated issue - found for resolve.c, but I think the patch to trans-decl.c should be correct as well (but I might be wrong). --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -7933,3 +7933,4 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) if (tsym->ts.type == BT_CLASS) - sym->attr.target = tsym->attr.target || CLASS_DATA (tsym)->attr.pointer; + sym->attr.target = tsym->attr.target + || CLASS_DATA (tsym)->attr.class_pointer; else --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -3689,3 +3689,3 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block) && (sym->ts.type == BT_CLASS - && CLASS_DATA (sym)->attr.pointer)) + && CLASS_DATA (sym)->attr.class_pointer)) continue; * * * Regarding comment 0 (with empty select type): The following hack works. The problem is that one has m%foo alias m%foo(<REF_AR_FULL>) which is internally: m->[ref]foo_class_container->[ref]<REF_AR_FULL> which does not work as the class container is a scalar. The proper fix is probably: m->[ref]foo_class_container->[ref]_data->[ref]<REF_AR_FULL> ^^^^^^^ The patch below handles it in a round-about fashion: It ignores the array ref by asking for the descriptor only and then adds the missing "_data". The issue with a nonempty select type (unmodified comment 0) might be similar. --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -1173,11 +1173,13 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) else if (class_target && sym->attr.dimension) { gfc_se se; gfc_init_se (&se, NULL); + se.descriptor_only = 1; gfc_conv_expr (&se, e); + se.expr = gfc_class_data_get (se.expr); gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))); gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl))); gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
Patch for the test in comment #1 at http://gcc.gnu.org/ml/fortran/2012-01/msg00197.html .
Author: burnus Date: Sun Jan 29 20:51:19 2012 New Revision: 183682 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=183682 Log: 2012-01-29 Tobias Burnus <burnus@net-b.de> PR fortran/41600 * expr.c (gfc_default_initializer): Convert the values if the type does not match. 2012-01-29 Tobias Burnus <burnus@net-b.de> PR fortran/41600 * gfortran.dg/default_initialization_6.f90: New. Added: trunk/gcc/testsuite/gfortran.dg/default_initialization_6.f90 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/expr.c trunk/gcc/testsuite/ChangeLog
Status: Comment 1 is fixed by the just committed patch of comment 8. TODO: The test case of comment 0: Once as is, once with "CLASS IS" instead of "TYPE IS" - and also with empty "SELECT TYPE" body.
I have a substantially complete fix for this PR. It fixes the original testcase but is still failing on one or two corner cases: (i) Whilst SELECT TYPE (bar => m%foo(1:2)) is OK, the offset is wrong for SELECT TYPE (bar => m%foo(3:2:-1)) (ii) I have had to put some work into getting CLASS is to work. For some reason, whilst CLASS IS (t1) print *, bar%i or print *, bar%j work fine, if (any (bar%j .ne. [4,5,6]) call abort does not (same for bar%i). Something goes wrong in the argument evaluation for the call to ANY. I suspect that there is another few days work in this one. Cheers Paul
Author: pault Date: Sat May 5 08:49:43 2012 New Revision: 187192 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=187192 Log: 2012-05-05 Paul Thomas <pault@gcc.gnu.org> PR fortran/41600 * trans-array.c (build_array_ref): New static function. (gfc_conv_array_ref, gfc_get_dataptr_offset): Call it. * trans-expr.c (gfc_get_vptr_from_expr): New function. (gfc_conv_derived_to_class): Add a new argument for a caller supplied vptr and use it if it is not NULL. (gfc_conv_procedure_call): Add NULL to call to above. symbol.c (gfc_is_associate_pointer): Return true if symbol is a class object. * trans-stmt.c (trans_associate_var): Handle class associate- names. * expr.c (gfc_get_variable_expr): Supply the array-spec if possible. * trans-types.c (gfc_typenode_for_spec): Set GFC_CLASS_TYPE_P for class types. * trans.h : Add prototypes for gfc_get_vptr_from_expr and gfc_conv_derived_to_class. Define GFC_CLASS_TYPE_P. * resolve.c (resolve_variable): For class arrays, ensure that the target expression has all the necessary _data references. (resolve_assoc_var): Throw a "not yet implemented" error for class array selectors that need a temporary. * match.c (copy_ts_from_selector_to_associate, select_derived_set_tmp, select_class_set_tmp): New functions. (select_type_set_tmp): Call one of last two new functions. (gfc_match_select_type): Copy_ts_from_selector_to_associate is called if associate-name is typed. PR fortran/53191 * resolve.c (resolve_ref): C614 applied to class expressions. 2012-05-05 Paul Thomas <pault@gcc.gnu.org> PR fortran/41600 * gfortran.dg/select_type_26.f03 : New test. * gfortran.dg/select_type_27.f03 : New test. PR fortran/53191 * gfortran.dg/select_type_28.f03 : New test. Added: trunk/gcc/testsuite/gfortran.dg/select_type_26.f03 trunk/gcc/testsuite/gfortran.dg/select_type_27.f03 trunk/gcc/testsuite/gfortran.dg/select_type_28.f03 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/expr.c trunk/gcc/fortran/match.c trunk/gcc/fortran/resolve.c trunk/gcc/fortran/symbol.c trunk/gcc/fortran/trans-array.c trunk/gcc/fortran/trans-expr.c trunk/gcc/fortran/trans-stmt.c trunk/gcc/fortran/trans-types.c trunk/gcc/fortran/trans.h trunk/gcc/testsuite/ChangeLog
Fixed on trunk Thanks for the report and sorry that it took more than two years to fix! Paul
oops - forgot to mark it as resolved