Bug 41600 - [OOP] SELECT TYPE with associate-name => exp: Arrays not supported
Summary: [OOP] SELECT TYPE with associate-name => exp: Arrays not supported
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: 4.8.0
Assignee: Paul Thomas
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2009-10-06 08:04 UTC by Tobias Burnus
Modified: 2016-11-16 14:47 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-01-28 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2009-10-06 08:04:19 UTC
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
Comment 1 janus 2010-01-30 10:37:59 UTC
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
Comment 2 Dominique d'Humieres 2010-04-18 16:24:05 UTC
The tests in comments #0 and #1 give a "Segmentation fault" with trunk or fortran-dev.
Comment 3 Tobias Burnus 2012-01-21 19:57:07 UTC
(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);
Comment 4 Mikael Morin 2012-01-22 13:39:26 UTC
(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).
Comment 5 Tobias Schlüter 2012-01-22 16:34:39 UTC
(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?
Comment 6 Tobias Burnus 2012-01-25 10:29:22 UTC
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);
Comment 7 Dominique d'Humieres 2012-01-28 14:10:51 UTC
Patch for the test in comment #1 at http://gcc.gnu.org/ml/fortran/2012-01/msg00197.html .
Comment 8 Tobias Burnus 2012-01-29 20:51:22 UTC
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
Comment 9 Tobias Burnus 2012-01-29 20:54:38 UTC
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.
Comment 10 Paul Thomas 2012-03-05 14:02:56 UTC
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
Comment 11 Paul Thomas 2012-05-05 08:49:53 UTC
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
Comment 12 Paul Thomas 2012-05-05 08:52:31 UTC
Fixed on trunk

Thanks for the report and sorry that it took more than two years to fix!

Paul
Comment 13 Paul Thomas 2012-05-05 08:54:40 UTC
oops - forgot to mark it as resolved