[Mlir-commits] [flang] [llvm] [mlir] [Flang] [Runtime ]Fix write endfile abort (PR #191633)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat Apr 11 07:39:17 PDT 2026


https://github.com/blazie2004 created https://github.com/llvm/llvm-project/pull/191633

A WRITE after ENDFILE with ERR= or IOSTAT= was crashing instead of handling the error properly .Earlier, the program was crashing because the error was triggered too early (before error handling was ready). Now, the error is just stored first using SignalPendingIoStat() and handled later, so IOSTAT is set and it correctly jumps to the ERR= label instead of crashing.

>From 26ab7b3e7e6551d3ebf2450b161f6b5db8279056 Mon Sep 17 00:00:00 2001
From: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Date: Thu, 26 Mar 2026 04:33:15 -0500
Subject: [PATCH 1/2] Revert "[mlir][bytecode] Fix crashes when reading
 bytecode with unsupported types (#186354)"

This reverts commit e904d559c5ae071a5d04cdf003021cb3df2bb1a4.
---
 .../include/mlir/IR/BuiltinDialectBytecode.td |  5 +-
 mlir/lib/IR/BuiltinDialectBytecode.cpp        | 22 +++-----
 .../invalid-dense-elem-type-interface.mlir    | 15 +++++
 .../invalid/invalid-type-remapping.mlir       | 55 -------------------
 4 files changed, 25 insertions(+), 72 deletions(-)
 create mode 100644 mlir/test/Bytecode/invalid/invalid-dense-elem-type-interface.mlir
 delete mode 100644 mlir/test/Bytecode/invalid/invalid-type-remapping.mlir

diff --git a/mlir/include/mlir/IR/BuiltinDialectBytecode.td b/mlir/include/mlir/IR/BuiltinDialectBytecode.td
index 8a1f3d5e5b2e0..7a0a7e71ba24b 100644
--- a/mlir/include/mlir/IR/BuiltinDialectBytecode.td
+++ b/mlir/include/mlir/IR/BuiltinDialectBytecode.td
@@ -296,9 +296,6 @@ def VectorType : DialectType<(type
   Type:$elementType
 )> {
   let printerPredicate = "!$_val.isScalable()";
-  // Use getChecked to produce a null type (and emit a diagnostic) instead of
-  // asserting when the element type does not implement VectorElementTypeInterface.
-  let cBuilder = "VectorType::getChecked([&]() { return reader.emitError(\"invalid vector type\"); }, shape, elementType)";
 }
 
 def VectorTypeWithScalableDims : DialectType<(type
@@ -308,7 +305,7 @@ def VectorTypeWithScalableDims : DialectType<(type
 )> {
   let printerPredicate = "$_val.isScalable()";
   // Note: order of serialization does not match order of builder.
-  let cBuilder = "getChecked<$_resultType>([&]() { return reader.emitError(); }, context, shape, elementType, scalableDims)";
+  let cBuilder = "get<$_resultType>(context, shape, elementType, scalableDims)";
 }
 }
 
diff --git a/mlir/lib/IR/BuiltinDialectBytecode.cpp b/mlir/lib/IR/BuiltinDialectBytecode.cpp
index 14dc665184099..f7430784dd222 100644
--- a/mlir/lib/IR/BuiltinDialectBytecode.cpp
+++ b/mlir/lib/IR/BuiltinDialectBytecode.cpp
@@ -33,27 +33,23 @@ namespace {
 
 // TODO: Move these to separate file.
 
-// Returns the bitwidth if known, else return std::nullopt.
-static std::optional<unsigned> getIntegerBitWidth(DialectBytecodeReader &reader,
-                                                  Type type) {
-  if (auto intType = dyn_cast<IntegerType>(type))
+// Returns the bitwidth if known, else return 0.
+static unsigned getIntegerBitWidth(DialectBytecodeReader &reader, Type type) {
+  if (auto intType = dyn_cast<IntegerType>(type)) {
     return intType.getWidth();
-  if (llvm::isa<IndexType>(type))
+  }
+  if (llvm::isa<IndexType>(type)) {
     return IndexType::kInternalStorageBitWidth;
+  }
   reader.emitError()
       << "expected integer or index type for IntegerAttr, but got: " << type;
-  return std::nullopt;
+  return 0;
 }
 
 static LogicalResult readAPIntWithKnownWidth(DialectBytecodeReader &reader,
                                              Type type, FailureOr<APInt> &val) {
-  std::optional<unsigned> bitWidth = getIntegerBitWidth(reader, type);
-  // getIntegerBitWidth returns std::nullopt and emits an error for unsupported
-  // types. Bail out early to avoid creating a zero-width APInt with a non-zero
-  // value.
-  if (!bitWidth)
-    return failure();
-  val = reader.readAPIntWithKnownWidth(*bitWidth);
+  unsigned bitWidth = getIntegerBitWidth(reader, type);
+  val = reader.readAPIntWithKnownWidth(bitWidth);
   return val;
 }
 
diff --git a/mlir/test/Bytecode/invalid/invalid-dense-elem-type-interface.mlir b/mlir/test/Bytecode/invalid/invalid-dense-elem-type-interface.mlir
new file mode 100644
index 0000000000000..f076dcb9b2f1f
--- /dev/null
+++ b/mlir/test/Bytecode/invalid/invalid-dense-elem-type-interface.mlir
@@ -0,0 +1,15 @@
+// RUN: not mlir-opt %s --test-bytecode-roundtrip="test-kind=2" 2>&1 | FileCheck %s
+
+// Regression test: test-kind=2 replaces i32 with !test.i32 (a type that does
+// not implement DenseElementTypeInterface). This should produce a proper error
+// instead of an assertion failure when deserializing DenseTypedElementsAttr.
+
+// CHECK: DenseTypedElementsAttr element type must implement DenseElementTypeInterface, but got: '!test.i32'
+// CHECK: failed to read bytecode
+
+module {
+  func.func @test() -> tensor<10xi32> {
+    %0 = arith.constant dense<42> : tensor<10xi32>
+    return %0 : tensor<10xi32>
+  }
+}
diff --git a/mlir/test/Bytecode/invalid/invalid-type-remapping.mlir b/mlir/test/Bytecode/invalid/invalid-type-remapping.mlir
deleted file mode 100644
index 44d0a4eb8bb4a..0000000000000
--- a/mlir/test/Bytecode/invalid/invalid-type-remapping.mlir
+++ /dev/null
@@ -1,55 +0,0 @@
-// RUN: not mlir-opt %s -split-input-file --test-bytecode-roundtrip="test-kind=2" 2>&1 | FileCheck %s
-
-// Tests that proper errors are emitted (rather than crashes) when the type
-// callback replaces types with ones that are incompatible with built-in types
-// and attributes (test-kind=2 replaces i32 with !test.i32).
-
-// CHECK: expected integer or index type for IntegerAttr, but got: '!test.i32'
-// CHECK: failed to read bytecode
-// IntegerAttr whose type is replaced by one that is neither IntegerType nor
-// IndexType — previously crashed with an APInt assertion.
-module {
-  func.func @integer_attr_unsupported_type() {
-    %c = arith.constant 1 : i32
-    return
-  }
-}
-
-// -----
-
-// CHECK: failed to verify 'elementType': VectorElementTypeInterface instance
-// CHECK: failed to read bytecode
-// Fixed-size VectorType whose element type is replaced by one that does not
-// implement VectorElementTypeInterface — previously crashed in VectorType::get.
-module {
-  func.func @vector_unsupported_elem_type() {
-    %cst = arith.constant dense<42> : vector<3xi32>
-    return
-  }
-}
-
-// -----
-
-// CHECK: failed to verify 'elementType': VectorElementTypeInterface instance
-// CHECK: failed to read bytecode
-// Scalable VectorType whose element type is replaced by one that does not
-// implement VectorElementTypeInterface — exercises the VectorTypeWithScalableDims
-// bytecode path.
-module {
-  func.func @scalable_vector_unsupported_elem_type(%v : vector<[3]xi32>) {
-    return
-  }
-}
-
-// -----
-
-// CHECK: DenseTypedElementsAttr element type must implement DenseElementTypeInterface, but got: '!test.i32'
-// CHECK: failed to read bytecode
-// DenseTypedElementsAttr whose element type is replaced by one that does not
-// implement DenseElementTypeInterface — previously crashed with an assertion.
-module {
-  func.func @dense_elem_unsupported_type() -> tensor<10xi32> {
-    %0 = arith.constant dense<42> : tensor<10xi32>
-    return %0 : tensor<10xi32>
-  }
-}

>From 557ad3cacd7555022c2a555f096b01063e36d40d Mon Sep 17 00:00:00 2001
From: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Date: Sat, 11 Apr 2026 08:51:39 -0500
Subject: [PATCH 2/2] Fix WRITE after ENDFILE abort

---
 flang-rt/include/flang-rt/runtime/io-error.h |  4 +++
 flang-rt/lib/runtime/unit.cpp                |  2 +-
 flang/test/Runtime/write-after-endfile.f90   | 29 ++++++++++++++++++++
 3 files changed, 34 insertions(+), 1 deletion(-)
 create mode 100644 flang/test/Runtime/write-after-endfile.f90

diff --git a/flang-rt/include/flang-rt/runtime/io-error.h b/flang-rt/include/flang-rt/runtime/io-error.h
index d2180a83f8c3c..4691a0ff5b8cd 100644
--- a/flang-rt/include/flang-rt/runtime/io-error.h
+++ b/flang-rt/include/flang-rt/runtime/io-error.h
@@ -34,6 +34,10 @@ class IoErrorHandler : public Terminator {
   RT_API_ATTRS void HasEorLabel() { flags_ |= hasEor; }
   RT_API_ATTRS void HasIoMsg() { flags_ |= hasIoMsg; }
   RT_API_ATTRS void HasRec() { flags_ |= hasRec; }
+  RT_API_ATTRS void SignalPendingIoStat(int iostat) {
+  if (ioStat_ == IostatOk || ioStat_ == IostatEnd || ioStat_ == IostatEor)
+    ioStat_ = iostat;
+}
 
   RT_API_ATTRS bool InError() const {
     return ioStat_ != IostatOk || pendingError_ != IostatOk;
diff --git a/flang-rt/lib/runtime/unit.cpp b/flang-rt/lib/runtime/unit.cpp
index c577ae7673127..32a48cd4fe3ef 100644
--- a/flang-rt/lib/runtime/unit.cpp
+++ b/flang-rt/lib/runtime/unit.cpp
@@ -84,7 +84,7 @@ bool ExternalFileUnit::Emit(const char *data, std::size_t bytes,
     beganReadingRecord_ = false;
   }
   if (IsAfterEndfile()) {
-    handler.SignalError(IostatWriteAfterEndfile);
+     handler.SignalPendingIoStat(IostatWriteAfterEndfile);
     return false;
   }
   CheckDirectAccess(handler);
diff --git a/flang/test/Runtime/write-after-endfile.f90 b/flang/test/Runtime/write-after-endfile.f90
new file mode 100644
index 0000000000000..c519bb4b649a0
--- /dev/null
+++ b/flang/test/Runtime/write-after-endfile.f90
@@ -0,0 +1,29 @@
+! RUN: %flang %s -o %t && %t | FileCheck %s
+! CHECK: k= {{ *}}2
+
+
+program test_write_after_endfile
+  implicit none
+  integer :: n, k
+
+  open(10, status='scratch')
+
+  write(10,*) 123
+  endfile(10)
+
+  ! This should NOT crash; should go to ERR label
+  write(10, err=100, iostat=n) 456
+  k = 1
+  goto 200
+
+100 continue
+  k = 2
+
+200 continue
+  print *, "k=", k
+end program
+
+
+
+
+



More information about the Mlir-commits mailing list