Reproducer, alias_seq_assign:
https://flang.godbolt.org/z/5z9rnq5e9
Flang appears to miscompile a test program that uses SEQUENCE types and EQUIVALENCE and performs a whole‑component intrinsic assignment c%b = d%b where c and d are different SEQUENCE views of the same storage. Other compilers (multiple gfortran versions, ifort/ifx) also fail this same test, suggesting this may be a common issue with the abstract Fortran semantics for this pattern.
To my understanding this program is standard‑conforming: It uses SEQUENCE derived types and an EQUIVALENCE statement in ways allowed by Fortran 2018 (7.5.2.3/Sequence type and 8.10.1/EQUIVALENCE statement).
The assignment c%b = d%b is a whole‑object intrinsic assignment between two SEQUENCE components of the same type, and must be executed componentwise:
- According to Fortran 2018, 10.2.1.2/Intrinsic assignment statement, items (7)–(8), intrinsic assignment is permitted between
c%b and d%b because they are compatible derived‑type variables with the same type and type parameters.
- 10.2.1.3/Interpretation of intrinsic assignments then specifies that execution of the intrinsic assignment
c%b = d%b has the same effect as if the expression d%b were fully evaluated before any portion of c%b is defined.
- In this case,
d%b is a SEQUENCE derived type with three integer components [1,2,3], so the final value of c%b must have those three component values, and hence the underlying equivalenced integer array e must end up as [1,1,2,3].
Expected semantics
Initial
After init_e (e = (/ (i, i=1,4) /)), we have e = [1,2,3,4].
Storage mapping via EQUIVALENCE:
c storage: [c%a, c%b%e(1), c%b%e(2), c%b%f(1)] = [1,2,3,4]
d storage: [d%b%e(1), d%b%e(2), d%b%f(1), d%a] = [1,2,3,4]
That is,
c%a is e(1)
c%b%e is e(2:3)
c%b%f(1) is e(4)
d%b%e is e(1:2)
d%b%f(1) is e(3)
d%a is e(4)
So d%b as a 3‑element SEQUENCE of integers is [1,2,3].
Right shift: c%b = d%b
The whole‑object intrinsic assignment c%b = d%b must copy those three original component values into c%b:
e(1) remains 1
c%b%e(1) = d%b%e(1) → e(2) = e(1)
c%b%e(2) = d%b%e(2) → e(3) = e(2)
c%b%f(1) = d%b%f(1) → e(4) = e(3)
Given e = [1,2,3,4] before right shift, the sequence is:
e(2) = e(1)
e(3) = e(2)
e(4) = e(3)
resulting in
e(1) unchanged = 1
e(2) = c%b%e(1) = 1
e(3) = c%b%e(2) = 2
e(4) = c%b%f(1) = 3
Thus the final e must be e = [1, 1, 2, 3] and check_right_shift should report no errors, printing: PASS alias_seq_assign.
Observed behavior
With flang (versions 21.1.8 - 22.0.0, checked as of commit 568b8e4), compiling with -O0 to -O3, the program results in a failure, and e contains values different from [1,1,2,3]:
2. Got e( 3 ) = 1 , expected 2
2. Got e( 4 ) = 1 , expected 3
What gives me pause is that other compilers (multiple gfortran versions, ifort/ifx) show similar failures on the same reproducer, so this appears to be a cross‑compiler corner case where the abstract semantics of whole‑object assignment in the presence of aliasing via EQUIVALENCE are not being respected.
However, CCE Fortran does result in correct compilation.
Interestingly, NVFortran 25.11 produces correct result for N=100, https://nvfortran.godbolt.org/z/sx6hEqd3d, but does result in a (different) failure for N=2: Got e( 4 ) = 2 , expected 3
Notes
A simpler test without EQUIVALENCE passes with flang; e and f are both copied. This suggests the bug is specific to the aliasing / equivalenced‑storage case, not to SEQUENCE assignment in general.
In a larger version of this test https://flang.godbolt.org/z/7WdoE7erj the generated FIR for c%b = d%b appears to only copy the e component of t. This may be an additional symptom of the same underlying issue (assignment in the presence of equivalenced host‑associated storage).
In particular, check_left_shift passes whereas check_right_shift fails.
Comparing HLFIR for both seems to show no major differences--however, FIR shows lowering for full assignment semantics for left_shift while FIR for right_shift is missing f.
This could indicate it's an HLFIR-to-FIR lowering problem?
Reproducer,
alias_seq_assign:https://flang.godbolt.org/z/5z9rnq5e9
Flang appears to miscompile a test program that uses
SEQUENCEtypes andEQUIVALENCEand performs a whole‑component intrinsic assignmentc%b = d%bwherecanddare differentSEQUENCEviews of the same storage. Other compilers (multiple gfortran versions, ifort/ifx) also fail this same test, suggesting this may be a common issue with the abstract Fortran semantics for this pattern.To my understanding this program is standard‑conforming: It uses
SEQUENCEderived types and anEQUIVALENCEstatement in ways allowed by Fortran 2018 (7.5.2.3/Sequence type and 8.10.1/EQUIVALENCEstatement).The assignment c%b = d%b is a whole‑object intrinsic assignment between two SEQUENCE components of the same type, and must be executed componentwise:
c%bandd%bbecause they are compatible derived‑type variables with the same type and type parameters.c%b = d%bhas the same effect as if the expressiond%bwere fully evaluated before any portion ofc%bis defined.d%bis aSEQUENCEderived type with three integer components[1,2,3], so the final value of c%b must have those three component values, and hence the underlying equivalenced integer array e must end up as[1,1,2,3].Expected semantics
Initial
After
init_e(e = (/ (i, i=1,4) /)), we havee = [1,2,3,4].Storage mapping via
EQUIVALENCE:cstorage:[c%a, c%b%e(1), c%b%e(2), c%b%f(1)] = [1,2,3,4]dstorage:[d%b%e(1), d%b%e(2), d%b%f(1), d%a] = [1,2,3,4]That is,
So
d%bas a 3‑elementSEQUENCEof integers is[1,2,3].Right shift:
c%b = d%bThe whole‑object intrinsic assignment
c%b = d%bmust copy those three original component values intoc%b:Given
e = [1,2,3,4]before right shift, the sequence is:resulting in
Thus the final
emust bee = [1, 1, 2, 3]andcheck_right_shiftshould report no errors, printing:PASS alias_seq_assign.Observed behavior
With flang (versions 21.1.8 - 22.0.0, checked as of commit 568b8e4), compiling with -O0 to -O3, the program results in a failure, and
econtains values different from[1,1,2,3]:What gives me pause is that other compilers (multiple gfortran versions, ifort/ifx) show similar failures on the same reproducer, so this appears to be a cross‑compiler corner case where the abstract semantics of whole‑object assignment in the presence of aliasing via EQUIVALENCE are not being respected.
However, CCE Fortran does result in correct compilation.
Interestingly, NVFortran 25.11 produces correct result for N=100, https://nvfortran.godbolt.org/z/sx6hEqd3d, but does result in a (different) failure for N=2:
Got e( 4 ) = 2 , expected 3Notes
A simpler test without
EQUIVALENCEpasses with flang;eandfare both copied. This suggests the bug is specific to the aliasing / equivalenced‑storage case, not to SEQUENCE assignment in general.In a larger version of this test https://flang.godbolt.org/z/7WdoE7erj the generated FIR for
c%b = d%bappears to only copy theecomponent oft. This may be an additional symptom of the same underlying issue (assignment in the presence of equivalenced host‑associated storage).In particular,
check_left_shiftpasses whereascheck_right_shiftfails.Comparing HLFIR for both seems to show no major differences--however, FIR shows lowering for full assignment semantics for
left_shiftwhile FIR forright_shiftis missingf.This could indicate it's an HLFIR-to-FIR lowering problem?