Bug 47519 - Deferred-length string wrong results with character intrinsic functions
Summary: Deferred-length string wrong results with character intrinsic functions
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: ice-on-valid-code, wrong-code
Depends on:
Blocks: 45170
  Show dependency treegraph
 
Reported: 2011-01-28 15:29 UTC by Tobias Burnus
Modified: 2011-02-02 20:53 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-01-29 16:30:00


Attachments
Patch for the PR (1.45 KB, patch)
2011-01-30 21:22 UTC, Paul Thomas
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2011-01-28 15:29:21 UTC
Follow up to deferred-length string PR 45170.

Part of the thread referenced at bug 35810 comment 0,
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/7d5d1e7f4a48071c/7c63fef65ba5ea70?lnk=gst&q=realloc_lhs

The following code of James ICEs with the current trunk:

foo.f90: In function ‘note7_35’:
foo.f90:9:0: internal compiler error: Segmentation fault

==7086== Invalid read of size 8
==7086==    at 0x5B1C46: gfc_trans_allocate (trans-stmt.c:4527)
==7086==    by 0x5656E7: trans_code (trans.c:1323)
==7086==    by 0x583D91: gfc_generate_function_code (trans-decl.c:4708)
==7086==    by 0x527CB7: gfc_parse_file (parse.c:4237)
==7086==    by 0x560D75: gfc_be_parse_file (f95-lang.c:250)
==7086==    by 0x867FCB: toplev_main (toplev.c:579)
==7086==    by 0x64C7BBC: (below main) (libc-start.c:226)
==7086==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

In the last line of the following (shortened) excerpt the ICE happens:

          else if (al->expr->ts.type == BT_CHARACTER
                     && al->expr->ts.deferred && code->expr3)
            {
              if (!code->expr3->ts.u.cl->backend_decl)
                {
                  if (code->expr3->expr_type == EXPR_VARIABLE
                        || code->expr3->expr_type == EXPR_CONSTANT)
                  else
                    {
                      gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);


program note7_35
   implicit none
   character, allocatable :: name*(:)
   character(*), parameter :: FIRST_NAME = 'Julius'
   character(*), parameter :: SURNAME = 'No'
   integer n

   n = 10
   allocate(name, SOURCE=repeat('x',n))
   name = 'Dr. '//FIRST_NAME//' '//SURNAME
   write(*,*) len(name), name
   deallocate(name)
   n = 10
   allocate(name, SOURCE=repeat('x',n))
   name(:) = 'Dr. '//FIRST_NAME//' '//SURNAME
   write(*,*) len(name), name
end program note7_35
Comment 1 Tobias Burnus 2011-01-28 18:28:52 UTC
The problem is the line:
     allocate(name, SOURCE=repeat('x',n))

A simplified (and not ICEing) version is:
   n = 10
   name = repeat('x',n)
   name = repeat('x',4)
   name = repeat('x',n)//"123"

For the first "repeat" len(name) is 0, for the second "repear' one gets the expected "xxxx". The third one gives "xxx".

In case of the allocate, the problem is that both
  code->expr3->ts.u.cl->backend_decl
and
  code->expr3->ts.u.cl->length
are NULL pointers. (code->expr3->expr_type is EXPR_FUNCTION)
Comment 2 Tobias Burnus 2011-01-28 20:00:31 UTC
Paul, do you think one should do something alike in gfc_trans_allocate and in the intrinsic scalar/array assignment block?

gfc_conv_intrinsic_len has:

    default:
      /* Anybody stupid enough to do this deserves inefficient code.  */
      ss = gfc_walk_expr (arg);
      gfc_init_se (&argse, se);
      if (ss == gfc_ss_terminator)
        gfc_conv_expr (&argse, arg);
      else
        gfc_conv_expr_descriptor (&argse, arg, ss);
      gfc_add_block_to_block (&se->pre, &argse.pre);
      gfc_add_block_to_block (&se->post, &argse.post);
      len = argse.string_length;
Comment 3 Paul Thomas 2011-01-29 16:30:00 UTC
(In reply to comment #2)
> Paul, do you think one should do something alike in gfc_trans_allocate and in
> the intrinsic scalar/array assignment block?
> 
> gfc_conv_intrinsic_len has:
> 
>     default:
>       /* Anybody stupid enough to do this deserves inefficient code.  */
>       ss = gfc_walk_expr (arg);
>       gfc_init_se (&argse, se);
>       if (ss == gfc_ss_terminator)
>         gfc_conv_expr (&argse, arg);
>       else
>         gfc_conv_expr_descriptor (&argse, arg, ss);
>       gfc_add_block_to_block (&se->pre, &argse.pre);
>       gfc_add_block_to_block (&se->post, &argse.post);
>       len = argse.string_length;

This is the only way to go.  The ss is not needed, though.

I'll take this one.

Cheers

Paul
Comment 4 Paul Thomas 2011-01-30 21:22:21 UTC
Created attachment 23170 [details]
Patch for the PR

This is regtesting as I right but I am sure that it is good.

Note the mod to dump-parse-file.c to allow for SOURCE/MOLD in ALLOCATE.

The trick was to generate a character length during resolution, in REPEAT.

Will submit tomorrow.

Paul
Comment 5 paul.richard.thomas@gmail.com 2011-01-31 07:26:23 UTC
> This is regtesting as I right but I am sure that it is good.

That does indeed regtest OK.

Paul
Comment 6 Dominique d'Humieres 2011-01-31 13:24:19 UTC
> That does indeed regtest OK.

It passes all my tests too;-)

Thanks for the patch.
Comment 7 Paul Thomas 2011-01-31 19:13:17 UTC
Author: pault
Date: Mon Jan 31 19:13:13 2011
New Revision: 169444

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

	PR fortran/47519
	* trans-stmt.c (gfc_trans_allocate): Improve handling of
	deferred character lengths with SOURCE.
	* iresolve.c (gfc_resolve_repeat): Calculate character
	length from source length and ncopies.
	* dump-parse-tree.c (show_code_node): Show MOLD and SOURCE
	expressions for ALLOCATE.


2011-01-31  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/47519
	* gfortran.dg/allocate_deferred_char_scalar_2.f03: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/allocate_deferred_char_scalar_2.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/dump-parse-tree.c
    trunk/gcc/fortran/iresolve.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/testsuite/ChangeLog
Comment 8 Diego Novillo 2011-02-02 18:12:18 UTC
Author: dnovillo
Date: Wed Feb  2 18:12:07 2011
New Revision: 169723

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

	PR fortran/47519
	* trans-stmt.c (gfc_trans_allocate): Improve handling of
	deferred character lengths with SOURCE.
	* iresolve.c (gfc_resolve_repeat): Calculate character
	length from source length and ncopies.
	* dump-parse-tree.c (show_code_node): Show MOLD and SOURCE
	expressions for ALLOCATE.


2011-01-31  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/47519
	* gfortran.dg/allocate_deferred_char_scalar_2.f03: New test.

Added:
    branches/google/integration/gcc/testsuite/gfortran.dg/allocate_deferred_char_scalar_2.f03
Modified:
    branches/google/integration/gcc/fortran/ChangeLog
    branches/google/integration/gcc/fortran/dump-parse-tree.c
    branches/google/integration/gcc/fortran/iresolve.c
    branches/google/integration/gcc/fortran/trans-stmt.c
    branches/google/integration/gcc/testsuite/ChangeLog
Comment 9 Paul Thomas 2011-02-02 19:00:11 UTC
Fixed on trunk.... and on google.

Thanks for the report, Tobias.

Paul
Comment 10 Tobias Burnus 2011-02-02 20:53:09 UTC
(In reply to comment #9)
> Fixed on trunk.... and on google.

Really mark is as FIXED. Thanks Paul for the patch!