[libc++][Android] Allow testing libc++ with clang-r536225 (#116149)
[llvm-project.git] / flang / runtime / io-api-common.h
blobc7b86cab73a5256754bd507df4b158d64c389110
1 //===-- runtime/io-api-common.h ---------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef FLANG_RUNTIME_IO_API_COMMON_H_
10 #define FLANG_RUNTIME_IO_API_COMMON_H_
12 #include "io-stmt.h"
13 #include "terminator.h"
14 #include "unit.h"
15 #include "flang/Common/api-attrs.h"
16 #include "flang/Common/optional.h"
17 #include "flang/Runtime/io-api.h"
19 namespace Fortran::runtime::io {
21 static inline RT_API_ATTRS Cookie NoopUnit(const Terminator &terminator,
22 int unitNumber, enum Iostat iostat = IostatOk) {
23 Cookie cookie{&New<NoopStatementState>{terminator}(
24 terminator.sourceFileName(), terminator.sourceLine(), unitNumber)
25 .release()
26 ->ioStatementState()};
27 if (iostat != IostatOk) {
28 cookie->GetIoErrorHandler().SetPendingError(iostat);
30 return cookie;
33 static inline RT_API_ATTRS ExternalFileUnit *GetOrCreateUnit(int unitNumber,
34 Direction direction, Fortran::common::optional<bool> isUnformatted,
35 const Terminator &terminator, Cookie &errorCookie) {
36 IoErrorHandler handler{terminator};
37 handler.HasIoStat();
38 if (ExternalFileUnit *
39 unit{ExternalFileUnit::LookUpOrCreateAnonymous(
40 unitNumber, direction, isUnformatted, handler)}) {
41 errorCookie = nullptr;
42 return unit;
43 } else {
44 auto iostat{static_cast<enum Iostat>(handler.GetIoStat())};
45 errorCookie = NoopUnit(terminator, unitNumber,
46 iostat != IostatOk ? iostat : IostatBadUnitNumber);
47 return nullptr;
51 template <Direction DIR, template <Direction> class STATE, typename... A>
52 RT_API_ATTRS Cookie BeginExternalListIO(
53 int unitNumber, const char *sourceFile, int sourceLine, A &&...xs) {
54 Terminator terminator{sourceFile, sourceLine};
55 Cookie errorCookie{nullptr};
56 ExternalFileUnit *unit{GetOrCreateUnit(
57 unitNumber, DIR, false /*!unformatted*/, terminator, errorCookie)};
58 if (!unit) {
59 return errorCookie;
61 if (!unit->isUnformatted.has_value()) {
62 unit->isUnformatted = false;
64 Iostat iostat{IostatOk};
65 if (*unit->isUnformatted) {
66 iostat = IostatFormattedIoOnUnformattedUnit;
68 if (ChildIo * child{unit->GetChildIo()}) {
69 if (iostat == IostatOk) {
70 iostat = child->CheckFormattingAndDirection(false, DIR);
72 if (iostat == IostatOk) {
73 return &child->BeginIoStatement<ChildListIoStatementState<DIR>>(
74 *child, sourceFile, sourceLine);
75 } else {
76 return &child->BeginIoStatement<ErroneousIoStatementState>(
77 iostat, nullptr /* no unit */, sourceFile, sourceLine);
79 } else {
80 if (iostat == IostatOk && unit->access == Access::Direct) {
81 iostat = IostatListIoOnDirectAccessUnit;
83 if (iostat == IostatOk) {
84 iostat = unit->SetDirection(DIR);
86 if (iostat == IostatOk) {
87 return &unit->BeginIoStatement<STATE<DIR>>(
88 terminator, std::forward<A>(xs)..., *unit, sourceFile, sourceLine);
89 } else {
90 return &unit->BeginIoStatement<ErroneousIoStatementState>(
91 terminator, iostat, unit, sourceFile, sourceLine);
96 } // namespace Fortran::runtime::io
97 #endif // FLANG_RUNTIME_IO_API_COMMON_H_