diff --git a/flang/include/flang/Common/optional.h b/flang/include/flang/Common/optional.h new file mode 100644 index 000000000000..b5623b84dbd3 --- /dev/null +++ b/flang/include/flang/Common/optional.h @@ -0,0 +1,243 @@ +//===-- include/flang/Common/optional.h -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implementation of std::optional borrowed from LLVM's +// libc/src/__support/CPP/optional.h with modifications (e.g. value_or, emplace +// methods were added). +// +// The implementation defines optional in Fortran::common namespace. +// This standalone implementation may be used if the target +// does not support std::optional implementation (e.g. CUDA device env), +// otherwise, Fortran::common::optional is an alias for std::optional. +// +// TODO: using libcu++ is the best option for CUDA, but there is a couple +// of issues: +// * Older CUDA toolkits' libcu++ implementations do not support optional. +// * The include paths need to be set up such that all STD header files +// are taken from libcu++. +// * cuda:: namespace need to be forced for all std:: references. +// +//===----------------------------------------------------------------------===// +#ifndef FORTRAN_COMMON_OPTIONAL_H +#define FORTRAN_COMMON_OPTIONAL_H + +#include "flang/Runtime/api-attrs.h" +#include +#include + +#if !defined(STD_OPTIONAL_UNSUPPORTED) && \ + (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define STD_OPTIONAL_UNSUPPORTED 1 +#endif + +#define FORTRAN_OPTIONAL_INLINE_WITH_ATTRS inline RT_API_ATTRS +#define FORTRAN_OPTIONAL_INLINE inline +#define FORTRAN_OPTIONAL_INLINE_VAR inline + +namespace Fortran::common { + +#if STD_OPTIONAL_UNSUPPORTED +// Trivial nullopt_t struct. +struct nullopt_t { + constexpr explicit nullopt_t() = default; +}; + +// nullopt that can be used and returned. +FORTRAN_OPTIONAL_INLINE_VAR constexpr nullopt_t nullopt{}; + +// This is very simple implementation of the std::optional class. It makes +// several assumptions that the underlying type is trivially constructible, +// copyable, or movable. +template class optional { + template ::value> + struct OptionalStorage { + union { + char empty; + U stored_value; + }; + + bool in_use = false; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS ~OptionalStorage() { reset(); } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr OptionalStorage() : empty() {} + + template + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr explicit OptionalStorage( + std::in_place_t, Args &&...args) + : stored_value(std::forward(args)...) {} + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr void reset() { + if (in_use) + stored_value.~U(); + in_use = false; + } + }; + + // The only difference is that this type U doesn't have a nontrivial + // destructor. + template struct OptionalStorage { + union { + char empty; + U stored_value; + }; + + bool in_use = false; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr OptionalStorage() : empty() {} + + template + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr explicit OptionalStorage( + std::in_place_t, Args &&...args) + : stored_value(std::forward(args)...) {} + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr void reset() { + in_use = false; + } + }; + + OptionalStorage storage; + +public: + // The default methods do not use RT_API_ATTRS, which causes + // warnings in CUDA compilation of form: + // __device__/__host__ annotation is ignored on a function .* that is + // explicitly defaulted on its first declaration + FORTRAN_OPTIONAL_INLINE constexpr optional() = default; + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional(nullopt_t) {} + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional(const T &t) + : storage(std::in_place, t) { + storage.in_use = true; + } + FORTRAN_OPTIONAL_INLINE constexpr optional(const optional &) = default; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional(T &&t) + : storage(std::in_place, std::move(t)) { + storage.in_use = true; + } + FORTRAN_OPTIONAL_INLINE constexpr optional(optional &&O) = default; + + template + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional( + std::in_place_t, ArgTypes &&...Args) + : storage(std::in_place, std::forward(Args)...) { + storage.in_use = true; + } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional &operator=(T &&t) { + storage.stored_value = std::move(t); + storage.in_use = true; + return *this; + } + + FORTRAN_OPTIONAL_INLINE constexpr optional &operator=(optional &&) = default; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional &operator=(const T &t) { + storage.stored_value = t; + storage.in_use = true; + return *this; + } + + FORTRAN_OPTIONAL_INLINE constexpr optional &operator=( + const optional &) = default; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr void reset() { storage.reset(); } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr const T &value() const & { + return storage.stored_value; + } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T &value() & { + return storage.stored_value; + } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr explicit operator bool() const { + return storage.in_use; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr bool has_value() const { + return storage.in_use; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr const T *operator->() const { + return &storage.stored_value; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T *operator->() { + return &storage.stored_value; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr const T &operator*() const & { + return storage.stored_value; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T &operator*() & { + return storage.stored_value; + } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T &&value() && { + return std::move(storage.stored_value); + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T &&operator*() && { + return std::move(storage.stored_value); + } + + template + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T value_or( + VT &&default_value) const & { + return storage.in_use ? storage.stored_value + : static_cast(std::forward(default_value)); + } + + template + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T value_or( + VT &&default_value) && { + return storage.in_use ? std::move(storage.stored_value) + : static_cast(std::forward(default_value)); + } + + template + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS + std::enable_if_t, T &> + emplace(ArgTypes &&...args) { + reset(); + new (reinterpret_cast(std::addressof(storage.stored_value))) + T(std::forward(args)...); + storage.in_use = true; + return value(); + } + + template && + !std::is_same_v, std::in_place_t> && + !std::is_same_v, optional> && + std::is_convertible_v), + bool> = true> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional(U &&value) { + new (reinterpret_cast(std::addressof(storage.stored_value))) + T(std::forward(value)); + storage.in_use = true; + } + + template && + !std::is_same_v, std::in_place_t> && + !std::is_same_v, optional> && + !std::is_convertible_v), + bool> = false> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS explicit constexpr optional(U &&value) { + new (reinterpret_cast(std::addressof(storage.stored_value))) + T(std::forward(value)); + storage.in_use = true; + } +}; +#else // !STD_OPTIONAL_UNSUPPORTED +using std::nullopt; +using std::nullopt_t; +using std::optional; +#endif // !STD_OPTIONAL_UNSUPPORTED + +} // namespace Fortran::common + +#endif // FORTRAN_COMMON_OPTIONAL_H diff --git a/flang/include/flang/Runtime/type-code.h b/flang/include/flang/Runtime/type-code.h index 3757840cfdef..f7419249c2ba 100644 --- a/flang/include/flang/Runtime/type-code.h +++ b/flang/include/flang/Runtime/type-code.h @@ -10,6 +10,7 @@ #define FORTRAN_RUNTIME_TYPE_CODE_H_ #include "flang/Common/Fortran.h" +#include "flang/Common/optional.h" #include "flang/ISO_Fortran_binding_wrapper.h" #include #include @@ -54,7 +55,7 @@ public: return IsValid() && !IsDerived(); } - RT_API_ATTRS std::optional> + RT_API_ATTRS Fortran::common::optional> GetCategoryAndKind() const; RT_API_ATTRS bool operator==(TypeCode that) const { diff --git a/flang/runtime/connection.h b/flang/runtime/connection.h index c9a7566f2098..c41970d47e7b 100644 --- a/flang/runtime/connection.h +++ b/flang/runtime/connection.h @@ -12,8 +12,8 @@ #define FORTRAN_RUNTIME_IO_CONNECTION_H_ #include "format.h" +#include "flang/Common/optional.h" #include -#include namespace Fortran::runtime::io { @@ -26,10 +26,10 @@ enum class Access { Sequential, Direct, Stream }; // established in an OPEN statement. struct ConnectionAttributes { Access access{Access::Sequential}; // ACCESS='SEQUENTIAL', 'DIRECT', 'STREAM' - std::optional isUnformatted; // FORM='UNFORMATTED' if true + Fortran::common::optional isUnformatted; // FORM='UNFORMATTED' if true bool isUTF8{false}; // ENCODING='UTF-8' unsigned char internalIoCharKind{0}; // 0->external, 1/2/4->internal - std::optional openRecl; // RECL= on OPEN + Fortran::common::optional openRecl; // RECL= on OPEN bool IsRecordFile() const { // Formatted stream files are viewed as having records, at least on input @@ -63,14 +63,14 @@ struct ConnectionState : public ConnectionAttributes { unterminatedRecord = false; } - std::optional EffectiveRecordLength() const { + Fortran::common::optional EffectiveRecordLength() const { // When an input record is longer than an explicit RECL= from OPEN // it is effectively truncated on input. return openRecl && recordLength && *openRecl < *recordLength ? openRecl : recordLength; } - std::optional recordLength; + Fortran::common::optional recordLength; std::int64_t currentRecordNumber{1}; // 1 is first @@ -86,11 +86,12 @@ struct ConnectionState : public ConnectionAttributes { std::int64_t furthestPositionInRecord{0}; // max(position+bytes) // Set at end of non-advancing I/O data transfer - std::optional leftTabLimit; // offset in current record + Fortran::common::optional + leftTabLimit; // offset in current record // currentRecordNumber value captured after ENDFILE/REWIND/BACKSPACE statement // or an end-of-file READ condition on a sequential access file - std::optional endfileRecordNumber; + Fortran::common::optional endfileRecordNumber; // Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP diff --git a/flang/runtime/descriptor-io.cpp b/flang/runtime/descriptor-io.cpp index 6041104773cc..7c7323b719ad 100644 --- a/flang/runtime/descriptor-io.cpp +++ b/flang/runtime/descriptor-io.cpp @@ -12,11 +12,12 @@ namespace Fortran::runtime::io::descr { // Defined formatted I/O (maybe) -std::optional DefinedFormattedIo(IoStatementState &io, +Fortran::common::optional DefinedFormattedIo(IoStatementState &io, const Descriptor &descriptor, const typeInfo::DerivedType &derived, const typeInfo::SpecialBinding &special, const SubscriptValue subscripts[]) { - std::optional peek{io.GetNextDataEdit(0 /*to peek at it*/)}; + Fortran::common::optional peek{ + io.GetNextDataEdit(0 /*to peek at it*/)}; if (peek && (peek->descriptor == DataEdit::DefinedDerivedType || peek->descriptor == DataEdit::ListDirected)) { @@ -55,7 +56,7 @@ std::optional DefinedFormattedIo(IoStatementState &io, int unit{external->unitNumber()}; int ioStat{IostatOk}; char ioMsg[100]; - std::optional startPos; + Fortran::common::optional startPos; if (edit.descriptor == DataEdit::DefinedDerivedType && special.which() == typeInfo::SpecialBinding::Which::ReadFormatted) { // DT is an edit descriptor so everything that the child @@ -96,7 +97,7 @@ std::optional DefinedFormattedIo(IoStatementState &io, // There's a defined I/O subroutine, but there's a FORMAT present and // it does not have a DT data edit descriptor, so apply default formatting // to the components of the derived type as usual. - return std::nullopt; + return Fortran::common::nullopt; } } diff --git a/flang/runtime/descriptor-io.h b/flang/runtime/descriptor-io.h index 394578796faa..b6b0fefcff87 100644 --- a/flang/runtime/descriptor-io.h +++ b/flang/runtime/descriptor-io.h @@ -21,6 +21,7 @@ #include "terminator.h" #include "type-info.h" #include "unit.h" +#include "flang/Common/optional.h" #include "flang/Common/uint128.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" @@ -321,9 +322,9 @@ static bool DefaultComponentwiseUnformattedIO(IoStatementState &io, return true; } -std::optional DefinedFormattedIo(IoStatementState &, const Descriptor &, - const typeInfo::DerivedType &, const typeInfo::SpecialBinding &, - const SubscriptValue[]); +Fortran::common::optional DefinedFormattedIo(IoStatementState &, + const Descriptor &, const typeInfo::DerivedType &, + const typeInfo::SpecialBinding &, const SubscriptValue[]); template static bool FormattedDerivedTypeIO(IoStatementState &io, @@ -334,7 +335,7 @@ static bool FormattedDerivedTypeIO(IoStatementState &io, RUNTIME_CHECK(handler, addendum != nullptr); const typeInfo::DerivedType *type{addendum->derivedType()}; RUNTIME_CHECK(handler, type != nullptr); - std::optional nonTbpSpecial; + Fortran::common::optional nonTbpSpecial; const typeInfo::SpecialBinding *special{nullptr}; if (table) { if (const auto *definedIo{table->Find(*type, @@ -365,7 +366,7 @@ static bool FormattedDerivedTypeIO(IoStatementState &io, std::size_t numElements{descriptor.Elements()}; for (std::size_t j{0}; j < numElements; ++j, descriptor.IncrementSubscripts(subscripts)) { - std::optional result; + Fortran::common::optional result; if (special) { result = DefinedFormattedIo(io, descriptor, *type, *special, subscripts); } @@ -406,7 +407,7 @@ static bool UnformattedDescriptorIO(IoStatementState &io, : typeInfo::SpecialBinding::Which::WriteUnformatted, definedIo->subroutine, definedIo->isDtvArgPolymorphic, false, false}; - if (std::optional wasDefined{ + if (Fortran::common::optional wasDefined{ DefinedUnformattedIo(io, descriptor, *type, special)}) { return *wasDefined; } diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp index 85cce2f1a166..f7cbbc21e595 100644 --- a/flang/runtime/edit-input.cpp +++ b/flang/runtime/edit-input.cpp @@ -9,6 +9,7 @@ #include "edit-input.h" #include "namelist.h" #include "utf.h" +#include "flang/Common/optional.h" #include "flang/Common/real.h" #include "flang/Common/uint128.h" #include @@ -54,9 +55,9 @@ template static bool EditBOZInput( IoStatementState &io, const DataEdit &edit, void *n, std::size_t bytes) { // Skip leading white space & zeroes - std::optional remaining{io.CueUpInput(edit)}; + Fortran::common::optional remaining{io.CueUpInput(edit)}; auto start{io.GetConnectionState().positionInRecord}; - std::optional next{io.NextInField(remaining, edit)}; + Fortran::common::optional next{io.NextInField(remaining, edit)}; if (next.value_or('?') == '0') { do { start = io.GetConnectionState().positionInRecord; @@ -156,7 +157,8 @@ static inline char32_t GetRadixPointChar(const DataEdit &edit) { // Prepares input from a field, and returns the sign, if any, else '\0'. static char ScanNumericPrefix(IoStatementState &io, const DataEdit &edit, - std::optional &next, std::optional &remaining) { + Fortran::common::optional &next, + Fortran::common::optional &remaining) { remaining = io.CueUpInput(edit); next = io.NextInField(remaining, edit); char sign{'\0'}; @@ -198,8 +200,8 @@ bool EditIntegerInput( edit.descriptor); return false; } - std::optional remaining; - std::optional next; + Fortran::common::optional remaining; + Fortran::common::optional next; char sign{ScanNumericPrefix(io, edit, next, remaining)}; common::UnsignedInt128 value{0}; bool any{!!sign}; @@ -279,10 +281,10 @@ struct ScannedRealInput { }; static ScannedRealInput ScanRealInput( char *buffer, int bufferSize, IoStatementState &io, const DataEdit &edit) { - std::optional remaining; - std::optional next; + Fortran::common::optional remaining; + Fortran::common::optional next; int got{0}; - std::optional radixPointOffset; + Fortran::common::optional radixPointOffset; auto Put{[&](char ch) -> void { if (got < bufferSize) { buffer[got] = ch; @@ -833,8 +835,8 @@ bool EditLogicalInput(IoStatementState &io, const DataEdit &edit, bool &x) { edit.descriptor); return false; } - std::optional remaining{io.CueUpInput(edit)}; - std::optional next{io.NextInField(remaining, edit)}; + Fortran::common::optional remaining{io.CueUpInput(edit)}; + Fortran::common::optional next{io.NextInField(remaining, edit)}; if (next && *next == '.') { // skip optional period next = io.NextInField(remaining, edit); } @@ -916,8 +918,9 @@ static bool EditListDirectedCharacterInput( // or the end of the current record. Subtlety: the "remaining" count // here is a dummy that's used to avoid the interpretation of separators // in NextInField. - std::optional remaining{length > 0 ? maxUTF8Bytes : 0}; - while (std::optional next{io.NextInField(remaining, edit)}) { + Fortran::common::optional remaining{length > 0 ? maxUTF8Bytes : 0}; + while (Fortran::common::optional next{ + io.NextInField(remaining, edit)}) { bool isSep{false}; switch (*next) { case ' ': diff --git a/flang/runtime/environment.cpp b/flang/runtime/environment.cpp index fe6701d72c9f..b74067a37777 100644 --- a/flang/runtime/environment.cpp +++ b/flang/runtime/environment.cpp @@ -49,7 +49,8 @@ static void SetEnvironmentDefaults(const EnvironmentDefaultList *envDefaults) { } } -std::optional GetConvertFromString(const char *x, std::size_t n) { +Fortran::common::optional GetConvertFromString( + const char *x, std::size_t n) { static const char *keywords[]{ "UNKNOWN", "NATIVE", "LITTLE_ENDIAN", "BIG_ENDIAN", "SWAP", nullptr}; switch (IdentifyValue(x, n, keywords)) { @@ -64,7 +65,7 @@ std::optional GetConvertFromString(const char *x, std::size_t n) { case 4: return Convert::Swap; default: - return std::nullopt; + return Fortran::common::nullopt; } } diff --git a/flang/runtime/environment.h b/flang/runtime/environment.h index 49c7dbd2940f..9bc115850961 100644 --- a/flang/runtime/environment.h +++ b/flang/runtime/environment.h @@ -9,9 +9,8 @@ #ifndef FORTRAN_RUNTIME_ENVIRONMENT_H_ #define FORTRAN_RUNTIME_ENVIRONMENT_H_ +#include "flang/Common/optional.h" #include "flang/Decimal/decimal.h" -#include "flang/Runtime/api-attrs.h" -#include struct EnvironmentDefaultList; @@ -30,7 +29,8 @@ constexpr bool isHostLittleEndian{true}; // External unformatted I/O data conversions enum class Convert { Unknown, Native, LittleEndian, BigEndian, Swap }; -std::optional GetConvertFromString(const char *, std::size_t); +Fortran::common::optional GetConvertFromString( + const char *, std::size_t); struct ExecutionEnvironment { #if !defined(_OPENMP) diff --git a/flang/runtime/extrema.cpp b/flang/runtime/extrema.cpp index 61afb0458430..d6e9633372f5 100644 --- a/flang/runtime/extrema.cpp +++ b/flang/runtime/extrema.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include namespace Fortran::runtime { diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp index 5cf91b8d64c8..6ca5776f812a 100644 --- a/flang/runtime/file.cpp +++ b/flang/runtime/file.cpp @@ -60,7 +60,7 @@ static int openfile_mkstemp(IoErrorHandler &handler) { return fd; } -void OpenFile::Open(OpenStatus status, std::optional action, +void OpenFile::Open(OpenStatus status, Fortran::common::optional action, Position position, IoErrorHandler &handler) { if (fd_ >= 0 && (status == OpenStatus::Old || status == OpenStatus::Unknown)) { @@ -322,7 +322,7 @@ int OpenFile::WriteAsynchronously(FileOffset at, const char *buffer, } void OpenFile::Wait(int id, IoErrorHandler &handler) { - std::optional ioStat; + Fortran::common::optional ioStat; Pending *prev{nullptr}; for (Pending *p{pending_.get()}; p; p = (prev = p)->next.get()) { if (p->id == id) { diff --git a/flang/runtime/file.h b/flang/runtime/file.h index a0712136a7f3..17deeb0e2f82 100644 --- a/flang/runtime/file.h +++ b/flang/runtime/file.h @@ -12,9 +12,9 @@ #define FORTRAN_RUNTIME_FILE_H_ #include "io-error.h" +#include "flang/Common/optional.h" #include "flang/Runtime/memory.h" #include -#include namespace Fortran::runtime::io { @@ -37,10 +37,11 @@ public: void set_mayAsynchronous(bool yes) { mayAsynchronous_ = yes; } bool isTerminal() const { return isTerminal_; } bool isWindowsTextFile() const { return isWindowsTextFile_; } - std::optional knownSize() const { return knownSize_; } + Fortran::common::optional knownSize() const { return knownSize_; } bool IsConnected() const { return fd_ >= 0; } - void Open(OpenStatus, std::optional, Position, IoErrorHandler &); + void Open(OpenStatus, Fortran::common::optional, Position, + IoErrorHandler &); void Predefine(int fd); void Close(CloseStatus, IoErrorHandler &); @@ -94,9 +95,10 @@ private: bool mayWrite_{false}; bool mayPosition_{false}; bool mayAsynchronous_{false}; - std::optional openPosition_; // from Open(); reset after positioning + Fortran::common::optional + openPosition_; // from Open(); reset after positioning FileOffset position_{0}; - std::optional knownSize_; + Fortran::common::optional knownSize_; bool isTerminal_{false}; bool isWindowsTextFile_{false}; // expands LF to CR+LF on write diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h index f554f740573f..b84e3208271b 100644 --- a/flang/runtime/format-implementation.h +++ b/flang/runtime/format-implementation.h @@ -233,7 +233,7 @@ int FormatControl::CueUpNextDataEdit(Context &context, bool stop) { } } while (true) { - std::optional repeat; + Fortran::common::optional repeat; bool unlimited{false}; auto maybeReversionPoint{offset_}; CharType ch{GetNextChar(context)}; @@ -419,7 +419,7 @@ int FormatControl::CueUpNextDataEdit(Context &context, bool stop) { // Returns the next data edit descriptor template -std::optional FormatControl::GetNextDataEdit( +Fortran::common::optional FormatControl::GetNextDataEdit( Context &context, int maxRepeat) { int repeat{CueUpNextDataEdit(context)}; auto start{offset_}; @@ -451,7 +451,7 @@ std::optional FormatControl::GetNextDataEdit( } if (edit.ioTypeChars >= edit.maxIoTypeChars) { ReportBadFormat(context, "Excessive DT'iotype' in FORMAT", start); - return std::nullopt; + return Fortran::common::nullopt; } edit.ioType[edit.ioTypeChars++] = ch; if (ch == quote) { @@ -460,7 +460,7 @@ std::optional FormatControl::GetNextDataEdit( } if (!ok) { ReportBadFormat(context, "Unclosed DT'iotype' in FORMAT", start); - return std::nullopt; + return Fortran::common::nullopt; } } if (PeekNext() == '(') { @@ -475,7 +475,7 @@ std::optional FormatControl::GetNextDataEdit( } if (edit.vListEntries >= edit.maxVListEntries) { ReportBadFormat(context, "Excessive DT(v_list) in FORMAT", start); - return std::nullopt; + return Fortran::common::nullopt; } edit.vList[edit.vListEntries++] = n; auto ch{static_cast(GetNextChar(context))}; @@ -486,7 +486,7 @@ std::optional FormatControl::GetNextDataEdit( } if (!ok) { ReportBadFormat(context, "Unclosed DT(v_list) in FORMAT", start); - return std::nullopt; + return Fortran::common::nullopt; } } } else { // not DT'iotype' diff --git a/flang/runtime/format.h b/flang/runtime/format.h index 1fe0802ac43c..e7d945599640 100644 --- a/flang/runtime/format.h +++ b/flang/runtime/format.h @@ -14,9 +14,9 @@ #include "environment.h" #include "io-error.h" #include "flang/Common/Fortran.h" +#include "flang/Common/optional.h" #include "flang/Decimal/decimal.h" #include -#include namespace Fortran::runtime { class Descriptor; @@ -64,9 +64,9 @@ struct DataEdit { static constexpr char DefinedDerivedType{'d'}; // DT defined I/O char variation{'\0'}; // N, S, or X for EN, ES, EX; G/l for original G/list - std::optional width; // the 'w' field; optional for A - std::optional digits; // the 'm' or 'd' field - std::optional expoDigits; // 'Ee' field + Fortran::common::optional width; // the 'w' field; optional for A + Fortran::common::optional digits; // the 'm' or 'd' field + Fortran::common::optional expoDigits; // 'Ee' field MutableModes modes; int repeat{1}; @@ -102,7 +102,8 @@ public: // Extracts the next data edit descriptor, handling control edit descriptors // along the way. If maxRepeat==0, this is a peek at the next data edit // descriptor. - std::optional GetNextDataEdit(Context &, int maxRepeat = 1); + Fortran::common::optional GetNextDataEdit( + Context &, int maxRepeat = 1); // Emit any remaining character literals after the last data item (on output) // and perform remaining record positioning actions. diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp index 0ac20d3346dd..094db5572f15 100644 --- a/flang/runtime/io-api.cpp +++ b/flang/runtime/io-api.cpp @@ -18,6 +18,7 @@ #include "terminator.h" #include "tools.h" #include "unit.h" +#include "flang/Common/optional.h" #include "flang/Runtime/descriptor.h" #include "flang/Runtime/memory.h" #include @@ -168,7 +169,7 @@ static Cookie NoopUnit(const Terminator &terminator, int unitNumber, } static ExternalFileUnit *GetOrCreateUnit(int unitNumber, Direction direction, - std::optional isUnformatted, const Terminator &terminator, + Fortran::common::optional isUnformatted, const Terminator &terminator, Cookie &errorCookie) { if (ExternalFileUnit * unit{ExternalFileUnit::LookUpOrCreateAnonymous( @@ -472,8 +473,8 @@ Cookie IONAME(BeginEndfile)( Terminator terminator{sourceFile, sourceLine}; Cookie errorCookie{nullptr}; if (ExternalFileUnit * - unit{GetOrCreateUnit(unitNumber, Direction::Output, std::nullopt, - terminator, errorCookie)}) { + unit{GetOrCreateUnit(unitNumber, Direction::Output, + Fortran::common::nullopt, terminator, errorCookie)}) { if (ChildIo * child{unit->GetChildIo()}) { return &child->BeginIoStatement( IostatBadOpOnChildUnit, nullptr /* no unit */, sourceFile, @@ -492,8 +493,8 @@ Cookie IONAME(BeginRewind)( Terminator terminator{sourceFile, sourceLine}; Cookie errorCookie{nullptr}; if (ExternalFileUnit * - unit{GetOrCreateUnit(unitNumber, Direction::Input, std::nullopt, - terminator, errorCookie)}) { + unit{GetOrCreateUnit(unitNumber, Direction::Input, + Fortran::common::nullopt, terminator, errorCookie)}) { if (ChildIo * child{unit->GetChildIo()}) { return &child->BeginIoStatement( IostatBadOpOnChildUnit, nullptr /* no unit */, sourceFile, @@ -801,7 +802,7 @@ bool IONAME(SetAction)(Cookie cookie, const char *keyword, std::size_t length) { io.GetIoErrorHandler().Crash( "SetAction() called after GetNewUnit() for an OPEN statement"); } - std::optional action; + Fortran::common::optional action; static const char *keywords[]{"READ", "WRITE", "READWRITE", nullptr}; switch (IdentifyValue(keyword, length, keywords)) { case 0: diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 153195fd9656..075d7b5ae518 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -39,9 +39,9 @@ bool IoStatementBase::Receive(char *, std::size_t, std::size_t) { return false; } -std::optional IoStatementBase::GetNextDataEdit( +Fortran::common::optional IoStatementBase::GetNextDataEdit( IoStatementState &, int) { - return std::nullopt; + return Fortran::common::nullopt; } ExternalFileUnit *IoStatementBase::GetExternalFileUnit() const { @@ -466,7 +466,7 @@ int ExternalFormattedIoStatementState::EndIoStatement() { return ExternalIoStatementState::EndIoStatement(); } -std::optional IoStatementState::GetNextDataEdit(int n) { +Fortran::common::optional IoStatementState::GetNextDataEdit(int n) { return common::visit( [&](auto &x) { return x.get().GetNextDataEdit(*this, n); }, u_); } @@ -541,13 +541,13 @@ ExternalFileUnit *IoStatementState::GetExternalFileUnit() const { [](auto &x) { return x.get().GetExternalFileUnit(); }, u_); } -std::optional IoStatementState::GetCurrentChar( +Fortran::common::optional IoStatementState::GetCurrentChar( std::size_t &byteCount) { const char *p{nullptr}; std::size_t bytes{GetNextInputBytes(p)}; if (bytes == 0) { byteCount = 0; - return std::nullopt; + return Fortran::common::nullopt; } else { const ConnectionState &connection{GetConnectionState()}; if (connection.isUTF8) { @@ -573,8 +573,8 @@ std::optional IoStatementState::GetCurrentChar( } } -std::optional IoStatementState::NextInField( - std::optional &remaining, const DataEdit &edit) { +Fortran::common::optional IoStatementState::NextInField( + Fortran::common::optional &remaining, const DataEdit &edit) { std::size_t byteCount{0}; if (!remaining) { // Stream, list-directed, or NAMELIST if (auto next{GetCurrentChar(byteCount)}) { @@ -590,21 +590,21 @@ std::optional IoStatementState::NextInField( case '"': case '*': case '\n': // for stream access - return std::nullopt; + return Fortran::common::nullopt; case '&': case '$': if (edit.IsNamelist()) { - return std::nullopt; + return Fortran::common::nullopt; } break; case ',': if (!(edit.modes.editingFlags & decimalComma)) { - return std::nullopt; + return Fortran::common::nullopt; } break; case ';': if (edit.modes.editingFlags & decimalComma) { - return std::nullopt; + return Fortran::common::nullopt; } break; default: @@ -618,7 +618,7 @@ std::optional IoStatementState::NextInField( } else if (*remaining > 0) { if (auto next{GetCurrentChar(byteCount)}) { if (byteCount > static_cast(*remaining)) { - return std::nullopt; + return Fortran::common::nullopt; } *remaining -= byteCount; HandleRelativePosition(byteCount); @@ -627,10 +627,10 @@ std::optional IoStatementState::NextInField( } if (CheckForEndOfRecord(0)) { // do padding --*remaining; - return std::optional{' '}; + return Fortran::common::optional{' '}; } } - return std::nullopt; + return Fortran::common::nullopt; } bool IoStatementState::CheckForEndOfRecord(std::size_t afterReading) { @@ -722,7 +722,7 @@ bool ListDirectedStatementState::EmitLeadingSpaceOrAdvance( return true; } -std::optional +Fortran::common::optional ListDirectedStatementState::GetNextDataEdit( IoStatementState &io, int maxRepeat) { DataEdit edit; @@ -739,7 +739,7 @@ int ListDirectedStatementState::EndIoStatement() { return IostatOk; } -std::optional +Fortran::common::optional ListDirectedStatementState::GetNextDataEdit( IoStatementState &io, int maxRepeat) { // N.B. list-directed transfers cannot be nonadvancing (C1221) @@ -795,7 +795,7 @@ ListDirectedStatementState::GetNextDataEdit( } eatComma_ = true; if (!ch) { - return std::nullopt; + return Fortran::common::nullopt; } if (*ch == '/') { hitSlash_ = true; diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index dcee7f936569..0477c32b3b53 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -16,6 +16,7 @@ #include "format.h" #include "internal-unit.h" #include "io-error.h" +#include "flang/Common/optional.h" #include "flang/Common/visit.h" #include "flang/Runtime/descriptor.h" #include "flang/Runtime/io-api.h" @@ -94,7 +95,7 @@ public: void BackspaceRecord(); void HandleRelativePosition(std::int64_t byteOffset); void HandleAbsolutePosition(std::int64_t byteOffset); // for r* in list I/O - std::optional GetNextDataEdit(int maxRepeat = 1); + Fortran::common::optional GetNextDataEdit(int maxRepeat = 1); ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit bool BeginReadingRecord(); void FinishReadingRecord(); @@ -122,7 +123,7 @@ public: } // Vacant after the end of the current record - std::optional GetCurrentChar(std::size_t &byteCount); + Fortran::common::optional GetCurrentChar(std::size_t &byteCount); // The "remaining" arguments to CueUpInput(), SkipSpaces(), & NextInField() // are always in units of bytes, not characters; the distinction matters @@ -130,8 +131,8 @@ public: // For fixed-width fields, return the number of remaining bytes. // Skip over leading blanks. - std::optional CueUpInput(const DataEdit &edit) { - std::optional remaining; + Fortran::common::optional CueUpInput(const DataEdit &edit) { + Fortran::common::optional remaining; if (edit.IsListDirected()) { std::size_t byteCount{0}; GetNextNonBlank(byteCount); @@ -148,7 +149,8 @@ public: return remaining; } - std::optional SkipSpaces(std::optional &remaining) { + Fortran::common::optional SkipSpaces( + Fortran::common::optional &remaining) { while (!remaining || *remaining > 0) { std::size_t byteCount{0}; if (auto ch{GetCurrentChar(byteCount)}) { @@ -167,27 +169,27 @@ public: break; } } - return std::nullopt; + return Fortran::common::nullopt; } // Acquires the next input character, respecting any applicable field width // or separator character. - std::optional NextInField( - std::optional &remaining, const DataEdit &); + Fortran::common::optional NextInField( + Fortran::common::optional &remaining, const DataEdit &); // Detect and signal any end-of-record condition after input. // Returns true if at EOR and remaining input should be padded with blanks. bool CheckForEndOfRecord(std::size_t afterReading); // Skips spaces, advances records, and ignores NAMELIST comments - std::optional GetNextNonBlank(std::size_t &byteCount) { + Fortran::common::optional GetNextNonBlank(std::size_t &byteCount) { auto ch{GetCurrentChar(byteCount)}; bool inNamelist{mutableModes().inNamelist}; while (!ch || *ch == ' ' || *ch == '\t' || (inNamelist && *ch == '!')) { if (ch && (*ch == ' ' || *ch == '\t')) { HandleRelativePosition(byteCount); } else if (!AdvanceRecord()) { - return std::nullopt; + return Fortran::common::nullopt; } ch = GetCurrentChar(byteCount); } @@ -262,7 +264,7 @@ public: void BackspaceRecord(); void HandleRelativePosition(std::int64_t); void HandleAbsolutePosition(std::int64_t); - std::optional GetNextDataEdit( + Fortran::common::optional GetNextDataEdit( IoStatementState &, int maxRepeat = 1); ExternalFileUnit *GetExternalFileUnit() const; bool BeginReadingRecord(); @@ -287,7 +289,7 @@ class ListDirectedStatementState public: bool EmitLeadingSpaceOrAdvance( IoStatementState &, std::size_t = 1, bool isCharacter = false); - std::optional GetNextDataEdit( + Fortran::common::optional GetNextDataEdit( IoStatementState &, int maxRepeat = 1); bool lastWasUndelimitedCharacter() const { return lastWasUndelimitedCharacter_; @@ -309,7 +311,7 @@ public: // Skips value separators, handles repetition and null values. // Vacant when '/' appears; present with descriptor == ListDirectedNullValue // when a null value appears. - std::optional GetNextDataEdit( + Fortran::common::optional GetNextDataEdit( IoStatementState &, int maxRepeat = 1); // Each NAMELIST input item is treated like a distinct list-directed @@ -328,7 +330,7 @@ public: private: int remaining_{0}; // for "r*" repetition - std::optional repeatPosition_; + Fortran::common::optional repeatPosition_; bool eatComma_{false}; // consume comma after previously read item bool hitSlash_{false}; // once '/' is seen, nullify further items bool realPart_{false}; @@ -380,7 +382,7 @@ public: IoStatementState &ioStatementState() { return ioStatementState_; } void CompleteOperation(); int EndIoStatement(); - std::optional GetNextDataEdit( + Fortran::common::optional GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -465,7 +467,7 @@ public: const char *sourceFile = nullptr, int sourceLine = 0); void CompleteOperation(); int EndIoStatement(); - std::optional GetNextDataEdit( + Fortran::common::optional GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -523,7 +525,7 @@ public: void CompleteOperation(); int EndIoStatement(); bool AdvanceRecord(int = 1); - std::optional GetNextDataEdit( + Fortran::common::optional GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -571,14 +573,14 @@ public: private: bool wasExtant_; bool isNewUnit_; - std::optional status_; - std::optional position_; - std::optional action_; + Fortran::common::optional status_; + Fortran::common::optional position_; + Fortran::common::optional action_; Convert convert_{Convert::Unknown}; OwningPtr path_; std::size_t pathLength_; - std::optional isUnformatted_; - std::optional access_; + Fortran::common::optional isUnformatted_; + Fortran::common::optional access_; }; class CloseStatementState : public ExternalIoStatementBase { diff --git a/flang/runtime/matmul-transpose.cpp b/flang/runtime/matmul-transpose.cpp index ee5fcd842b02..a12d188266f7 100644 --- a/flang/runtime/matmul-transpose.cpp +++ b/flang/runtime/matmul-transpose.cpp @@ -23,6 +23,7 @@ #include "flang/Runtime/matmul-transpose.h" #include "terminator.h" #include "tools.h" +#include "flang/Common/optional.h" #include "flang/Runtime/c-or-cpp.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" @@ -96,8 +97,8 @@ template inline static RT_API_ATTRS void MatrixTransposedTimesMatrixHelper( CppTypeFor *RESTRICT product, SubscriptValue rows, SubscriptValue cols, const XT *RESTRICT x, const YT *RESTRICT y, - SubscriptValue n, std::optional xColumnByteStride, - std::optional yColumnByteStride) { + SubscriptValue n, Fortran::common::optional xColumnByteStride, + Fortran::common::optional yColumnByteStride) { if (!xColumnByteStride) { if (!yColumnByteStride) { MatrixTransposedTimesMatrix( @@ -163,7 +164,7 @@ template inline static RT_API_ATTRS void MatrixTransposedTimesVectorHelper( CppTypeFor *RESTRICT product, SubscriptValue rows, SubscriptValue n, const XT *RESTRICT x, const YT *RESTRICT y, - std::optional xColumnByteStride) { + Fortran::common::optional xColumnByteStride) { if (!xColumnByteStride) { MatrixTransposedTimesVector( product, rows, n, x, y); @@ -229,7 +230,7 @@ inline static RT_API_ATTRS void DoMatmulTranspose( (IS_ALLOCATING || result.IsContiguous())) { // Contiguous numeric matrices (maybe with columns // separated by a stride). - std::optional xColumnByteStride; + Fortran::common::optional xColumnByteStride; if (!x.IsContiguous()) { // X's columns are strided. SubscriptValue xAt[2]{}; @@ -237,7 +238,7 @@ inline static RT_API_ATTRS void DoMatmulTranspose( xAt[1]++; xColumnByteStride = x.SubscriptsToByteOffset(xAt); } - std::optional yColumnByteStride; + Fortran::common::optional yColumnByteStride; if (!y.IsContiguous()) { // Y's columns are strided. SubscriptValue yAt[2]{}; diff --git a/flang/runtime/matmul.cpp b/flang/runtime/matmul.cpp index e4595db77926..543284cb5c36 100644 --- a/flang/runtime/matmul.cpp +++ b/flang/runtime/matmul.cpp @@ -22,6 +22,7 @@ #include "flang/Runtime/matmul.h" #include "terminator.h" #include "tools.h" +#include "flang/Common/optional.h" #include "flang/Runtime/c-or-cpp.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" @@ -116,8 +117,8 @@ template inline RT_API_ATTRS void MatrixTimesMatrixHelper( CppTypeFor *RESTRICT product, SubscriptValue rows, SubscriptValue cols, const XT *RESTRICT x, const YT *RESTRICT y, - SubscriptValue n, std::optional xColumnByteStride, - std::optional yColumnByteStride) { + SubscriptValue n, Fortran::common::optional xColumnByteStride, + Fortran::common::optional yColumnByteStride) { if (!xColumnByteStride) { if (!yColumnByteStride) { MatrixTimesMatrix( @@ -183,7 +184,7 @@ template inline RT_API_ATTRS void MatrixTimesVectorHelper( CppTypeFor *RESTRICT product, SubscriptValue rows, SubscriptValue n, const XT *RESTRICT x, const YT *RESTRICT y, - std::optional xColumnByteStride) { + Fortran::common::optional xColumnByteStride) { if (!xColumnByteStride) { MatrixTimesVector(product, rows, n, x, y); } else { @@ -240,7 +241,7 @@ template *RESTRICT product, SubscriptValue n, SubscriptValue cols, const XT *RESTRICT x, const YT *RESTRICT y, - std::optional yColumnByteStride) { + Fortran::common::optional yColumnByteStride) { if (!yColumnByteStride) { VectorTimesMatrix(product, n, cols, x, y); } else { @@ -301,7 +302,7 @@ static inline RT_API_ATTRS void DoMatmul( (IS_ALLOCATING || result.IsContiguous())) { // Contiguous numeric matrices (maybe with columns // separated by a stride). - std::optional xColumnByteStride; + Fortran::common::optional xColumnByteStride; if (!x.IsContiguous()) { // X's columns are strided. SubscriptValue xAt[2]{}; @@ -309,7 +310,7 @@ static inline RT_API_ATTRS void DoMatmul( xAt[1]++; xColumnByteStride = x.SubscriptsToByteOffset(xAt); } - std::optional yColumnByteStride; + Fortran::common::optional yColumnByteStride; if (!y.IsContiguous()) { // Y's columns are strided. SubscriptValue yAt[2]{}; diff --git a/flang/runtime/misc-intrinsic.cpp b/flang/runtime/misc-intrinsic.cpp index 56f2028c2ff0..f5b292a1f3d3 100644 --- a/flang/runtime/misc-intrinsic.cpp +++ b/flang/runtime/misc-intrinsic.cpp @@ -9,16 +9,16 @@ #include "flang/Runtime/misc-intrinsic.h" #include "terminator.h" #include "tools.h" +#include "flang/Common/optional.h" #include "flang/Runtime/descriptor.h" #include #include -#include namespace Fortran::runtime { static RT_API_ATTRS void TransferImpl(Descriptor &result, const Descriptor &source, const Descriptor &mold, const char *sourceFile, - int line, std::optional resultExtent) { + int line, Fortran::common::optional resultExtent) { int rank{resultExtent.has_value() ? 1 : 0}; std::size_t elementBytes{mold.ElementBytes()}; result.Establish(mold.type(), elementBytes, nullptr, rank, nullptr, @@ -57,7 +57,7 @@ RT_EXT_API_GROUP_BEGIN void RTDEF(Transfer)(Descriptor &result, const Descriptor &source, const Descriptor &mold, const char *sourceFile, int line) { - std::optional elements; + Fortran::common::optional elements; if (mold.rank() > 0) { if (std::size_t sourceElementBytes{ source.Elements() * source.ElementBytes()}) { diff --git a/flang/runtime/namelist.cpp b/flang/runtime/namelist.cpp index f5d7404fdcb8..ac9234f4af83 100644 --- a/flang/runtime/namelist.cpp +++ b/flang/runtime/namelist.cpp @@ -116,10 +116,11 @@ static bool GetLowerCaseName( return false; } -static std::optional GetSubscriptValue(IoStatementState &io) { - std::optional value; +static Fortran::common::optional GetSubscriptValue( + IoStatementState &io) { + Fortran::common::optional value; std::size_t byteCount{0}; - std::optional ch{io.GetCurrentChar(byteCount)}; + Fortran::common::optional ch{io.GetCurrentChar(byteCount)}; bool negate{ch && *ch == '-'}; if ((ch && *ch == '+') || negate) { io.HandleRelativePosition(byteCount); @@ -136,7 +137,7 @@ static std::optional GetSubscriptValue(IoStatementState &io) { if (overflow) { io.GetIoErrorHandler().SignalError( "NAMELIST input subscript value overflow"); - return std::nullopt; + return Fortran::common::nullopt; } if (negate) { if (value) { @@ -158,7 +159,7 @@ static bool HandleSubscripts(IoStatementState &io, Descriptor &desc, std::size_t contiguousStride{source.ElementBytes()}; bool ok{true}; std::size_t byteCount{0}; - std::optional ch{io.GetNextNonBlank(byteCount)}; + Fortran::common::optional ch{io.GetNextNonBlank(byteCount)}; char32_t comma{GetComma(io)}; for (; ch && *ch != ')'; ++j) { SubscriptValue dimLower{0}, dimUpper{0}, dimStride{0}; @@ -282,9 +283,9 @@ static bool HandleSubstring( SubscriptValue chars{static_cast(desc.ElementBytes()) / kind}; // Allow for blanks in substring bounds; they're nonstandard, but not // ambiguous within the parentheses. - std::optional lower, upper; + Fortran::common::optional lower, upper; std::size_t byteCount{0}; - std::optional ch{io.GetNextNonBlank(byteCount)}; + Fortran::common::optional ch{io.GetNextNonBlank(byteCount)}; if (ch) { if (*ch == ':') { lower = 1; @@ -346,7 +347,8 @@ static bool HandleComponent(IoStatementState &io, Descriptor &desc, // If base and component are both arrays, the component name // must be followed by subscripts; process them now. std::size_t byteCount{0}; - if (std::optional next{io.GetNextNonBlank(byteCount)}; + if (Fortran::common::optional next{ + io.GetNextNonBlank(byteCount)}; next && *next == '(') { io.HandleRelativePosition(byteCount); // skip over '(' StaticDescriptor staticDesc; @@ -435,7 +437,7 @@ bool IONAME(InputNamelist)(Cookie cookie, const NamelistGroup &group) { RUNTIME_CHECK(handler, listInput != nullptr); // Find this namelist group's header in the input io.BeginReadingRecord(); - std::optional next; + Fortran::common::optional next; char name[nameBufferSize]; RUNTIME_CHECK(handler, group.groupName != nullptr); char32_t comma{GetComma(io)}; diff --git a/flang/runtime/random-templates.h b/flang/runtime/random-templates.h index ce64a94901a2..f34422f6f5d9 100644 --- a/flang/runtime/random-templates.h +++ b/flang/runtime/random-templates.h @@ -11,6 +11,7 @@ #include "lock.h" #include "numeric-templates.h" +#include "flang/Common/optional.h" #include "flang/Runtime/descriptor.h" #include #include @@ -32,7 +33,7 @@ static constexpr int rangeBits{ extern Lock lock; extern Generator generator; -extern std::optional nextValue; +extern Fortran::common::optional nextValue; // Call only with lock held static GeneratedWord GetNextValue() { diff --git a/flang/runtime/random.cpp b/flang/runtime/random.cpp index 13bed1f0abe1..e0a421fd2839 100644 --- a/flang/runtime/random.cpp +++ b/flang/runtime/random.cpp @@ -28,7 +28,7 @@ namespace Fortran::runtime::random { Lock lock; Generator generator; -std::optional nextValue; +Fortran::common::optional nextValue; extern "C" { diff --git a/flang/runtime/tools.h b/flang/runtime/tools.h index c1f89cadca06..392e3fc6c891 100644 --- a/flang/runtime/tools.h +++ b/flang/runtime/tools.h @@ -12,6 +12,7 @@ #include "freestanding-tools.h" #include "stat.h" #include "terminator.h" +#include "flang/Common/optional.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" #include "flang/Runtime/memory.h" @@ -95,7 +96,7 @@ static inline RT_API_ATTRS std::int64_t GetInt64( } } -static inline RT_API_ATTRS std::optional GetInt64Safe( +static inline RT_API_ATTRS Fortran::common::optional GetInt64Safe( const char *p, std::size_t bytes, Terminator &terminator) { switch (bytes) { case 1: @@ -113,7 +114,7 @@ static inline RT_API_ATTRS std::optional GetInt64Safe( if (static_cast(result) == n) { return result; } - return std::nullopt; + return Fortran::common::nullopt; } default: terminator.Crash("GetInt64Safe: no case for %zd bytes", bytes); @@ -334,7 +335,8 @@ inline RT_API_ATTRS RESULT ApplyLogicalKind( } // Calculate result type of (X op Y) for *, //, DOT_PRODUCT, &c. -std::optional> inline constexpr RT_API_ATTRS +Fortran::common::optional< + std::pair> inline constexpr RT_API_ATTRS GetResultType(TypeCategory xCat, int xKind, TypeCategory yCat, int yKind) { int maxKind{std::max(xKind, yKind)}; switch (xCat) { @@ -390,18 +392,18 @@ GetResultType(TypeCategory xCat, int xKind, TypeCategory yCat, int yKind) { if (yCat == TypeCategory::Character) { return std::make_pair(TypeCategory::Character, maxKind); } else { - return std::nullopt; + return Fortran::common::nullopt; } case TypeCategory::Logical: if (yCat == TypeCategory::Logical) { return std::make_pair(TypeCategory::Logical, maxKind); } else { - return std::nullopt; + return Fortran::common::nullopt; } default: break; } - return std::nullopt; + return Fortran::common::nullopt; } // Accumulate floating-point results in (at least) double precision diff --git a/flang/runtime/type-code.cpp b/flang/runtime/type-code.cpp index b9ef307835df..cb1b944433aa 100644 --- a/flang/runtime/type-code.cpp +++ b/flang/runtime/type-code.cpp @@ -112,7 +112,7 @@ RT_API_ATTRS TypeCode::TypeCode(TypeCategory f, int kind) { } } -RT_API_ATTRS std::optional> +RT_API_ATTRS Fortran::common::optional> TypeCode::GetCategoryAndKind() const { switch (raw_) { case CFI_type_signed_char: @@ -204,7 +204,7 @@ TypeCode::GetCategoryAndKind() const { case CFI_type_char32_t: return std::make_pair(TypeCategory::Character, 4); default: - return std::nullopt; + return Fortran::common::nullopt; } } diff --git a/flang/runtime/type-info.cpp b/flang/runtime/type-info.cpp index b30a2c832a13..cb18c5669b5f 100644 --- a/flang/runtime/type-info.cpp +++ b/flang/runtime/type-info.cpp @@ -15,7 +15,7 @@ namespace Fortran::runtime::typeInfo { RT_OFFLOAD_API_GROUP_BEGIN -RT_API_ATTRS std::optional Value::GetValue( +RT_API_ATTRS Fortran::common::optional Value::GetValue( const Descriptor *descriptor) const { switch (genre_) { case Genre::Explicit: @@ -26,9 +26,9 @@ RT_API_ATTRS std::optional Value::GetValue( return addendum->LenParameterValue(value_); } } - return std::nullopt; + return Fortran::common::nullopt; default: - return std::nullopt; + return Fortran::common::nullopt; } } diff --git a/flang/runtime/type-info.h b/flang/runtime/type-info.h index bd8112d9d6d8..ee1ddbd0685c 100644 --- a/flang/runtime/type-info.h +++ b/flang/runtime/type-info.h @@ -15,10 +15,10 @@ #include "terminator.h" #include "flang/Common/Fortran.h" #include "flang/Common/bit-population-count.h" +#include "flang/Common/optional.h" #include "flang/Runtime/descriptor.h" #include #include -#include namespace Fortran::runtime::typeInfo { @@ -39,7 +39,7 @@ public: LenParameter = 3 }; RT_API_ATTRS Genre genre() const { return genre_; } - RT_API_ATTRS std::optional GetValue( + RT_API_ATTRS Fortran::common::optional GetValue( const Descriptor *) const; private: diff --git a/flang/runtime/unit-map.cpp b/flang/runtime/unit-map.cpp index 6ebda5c45f08..684a9b9e20b9 100644 --- a/flang/runtime/unit-map.cpp +++ b/flang/runtime/unit-map.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "unit-map.h" +#include "flang/Common/optional.h" namespace Fortran::runtime::io { @@ -29,7 +30,7 @@ void UnitMap::Initialize() { ExternalFileUnit &UnitMap::NewUnit(const Terminator &terminator) { CriticalSection critical{lock_}; Initialize(); - std::optional n{freeNewUnits_.PopValue()}; + Fortran::common::optional n{freeNewUnits_.PopValue()}; if (!n) { n = emergencyNewUnit_++; } diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp index 09782d2f8492..82f0e68cc20a 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -52,7 +52,7 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreate( } ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit, - Direction dir, std::optional isUnformatted, + Direction dir, Fortran::common::optional isUnformatted, const Terminator &terminator) { // Make sure that the returned anonymous unit has been opened // not just created in the unitMap. @@ -95,9 +95,10 @@ ExternalFileUnit &ExternalFileUnit::NewUnit( return unit; } -bool ExternalFileUnit::OpenUnit(std::optional status, - std::optional action, Position position, OwningPtr &&newPath, - std::size_t newPathLength, Convert convert, IoErrorHandler &handler) { +bool ExternalFileUnit::OpenUnit(Fortran::common::optional status, + Fortran::common::optional action, Position position, + OwningPtr &&newPath, std::size_t newPathLength, Convert convert, + IoErrorHandler &handler) { if (convert == Convert::Unknown) { convert = executionEnvironment.conversion; } @@ -176,9 +177,10 @@ bool ExternalFileUnit::OpenUnit(std::optional status, return impliedClose; } -void ExternalFileUnit::OpenAnonymousUnit(std::optional status, - std::optional action, Position position, Convert convert, - IoErrorHandler &handler) { +void ExternalFileUnit::OpenAnonymousUnit( + Fortran::common::optional status, + Fortran::common::optional action, Position position, + Convert convert, IoErrorHandler &handler) { // I/O to an unconnected unit reads/creates a local file, e.g. fort.7 std::size_t pathMaxLen{32}; auto path{SizedNew{handler}(pathMaxLen)}; diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index e3c8757645bb..fc5bead7e1d9 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -21,10 +21,10 @@ #include "lock.h" #include "terminator.h" #include "flang/Common/constexpr-bitset.h" +#include "flang/Common/optional.h" #include "flang/Runtime/memory.h" #include #include -#include #include namespace Fortran::runtime::io { @@ -55,7 +55,7 @@ public: static ExternalFileUnit *LookUpOrCreate( int unit, const Terminator &, bool &wasExtant); static ExternalFileUnit *LookUpOrCreateAnonymous(int unit, Direction, - std::optional isUnformatted, const Terminator &); + Fortran::common::optional isUnformatted, const Terminator &); static ExternalFileUnit *LookUp(const char *path, std::size_t pathLen); static ExternalFileUnit &CreateNew(int unit, const Terminator &); static ExternalFileUnit *LookUpForClose(int unit); @@ -64,11 +64,11 @@ public: static void FlushAll(IoErrorHandler &); // Returns true if an existing unit was closed - bool OpenUnit(std::optional, std::optional, Position, - OwningPtr &&path, std::size_t pathLength, Convert, - IoErrorHandler &); - void OpenAnonymousUnit(std::optional, std::optional, - Position, Convert, IoErrorHandler &); + bool OpenUnit(Fortran::common::optional, + Fortran::common::optional, Position, OwningPtr &&path, + std::size_t pathLength, Convert, IoErrorHandler &); + void OpenAnonymousUnit(Fortran::common::optional, + Fortran::common::optional, Position, Convert, IoErrorHandler &); void CloseUnit(CloseStatus, IoErrorHandler &); void DestroyClosed(); @@ -169,7 +169,7 @@ private: u_; // Points to the active alternative (if any) in u_ for use as a Cookie - std::optional io_; + Fortran::common::optional io_; // A stack of child I/O pseudo-units for defined I/O that have this // unit number. @@ -211,7 +211,7 @@ private: ChildUnformattedIoStatementState, InquireUnitState, ErroneousIoStatementState, ExternalMiscIoStatementState> u_; - std::optional io_; + Fortran::common::optional io_; }; } // namespace Fortran::runtime::io diff --git a/flang/runtime/utf.cpp b/flang/runtime/utf.cpp index 8f59ddbb1966..e9ccc2c04b6b 100644 --- a/flang/runtime/utf.cpp +++ b/flang/runtime/utf.cpp @@ -40,7 +40,7 @@ const std::uint8_t UTF8FirstByteTable[256]{ // clang-format on // Non-minimal encodings are accepted. -std::optional DecodeUTF8(const char *p0) { +Fortran::common::optional DecodeUTF8(const char *p0) { const std::uint8_t *p{reinterpret_cast(p0)}; std::size_t bytes{MeasureUTF8Bytes(*p0)}; if (bytes == 1) { @@ -50,7 +50,7 @@ std::optional DecodeUTF8(const char *p0) { for (std::size_t j{1}; j < bytes; ++j) { std::uint8_t next{p[j]}; if (next < 0x80 || next > 0xbf) { - return std::nullopt; + return Fortran::common::nullopt; } result = (result << 6) | (next & 0x3f); } @@ -58,7 +58,7 @@ std::optional DecodeUTF8(const char *p0) { return static_cast(result); } } - return std::nullopt; + return Fortran::common::nullopt; } std::size_t EncodeUTF8(char *p0, char32_t ucs) { diff --git a/flang/runtime/utf.h b/flang/runtime/utf.h index 6d9943bb6b8a..2b4e4f9a1887 100644 --- a/flang/runtime/utf.h +++ b/flang/runtime/utf.h @@ -41,9 +41,9 @@ #ifndef FORTRAN_RUNTIME_UTF_H_ #define FORTRAN_RUNTIME_UTF_H_ +#include "flang/Common/optional.h" #include #include -#include namespace Fortran::runtime { @@ -58,7 +58,7 @@ static constexpr std::size_t maxUTF8Bytes{7}; // Ensure that all bytes are present in sequence in the input buffer // before calling; use MeasureUTF8Bytes(first byte) to count them. -std::optional DecodeUTF8(const char *); +Fortran::common::optional DecodeUTF8(const char *); // Ensure that at least maxUTF8Bytes remain in the output // buffer before calling.