-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error message is not returned correctly by gfortran 9+ #24
Comments
As an example, when the Here's a minimal reproducer that mimics the module foo
contains
subroutine set(msg)
character(:), allocatable, intent(out), optional :: msg
if (present(msg)) msg = 'foo'
end subroutine set
subroutine wrap(msg)
character(:), allocatable, intent(out), optional :: msg
call set(msg)
end subroutine wrap
end module foo
program minimal
use foo
character(:), allocatable :: msg
call wrap(msg)
print *, msg
end program minimal Note that removing the optional attribute from either subroutine solves the issue. So one possible fix is to have two |
Thanks for the report David. I'll see what I can do. |
I've been digging into this problem. For poking around I've taken your example and added another level of "pass-through" call like your wrap to give the more general situation. And yes, the error is triggered by a call where the dummy argument is an optional deferred-length allocatable character, and the corresponding actual argument is likewise an optional deferred-length character in the calling routine. The length of the allocated character is not being propagated from the dummy back to the actual. In any other situation things seems to work okay. I had hoped to be able to perhaps fiddle with the error routine (by possibly adding calls to auxiliary procedures with non-optional args) to fix things since that's a single point in the flow. But that's not possible. The solution you propose would take care of the "wrap -> set" call, but that involves making workarounds in dozens of places, and if only fixes things for one hierarchy of calls. Another fix (equally obnoxious) is to always pass a local deferred-length allocatable character as the actual argument, and then copy the returned temporary to the original optional dummy variable. So I'm not sure how I'm going to handle this. I'm tempted to alter the API for gfortran to make the error handling arguments non-optional. That hack may be cleaner. The bigger issue for us is this gfortran bug affects Truchas as well; we make a lot of use of optional deferred-length allocatable character arguments. |
Incidentally, in my poking around I was printing the address of the print '(z16.16)', transfer(c_loc(msg), 1_int64) and it was curious that the address was always the same (and it was the start of the actual string). It was if the generated code was treating |
I looked into this again, but couldn't think of any better workarounds than the ones you pointed out. At least not any fully safe ones. There's a simple fix, but it relies on undefined behavior. By removing the However, this may be an ok solution for Truchas if we know that an actual subroutine error (errmsg_, stat, errmsg)
use,intrinsic :: iso_fortran_env, only: error_unit
character(*), intent(in) :: errmsg_
integer, intent(out), optional :: stat
character(:), allocatable, intent(out) :: errmsg
if (present(stat)) then
stat = 1
if (present(stat)) errmsg = errmsg_
else
write(error_unit,'(a)') 'ERROR: ' // errmsg_
stop 1
end if
end subroutine error It's kind of janky, but I think it should work given the above condition on |
I think this is a great solution @dhnza. The bug arises in an "A calls B" situation where |
Argh. I spoke too soon. Compiles fine, but segfaults on the call to |
Actually it does work with a slight tweak! The segfault is apparently coming from the deallocation of |
Workaround for gfortran bug (resolves #24)
Great, I'm glad the fix worked out in the end! |
This is related to GNU 93762.
In short, when passing optional deferred-length strings through multiple calls, gfortran doesn't propagate the string's length up the chain. The string length at the top of the chain is uninitialized, which can lead to allocation errors like
This bug is triggered whenever an
errmsg
is returned by one of theparameter_list
procedures, for exampleIf integers are default initialized to 0, such as with the flag
-finit-integer=0
, then the above error is not catastrophic but an empty string is returned.The text was updated successfully, but these errors were encountered: