The code: module a_module type :: a_type integer::length=0 end type a_type type,extends(a_type) :: b_type end type b_type contains function a_string(this) result(form) class(a_type),intent(in)::this character(max(1,this%length))::form end function a_string subroutine b_sub(this) class(b_type),intent(inout),target::this print *,a_string(this) end subroutine b_sub end module a_module The ICE message: a.f90: In Funktion »b_sub«: a.f90:14:0: interner Compiler-Fehler: in gfc_conv_component_ref, bei fortran/trans-expr.c:523 Fortran version: GNU Fortran (GCC) 4.6.0 20110310 (experimental) I know that the length specification in a_string is a little bit creepy, but it is valid. I had a discussion with the NAG about this before and they decided to give a "questionable" warning message but no error message. It anyway went right until today. I have updated gfortran and got this ICE for the first time although the code is a few months old now. Unfortunately, I'm not totally sure when I have done the last update before.
The ICE appeared between revisions 169790 and 170493.
I have removed this character function from my project and found the same ICE message with other, non character-valued functions of extended types. So it seems to be a more general problem then character-valued functions.
(In reply to comment #0) > The code: For what it's worth: ifort 12.0 and PGI 11.1 accept the code, and xlf 13.1.0.4 warns: "test.f90", 1513-083 (E) Internal or module function form was not set within the function. ** a_module === End of Compilation 1 === 1501-510 Compilation successful for file test.f90.
Michael, I CCed you because the ICE is in gfc_conv_component_ref, which you have modified for PR 45586 (Rev. 170284). That's also in the range of commits (169790:170493), which Dominique has given.
This is indeed cause by revision 170284 (no ICE at r 170283).
Without the assert it tries to generate this code: struct __class_a_module_B_type * D.1572; D.1572 = (struct __class_a_module_B_type *) this; D.1574 = D.1572->_data->length; It's the forming of _data->length that is wrong. That is because _data is of type b_type, and that one doesn't have a 'length' member. It only has a a_type member, and _that_ one has length. So, what it should have generated is: D.1574 = D.1572->_data->a_type.length; I think the inputs to conv_parent_component_references are already wrong. From the caller of that function (gfc_conv_variable): 755 case REF_COMPONENT: 756 if (ref->u.c.sym->attr.extension) 757>>> conv_parent_component_references (se, ref); 758 759 gfc_conv_component_ref (se, ref); (gdb) p debug_generic_expr(se->expr) *D.1572 (That's the b_type variable) (gdb) p ref->u.c.sym->name $55 = 0x7ffff7f47b28 "__class_a_module_A_type" (gdb) p ref->u.c.component->name $56 = 0x7ffff7e7ffa0 "length" So, it wants to get at the a_type.length member, but applies the whole thing to a b_type'd variable. That's not what conv_parent_component_references is supposed to fix up. I don't know enough about fortrans OOP implementation to suggest where this is supposed to be fixed up.
(In reply to comment #6) > I think the inputs to conv_parent_component_references are already wrong. > From the caller of that function (gfc_conv_variable): > > 755 case REF_COMPONENT: > 756 if (ref->u.c.sym->attr.extension) > 757>>> conv_parent_component_references (se, ref); > 758 > 759 gfc_conv_component_ref (se, ref); > > (gdb) p debug_generic_expr(se->expr) > *D.1572 > > (That's the b_type variable) > (gdb) p ref->u.c.sym->name > $55 = 0x7ffff7f47b28 "__class_a_module_A_type" > (gdb) p ref->u.c.component->name > $56 = 0x7ffff7e7ffa0 "length" > > So, it wants to get at the a_type.length member, but applies the whole > thing to a b_type'd variable. Yes, the base type in the reference is wrong. And the reason for this seems to be that it is not corrected in the interface mapping. I think we need to extend 'gfc_apply_interface_mapping_to_ref' to set the correct base type for polymorphic arguments.
(In reply to comment #7) > > So, it wants to get at the a_type.length member, but applies the whole > > thing to a b_type'd variable. > > Yes, the base type in the reference is wrong. And the reason for this seems to > be that it is not corrected in the interface mapping. I think we need to extend > 'gfc_apply_interface_mapping_to_ref' to set the correct base type for > polymorphic arguments. The following seems to do the trick (not regtested yet): Index: trans-expr.c =================================================================== --- trans-expr.c (revision 170870) +++ trans-expr.c (working copy) @@ -2247,6 +2247,9 @@ gfc_apply_interface_mapping_to_expr (gfc_interface expr->symtree = sym->new_sym; else if (sym->expr) gfc_replace_expr (expr, gfc_copy_expr (sym->expr)); + /* Replace base type for polymorphic arguments. */ + if (expr->ref && expr->ref->type == REF_COMPONENT && sym->expr) + expr->ref->u.c.sym = sym->expr->ts.u.derived; } /* ...and to subexpressions in expr->value. */
Janus, That looks like the right way to go. Do you understand how this can be a regression, whilst the correct interface mapping was previously not present :-) ? Cheers Paul On Fri, Mar 11, 2011 at 4:39 PM, janus at gcc dot gnu.org <gcc-bugzilla@gcc.gnu.org> wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48059 > > janus at gcc dot gnu.org changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > Status|NEW |ASSIGNED > AssignedTo|unassigned at gcc dot |janus at gcc dot gnu.org > |gnu.org | > > --- Comment #8 from janus at gcc dot gnu.org 2011-03-11 15:39:20 UTC --- > (In reply to comment #7) >> > So, it wants to get at the a_type.length member, but applies the whole >> > thing to a b_type'd variable. >> >> Yes, the base type in the reference is wrong. And the reason for this seems to >> be that it is not corrected in the interface mapping. I think we need to extend >> 'gfc_apply_interface_mapping_to_ref' to set the correct base type for >> polymorphic arguments. > > The following seems to do the trick (not regtested yet): > > Index: trans-expr.c > =================================================================== > --- trans-expr.c (revision 170870) > +++ trans-expr.c (working copy) > @@ -2247,6 +2247,9 @@ gfc_apply_interface_mapping_to_expr (gfc_interface > expr->symtree = sym->new_sym; > else if (sym->expr) > gfc_replace_expr (expr, gfc_copy_expr (sym->expr)); > + /* Replace base type for polymorphic arguments. */ > + if (expr->ref && expr->ref->type == REF_COMPONENT && sym->expr) > + expr->ref->u.c.sym = sym->expr->ts.u.derived; > } > > /* ...and to subexpressions in expr->value. */ > > -- > Configure bugmail: http://gcc.gnu.org/bugzilla/userprefs.cgi?tab=email > ------- You are receiving this mail because: ------- > You are on the CC list for the bug. >
(In reply to comment #9) > That looks like the right way to go. Do you understand how this can > be a regression, whilst the correct interface mapping was previously > not present :-) ? Well, I think gfortran 4.5 just silently produced wrong code, and then Michael's patch triggered the ICE (uncovering a bug that had been there before). The dump with my patch shows D.1574 = D.1572->_data->a_type.length; while 4.5 gives: D.1565 = D.1563->$data->length; (missing the "a_type" parent reference).
The patch in comment #8 induced a regression in module_read_2.f90, which is fixed by the following update (we must only replace the base type, if the actual argument is polymorphic!): Index: gcc/fortran/trans-expr.c =================================================================== --- gcc/fortran/trans-expr.c (revision 170879) +++ gcc/fortran/trans-expr.c (working copy) @@ -2247,6 +2247,10 @@ gfc_apply_interface_mapping_to_expr (gfc_interface expr->symtree = sym->new_sym; else if (sym->expr) gfc_replace_expr (expr, gfc_copy_expr (sym->expr)); + /* Replace base type for polymorphic arguments. */ + if (expr->ref && expr->ref->type == REF_COMPONENT + && sym->expr && sym->expr->ts.type == BT_CLASS) + expr->ref->u.c.sym = sym->expr->ts.u.derived; } /* ...and to subexpressions in expr->value. */ In this form the patch is free of testsuite regressions (on x86_64-unknown-linux-gnu). Ok for trunk?
Ha! That's what I suspected. Good. I'll OK the submission. Thanks Paul PS I'll keep quiet about it being a bit of a dubious "regression" :-) On Fri, Mar 11, 2011 at 4:57 PM, janus at gcc dot gnu.org <gcc-bugzilla@gcc.gnu.org> wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48059 > > --- Comment #10 from janus at gcc dot gnu.org 2011-03-11 15:57:47 UTC --- > (In reply to comment #9) >> That looks like the right way to go. Do you understand how this can >> be a regression, whilst the correct interface mapping was previously >> not present :-) ? > > Well, I think gfortran 4.5 just silently produced wrong code, and then > Michael's patch triggered the ICE (uncovering a bug that had been there > before). > > The dump with my patch shows > > D.1574 = D.1572->_data->a_type.length; > > while 4.5 gives: > > D.1565 = D.1563->$data->length; > > (missing the "a_type" parent reference). > > -- > Configure bugmail: http://gcc.gnu.org/bugzilla/userprefs.cgi?tab=email > ------- You are receiving this mail because: ------- > You are on the CC list for the bug. >
Author: janus Date: Sat Mar 12 16:58:33 2011 New Revision: 170906 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=170906 Log: 2011-03-12 Janus Weil <janus@gcc.gnu.org> PR fortran/48059 * trans-expr.c (gfc_apply_interface_mapping_to_expr): Replace base type for polymorphic arguments. 2011-03-12 Janus Weil <janus@gcc.gnu.org> PR fortran/48059 * gfortran.dg/class_41.f03: New. Added: trunk/gcc/testsuite/gfortran.dg/class_41.f03 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/trans-expr.c trunk/gcc/testsuite/ChangeLog
Fixed with r170906. Thanks for the report, Hans!