[flang-commits] [flang] 5cf7ac6 - [flang][Semantics] reject COMMON/EQUIVALENCE/derived types whose size does not fit in int64 (#219976)

via flang-commits flang-commits at lists.llvm.org
Fri Sep 4 00:48:07 PDT 2026


Author: jeanPerier
Date: 2026-09-04T09:48:03+02:00
New Revision: 5cf7ac65133ec30e2a7333585961feae5b224983

URL: https://github.com/llvm/llvm-project/commit/5cf7ac65133ec30e2a7333585961feae5b224983
DIFF: https://github.com/llvm/llvm-project/commit/5cf7ac65133ec30e2a7333585961feae5b224983.diff

LOG: [flang][Semantics] reject COMMON/EQUIVALENCE/derived types whose size does not fit in int64 (#219976)

Semantics was not enforcing the overall byte sizes when of
common block and equivalence storage when building the related symbols
and computing offsets for members. The size and offset silently
overflow, leading to computing inconsistent offsets in lowering and
aborting compilation with internal errors like "error: 'hlfir.declare'
op storage offset exceeds the storage size".

This patch limits the storage of such objects to what can fit a signed
64 bit integer (like gfortran/ifx/classic flang).

Assisted-by: AI

Added: 
    flang/test/Semantics/common-block-size.f90
    flang/test/Semantics/oversized-storage-sequence.f90

Modified: 
    flang/lib/Semantics/compute-offsets.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/compute-offsets.cpp b/flang/lib/Semantics/compute-offsets.cpp
index f72bc844e89b6..06d9c50ecc6eb 100644
--- a/flang/lib/Semantics/compute-offsets.cpp
+++ b/flang/lib/Semantics/compute-offsets.cpp
@@ -9,6 +9,7 @@
 #include "compute-offsets.h"
 #include "flang/Evaluate/fold-designator.h"
 #include "flang/Evaluate/fold.h"
+#include "flang/Evaluate/shape.h"
 #include "flang/Evaluate/type.h"
 #include "flang/Runtime/descriptor-consts.h"
 #include "flang/Semantics/scope.h"
@@ -19,10 +20,46 @@
 #include "llvm/TargetParser/Host.h"
 #include "llvm/TargetParser/Triple.h"
 #include <algorithm>
+#include <cstdint>
+#include <limits>
 #include <vector>
 
 namespace Fortran::semantics {
 
+// Generated IR represents storage sizes and offsets as signed 64-bit integers.
+static_assert(sizeof(std::size_t) >= sizeof(std::int64_t),
+    "byte sizes and offsets are accumulated in std::size_t and must not be "
+    "narrowed");
+static constexpr std::size_t maxStorageSizeInBytes{
+    static_cast<std::size_t>(std::numeric_limits<std::int64_t>::max())};
+
+static bool IsTooBig(std::size_t bytes) {
+  return bytes > maxStorageSizeInBytes;
+}
+
+// Add sizes while tracking whether the signed 64-bit limit was exceeded.
+static std::size_t AddSizes(std::size_t x, std::size_t y, bool &tooBig) {
+  tooBig |= IsTooBig(x) || IsTooBig(y) || x > maxStorageSizeInBytes - y;
+  return x + y;
+}
+
+// A folded extent is (ub-lb+1) evaluated with signed 64-bit arithmetic, so it
+// comes out nonpositive both for an empty dimension and for one that wrapped
+// around, as in a(0:huge(0_8)). Tell those apart with the declared bounds.
+static bool IsEmptyDimension(const Symbol &symbol, int dimension) {
+  if (const auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
+    const ArraySpec &shape{object->shape()};
+    if (dimension < shape.Rank()) {
+      auto lb{evaluate::ToInt64(shape[dimension].lbound().GetExplicit())};
+      auto ub{evaluate::ToInt64(shape[dimension].ubound().GetExplicit())};
+      if (lb && ub) {
+        return *ub < *lb;
+      }
+    }
+  }
+  return true; // no constant bounds to contradict the folded extent
+}
+
 class ComputeOffsetsHelper {
 public:
   ComputeOffsetsHelper(SemanticsContext &context) : context_{context} {}
@@ -34,8 +71,14 @@ class ComputeOffsetsHelper {
     SizeAndAlignment(std::size_t bytes) : size{bytes}, alignment{bytes} {}
     SizeAndAlignment(std::size_t bytes, std::size_t align)
         : size{bytes}, alignment{align} {}
+    SizeAndAlignment(std::size_t bytes, std::size_t align, const Symbol *tooBig)
+        : size{bytes}, alignment{align}, oversized{tooBig} {}
     std::size_t size{0};
     std::size_t alignment{0};
+    // Null unless the size exceeds maxStorageSizeInBytes, in which case the
+    // size is clamped to it and this is the symbol to blame in a diagnostic:
+    // for an EQUIVALENCE storage sequence, the first member found not to fit.
+    const Symbol *oversized{nullptr};
   };
   struct SymbolAndOffset {
     SymbolAndOffset(Symbol &s, std::size_t off, const EquivalenceObject &obj)
@@ -44,6 +87,7 @@ class ComputeOffsetsHelper {
     MutableSymbolRef symbol;
     std::size_t offset;
     const EquivalenceObject *object;
+    bool offsetOverflow{false};
   };
 
   void DoCommonBlock(Symbol &);
@@ -62,6 +106,7 @@ class ComputeOffsetsHelper {
   SemanticsContext &context_;
   std::size_t offset_{0};
   std::size_t alignment_{1};
+  bool sizeOverflow_{false};
   // symbol -> symbol+offset that determines its location, from EQUIVALENCE
   std::map<MutableSymbolRef, SymbolAndOffset, SymbolAddressCompare> dependents_;
   // base symbol -> SizeAndAlignment for each distinct EQUIVALENCE block
@@ -156,21 +201,46 @@ void ComputeOffsetsHelper::Compute(Scope &scope) {
     symbol->set_size(symInfo.size);
     Symbol &base{*dep.symbol};
     auto iter{equivalenceBlock_.find(base)};
-    std::size_t minBlockSize{dep.offset + symInfo.size};
+    bool blockOverflow{dep.offsetOverflow || symInfo.oversized};
+    std::size_t minBlockSize{AddSizes(dep.offset, symInfo.size, blockOverflow)};
+    const Symbol *oversized{
+        blockOverflow || IsTooBig(minBlockSize) ? &*symbol : nullptr};
     if (iter == equivalenceBlock_.end()) {
       equivalenceBlock_.emplace(
-          base, SizeAndAlignment{minBlockSize, symInfo.alignment});
+          base, SizeAndAlignment{minBlockSize, symInfo.alignment, oversized});
     } else {
       SizeAndAlignment &blockInfo{iter->second};
       blockInfo.size = std::max(blockInfo.size, minBlockSize);
       blockInfo.alignment = std::max(blockInfo.alignment, symInfo.alignment);
+      if (!blockInfo.oversized) {
+        blockInfo.oversized = oversized;
+      }
     }
   }
-  // Assign offsets for non-COMMON EQUIVALENCE blocks
+  // Complete each EQUIVALENCE block with its base object, and assign offsets
+  // for non-COMMON blocks.
   for (auto &[symbol, blockInfo] : equivalenceBlock_) {
+    // The base does not appear in dependents_.
+    SizeAndAlignment baseInfo{GetSizeAndAlignment(*symbol, true)};
+    blockInfo.size = std::max(blockInfo.size, baseInfo.size);
+    blockInfo.alignment = std::max(blockInfo.alignment, baseInfo.alignment);
+    if (!blockInfo.oversized &&
+        (baseInfo.oversized || IsTooBig(baseInfo.size))) {
+      blockInfo.oversized = &*symbol;
+    }
     if (!FindCommonBlockContaining(*symbol)) {
       DoSymbol(*symbol);
       DoEquivalenceBlockBase(*symbol, blockInfo);
+      // Each EQUIVALENCE block is lowered as one aggregate. Blame a member
+      // that does not fit rather than the base object, whose selection in
+      // DoEquivalenceSet is a layout decision that is invisible to the user.
+      if (blockInfo.oversized || IsTooBig(blockInfo.size)) {
+        const Symbol &blamed{
+            blockInfo.oversized ? *blockInfo.oversized : *symbol};
+        context_.Say(blamed.name(),
+            "The size of the storage sequence created by EQUIVALENCE with '%s' exceeds the maximum supported size of %zu bytes"_err_en_US,
+            blamed.name(), maxStorageSizeInBytes);
+      }
       offset_ = std::max(offset_, symbol->offset() + blockInfo.size);
     }
   }
@@ -200,6 +270,13 @@ void ComputeOffsetsHelper::Compute(Scope &scope) {
   }
   // Ensure that the size is a multiple of the alignment
   offset_ = Align(offset_, alignment_);
+  sizeOverflow_ |= IsTooBig(offset_);
+  // Only derived-type scope sizes are materialized in generated IR.
+  if (sizeOverflow_ && scope.IsDerivedType() && scope.symbol()) {
+    context_.Say(scope.symbol()->name(),
+        "The size of derived type '%s' exceeds the maximum supported size of %zu bytes"_err_en_US,
+        scope.symbol()->name(), maxStorageSizeInBytes);
+  }
   scope.set_size(offset_);
   scope.SetAlignment(alignment_);
   // Assign offsets in COMMON blocks, unless this scope is a BLOCK construct,
@@ -226,7 +303,11 @@ auto ComputeOffsetsHelper::Resolve(const SymbolAndOffset &dep)
     return dep;
   } else {
     SymbolAndOffset result{Resolve(it->second)};
-    result.offset += dep.offset;
+    // Preserve overflow while resolving EQUIVALENCE chains, both the overflow
+    // already recorded for the offset being resolved and any that appears when
+    // accumulating it.
+    result.offsetOverflow |= dep.offsetOverflow;
+    result.offset = AddSizes(result.offset, dep.offset, result.offsetOverflow);
     result.object = dep.object;
     return result;
   }
@@ -236,6 +317,7 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
   auto &details{commonBlock.get<CommonBlockDetails>()};
   offset_ = 0;
   alignment_ = 0;
+  sizeOverflow_ = false;
   std::size_t minSize{0};
   std::size_t minAlignment{0};
   UnorderedSymbolSet previous;
@@ -290,12 +372,20 @@ void ComputeOffsetsHelper::DoCommonBlock(Symbol &commonBlock) {
     // 8.10.2.2 point 1 (2))
     if (eqIter != equivalenceBlock_.end()) {
       SizeAndAlignment &blockInfo{eqIter->second};
-      minSize = std::max(
-          minSize, std::max(offset_, eqIter->first->offset() + blockInfo.size));
+      sizeOverflow_ |= blockInfo.oversized != nullptr;
+      std::size_t blockEnd{
+          AddSizes(eqIter->first->offset(), blockInfo.size, sizeOverflow_)};
+      minSize = std::max(minSize, std::max(offset_, blockEnd));
       minAlignment = std::max(minAlignment, blockInfo.alignment);
     }
   }
-  commonBlock.set_size(std::max(minSize, offset_));
+  std::size_t size{std::max(minSize, offset_)};
+  if (sizeOverflow_) {
+    context_.Say(details.sourceLocation(),
+        "The size of COMMON block /%s/ exceeds the maximum supported size of %zu bytes"_err_en_US,
+        commonBlock.name(), maxStorageSizeInBytes);
+  }
+  commonBlock.set_size(size);
   details.set_alignment(std::max(minAlignment, alignment_));
   context_.MapCommonBlockAndCheckConflicts(commonBlock);
 }
@@ -325,7 +415,7 @@ void ComputeOffsetsHelper::DoEquivalenceSet(const EquivalenceSet &set) {
   }
   CHECK(representative);
   const SymbolAndOffset &base{symbolOffsets[*representative]};
-  for (const auto &[symbol, offset, object] : symbolOffsets) {
+  for (const auto &[symbol, offset, object, offsetOverflow] : symbolOffsets) {
     if (symbol == base.symbol) {
       if (offset != base.offset) {
         auto x{evaluate::OffsetToDesignator(
@@ -350,8 +440,9 @@ void ComputeOffsetsHelper::DoEquivalenceSet(const EquivalenceSet &set) {
         }
       }
     } else {
-      dependents_.emplace(*symbol,
-          SymbolAndOffset{*base.symbol, base.offset - offset, *object});
+      SymbolAndOffset dependent{*base.symbol, base.offset - offset, *object};
+      dependent.offsetOverflow = base.offsetOverflow || offsetOverflow;
+      dependents_.emplace(*symbol, dependent);
     }
   }
 }
@@ -398,6 +489,8 @@ std::size_t ComputeOffsetsHelper::DoSymbol(
     return 0;
   }
   SizeAndAlignment s{GetSizeAndAlignment(symbol, true)};
+  // Oversized standalone objects are left to object emission.
+  sizeOverflow_ |= s.oversized != nullptr;
   if (s.size == 0) {
     // Zero-size symbols (e.g. CHARACTER*0) still occupy their sequential
     // position in a COMMON block or derived-type sequence. Record the current
@@ -410,10 +503,11 @@ std::size_t ComputeOffsetsHelper::DoSymbol(
   std::size_t previousOffset{offset_};
   size_t alignVal{newAlign.value_or(s.alignment)};
   offset_ = Align(offset_, alignVal);
+  sizeOverflow_ |= IsTooBig(offset_);
   std::size_t padding{offset_ - previousOffset};
   symbol.set_size(s.size);
   symbol.set_offset(offset_);
-  offset_ += s.size;
+  offset_ = AddSizes(offset_, s.size, sizeOverflow_);
   alignment_ = std::max(alignment_, alignVal);
   return padding;
 }
@@ -444,17 +538,60 @@ auto ComputeOffsetsHelper::GetSizeAndAlignment(
   auto &foldingContext{context_.foldingContext()};
   if (auto chars{evaluate::characteristics::TypeAndShape::Characterize(
           symbol, foldingContext)}) {
-    if (entire) {
-      if (auto size{ToInt64(chars->MeasureSizeInBytes(foldingContext))}) {
-        return {static_cast<std::size_t>(*size),
-            chars->type().GetAlignment(targetCharacteristics)};
+    std::size_t alignment{chars->type().GetAlignment(targetCharacteristics)};
+    // Avoid folded products, which can wrap in signed 64-bit arithmetic.
+    bool aligned{!entire || chars->Rank() > 0};
+    std::size_t size;
+    if (chars->type().category() == TypeCategory::Character && chars->LEN()) {
+      auto length{ToInt64(*chars->LEN())};
+      if (!length) {
+        return {};
       }
-    } else { // element size only
-      if (auto size{ToInt64(chars->MeasureElementSizeInBytes(
-              foldingContext, true /*aligned*/))}) {
-        return {static_cast<std::size_t>(*size),
-            chars->type().GetAlignment(targetCharacteristics)};
+      auto bytesPerCharacter{
+          static_cast<std::size_t>(targetCharacteristics.GetByteSize(
+              TypeCategory::Character, chars->type().kind()))};
+      if (*length < 0 ||
+          static_cast<std::size_t>(*length) >
+              maxStorageSizeInBytes / bytesPerCharacter) {
+        return {maxStorageSizeInBytes, alignment, &symbol};
+      }
+      size = static_cast<std::size_t>(*length) * bytesPerCharacter;
+    } else {
+      auto elementSize{
+          ToInt64(chars->MeasureElementSizeInBytes(foldingContext, aligned))};
+      if (!elementSize) {
+        return {};
+      }
+      if (*elementSize < 0) {
+        return {maxStorageSizeInBytes, alignment, &symbol};
+      }
+      size = static_cast<std::size_t>(*elementSize);
+    }
+    if (!entire) { // element size only
+      return {size, alignment};
+    }
+    if (auto extents{
+            evaluate::AsConstantExtents(foldingContext, chars->shape())}) {
+      if (size == 0) { // zero-sized elements occupy no storage
+        return {0, alignment};
+      }
+      for (int dimension{0}; dimension < static_cast<int>(extents->size());
+          ++dimension) {
+        if ((*extents)[dimension] <= 0) {
+          if (!IsEmptyDimension(symbol, dimension)) {
+            return {maxStorageSizeInBytes, alignment, &symbol};
+          }
+          return {0, alignment}; // a zero-sized array occupies no storage
+        }
+      }
+      for (ConstantSubscript extent : *extents) {
+        auto n{static_cast<std::size_t>(extent)};
+        if (size > maxStorageSizeInBytes / n) {
+          return {maxStorageSizeInBytes, alignment, &symbol};
+        }
+        size *= n;
       }
+      return {size, alignment};
     }
   }
   return {};

diff  --git a/flang/test/Semantics/common-block-size.f90 b/flang/test/Semantics/common-block-size.f90
new file mode 100644
index 0000000000000..650cfcbf9d985
--- /dev/null
+++ b/flang/test/Semantics/common-block-size.f90
@@ -0,0 +1,29 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+
+! COMMON block byte sizes and offsets must fit in signed 64-bit integers.
+
+subroutine biggest
+  ! 2305843009213693951 * 4 bytes == huge(0_8) - 3, the largest REAL(4)
+  ! array that still fits.
+  real :: a(2305843009213693951_8)
+  common /fits/ a
+end subroutine
+
+subroutine one_object
+  real :: a(3000000000000000000_8)
+  !ERROR: The size of COMMON block /one/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /one/ a
+end subroutine
+
+subroutine several_objects
+  real :: a(1999999999999999999_8), b(1999999999999999999_8), &
+      c(1999999999999999999_8)
+  !ERROR: The size of COMMON block /several/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /several/ a, b, c
+end subroutine
+
+subroutine blank_common
+  real :: a(1999999999999999999_8), b(1999999999999999999_8)
+  !ERROR: The size of COMMON block // exceeds the maximum supported size of 9223372036854775807 bytes
+  common a, b
+end subroutine

diff  --git a/flang/test/Semantics/oversized-storage-sequence.f90 b/flang/test/Semantics/oversized-storage-sequence.f90
new file mode 100644
index 0000000000000..afe2835b7f754
--- /dev/null
+++ b/flang/test/Semantics/oversized-storage-sequence.f90
@@ -0,0 +1,172 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+
+! The storage sequences laid out for COMMON blocks, EQUIVALENCE sets, and
+! derived types must fit in a signed 64-bit byte size.
+! Oversized standalone objects are left to the assembler and linker.
+
+subroutine biggest_object
+  ! huge(0_8) bytes exactly, the largest object that can be laid out
+  character(len=9223372036854775807_8) :: c
+end subroutine
+
+subroutine biggest_array
+  ! 2305843009213693951 * 4 == huge(0_8) - 3 bytes
+  real :: a(2305843009213693951_8)
+end subroutine
+
+subroutine zero_sized_array
+  ! a zero-sized array is not a wrapped size
+  real :: z(2305843009213693952_8, 0)
+end subroutine
+
+subroutine explicit_bounds_that_fit
+  ! extent = huge(0_8) in both cases, one byte per element
+  integer(1) :: a(0_8:9223372036854775806_8)
+  integer(1) :: b(-9223372036854775807_8:-1_8)
+  common /fits1/ a
+  common /fits2/ b
+end subroutine
+
+subroutine empty_explicit_bounds
+  ! an upper bound below the lower bound makes the whole array empty
+  integer(8) :: a(1_8:0_8)
+  integer(8) :: b(-5_8:-10_8)
+  integer(8) :: c(2305843009213693952_8, 1_8:0_8)
+  common /empty/ a, b, c
+end subroutine
+
+subroutine unassociated_objects
+  ! A procedure scope is not laid out as one storage sequence.
+  integer(8) :: a(576460752303423488_8), b(576460752303423488_8), &
+      c(576460752303423488_8)
+  ! Standalone object sizes are also accepted here.
+  integer(8) :: d(1152921504606846976_8)
+  integer(8) :: e(2305843009213693952_8)
+  character(kind=4, len=2305843009213693952_8) :: f
+end subroutine
+
+subroutine object_size_in_common
+  ! 2305843009213693952 * 8 bytes is a multiple of 2**64, so the size folds to
+  ! exactly zero; without a diagnostic 'b' would silently overlap 'a'
+  integer(8) :: a(2305843009213693952_8)
+  integer(8) :: b(4)
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ a, b
+end subroutine
+
+subroutine element_size_in_common
+  ! the size of a single element does not fit: 4 * 2305843009213693952 bytes
+  character(kind=4, len=2305843009213693952_8) :: c
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ c
+end subroutine
+
+subroutine element_size_wraps_positive
+  ! 4 * (2**62 + 1) wraps around to 4 when folded as a signed 64-bit
+  ! integer, but the true element size does not fit
+  character(kind=4, len=4611686018427387905_8) :: c
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ c
+end subroutine
+
+subroutine zero_lower_bound_in_common
+  ! extent = huge(0_8) + 1 wraps around to a negative value, which must not be
+  ! taken for an empty dimension; without a diagnostic 'b' would overlap 'a'
+  integer(1) :: a(0_8:9223372036854775807_8)
+  integer(1) :: b(4)
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ a, b
+end subroutine
+
+subroutine negative_bounds_in_common
+  ! extent = huge(0_8) fits, but there are two bytes per element
+  integer(2) :: a(-9223372036854775807_8:-1_8)
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ a
+end subroutine
+
+subroutine negative_to_positive_bounds_in_common
+  ! extent = 2**63 wraps around to a negative value
+  integer(1) :: a(-4611686018427387904_8:4611686018427387903_8)
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ a
+end subroutine
+
+subroutine multidimensional_in_common
+  ! 2**32 * 2**32 == 2**64 elements, so the size folds to exactly zero
+  integer(1) :: a(4294967296_8, 4294967296_8)
+  integer(1) :: b(4)
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ a, b
+end subroutine
+
+subroutine multidimensional_bounds_in_common
+  ! same element count, spelled with explicit zero lower bounds
+  integer(1) :: a(0_8:4294967295_8, 0_8:4294967295_8)
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ a
+end subroutine
+
+module derived_type_size
+  !ERROR: The size of derived type 't' exceeds the maximum supported size of 9223372036854775807 bytes
+  type t
+    sequence
+    integer(8) :: a(576460752303423488_8), b(576460752303423488_8), &
+        c(576460752303423488_8)
+  end type
+  !ERROR: The size of derived type 'padded' exceeds the maximum supported size of 9223372036854775807 bytes
+  type padded
+    ! the components occupy exactly huge(0_8) bytes, but rounding that up to a
+    ! multiple of the alignment of the type no longer fits
+    sequence
+    integer(8) :: n
+    character(len=9223372036854775799_8) :: c
+  end type
+end module
+
+subroutine equivalence_block_size
+  ! the EQUIVALENCE chain extends the storage sequence to 3 * 2**62 bytes; the
+  ! accumulated offsets are what can wrap around into a plausible small value
+  integer(8) :: a(576460752303423488_8), b(576460752303423488_8)
+  !ERROR: The size of the storage sequence created by EQUIVALENCE with 'c' exceeds the maximum supported size of 9223372036854775807 bytes
+  integer(8) :: c(576460752303423488_8)
+  equivalence (a(576460752303423488_8), b(1))
+  equivalence (b(576460752303423488_8), c(1))
+end subroutine
+
+subroutine equivalence_oversized_member
+  ! The base of a storage sequence is picked for layout reasons and is often
+  ! its smallest member, so name the member that does not fit instead: here
+  ! 'marker' is the base, but 'oversized' is what the user has to shrink.
+  !ERROR: The size of the storage sequence created by EQUIVALENCE with 'oversized' exceeds the maximum supported size of 9223372036854775807 bytes
+  integer(1) :: oversized(0_8:9223372036854775807_8)
+  integer(8) :: marker
+  equivalence (oversized, marker)
+end subroutine
+
+subroutine equivalence_base_size
+  ! List the small object first so that the oversized array is selected as the
+  ! base of the EQUIVALENCE storage sequence.
+  !ERROR: The size of the storage sequence created by EQUIVALENCE with 'a' exceeds the maximum supported size of 9223372036854775807 bytes
+  integer(8) :: a(2305843009213693952_8)
+  integer(8) :: b
+  equivalence (b, a(1))
+end subroutine
+
+subroutine equivalence_block_placement
+  ! EQUIVALENCE block extents must fit independently of their scope offsets.
+  character(len=9223372036854775800_8) :: c1
+  character(len=8) :: c2
+  equivalence (c1(9223372036854775793_8:), c2)
+  integer :: a(2), b(2)
+  equivalence (a(1), b(1))
+end subroutine
+
+subroutine equivalence_block_size_in_common
+  integer(8) :: a(576460752303423488_8), b(576460752303423488_8), &
+      c(576460752303423488_8)
+  equivalence (a(576460752303423488_8), b(1))
+  equivalence (b(576460752303423488_8), c(1))
+  !ERROR: The size of COMMON block /blk/ exceeds the maximum supported size of 9223372036854775807 bytes
+  common /blk/ a
+end subroutine


        


More information about the flang-commits mailing list