Bug 33998 - ICE in make_decl_rtl, at varasm.c:1263
Summary: ICE in make_decl_rtl, at varasm.c:1263
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: ice-on-valid-code
Depends on: 31213 33888
Blocks: 32834
  Show dependency treegraph
 
Reported: 2007-11-05 22:04 UTC by Tobias Burnus
Modified: 2007-12-16 11:42 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2007-11-30 17:06:19


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2007-11-05 22:04:05 UTC
Found at http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/f222faf1eb571cba

The following program crashes a couple of compilers, including gfortran 4.1.x to 4.3.0. The error message is:

sdsd.f90: In function 'len_test':
sdsd.f90:23: internal compiler error: in make_decl_rtl, at varasm.c:1263

This is the following assert:

  /* A weak alias has TREE_PUBLIC set but not the other bits.  */
  gcc_assert (TREE_CODE (decl) != VAR_DECL
              || TREE_STATIC (decl)
              || TREE_PUBLIC (decl)
              || DECL_EXTERNAL (decl)
              || DECL_REGISTER (decl));

 * * *

Using NAG f95, the following program compiles and prints "01234567890".


module test
   implicit none
   contains
      function my_string(x)
         integer i
         real, intent(in) :: x(:)
         character(0) h4(1:minval([(1,i=1,0)],1))
         character(0) sv1(size(x,1):size(h4))
         character(0) sv2(2*lbound(sv1,1):size(h4))
         character(lbound(sv2,1)-3) my_string

         do i = 1, len(my_string)
            my_string(i:i) = achar(modulo(i-1,10)+iachar('0'))
         end do
      end function my_string
end module test

program len_test
   use test
   implicit none
   real x(7)

   write(*,*) my_string(x) ! <<< Line 23
end program len_test
Comment 1 Francois-Xavier Coudert 2007-11-05 23:46:09 UTC
Hey, it crashes Intel, Sun, g95 and gives a runtime error with Portland. Not bad!

Reduced testcase:

program test
  interface
  function my_string(x)
    integer, intent(in) :: x
    integer :: sv(x)
    character(size(sv)) my_string
  end function my_string
  end interface

  integer x
  write(*,*) my_string(x)
end program test

The following one triggers a slightly different ICE, most probably has the same cause:

program test
  integer x
  write(*,*) my_string(x)
contains
  function my_string(x)
    integer, intent(in) :: x
    integer :: sv(x)
    character(size(sv)) my_string
  end function my_string
end program test

The reason for the failure is apparent from the tree dump:

    test ()
    {
      char[1:MAX_EXPR <D.876, 0>] * pstr.5;
      int4 D.876;
      ...
      D.875 = &parm.4;
      D.876 = (int4) _gfortran_size0 (D.875);
      D.878 = MAX_EXPR <D.876, 0>;
      ...
      pstr.5 = (char[1:MAX_EXPR <D.876, 0>] *) D.879;
      my_string (pstr.5, MAX_EXPR <D.876, 0>, D.860);
      _gfortran_transfer_character (&dt_parm.1, pstr.5, MAX_EXPR <D.876, 0>);
    }

When we're declaring pstr.5, we don't know yet what length it's gonna have, so we probably need to make it a simple char *, instead of being clever. I hope this can put someone on the right track about how to fix this.
Comment 2 Paul Thomas 2007-11-06 11:49:59 UTC
In the code for the testcase:

len_test ()
{
  real4 x[7];
  static int4 options.40[7] = {68, 127, 0, 0, 0, 1, 0};

......snip......

      parm.48.dim[0].lbound = D.727;
      parm.48.dim[0].ubound = ubound.45;
      parm.48.dim[0].stride = 1;
      parm.48.data = (void *) (char[0:][1:1] *) &(*sv2)[D.727 - lbound.44];
      parm.48.offset = (lbound.44 - D.727) + D.730;

......snip.....

    _gfortran_st_write_done (&dt_parm.41);
  }
}

Thus, there are two remarks to make:
(1) First 'sv2' is being referenced in the main programme, so the interface functions in trans-expr.c are failing; and
(2) A temporary descriptor is being written, which is unnecessary.

This is very much related to PR33888 in my opinion.  In that PR, the problem arises because trans-array.c(gfc_conv_expr_descriptor) fails to substitute the dummy expressions, with the interface routines, before creating the temporary.  The character length calculation at trans-array.c:4685 is simply not up to the job.

I do not see any alternative but to rewrite the interface routines and put them in resolve.c.

Cheers

Paul
Comment 3 Paul Thomas 2007-11-17 17:07:24 UTC
(In reply to comment #2)
>
> I do not see any alternative but to rewrite the interface routines and put
> them in resolve.c.

This maybe a bit alarmist but not by much.  Certainly, 33888 needs a bit of help from resolve.c.  I have written a trial patch that does the substitution of the formal arguments by the actuals and cures 33888.

In fact, the original example in PR31213 also has this same problem; however, PR31213 also suffers from at least two other bugs!

Paul
Comment 4 Paul Thomas 2007-11-30 17:06:19 UTC
I think that I have a fix

Paul
Comment 5 Paul Thomas 2007-12-03 15:05:41 UTC
(In reply to comment #4)

Just for the record, the following, very crude patch works and produces the same output as NAG.  It needs a lot of cleaning up and I should understand why the inclusion of LEN works fine, except for char_result_[1-2].f90  It is my belief that  for the latter two the interface DOUBLE screws things up.  As soonas I get on top of this, I'll revamp the whole thing and submit it => a few days from now.

Cheers

Paul

Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c    (revision 130333)
--- gcc/fortran/trans-expr.c    (working copy)
*************** along with GCC; see the file COPYING3.
*** 34,39 ****
--- 34,40 ----
  #include "langhooks.h"
  #include "flags.h"
  #include "gfortran.h"
+ #include "arith.h"
  #include "trans.h"
  #include "trans-const.h"
  #include "trans-types.h"
*************** gfc_apply_interface_mapping_to_expr (gfc
*** 1731,1736 ****
--- 1732,1818 ----
        if (sym->old == expr->symtree->n.sym)
        expr->symtree = sym->new;

+   if (expr->expr_type == EXPR_FUNCTION
+           && expr->value.function.esym == NULL
+           && expr->value.function.isym != NULL
+           && expr->value.function.isym->id == GFC_ISYM_SIZE
+           && expr->value.function.actual->expr->expr_type == EXPR_VARIABLE
+           && expr->value.function.actual->expr->symtree->n.sym->as)
+   {
+     gfc_symbol *sym = expr->value.function.actual->expr->symtree->n.sym;
+
+     if (!sym->attr.dummy)
+       {
+       gfc_expr *new_expr = NULL;
+       int d, dup;
+
+       gfc_apply_interface_mapping_to_expr (mapping, expr->value.function.actua
l->expr);
+       if (expr->value.function.actual->next
+             && expr->value.function.actual->next->expr
+             && expr->value.function.actual->next->expr->expr_type == EXPR_CONS
TANT)
+         {
+           dup = mpz_get_si (expr->value.function.actual->next->expr->value.int
eger);
+           d = dup - 1;
+         }
+       else
+         {
+           dup = sym->as->rank;
+           d = 0;
+         }
+
+       for (; d < dup; d++)
+         {
+           gfc_expr *tmp;
+           gfc_apply_interface_mapping_to_expr (mapping, sym->as->upper[d]);
+           gfc_apply_interface_mapping_to_expr (mapping, sym->as->lower[d]);
+           tmp = gfc_add (gfc_copy_expr (sym->as->upper[d]), gfc_int_expr (1));

+           tmp = gfc_subtract (tmp, gfc_copy_expr (sym->as->lower[d]));
+           if (new_expr)
+             new_expr = gfc_multiply (new_expr, tmp);
+           else
+             new_expr = tmp;
+           new_expr->where = expr->where;
+         }
+       gfc_replace_expr (expr, new_expr);
+       return 0;
+       }
+   }
+
+   if (expr->expr_type == EXPR_FUNCTION
+           && expr->value.function.esym == NULL
+           && expr->value.function.isym != NULL
+           && (expr->value.function.isym->id == GFC_ISYM_LBOUND
+                 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
+           && expr->value.function.actual->expr->expr_type == EXPR_VARIABLE
+           && expr->value.function.actual->expr->symtree->n.sym->as)
+   {
+     gfc_symbol *sym = expr->value.function.actual->expr->symtree->n.sym;
+
+     if (!sym->attr.dummy)
+       {
+       gfc_expr *new_expr = NULL;
+       int d;
+
+       gfc_apply_interface_mapping_to_expr (mapping, expr->value.function.actua
l->expr);
+       if (expr->value.function.actual->next
+             && expr->value.function.actual->next->expr
+             && expr->value.function.actual->next->expr->expr_type == EXPR_CONS
TANT)
+         d = mpz_get_si (expr->value.function.actual->next->expr->value.integer
) - 1;
+       else
+         d = 0;
+
+       if (expr->value.function.isym->id == GFC_ISYM_LBOUND)
+         new_expr = gfc_copy_expr (sym->as->lower[d]);
+       else
+         new_expr = gfc_copy_expr (sym->as->upper[d]);
+
+       gfc_apply_interface_mapping_to_expr (mapping, new_expr);
+       new_expr->where = expr->where;
+       gfc_replace_expr (expr, new_expr);
+       return 0;
+       }
+   }
+
    /* ...and to subexpressions in expr->value.  */
    switch (expr->expr_type)
      {


Comment 6 Paul Thomas 2007-12-16 11:34:29 UTC
Subject: Bug 33998

Author: pault
Date: Sun Dec 16 11:34:08 2007
New Revision: 130988

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=130988
Log:
2007-12-16  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/31213
	PR fortran/33888
	PR fortran/33998
	* trans-array.c (gfc_trans_array_constructor_value): If the
	iterator variable does not have a backend_decl, use a local
	temporary.
	(get_elemental_fcn_charlen): New function to map the character
	length of an elemental function onto its actual arglist.
	(gfc_conv_expr_descriptor): Call the above so that the size of
	the temporary can be evaluated.
	* trans-expr.c : Include arith.h and change prototype of
	gfc_apply_interface_mapping_to_expr to return void.  Change all
	references to gfc_apply_interface_mapping_to_expr accordingly.
	(gfc_free_interface_mapping): Free the 'expr' field.
	(gfc_add_interface_mapping): Add an argument for the actual
	argument expression. This is copied to the 'expr' field of the
	mapping.  Only stabilize the backend_decl if the se is present.
	Copy the character length expression and only add it's backend
	declaration if se is present.  Return without working on the
	backend declaration for the new symbol if se is not present.
	(gfc_map_intrinsic_function) : To simplify intrinsics 'len',
	'size', 'ubound' and 'lbound' and then to map the result.
	(gfc_map_fcn_formal_to_actual): Performs the formal to actual
	mapping for the case of a function found in a specification
	expression in the interface being mapped.
	(gfc_apply_interface_mapping_to_ref): Remove seen_result and
	all its references. Remove the inline simplification of LEN
	and call gfc_map_intrinsic_function instead.  Change the
	order of mapping of the actual arguments and simplifying
	intrinsic functions.  Finally, if a function maps to an
	actual argument, call gfc_map_fcn_formal_to_actual.
	(gfc_conv_function_call): Add 'e' to the call to
	gfc_add_interface_mapping.
	* dump-parse-tree.c (gfc_show_symbol_n): New function for
	diagnostic purposes.
	* gfortran.h : Add prototype for gfc_show_symbol_n.
	* trans.h : Add 'expr' field to gfc_add_interface_mapping.
	Add 'expr' to prototype for gfc_show_symbol_n.
	* resolve.c (resolve_generic_f0): Set specific function as
	referenced.

2007-12-16  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/31213
	PR fortran/33888
	PR fortran/33998
	* gfortran.dg/mapping_1.f90: New test.
	* gfortran.dg/mapping_2.f90: New test.
	* gfortran.dg/mapping_3.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/mapping_1.f90
    trunk/gcc/testsuite/gfortran.dg/mapping_2.f90
    trunk/gcc/testsuite/gfortran.dg/mapping_3.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/dump-parse-tree.c
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans.h
    trunk/gcc/testsuite/ChangeLog

Comment 7 Paul Thomas 2007-12-16 11:42:23 UTC
Fixed on trunk

Paul