https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90744
Bug ID: 90744
Summary: [9/10 Regression] Bogus length for character
temporaries passed to external procedures since
r268992
Product: gcc
Version: 9.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: fortran
Assignee: unassigned at gcc dot gnu.org
Reporter: trnka at scm dot com
Target Milestone: ---
The fix for PR87689 in r268992 broke some of our code that passes character
temporaries as actual arguments to external procedures. The length of the
string is not passed correctly, leading to segfaults once the external
procedure touches the string.
To reproduce, compile the following two files (gfortran -g concat-length.f90
convrs.f90) and see a segfault in convrs(). (I couldn't reduce this further.
For example, the seemingly useless "if" in DoTest() is important, convrs() has
to be called from both branches or the issue won't appear. I'd guess it's due
to some CSE/redundancy elimination, but the issue also occurs at -O0.)
external-char-length.f90
------------------------
module StringModule
implicit none
contains
function getstr()
character(:), allocatable :: getstr
getstr = 'OK'
end function
end module
module TestModule
use StringModule
implicit none
contains
subroutine DoTest()
if (.false.) then
call convrs('A',getstr())
else
call convrs('B',getstr())
end if
end subroutine
end module
program external_char_length
use TestModule
implicit none
call DoTest()
end program
------------------------
convrs.f90
------------------------
subroutine convrs(quanty,fromto)
implicit none
character(*), intent(in) :: quanty,fromto
write(*,*) fromto
end subroutine
------------------------
Comparing the dumps from a good and bad gfortran, it's evident that "slen.2" is
being passed incorrectly by reference:
--- good-85bbaeac3dd/external-char-length.f90.004t.original 2019-06-04
15:39:28.440490081 +0200
+++ bad-d50eaffb899/external-char-length.f90.004t.original 2019-06-04
15:28:39.410192786 +0200
@@ -51,7 +51,7 @@
pstr.3 = 0B;
slen.2 = 0;
getstr (&pstr.3, &slen.2);
- convrs (&"B"[1]{lb: 1 sz: 1}, pstr.3, 1, slen.2);
+ convrs (&"B"[1]{lb: 1 sz: 1}, pstr.3, 1, &slen.2);
__builtin_free ((void *) pstr.3);
}
L.3:;