Skip to content

[flang] Incorrect result for whole SEQUENCE component assignment with EQUIVALENCE aliasing #175246

@MattPD

Description

@MattPD

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?

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions