Bug 48059 - [4.6 Regression][OOP] ICE in in gfc_conv_component_ref: character function of extended type
Summary: [4.6 Regression][OOP] ICE in in gfc_conv_component_ref: character function of...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.6.0
: P4 normal
Target Milestone: 4.6.0
Assignee: janus
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2011-03-10 13:44 UTC by Hans-Werner Boschmann
Modified: 2011-03-12 17:01 UTC (History)
7 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.5.2
Known to fail: 4.6.0
Last reconfirmed: 2011-03-10 13:54:15


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Hans-Werner Boschmann 2011-03-10 13:44:50 UTC
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.
Comment 1 Dominique d'Humieres 2011-03-10 13:54:15 UTC
The ICE appeared between revisions 169790 and 170493.
Comment 2 Hans-Werner Boschmann 2011-03-10 14:06:06 UTC
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.
Comment 3 Harald Anlauf 2011-03-10 20:23:56 UTC
(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.
Comment 4 Tobias Burnus 2011-03-10 21:45:02 UTC
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.
Comment 5 Dominique d'Humieres 2011-03-10 23:15:40 UTC
This is indeed cause by revision 170284 (no ICE at r 170283).
Comment 6 Michael Matz 2011-03-11 13:35:04 UTC
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.
Comment 7 janus 2011-03-11 14:45:22 UTC
(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.
Comment 8 janus 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.  */
Comment 9 paul.richard.thomas@gmail.com 2011-03-11 15:51:31 UTC
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.
>
Comment 10 janus 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).
Comment 11 janus 2011-03-11 18:24:01 UTC
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?
Comment 12 paul.richard.thomas@gmail.com 2011-03-12 16:07:47 UTC
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.
>
Comment 13 janus 2011-03-12 16:58:36 UTC
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
Comment 14 janus 2011-03-12 17:01:20 UTC
Fixed with r170906. Thanks for the report, Hans!