-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang][runtime] Don't use -1 in I/O API for "default unit" #76642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-flang-runtime @llvm/pr-subscribers-flang-fir-hlfir Author: Peter Klausler (klausler) ChangesThe I/O runtime's API allows -1 to be passed for a unit number in a READ, WRITE, or PRINT statement, where it gets replaced by 5 or 6 as appropriate. This turns out to have been a bad idea, as it prevents the I/O runtime from detecting and reporting a program's invalid attempt to use -1 as an I/O unit number. So just pass 5 or 6 as appropriate. Patch is 37.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/76642.diff 17 Files Affected:
diff --git a/flang/include/flang/Runtime/io-api.h b/flang/include/flang/Runtime/io-api.h
index 41574e3bb80ad3..c6cb60a4046d98 100644
--- a/flang/include/flang/Runtime/io-api.h
+++ b/flang/include/flang/Runtime/io-api.h
@@ -14,6 +14,7 @@
#include "flang/Common/uint128.h"
#include "flang/Runtime/entry-names.h"
#include "flang/Runtime/iostat.h"
+#include "flang/Runtime/magic-numbers.h"
#include <cinttypes>
#include <cstddef>
@@ -29,7 +30,9 @@ class IoStatementState;
using Cookie = IoStatementState *;
using ExternalUnit = int;
using AsynchronousId = int;
-static constexpr ExternalUnit DefaultUnit{-1}; // READ(*), WRITE(*), PRINT
+
+static constexpr ExternalUnit DefaultOutputUnit{FORTRAN_DEFAULT_OUTPUT_UNIT};
+static constexpr ExternalUnit DefaultInputUnit{FORTRAN_DEFAULT_INPUT_UNIT};
// INQUIRE specifiers are encoded as simple base-26 packings of
// the spellings of their keywords.
@@ -57,7 +60,8 @@ extern "C" {
// These functions initiate data transfer statements (READ, WRITE, PRINT).
// Example: PRINT *, 666 is implemented as the series of calls:
-// Cookie cookie{BeginExternalListOutput(DefaultUnit,__FILE__,__LINE__)};
+// Cookie cookie{BeginExternalListOutput(DefaultOutputUnit,
+// __FILE__, __LINE__)};
// OutputInteger32(cookie, 666);
// EndIoStatement(cookie);
// Formatted I/O with explicit formats can supply the format as a
@@ -135,19 +139,21 @@ enum Iostat IONAME(CheckUnitNumberInRange128)(common::int128_t unit,
const char *sourceFile = nullptr, int sourceLine = 0);
// External synchronous I/O initiation
-Cookie IONAME(BeginExternalListOutput)(ExternalUnit = DefaultUnit,
+Cookie IONAME(BeginExternalListOutput)(ExternalUnit = DefaultOutputUnit,
const char *sourceFile = nullptr, int sourceLine = 0);
-Cookie IONAME(BeginExternalListInput)(ExternalUnit = DefaultUnit,
+Cookie IONAME(BeginExternalListInput)(ExternalUnit = DefaultInputUnit,
const char *sourceFile = nullptr, int sourceLine = 0);
Cookie IONAME(BeginExternalFormattedOutput)(const char *format, std::size_t,
- const Descriptor *formatDescriptor = nullptr, ExternalUnit = DefaultUnit,
- const char *sourceFile = nullptr, int sourceLine = 0);
+ const Descriptor *formatDescriptor = nullptr,
+ ExternalUnit = DefaultOutputUnit, const char *sourceFile = nullptr,
+ int sourceLine = 0);
Cookie IONAME(BeginExternalFormattedInput)(const char *format, std::size_t,
- const Descriptor *formatDescriptor = nullptr, ExternalUnit = DefaultUnit,
- const char *sourceFile = nullptr, int sourceLine = 0);
-Cookie IONAME(BeginUnformattedOutput)(ExternalUnit = DefaultUnit,
+ const Descriptor *formatDescriptor = nullptr,
+ ExternalUnit = DefaultInputUnit, const char *sourceFile = nullptr,
+ int sourceLine = 0);
+Cookie IONAME(BeginUnformattedOutput)(ExternalUnit = DefaultOutputUnit,
const char *sourceFile = nullptr, int sourceLine = 0);
-Cookie IONAME(BeginUnformattedInput)(ExternalUnit = DefaultUnit,
+Cookie IONAME(BeginUnformattedInput)(ExternalUnit = DefaultInputUnit,
const char *sourceFile = nullptr, int sourceLine = 0);
// WAIT(ID=)
@@ -190,7 +196,7 @@ Cookie IONAME(BeginInquireIoLength)(
// This call makes the runtime library defer those particular error/end
// conditions to the EndIoStatement() call rather than terminating
// the image. E.g., for READ(*,*,END=666) A, B, (C(J),J=1,N)
-// Cookie cookie{BeginExternalListInput(DefaultUnit,__FILE__,__LINE__)};
+// Cookie cookie{BeginExternalListInput(DefaultOutputUnit,__FILE__,__LINE__)};
// EnableHandlers(cookie, false, false, true /*END=*/, false);
// if (InputReal64(cookie, &A)) {
// if (InputReal64(cookie, &B)) {
diff --git a/flang/include/flang/Runtime/magic-numbers.h b/flang/include/flang/Runtime/magic-numbers.h
index d00d5027d4ed27..196b13ad3755b3 100644
--- a/flang/include/flang/Runtime/magic-numbers.h
+++ b/flang/include/flang/Runtime/magic-numbers.h
@@ -27,6 +27,10 @@ start at 100 so as to never conflict with those codes.
#ifndef FORTRAN_RUNTIME_MAGIC_NUMBERS_H_
#define FORTRAN_RUNTIME_MAGIC_NUMBERS_H_
+#define FORTRAN_DEFAULT_OUTPUT_UNIT 6
+#define FORTRAN_DEFAULT_INPUT_UNIT 5
+#define FORTRAN_ERROR_UNIT 0
+
#define FORTRAN_RUNTIME_IOSTAT_END (-1)
#define FORTRAN_RUNTIME_IOSTAT_EOR (-2)
#define FORTRAN_RUNTIME_IOSTAT_FLUSH (-3)
diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index a60ca92a8733e3..3933ebeb9b3cc7 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -1850,24 +1850,25 @@ static mlir::Value genIOUnit(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
const Fortran::parser::IoUnit *iounit,
mlir::Type ty, ConditionSpecInfo &csi,
- Fortran::lower::StatementContext &stmtCtx) {
+ Fortran::lower::StatementContext &stmtCtx,
+ int defaultUnitNumber) {
auto &builder = converter.getFirOpBuilder();
if (iounit)
if (auto *e = std::get_if<Fortran::parser::FileUnitNumber>(&iounit->u))
return genIOUnitNumber(converter, loc, Fortran::semantics::GetExpr(*e),
ty, csi, stmtCtx);
return builder.create<mlir::arith::ConstantOp>(
- loc, builder.getIntegerAttr(ty, Fortran::runtime::io::DefaultUnit));
+ loc, builder.getIntegerAttr(ty, defaultUnitNumber));
}
template <typename A>
-static mlir::Value getIOUnit(Fortran::lower::AbstractConverter &converter,
- mlir::Location loc, const A &stmt, mlir::Type ty,
- ConditionSpecInfo &csi,
- Fortran::lower::StatementContext &stmtCtx) {
+static mlir::Value
+getIOUnit(Fortran::lower::AbstractConverter &converter, mlir::Location loc,
+ const A &stmt, mlir::Type ty, ConditionSpecInfo &csi,
+ Fortran::lower::StatementContext &stmtCtx, int defaultUnitNumber) {
const Fortran::parser::IoUnit *iounit =
stmt.iounit ? &*stmt.iounit : getIOControl<Fortran::parser::IoUnit>(stmt);
- return genIOUnit(converter, loc, iounit, ty, csi, stmtCtx);
+ return genIOUnit(converter, loc, iounit, ty, csi, stmtCtx, defaultUnitNumber);
}
//===----------------------------------------------------------------------===//
// Generators for each IO statement type.
@@ -2091,7 +2092,7 @@ getBeginDataTransferFunc(mlir::Location loc, fir::FirOpBuilder &builder,
}
/// Generate the arguments of a begin data transfer statement call.
-template <bool hasIOCtrl, typename A>
+template <bool hasIOCtrl, int defaultUnitNumber, typename A>
void genBeginDataTransferCallArgs(
llvm::SmallVectorImpl<mlir::Value> &ioArgs,
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
@@ -2149,14 +2150,14 @@ void genBeginDataTransferCallArgs(
TODO(loc, "asynchronous");
maybeGetFormatArgs();
ioArgs.push_back(getIOUnit(converter, loc, stmt,
- ioFuncTy.getInput(ioArgs.size()), csi,
- stmtCtx));
+ ioFuncTy.getInput(ioArgs.size()), csi, stmtCtx,
+ defaultUnitNumber));
}
} else { // PRINT - maybe explicit format; default unit
maybeGetFormatArgs();
ioArgs.push_back(builder.create<mlir::arith::ConstantOp>(
loc, builder.getIntegerAttr(ioFuncTy.getInput(ioArgs.size()),
- Fortran::runtime::io::DefaultUnit)));
+ defaultUnitNumber)));
}
// File name and line number are always the last two arguments.
ioArgs.push_back(
@@ -2193,7 +2194,9 @@ genDataTransferStmt(Fortran::lower::AbstractConverter &converter,
loc, builder, isFormatted, isList || isNml, isInternal,
isInternalWithDesc, isAsync);
llvm::SmallVector<mlir::Value> ioArgs;
- genBeginDataTransferCallArgs<hasIOCtrl>(
+ genBeginDataTransferCallArgs<
+ hasIOCtrl, isInput ? Fortran::runtime::io::DefaultInputUnit
+ : Fortran::runtime::io::DefaultOutputUnit>(
ioArgs, converter, loc, stmt, ioFunc.getFunctionType(), isFormatted,
isList || isNml, isInternal, isAsync, descRef, csi, stmtCtx);
mlir::Value cookie =
diff --git a/flang/module/iso_fortran_env.f90 b/flang/module/iso_fortran_env.f90
index 61d8a07e611338..6ee153592e1c6f 100644
--- a/flang/module/iso_fortran_env.f90
+++ b/flang/module/iso_fortran_env.f90
@@ -9,7 +9,7 @@
! See Fortran 2018, clause 16.10.2
! TODO: These are placeholder values so that some tests can be run.
-include '../include/flang/Runtime/magic-numbers.h' ! IOSTAT values
+include '../include/flang/Runtime/magic-numbers.h'
module iso_fortran_env
@@ -130,8 +130,9 @@ module iso_fortran_env
integer, parameter :: current_team = -1, initial_team = -2, parent_team = -3
- integer, parameter :: input_unit = 5, output_unit = 6
- integer, parameter :: error_unit = 0
+ integer, parameter :: output_unit = FORTRAN_DEFAULT_OUTPUT_UNIT
+ integer, parameter :: input_unit = FORTRAN_DEFAULT_INPUT_UNIT
+ integer, parameter :: error_unit = FORTRAN_ERROR_UNIT
integer, parameter :: iostat_end = FORTRAN_RUNTIME_IOSTAT_END
integer, parameter :: iostat_eor = FORTRAN_RUNTIME_IOSTAT_EOR
integer, parameter :: iostat_inquire_internal_unit = &
diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index 9a69a262464123..79d43c7cc884fc 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -185,9 +185,6 @@ template <Direction DIR, template <Direction> class STATE, typename... A>
Cookie BeginExternalListIO(
int unitNumber, const char *sourceFile, int sourceLine, A &&...xs) {
Terminator terminator{sourceFile, sourceLine};
- if (unitNumber == DefaultUnit) {
- unitNumber = DIR == Direction::Input ? 5 : 6;
- }
Cookie errorCookie{nullptr};
ExternalFileUnit *unit{GetOrCreateUnit(
unitNumber, DIR, false /*!unformatted*/, terminator, errorCookie)};
@@ -246,9 +243,6 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
const Descriptor *formatDescriptor, ExternalUnit unitNumber,
const char *sourceFile, int sourceLine) {
Terminator terminator{sourceFile, sourceLine};
- if (unitNumber == DefaultUnit) {
- unitNumber = DIR == Direction::Input ? 5 : 6;
- }
Cookie errorCookie{nullptr};
ExternalFileUnit *unit{GetOrCreateUnit(
unitNumber, DIR, false /*!unformatted*/, terminator, errorCookie)};
@@ -761,7 +755,8 @@ bool IONAME(SetAccess)(Cookie cookie, const char *keyword, std::size_t length) {
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetAccess() called when not in an OPEN statement");
}
@@ -796,7 +791,8 @@ bool IONAME(SetAction)(Cookie cookie, const char *keyword, std::size_t length) {
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetAction() called when not in an OPEN statement");
}
@@ -852,7 +848,8 @@ bool IONAME(SetAsynchronous)(
handler.SignalError(IostatBadAsynchronous);
}
}
- } else if (!io.get_if<ErroneousIoStatementState>()) {
+ } else if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
handler.Crash("SetAsynchronous() called when not in an OPEN or external "
"I/O statement");
}
@@ -864,7 +861,8 @@ bool IONAME(SetCarriagecontrol)(
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetCarriageControl() called when not in an OPEN statement");
}
@@ -895,7 +893,8 @@ bool IONAME(SetConvert)(
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetConvert() called when not in an OPEN statement");
}
@@ -919,7 +918,8 @@ bool IONAME(SetEncoding)(
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetEncoding() called when not in an OPEN statement");
}
@@ -949,7 +949,8 @@ bool IONAME(SetForm)(Cookie cookie, const char *keyword, std::size_t length) {
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetForm() called when not in an OPEN statement");
}
@@ -977,7 +978,8 @@ bool IONAME(SetPosition)(
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetPosition() called when not in an OPEN statement");
}
@@ -1008,7 +1010,8 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) {
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetRecl() called when not in an OPEN statement");
}
@@ -1093,7 +1096,8 @@ bool IONAME(SetFile)(Cookie cookie, const char *path, std::size_t chars) {
}
open->set_path(path, chars);
return true;
- } else if (!io.get_if<ErroneousIoStatementState>()) {
+ } else if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"SetFile() called when not in an OPEN statement");
}
@@ -1104,7 +1108,8 @@ bool IONAME(GetNewUnit)(Cookie cookie, int &unit, int kind) {
IoStatementState &io{*cookie};
auto *open{io.get_if<OpenStatementState>()};
if (!open) {
- if (!io.get_if<ErroneousIoStatementState>()) {
+ if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
io.GetIoErrorHandler().Crash(
"GetNewUnit() called when not in an OPEN statement");
}
@@ -1361,7 +1366,8 @@ std::size_t IONAME(GetSize)(Cookie cookie) {
if (const auto *formatted{
io.get_if<FormattedIoStatementState<Direction::Input>>()}) {
return formatted->GetEditDescriptorChars();
- } else if (!io.get_if<ErroneousIoStatementState>()) {
+ } else if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
handler.Crash("GetIoSize() called for an I/O statement that is not a "
"formatted READ()");
}
@@ -1376,7 +1382,8 @@ std::size_t IONAME(GetIoLength)(Cookie cookie) {
}
if (const auto *inq{io.get_if<InquireIOLengthState>()}) {
return inq->bytes();
- } else if (!io.get_if<ErroneousIoStatementState>()) {
+ } else if (!io.get_if<NoopStatementState>() &&
+ !io.get_if<ErroneousIoStatementState>()) {
handler.Crash("GetIoLength() called for an I/O statement that is not "
"INQUIRE(IOLENGTH=)");
}
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index e4f346ae941f3b..18590567c65eb0 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -11,6 +11,7 @@
#include "lock.h"
#include "tools.h"
#include "unit-map.h"
+#include "flang/Runtime/magic-numbers.h"
#include <cstdio>
#include <limits>
#include <utility>
@@ -220,21 +221,24 @@ UnitMap &ExternalFileUnit::CreateUnitMap() {
UnitMap &newUnitMap{*New<UnitMap>{terminator}().release()};
bool wasExtant{false};
- ExternalFileUnit &out{*newUnitMap.LookUpOrCreate(6, terminator, wasExtant)};
+ ExternalFileUnit &out{*newUnitMap.LookUpOrCreate(
+ FORTRAN_DEFAULT_OUTPUT_UNIT, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
out.Predefine(1);
handler.SignalError(out.SetDirection(Direction::Output));
out.isUnformatted = false;
defaultOutput = &out;
- ExternalFileUnit &in{*newUnitMap.LookUpOrCreate(5, terminator, wasExtant)};
+ ExternalFileUnit &in{*newUnitMap.LookUpOrCreate(
+ FORTRAN_DEFAULT_INPUT_UNIT, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
in.Predefine(0);
handler.SignalError(in.SetDirection(Direction::Input));
in.isUnformatted = false;
defaultInput = ∈
- ExternalFileUnit &error{*newUnitMap.LookUpOrCreate(0, terminator, wasExtant)};
+ ExternalFileUnit &error{
+ *newUnitMap.LookUpOrCreate(FORTRAN_ERROR_UNIT, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
error.Predefine(2);
handler.SignalError(error.SetDirection(Direction::Output));
diff --git a/flang/test/Lower/HLFIR/calls-f77.f90 b/flang/test/Lower/HLFIR/calls-f77.f90
index 09eebaae760600..ac5be007eb838c 100644
--- a/flang/test/Lower/HLFIR/calls-f77.f90
+++ b/flang/test/Lower/HLFIR/calls-f77.f90
@@ -156,7 +156,7 @@ subroutine return_char(n)
end subroutine
! CHECK-LABEL: func.func @_QPreturn_char(
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare {{.*}}n
-! CHECK: %[[VAL_2:.*]] = arith.constant -1 : i32
+! CHECK: %[[VAL_2:.*]] = arith.constant 6 : i32
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i64) -> index
! CHECK: %[[VAL_9:.*]] = arith.constant 0 : index
diff --git a/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 b/flang/test/Lower/HLFIR/convert-mbox-to-value.f90
index cb9dd2fa7956f2..b943cd3225a564 100644
--- a/flang/test/Lower/HLFIR/convert-mbox-to-value.f90
+++ b/flang/test/Lower/HLFIR/convert-mbox-to-value.f90
@@ -8,7 +8,7 @@ end subroutine test_int_allocatable
! CHECK-LABEL: func.func @_QPtest_int_allocatable(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>> {fir.bindc_name = "a"}) {
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_int_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>)
-! CHECK: %[[VAL_2:.*]] = arith.constant -1 : i32
+! CHECK: %[[VAL_2:.*]] = arith.constant 6 : i32
! CHECK: %[[VAL_3:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
! CHECK: %[[VAL_5:.*]] = arith.constant {{[0-9]*}} : i32
@@ -28,7 +28,7 @@ end subroutine test_int_pointer
! CHECK-LABEL: func.func @_QPtest_int_pointer(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "p"}) {
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_int_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
-! CHECK: %[[VAL_2:.*]] = arith.constant -1 : i32
+! CHECK: %[[VAL_2:.*]] = arith.constant 6 : i32
! CHECK: %[[VAL_3:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
! CHECK: %[[VAL_5:.*]] = arith.constant {{[0-9]*}} : i32
diff --git a/flang/tes...
[truncated]
|
flang/include/flang/Runtime/io-api.h
Outdated
@@ -190,7 +196,7 @@ Cookie IONAME(BeginInquireIoLength)( | |||
// This call makes the runtime library defer those particular error/end | |||
// conditions to the EndIoStatement() call rather than terminating | |||
// the image. E.g., for READ(*,*,END=666) A, B, (C(J),J=1,N) | |||
// Cookie cookie{BeginExternalListInput(DefaultUnit,__FILE__,__LINE__)}; | |||
// Cookie cookie{BeginExternalListInput(DefaultOutputUnit,__FILE__,__LINE__)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean DefaultInputUnit
in this comment?
The I/O runtime's API allows -1 to be passed for a unit number in a READ, WRITE, or PRINT statement, where it gets replaced by 5 or 6 as appropriate. This turns out to have been a bad idea, as it prevents the I/O runtime from detecting and reporting a program's invalid attempt to use -1 as an I/O unit number. So just pass 5 or 6 as appropriate. Fixes llvm-test-suite/Fortran/gfortran/regression/open_negative_unit_1.f90.
The I/O runtime's API allows -1 to be passed for a unit number in a READ, WRITE, or PRINT statement, where it gets replaced by 5 or 6 as appropriate. This turns out to have been a bad idea, as it prevents the I/O runtime from detecting and reporting a program's invalid attempt to use -1 as an I/O unit number. So just pass 5 or 6 as appropriate.