Issue 175246
Summary [flang] Incorrect result for whole `SEQUENCE` component assignment with `EQUIVALENCE` aliasing
Labels flang
Assignees
Reporter 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 568b8e4873b2d04be7ab302246c8e3986ea61176), 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?

_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to