This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug fortran/31725] overwriting of neighbouring character array



------- Comment #4 from burnus at gcc dot gnu dot org  2007-04-27 18:59 -------
(Slabs oneself because of deleting important lines while deleting "only"
comments.)

Thanks for being persistent!


Reduced test case, should print twice "X,Y" but prints (once) ",Y".

The problem is that for
        zsymel(3)(lenstr(zsymel(3))+1:)='X'

lenstr() is called trice instead of only once.
The assignment should be:   string(1:3) = 'X  '

gfortran divides this into two parts: Assigning the 'X' and assigning the two
spaces; unfortunally, it calls strlen inbetween, which gives "1" after the "X"
has been assigned. And thus:

Thus instead of string(1:1) = 'X'; string(2:3) = '  '
         we do: string(1:1) = 'X'; string(1:2) = '  '

Or in the beauty of the dump:

__builtin_memmove ((char[1:_zsymel] *) &(*zsymel.0)[2][lenstr (&(*zsymel.0)[2],
_zsymel) + 1]{lb: 1 sz: 1}, "X", 1);
__builtin_memset ((char[1:_zsymel] *) &(*zsymel.0)[2][lenstr (&(*zsymel.0)[2],
_zsymel) + 1]{lb: 1 sz: 1} + 1B, 32, (int8) D

In addition it is called before in order to test whether an assignment should
be done at all:
  D.1374 = MAX_EXPR <_zsymel - lenstr (&(*zsymel.0)[2], _zsymel), 0>;

As lenstr could have side effects and because of speed, it makes sense to call
it only once and not twice or - as here - trice.

Example program:
      program char3
      implicit none
      character(3), dimension(3) :: zsymel,zsymelr
      common /xx/ zsymel, zsymelr
      integer :: znsymelr
      zsymel = (/ 'X', 'Y', ' ' /)
      zsymelr= (/ 'X', 'Y', ' ' /)
      znsymelr=2
      call check_zsymel(zsymel,zsymelr,znsymelr)
      contains
      subroutine check_zsymel(zsymel,zsymelr,znsymelr)
        implicit none
        integer znsymelr, isym
        character(*) zsymel(*),zsymelr(*)
        zsymel(3)(lenstr(zsymel(3))+1:)='X'
        write (*,10) (trim(zsymelr(isym)),isym=1,znsymelr)
10      format(3(a,:,','))
      end subroutine check_zsymel
      function lenstr(s)
        character(len=*),intent(in) :: s
        integer :: lenstr
        print *, 's: ',len_trim(s)
        lenstr = len_trim(s)
      end function lenstr
      end program


-- 

burnus at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
     Ever Confirmed|0                           |1
  GCC build triplet|i386-apple-darwin8.9.1      |
   GCC host triplet|i386-apple-darwin8.9.1      |
 GCC target triplet|i386-apple-darwin8.9.1      |
           Keywords|                            |wrong-code
   Last reconfirmed|0000-00-00 00:00:00         |2007-04-27 18:59:17
               date|                            |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31725


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]