[flang-commits] [flang] [flang] Fix `getTypeSizeAndAlignment` for packed/tail-padded `RecordType` and `TRANSFER` gate (PR #220377)
via flang-commits
flang-commits at lists.llvm.org
Thu Sep 3 12:52:58 PDT 2026
================
@@ -0,0 +1,67 @@
+! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-hlfir %s -o - | FileCheck %s
+! REQUIRES: x86-registered-target
+
+! Regression test for https://github.com/llvm/llvm-project/pull/220377
+!
+! The TRANSFER inline gate compares store sizes, not allocation sizes.
+! Tail padding must not be included in the comparison.
+!
+! Types declared at module scope so that bare %flang_fc1 does not abort when
+! TRANSFER falls through to the runtime path (pre-existing defect: runtime
+! TRANSFER of a subroutine-local derived type aborts under bare %flang_fc1).
+
+! Shape 1: tail-padded record whose store size matches real(10).
+! t1 fields: integer(8) [8B, align 8] + integer(2) [2B, align 2]
+! Store size = 10B; allocation size = alignTo(10, 8) = 16B.
+! real(10) = f80 on x86-64: store size = 10B.
+! 10 == 10 on store size -> must INLINE (fir.load), not call _FortranATransfer.
+! Without the storeSizeOnly fix the allocation size (16) != 10 and this
+! would wrongly fall through to the runtime path.
+module m1
+ type :: t1
+ integer(8) :: a
+ integer(2) :: b
+ end type
+end module
+
+! Shape 2: tail-padded record whose allocation size matches integer(8) but
+! whose store size does not.
+! t2 fields: integer(4) [4B, align 4] + integer(1) [1B, align 1]
+! Store size = 5B; allocation size = alignTo(5, 4) = 8B.
+! integer(8) store size = 8B.
+! Without the storeSizeOnly fix: 8 == 8 on allocation size -> would inline,
+! but that reads 3 bytes of uninitialized tail padding into the result.
+! With the fix: 5 != 8 on store size -> correctly stays on RUNTIME path.
+module m2
+ type :: t2
+ integer(4) :: a
+ integer(1) :: b
+ end type
+end module
+
+subroutine transfer_rec_to_real10(out)
+ ! CHECK-LABEL: func @_QPtransfer_rec_to_real10(
+ ! CHECK-NOT: fir.call @_FortranATransfer
+ ! CHECK: fir.convert {{.*}} : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<f80>
+ ! CHECK: fir.load {{.*}} : !fir.ref<f80>
----------------
MattPD wrote:
The `transfer_rec_to_real10` routine lowers cleanly through `flang -fc1 -emit-llvm` when compiled alone. The missing-descriptor abort comes from `transfer_rec_to_int8`, which exercises the runtime path. Could the positive case move to a test on the final LLVM IR that checks the aligned storage and byte copy?
https://github.com/llvm/llvm-project/pull/220377
More information about the flang-commits
mailing list