Bug 33881 - [4.3 regression] wrong code for assumed length character arrays
Summary: [4.3 regression] wrong code for assumed length character arrays
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: 4.3.0
Assignee: Francois-Xavier Coudert
URL:
Keywords: wrong-code
Depends on:
Blocks: 32834
  Show dependency treegraph
 
Reported: 2007-10-24 14:09 UTC by william.mitchell
Modified: 2007-11-03 22:14 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.2.2 4.1.3
Known to fail: 4.3.0
Last reconfirmed: 2007-10-26 22:26:14


Attachments
this is the program (468 bytes, text/plain)
2007-10-24 14:10 UTC, william.mitchell
Details

Note You need to log in before you can comment on or make changes to this bug.
Description william.mitchell 2007-10-24 14:09:18 UTC
With this program I get a runtime error message
Fortran runtime error: Attempt to allocate a negative amount of memory.
The error occurs at line 33.  I suspect the "allocation" is the constant array actual argument (/name/).
This program is a little longer than I like my bug reports to be, but any attempt to shorten it changes the error to a segmentation fault, except for removing the print statement in the main program which results in the program running correctly.

mitchell@speedy> gfortran --version
GNU Fortran (GCC) 4.3.0 20071023 (experimental) [trunk revision 129569]
Copyright (C) 2007 Free Software Foundation, Inc.

mitchell@speedy> gfortran bug071024.f90
mitchell@speedy> a.out
 something
Fortran runtime error: Attempt to allocate a negative amount of memory.
Comment 1 william.mitchell 2007-10-24 14:10:53 UTC
Created attachment 14405 [details]
this is the program
Comment 2 Tobias Burnus 2007-10-24 15:33:57 UTC
> Fortran runtime error: Attempt to allocate a negative amount of memory.

This error usually means that you allocate that much memory that an integer(4) variable overflows. I cannot reproduce the error here with -m32 or -m64 on x86_64/Linux (20071016 (experimental) [trunk revision 129378]).

(Using valgrind I get a lot of unintialized-variable warnings which are due to the fact that create_watch_actual is only a stub.)

Which platform are you using (CPU + operating system; "gfortran -v" shows this in the "Target:" line.)
Comment 3 william.mitchell 2007-10-24 15:48:00 UTC
(In reply to comment #2)
Sorry I forgot to give the computer information.  This is a 32 bit CentOS 5 Linux distribution on an Intel Core 2 Duo T7700

mitchell@speedy> gfortran -v
Using built-in specs.
Target: i386-pc-linux-gnu
Configured with: /home/fx/gfortran_nightbuild/trunk/configure --prefix=/home/fx/gfortran_nightbuild/irun-20071023 --enable-languages=c,fortran --build=i386-pc-linux-gnu --enable-checking=release --with-gmp=/home/fx/gfortran_nightbuild/software
Thread model: posix
gcc version 4.3.0 20071023 (experimental) [trunk revision 129569] (GCC)

mitchell@speedy> uname -a
Linux speedy.cam.nist.gov 2.6.18-8.1.10.el5 #1 SMP Thu Sep 13 12:17:54 EDT 2007 i686 i686 i386 GNU/Linux
Comment 4 Joost VandeVondele 2007-10-26 07:17:06 UTC
In order to make the testcase valid, subroutine option_stopwatch_a needs to be replaced by:

subroutine option_stopwatch_a(default_clock)
character(len=*), intent(in), dimension(:) :: default_clock
allocate(default_clocks(size(default_clock)))
end subroutine option_stopwatch_a

In that case it segfaults with gfortran and runs fine .e.g. with g95 and NAG, also the g95 run is clean within valgrind, but gives several errors with gfortran:

==16592== Conditional jump or move depends on uninitialised value(s)
==16592==    at 0x4011EE: __stopwatch_MOD_create_watch_ss (test.f90:33)
==16592==    by 0x401A71: MAIN__ (test.f90:59)
==16592==    by 0x401AAB: main (fmain.c:21)
==16592==
==16592== Conditional jump or move depends on uninitialised value(s)
==16592==    at 0x401207: __stopwatch_MOD_create_watch_ss (test.f90:33)
==16592==    by 0x401A71: MAIN__ (test.f90:59)
==16592==    by 0x401AAB: main (fmain.c:21)
==16592==
==16592== Conditional jump or move depends on uninitialised value(s)
==16592==    at 0x4A225FA: memcpy (mc_replace_strmem.c:406)
==16592==    by 0x401271: __stopwatch_MOD_create_watch_ss (test.f90:33)
==16592==    by 0x401A71: MAIN__ (test.f90:59)
==16592==    by 0x401AAB: main (fmain.c:21)
==16592==
==16592== Conditional jump or move depends on uninitialised value(s)
==16592==    at 0x4012D5: __stopwatch_MOD_create_watch_ss (test.f90:33)
==16592==    by 0x401A71: MAIN__ (test.f90:59)
==16592==    by 0x401AAB: main (fmain.c:21)
==16592==
==16592== Conditional jump or move depends on uninitialised value(s)
==16592==    at 0x4012EE: __stopwatch_MOD_create_watch_ss (test.f90:33)
==16592==    by 0x401A71: MAIN__ (test.f90:59)
==16592==    by 0x401AAB: main (fmain.c:21)
==16592==
==16592== Conditional jump or move depends on uninitialised value(s)
==16592==    at 0x4A225FA: memcpy (mc_replace_strmem.c:406)
==16592==    by 0x4013A0: __stopwatch_MOD_create_watch_ss (test.f90:33)
==16592==    by 0x401A71: MAIN__ (test.f90:59)
==16592==    by 0x401AAB: main (fmain.c:21)

which look as if they could be related to the optional character arguments.
Comment 5 Joost VandeVondele 2007-10-26 07:51:04 UTC
I'm guess-changing the summary
Comment 6 Joost VandeVondele 2007-10-26 17:54:11 UTC
reduced testcase still failing with valgrind

  character(len=4), dimension(4) :: default_clocks=""
  call create_watch_ss('total')
contains
  subroutine create_watch_actual(clock,name)
    character(len=*), dimension(:) :: clock
    character(len=*), dimension(:) :: name
  end subroutine create_watch_actual

  subroutine create_watch_ss(name,clock)
  character(len=*), optional :: clock
  character(len=*) :: name
      if (present(clock)) then
        call create_watch_actual((/clock/),(/name/))
      else
        call create_watch_actual(default_clocks,(/name/))
      end if
  end subroutine create_watch_ss
end
Comment 7 Tobias Burnus 2007-10-26 21:16:44 UTC
Works: 2007-07-13-r126613
Fails: 2007-07-16-r126671

Comment 8 Francois-Xavier Coudert 2007-10-26 22:26:13 UTC
Reduced-reduced testcase which still triggers valgrind:

  call create_watch_ss(" ")
contains
  subroutine create_watch_actual(name)
    character(len=1) :: name(1)
  end subroutine create_watch_actual

  subroutine create_watch_ss(name,clock)
    character(len=*) :: name
    integer, optional :: clock
    if (present(clock)) then
      call create_watch_actual((/name/))
    else
      call create_watch_actual((/name/))
    end if
  end subroutine create_watch_ss
end

It's apparent form the dump that, in the second branch of the IF, we use variables declared in the first branch.
Comment 9 Francois-Xavier Coudert 2007-10-26 22:40:08 UTC
And the smaller testcase with invalid dump:

  subroutine create_watch_ss (name,l)
    character(len=*) :: name
    logical l
    if (l) then
      call create_watch_actual([name])
    else
      call create_watch_actual([name])
    end if
  end
Comment 10 Paul Thomas 2007-11-01 18:07:21 UTC
FX,

I believe that the fix is something like:

Index: gcc/fortran/trans-array.c
===================================================================
*** gcc/fortran/trans-array.c   (revision 129505)
--- gcc/fortran/trans-array.c   (working copy)
*************** gfc_conv_array_parameter (gfc_se * se, g
*** 4965,4972 ****
    if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
      {
        get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
!       expr->ts.cl->backend_decl = gfc_evaluate_now (tmp, &se->pre);
!       se->string_length = expr->ts.cl->backend_decl;
      }

    /* Is this the result of the enclosing procedure?  */
--- 4972,4979 ----
    if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
      {
        get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
!       expr->ts.cl->backend_decl = tmp;
!       se->string_length = gfc_evaluate_now (tmp, &se->pre);
      }

    /* Is this the result of the enclosing procedure?  */

Fixing the value of a cl->backend_decl has the observed consequences because, in some cases like this one, the expr->ts.cl is a copy of a variable cl.

This survives dg.expr=gfortran.dg/char* but beyond that I am not in a position to go.

Please make use of it as you will.

Cheers

Paul

PS It's my fault!
Comment 11 Francois-Xavier Coudert 2007-11-03 22:12:16 UTC
Subject: Bug 33881

Author: fxcoudert
Date: Sat Nov  3 22:12:03 2007
New Revision: 129874

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129874
Log:
	PR fortran/33881

	* trans-array.c (gfc_conv_array_parameter): Evaluate
	se->string_length instead of the expr->ts.cl->backend_decl.

	* gfortran.dg/assumed_charlen_arg_1.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/assumed_charlen_arg_1.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/testsuite/ChangeLog

Comment 12 Francois-Xavier Coudert 2007-11-03 22:14:47 UTC
Fixed. Thanks Paul!