On Aug 14 2019, Mark Eggleston <[hidden email]> wrote:
> * gfortran.dg/auto_in_equiv_3.f90: New test. This test fails everywhere. Andreas. -- Andreas Schwab, [hidden email] GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1 "And now for something completely different." |
On Sat, Sep 28, 2019 at 10:33:26PM +0200, Andreas Schwab wrote:
> On Aug 14 2019, Mark Eggleston <[hidden email]> wrote: > > > * gfortran.dg/auto_in_equiv_3.f90: New test. > > This test fails everywhere. Yes, and _2 on i686-linux at -O0. To me both testcases are undefined behavior. E.g. the first one has: subroutine suba(option) integer, intent(in) :: option integer, automatic :: a integer :: b integer :: c equivalence (a, b) if (option.eq.0) then ! initialise a and c a = 9 c = 99 if (a.ne.b) stop 1 if (loc(a).ne.loc(b)) stop 2 else ! a should've been overwritten if (a.eq.9) stop 3 end if end subroutine suba My understanding is that because a is explicitly automatic and b is automatic too (implicitly), the whole equivalence is automatic, so if you call this subroutine with non-zero option, you read an uninitialized variable and compare it to 9. That can result in anything, .false., .true., disk formatting, you can't rely on some other routine laying out its automatic variable at exactly the same spot and overwriting the memory in there, not to mention that the compiler can easily spot the uninitialized use too. Similarly in the second test, returning address of an automatic variable from a function is already something e.g. the C/C++ FEs warn about, because you really can't do anything useful with that address, it can't be dereferenced, or even the comparisons to addresses of other automatic variables that left their scope is wrong. IMHO if you want to check if a variable is SAVEd or AUTOMATIC, you want to recurse, either directly or indirectly, pass the address of the variable in the outer subroutine down to the inner one and compare there, SAVEd variables need to have the same address, while AUTOMATIC variables where both the outer and inner variable is at that point still in the scope need to have the addresses different. Though, in order to have in Fortran a recursively callable subroutine, one needs to use RECURSIVE. So, IMHO we want 4 testcases out of these 2, two dg-do compile only which will verify the tests compile when mixing automatic with no explicit save/automatic in equivalence and will -fdump-tree-gimple and scan the gimple dump to verify there is equiv.\[0-9]* variable which is not static, and then two runtime testcases like (one with just -fdec-static, one with also -fno-automatic, though guess it doesn't matter that much, as recursive already implies that it is automatic). program test integer :: dummy integer, parameter :: address = kind(loc(dummy)) integer(address) :: addr addr = 0 call sub (0, addr) contains recursive subroutine sub (option, addr) integer, intent(in) :: option integer(address), intent(in) :: addr integer, automatic :: a integer :: b integer(address) :: c equivalence (a, b) if (option.eq.0) then a = 9 if (a.ne.b) stop 1 if (loc(a).ne.loc(b)) stop 2 c = loc(a) call sub (1, c) if (a.ne.9) stop 3 else a = 10 if (a.ne.b) stop 4 if (loc(a).ne.loc(b)) stop 5 if (addr.eq.loc(a)) stop 6 end if end subroutine sub end program test Jakub |
Thanks, as you point out all the test needs to do is verify that that a
variable with an AUTOMATIC attribute can be used in an EQUIVALENCE and and that the items in the EQUIVALENCE are on the stack by using in a recursive routine. I've created a patch to replace the existing test cases and have sent it to this e-mail thread https://gcc.gnu.org/ml/fortran/2019-09/msg00123.html regards, Mark On 30/09/2019 11:24, Jakub Jelinek wrote: > On Sat, Sep 28, 2019 at 10:33:26PM +0200, Andreas Schwab wrote: >> On Aug 14 2019, Mark Eggleston <[hidden email]> wrote: >> >>> * gfortran.dg/auto_in_equiv_3.f90: New test. >> This test fails everywhere. > Yes, and _2 on i686-linux at -O0. > > To me both testcases are undefined behavior. > E.g. the first one has: > subroutine suba(option) > integer, intent(in) :: option > integer, automatic :: a > integer :: b > integer :: c > equivalence (a, b) > if (option.eq.0) then > ! initialise a and c > a = 9 > c = 99 > if (a.ne.b) stop 1 > if (loc(a).ne.loc(b)) stop 2 > else > ! a should've been overwritten > if (a.eq.9) stop 3 > end if > end subroutine suba > My understanding is that because a is explicitly automatic and b is automatic too > (implicitly), the whole equivalence is automatic, so if you call this > subroutine with non-zero option, you read an uninitialized variable and > compare it to 9. That can result in anything, .false., .true., disk > formatting, you can't rely on some other routine laying out its automatic > variable at exactly the same spot and overwriting the memory in there, not > to mention that the compiler can easily spot the uninitialized use too. > Similarly in the second test, returning address of an automatic variable > from a function is already something e.g. the C/C++ FEs warn about, because > you really can't do anything useful with that address, it can't be > dereferenced, or even the comparisons to addresses of other automatic > variables that left their scope is wrong. > > IMHO if you want to check if a variable is SAVEd or AUTOMATIC, you want to > recurse, either directly or indirectly, pass the address of the variable in > the outer subroutine down to the inner one and compare there, SAVEd > variables need to have the same address, while AUTOMATIC variables where > both the outer and inner variable is at that point still in the scope need > to have the addresses different. > > Though, in order to have in Fortran a recursively callable subroutine, one > needs to use RECURSIVE. > So, IMHO we want 4 testcases out of these 2, two dg-do compile only which > will verify the tests compile when mixing automatic with no explicit > save/automatic in equivalence and will -fdump-tree-gimple and scan the > gimple dump to verify there is equiv.\[0-9]* variable which is not static, > and then two runtime testcases like (one with just -fdec-static, one with > also -fno-automatic, though guess it doesn't matter that much, as recursive > already implies that it is automatic). > program test > integer :: dummy > integer, parameter :: address = kind(loc(dummy)) > integer(address) :: addr > addr = 0 > call sub (0, addr) > contains > recursive subroutine sub (option, addr) > integer, intent(in) :: option > integer(address), intent(in) :: addr > integer, automatic :: a > integer :: b > integer(address) :: c > equivalence (a, b) > if (option.eq.0) then > a = 9 > if (a.ne.b) stop 1 > if (loc(a).ne.loc(b)) stop 2 > c = loc(a) > call sub (1, c) > if (a.ne.9) stop 3 > else > a = 10 > if (a.ne.b) stop 4 > if (loc(a).ne.loc(b)) stop 5 > if (addr.eq.loc(a)) stop 6 > end if > end subroutine sub > end program test > > Jakub > https://www.codethink.co.uk/privacy.html |
Free forum by Nabble | Edit this page |