Bug 31879 - ICE with function having array of character variables argument
Summary: ICE with function having array of character variables argument
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:
Blocks: 19276 32834
  Show dependency treegraph
 
Reported: 2007-05-09 16:36 UTC by Vivek Rao
Modified: 2007-08-30 22:12 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2007-05-16 20:55:31


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vivek Rao 2007-05-09 16:36:12 UTC
module str_mod
contains
function copy_str(xx) result(yy)
character (len=*), intent(in) :: xx(:)
character (len=1)       :: yy(size(xx))
yy = (/xx/)
end function copy_str
subroutine print_vec(labels)
character (len=*), intent(in) :: labels(:)
print*,labels
end subroutine print_vec
!
function ccopy(yy) result(xy)
character (len=*), intent(in) :: yy(:)
character (len=1) :: xy(size(yy))
xy = yy
end function ccopy
end module str_mod
!
program xx
use str_mod, only: print_vec,ccopy,copy_str
implicit none
call print_vec(ccopy("_"//copy_str(["a"])))
end program xx

gfortran -c -v xxgfortran_bug.f90

Using built-in specs.
Target: i386-pc-mingw32
Configured with: ../trunk/configure --prefix=/mingw --enable-languages=c,fortran --with-gmp=/home/coudert/local --disable-nls --with-ld=/mingw/bin/ld --with-as=/mingw/bin/as --disable-werror --enable-bootstrap --enable-threads --build=i386-pc-mingw32 --disable-shared --enable-libgomp
Thread model: win32
gcc version 4.3.0 20070506 (experimental)
 c:/programs/gfortran/bin/../libexec/gcc/i386-pc-mingw32/4.3.0/f951.exe xxgfortran_bug.f90 -quiet -dumpbase xxgfortran_bug.f90 -mtune=i386 -auxbase xxgfortran_bug -version -fintrinsic-modules-path c:/programs/gfortran/bin/../lib/gcc/i386-pc-mingw32/4.3.0/finclude -o C:\DOCUME~1\vrao\LOCALS~1\Temp/ccB1NNxN.s
GNU F95 version 4.3.0 20070506 (experimental) (i386-pc-mingw32)
	compiled by GNU C version 4.3.0 20070506 (experimental).
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096

xxgfortran_bug.f90: In function 'MAIN__':
xxgfortran_bug.f90:20: internal compiler error: in gfc_conv_expr_descriptor, at fortran/trans-array.c:4474
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
Comment 1 Vivek Rao 2007-05-09 16:41:44 UTC
A simpler program exhibiting the same bug:

module str_mod
contains
function ccopy(yy) result(xy)
character (len=*), intent(in) :: yy(:)
character (len=1) :: xy(size(yy))
xy = yy
end function ccopy
end module str_mod
!
program xx
use str_mod, only: ccopy
implicit none
print*,ccopy("_"//["a"])
end program xx

gfortran -c -v xxgfortran_bug.f90
Using built-in specs.
Target: i386-pc-mingw32
Configured with: ../trunk/configure --prefix=/mingw --enable-languages=c,fortran --with-gmp=/home/coudert/local --disable-nls --with-ld=/mingw/bin/ld --with-as=/mingw/bin/as --disable-werror --enable-bootstrap --enable-threads --build=i386-pc-mingw32 --disable-shared --enable-libgomp
Thread model: win32
gcc version 4.3.0 20070506 (experimental)
 c:/programs/gfortran/bin/../libexec/gcc/i386-pc-mingw32/4.3.0/f951.exe xxgfortran_bug.f90 -quiet -dumpbase xxgfortran_bug.f90 -mtune=i386 -auxbase xxgfortran_bug -version -fintrinsic-modules-path c:/programs/gfortran/bin/../lib/gcc/i386-pc-mingw32/4.3.0/finclude -o C:\DOCUME~1\vrao\LOCALS~1\Temp/ccGUWtbU.s
GNU F95 version 4.3.0 20070506 (experimental) (i386-pc-mingw32)
	compiled by GNU C version 4.3.0 20070506 (experimental).
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096

xxgfortran_bug.f90: In function 'MAIN__':
xxgfortran_bug.f90:10: internal compiler error: in gfc_conv_expr_descriptor, at fortran/trans-array.c:4474
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
Comment 2 Tobias Burnus 2007-05-09 22:53:24 UTC
gfc_conv_expr_descriptor, at fortran/trans-array.c:4474:

      if (expr->ts.type == BT_CHARACTER)
        {
          if (expr->ts.cl == NULL)
            {
              /* This had better be a substring reference!  */
              gfc_ref *char_ref = expr->ref;
              for (; char_ref; char_ref = char_ref->next)
                if (char_ref->type == REF_SUBSTRING)
                   [......]
                      break;
                  }
              gcc_assert (char_ref != NULL);
Comment 3 Paul Thomas 2007-05-16 20:55:31 UTC
This fixes it and much more besides. It needs commenting and tidying up.

Paul

Index: gcc/fortran/trans-array.c
===================================================================
*** gcc/fortran/trans-array.c	(révision 124762)
--- gcc/fortran/trans-array.c	(copie de travail)
*************** gfc_trans_dummy_array_bias (gfc_symbol *
*** 4243,4248 ****
--- 4243,4315 ----
  }
  
  
+ static void
+ gfc_fixup_missing_charlen (gfc_se *se, gfc_expr *expr)
+ {
+   tree tmp;
+   gfc_ref *char_ref = expr->ref;
+ 
+   expr->ts.cl = gfc_get_charlen ();
+   expr->ts.cl->next = gfc_current_ns->cl_list;
+   gfc_current_ns->cl_list = expr->ts.cl;
+   expr->ts.cl->backend_decl
+ 		= gfc_create_var (gfc_charlen_type_node, "cl");
+ 
+   for (; char_ref; char_ref = char_ref->next)
+     if (char_ref->type == REF_SUBSTRING)
+       {
+ 	mpz_t char_len;
+ 
+ 	mpz_init_set_ui (char_len, 1);
+ 	mpz_add (char_len, char_len,
+ 	char_ref->u.ss.end->value.integer);
+ 	mpz_sub (char_len, char_len,
+ 	char_ref->u.ss.start->value.integer);
+ 	tmp = gfc_conv_mpz_to_tree (char_len,
+ 				    gfc_default_character_kind);
+ 	/* Cast is necessary for *-charlen refs.  */
+ 	tmp = convert (gfc_charlen_type_node, tmp);
+ 
+ 	gfc_add_modify_expr (&se->pre, expr->ts.cl->backend_decl, tmp);
+ 	mpz_clear (char_len);
+ 	break;
+       }
+ 
+   if (char_ref == NULL)
+     {
+       mpz_t length;
+       tmp = NULL_TREE;
+ 
+       if (expr->expr_type == EXPR_CONSTANT)
+ 	mpz_init_set_si (length, expr->value.character.length);
+       else if (expr->expr_type == EXPR_ARRAY)
+ 	mpz_init_set_si (length,
+ 		expr->value.constructor->expr->value.character.length);
+       else if (expr->expr_type == EXPR_OP)
+ 	{
+ 	  if (!expr->value.op.op1->ts.cl)
+ 	    gfc_fixup_missing_charlen (se, expr->value.op.op1);
+ 	  if (!expr->value.op.op2->ts.cl)
+ 	    gfc_fixup_missing_charlen (se, expr->value.op.op2);
+ 	  tmp = fold_build2 (PLUS_EXPR, gfc_charlen_type_node,
+ 			     expr->value.op.op1->ts.cl->backend_decl,
+ 			     expr->value.op.op2->ts.cl->backend_decl);
+ 	}
+       else
+ 	mpz_init_set_ui (length, 0);
+ 
+       if (!tmp)
+ 	{
+ 	  tmp = gfc_conv_mpz_to_tree (length,
+ 				      gfc_default_character_kind);
+ 	  tmp = convert (gfc_charlen_type_node, tmp);
+ 	}
+ 
+       gfc_add_modify_expr (&se->pre, expr->ts.cl->backend_decl, tmp);
+     }
+ }
+ 
+ 
  /* Convert an array for passing as an actual argument.  Expressions and
     vector subscripts are evaluated and stored in a temporary, which is then
     passed.  For whole arrays the descriptor is passed.  For array sections
*************** gfc_conv_expr_descriptor (gfc_se * se, g
*** 4430,4463 ****
  	{
  	  if (expr->ts.cl == NULL)
  	    {
! 	      /* This had better be a substring reference!  */
! 	      gfc_ref *char_ref = expr->ref;
! 	      for (; char_ref; char_ref = char_ref->next)
! 		if (char_ref->type == REF_SUBSTRING)
! 		  {
! 		    mpz_t char_len;
! 		    expr->ts.cl = gfc_get_charlen ();
! 		    expr->ts.cl->next = char_ref->u.ss.length->next;
! 		    char_ref->u.ss.length->next = expr->ts.cl;
! 
! 		    mpz_init_set_ui (char_len, 1);
! 		    mpz_add (char_len, char_len,
! 			     char_ref->u.ss.end->value.integer);
! 		    mpz_sub (char_len, char_len,
! 			     char_ref->u.ss.start->value.integer);
! 		    expr->ts.cl->backend_decl
! 			= gfc_conv_mpz_to_tree (char_len,
! 					gfc_default_character_kind);
! 		    /* Cast is necessary for *-charlen refs.  */
! 		    expr->ts.cl->backend_decl
! 			= convert (gfc_charlen_type_node,
! 				   expr->ts.cl->backend_decl);
! 		    mpz_clear (char_len);
! 		      break;
! 		  }
! 	      gcc_assert (char_ref != NULL);
  	      loop.temp_ss->data.temp.type
! 		= gfc_typenode_for_spec (&expr->ts);
  	      loop.temp_ss->string_length = expr->ts.cl->backend_decl;
  	    }
  	  else if (expr->ts.cl->length
--- 4497,4505 ----
  	{
  	  if (expr->ts.cl == NULL)
  	    {
! 	      gfc_fixup_missing_charlen (se, expr);
  	      loop.temp_ss->data.temp.type
! 				= gfc_typenode_for_spec (&expr->ts);
  	      loop.temp_ss->string_length = expr->ts.cl->backend_decl;
  	    }
  	  else if (expr->ts.cl->length
Comment 4 Paul Thomas 2007-05-18 07:18:35 UTC
(In reply to comment #3)
> This fixes it and much more besides. It needs commenting and tidying up.
> 

...but is broken on x86_ia64 with a very odd error message:

pr31879.f90: In function ‘MAIN__’:
pr31879.f90:13: internal compiler error: in simplify_subreg, at simplify-rtx.c:4674

I cannot see anything wrong with the code.

I will have to drop this until next week.

Paul
Comment 5 patchapp@dberlin.org 2007-08-29 18:05:27 UTC
Subject: Bug number PR31879

A patch for this bug has been added to the patch tracker.
The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2007-08/msg02114.html
Comment 6 Paul Thomas 2007-08-30 22:11:14 UTC
Subject: Bug 31879

Author: pault
Date: Thu Aug 30 22:10:55 2007
New Revision: 127939

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

	PR fortran/31879
	PR fortran/31197
	PR fortran/31258
	PR fortran/32703
	* gfortran.h : Add prototype for gfc_resolve_substring_charlen.
	* resolve.c (gfc_resolve_substring_charlen): New function.
	(resolve_ref): Call gfc_resolve_substring_charlen.
	(gfc_resolve_character_operator): New function.
	(gfc_resolve_expr): Call the new functions in cases where the
	character length is missing.
	* iresolve.c (cshift, eoshift, merge, pack, reshape, spread,
	transpose, unpack): Call gfc_resolve_substring_charlen for
	source expressions that are character and have a reference.
	* trans.h (gfc_trans_init_string_length) Change name to
	gfc_conv_string_length; modify references in trans-expr.c,
	trans-array.c and trans-decl.c.
	* trans-expr.c (gfc_trans_string_length): Handle case of no
	backend_decl.
	(gfc_conv_aliased_arg): Remove code for treating substrings
	and replace with call to gfc_trans_string_length.
	* trans-array.c (gfc_conv_expr_descriptor): Remove code for
	treating strings and call gfc_trans_string_length instead.

2007-08-31  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/31879
	* gfortran.dg/char_length_7.f90: New test.
	* gfortran.dg/char_length_9.f90: New test.
	* gfortran.dg/char_assign_1.f90: Add extra warning.

	PR fortran/31197
	PR fortran/31258
	* gfortran.dg/char_length_8.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/char_length_7.f90
    trunk/gcc/testsuite/gfortran.dg/char_length_8.f90
    trunk/gcc/testsuite/gfortran.dg/char_length_9.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/iresolve.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans.h
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/char_assign_1.f90

Comment 7 Paul Thomas 2007-08-30 22:12:37 UTC
Fixed on trunk.

Thanks for the report!

Paul