Bug 34396 - Length of substrings defined by expressions not correctly computed in constructors
Summary: Length of substrings defined by expressions not correctly computed in constru...
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:
Depends on:
Blocks: 32834
  Show dependency treegraph
 
Reported: 2007-12-08 21:02 UTC by Dominique d'Humieres
Modified: 2008-01-10 19:13 UTC (History)
1 user (show)

See Also:
Host: i686-apple-darwin9
Target: i686-apple-darwin9
Build: i686-apple-darwin9
Known to work:
Known to fail:
Last reconfirmed: 2007-12-16 11:45:31


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dominique d'Humieres 2007-12-08 21:02:13 UTC
The following code

program array_char
implicit none
integer :: i
character (len=5) :: x, y
character (len=5) :: z(2)
x = "a "
y = "cd"
z = ""
z = (/y(1:len(trim(y))), x(1:len(trim(x)))/) 
print *, "|", z(1), "|  |", z(2), "|"
print '(99i4)', ichar ( [ (z(1)(i:i), i=1,5) ] )
print '(99i4)', ichar ( [ (z(2)(i:i), i=1,5) ] )
end program array_char

gives

[ibook-dhum] f90/bug% a.out
 |cdI|  |a`
           |
  99 100 128  73  16
  97  96  12  17   0

As reported in PR33254, comment #14, the length of the strings seems not computed inget_array_ctor_var_strlen() by:

          if (ref->u.ss.start->expr_type != EXPR_CONSTANT
              || ref->u.ss.end->expr_type != EXPR_CONSTANT)
            break;
Comment 1 Tobias Burnus 2007-12-08 23:02:57 UTC
According to NAG f95 the program is invalid; it prints at run time:

Unequal character lengths (1 and 2) in array constructor
Program terminated by fatal error
In ARRAY_CHAR, line 9 of aaa.f90

I actually would expect gfortran to diagnose this with -fbounds-check.
Comment 2 Dominique d'Humieres 2007-12-08 23:08:32 UTC
> I actually would expect gfortran to diagnose this with -fbounds-check.

Me too, but this works only if the lengths are correctly computed. The test case pass the bounds check.

Comment 3 Joost VandeVondele 2007-12-09 06:20:03 UTC
changing into:

z = (/y(1:len(trim(y))), x(1:len(trim(x)))//"e"/)

makes this valid and shows the same issue on valid code
Comment 4 Paul Thomas 2007-12-09 09:29:20 UTC
For the original, I am getting:

 |cd|  |a|
  99 100   0   0   0
  97   0   0   0   0

and for comment #3:

 |cd|  |ae|
  99 100   0   0   0
  97 101   0   0   0

Today's trunk on x86_ia64/fc5.

Paul
Comment 5 Dominique d'Humieres 2007-12-09 09:34:54 UTC
> For the original, I am getting: ...

Yes it depends of the memory content, anyway the 0 in your results should be spaces.

Comment 6 Paul Thomas 2007-12-09 17:14:12 UTC
Dominique,

> Yes it depends of the memory content, anyway the 0 in your results should be
> spaces.
> 

Ah yes.  The problem is in trans-array.c(gfc_trans_array_ctor_element), where   the assignment, line 975 onwards, uses memcpy and produces this code:

    {
      integer(kind=4) D.879;
      integer(kind=4) len.6;
      character(kind=1) * pstr.5;

      _gfortran_string_trim (&len.6, (void * *) &pstr.5, 5, &y[1]{lb: 1 sz: 1});
      D.879 = len.6;
      if (len.6 > 0)
        {
          {
            void * D.878;

            D.878 = (void *) pstr.5;
            if (D.878 != 0B)
              {
                __builtin_free (D.878);
              }
          }
        }
      __builtin_memcpy (&(*(character(kind=1)[0:][1:5] *) atmp.2.data)[0][1]{lb: 1 sz: 1}, &y[1]{lb: 1 sz: 1}, MAX_EXPR <NON_LVALUE_EXPR <D.879>, 0>);
    }

This is called in two places and the returned se->string_length could be used for bounds checking.  Also, the required padding with spaces could be done too.  ss->string_length has the length of the target.

I am setting aside evenings of this week to a determined attack on PRs 31213, 33888 and 33998.  I have solutions to most of the bugs and it now needs packaging up and submitting. If this PR still remains next week, I'll give it a try.  Otherwise, I would be happy to lend a helping hand...

Cheers

Paul
Comment 7 Paul Thomas 2007-12-16 11:45:31 UTC
OK then, I'll give it a try!

Paul
Comment 8 Tobias Burnus 2008-01-10 07:45:28 UTC
Patch: http://gcc.gnu.org/ml/fortran/2008-01/msg00117.html
Comment 9 Paul Thomas 2008-01-10 19:11:32 UTC
Subject: Bug 34396

Author: pault
Date: Thu Jan 10 19:10:48 2008
New Revision: 131448

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

	PR fortran/34396
	* trans-array.c (gfc_trans_array_ctor_element):  Use gfc_trans_string_copy
	to assign strings and perform bounds checks on the string length.
	(get_array_ctor_strlen): Remove bounds checking.
	(gfc_trans_array_constructor): Initialize string length checking.
	* trans-array.h : Add prototype for gfc_trans_string_copy.

2008-01-10  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/34396
	* gfortran.dg/bounds_check_12.f90: New test.

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

Comment 10 Paul Thomas 2008-01-10 19:13:34 UTC
Fixed on trunk

Paul
Comment 11 Paul Thomas 2008-06-17 18:09:11 UTC
Subject: Bug 34396

Author: pault
Date: Tue Jun 17 18:08:24 2008
New Revision: 136871

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=136871
Log:
2008-06-17  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/34396
	* resolve.c (add_dt_to_dt_list):  New function.
	(resolve_fl_derived): Call new function for pointer components
	and when derived type resolved.

2008-06-17  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/36366
	* gfortran.dg/used_types_20.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/used_types_20.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog