Bug 42888 - [4.5 Regression] ICE in fold_convert_loc, at fold-const.c:2670
Summary: [4.5 Regression] ICE in fold_convert_loc, at fold-const.c:2670
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P4 normal
Target Milestone: 4.5.0
Assignee: janus
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: 32834
  Show dependency treegraph
 
Reported: 2010-01-27 23:21 UTC by Harald Anlauf
Modified: 2010-01-31 22:01 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.3.2 4.4.0
Known to fail: 4.5.0
Last reconfirmed: 2010-01-28 13:32:22


Attachments
Test that gives the error in comment #11 (wrongly attached to pr42889). (676 bytes, text/plain)
2010-01-28 15:39 UTC, Dominique d'Humieres
Details
patch (1.20 KB, patch)
2010-01-29 22:41 UTC, janus
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Harald Anlauf 2010-01-27 23:21:52 UTC
Another regression:

gfcbug103.f90: In function ‘foo’:
gfcbug103.f90:7:0: internal compiler error: in fold_convert_loc, at fold-const.c:2670


Source:

module gfcbug103
  implicit none
  type t
     integer :: X = -999.0   ! Real initializer!
  end type t
contains
  subroutine foo
    type(t),  allocatable :: x(:)
    allocate (x(1))          ! ICE
  end subroutine foo
end module gfcbug103
Comment 1 Dominique d'Humieres 2010-01-27 23:47:43 UTC
Confirmed. The test compiles with 4.4.2 and 4.5 revision 151462.
Comment 2 Jerry DeLisle 2010-01-28 02:39:26 UTC
I have a regression hunt started
Comment 3 Jerry DeLisle 2010-01-28 04:15:06 UTC
The breakage is from rev 152345 which looks like a merge from fortran-dev.  Continuing the hunt in fortran-dev gives ...---...  ...---... ...---...

r152375 Fails
r152345 Fails  < ----- Regression occurs here on trunk
  r152200 Fails
  r152123 Fails < ----- Regression occurs here on fortran-dev
  r152122 Passes
  r152057 Passes
r152344 Passes
r152343 passes

	* dump-parse-tree.c (show_code_node): Renamed 'alloc_list'.
	* gfortran.h (gfc_code): Rename 'alloc_list'. Add member 'ts'.
	(gfc_expr_to_initialize): New prototype.
	* match.c (alloc_opt_list): Correctly check type compatibility.
	Renamed 'alloc_list'.
	(dealloc_opt_list): Renamed 'alloc_list'.
	* resolve.c (expr_to_initialize): Rename to 'gfc_expr_to_initialize'
	and make it non-static.
	(resolve_allocate_expr): Set vindex for CLASS variables correctly.
	Move initialization code to gfc_trans_allocate. Renamed 'alloc_list'.
	(resolve_allocate_deallocate): Renamed 'alloc_list'.
	(check_class_pointer_assign): Rename to 'resolve_class_assign'. Change
	argument type. Adjust to work with ordinary assignments.
	(resolve_code): Call 'resolve_class_assign' for ordinary assignments.
	Renamed 'check_class_pointer_assign'.
	* st.c (gfc_free_statement): Renamed 'alloc_list'.
	* trans-stmt.c (gfc_trans_allocate): Renamed 'alloc_list'. Handle
	size determination and initialization of CLASS variables. Bugfix for
	ALLOCATE statements with default initialization and SOURCE block.
	(gfc_trans_deallocate): Renamed 'alloc_list'.

Comment 4 Jerry DeLisle 2010-01-28 04:27:20 UTC
Confirming.
Comment 5 Tobias Burnus 2010-01-28 08:50:18 UTC
Janus, can you have a look? It is related to your allocatable + class patch.

Fortran-dev commit:
  http://gcc.gnu.org/ml/gcc-cvs/2009-09/msg00874.html
Branch merge:
  http://gcc.gnu.org/viewcvs?view=revision&revision=152345

I think the relevant part is:
http://gcc.gnu.org/viewcvs/trunk/gcc/fortran/trans-stmt.c?r1=152345&r2=152344&pathrev=152345 -- especially around "Add default initializer for those derived types that need them" (I don't have access to my GCC build computer currently and thus cannot check.)
Comment 6 janus 2010-01-28 10:29:42 UTC
(In reply to comment #5)
> I think the relevant part is:
> http://gcc.gnu.org/viewcvs/trunk/gcc/fortran/trans-stmt.c?r1=152345&r2=152344&pathrev=152345
> -- especially around "Add default initializer for those derived types that need
> them"

Yes, I think this is correct. The commit moved that part from resolve_allocate_expr (resolve.c) to gfc_trans_allocate (trans-stmt.c) and modified it a bit.

The backtrace is:

#0  fold_convert_loc (loc=0, type=0x7ffff7e83498, arg=0x7ffff7f65060) at /home/jweil/gcc45/trunk/gcc/fold-const.c:2669
#1  0x00000000005a088a in gfc_trans_scalar_assign (lse=0x7fffffffd4d0, rse=0x7fffffffd520, ts=..., l_is_temp=1 '\001', r_is_var=0 '\000')
    at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4840
#2  0x000000000059e7eb in gfc_trans_subcomponent_assign (dest=0x7ffff7f6c4c0, cm=0x17deab0, expr=0x17dc890) at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4224
#3  0x000000000059e9ce in gfc_trans_structure_assign (dest=0x7ffff7f6b5a0, expr=0x17dc720) at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4265
#4  0x000000000059eaec in gfc_conv_structure (se=0x7fffffffd780, expr=0x17dc720, init=0) at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4292
#5  0x000000000059f2f4 in gfc_conv_expr (se=0x7fffffffd780, expr=0x17dc720) at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4441
#6  0x000000000056d46b in gfc_add_loop_ss_code (loop=0x7fffffffd940, ss=0x17dce70, subscript=0 '\000', where=0x17dc770) at /home/jweil/gcc45/trunk/gcc/fortran/trans-array.c:2028
#7  0x0000000000572a92 in gfc_conv_loop_setup (loop=0x7fffffffd940, where=0x17dc770) at /home/jweil/gcc45/trunk/gcc/fortran/trans-array.c:3722
#8  0x00000000005a1b95 in gfc_trans_assignment_1 (expr1=0x17dc980, expr2=0x17dc720, init_flag=1 '\001') at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:5232
#9  0x00000000005a2316 in gfc_trans_assignment (expr1=0x17dc980, expr2=0x17dc720, init_flag=1 '\001') at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:5434
#10 0x00000000005d3bb7 in gfc_trans_allocate (code=0x17df760) at /home/jweil/gcc45/trunk/gcc/fortran/trans-stmt.c:4183
#11 0x000000000056759a in gfc_trans_code (code=0x17df760) at /home/jweil/gcc45/trunk/gcc/fortran/trans.c:1203
#12 0x0000000000591abd in gfc_generate_function_code (ns=0x17dd350) at /home/jweil/gcc45/trunk/gcc/fortran/trans-decl.c:4373
#13 0x00000000005678a9 in gfc_generate_code (ns=0x17dd350) at /home/jweil/gcc45/trunk/gcc/fortran/trans.c:1311
#14 0x0000000000516f59 in gfc_parse_file () at /home/jweil/gcc45/trunk/gcc/fortran/parse.c:4226
#15 0x0000000000556c1f in gfc_be_parse_file (set_yydebug=0) at /home/jweil/gcc45/trunk/gcc/fortran/f95-lang.c:239
#16 0x0000000000a00f3e in compile_file () at /home/jweil/gcc45/trunk/gcc/toplev.c:1053
#17 0x0000000000a03161 in do_compile () at /home/jweil/gcc45/trunk/gcc/toplev.c:2405
#18 0x0000000000a03237 in toplev_main (argc=2, argv=0x7fffffffe2c8) at /home/jweil/gcc45/trunk/gcc/toplev.c:2447
#19 0x00000000005dd404 in main (argc=2, argv=0x7fffffffe2c8) at /home/jweil/gcc45/trunk/gcc/main.c:35

Unfortunately I don't see what goes wrong right away (I'm no expert for initializers).
Comment 7 janus 2010-01-28 13:02:06 UTC
(In reply to comment #6)
> #0  fold_convert_loc (loc=0, type=0x7ffff7e83498, arg=0x7ffff7f65060) at
> /home/jweil/gcc45/trunk/gcc/fold-const.c:2669
> #1  0x00000000005a088a in gfc_trans_scalar_assign (lse=0x7fffffffd4d0,
> rse=0x7fffffffd520, ts=..., l_is_temp=1 '\001', r_is_var=0 '\000')
>     at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4840
> #2  0x000000000059e7eb in gfc_trans_subcomponent_assign (dest=0x7ffff7f6c4c0,
> cm=0x17deab0, expr=0x17dc890) at
> /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4224
> #3  0x000000000059e9ce in gfc_trans_structure_assign (dest=0x7ffff7f6b5a0,
> expr=0x17dc720) at /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4265
> #4  0x000000000059eaec in gfc_conv_structure (se=0x7fffffffd780,
> expr=0x17dc720, init=0) at
> /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4292
> #5  0x000000000059f2f4 in gfc_conv_expr (se=0x7fffffffd780, expr=0x17dc720) at
> /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:4441
> #6  0x000000000056d46b in gfc_add_loop_ss_code (loop=0x7fffffffd940,
> ss=0x17dce70, subscript=0 '\000', where=0x17dc770) at
> /home/jweil/gcc45/trunk/gcc/fortran/trans-array.c:2028
> #7  0x0000000000572a92 in gfc_conv_loop_setup (loop=0x7fffffffd940,
> where=0x17dc770) at /home/jweil/gcc45/trunk/gcc/fortran/trans-array.c:3722
> #8  0x00000000005a1b95 in gfc_trans_assignment_1 (expr1=0x17dc980,
> expr2=0x17dc720, init_flag=1 '\001') at
> /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:5232
> #9  0x00000000005a2316 in gfc_trans_assignment (expr1=0x17dc980,
> expr2=0x17dc720, init_flag=1 '\001') at
> /home/jweil/gcc45/trunk/gcc/fortran/trans-expr.c:5434

The same code path is also taken on the old fortran-dev r152122. The difference in 'fold_convert_loc' is: While for the old rev. 'type' and 'orig' are both INTEGER_TYPE, 'orig' is REAL_TYPE on current trunk. I'll try to find out how that comes about.

Btw: Isn't this whole thing of 'integer component with real initializer' invalid in some way? Shouldn't we at least throw a warning?
Comment 8 Tobias Burnus 2010-01-28 13:27:16 UTC
(In reply to comment #7)
> Btw: Isn't this whole thing of 'integer component with real initializer'
> invalid in some way? Shouldn't we at least throw a warning?

Well, according to the standard (F2008 because I have it at hand):

"numeric type -- one of the types integer, real, and complex"

"For an intrinsic assignment statement where the variable is of numeric type, the expr may have a different numeric-type or kind type parameter, in which case the value of expr is converted to the type and kind type parameter of the variable [...]"

Thus it is definitely valid. The question, when to warn and when not, is a difficult one. -Wconversion does (should) warn in this case; some argue that it is too verbose; I agree, but the last time I was thinking about -Wconversion, I had problems to come up with rules which warn exactly as wanted.

(Regarding the rest: No idea - without access to the source it is too inconvenient to debug.)
Comment 9 janus 2010-01-28 13:32:22 UTC
(In reply to comment #7)
> While for the old rev. 'type' and 'orig' are both
> INTEGER_TYPE, 'orig' is REAL_TYPE on current trunk. I'll try to find out how
> that comes about.

Got it. Previously the constructor was created already at resolution stage and was then resolved by 'resolve_structure_cons', which takes care of type conversions. Now the constructor is created at translation stage, therefore the resolution is missing (resolve_structure_cons is never called) and the type comes out wrong in our example.

Here is a simple patch which removes the ICE:

Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c    (revision 156258)
+++ gcc/fortran/trans-stmt.c    (working copy)
@@ -4180,6 +4180,7 @@ gfc_trans_allocate (gfc_code * code)
       else if (expr->ts.type == BT_DERIVED
               && (init_e = gfc_default_initializer (&expr->ts)))
        {
+         gfc_resolve_expr (init_e);
          tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
                                      init_e, true);
          gfc_add_expr_to_block (&block, tmp);
Comment 10 janus 2010-01-28 14:51:47 UTC
(In reply to comment #9)
> Index: gcc/fortran/trans-stmt.c
> ===================================================================
> --- gcc/fortran/trans-stmt.c    (revision 156258)
> +++ gcc/fortran/trans-stmt.c    (working copy)
> @@ -4180,6 +4180,7 @@ gfc_trans_allocate (gfc_code * code)
>        else if (expr->ts.type == BT_DERIVED
>                && (init_e = gfc_default_initializer (&expr->ts)))
>         {
> +         gfc_resolve_expr (init_e);
>           tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
>                                       init_e, true);
>           gfc_add_expr_to_block (&block, tmp);


This patch does not induce any regressions in the testsuite. However, the question is if there are other problems, e.g. when resolve_structure_cons would throw an error message.
Comment 11 Dominique d'Humieres 2010-01-28 14:58:02 UTC
> This patch does not induce any regressions in the testsuite. However, the
> question is if there are other problems, e.g. when resolve_structure_cons would
> throw an error message.

I did not regtest, but I get a suspicious error:

type_void.f90:28.15:

   use mytypes 
               1
Error: The NULL in the derived type constructor at (1) is being applied to component 'ptr', which is neither a POINTER nor ALLOCATABLE

for the attached coded.
Comment 12 Dominique d'Humieres 2010-01-28 15:39:57 UTC
Created attachment 19742 [details]
Test that gives the error in comment #11 (wrongly attached to pr42889).
Comment 13 Tobias Burnus 2010-01-28 18:44:24 UTC
(In reply to comment #11)
> I get a suspicious error:
>
> Error: The NULL in the derived type constructor at (1) is being applied to
> component 'ptr', which is neither a POINTER nor ALLOCATABLE

The problem is that for both
  type(c_ptr) :: ptr => C_NULL_PTR
and for
  integer, pointer :: ptr => null()
the expression type EXPR_NULL is used. At some point when going from the front-end representation (gfc_symbol, gfc_expr) to the middle-end representation (tree), the derived type non-pointer "type(c_ptr)" will be converted to a scalar pointer. Seemingly, by moving code from resolve.c to trans*.c you have an ordering problem with regards to type(c_(fun)ptr).
Comment 14 janus 2010-01-29 19:01:47 UTC
Ok, I think the best solution is to move the code setting up the initializer back to resolve.c. Here is a patch which does so (without any testsuite regressions):


Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c	(revision 156357)
+++ gcc/fortran/trans-stmt.c	(working copy)
@@ -4176,14 +4176,6 @@ gfc_trans_allocate (gfc_code * code)
 	  tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz);
 	  gfc_add_expr_to_block (&block, tmp);
 	}
-      /* Add default initializer for those derived types that need them.  */
-      else if (expr->ts.type == BT_DERIVED
-	       && (init_e = gfc_default_initializer (&expr->ts)))
-	{
-	  tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
-				      init_e, true);
-	  gfc_add_expr_to_block (&block, tmp);
-	}
 
       /* Allocation of CLASS entities.  */
       gfc_free_expr (expr);
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 156357)
+++ gcc/fortran/resolve.c	(working copy)
@@ -6099,6 +6099,7 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code
   gfc_symbol *sym;
   gfc_alloc *a;
   gfc_component *c;
+  gfc_expr *init_e;
 
   /* Check INTENT(IN), unless the object is a sub-component of a pointer.  */
   check_intent_in = 1;
@@ -6223,6 +6224,34 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code
 		 sym->name, &e->where);
       return FAILURE;
     }
+    
+  if (!code->expr3)
+    {
+      /* Add default initializer for those derived types that need them.  */
+      if (e->ts.type == BT_DERIVED
+	  && (init_e = gfc_default_initializer (&e->ts)))
+	{
+	  gfc_code *init_st = gfc_get_code ();
+	  init_st->loc = code->loc;
+	  init_st->op = EXEC_INIT_ASSIGN;
+	  init_st->expr1 = gfc_expr_to_initialize (e);
+	  init_st->expr2 = init_e;
+	  init_st->next = code->next;
+	  code->next = init_st;
+	}
+      else if (e->ts.type == BT_CLASS && code->ext.alloc.ts.type == BT_UNKNOWN
+	       && (init_e = gfc_default_initializer (&e->ts.u.derived->components->ts)))
+	{
+	  gfc_code *init_st = gfc_get_code ();
+	  init_st->loc = code->loc;
+	  init_st->op = EXEC_INIT_ASSIGN;
+	  init_st->expr1 = gfc_expr_to_initialize (e);
+	  gfc_add_component_ref (init_st->expr1, "$data");
+	  init_st->expr2 = init_e;
+	  init_st->next = code->next;
+	  code->next = init_st;
+	}
+    }
 
   if (pointer || dimension == 0)
     return SUCCESS;


Note: There is another call to 'gfc_default_initializer' in 'gfc_trans_allocate', which should be moved to resolve.c too, I guess.
Comment 15 janus 2010-01-29 19:18:16 UTC
(In reply to comment #14)
> Note: There is another call to 'gfc_default_initializer' in
> 'gfc_trans_allocate', which should be moved to resolve.c too, I guess.

Here is a small test case (very similar to comment #0, but with CLASS) which confirms this:


  type t
     integer :: X = -999.0   ! Real initializer!
  end type t

  class(t), allocatable :: x
  allocate (x)     ! works
  allocate (t::x)  ! ICE

end
Comment 16 janus 2010-01-29 22:41:50 UTC
Created attachment 19754 [details]
patch

Here is an updated patch which fixes the test case in the last comment and the original problem.
Comment 17 Harald Anlauf 2010-01-29 23:32:33 UTC
(In reply to comment #16)
> Created an attachment (id=19754) [edit]
> patch
> 
> Here is an updated patch which fixes the test case in the last comment and the
> original problem.
> 

I tried this one and compared it to the semi-solution in comment #9.
Both "work for me", but the patch from comment #16 appears to produce
a significant performance regression for my code of the order of 10-15%
as compared to the one from #9.

There is another problem left with the patch.  I am not sure whether the
code is legal, but it gives an ICE for me:

  implicit none
  type t
     integer :: X = -999.0   ! Real initializer!
  end type t
  class(t), allocatable :: x
  class(t), allocatable :: y(:)
  allocate (t::x)
  allocate (t::y(1))         ! ICE
end

gfcbug103a.f90: In function ‘MAIN__’:
gfcbug103a.f90:8:0: internal compiler error: Segmentation fault

(gdb) run gfcbug103a.f90
Starting program: /opt/gfortran/4.5/libexec/gcc/i686-pc-linux-gnu/4.5.0/f951 gfcbug103a.f90
 MAIN__
Program received signal SIGSEGV, Segmentation fault.
0x0816ee06 in gfc_conv_scalarized_array_ref (se=0xbfffe468, ar=0x8bf3394)
    at ../../trunk/gcc/fortran/trans-array.c:2487
2487        n = se->loop->order[0];
(gdb) bt
#0  0x0816ee06 in gfc_conv_scalarized_array_ref (se=0xbfffe468, ar=0x8bf3394)
    at ../../trunk/gcc/fortran/trans-array.c:2487
#1  0x0816f5c9 in gfc_conv_array_ref (se=0xbfffe468, ar=0x8bf3394, sym=0x8bf0c90,
    where=0x8bf3350) at ../../trunk/gcc/fortran/trans-array.c:2537
#2  0x00000029 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

Comment 18 Harald Anlauf 2010-01-30 00:01:17 UTC
(In reply to comment #17)

> I tried this one and compared it to the semi-solution in comment #9.
> Both "work for me", but the patch from comment #16 appears to produce
> a significant performance regression for my code of the order of 10-15%
> as compared to the one from #9.

My mistake.  I had 3 consistent, bad timings, but now it appears that the
system was not properly idle.  I redid the timings on an now idle system,
and performance was back to normal.  Sorry for the false alarm!

As far as the patch is concerned, I guess that you are on the right track.
Comment 19 janus 2010-01-30 10:29:13 UTC
(In reply to comment #17)
> There is another problem left with the patch.  I am not sure whether the
> code is legal, but it gives an ICE for me:
> 
>   implicit none
>   type t
>      integer :: X = -999.0   ! Real initializer!
>   end type t
>   class(t), allocatable :: x
>   class(t), allocatable :: y(:)
>   allocate (t::x)
>   allocate (t::y(1))         ! ICE
> end
> 
> gfcbug103a.f90: In function ‘MAIN__’:
> gfcbug103a.f90:8:0: internal compiler error: Segmentation fault

Yes, it is legal. And the ICE is kind of expected right now, since CLASS arrays are not really supported yet (cf. PR42539, PR41600, PR41951; the second one contains a similar ALLOCATE statement). Implementing CLASS array support requires an array descriptor update, so it is 4.6 stuff.
Comment 20 janus 2010-01-30 10:31:31 UTC
(In reply to comment #19)
> And the ICE is kind of expected right now, since CLASS arrays
> are not really supported yet (cf. PR42539, PR41600, PR41951; the second one
> contains a similar ALLOCATE statement). 

Oops. The first one was supposed to be PR41539.
Comment 21 janus 2010-01-31 21:56:17 UTC
Subject: Bug 42888

Author: janus
Date: Sun Jan 31 21:56:02 2010
New Revision: 156418

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=156418
Log:
gcc/fortran/
2010-01-31  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42888
	* resolve.c (resolve_allocate_expr): Move default initialization code
	here from gfc_trans_allocate.
	* trans.c (gfc_trans_code): Call gfc_trans_class_assign also for
	EXEC_INIT_ASSIGN.
	* trans-expr.c (gfc_trans_class_assign): Handle default initialization
	of CLASS variables via memcpy.
	* trans-stmt.c (gfc_trans_allocate): Move default initialization code
	to resolve_allocate_expr.

gcc/testsuite/
2010-01-31  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42888
	* gfortran.dg/allocate_derived_2.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/allocate_derived_2.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/fortran/trans.c
    trunk/gcc/testsuite/ChangeLog

Comment 22 janus 2010-01-31 22:01:24 UTC
Fixed with r156418. Thanks for the report!