[llvm] [flang-rt] Fix REAL(10)/COMPLEX(10) component sizes in runtime type info (PR #192049)

Sairudra More via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 04:55:42 PDT 2026


https://github.com/Saieiei updated https://github.com/llvm/llvm-project/pull/192049

>From dc680c4e9d5422a97cf3e8f905854f0d2ce98d6b Mon Sep 17 00:00:00 2001
From: Sairudra More <moresair at pe31.hpc.amslabs.hpecorp.net>
Date: Tue, 14 Apr 2026 07:46:11 -0500
Subject: [PATCH 1/2] [flang] Fix REAL(10)/COMPLEX(10) component sizes in
 runtime type info

For REAL(10) and COMPLEX(10) components, Component::GetElementByteSize()
was using the Fortran kind value as the byte size. On x86-64 that
underestimates the actual storage size (10 vs 16 bytes for REAL(10),
20 vs 32 for COMPLEX(10)), so strided componentwise assignment of
SEQUENCE types can corrupt adjacent data and crash.

Route REAL and COMPLEX component sizes through Descriptor::BytesFor(),
which matches the runtime existing storage-size handling.

Add a regression test covering strided assignment of a SEQUENCE type
with REAL(10)/COMPLEX(10) components.
---
 flang-rt/lib/runtime/type-info.cpp        |  5 ++--
 flang-rt/unittests/Runtime/Descriptor.cpp | 28 +++++++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/flang-rt/lib/runtime/type-info.cpp b/flang-rt/lib/runtime/type-info.cpp
index cb8e894bd3922..c5acfad3a98e3 100644
--- a/flang-rt/lib/runtime/type-info.cpp
+++ b/flang-rt/lib/runtime/type-info.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang-rt/runtime/type-info.h"
+#include "flang-rt/runtime/descriptor.h"
 #include "flang-rt/runtime/terminator.h"
 #include "flang-rt/runtime/tools.h"
 #include <cstdio>
@@ -37,11 +38,11 @@ RT_API_ATTRS std::size_t Component::GetElementByteSize(
   switch (category()) {
   case TypeCategory::Integer:
   case TypeCategory::Unsigned:
-  case TypeCategory::Real:
   case TypeCategory::Logical:
     return kind_;
+  case TypeCategory::Real:
   case TypeCategory::Complex:
-    return 2 * kind_;
+    return Descriptor::BytesFor(category(), kind_);
   case TypeCategory::Character:
     if (auto value{characterLen_.GetValue(&instance)}) {
       return kind_ * *value;
diff --git a/flang-rt/unittests/Runtime/Descriptor.cpp b/flang-rt/unittests/Runtime/Descriptor.cpp
index 7737b91d8a5b4..fc7f266dd17c6 100644
--- a/flang-rt/unittests/Runtime/Descriptor.cpp
+++ b/flang-rt/unittests/Runtime/Descriptor.cpp
@@ -280,3 +280,31 @@ TEST(Descriptor, Dump) {
   fclose(tmpf);
 }
 #endif // defined(__linux__) && !defined(__ANDROID__)
+
+// Verify that Descriptor::BytesFor returns the correct storage size
+// for Real and Complex types, especially for kind=10 where the x87
+// 80-bit extended precision value is stored in a 16-byte container.
+TEST(Descriptor, BytesForRealAndComplex) {
+  using TC = TypeCategory;
+  // Real kinds: storage size should account for container padding
+  EXPECT_EQ(Descriptor::BytesFor(TC::Real, 2), 2u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Real, 3), 2u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Real, 4), 4u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Real, 8), 8u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Real, 10),
+      16u); // x87: 80-bit in 128-bit container
+  EXPECT_EQ(Descriptor::BytesFor(TC::Real, 16), 16u);
+  // Complex kinds: should be twice the Real storage size
+  EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 2), 4u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 3), 4u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 4), 8u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 8), 16u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 10), 32u); // x87: 2 * 16 bytes
+  EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 16), 32u);
+  // Integer and Logical kinds: storage size equals the kind value
+  EXPECT_EQ(Descriptor::BytesFor(TC::Integer, 1), 1u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Integer, 4), 4u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Integer, 8), 8u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Logical, 1), 1u);
+  EXPECT_EQ(Descriptor::BytesFor(TC::Logical, 4), 4u);
+}

>From f85904f400844ffba6688052cf1191370f092987 Mon Sep 17 00:00:00 2001
From: Sairudra More <moresair at pe31.hpc.amslabs.hpecorp.net>
Date: Tue, 14 Apr 2026 12:00:15 -0500
Subject: [PATCH 2/2] [flang-rt] Guard kind-10 checks on x86 and test
 GetElementByteSize

Fixes #192085
---
 flang-rt/unittests/Runtime/Descriptor.cpp | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/flang-rt/unittests/Runtime/Descriptor.cpp b/flang-rt/unittests/Runtime/Descriptor.cpp
index fc7f266dd17c6..b2ad4700964d4 100644
--- a/flang-rt/unittests/Runtime/Descriptor.cpp
+++ b/flang-rt/unittests/Runtime/Descriptor.cpp
@@ -291,15 +291,22 @@ TEST(Descriptor, BytesForRealAndComplex) {
   EXPECT_EQ(Descriptor::BytesFor(TC::Real, 3), 2u);
   EXPECT_EQ(Descriptor::BytesFor(TC::Real, 4), 4u);
   EXPECT_EQ(Descriptor::BytesFor(TC::Real, 8), 8u);
-  EXPECT_EQ(Descriptor::BytesFor(TC::Real, 10),
-      16u); // x87: 80-bit in 128-bit container
+#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
+    defined(_M_IX86)
+  // x87: 80-bit in 128-bit container
+  EXPECT_EQ(Descriptor::BytesFor(TC::Real, 10), 16u);
+#endif
   EXPECT_EQ(Descriptor::BytesFor(TC::Real, 16), 16u);
   // Complex kinds: should be twice the Real storage size
   EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 2), 4u);
   EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 3), 4u);
   EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 4), 8u);
   EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 8), 16u);
-  EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 10), 32u); // x87: 2 * 16 bytes
+#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
+    defined(_M_IX86)
+  // x87: 2 * 16 bytes
+  EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 10), 32u);
+#endif
   EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 16), 32u);
   // Integer and Logical kinds: storage size equals the kind value
   EXPECT_EQ(Descriptor::BytesFor(TC::Integer, 1), 1u);



More information about the llvm-commits mailing list