[Bug fortran/31725] overwriting of neighbouring character array

2007-04-27 Thread KnowlesPJ at Cardiff dot ac dot uk


--- Comment #1 from KnowlesPJ at Cardiff dot ac dot uk  2007-04-27 10:34 
---
Created an attachment (id=13455)
 -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=13455action=view)
failing program


-- 


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



[Bug fortran/31725] overwriting of neighbouring character array

2007-04-27 Thread burnus at gcc dot gnu dot org


--- Comment #2 from burnus at gcc dot gnu dot org  2007-04-27 15:47 ---
The program is broken / invalid:

  function lenstr(s)
  character*(*) s
  do 1 l=ll,1,-1
  if (s(l:l).ne.' ') goto 2
1 continue

Question: What value has ll ? 0, 325, -4326 ?

Depending on the compiler, anything may happen. Using NAG f95 I simply get a
coredump, using gfortran I got This should not happen. The Intel compiler
silently sets this number to zero and runs l = 0, 1, -1. I think neither does
the right thing.

If I add
  ll = 0
all my compilers produce the same result - however meaningless/-full it might
be.

By the way, using Fortran 95, you have the function LEN_TRIM which gives the
string length without tailing blanks.

If there remains another bug, please reopen.


-- 

burnus at gcc dot gnu dot org changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution||INVALID


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



[Bug fortran/31725] overwriting of neighbouring character array

2007-04-27 Thread KnowlesPJ at Cardiff dot ac dot uk


--- Comment #3 from KnowlesPJ at Cardiff dot ac dot uk  2007-04-27 16:13 
---
I don't agree with this analysis, as ll is certainly defined in char3.f as
attached -
ll=len(s)
Please try with the program exactly as supplied!
Yes, you are right, this function is the same as len_trim but all I am doing is
pulling a small extract from a legacy code and I wanted simply to expose the
problem not tidy up.  But if I replace lenstr by len_trim the error still
occurs.


-- 

KnowlesPJ at Cardiff dot ac dot uk changed:

   What|Removed |Added

 Status|RESOLVED|UNCONFIRMED
 Resolution|INVALID |


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



[Bug fortran/31725] overwriting of neighbouring character array

2007-04-27 Thread burnus at gcc dot gnu dot org


--- 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|-00-00 00:00:00 |2007-04-27 18:59:17
   date||


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