Bug 55825 - [OOP] Bogus rank error with CLASS pointer assignment using structure constructors
Summary: [OOP] Bogus rank error with CLASS pointer assignment using structure construc...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2012-12-28 17:07 UTC by Tobias Burnus
Modified: 2012-12-28 21:53 UTC (History)
2 users (show)

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


Attachments
Failing test case (625 bytes, text/plain)
2012-12-28 17:07 UTC, Tobias Burnus
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2012-12-28 17:07:45 UTC
Created attachment 29058 [details]
Failing test case

Another test case by Reinhold Bader.

  type :: t_ptr
     class(interior), pointer :: r(:) => null()
  end type t_ptr
...
  type(interior), target :: r(3)
  type(t_ptr) :: o1
...
  o1 = t_ptr(r)

Gives:

  o1 = t_ptr(r)      ! fine, r has TARGET attribute and can't go away
             1
Error: The rank of the element in the structure constructor at (1) does not match that of the component (1/0)
Comment 1 janus 2012-12-28 17:36:39 UTC
Reduced test case:


program construct_poly

  implicit none
  
  type :: interior
     real :: x
  end type interior

  type :: t_ptr
     class(interior), pointer :: r(:) => null()
  end type t_ptr

  type(t_ptr) :: o1
  type(interior), target :: r(3)

  o1 = t_ptr(r)

end program 


This gives me:

test.f90:16.13:

  o1 = t_ptr(r)
             1
Error: The rank of the element in the structure constructor at (1) does not match that of the component (1/0)
test.f90:16.13:

  o1 = t_ptr(r)
             1
Error: Can't convert TYPE(interior) to CLASS(interior) at (1)


For the original test case, I get some more of these errors (on line 38, 52 and 63).
Comment 2 janus 2012-12-28 17:49:41 UTC
Draft patch:

Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 194743)
+++ gcc/fortran/resolve.c	(working copy)
@@ -1089,7 +1089,10 @@ resolve_structure_cons (gfc_expr *expr, int init)
 	  continue;
 	}
 
-      rank = comp->as ? comp->as->rank : 0;
+      if (comp->ts.type == BT_CLASS)
+	rank = CLASS_DATA (comp)->as ? CLASS_DATA (comp)->as->rank : 0;
+      else
+	rank = comp->as ? comp->as->rank : 0;
       if (cons->expr->expr_type != EXPR_NULL && rank != cons->expr->rank
 	  && (comp->attr.allocatable || cons->expr->rank))
 	{


This gets me past the first error in comment 1, but does not fix the second one.
Comment 3 janus 2012-12-28 19:23:38 UTC
The second error is fixed by the following:

Index: gcc/fortran/intrinsic.c
===================================================================
--- gcc/fortran/intrinsic.c	(revision 194743)
+++ gcc/fortran/intrinsic.c	(working copy)
@@ -4287,8 +4287,9 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespe
   if (expr->ts.type == BT_UNKNOWN)
     goto bad;
 
-  if (expr->ts.type == BT_DERIVED && ts->type == BT_DERIVED
-      && gfc_compare_types (&expr->ts, ts))
+  if (expr->ts.type == BT_DERIVED
+      && (ts->type == BT_DERIVED || ts->type == BT_CLASS) 
+      && gfc_compare_types (ts, &expr->ts))
     return SUCCESS;
 
   sym = find_conv (&expr->ts, ts);
Comment 4 janus 2012-12-28 20:19:06 UTC
After getting past the error messages with the patches in comment 2 and 3, the test case segfaults with the following backtrace:

internal compiler error: Segmentation fault
   o1 = t_ptr(r)
 ^
0xb0a58d crash_signal
        /home/jweil/gcc48/trunk/gcc/toplev.c:334
0x63466e gfc_conv_scalarized_array_ref
        /home/jweil/gcc48/trunk/gcc/fortran/trans-array.c:3042
0x634cd6 gfc_conv_array_ref(gfc_se*, gfc_array_ref*, gfc_symbol*, locus*)
        /home/jweil/gcc48/trunk/gcc/fortran/trans-array.c:3168
0x661b9b gfc_conv_variable
        /home/jweil/gcc48/trunk/gcc/fortran/trans-expr.c:1795
Comment 5 janus 2012-12-28 21:53:38 UTC
There are problems with handling CLASS components in gfc_trans_subcomponent_assign:


Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 194743)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -5934,11 +5934,14 @@ gfc_trans_subcomponent_assign (tree dest, gfc_comp
 
   gfc_start_block (&block);
 
-  if (cm->attr.pointer || cm->attr.proc_pointer)
+  if (cm->attr.pointer || cm->attr.proc_pointer
+      || (cm->ts.type == BT_CLASS && CLASS_DATA (cm)->attr.pointer))
     {
       gfc_init_se (&se, NULL);
       /* Pointer component.  */
-      if (cm->attr.dimension && !cm->attr.proc_pointer)
+      if ((cm->attr.dimension
+	   || (cm->ts.type == BT_CLASS && CLASS_DATA (cm)->attr.dimension))
+	  && !cm->attr.proc_pointer)
 	{
 	  /* Array pointer.  */
 	  if (expr->expr_type == EXPR_NULL)



However, this is not enough. The test case still gives an ICE.