[flang] Add & use a better visit() (take 2)

Adds flang/include/flang/Common/log2-visit.h, which defines
a Fortran::common::visit() template function that is a drop-in
replacement for std::visit().  Modifies most use sites in
the front-end and runtime to use common::visit().

The C++ standard mandates that std::visit() have O(1) execution
time, which forces implementations to build dispatch tables.
This new common::visit() is O(log2 N) in the number of alternatives
in a variant<>, but that N tends to be small and so this change
produces a fairly significant improvement in compiler build
memory requirements, a 5-10% improvement in compiler build time,
and a small improvement in compiler execution time.

Building with -DFLANG_USE_STD_VISIT causes common::visit()
to be an alias for std::visit().

Calls to common::visit() with multiple variant arguments
are referred to std::visit(), pending further work.

This change is enabled only for GCC builds with GCC >= 9;
an earlier attempt (D122441) ran into bugs in some versions of
clang and was reverted rather than simply disabled; and it is
not well tested with MSVC. In non-GCC and older GCC builds,
common::visit() is simply an alias for std::visit().
This commit is contained in:
Peter Klausler 2022-03-23 14:05:50 -07:00
parent c6fdb1de47
commit cd03e96f00
62 changed files with 1469 additions and 1331 deletions

View File

@ -23,6 +23,7 @@
#error g++ >= 7.2 is required
#endif
#include "visit.h"
#include "llvm/Support/Compiler.h"
#include <functional>
#include <list>
@ -49,8 +50,8 @@ using namespace std::literals::string_literals;
namespace Fortran::common {
// Helper templates for combining a list of lambdas into an anonymous
// struct for use with std::visit() on a std::variant<> sum type.
// E.g.: std::visit(visitors{
// struct for use with common::visit() on a std::variant<> sum type.
// E.g.: common::visit(visitors{
// [&](const firstType &x) { ... },
// [&](const secondType &x) { ... },
// ...

View File

@ -118,14 +118,14 @@ template <typename A> const A *GetPtrFromOptional(const std::optional<A> &x) {
// Copy a value from one variant type to another. The types allowed in the
// source variant must all be allowed in the destination variant type.
template <typename TOV, typename FROMV> TOV CopyVariant(const FROMV &u) {
return std::visit([](const auto &x) -> TOV { return {x}; }, u);
return common::visit([](const auto &x) -> TOV { return {x}; }, u);
}
// Move a value from one variant type to another. The types allowed in the
// source variant must all be allowed in the destination variant type.
template <typename TOV, typename FROMV>
common::IfNoLvalue<TOV, FROMV> MoveVariant(FROMV &&u) {
return std::visit(
return common::visit(
[](auto &&x) -> TOV { return {std::move(x)}; }, std::move(u));
}

View File

@ -12,6 +12,7 @@
#include "indirection.h"
#include "reference-counted.h"
#include "reference.h"
#include "visit.h"
#include <memory>
#include <optional>
#include <type_traits>
@ -103,7 +104,7 @@ struct UnwrapperHelper {
template <typename A, typename... Bs>
static A *Unwrap(std::variant<Bs...> &u) {
return std::visit(
return common::visit(
[](auto &x) -> A * {
using Ty = std::decay_t<decltype(Unwrap<A>(x))>;
if constexpr (!std::is_const_v<std::remove_pointer_t<Ty>> ||
@ -117,7 +118,7 @@ struct UnwrapperHelper {
template <typename A, typename... Bs>
static auto Unwrap(const std::variant<Bs...> &u) -> std::add_const_t<A> * {
return std::visit(
return common::visit(
[](const auto &x) -> std::add_const_t<A> * { return Unwrap<A>(x); }, u);
}

View File

@ -0,0 +1,101 @@
//===-- include/flang/Common/visit.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
//
//===----------------------------------------------------------------------===//
// common::visit() is a drop-in replacement for std::visit() that reduces both
// compiler build time and compiler execution time modestly, and reduces
// compiler build memory requirements significantly (overall & maximum).
// It does not require redefinition of std::variant<>.
//
// The C++ standard mandates that std::visit be O(1), but most variants are
// small and O(logN) is faster in practice to compile and execute, avoiding
// the need to build a dispatch table.
//
// Define FLANG_USE_STD_VISIT to avoid this code and make common::visit() an
// alias for ::std::visit().
//
//
// With GCC 9.3.0 on a Haswell x86 Ubuntu system, doing out-of-tree builds:
// Before:
// build:
// 6948.53user 212.48system 27:32.92elapsed 433%CPU
// (0avgtext+0avgdata 6429568maxresident)k
// 36181912inputs+8943720outputs (3613684major+97908699minor)pagefaults 0swaps
// execution of tests:
// 205.99user 26.05system 1:08.87elapsed 336%CPU
// (0avgtext+0avgdata 2671452maxresident)k
// 244432inputs+355464outputs (422major+8746468minor)pagefaults 0swaps
// After:
// build:
// 6651.91user 182.57system 25:15.73elapsed 450%CPU
// (0avgtext+0avgdata 6209296maxresident)k
// 17413480inputs+6376360outputs (1567210major+93068230minor)pagefaults 0swaps
// execution of tests:
// 201.42user 25.91system 1:04.68elapsed 351%CPU
// (0avgtext+0avgdata 2661424maxresident)k
// 238840inputs+295912outputs (428major+8489300minor)pagefaults 0swaps
#ifndef FORTRAN_COMMON_VISIT_H_
#define FORTRAN_COMMON_VISIT_H_
#include <type_traits>
#include <variant>
namespace Fortran::common {
namespace log2visit {
template <std::size_t LOW, std::size_t HIGH, typename RESULT, typename VISITOR,
typename... VARIANT>
inline RESULT Log2VisitHelper(
VISITOR &&visitor, std::size_t which, VARIANT &&...u) {
if constexpr (LOW == HIGH) {
return visitor(std::get<LOW>(std::forward<VARIANT>(u))...);
} else {
static constexpr std::size_t mid{(HIGH + LOW) / 2};
if (which <= mid) {
return Log2VisitHelper<LOW, mid, RESULT>(
std::forward<VISITOR>(visitor), which, std::forward<VARIANT>(u)...);
} else {
return Log2VisitHelper<(mid + 1), HIGH, RESULT>(
std::forward<VISITOR>(visitor), which, std::forward<VARIANT>(u)...);
}
}
}
template <typename VISITOR, typename... VARIANT>
inline auto visit(VISITOR &&visitor, VARIANT &&...u)
-> decltype(visitor(std::get<0>(std::forward<VARIANT>(u))...)) {
using Result = decltype(visitor(std::get<0>(std::forward<VARIANT>(u))...));
if constexpr (sizeof...(u) == 1) {
static constexpr std::size_t high{
(std::variant_size_v<std::decay_t<decltype(u)>> * ...) - 1};
return Log2VisitHelper<0, high, Result>(std::forward<VISITOR>(visitor),
u.index()..., std::forward<VARIANT>(u)...);
} else {
// TODO: figure out how to do multiple variant arguments
return ::std::visit(
std::forward<VISITOR>(visitor), std::forward<VARIANT>(u)...);
}
}
} // namespace log2visit
// Some versions of clang have bugs that cause compilation to hang
// on these templates. MSVC and older GCC versions may work but are
// not well tested. So enable only for GCC 9 and better.
#if __GNUC__ < 9
#define FLANG_USE_STD_VISIT
#endif
#ifdef FLANG_USE_STD_VISIT
using ::std::visit;
#else
using Fortran::common::log2visit::visit;
#endif
} // namespace Fortran::common
#endif // FORTRAN_COMMON_VISIT_H_

View File

@ -646,7 +646,7 @@ public:
EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
static constexpr DynamicType GetType() { return Result::GetType(); }
int Rank() const {
return std::visit([](const auto &x) { return x.Rank(); }, u);
return common::visit([](const auto &x) { return x.Rank(); }, u);
}
llvm::raw_ostream &AsFortran(llvm::raw_ostream &o) const;
common::MapTemplate<Relational, DirectlyComparableTypes> u;

View File

@ -67,7 +67,7 @@ public:
template <typename T>
std::optional<OffsetSymbol> FoldDesignator(const Expr<T> &expr) {
return std::visit(
return common::visit(
[&](const auto &x) { return FoldDesignator(x, elementNumber_++); },
expr.u);
}
@ -98,7 +98,7 @@ private:
template <typename T>
std::optional<OffsetSymbol> FoldDesignator(
const Expr<T> &expr, ConstantSubscript which) {
return std::visit(
return common::visit(
[&](const auto &x) { return FoldDesignator(x, which); }, expr.u);
}
@ -110,14 +110,14 @@ private:
template <typename T>
std::optional<OffsetSymbol> FoldDesignator(
const Designator<T> &designator, ConstantSubscript which) {
return std::visit(
return common::visit(
[&](const auto &x) { return FoldDesignator(x, which); }, designator.u);
}
template <int KIND>
std::optional<OffsetSymbol> FoldDesignator(
const Designator<Type<TypeCategory::Character, KIND>> &designator,
ConstantSubscript which) {
return std::visit(
return common::visit(
common::visitors{
[&](const Substring &ss) {
if (const auto *dataRef{ss.GetParentIf<DataRef>()}) {

View File

@ -88,7 +88,7 @@ public:
template <typename T>
Result Add(ConstantSubscript offset, std::size_t bytes, const Expr<T> &x,
FoldingContext &c) {
return std::visit(
return common::visit(
[&](const auto &y) { return Add(offset, bytes, y, c); }, x.u);
}

View File

@ -167,7 +167,7 @@ private:
template <typename T>
MaybeExtentExpr GetArrayConstructorValueExtent(
const ArrayConstructorValue<T> &value) const {
return std::visit(
return common::visit(
common::visitors{
[&](const Expr<T> &x) -> MaybeExtentExpr {
if (auto xShape{

View File

@ -83,7 +83,7 @@ template <typename A> bool IsAssumedRank(const Designator<A> &designator) {
}
}
template <typename T> bool IsAssumedRank(const Expr<T> &expr) {
return std::visit([](const auto &x) { return IsAssumedRank(x); }, expr.u);
return common::visit([](const auto &x) { return IsAssumedRank(x); }, expr.u);
}
template <typename A> bool IsAssumedRank(const std::optional<A> &x) {
return x && IsAssumedRank(*x);
@ -100,7 +100,7 @@ template <typename A> bool IsCoarray(const Designator<A> &designator) {
return false;
}
template <typename T> bool IsCoarray(const Expr<T> &expr) {
return std::visit([](const auto &x) { return IsCoarray(x); }, expr.u);
return common::visit([](const auto &x) { return IsCoarray(x); }, expr.u);
}
template <typename A> bool IsCoarray(const std::optional<A> &x) {
return x && IsCoarray(*x);
@ -177,11 +177,11 @@ auto UnwrapExpr(B &x) -> common::Constify<A, B> * {
return UnwrapExpr<A>(*expr);
}
} else if constexpr (std::is_same_v<Ty, Expr<SomeType>>) {
return std::visit([](auto &x) { return UnwrapExpr<A>(x); }, x.u);
return common::visit([](auto &x) { return UnwrapExpr<A>(x); }, x.u);
} else if constexpr (!common::HasMember<A, TypelessExpression>) {
if constexpr (std::is_same_v<Ty, Expr<ResultType<A>>> ||
std::is_same_v<Ty, Expr<SomeKind<ResultType<A>::category>>>) {
return std::visit([](auto &x) { return UnwrapExpr<A>(x); }, x.u);
return common::visit([](auto &x) { return UnwrapExpr<A>(x); }, x.u);
}
}
return nullptr;
@ -217,15 +217,17 @@ auto UnwrapConvertedExpr(B &x) -> common::Constify<A, B> * {
return UnwrapConvertedExpr<A>(*expr);
}
} else if constexpr (std::is_same_v<Ty, Expr<SomeType>>) {
return std::visit([](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.u);
return common::visit(
[](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.u);
} else if constexpr (!common::HasMember<A, TypelessExpression>) {
using Result = ResultType<A>;
if constexpr (std::is_same_v<Ty, Expr<Result>> ||
std::is_same_v<Ty, Expr<SomeKind<Result::category>>>) {
return std::visit([](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.u);
return common::visit(
[](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.u);
} else if constexpr (std::is_same_v<Ty, Parentheses<Result>> ||
std::is_same_v<Ty, Convert<Result, Result::category>>) {
return std::visit(
return common::visit(
[](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.left().u);
}
}
@ -262,7 +264,7 @@ common::IfNoLvalue<std::optional<DataRef>, A> ExtractDataRef(
template <typename T>
std::optional<DataRef> ExtractDataRef(
const Designator<T> &d, bool intoSubstring = false) {
return std::visit(
return common::visit(
[=](const auto &x) -> std::optional<DataRef> {
if constexpr (common::HasMember<decltype(x), decltype(DataRef::u)>) {
return DataRef{x};
@ -279,7 +281,7 @@ std::optional<DataRef> ExtractDataRef(
template <typename T>
std::optional<DataRef> ExtractDataRef(
const Expr<T> &expr, bool intoSubstring = false) {
return std::visit(
return common::visit(
[=](const auto &x) { return ExtractDataRef(x, intoSubstring); }, expr.u);
}
template <typename A>
@ -328,7 +330,7 @@ bool IsArrayElement(const Expr<T> &expr, bool intoSubstring = true,
template <typename A>
std::optional<NamedEntity> ExtractNamedEntity(const A &x) {
if (auto dataRef{ExtractDataRef(x, true)}) {
return std::visit(
return common::visit(
common::visitors{
[](SymbolRef &&symbol) -> std::optional<NamedEntity> {
return NamedEntity{symbol};
@ -354,10 +356,10 @@ struct ExtractCoindexedObjectHelper {
std::optional<CoarrayRef> operator()(const CoarrayRef &x) const { return x; }
template <typename A>
std::optional<CoarrayRef> operator()(const Expr<A> &expr) const {
return std::visit(*this, expr.u);
return common::visit(*this, expr.u);
}
std::optional<CoarrayRef> operator()(const DataRef &dataRef) const {
return std::visit(*this, dataRef.u);
return common::visit(*this, dataRef.u);
}
std::optional<CoarrayRef> operator()(const NamedEntity &named) const {
if (const Component * component{named.UnwrapComponent()}) {
@ -470,7 +472,7 @@ Expr<TO> ConvertToType(Expr<SomeKind<FROMCAT>> &&x) {
ConvertToType<Part>(std::move(x)), Expr<Part>{Constant<Part>{zero}}}};
} else if constexpr (FROMCAT == TypeCategory::Complex) {
// Extract and convert the real component of a complex value
return std::visit(
return common::visit(
[&](auto &&z) {
using ZType = ResultType<decltype(z)>;
using Part = typename ZType::Part;
@ -524,7 +526,7 @@ common::IfNoLvalue<Expr<Type<TC, TK>>, FROM> ConvertTo(
template <TypeCategory TC, typename FROM>
common::IfNoLvalue<Expr<SomeKind<TC>>, FROM> ConvertTo(
const Expr<SomeKind<TC>> &to, FROM &&from) {
return std::visit(
return common::visit(
[&](const auto &toKindExpr) {
using KindExpr = std::decay_t<decltype(toKindExpr)>;
return AsCategoryExpr(
@ -536,7 +538,7 @@ common::IfNoLvalue<Expr<SomeKind<TC>>, FROM> ConvertTo(
template <typename FROM>
common::IfNoLvalue<Expr<SomeType>, FROM> ConvertTo(
const Expr<SomeType> &to, FROM &&from) {
return std::visit(
return common::visit(
[&](const auto &toCatExpr) {
return AsGenericExpr(ConvertTo(toCatExpr, std::move(from)));
},
@ -586,7 +588,7 @@ using SameKindExprs =
template <TypeCategory CAT>
SameKindExprs<CAT, 2> AsSameKindExprs(
Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) {
return std::visit(
return common::visit(
[&](auto &&kx, auto &&ky) -> SameKindExprs<CAT, 2> {
using XTy = ResultType<decltype(kx)>;
using YTy = ResultType<decltype(ky)>;
@ -647,7 +649,7 @@ Expr<SPECIFIC> Combine(Expr<SPECIFIC> &&x, Expr<SPECIFIC> &&y) {
template <template <typename> class OPR, TypeCategory CAT>
Expr<SomeKind<CAT>> PromoteAndCombine(
Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) {
return std::visit(
return common::visit(
[](auto &&xy) {
using Ty = ResultType<decltype(xy[0])>;
return AsCategoryExpr(
@ -748,7 +750,7 @@ Expr<Type<C, K>> operator/(Expr<Type<C, K>> &&x, Expr<Type<C, K>> &&y) {
}
template <TypeCategory C> Expr<SomeKind<C>> operator-(Expr<SomeKind<C>> &&x) {
return std::visit(
return common::visit(
[](auto &xk) { return Expr<SomeKind<C>>{-std::move(xk)}; }, x.u);
}
@ -893,7 +895,7 @@ std::optional<BaseObject> GetBaseObject(const Designator<T> &x) {
}
template <typename T>
std::optional<BaseObject> GetBaseObject(const Expr<T> &x) {
return std::visit([](const auto &y) { return GetBaseObject(y); }, x.u);
return common::visit([](const auto &y) { return GetBaseObject(y); }, x.u);
}
template <typename A>
std::optional<BaseObject> GetBaseObject(const std::optional<A> &x) {
@ -1035,7 +1037,8 @@ public:
return Expand(std::move(x.left())); // Constant<> can be parenthesized
}
template <typename T> Expr<T> Expand(Expr<T> &&x) {
return std::visit([&](auto &&x) { return Expr<T>{Expand(std::move(x))}; },
return common::visit(
[&](auto &&x) { return Expr<T>{Expand(std::move(x))}; },
std::move(x.u));
}

View File

@ -78,7 +78,7 @@ public:
}
template <typename... A>
Result operator()(const std::variant<A...> &u) const {
return std::visit(visitor_, u);
return common::visit(visitor_, u);
}
template <typename A> Result operator()(const std::vector<A> &x) const {
return CombineContents(x);

View File

@ -10,6 +10,7 @@
#define FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
#include "parse-tree.h"
#include "flang/Common/visit.h"
#include <cstddef>
#include <optional>
#include <tuple>
@ -133,14 +134,14 @@ void Walk(std::tuple<A...> &x, M &mutator) {
template <typename V, typename... A>
void Walk(const std::variant<A...> &x, V &visitor) {
if (visitor.Pre(x)) {
std::visit([&](const auto &y) { Walk(y, visitor); }, x);
common::visit([&](const auto &y) { Walk(y, visitor); }, x);
visitor.Post(x);
}
}
template <typename M, typename... A>
void Walk(std::variant<A...> &x, M &mutator) {
if (mutator.Pre(x)) {
std::visit([&](auto &y) { Walk(y, mutator); }, x);
common::visit([&](auto &y) { Walk(y, mutator); }, x);
mutator.Post(x);
}
}

View File

@ -62,7 +62,7 @@ struct UnwrapperHelper {
template <typename A, typename... Bs>
static const A *Unwrap(const std::variant<Bs...> &x) {
return std::visit([](const auto &y) { return Unwrap<A>(y); }, x);
return common::visit([](const auto &y) { return Unwrap<A>(y); }, x);
}
template <typename A, typename B>

View File

@ -13,6 +13,7 @@
#include "flang/Common/Fortran.h"
#include "flang/Common/indirection.h"
#include "flang/Common/restorer.h"
#include "flang/Common/visit.h"
#include "flang/Evaluate/characteristics.h"
#include "flang/Evaluate/check-expression.h"
#include "flang/Evaluate/expression.h"
@ -299,11 +300,7 @@ private:
return Analyze(x.u); // default case
}
template <typename... As> MaybeExpr Analyze(const std::variant<As...> &u) {
return std::visit(
[&](const auto &x) {
return Analyze(x);
},
u);
return common::visit([&](const auto &x) { return Analyze(x); }, u);
}
// Analysis subroutines

View File

@ -13,6 +13,7 @@
#include "flang/Common/Fortran.h"
#include "flang/Common/enum-set.h"
#include "flang/Common/reference.h"
#include "flang/Common/visit.h"
#include "llvm/ADT/DenseMapInfo.h"
#include <array>
#include <functional>
@ -612,24 +613,24 @@ public:
bool IsSubprogram() const;
bool IsFromModFile() const;
bool HasExplicitInterface() const {
return std::visit(common::visitors{
[](const SubprogramDetails &) { return true; },
[](const SubprogramNameDetails &) { return true; },
[&](const ProcEntityDetails &x) {
return attrs_.test(Attr::INTRINSIC) ||
x.HasExplicitInterface();
},
[](const ProcBindingDetails &x) {
return x.symbol().HasExplicitInterface();
},
[](const UseDetails &x) {
return x.symbol().HasExplicitInterface();
},
[](const HostAssocDetails &x) {
return x.symbol().HasExplicitInterface();
},
[](const auto &) { return false; },
},
return common::visit(common::visitors{
[](const SubprogramDetails &) { return true; },
[](const SubprogramNameDetails &) { return true; },
[&](const ProcEntityDetails &x) {
return attrs_.test(Attr::INTRINSIC) ||
x.HasExplicitInterface();
},
[](const ProcBindingDetails &x) {
return x.symbol().HasExplicitInterface();
},
[](const UseDetails &x) {
return x.symbol().HasExplicitInterface();
},
[](const HostAssocDetails &x) {
return x.symbol().HasExplicitInterface();
},
[](const auto &) { return false; },
},
details_);
}
@ -637,7 +638,7 @@ public:
bool operator!=(const Symbol &that) const { return !(*this == that); }
int Rank() const {
return std::visit(
return common::visit(
common::visitors{
[](const SubprogramDetails &sd) {
return sd.isFunction() ? sd.result().Rank() : 0;
@ -670,7 +671,7 @@ public:
}
int Corank() const {
return std::visit(
return common::visit(
common::visitors{
[](const SubprogramDetails &sd) {
return sd.isFunction() ? sd.result().Corank() : 0;
@ -786,7 +787,7 @@ inline DeclTypeSpec *Symbol::GetType() {
const_cast<const Symbol *>(this)->GetType());
}
inline const DeclTypeSpec *Symbol::GetType() const {
return std::visit(
return common::visit(
common::visitors{
[](const EntityDetails &x) { return x.type(); },
[](const ObjectEntityDetails &x) { return x.type(); },

View File

@ -13,6 +13,7 @@
// canonically for use in semantic checking.
#include "flang/Common/Fortran.h"
#include "flang/Common/visit.h"
#include "flang/Evaluate/expression.h"
#include "flang/Evaluate/shape.h"
#include "flang/Evaluate/type.h"
@ -239,7 +240,7 @@ const Symbol *FindExternallyVisibleObject(
template <typename T>
const Symbol *FindExternallyVisibleObject(
const evaluate::Expr<T> &expr, const Scope &scope) {
return std::visit(
return common::visit(
[&](const auto &x) { return FindExternallyVisibleObject(x, scope); },
expr.u);
}

View File

@ -157,18 +157,19 @@ const Component *ProcedureDesignator::GetComponent() const {
}
const Symbol *ProcedureDesignator::GetSymbol() const {
return std::visit(common::visitors{
[](SymbolRef symbol) { return &*symbol; },
[](const common::CopyableIndirection<Component> &c) {
return &c.value().GetLastSymbol();
},
[](const auto &) -> const Symbol * { return nullptr; },
},
return common::visit(
common::visitors{
[](SymbolRef symbol) { return &*symbol; },
[](const common::CopyableIndirection<Component> &c) {
return &c.value().GetLastSymbol();
},
[](const auto &) -> const Symbol * { return nullptr; },
},
u);
}
std::string ProcedureDesignator::GetName() const {
return std::visit(
return common::visit(
common::visitors{
[](const SpecificIntrinsic &i) { return i.name; },
[](const Symbol &symbol) { return symbol.name().ToString(); },

View File

@ -69,7 +69,7 @@ TypeAndShape &TypeAndShape::Rewrite(FoldingContext &context) {
std::optional<TypeAndShape> TypeAndShape::Characterize(
const semantics::Symbol &symbol, FoldingContext &context) {
const auto &ultimate{symbol.GetUltimate()};
return std::visit(
return common::visit(
common::visitors{
[&](const semantics::ProcEntityDetails &proc) {
const semantics::ProcInterface &interface{proc.interface()};
@ -392,7 +392,7 @@ static std::optional<Procedure> CharacterizeProcedure(
result.attrs.test(Procedure::Attr::Elemental))) {
result.attrs.set(Procedure::Attr::Pure);
}
return std::visit(
return common::visit(
common::visitors{
[&](const semantics::SubprogramDetails &subp)
-> std::optional<Procedure> {
@ -578,7 +578,7 @@ static std::optional<DummyArgument> CharacterizeDummyArgument(
std::optional<DummyArgument> DummyArgument::FromActual(
std::string &&name, const Expr<SomeType> &expr, FoldingContext &context) {
return std::visit(
return common::visit(
common::visitors{
[&](const BOZLiteralConstant &) {
return std::make_optional<DummyArgument>(std::move(name),
@ -619,7 +619,7 @@ std::optional<DummyArgument> DummyArgument::FromActual(
}
bool DummyArgument::IsOptional() const {
return std::visit(
return common::visit(
common::visitors{
[](const DummyDataObject &data) {
return data.attrs.test(DummyDataObject::Attr::Optional);
@ -633,35 +633,36 @@ bool DummyArgument::IsOptional() const {
}
void DummyArgument::SetOptional(bool value) {
std::visit(common::visitors{
[value](DummyDataObject &data) {
data.attrs.set(DummyDataObject::Attr::Optional, value);
},
[value](DummyProcedure &proc) {
proc.attrs.set(DummyProcedure::Attr::Optional, value);
},
[](AlternateReturn &) { DIE("cannot set optional"); },
},
common::visit(common::visitors{
[value](DummyDataObject &data) {
data.attrs.set(DummyDataObject::Attr::Optional, value);
},
[value](DummyProcedure &proc) {
proc.attrs.set(DummyProcedure::Attr::Optional, value);
},
[](AlternateReturn &) { DIE("cannot set optional"); },
},
u);
}
void DummyArgument::SetIntent(common::Intent intent) {
std::visit(common::visitors{
[intent](DummyDataObject &data) { data.intent = intent; },
[intent](DummyProcedure &proc) { proc.intent = intent; },
[](AlternateReturn &) { DIE("cannot set intent"); },
},
common::visit(common::visitors{
[intent](DummyDataObject &data) { data.intent = intent; },
[intent](DummyProcedure &proc) { proc.intent = intent; },
[](AlternateReturn &) { DIE("cannot set intent"); },
},
u);
}
common::Intent DummyArgument::GetIntent() const {
return std::visit(common::visitors{
[](const DummyDataObject &data) { return data.intent; },
[](const DummyProcedure &proc) { return proc.intent; },
[](const AlternateReturn &) -> common::Intent {
DIE("Alternate returns have no intent");
},
},
return common::visit(
common::visitors{
[](const DummyDataObject &data) { return data.intent; },
[](const DummyProcedure &proc) { return proc.intent; },
[](const AlternateReturn &) -> common::Intent {
DIE("Alternate returns have no intent");
},
},
u);
}
@ -685,7 +686,7 @@ llvm::raw_ostream &DummyArgument::Dump(llvm::raw_ostream &o) const {
if (pass) {
o << " PASS";
}
std::visit([&](const auto &x) { x.Dump(o); }, u);
common::visit([&](const auto &x) { x.Dump(o); }, u);
return o;
}
@ -798,12 +799,12 @@ bool FunctionResult::IsCompatibleWith(const FunctionResult &actual) const {
llvm::raw_ostream &FunctionResult::Dump(llvm::raw_ostream &o) const {
attrs.Dump(o, EnumToString);
std::visit(common::visitors{
[&](const TypeAndShape &ts) { ts.Dump(o); },
[&](const CopyableIndirection<Procedure> &p) {
p.value().Dump(o << " procedure(") << ')';
},
},
common::visit(common::visitors{
[&](const TypeAndShape &ts) { ts.Dump(o); },
[&](const CopyableIndirection<Procedure> &p) {
p.value().Dump(o << " procedure(") << ')';
},
},
u);
return o;
}
@ -1135,7 +1136,7 @@ bool DistinguishUtils::Distinguishable(
if (x.u.index() != y.u.index()) {
return true; // different kind: data/proc/alt-return
}
return std::visit(
return common::visit(
common::visitors{
[&](const DummyDataObject &z) {
return Distinguishable(z, std::get<DummyDataObject>(y.u));
@ -1197,7 +1198,7 @@ bool DistinguishUtils::Distinguishable(
if (x.u.index() != y.u.index()) {
return true; // one is data object, one is procedure
}
return std::visit(
return common::visit(
common::visitors{
[&](const TypeAndShape &z) {
return Distinguishable(z, std::get<TypeAndShape>(y.u));

View File

@ -173,13 +173,13 @@ struct IsActuallyConstantHelper {
return (*this)(x.left());
}
template <typename T> bool operator()(const Expr<T> &x) {
return std::visit([=](const auto &y) { return (*this)(y); }, x.u);
return common::visit([=](const auto &y) { return (*this)(y); }, x.u);
}
bool operator()(const Expr<SomeType> &x) {
if (IsNullPointer(x)) {
return true;
}
return std::visit([this](const auto &y) { return (*this)(y); }, x.u);
return common::visit([this](const auto &y) { return (*this)(y); }, x.u);
}
template <typename A> bool operator()(const A *x) { return x && (*this)(*x); }
template <typename A> bool operator()(const std::optional<A> &x) {
@ -256,13 +256,13 @@ public:
IsConstantExpr(x.stride());
}
bool operator()(const Subscript &x) const {
return std::visit(common::visitors{
[&](const Triplet &t) { return (*this)(t); },
[&](const auto &y) {
return y.value().Rank() == 0 &&
IsConstantExpr(y.value());
},
},
return common::visit(common::visitors{
[&](const Triplet &t) { return (*this)(t); },
[&](const auto &y) {
return y.value().Rank() == 0 &&
IsConstantExpr(y.value());
},
},
x.u);
}
bool operator()(const CoarrayRef &) const { return false; }
@ -334,7 +334,7 @@ bool IsInitialDataTarget(
bool IsInitialProcedureTarget(const semantics::Symbol &symbol) {
const auto &ultimate{symbol.GetUltimate()};
return std::visit(
return common::visit(
common::visitors{
[](const semantics::SubprogramDetails &subp) {
return !subp.isDummy();
@ -383,7 +383,7 @@ public:
std::move(x.left())); // Constant<> can be parenthesized
}
template <typename T> Expr<T> ChangeLbounds(Expr<T> &&x) {
return std::visit(
return common::visit(
[&](auto &&x) { return Expr<T>{ChangeLbounds(std::move(x))}; },
std::move(x.u)); // recurse until we hit a constant
}

View File

@ -30,7 +30,7 @@ template <int KIND>
std::optional<Expr<SubscriptInteger>>
Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
using T = std::optional<Expr<SubscriptInteger>>;
return std::visit(
return common::visit(
common::visitors{
[](const Constant<Result> &c) -> T {
return AsExpr(Constant<SubscriptInteger>{c.LEN()});
@ -38,7 +38,7 @@ Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
[](const ArrayConstructor<Result> &a) -> T { return a.LEN(); },
[](const Parentheses<Result> &x) { return x.left().LEN(); },
[](const Convert<Result> &x) {
return std::visit(
return common::visit(
[&](const auto &kx) { return kx.LEN(); }, x.left().u);
},
[](const Concat<KIND> &c) -> T {
@ -84,7 +84,7 @@ std::optional<DynamicType> ExpressionBase<A>::GetType() const {
if constexpr (IsLengthlessIntrinsicType<Result>) {
return Result::GetType();
} else {
return std::visit(
return common::visit(
[&](const auto &x) -> std::optional<DynamicType> {
if constexpr (!common::HasMember<decltype(x), TypelessExpression>) {
return x.GetType();
@ -96,7 +96,7 @@ std::optional<DynamicType> ExpressionBase<A>::GetType() const {
}
template <typename A> int ExpressionBase<A>::Rank() const {
return std::visit(
return common::visit(
[](const auto &x) {
if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
return 0;
@ -309,19 +309,19 @@ void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *p) {
}
template <TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const {
return std::visit(
return common::visit(
[](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
u);
}
int Expr<SomeCharacter>::GetKind() const {
return std::visit(
return common::visit(
[](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
u);
}
std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
return std::visit([](const auto &kx) { return kx.LEN(); }, u);
return common::visit([](const auto &kx) { return kx.LEN(); }, u);
}
#ifdef _MSC_VER // disable bogus warning about missing definitions

View File

@ -70,7 +70,7 @@ std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator(
ConstantSubscript lower{lowerBounds->at(dim)};
ConstantSubscript extent{extents->at(dim)};
ConstantSubscript upper{lower + extent - 1};
if (!std::visit(
if (!common::visit(
common::visitors{
[&](const IndirectSubscriptIntegerExpr &expr) {
auto folded{
@ -169,7 +169,7 @@ std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator(
std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator(
const DataRef &dataRef, ConstantSubscript which) {
return std::visit(
return common::visit(
[&](const auto &x) { return FoldDesignator(x, which); }, dataRef.u);
}
@ -317,7 +317,7 @@ std::optional<Expr<SomeType>> OffsetToDesignator(FoldingContext &context,
// Pick a COMPLEX component
auto part{
offset == 0 ? ComplexPart::Part::RE : ComplexPart::Part::IM};
return std::visit(
return common::visit(
[&](const auto &z) -> std::optional<Expr<SomeType>> {
using PartType = typename ResultType<decltype(z)>::Part;
return AsGenericExpr(Designator<PartType>{ComplexPart{
@ -329,7 +329,7 @@ std::optional<Expr<SomeType>> OffsetToDesignator(FoldingContext &context,
std::get_if<Expr<SomeCharacter>>(&result->u)}) {
if (offset > 0 || size != static_cast<std::size_t>(*elementBytes)) {
// Select a substring
return std::visit(
return common::visit(
[&](const auto &x) -> std::optional<Expr<SomeType>> {
using T = typename std::decay_t<decltype(x)>::Result;
return AsGenericExpr(Designator<T>{

View File

@ -303,7 +303,7 @@ std::optional<Constant<T>> Folder<T>::ApplyComponent(
template <typename T>
std::optional<Constant<T>> Folder<T>::GetConstantComponent(Component &component,
const std::vector<Constant<SubscriptInteger>> *subscripts) {
if (std::optional<Constant<SomeDerived>> structures{std::visit(
if (std::optional<Constant<SomeDerived>> structures{common::visit(
common::visitors{
[&](const Symbol &symbol) {
return Folder<SomeDerived>{context_}.GetNamedConstant(symbol);
@ -342,7 +342,7 @@ template <typename T> Expr<T> Folder<T>::Folding(Designator<T> &&designator) {
}
}
}
return std::visit(
return common::visit(
common::visitors{
[&](SymbolRef &&symbol) {
if (auto constant{GetNamedConstant(*symbol)}) {
@ -523,7 +523,7 @@ template <typename A, typename B>
std::optional<std::vector<A>> GetIntegerVector(const B &x) {
static_assert(std::is_integral_v<A>);
if (const auto *someInteger{UnwrapExpr<Expr<SomeInteger>>(x)}) {
return std::visit(
return common::visit(
[](const auto &typedExpr) -> std::optional<std::vector<A>> {
using T = ResultType<decltype(typedExpr)>;
if (const auto *constant{UnwrapConstantValue<T>(typedExpr)}) {
@ -1039,10 +1039,10 @@ Expr<T> RewriteSpecificMINorMAX(
return Fold(context, ConvertToType<T>(AsCategoryExpr(std::move(maxRef))));
}};
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(*resultTypeArg)}) {
return std::visit(insertConversion, sx->u);
return common::visit(insertConversion, sx->u);
}
auto &sx{DEREF(UnwrapExpr<Expr<SomeInteger>>(*resultTypeArg))};
return std::visit(insertConversion, sx.u);
return common::visit(insertConversion, sx.u);
}
template <typename T>
@ -1164,7 +1164,7 @@ private:
}
}
bool FoldArray(const ArrayConstructorValue<T> &x) {
return std::visit([&](const auto &y) { return FoldArray(y); }, x.u);
return common::visit([&](const auto &y) { return FoldArray(y); }, x.u);
}
bool FoldArray(const ArrayConstructorValues<T> &xs) {
for (const auto &x : xs) {
@ -1227,7 +1227,7 @@ template <TypeCategory CAT>
std::enable_if_t<CAT != TypeCategory::Derived,
std::optional<Expr<SomeKind<CAT>>>>
AsFlatArrayConstructor(const Expr<SomeKind<CAT>> &expr) {
return std::visit(
return common::visit(
[&](const auto &kindExpr) -> std::optional<Expr<SomeKind<CAT>>> {
if (auto flattened{AsFlatArrayConstructor(kindExpr)}) {
return Expr<SomeKind<CAT>>{std::move(*flattened)};
@ -1268,7 +1268,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
Expr<OPERAND> &&values) {
ArrayConstructor<RESULT> result{values};
if constexpr (common::HasMember<OPERAND, AllIntrinsicCategoryTypes>) {
std::visit(
common::visit(
[&](auto &&kindExpr) {
using kindType = ResultType<decltype(kindExpr)>;
auto &aConst{std::get<ArrayConstructor<kindType>>(kindExpr.u)};
@ -1309,7 +1309,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
auto result{ArrayConstructorFromMold<RESULT>(leftValues, std::move(length))};
auto &leftArrConst{std::get<ArrayConstructor<LEFT>>(leftValues.u)};
if constexpr (common::HasMember<RIGHT, AllIntrinsicCategoryTypes>) {
std::visit(
common::visit(
[&](auto &&kindExpr) {
using kindType = ResultType<decltype(kindExpr)>;
@ -1366,7 +1366,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
const Expr<LEFT> &leftScalar, Expr<RIGHT> &&rightValues) {
auto result{ArrayConstructorFromMold<RESULT>(leftScalar, std::move(length))};
if constexpr (common::HasMember<RIGHT, AllIntrinsicCategoryTypes>) {
std::visit(
common::visit(
[&](auto &&kindExpr) {
using kindType = ResultType<decltype(kindExpr)>;
auto &rightArrConst{std::get<ArrayConstructor<kindType>>(kindExpr.u)};
@ -1518,7 +1518,7 @@ Expr<TO> FoldOperation(
FoldingContext &context;
Convert<TO, FROMCAT> &convert;
} msvcWorkaround{context, convert};
return std::visit(
return common::visit(
[&msvcWorkaround](auto &kindExpr) -> Expr<TO> {
using Operand = ResultType<decltype(kindExpr)>;
// This variable is a workaround for msvc which emits an error when
@ -1839,7 +1839,7 @@ Expr<T> FoldOperation(FoldingContext &context, RealToIntPower<T> &&x) {
if (auto array{ApplyElementwise(context, x)}) {
return *array;
}
return std::visit(
return common::visit(
[&](auto &y) -> Expr<T> {
if (auto folded{OperandsAreConstants(x.left(), y)}) {
auto power{evaluate::IntPower(folded->first, folded->second)};
@ -1897,7 +1897,7 @@ Expr<Type<TypeCategory::Real, KIND>> ToReal(
FoldingContext &context, Expr<SomeType> &&expr) {
using Result = Type<TypeCategory::Real, KIND>;
std::optional<Expr<Result>> result;
std::visit(
common::visit(
[&](auto &&x) {
using From = std::decay_t<decltype(x)>;
if constexpr (std::is_same_v<From, BOZLiteralConstant>) {
@ -1924,7 +1924,7 @@ Expr<Type<TypeCategory::Real, KIND>> ToReal(
template <typename T>
Expr<T> ExpressionBase<T>::Rewrite(FoldingContext &context, Expr<T> &&expr) {
return std::visit(
return common::visit(
[&](auto &&x) -> Expr<T> {
if constexpr (IsSpecificIntrinsicType<T>) {
return FoldOperation(context, std::move(x));

View File

@ -37,7 +37,7 @@ public:
template <typename T> ConstantSubscript GetLbound(const Expr<T> &x) {
// recurse through Expr<T>'a until we hit a constant
return std::visit([&](const auto &inner) { return GetLbound(inner); },
return common::visit([&](const auto &inner) { return GetLbound(inner); },
// [&](const auto &) { return 0; },
x.u);
}
@ -431,7 +431,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
common::RoundingMode mode{name == "ceiling" ? common::RoundingMode::Up
: name == "floor" ? common::RoundingMode::Down
: common::RoundingMode::TiesAwayFromZero};
return std::visit(
return common::visit(
[&](const auto &kx) {
using TR = ResultType<decltype(kx)>;
return FoldElementalIntrinsic<T, TR>(context, std::move(funcRef),
@ -450,19 +450,19 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
return FoldCount<T>(context, std::move(funcRef));
} else if (name == "digits") {
if (const auto *cx{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
return Expr<T>{std::visit(
return Expr<T>{common::visit(
[](const auto &kx) {
return Scalar<ResultType<decltype(kx)>>::DIGITS;
},
cx->u)};
} else if (const auto *cx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
return Expr<T>{std::visit(
return Expr<T>{common::visit(
[](const auto &kx) {
return Scalar<ResultType<decltype(kx)>>::DIGITS;
},
cx->u)};
} else if (const auto *cx{UnwrapExpr<Expr<SomeComplex>>(args[0])}) {
return Expr<T>{std::visit(
return Expr<T>{common::visit(
[](const auto &kx) {
return Scalar<typename ResultType<decltype(kx)>::Part>::DIGITS;
},
@ -484,7 +484,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
}));
} else if (name == "exponent") {
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
return std::visit(
return common::visit(
[&funcRef, &context](const auto &x) -> Expr<T> {
using TR = typename std::decay_t<decltype(x)>::Result;
return FoldElementalIntrinsic<T, TR>(context, std::move(funcRef),
@ -508,7 +508,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
"Character in intrinsic function %s must have length one"_warn_en_US,
name);
} else {
return std::visit(
return common::visit(
[&funcRef, &context](const auto &str) -> Expr<T> {
using Char = typename std::decay_t<decltype(str)>::Result;
return FoldElementalIntrinsic<T, Char>(context,
@ -586,7 +586,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
}));
} else if (name == "index" || name == "scan" || name == "verify") {
if (auto *charExpr{UnwrapExpr<Expr<SomeCharacter>>(args[0])}) {
return std::visit(
return common::visit(
[&](const auto &kch) -> Expr<T> {
using TC = typename std::decay_t<decltype(kch)>::Result;
if (UnwrapExpr<Expr<SomeLogical>>(args[2])) { // BACK=
@ -623,7 +623,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
}
} else if (name == "int") {
if (auto *expr{UnwrapExpr<Expr<SomeType>>(args[0])}) {
return std::visit(
return common::visit(
[&](auto &&x) -> Expr<T> {
using From = std::decay_t<decltype(x)>;
if constexpr (std::is_same_v<From, BOZLiteralConstant> ||
@ -666,7 +666,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
} else if (name == "leadz" || name == "trailz" || name == "poppar" ||
name == "popcnt") {
if (auto *sn{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
return std::visit(
return common::visit(
[&funcRef, &context, &name](const auto &n) -> Expr<T> {
using TI = typename std::decay_t<decltype(n)>::Result;
if (name == "poppar") {
@ -696,7 +696,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
}
} else if (name == "len") {
if (auto *charExpr{UnwrapExpr<Expr<SomeCharacter>>(args[0])}) {
return std::visit(
return common::visit(
[&](auto &kx) {
if (auto len{kx.LEN()}) {
if (IsScopeInvariantExpr(*len)) {
@ -714,7 +714,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
}
} else if (name == "len_trim") {
if (auto *charExpr{UnwrapExpr<Expr<SomeCharacter>>(args[0])}) {
return std::visit(
return common::visit(
[&](const auto &kch) -> Expr<T> {
using TC = typename std::decay_t<decltype(kch)>::Result;
return FoldElementalIntrinsic<T, TC>(context, std::move(funcRef),
@ -740,7 +740,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
return RewriteSpecificMINorMAX(context, std::move(funcRef));
} else if (name == "maxexponent") {
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
return std::visit(
return common::visit(
[](const auto &x) {
using TR = typename std::decay_t<decltype(x)>::Result;
return Expr<T>{Scalar<TR>::MAXEXPONENT};
@ -763,7 +763,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
return RewriteSpecificMINorMAX(context, std::move(funcRef));
} else if (name == "minexponent") {
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
return std::visit(
return common::visit(
[](const auto &x) {
using TR = typename std::decay_t<decltype(x)>::Result;
return Expr<T>{Scalar<TR>::MINEXPONENT};
@ -805,13 +805,13 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
context, std::move(funcRef), &Scalar<T>::NOT);
} else if (name == "precision") {
if (const auto *cx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
return Expr<T>{std::visit(
return Expr<T>{common::visit(
[](const auto &kx) {
return Scalar<ResultType<decltype(kx)>>::PRECISION;
},
cx->u)};
} else if (const auto *cx{UnwrapExpr<Expr<SomeComplex>>(args[0])}) {
return Expr<T>{std::visit(
return Expr<T>{common::visit(
[](const auto &kx) {
return Scalar<typename ResultType<decltype(kx)>::Part>::PRECISION;
},
@ -823,19 +823,19 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
return Expr<T>{2};
} else if (name == "range") {
if (const auto *cx{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
return Expr<T>{std::visit(
return Expr<T>{common::visit(
[](const auto &kx) {
return Scalar<ResultType<decltype(kx)>>::RANGE;
},
cx->u)};
} else if (const auto *cx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
return Expr<T>{std::visit(
return Expr<T>{common::visit(
[](const auto &kx) {
return Scalar<ResultType<decltype(kx)>>::RANGE;
},
cx->u)};
} else if (const auto *cx{UnwrapExpr<Expr<SomeComplex>>(args[0])}) {
return Expr<T>{std::visit(
return Expr<T>{common::visit(
[](const auto &kx) {
return Scalar<typename ResultType<decltype(kx)>::Part>::RANGE;
},
@ -1036,7 +1036,7 @@ Expr<TypeParamInquiry::Result> FoldOperation(
}
std::optional<std::int64_t> ToInt64(const Expr<SomeInteger> &expr) {
return std::visit(
return common::visit(
[](const auto &kindExpr) { return ToInt64(kindExpr); }, expr.u);
}

View File

@ -91,7 +91,7 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
}));
} else if (name == "btest") {
if (const auto *ix{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
return std::visit(
return common::visit(
[&](const auto &x) {
using IT = ResultType<decltype(x)>;
return FoldElementalIntrinsic<T, IT, SameInt>(context,
@ -212,7 +212,7 @@ Expr<LogicalResult> FoldOperation(
Expr<LogicalResult> FoldOperation(
FoldingContext &context, Relational<SomeType> &&relation) {
return std::visit(
return common::visit(
[&](auto &&x) {
return Expr<LogicalResult>{FoldOperation(context, std::move(x))};
},

View File

@ -121,7 +121,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
return FoldMerge<T>(context, std::move(funcRef));
} else if (name == "nearest") {
if (const auto *sExpr{UnwrapExpr<Expr<SomeReal>>(args[1])}) {
return std::visit(
return common::visit(
[&](const auto &sVal) {
using TS = ResultType<decltype(sVal)>;
return FoldElementalIntrinsic<T, T, TS>(context, std::move(funcRef),
@ -158,7 +158,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
}
} else if (name == "scale") {
if (const auto *byExpr{UnwrapExpr<Expr<SomeInteger>>(args[1])}) {
return std::visit(
return common::visit(
[&](const auto &byVal) {
using TBY = ResultType<decltype(byVal)>;
return FoldElementalIntrinsic<T, T, TBY>(context,
@ -194,7 +194,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
return Expr<T>{Scalar<T>::TINY()};
} else if (name == "__builtin_ieee_next_after") {
if (const auto *yExpr{UnwrapExpr<Expr<SomeReal>>(args[1])}) {
return std::visit(
return common::visit(
[&](const auto &yVal) {
using TY = ResultType<decltype(yVal)>;
return FoldElementalIntrinsic<T, T, TY>(context, std::move(funcRef),

View File

@ -21,7 +21,7 @@ characteristics::TypeAndShape Fold(
std::optional<Constant<SubscriptInteger>> GetConstantSubscript(
FoldingContext &context, Subscript &ss, const NamedEntity &base, int dim) {
ss = FoldOperation(context, std::move(ss));
return std::visit(
return common::visit(
common::visitors{
[](IndirectSubscriptIntegerExpr &expr)
-> std::optional<Constant<SubscriptInteger>> {
@ -119,16 +119,16 @@ Triplet FoldOperation(FoldingContext &context, Triplet &&triplet) {
}
Subscript FoldOperation(FoldingContext &context, Subscript &&subscript) {
return std::visit(common::visitors{
[&](IndirectSubscriptIntegerExpr &&expr) {
expr.value() = Fold(context, std::move(expr.value()));
return Subscript(std::move(expr));
},
[&](Triplet &&triplet) {
return Subscript(
FoldOperation(context, std::move(triplet)));
},
},
return common::visit(
common::visitors{
[&](IndirectSubscriptIntegerExpr &&expr) {
expr.value() = Fold(context, std::move(expr.value()));
return Subscript(std::move(expr));
},
[&](Triplet &&triplet) {
return Subscript(FoldOperation(context, std::move(triplet)));
},
},
std::move(subscript.u));
}
@ -162,12 +162,13 @@ CoarrayRef FoldOperation(FoldingContext &context, CoarrayRef &&coarrayRef) {
}
DataRef FoldOperation(FoldingContext &context, DataRef &&dataRef) {
return std::visit(common::visitors{
[&](SymbolRef symbol) { return DataRef{*symbol}; },
[&](auto &&x) {
return DataRef{FoldOperation(context, std::move(x))};
},
},
return common::visit(common::visitors{
[&](SymbolRef symbol) { return DataRef{*symbol}; },
[&](auto &&x) {
return DataRef{
FoldOperation(context, std::move(x))};
},
},
std::move(dataRef.u));
}

View File

@ -111,7 +111,7 @@ llvm::raw_ostream &ActualArgument::AsFortran(llvm::raw_ostream &o) const {
if (keyword_) {
o << keyword_->ToString() << '=';
}
std::visit(
common::visit(
common::visitors{
[&](const common::CopyableIndirection<Expr<SomeType>> &expr) {
expr.value().AsFortran(o);
@ -227,7 +227,7 @@ template <typename T> static Precedence ToPrecedence(const Constant<T> &x) {
return Precedence::Top;
}
template <typename T> static Precedence ToPrecedence(const Expr<T> &expr) {
return std::visit([](const auto &x) { return ToPrecedence(x); }, expr.u);
return common::visit([](const auto &x) { return ToPrecedence(x); }, expr.u);
}
template <typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
@ -242,7 +242,7 @@ template <typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
template <TypeCategory CAT>
static bool IsNegatedScalarConstant(const Expr<SomeKind<CAT>> &expr) {
return std::visit(
return common::visit(
[](const auto &x) { return IsNegatedScalarConstant(x); }, expr.u);
}
@ -373,7 +373,7 @@ llvm::raw_ostream &Convert<TO, FROMCAT>::AsFortran(llvm::raw_ostream &o) const {
}
llvm::raw_ostream &Relational<SomeType>::AsFortran(llvm::raw_ostream &o) const {
std::visit([&](const auto &rel) { rel.AsFortran(o); }, u);
common::visit([&](const auto &rel) { rel.AsFortran(o); }, u);
return o;
}
@ -404,7 +404,7 @@ llvm::raw_ostream &EmitArray(
const char *sep{""};
for (const auto &value : values) {
o << sep;
std::visit([&](const auto &x) { EmitArray(o, x); }, value.u);
common::visit([&](const auto &x) { EmitArray(o, x); }, value.u);
sep = ",";
}
return o;
@ -444,17 +444,17 @@ std::string ExpressionBase<RESULT>::AsFortran() const {
template <typename RESULT>
llvm::raw_ostream &ExpressionBase<RESULT>::AsFortran(
llvm::raw_ostream &o) const {
std::visit(common::visitors{
[&](const BOZLiteralConstant &x) {
o << "z'" << x.Hexadecimal() << "'";
},
[&](const NullPointer &) { o << "NULL()"; },
[&](const common::CopyableIndirection<Substring> &s) {
s.value().AsFortran(o);
},
[&](const ImpliedDoIndex &i) { o << i.name.ToString(); },
[&](const auto &x) { x.AsFortran(o); },
},
common::visit(common::visitors{
[&](const BOZLiteralConstant &x) {
o << "z'" << x.Hexadecimal() << "'";
},
[&](const NullPointer &) { o << "NULL()"; },
[&](const common::CopyableIndirection<Substring> &s) {
s.value().AsFortran(o);
},
[&](const ImpliedDoIndex &i) { o << i.name.ToString(); },
[&](const auto &x) { x.AsFortran(o); },
},
derived().u);
return o;
}
@ -608,7 +608,7 @@ llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::shared_ptr<A> &p) {
template <typename... A>
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::variant<A...> &u) {
std::visit([&](const auto &x) { EmitVar(o, x); }, u);
common::visit([&](const auto &x) { EmitVar(o, x); }, u);
return o;
}
@ -629,10 +629,10 @@ llvm::raw_ostream &Component::AsFortran(llvm::raw_ostream &o) const {
}
llvm::raw_ostream &NamedEntity::AsFortran(llvm::raw_ostream &o) const {
std::visit(common::visitors{
[&](SymbolRef s) { EmitVar(o, s); },
[&](const Component &c) { c.AsFortran(o); },
},
common::visit(common::visitors{
[&](SymbolRef s) { EmitVar(o, s); },
[&](const Component &c) { c.AsFortran(o); },
},
u_);
return o;
}
@ -712,10 +712,10 @@ llvm::raw_ostream &ProcedureDesignator::AsFortran(llvm::raw_ostream &o) const {
template <typename T>
llvm::raw_ostream &Designator<T>::AsFortran(llvm::raw_ostream &o) const {
std::visit(common::visitors{
[&](SymbolRef symbol) { EmitVar(o, symbol); },
[&](const auto &x) { x.AsFortran(o); },
},
common::visit(common::visitors{
[&](SymbolRef symbol) { EmitVar(o, symbol); },
[&](const auto &x) { x.AsFortran(o); },
},
u);
return o;
}
@ -752,7 +752,7 @@ llvm::raw_ostream &DescriptorInquiry::AsFortran(llvm::raw_ostream &o) const {
}
llvm::raw_ostream &Assignment::AsFortran(llvm::raw_ostream &o) const {
std::visit(
common::visit(
common::visitors{
[&](const Assignment::Intrinsic &) {
rhs.AsFortran(lhs.AsFortran(o) << '=');

View File

@ -480,7 +480,7 @@ MaybeExtentExpr GetExtent(
MaybeExtentExpr GetExtent(
const Subscript &subscript, const NamedEntity &base, int dimension) {
return std::visit(
return common::visit(
common::visitors{
[&](const Triplet &triplet) -> MaybeExtentExpr {
MaybeExtentExpr upper{triplet.upper()};
@ -650,7 +650,7 @@ Shape GetUBOUNDs(FoldingContext &context, const NamedEntity &base) {
Shape GetUBOUNDs(const NamedEntity &base) { return GetUBOUNDs(nullptr, base); }
auto GetShapeHelper::operator()(const Symbol &symbol) const -> Result {
return std::visit(
return common::visit(
common::visitors{
[&](const semantics::ObjectEntityDetails &object) {
if (IsImpliedShape(symbol) && object.init()) {

View File

@ -40,7 +40,7 @@ std::optional<Expr<SomeType>> AsGenericExpr(const Symbol &symbol) {
}
Expr<SomeType> Parenthesize(Expr<SomeType> &&expr) {
return std::visit(
return common::visit(
[&](auto &&x) {
using T = std::decay_t<decltype(x)>;
if constexpr (common::HasMember<T, TypelessExpression>) {
@ -48,7 +48,7 @@ Expr<SomeType> Parenthesize(Expr<SomeType> &&expr) {
} else if constexpr (std::is_same_v<T, Expr<SomeDerived>>) {
return AsGenericExpr(Parentheses<SomeDerived>{std::move(x)});
} else {
return std::visit(
return common::visit(
[](auto &&y) {
using T = ResultType<decltype(y)>;
return AsGenericExpr(Parentheses<T>{std::move(y)});
@ -69,7 +69,7 @@ std::optional<DataRef> ExtractDataRef(
}
std::optional<DataRef> ExtractSubstringBase(const Substring &substring) {
return std::visit(
return common::visit(
common::visitors{
[&](const DataRef &x) -> std::optional<DataRef> { return x; },
[&](const StaticDataObject::Pointer &) -> std::optional<DataRef> {
@ -108,7 +108,7 @@ auto IsVariableHelper::operator()(const ProcedureDesignator &x) const
ConvertRealOperandsResult ConvertRealOperands(
parser::ContextualMessages &messages, Expr<SomeType> &&x,
Expr<SomeType> &&y, int defaultRealKind) {
return std::visit(
return common::visit(
common::visitors{
[&](Expr<SomeInteger> &&ix,
Expr<SomeInteger> &&iy) -> ConvertRealOperandsResult {
@ -190,7 +190,7 @@ std::optional<Expr<SomeType>> Package(
template <template <typename> class OPR>
std::optional<Expr<SomeType>> MixedRealLeft(
Expr<SomeReal> &&rx, Expr<SomeInteger> &&iy) {
return Package(std::visit(
return Package(common::visit(
[&](auto &&rxk) -> Expr<SomeReal> {
using resultType = ResultType<decltype(rxk)>;
if constexpr (std::is_same_v<OPR<resultType>, Power<resultType>>) {
@ -210,7 +210,7 @@ std::optional<Expr<SomeComplex>> ConstructComplex(
Expr<SomeType> &&imaginary, int defaultRealKind) {
if (auto converted{ConvertRealOperands(
messages, std::move(real), std::move(imaginary), defaultRealKind)}) {
return {std::visit(
return {common::visit(
[](auto &&pair) {
return MakeComplex(std::move(pair[0]), std::move(pair[1]));
},
@ -230,7 +230,7 @@ std::optional<Expr<SomeComplex>> ConstructComplex(
}
Expr<SomeReal> GetComplexPart(const Expr<SomeComplex> &z, bool isImaginary) {
return std::visit(
return common::visit(
[&](const auto &zk) {
static constexpr int kind{ResultType<decltype(zk)>::kind};
return AsCategoryExpr(ComplexComponent<kind>{isImaginary, zk});
@ -243,7 +243,7 @@ Expr<SomeReal> GetComplexPart(const Expr<SomeComplex> &z, bool isImaginary) {
// the highest precision of REAL and COMPLEX operands as required by Fortran
// 2018 10.9.1.3.
Expr<SomeComplex> PromoteRealToComplex(Expr<SomeReal> &&someX) {
return std::visit(
return common::visit(
[](auto &&x) {
using RT = ResultType<decltype(x)>;
return AsCategoryExpr(ComplexConstructor<RT::kind>{
@ -289,7 +289,7 @@ std::optional<Expr<SomeType>> MixedComplexLeft(
std::is_same_v<OPR<LargestReal>, Power<LargestReal>>) {
// COMPLEX**INTEGER is a special case that doesn't convert the exponent.
static_assert(RCAT == TypeCategory::Integer);
return Package(std::visit(
return Package(common::visit(
[&](auto &&zxk) {
using Ty = ResultType<decltype(zxk)>;
return AsCategoryExpr(
@ -358,7 +358,7 @@ template <template <typename> class OPR>
std::optional<Expr<SomeType>> NumericOperation(
parser::ContextualMessages &messages, Expr<SomeType> &&x,
Expr<SomeType> &&y, int defaultRealKind) {
return std::visit(
return common::visit(
common::visitors{
[](Expr<SomeInteger> &&ix, Expr<SomeInteger> &&iy) {
return Package(PromoteAndCombine<OPR, TypeCategory::Integer>(
@ -373,7 +373,7 @@ std::optional<Expr<SomeType>> NumericOperation(
return MixedRealLeft<OPR>(std::move(rx), std::move(iy));
},
[](Expr<SomeInteger> &&ix, Expr<SomeReal> &&ry) {
return Package(std::visit(
return Package(common::visit(
[&](auto &&ryk) -> Expr<SomeReal> {
using resultType = ResultType<decltype(ryk)>;
return AsCategoryExpr(
@ -450,7 +450,7 @@ template std::optional<Expr<SomeType>> NumericOperation<Subtract>(
std::optional<Expr<SomeType>> Negation(
parser::ContextualMessages &messages, Expr<SomeType> &&x) {
return std::visit(
return common::visit(
common::visitors{
[&](BOZLiteralConstant &&) {
messages.Say("BOZ literal cannot be negated"_err_en_US);
@ -491,7 +491,7 @@ std::optional<Expr<SomeType>> Negation(
}
Expr<SomeLogical> LogicalNegation(Expr<SomeLogical> &&x) {
return std::visit(
return common::visit(
[](auto &&xk) { return AsCategoryExpr(LogicalNegation(std::move(xk))); },
std::move(x.u));
}
@ -499,7 +499,7 @@ Expr<SomeLogical> LogicalNegation(Expr<SomeLogical> &&x) {
template <TypeCategory CAT>
Expr<LogicalResult> PromoteAndRelate(
RelationalOperator opr, Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) {
return std::visit(
return common::visit(
[=](auto &&xy) {
return PackageRelation(opr, std::move(xy[0]), std::move(xy[1]));
},
@ -508,7 +508,7 @@ Expr<LogicalResult> PromoteAndRelate(
std::optional<Expr<LogicalResult>> Relate(parser::ContextualMessages &messages,
RelationalOperator opr, Expr<SomeType> &&x, Expr<SomeType> &&y) {
return std::visit(
return common::visit(
common::visitors{
[=](Expr<SomeInteger> &&ix,
Expr<SomeInteger> &&iy) -> std::optional<Expr<LogicalResult>> {
@ -554,7 +554,7 @@ std::optional<Expr<LogicalResult>> Relate(parser::ContextualMessages &messages,
AsGenericExpr(ConvertTo(zy, std::move(rx))), std::move(y));
},
[&](Expr<SomeCharacter> &&cx, Expr<SomeCharacter> &&cy) {
return std::visit(
return common::visit(
[&](auto &&cxk,
auto &&cyk) -> std::optional<Expr<LogicalResult>> {
using Ty = ResultType<decltype(cxk)>;
@ -580,7 +580,7 @@ std::optional<Expr<LogicalResult>> Relate(parser::ContextualMessages &messages,
Expr<SomeLogical> BinaryLogicalOperation(
LogicalOperator opr, Expr<SomeLogical> &&x, Expr<SomeLogical> &&y) {
CHECK(opr != LogicalOperator::Not);
return std::visit(
return common::visit(
[=](auto &&xy) {
using Ty = ResultType<decltype(xy[0])>;
return Expr<SomeLogical>{BinaryLogicalOperation<Ty::kind>(
@ -592,7 +592,7 @@ Expr<SomeLogical> BinaryLogicalOperation(
template <TypeCategory TO>
std::optional<Expr<SomeType>> ConvertToNumeric(int kind, Expr<SomeType> &&x) {
static_assert(common::IsNumericTypeCategory(TO));
return std::visit(
return common::visit(
[=](auto &&cx) -> std::optional<Expr<SomeType>> {
using cxType = std::decay_t<decltype(cx)>;
if constexpr (!common::HasMember<cxType, TypelessExpression>) {
@ -632,7 +632,7 @@ std::optional<Expr<SomeType>> ConvertToType(
auto converted{
ConvertToKind<TypeCategory::Character>(type.kind(), std::move(*cx))};
if (auto length{type.GetCharLength()}) {
converted = std::visit(
converted = common::visit(
[&](auto &&x) {
using Ty = std::decay_t<decltype(x)>;
using CharacterType = typename Ty::Result;
@ -732,15 +732,15 @@ bool IsFunction(const Expr<SomeType> &expr) {
}
bool IsProcedurePointerTarget(const Expr<SomeType> &expr) {
return std::visit(common::visitors{
[](const NullPointer &) { return true; },
[](const ProcedureDesignator &) { return true; },
[](const ProcedureRef &) { return true; },
[&](const auto &) {
const Symbol *last{GetLastSymbol(expr)};
return last && IsProcedurePointer(*last);
},
},
return common::visit(common::visitors{
[](const NullPointer &) { return true; },
[](const ProcedureDesignator &) { return true; },
[](const ProcedureRef &) { return true; },
[&](const auto &) {
const Symbol *last{GetLastSymbol(expr)};
return last && IsProcedurePointer(*last);
},
},
expr.u);
}
@ -755,7 +755,7 @@ inline const ProcedureRef *UnwrapProcedureRef(const FunctionRef<T> &func) {
template <typename T>
inline const ProcedureRef *UnwrapProcedureRef(const Expr<T> &expr) {
return std::visit(
return common::visit(
[](const auto &x) { return UnwrapProcedureRef(x); }, expr.u);
}
@ -792,7 +792,7 @@ struct IsNullPointerHelper {
return (*this)(x.left());
}
template <typename T> bool operator()(const Expr<T> &x) const {
return std::visit(*this, x.u);
return common::visit(*this, x.u);
}
};
@ -1019,7 +1019,8 @@ static const Symbol *GetLastPointerSymbol(const CoarrayRef &x) {
return nullptr;
}
const Symbol *GetLastPointerSymbol(const DataRef &x) {
return std::visit([](const auto &y) { return GetLastPointerSymbol(y); }, x.u);
return common::visit(
[](const auto &y) { return GetLastPointerSymbol(y); }, x.u);
}
template <TypeCategory TO, TypeCategory FROM>
@ -1030,7 +1031,7 @@ static std::optional<Expr<SomeType>> DataConstantConversionHelper(
if (auto sized{
Fold(context, ConvertToType(sizedType, Expr<SomeType>{expr}))}) {
if (const auto *someExpr{UnwrapExpr<Expr<SomeKind<FROM>>>(*sized)}) {
return std::visit(
return common::visit(
[](const auto &w) -> std::optional<Expr<SomeType>> {
using FromType = typename std::decay_t<decltype(w)>::Result;
static constexpr int kind{FromType::kind};
@ -1219,18 +1220,19 @@ bool IsPureProcedure(const Scope &scope) {
bool IsFunction(const Symbol &symbol) {
const Symbol &ultimate{symbol.GetUltimate()};
return ultimate.test(Symbol::Flag::Function) ||
std::visit(common::visitors{
[](const SubprogramDetails &x) { return x.isFunction(); },
[](const ProcEntityDetails &x) {
const auto &ifc{x.interface()};
return ifc.type() ||
(ifc.symbol() && IsFunction(*ifc.symbol()));
},
[](const ProcBindingDetails &x) {
return IsFunction(x.symbol());
},
[](const auto &) { return false; },
},
common::visit(
common::visitors{
[](const SubprogramDetails &x) { return x.isFunction(); },
[](const ProcEntityDetails &x) {
const auto &ifc{x.interface()};
return ifc.type() ||
(ifc.symbol() && IsFunction(*ifc.symbol()));
},
[](const ProcBindingDetails &x) {
return IsFunction(x.symbol());
},
[](const auto &) { return false; },
},
ultimate.details());
}
@ -1240,14 +1242,14 @@ bool IsFunction(const Scope &scope) {
}
bool IsProcedure(const Symbol &symbol) {
return std::visit(common::visitors{
[](const SubprogramDetails &) { return true; },
[](const SubprogramNameDetails &) { return true; },
[](const ProcEntityDetails &) { return true; },
[](const GenericDetails &) { return true; },
[](const ProcBindingDetails &) { return true; },
[](const auto &) { return false; },
},
return common::visit(common::visitors{
[](const SubprogramDetails &) { return true; },
[](const SubprogramNameDetails &) { return true; },
[](const ProcEntityDetails &) { return true; },
[](const GenericDetails &) { return true; },
[](const ProcBindingDetails &) { return true; },
[](const auto &) { return false; },
},
symbol.GetUltimate().details());
}
@ -1361,7 +1363,7 @@ bool IsSaved(const Symbol &original) {
}
bool IsDummy(const Symbol &symbol) {
return std::visit(
return common::visit(
common::visitors{[](const EntityDetails &x) { return x.isDummy(); },
[](const ObjectEntityDetails &x) { return x.isDummy(); },
[](const ProcEntityDetails &x) { return x.isDummy(); },
@ -1490,7 +1492,7 @@ static const Symbol *FindFunctionResult(
if (!seen.insert(root).second) {
return nullptr; // don't loop
}
return std::visit(
return common::visit(
common::visitors{[](const SubprogramDetails &subp) {
return subp.isFunction() ? &subp.result() : nullptr;
},

View File

@ -55,7 +55,7 @@ static bool IsDescriptor(const ProcEntityDetails &details) {
}
bool IsDescriptor(const Symbol &symbol) {
return std::visit(
return common::visit(
common::visitors{
[&](const ObjectEntityDetails &d) {
return IsAllocatableOrPointer(symbol) || IsDescriptor(d);

View File

@ -145,7 +145,7 @@ std::optional<Expr<SubscriptInteger>> Substring::upper() const {
if (upper_) {
return upper_.value().value();
} else {
return std::visit(
return common::visit(
common::visitors{
[](const DataRef &dataRef) { return dataRef.LEN(); },
[](const StaticDataObject::Pointer &object)
@ -208,7 +208,7 @@ std::optional<Expr<SomeCharacter>> Substring::Fold(FoldingContext &context) {
}
std::optional<Expr<SomeCharacter>> result;
if (strings) {
result = std::visit(
result = common::visit(
[&](const auto &expr) -> std::optional<Expr<SomeCharacter>> {
using Type = typename std::decay_t<decltype(expr)>::Result;
if (const auto *cc{std::get_if<Constant<Type>>(&expr.u)}) {
@ -281,7 +281,7 @@ static std::optional<Expr<SubscriptInteger>> SymbolLEN(const Symbol &symbol) {
}
std::optional<Expr<SubscriptInteger>> BaseObject::LEN() const {
return std::visit(
return common::visit(
common::visitors{
[](const Symbol &symbol) { return SymbolLEN(symbol); },
[](const StaticDataObject::Pointer &object)
@ -309,10 +309,10 @@ std::optional<Expr<SubscriptInteger>> CoarrayRef::LEN() const {
}
std::optional<Expr<SubscriptInteger>> DataRef::LEN() const {
return std::visit(common::visitors{
[](SymbolRef symbol) { return SymbolLEN(symbol); },
[](const auto &x) { return x.LEN(); },
},
return common::visit(common::visitors{
[](SymbolRef symbol) { return SymbolLEN(symbol); },
[](const auto &x) { return x.LEN(); },
},
u);
}
@ -329,10 +329,10 @@ std::optional<Expr<SubscriptInteger>> Substring::LEN() const {
template <typename T>
std::optional<Expr<SubscriptInteger>> Designator<T>::LEN() const {
if constexpr (T::category == TypeCategory::Character) {
return std::visit(common::visitors{
[](SymbolRef symbol) { return SymbolLEN(symbol); },
[](const auto &x) { return x.LEN(); },
},
return common::visit(common::visitors{
[](SymbolRef symbol) { return SymbolLEN(symbol); },
[](const auto &x) { return x.LEN(); },
},
u);
} else {
common::die("Designator<non-char>::LEN() called");
@ -342,7 +342,7 @@ std::optional<Expr<SubscriptInteger>> Designator<T>::LEN() const {
std::optional<Expr<SubscriptInteger>> ProcedureDesignator::LEN() const {
using T = std::optional<Expr<SubscriptInteger>>;
return std::visit(
return common::visit(
common::visitors{
[](SymbolRef symbol) -> T { return SymbolLEN(symbol); },
[](const common::CopyableIndirection<Component> &c) -> T {
@ -367,10 +367,10 @@ std::optional<Expr<SubscriptInteger>> ProcedureDesignator::LEN() const {
// Rank()
int BaseObject::Rank() const {
return std::visit(common::visitors{
[](SymbolRef symbol) { return symbol->Rank(); },
[](const StaticDataObject::Pointer &) { return 0; },
},
return common::visit(common::visitors{
[](SymbolRef symbol) { return symbol->Rank(); },
[](const StaticDataObject::Pointer &) { return 0; },
},
u);
}
@ -382,20 +382,20 @@ int Component::Rank() const {
}
int NamedEntity::Rank() const {
return std::visit(common::visitors{
[](const SymbolRef s) { return s->Rank(); },
[](const Component &c) { return c.Rank(); },
},
return common::visit(common::visitors{
[](const SymbolRef s) { return s->Rank(); },
[](const Component &c) { return c.Rank(); },
},
u_);
}
int Subscript::Rank() const {
return std::visit(common::visitors{
[](const IndirectSubscriptIntegerExpr &x) {
return x.value().Rank();
},
[](const Triplet &) { return 1; },
},
return common::visit(common::visitors{
[](const IndirectSubscriptIntegerExpr &x) {
return x.value().Rank();
},
[](const Triplet &) { return 1; },
},
u);
}
@ -426,28 +426,29 @@ int CoarrayRef::Rank() const {
}
int DataRef::Rank() const {
return std::visit(common::visitors{
[](SymbolRef symbol) { return symbol->Rank(); },
[](const auto &x) { return x.Rank(); },
},
return common::visit(common::visitors{
[](SymbolRef symbol) { return symbol->Rank(); },
[](const auto &x) { return x.Rank(); },
},
u);
}
int Substring::Rank() const {
return std::visit(common::visitors{
[](const DataRef &dataRef) { return dataRef.Rank(); },
[](const StaticDataObject::Pointer &) { return 0; },
},
return common::visit(
common::visitors{
[](const DataRef &dataRef) { return dataRef.Rank(); },
[](const StaticDataObject::Pointer &) { return 0; },
},
parent_);
}
int ComplexPart::Rank() const { return complex_.Rank(); }
template <typename T> int Designator<T>::Rank() const {
return std::visit(common::visitors{
[](SymbolRef symbol) { return symbol->Rank(); },
[](const auto &x) { return x.Rank(); },
},
return common::visit(common::visitors{
[](SymbolRef symbol) { return symbol->Rank(); },
[](const auto &x) { return x.Rank(); },
},
u);
}
@ -457,38 +458,39 @@ const Symbol &Component::GetFirstSymbol() const {
}
const Symbol &NamedEntity::GetFirstSymbol() const {
return std::visit(common::visitors{
[](SymbolRef s) -> const Symbol & { return s; },
[](const Component &c) -> const Symbol & {
return c.GetFirstSymbol();
},
},
return common::visit(common::visitors{
[](SymbolRef s) -> const Symbol & { return s; },
[](const Component &c) -> const Symbol & {
return c.GetFirstSymbol();
},
},
u_);
}
const Symbol &NamedEntity::GetLastSymbol() const {
return std::visit(common::visitors{
[](SymbolRef s) -> const Symbol & { return s; },
[](const Component &c) -> const Symbol & {
return c.GetLastSymbol();
},
},
return common::visit(common::visitors{
[](SymbolRef s) -> const Symbol & { return s; },
[](const Component &c) -> const Symbol & {
return c.GetLastSymbol();
},
},
u_);
}
const Component *NamedEntity::UnwrapComponent() const {
return std::visit(common::visitors{
[](SymbolRef) -> const Component * { return nullptr; },
[](const Component &c) { return &c; },
},
return common::visit(
common::visitors{
[](SymbolRef) -> const Component * { return nullptr; },
[](const Component &c) { return &c; },
},
u_);
}
Component *NamedEntity::UnwrapComponent() {
return std::visit(common::visitors{
[](SymbolRef &) -> Component * { return nullptr; },
[](Component &c) { return &c; },
},
return common::visit(common::visitors{
[](SymbolRef &) -> Component * { return nullptr; },
[](Component &c) { return &c; },
},
u_);
}
@ -499,35 +501,35 @@ const Symbol &ArrayRef::GetFirstSymbol() const {
const Symbol &ArrayRef::GetLastSymbol() const { return base_.GetLastSymbol(); }
const Symbol &DataRef::GetFirstSymbol() const {
return *std::visit(common::visitors{
[](SymbolRef symbol) { return &*symbol; },
[](const auto &x) { return &x.GetFirstSymbol(); },
},
return *common::visit(common::visitors{
[](SymbolRef symbol) { return &*symbol; },
[](const auto &x) { return &x.GetFirstSymbol(); },
},
u);
}
const Symbol &DataRef::GetLastSymbol() const {
return *std::visit(common::visitors{
[](SymbolRef symbol) { return &*symbol; },
[](const auto &x) { return &x.GetLastSymbol(); },
},
return *common::visit(common::visitors{
[](SymbolRef symbol) { return &*symbol; },
[](const auto &x) { return &x.GetLastSymbol(); },
},
u);
}
BaseObject Substring::GetBaseObject() const {
return std::visit(common::visitors{
[](const DataRef &dataRef) {
return BaseObject{dataRef.GetFirstSymbol()};
},
[](StaticDataObject::Pointer pointer) {
return BaseObject{std::move(pointer)};
},
},
return common::visit(common::visitors{
[](const DataRef &dataRef) {
return BaseObject{dataRef.GetFirstSymbol()};
},
[](StaticDataObject::Pointer pointer) {
return BaseObject{std::move(pointer)};
},
},
parent_);
}
const Symbol *Substring::GetLastSymbol() const {
return std::visit(
return common::visit(
common::visitors{
[](const DataRef &dataRef) { return &dataRef.GetLastSymbol(); },
[](const auto &) -> const Symbol * { return nullptr; },
@ -536,7 +538,7 @@ const Symbol *Substring::GetLastSymbol() const {
}
template <typename T> BaseObject Designator<T>::GetBaseObject() const {
return std::visit(
return common::visit(
common::visitors{
[](SymbolRef symbol) { return BaseObject{symbol}; },
[](const Substring &sstring) { return sstring.GetBaseObject(); },
@ -554,7 +556,7 @@ template <typename T> BaseObject Designator<T>::GetBaseObject() const {
}
template <typename T> const Symbol *Designator<T>::GetLastSymbol() const {
return std::visit(
return common::visit(
common::visitors{
[](SymbolRef symbol) { return &*symbol; },
[](const Substring &sstring) { return sstring.GetLastSymbol(); },

View File

@ -85,7 +85,7 @@ const char *MessageFormattedText::Convert(CharBlock x) {
}
std::string MessageExpectedText::ToString() const {
return std::visit(
return common::visit(
common::visitors{
[](CharBlock cb) {
return MessageFormattedText("expected '%s'"_err_en_US, cb)
@ -124,13 +124,13 @@ std::string MessageExpectedText::ToString() const {
}
bool MessageExpectedText::Merge(const MessageExpectedText &that) {
return std::visit(common::visitors{
[](SetOfChars &s1, const SetOfChars &s2) {
s1 = s1.Union(s2);
return true;
},
[](const auto &, const auto &) { return false; },
},
return common::visit(common::visitors{
[](SetOfChars &s1, const SetOfChars &s2) {
s1 = s1.Union(s2);
return true;
},
[](const auto &, const auto &) { return false; },
},
u_, that.u_);
}
@ -141,7 +141,7 @@ bool Message::SortBefore(const Message &that) const {
// free and needs to be deferred, and many messages created during parsing
// are speculative. Messages with ProvenanceRange locations are ordered
// before others for sorting.
return std::visit(
return common::visit(
common::visitors{
[](CharBlock cb1, CharBlock cb2) {
return cb1.begin() < cb2.begin();
@ -158,7 +158,7 @@ bool Message::SortBefore(const Message &that) const {
bool Message::IsFatal() const { return severity() == Severity::Error; }
Severity Message::severity() const {
return std::visit(
return common::visit(
common::visitors{
[](const MessageExpectedText &) { return Severity::Error; },
[](const MessageFixedText &x) { return x.severity(); },
@ -168,7 +168,7 @@ Severity Message::severity() const {
}
Message &Message::set_severity(Severity severity) {
std::visit(
common::visit(
common::visitors{
[](const MessageExpectedText &) {},
[severity](MessageFixedText &x) { x.set_severity(severity); },
@ -179,7 +179,7 @@ Message &Message::set_severity(Severity severity) {
}
std::string Message::ToString() const {
return std::visit(
return common::visit(
common::visitors{
[](const MessageFixedText &t) {
return t.text().NULTerminatedToString();
@ -204,7 +204,7 @@ void Message::ResolveProvenances(const AllCookedSources &allCooked) {
std::optional<ProvenanceRange> Message::GetProvenanceRange(
const AllCookedSources &allCooked) const {
return std::visit(
return common::visit(
common::visitors{
[&](CharBlock cb) { return allCooked.GetProvenanceRange(cb); },
[](const ProvenanceRange &pr) { return std::make_optional(pr); },
@ -271,7 +271,7 @@ bool Message::Merge(const Message &that) {
return AtSameLocation(that) &&
(!that.attachment_.get() ||
attachment_.get() == that.attachment_.get()) &&
std::visit(
common::visit(
common::visitors{
[](MessageExpectedText &e1, const MessageExpectedText &e2) {
return e1.Merge(e2);
@ -299,7 +299,7 @@ Message &Message::Attach(std::unique_ptr<Message> &&m) {
}
bool Message::AtSameLocation(const Message &that) const {
return std::visit(
return common::visit(
common::visitors{
[](CharBlock cb1, CharBlock cb2) {
return cb1.begin() == cb2.begin();

View File

@ -32,7 +32,7 @@ CommonStmt::CommonStmt(std::optional<Name> &&name,
// R901 designator
bool Designator::EndsInBareName() const {
return std::visit(
return common::visit(
common::visitors{
[](const DataRef &dr) {
return std::holds_alternative<Name>(dr.u) ||
@ -120,11 +120,11 @@ template <typename T> T WithSource(CharBlock source, T &&x) {
}
static Expr ActualArgToExpr(ActualArgSpec &arg) {
return std::visit(
return common::visit(
common::visitors{
[&](common::Indirection<Expr> &y) { return std::move(y.value()); },
[&](common::Indirection<Variable> &y) {
return std::visit(
return common::visit(
common::visitors{
[&](common::Indirection<Designator> &z) {
return WithSource(
@ -147,7 +147,7 @@ Designator FunctionReference::ConvertToArrayElementRef() {
for (auto &arg : std::get<std::list<ActualArgSpec>>(v.t)) {
args.emplace_back(ActualArgToExpr(arg));
}
return std::visit(
return common::visit(
common::visitors{
[&](const Name &name) {
return WithSource(
@ -231,7 +231,7 @@ Statement<ActionStmt> StmtFunctionStmt::ConvertToAssignment() {
}
CharBlock Variable::GetSource() const {
return std::visit(
return common::visit(
common::visitors{
[&](const common::Indirection<Designator> &des) {
return des.value().source;

View File

@ -232,7 +232,7 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
}
CHECK(IsValid(*range));
const Origin &origin{MapToOrigin(range->start())};
std::visit(
common::visit(
common::visitors{
[&](const Inclusion &inc) {
o << inc.source.path();
@ -294,23 +294,24 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
const SourceFile *AllSources::GetSourceFile(
Provenance at, std::size_t *offset) const {
const Origin &origin{MapToOrigin(at)};
return std::visit(common::visitors{
[&](const Inclusion &inc) {
if (offset) {
*offset = origin.covers.MemberOffset(at);
}
return &inc.source;
},
[&](const Macro &) {
return GetSourceFile(origin.replaces.start(), offset);
},
[offset](const CompilerInsertion &) {
if (offset) {
*offset = 0;
}
return static_cast<const SourceFile *>(nullptr);
},
},
return common::visit(common::visitors{
[&](const Inclusion &inc) {
if (offset) {
*offset = origin.covers.MemberOffset(at);
}
return &inc.source;
},
[&](const Macro &) {
return GetSourceFile(
origin.replaces.start(), offset);
},
[offset](const CompilerInsertion &) {
if (offset) {
*offset = 0;
}
return static_cast<const SourceFile *>(nullptr);
},
},
origin.u);
}
@ -325,7 +326,7 @@ const char *AllSources::GetSource(ProvenanceRange range) const {
std::optional<SourcePosition> AllSources::GetSourcePosition(
Provenance prov) const {
const Origin &origin{MapToOrigin(prov)};
return std::visit(
return common::visit(
common::visitors{
[&](const Inclusion &inc) -> std::optional<SourcePosition> {
std::size_t offset{origin.covers.MemberOffset(prov)};
@ -400,7 +401,7 @@ AllSources::Origin::Origin(ProvenanceRange r, const std::string &text)
: u{CompilerInsertion{text}}, covers{r} {}
const char &AllSources::Origin::operator[](std::size_t n) const {
return std::visit(
return common::visit(
common::visitors{
[n](const Inclusion &inc) -> const char & {
return inc.source.content()[n];
@ -511,23 +512,23 @@ llvm::raw_ostream &AllSources::Dump(llvm::raw_ostream &o) const {
o << " ";
DumpRange(o, m.covers);
o << " -> ";
std::visit(common::visitors{
[&](const Inclusion &inc) {
if (inc.isModule) {
o << "module ";
}
o << "file " << inc.source.path();
},
[&](const Macro &mac) { o << "macro " << mac.expansion; },
[&](const CompilerInsertion &ins) {
o << "compiler '" << ins.text << '\'';
if (ins.text.length() == 1) {
int ch = ins.text[0];
o << "(0x";
o.write_hex(ch & 0xff) << ")";
}
},
},
common::visit(common::visitors{
[&](const Inclusion &inc) {
if (inc.isModule) {
o << "module ";
}
o << "file " << inc.source.path();
},
[&](const Macro &mac) { o << "macro " << mac.expansion; },
[&](const CompilerInsertion &ins) {
o << "compiler '" << ins.text << '\'';
if (ins.text.length() == 1) {
int ch = ins.text[0];
o << "(0x";
o.write_hex(ch & 0xff) << ")";
}
},
},
m.u);
if (IsValid(m.replaces)) {
o << " replaces ";

View File

@ -17,7 +17,7 @@ const Name &GetLastName(const StructureComponent &x) {
}
const Name &GetLastName(const DataRef &x) {
return std::visit(
return common::visit(
common::visitors{
[](const Name &name) -> const Name & { return name; },
[](const common::Indirection<StructureComponent> &sc)
@ -36,7 +36,7 @@ const Name &GetLastName(const Substring &x) {
}
const Name &GetLastName(const Designator &x) {
return std::visit(
return common::visit(
[](const auto &y) -> const Name & { return GetLastName(y); }, x.u);
}
@ -45,7 +45,7 @@ const Name &GetLastName(const ProcComponentRef &x) {
}
const Name &GetLastName(const ProcedureDesignator &x) {
return std::visit(
return common::visit(
[](const auto &y) -> const Name & { return GetLastName(y); }, x.u);
}
@ -56,7 +56,7 @@ const Name &GetLastName(const Call &x) {
const Name &GetLastName(const FunctionReference &x) { return GetLastName(x.v); }
const Name &GetLastName(const Variable &x) {
return std::visit(
return common::visit(
[](const auto &indirection) -> const Name & {
return GetLastName(indirection.value());
},
@ -64,7 +64,7 @@ const Name &GetLastName(const Variable &x) {
}
const Name &GetLastName(const AllocateObject &x) {
return std::visit(
return common::visit(
[](const auto &y) -> const Name & { return GetLastName(y); }, x.u);
}
@ -75,7 +75,7 @@ const Name &GetFirstName(const StructureComponent &x) {
}
const Name &GetFirstName(const DataRef &x) {
return std::visit(
return common::visit(
common::visitors{
[](const Name &name) -> const Name & { return name; },
[](const common::Indirection<StructureComponent> &sc)
@ -94,7 +94,7 @@ const Name &GetFirstName(const Substring &x) {
}
const Name &GetFirstName(const Designator &x) {
return std::visit(
return common::visit(
[](const auto &y) -> const Name & { return GetFirstName(y); }, x.u);
}
@ -103,7 +103,7 @@ const Name &GetFirstName(const ProcComponentRef &x) {
}
const Name &GetFirstName(const ProcedureDesignator &x) {
return std::visit(
return common::visit(
[](const auto &y) -> const Name & { return GetFirstName(y); }, x.u);
}
@ -116,7 +116,7 @@ const Name &GetFirstName(const FunctionReference &x) {
}
const Name &GetFirstName(const Variable &x) {
return std::visit(
return common::visit(
[](const auto &indirect) -> const Name & {
return GetFirstName(indirect.value());
},
@ -124,7 +124,7 @@ const Name &GetFirstName(const Variable &x) {
}
const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &base) {
return std::visit(
return common::visit(
common::visitors{
[](const Name &) -> const CoindexedNamedObject * { return nullptr; },
[](const common::Indirection<CoindexedNamedObject> &x)
@ -137,19 +137,19 @@ const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &base) {
}
const CoindexedNamedObject *GetCoindexedNamedObject(
const Designator &designator) {
return std::visit(common::visitors{
[](const DataRef &x) -> const CoindexedNamedObject * {
return GetCoindexedNamedObject(x);
},
[](const Substring &x) -> const CoindexedNamedObject * {
return GetCoindexedNamedObject(
std::get<DataRef>(x.t));
},
},
return common::visit(
common::visitors{
[](const DataRef &x) -> const CoindexedNamedObject * {
return GetCoindexedNamedObject(x);
},
[](const Substring &x) -> const CoindexedNamedObject * {
return GetCoindexedNamedObject(std::get<DataRef>(x.t));
},
},
designator.u);
}
const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &variable) {
return std::visit(
return common::visit(
common::visitors{
[](const common::Indirection<Designator> &designator)
-> const CoindexedNamedObject * {
@ -161,7 +161,7 @@ const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &variable) {
}
const CoindexedNamedObject *GetCoindexedNamedObject(
const AllocateObject &allocateObject) {
return std::visit(
return common::visit(
common::visitors{
[](const StructureComponent &x) -> const CoindexedNamedObject * {
return GetCoindexedNamedObject(x.base);

View File

@ -165,7 +165,7 @@ public:
Word("INTEGER");
}
void Unparse(const KindSelector &x) { // R706
std::visit(
common::visit(
common::visitors{
[&](const ScalarIntConstantExpr &y) {
Put('('), Word("KIND="), Walk(y), Put(')');
@ -196,16 +196,16 @@ public:
Walk(", LEN=", x.length), Put(')');
}
void Unparse(const LengthSelector &x) { // R722
std::visit(common::visitors{
[&](const TypeParamValue &y) {
Put('('), Word("LEN="), Walk(y), Put(')');
},
[&](const CharLength &y) { Put('*'), Walk(y); },
},
common::visit(common::visitors{
[&](const TypeParamValue &y) {
Put('('), Word("LEN="), Walk(y), Put(')');
},
[&](const CharLength &y) { Put('*'), Walk(y); },
},
x.u);
}
void Unparse(const CharLength &x) { // R723
std::visit(
common::visit(
common::visitors{
[&](const TypeParamValue &y) { Put('('), Walk(y), Put(')'); },
[&](const std::int64_t &y) { Walk(y); },
@ -271,7 +271,7 @@ public:
(!std::holds_alternative<DeclarationTypeSpec::Record>(dts.u) &&
std::none_of(
decls.begin(), decls.end(), [](const ComponentOrFill &c) {
return std::visit(
return common::visit(
common::visitors{
[](const ComponentDecl &d) {
const auto &init{
@ -295,19 +295,19 @@ public:
void Unparse(const Pointer &) { Word("POINTER"); }
void Unparse(const Contiguous &) { Word("CONTIGUOUS"); }
void Before(const ComponentAttrSpec &x) {
std::visit(common::visitors{
[&](const CoarraySpec &) { Word("CODIMENSION["); },
[&](const ComponentArraySpec &) { Word("DIMENSION("); },
[](const auto &) {},
},
common::visit(common::visitors{
[&](const CoarraySpec &) { Word("CODIMENSION["); },
[&](const ComponentArraySpec &) { Word("DIMENSION("); },
[](const auto &) {},
},
x.u);
}
void Post(const ComponentAttrSpec &x) {
std::visit(common::visitors{
[&](const CoarraySpec &) { Put(']'); },
[&](const ComponentArraySpec &) { Put(')'); },
[](const auto &) {},
},
common::visit(common::visitors{
[&](const CoarraySpec &) { Put(']'); },
[&](const ComponentArraySpec &) { Put(')'); },
[](const auto &) {},
},
x.u);
}
void Unparse(const ComponentDecl &x) { // R739
@ -323,10 +323,11 @@ public:
Walk("*", std::get<std::optional<CharLength>>(x.t));
}
void Unparse(const ComponentArraySpec &x) { // R740
std::visit(common::visitors{
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
[&](const DeferredShapeSpecList &y) { Walk(y); },
},
common::visit(
common::visitors{
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
[&](const DeferredShapeSpecList &y) { Walk(y); },
},
x.u);
}
void Unparse(const ProcComponentDefStmt &x) { // R741
@ -340,14 +341,15 @@ public:
}
void Unparse(const Pass &x) { Word("PASS"), Walk("(", x.v, ")"); }
void Unparse(const Initialization &x) { // R743 & R805
std::visit(common::visitors{
[&](const ConstantExpr &y) { Put(" = "), Walk(y); },
[&](const NullInit &y) { Put(" => "), Walk(y); },
[&](const InitialDataTarget &y) { Put(" => "), Walk(y); },
[&](const std::list<common::Indirection<DataStmtValue>> &y) {
Walk("/", y, ", ", "/");
},
},
common::visit(
common::visitors{
[&](const ConstantExpr &y) { Put(" = "), Walk(y); },
[&](const NullInit &y) { Put(" => "), Walk(y); },
[&](const InitialDataTarget &y) { Put(" => "), Walk(y); },
[&](const std::list<common::Indirection<DataStmtValue>> &y) {
Walk("/", y, ", ", "/");
},
},
x.u);
}
void Unparse(const PrivateStmt &) { // R745
@ -487,19 +489,19 @@ public:
Put(' '), Walk(std::get<std::list<EntityDecl>>(x.t), ", ");
}
void Before(const AttrSpec &x) { // R802
std::visit(common::visitors{
[&](const CoarraySpec &) { Word("CODIMENSION["); },
[&](const ArraySpec &) { Word("DIMENSION("); },
[](const auto &) {},
},
common::visit(common::visitors{
[&](const CoarraySpec &) { Word("CODIMENSION["); },
[&](const ArraySpec &) { Word("DIMENSION("); },
[](const auto &) {},
},
x.u);
}
void Post(const AttrSpec &x) {
std::visit(common::visitors{
[&](const CoarraySpec &) { Put(']'); },
[&](const ArraySpec &) { Put(')'); },
[](const auto &) {},
},
common::visit(common::visitors{
[&](const CoarraySpec &) { Put(']'); },
[&](const ArraySpec &) { Put(')'); },
[](const auto &) {},
},
x.u);
}
void Unparse(const EntityDecl &x) { // R803
@ -516,10 +518,10 @@ public:
Word("BIND(C"), Walk(", NAME=", x.v), Put(')');
}
void Unparse(const CoarraySpec &x) { // R809
std::visit(common::visitors{
[&](const DeferredCoshapeSpecList &y) { Walk(y); },
[&](const ExplicitCoshapeSpec &y) { Walk(y); },
},
common::visit(common::visitors{
[&](const DeferredCoshapeSpecList &y) { Walk(y); },
[&](const ExplicitCoshapeSpec &y) { Walk(y); },
},
x.u);
}
void Unparse(const DeferredCoshapeSpecList &x) { // R810
@ -539,14 +541,15 @@ public:
Walk(std::get<SpecificationExpr>(x.t));
}
void Unparse(const ArraySpec &x) { // R815
std::visit(common::visitors{
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
[&](const std::list<AssumedShapeSpec> &y) { Walk(y, ","); },
[&](const DeferredShapeSpecList &y) { Walk(y); },
[&](const AssumedSizeSpec &y) { Walk(y); },
[&](const ImpliedShapeSpec &y) { Walk(y); },
[&](const AssumedRankSpec &y) { Walk(y); },
},
common::visit(
common::visitors{
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
[&](const std::list<AssumedShapeSpec> &y) { Walk(y, ","); },
[&](const DeferredShapeSpecList &y) { Walk(y); },
[&](const AssumedSizeSpec &y) { Walk(y); },
[&](const ImpliedShapeSpec &y) { Walk(y); },
[&](const AssumedRankSpec &y) { Walk(y); },
},
x.u);
}
void Post(const AssumedShapeSpec &) { Put(':'); } // R819
@ -681,12 +684,13 @@ public:
}
void Unparse(const ImplicitStmt &x) { // R863
Word("IMPLICIT ");
std::visit(common::visitors{
[&](const std::list<ImplicitSpec> &y) { Walk(y, ", "); },
[&](const std::list<ImplicitStmt::ImplicitNoneNameSpec> &y) {
Word("NONE"), Walk(" (", y, ", ", ")");
},
},
common::visit(
common::visitors{
[&](const std::list<ImplicitSpec> &y) { Walk(y, ", "); },
[&](const std::list<ImplicitStmt::ImplicitNoneNameSpec> &y) {
Word("NONE"), Walk(" (", y, ", ", ")");
},
},
x.u);
}
void Unparse(const ImplicitSpec &x) { // R864
@ -800,11 +804,11 @@ public:
Walk(", ", std::get<std::list<AllocOpt>>(x.t), ", "), Put(')');
}
void Before(const AllocOpt &x) { // R928, R931
std::visit(common::visitors{
[&](const AllocOpt::Mold &) { Word("MOLD="); },
[&](const AllocOpt::Source &) { Word("SOURCE="); },
[](const StatOrErrmsg &) {},
},
common::visit(common::visitors{
[&](const AllocOpt::Mold &) { Word("MOLD="); },
[&](const AllocOpt::Source &) { Word("SOURCE="); },
[](const StatOrErrmsg &) {},
},
x.u);
}
void Unparse(const Allocation &x) { // R932
@ -829,10 +833,10 @@ public:
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
}
void Before(const StatOrErrmsg &x) { // R942 & R1165
std::visit(common::visitors{
[&](const StatVariable &) { Word("STAT="); },
[&](const MsgVariable &) { Word("ERRMSG="); },
},
common::visit(common::visitors{
[&](const StatVariable &) { Word("STAT="); },
[&](const MsgVariable &) { Word("ERRMSG="); },
},
x.u);
}
@ -887,7 +891,7 @@ public:
Put('\n');
} else {
Walk(std::get<DataRef>(x.t));
std::visit(
common::visit(
common::visitors{
[&](const std::list<BoundsRemapping> &y) {
Put('('), Walk(y), Put(')');
@ -991,12 +995,12 @@ public:
Word("DO "), Walk(std::get<std::optional<LoopControl>>(x.t));
}
void Unparse(const LoopControl &x) { // R1123
std::visit(common::visitors{
[&](const ScalarLogicalExpr &y) {
Word("WHILE ("), Walk(y), Put(')');
},
[&](const auto &y) { Walk(y); },
},
common::visit(common::visitors{
[&](const ScalarLogicalExpr &y) {
Word("WHILE ("), Walk(y), Put(')');
},
[&](const auto &y) { Walk(y); },
},
x.u);
}
void Unparse(const ConcurrentHeader &x) { // R1125
@ -1060,12 +1064,12 @@ public:
Outdent(), Word("END SELECT"), Walk(" ", x.v);
}
void Unparse(const CaseSelector &x) { // R1145
std::visit(common::visitors{
[&](const std::list<CaseValueRange> &y) {
Put('('), Walk(y), Put(')');
},
[&](const Default &) { Word("DEFAULT"); },
},
common::visit(common::visitors{
[&](const std::list<CaseValueRange> &y) {
Put('('), Walk(y), Put(')');
},
[&](const Default &) { Word("DEFAULT"); },
},
x.u);
}
void Unparse(const CaseValueRange::Range &x) { // R1146
@ -1078,13 +1082,13 @@ public:
}
void Unparse(const SelectRankCaseStmt &x) { // R1150
Outdent(), Word("RANK ");
std::visit(common::visitors{
[&](const ScalarIntConstantExpr &y) {
Put('('), Walk(y), Put(')');
},
[&](const Star &) { Put("(*)"); },
[&](const Default &) { Word("DEFAULT"); },
},
common::visit(common::visitors{
[&](const ScalarIntConstantExpr &y) {
Put('('), Walk(y), Put(')');
},
[&](const Star &) { Put("(*)"); },
[&](const Default &) { Word("DEFAULT"); },
},
std::get<SelectRankCaseStmt::Rank>(x.t).u);
Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
}
@ -1098,7 +1102,7 @@ public:
Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
}
void Unparse(const TypeGuardStmt::Guard &x) {
std::visit(
common::visit(
common::visitors{
[&](const TypeSpec &y) { Word("TYPE IS ("), Walk(y), Put(')'); },
[&](const DerivedTypeSpec &y) {
@ -1150,10 +1154,10 @@ public:
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
}
void Before(const EventWaitStmt::EventWaitSpec &x) { // R1173, R1174
std::visit(common::visitors{
[&](const ScalarIntExpr &) { Word("UNTIL_COUNT="); },
[](const StatOrErrmsg &) {},
},
common::visit(common::visitors{
[&](const ScalarIntExpr &) { Word("UNTIL_COUNT="); },
[](const StatOrErrmsg &) {},
},
x.u);
}
void Unparse(const EventWaitStmt &x) { // R1170
@ -1168,10 +1172,10 @@ public:
Put(')');
}
void Before(const FormTeamStmt::FormTeamSpec &x) { // R1176, R1178
std::visit(common::visitors{
[&](const ScalarIntExpr &) { Word("NEW_INDEX="); },
[](const StatOrErrmsg &) {},
},
common::visit(common::visitors{
[&](const ScalarIntExpr &) { Word("NEW_INDEX="); },
[](const StatOrErrmsg &) {},
},
x.u);
}
void Unparse(const LockStmt &x) { // R1179
@ -1180,7 +1184,7 @@ public:
Put(')');
}
void Before(const LockStmt::LockStat &x) { // R1180
std::visit(
common::visit(
common::visitors{
[&](const ScalarLogicalVariable &) { Word("ACQUIRED_LOCK="); },
[](const StatOrErrmsg &) {},
@ -1197,57 +1201,57 @@ public:
Word("OPEN ("), Walk(x.v, ", "), Put(')');
}
bool Pre(const ConnectSpec &x) { // R1205
return std::visit(common::visitors{
[&](const FileUnitNumber &) {
Word("UNIT=");
return true;
},
[&](const FileNameExpr &) {
Word("FILE=");
return true;
},
[&](const ConnectSpec::CharExpr &y) {
Walk(y.t, "=");
return false;
},
[&](const MsgVariable &) {
Word("IOMSG=");
return true;
},
[&](const StatVariable &) {
Word("IOSTAT=");
return true;
},
[&](const ConnectSpec::Recl &) {
Word("RECL=");
return true;
},
[&](const ConnectSpec::Newunit &) {
Word("NEWUNIT=");
return true;
},
[&](const ErrLabel &) {
Word("ERR=");
return true;
},
[&](const StatusExpr &) {
Word("STATUS=");
return true;
},
},
return common::visit(common::visitors{
[&](const FileUnitNumber &) {
Word("UNIT=");
return true;
},
[&](const FileNameExpr &) {
Word("FILE=");
return true;
},
[&](const ConnectSpec::CharExpr &y) {
Walk(y.t, "=");
return false;
},
[&](const MsgVariable &) {
Word("IOMSG=");
return true;
},
[&](const StatVariable &) {
Word("IOSTAT=");
return true;
},
[&](const ConnectSpec::Recl &) {
Word("RECL=");
return true;
},
[&](const ConnectSpec::Newunit &) {
Word("NEWUNIT=");
return true;
},
[&](const ErrLabel &) {
Word("ERR=");
return true;
},
[&](const StatusExpr &) {
Word("STATUS=");
return true;
},
},
x.u);
}
void Unparse(const CloseStmt &x) { // R1208
Word("CLOSE ("), Walk(x.v, ", "), Put(')');
}
void Before(const CloseStmt::CloseSpec &x) { // R1209
std::visit(common::visitors{
[&](const FileUnitNumber &) { Word("UNIT="); },
[&](const StatVariable &) { Word("IOSTAT="); },
[&](const MsgVariable &) { Word("IOMSG="); },
[&](const ErrLabel &) { Word("ERR="); },
[&](const StatusExpr &) { Word("STATUS="); },
},
common::visit(common::visitors{
[&](const FileUnitNumber &) { Word("UNIT="); },
[&](const StatVariable &) { Word("IOSTAT="); },
[&](const MsgVariable &) { Word("IOMSG="); },
[&](const ErrLabel &) { Word("ERR="); },
[&](const StatusExpr &) { Word("STATUS="); },
},
x.u);
}
void Unparse(const ReadStmt &x) { // R1210
@ -1287,64 +1291,64 @@ public:
Walk(", ", std::get<std::list<OutputItem>>(x.t), ", ");
}
bool Pre(const IoControlSpec &x) { // R1213
return std::visit(common::visitors{
[&](const IoUnit &) {
Word("UNIT=");
return true;
},
[&](const Format &) {
Word("FMT=");
return true;
},
[&](const Name &) {
Word("NML=");
return true;
},
[&](const IoControlSpec::CharExpr &y) {
Walk(y.t, "=");
return false;
},
[&](const IoControlSpec::Asynchronous &) {
Word("ASYNCHRONOUS=");
return true;
},
[&](const EndLabel &) {
Word("END=");
return true;
},
[&](const EorLabel &) {
Word("EOR=");
return true;
},
[&](const ErrLabel &) {
Word("ERR=");
return true;
},
[&](const IdVariable &) {
Word("ID=");
return true;
},
[&](const MsgVariable &) {
Word("IOMSG=");
return true;
},
[&](const StatVariable &) {
Word("IOSTAT=");
return true;
},
[&](const IoControlSpec::Pos &) {
Word("POS=");
return true;
},
[&](const IoControlSpec::Rec &) {
Word("REC=");
return true;
},
[&](const IoControlSpec::Size &) {
Word("SIZE=");
return true;
},
},
return common::visit(common::visitors{
[&](const IoUnit &) {
Word("UNIT=");
return true;
},
[&](const Format &) {
Word("FMT=");
return true;
},
[&](const Name &) {
Word("NML=");
return true;
},
[&](const IoControlSpec::CharExpr &y) {
Walk(y.t, "=");
return false;
},
[&](const IoControlSpec::Asynchronous &) {
Word("ASYNCHRONOUS=");
return true;
},
[&](const EndLabel &) {
Word("END=");
return true;
},
[&](const EorLabel &) {
Word("EOR=");
return true;
},
[&](const ErrLabel &) {
Word("ERR=");
return true;
},
[&](const IdVariable &) {
Word("ID=");
return true;
},
[&](const MsgVariable &) {
Word("IOMSG=");
return true;
},
[&](const StatVariable &) {
Word("IOSTAT=");
return true;
},
[&](const IoControlSpec::Pos &) {
Word("POS=");
return true;
},
[&](const IoControlSpec::Rec &) {
Word("REC=");
return true;
},
[&](const IoControlSpec::Size &) {
Word("SIZE=");
return true;
},
},
x.u);
}
void Unparse(const InputImpliedDo &x) { // R1218
@ -1359,15 +1363,15 @@ public:
Word("WAIT ("), Walk(x.v, ", "), Put(')');
}
void Before(const WaitSpec &x) { // R1223
std::visit(common::visitors{
[&](const FileUnitNumber &) { Word("UNIT="); },
[&](const EndLabel &) { Word("END="); },
[&](const EorLabel &) { Word("EOR="); },
[&](const ErrLabel &) { Word("ERR="); },
[&](const IdExpr &) { Word("ID="); },
[&](const MsgVariable &) { Word("IOMSG="); },
[&](const StatVariable &) { Word("IOSTAT="); },
},
common::visit(common::visitors{
[&](const FileUnitNumber &) { Word("UNIT="); },
[&](const EndLabel &) { Word("END="); },
[&](const EorLabel &) { Word("EOR="); },
[&](const ErrLabel &) { Word("ERR="); },
[&](const IdExpr &) { Word("ID="); },
[&](const MsgVariable &) { Word("IOMSG="); },
[&](const StatVariable &) { Word("IOSTAT="); },
},
x.u);
}
void Unparse(const BackspaceStmt &x) { // R1224
@ -1380,12 +1384,12 @@ public:
Word("REWIND ("), Walk(x.v, ", "), Put(')');
}
void Before(const PositionOrFlushSpec &x) { // R1227 & R1229
std::visit(common::visitors{
[&](const FileUnitNumber &) { Word("UNIT="); },
[&](const MsgVariable &) { Word("IOMSG="); },
[&](const StatVariable &) { Word("IOSTAT="); },
[&](const ErrLabel &) { Word("ERR="); },
},
common::visit(common::visitors{
[&](const FileUnitNumber &) { Word("UNIT="); },
[&](const MsgVariable &) { Word("IOMSG="); },
[&](const StatVariable &) { Word("IOSTAT="); },
[&](const ErrLabel &) { Word("ERR="); },
},
x.u);
}
void Unparse(const FlushStmt &x) { // R1228
@ -1393,7 +1397,7 @@ public:
}
void Unparse(const InquireStmt &x) { // R1230
Word("INQUIRE (");
std::visit(
common::visit(
common::visitors{
[&](const InquireStmt::Iolength &y) {
Word("IOLENGTH="), Walk(y.t, ") ");
@ -1403,36 +1407,36 @@ public:
x.u);
}
bool Pre(const InquireSpec &x) { // R1231
return std::visit(common::visitors{
[&](const FileUnitNumber &) {
Word("UNIT=");
return true;
},
[&](const FileNameExpr &) {
Word("FILE=");
return true;
},
[&](const InquireSpec::CharVar &y) {
Walk(y.t, "=");
return false;
},
[&](const InquireSpec::IntVar &y) {
Walk(y.t, "=");
return false;
},
[&](const InquireSpec::LogVar &y) {
Walk(y.t, "=");
return false;
},
[&](const IdExpr &) {
Word("ID=");
return true;
},
[&](const ErrLabel &) {
Word("ERR=");
return true;
},
},
return common::visit(common::visitors{
[&](const FileUnitNumber &) {
Word("UNIT=");
return true;
},
[&](const FileNameExpr &) {
Word("FILE=");
return true;
},
[&](const InquireSpec::CharVar &y) {
Walk(y.t, "=");
return false;
},
[&](const InquireSpec::IntVar &y) {
Walk(y.t, "=");
return false;
},
[&](const InquireSpec::LogVar &y) {
Walk(y.t, "=");
return false;
},
[&](const IdExpr &) {
Word("ID=");
return true;
},
[&](const ErrLabel &) {
Word("ERR=");
return true;
},
},
x.u);
}
@ -1447,13 +1451,13 @@ public:
if (x.repeatCount) {
Walk(*x.repeatCount);
}
std::visit(common::visitors{
[&](const std::string &y) { PutNormalized(y); },
[&](const std::list<format::FormatItem> &y) {
Walk("(", y, ",", ")");
},
[&](const auto &y) { Walk(y); },
},
common::visit(common::visitors{
[&](const std::string &y) { PutNormalized(y); },
[&](const std::list<format::FormatItem> &y) {
Walk("(", y, ",", ")");
},
[&](const auto &y) { Walk(y); },
},
x.u);
}
void Unparse(
@ -1566,19 +1570,21 @@ public:
}
void Unparse(const UseStmt &x) { // R1409
Word("USE"), Walk(", ", x.nature), Put(" :: "), Walk(x.moduleName);
std::visit(common::visitors{
[&](const std::list<Rename> &y) { Walk(", ", y, ", "); },
[&](const std::list<Only> &y) { Walk(", ONLY: ", y, ", "); },
},
common::visit(
common::visitors{
[&](const std::list<Rename> &y) { Walk(", ", y, ", "); },
[&](const std::list<Only> &y) { Walk(", ONLY: ", y, ", "); },
},
x.u);
}
void Unparse(const Rename &x) { // R1411
std::visit(common::visitors{
[&](const Rename::Names &y) { Walk(y.t, " => "); },
[&](const Rename::Operators &y) {
Word("OPERATOR("), Walk(y.t, ") => OPERATOR("), Put(")");
},
},
common::visit(common::visitors{
[&](const Rename::Names &y) { Walk(y.t, " => "); },
[&](const Rename::Operators &y) {
Word("OPERATOR("), Walk(y.t, ") => OPERATOR("),
Put(")");
},
},
x.u);
}
void Unparse(const SubmoduleStmt &x) { // R1417
@ -1598,12 +1604,12 @@ public:
}
void Unparse(const InterfaceStmt &x) { // R1503
std::visit(common::visitors{
[&](const std::optional<GenericSpec> &y) {
Word("INTERFACE"), Walk(" ", y);
},
[&](const Abstract &) { Word("ABSTRACT INTERFACE"); },
},
common::visit(common::visitors{
[&](const std::optional<GenericSpec> &y) {
Word("INTERFACE"), Walk(" ", y);
},
[&](const Abstract &) { Word("ABSTRACT INTERFACE"); },
},
x.u);
Indent();
}
@ -1619,7 +1625,7 @@ public:
Walk(std::get<std::list<Name>>(x.t), ", ");
}
void Before(const GenericSpec &x) { // R1508, R1509
std::visit(
common::visit(
common::visitors{
[&](const DefinedOperator &) { Word("OPERATOR("); },
[&](const GenericSpec::Assignment &) { Word("ASSIGNMENT(=)"); },
@ -1640,10 +1646,10 @@ public:
x.u);
}
void Post(const GenericSpec &x) {
std::visit(common::visitors{
[&](const DefinedOperator &) { Put(')'); },
[](const auto &) {},
},
common::visit(common::visitors{
[&](const DefinedOperator &) { Put(')'); },
[](const auto &) {},
},
x.u);
}
void Unparse(const GenericStmt &x) { // R1510
@ -1767,7 +1773,7 @@ public:
// Directives, extensions, and deprecated constructs
void Unparse(const CompilerDirective &x) {
std::visit(
common::visit(
common::visitors{
[&](const std::list<CompilerDirective::IgnoreTKR> &tkr) {
Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty
@ -1852,12 +1858,12 @@ public:
Word(AccDataModifier::EnumToString(x));
}
void Unparse(const AccBindClause &x) {
std::visit(common::visitors{
[&](const Name &y) { Put('('), Walk(y), Put(')'); },
[&](const ScalarDefaultCharExpr &y) {
Put('('), Walk(y), Put(')');
},
},
common::visit(common::visitors{
[&](const Name &y) { Put('('), Walk(y), Put(')'); },
[&](const ScalarDefaultCharExpr &y) {
Put('('), Walk(y), Put(')');
},
},
x.u);
}
void Unparse(const AccDefaultClause &x) {
@ -1937,10 +1943,10 @@ public:
EndOpenACC();
}
void Unparse(const AccObject &x) {
std::visit(common::visitors{
[&](const Designator &y) { Walk(y); },
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
},
common::visit(common::visitors{
[&](const Designator &y) { Walk(y); },
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
},
x.u);
}
void Unparse(const AccObjectList &x) { Walk(x.v, ","); }
@ -1978,10 +1984,10 @@ public:
// OpenMP Clauses & Directives
void Unparse(const OmpObject &x) {
std::visit(common::visitors{
[&](const Designator &y) { Walk(y); },
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
},
common::visit(common::visitors{
[&](const Designator &y) { Walk(y); },
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
},
x.u);
}
void Unparse(const OmpMapType::Always &) { Word("ALWAYS,"); }
@ -2040,19 +2046,20 @@ public:
Put(")");
}
bool Pre(const OmpDependClause &x) {
return std::visit(common::visitors{
[&](const OmpDependClause::Source &) {
Word("SOURCE");
return false;
},
[&](const OmpDependClause::Sink &y) {
Word("SINK:");
Walk(y.v);
Put(")");
return false;
},
[&](const OmpDependClause::InOut &) { return true; },
},
return common::visit(
common::visitors{
[&](const OmpDependClause::Source &) {
Word("SOURCE");
return false;
},
[&](const OmpDependClause::Sink &y) {
Word("SINK:");
Walk(y.v);
Put(")");
return false;
},
[&](const OmpDependClause::InOut &) { return true; },
},
x.u);
}
void Unparse(const OmpDefaultmapClause &x) {
@ -2346,37 +2353,38 @@ public:
bool Pre(const OpenMPDeclarativeConstruct &x) {
BeginOpenMP();
Word("!$OMP ");
return std::visit(common::visitors{
[&](const OpenMPDeclarativeAllocate &z) {
Word("ALLOCATE (");
Walk(std::get<OmpObjectList>(z.t));
Put(")");
Walk(std::get<OmpClauseList>(z.t));
Put("\n");
EndOpenMP();
return false;
},
[&](const OpenMPDeclareReductionConstruct &) {
Word("DECLARE REDUCTION ");
return true;
},
[&](const OpenMPDeclareSimdConstruct &y) {
Word("DECLARE SIMD ");
Walk("(", std::get<std::optional<Name>>(y.t), ")");
Walk(std::get<OmpClauseList>(y.t));
Put("\n");
EndOpenMP();
return false;
},
[&](const OpenMPDeclareTargetConstruct &) {
Word("DECLARE TARGET ");
return true;
},
[&](const OpenMPThreadprivate &) {
Word("THREADPRIVATE (");
return true;
},
},
return common::visit(
common::visitors{
[&](const OpenMPDeclarativeAllocate &z) {
Word("ALLOCATE (");
Walk(std::get<OmpObjectList>(z.t));
Put(")");
Walk(std::get<OmpClauseList>(z.t));
Put("\n");
EndOpenMP();
return false;
},
[&](const OpenMPDeclareReductionConstruct &) {
Word("DECLARE REDUCTION ");
return true;
},
[&](const OpenMPDeclareSimdConstruct &y) {
Word("DECLARE SIMD ");
Walk("(", std::get<std::optional<Name>>(y.t), ")");
Walk(std::get<OmpClauseList>(y.t));
Put("\n");
EndOpenMP();
return false;
},
[&](const OpenMPDeclareTargetConstruct &) {
Word("DECLARE TARGET ");
return true;
},
[&](const OpenMPThreadprivate &) {
Word("THREADPRIVATE (");
return true;
},
},
x.u);
}
void Post(const OpenMPDeclarativeConstruct &) {
@ -2440,10 +2448,10 @@ public:
}
void Unparse(const OmpMemoryOrderClause &x) { Walk(x.v); }
void Unparse(const OmpAtomicClause &x) {
std::visit(common::visitors{
[&](const OmpMemoryOrderClause &y) { Walk(y); },
[&](const OmpClause &z) { Walk(z); },
},
common::visit(common::visitors{
[&](const OmpMemoryOrderClause &y) { Walk(y); },
[&](const OmpClause &z) { Walk(z); },
},
x.u);
}
void Unparse(const OpenMPFlushConstruct &x) {

View File

@ -24,7 +24,7 @@ public:
std::vector<LabelInfo> stack;
for (auto i{block.begin()}, end{block.end()}; i != end; ++i) {
if (auto *executableConstruct{std::get_if<ExecutableConstruct>(&i->u)}) {
std::visit(
common::visit(
common::visitors{
[](auto &) {},
// Labels on end-stmt of constructs are accepted by f18 as an

View File

@ -128,10 +128,10 @@ static std::optional<AllocateCheckerInfo> CheckAllocateOptions(
const parser::Expr *parserSourceExpr{nullptr};
for (const parser::AllocOpt &allocOpt :
std::get<std::list<parser::AllocOpt>>(allocateStmt.t)) {
std::visit(
common::visit(
common::visitors{
[&](const parser::StatOrErrmsg &statOrErr) {
std::visit(
common::visit(
common::visitors{
[&](const parser::StatVariable &) {
if (info.gotStat) { // C943

View File

@ -672,7 +672,7 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
}
auto restorer{
messages.SetLocation(arg.sourceLocation().value_or(messages.at()))};
std::visit(
common::visit(
common::visitors{
[&](const characteristics::DummyDataObject &object) {
ConvertBOZLiteralArg(arg, object.type.type());

View File

@ -43,7 +43,7 @@ private:
const auto &stmt{std::get<parser::Statement<parser::CaseStmt>>(c.t)};
const parser::CaseStmt &caseStmt{stmt.statement};
const auto &selector{std::get<parser::CaseSelector>(caseStmt.t)};
std::visit(
common::visit(
common::visitors{
[&](const std::list<parser::CaseValueRange> &ranges) {
for (const auto &range : ranges) {
@ -117,25 +117,26 @@ private:
using PairOfValues = std::pair<std::optional<Value>, std::optional<Value>>;
PairOfValues ComputeBounds(const parser::CaseValueRange &range) {
return std::visit(common::visitors{
[&](const parser::CaseValue &x) {
auto value{GetValue(x)};
return PairOfValues{value, value};
},
[&](const parser::CaseValueRange::Range &x) {
std::optional<Value> lo, hi;
if (x.lower) {
lo = GetValue(*x.lower);
}
if (x.upper) {
hi = GetValue(*x.upper);
}
if ((x.lower && !lo) || (x.upper && !hi)) {
return PairOfValues{}; // error case
}
return PairOfValues{std::move(lo), std::move(hi)};
},
},
return common::visit(
common::visitors{
[&](const parser::CaseValue &x) {
auto value{GetValue(x)};
return PairOfValues{value, value};
},
[&](const parser::CaseValueRange::Range &x) {
std::optional<Value> lo, hi;
if (x.lower) {
lo = GetValue(*x.lower);
}
if (x.upper) {
hi = GetValue(*x.upper);
}
if ((x.lower && !lo) || (x.upper && !hi)) {
return PairOfValues{}; // error case
}
return PairOfValues{std::move(lo), std::move(hi)};
},
},
range.u);
}

View File

@ -129,7 +129,7 @@ public:
bool operator()(const evaluate::Subscript &subs) {
DataVarChecker subscriptChecker{context_, source_};
subscriptChecker.RestrictPointer();
return std::visit(
return common::visit(
common::visitors{
[&](const evaluate::IndirectSubscriptIntegerExpr &expr) {
return CheckSubscriptExpr(expr);
@ -205,18 +205,19 @@ void DataChecker::Leave(const parser::DataIDoObject &object) {
}
void DataChecker::Leave(const parser::DataStmtObject &dataObject) {
std::visit(common::visitors{
[](const parser::DataImpliedDo &) { // has own Enter()/Leave()
},
[&](const auto &var) {
auto expr{exprAnalyzer_.Analyze(var)};
if (!expr ||
!DataVarChecker{exprAnalyzer_.context(),
parser::FindSourceLocation(dataObject)}(*expr)) {
currentSetHasFatalErrors_ = true;
}
},
},
common::visit(
common::visitors{
[](const parser::DataImpliedDo &) { // has own Enter()/Leave()
},
[&](const auto &var) {
auto expr{exprAnalyzer_.Analyze(var)};
if (!expr ||
!DataVarChecker{exprAnalyzer_.context(),
parser::FindSourceLocation(dataObject)}(*expr)) {
currentSetHasFatalErrors_ = true;
}
},
},
dataObject.u);
}

View File

@ -17,7 +17,7 @@ namespace Fortran::semantics {
void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
for (const parser::AllocateObject &allocateObject :
std::get<std::list<parser::AllocateObject>>(deallocateStmt.t)) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Name &name) {
auto const *symbol{name.symbol};
@ -50,7 +50,7 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
bool gotStat{false}, gotMsg{false};
for (const parser::StatOrErrmsg &deallocOpt :
std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t)) {
std::visit(
common::visit(
common::visitors{
[&](const parser::StatVariable &) {
if (gotStat) {

View File

@ -206,7 +206,7 @@ void CheckHelper::Check(const Symbol &symbol) {
const DeclTypeSpec *type{symbol.GetType()};
const DerivedTypeSpec *derived{type ? type->AsDerived() : nullptr};
bool isDone{false};
std::visit(
common::visit(
common::visitors{
[&](const UseDetails &x) { isDone = true; },
[&](const HostAssocDetails &x) {
@ -1145,17 +1145,17 @@ void CheckHelper::CheckHostAssoc(
void CheckHelper::CheckGeneric(
const Symbol &symbol, const GenericDetails &details) {
CheckSpecificsAreDistinguishable(symbol, details);
std::visit(common::visitors{
[&](const GenericKind::DefinedIo &io) {
CheckDefinedIoProc(symbol, details, io);
},
[&](const GenericKind::OtherKind &other) {
if (other == GenericKind::OtherKind::Name) {
CheckGenericVsIntrinsic(symbol, details);
}
},
[](const auto &) {},
},
common::visit(common::visitors{
[&](const GenericKind::DefinedIo &io) {
CheckDefinedIoProc(symbol, details, io);
},
[&](const GenericKind::OtherKind &other) {
if (other == GenericKind::OtherKind::Name) {
CheckGenericVsIntrinsic(symbol, details);
}
},
[](const auto &) {},
},
details.kind().u);
}
@ -1192,7 +1192,7 @@ static bool ConflictsWithIntrinsicOperator(
auto arg0{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
auto type0{arg0.type()};
if (proc.dummyArguments.size() == 1) { // unary
return std::visit(
return common::visit(
common::visitors{
[&](common::NumericOperator) { return IsIntrinsicNumeric(type0); },
[&](common::LogicalOperator) { return IsIntrinsicLogical(type0); },
@ -1204,7 +1204,7 @@ static bool ConflictsWithIntrinsicOperator(
auto arg1{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
auto type1{arg1.type()};
int rank1{arg1.Rank()};
return std::visit(
return common::visit(
common::visitors{
[&](common::NumericOperator) {
return IsIntrinsicNumeric(type0, rank0, type1, rank1);
@ -1268,27 +1268,27 @@ std::optional<parser::MessageFixedText> CheckHelper::CheckNumberOfArgs(
return std::nullopt;
}
std::size_t min{2}, max{2}; // allowed number of args; default is binary
std::visit(common::visitors{
[&](const common::NumericOperator &x) {
if (x == common::NumericOperator::Add ||
x == common::NumericOperator::Subtract) {
min = 1; // + and - are unary or binary
}
},
[&](const common::LogicalOperator &x) {
if (x == common::LogicalOperator::Not) {
min = 1; // .NOT. is unary
max = 1;
}
},
[](const common::RelationalOperator &) {
// all are binary
},
[](const GenericKind::OtherKind &x) {
CHECK(x == GenericKind::OtherKind::Concat);
},
[](const auto &) { DIE("expected intrinsic operator"); },
},
common::visit(common::visitors{
[&](const common::NumericOperator &x) {
if (x == common::NumericOperator::Add ||
x == common::NumericOperator::Subtract) {
min = 1; // + and - are unary or binary
}
},
[&](const common::LogicalOperator &x) {
if (x == common::LogicalOperator::Not) {
min = 1; // .NOT. is unary
max = 1;
}
},
[](const common::RelationalOperator &) {
// all are binary
},
[](const GenericKind::OtherKind &x) {
CHECK(x == GenericKind::OtherKind::Concat);
},
[](const auto &) { DIE("expected intrinsic operator"); },
},
kind.u);
if (nargs >= min && nargs <= max) {
return std::nullopt;
@ -2229,28 +2229,29 @@ void SubprogramMatchHelper::Check(
void SubprogramMatchHelper::CheckDummyArg(const Symbol &symbol1,
const Symbol &symbol2, const DummyArgument &arg1,
const DummyArgument &arg2) {
std::visit(common::visitors{
[&](const DummyDataObject &obj1, const DummyDataObject &obj2) {
CheckDummyDataObject(symbol1, symbol2, obj1, obj2);
},
[&](const DummyProcedure &proc1, const DummyProcedure &proc2) {
CheckDummyProcedure(symbol1, symbol2, proc1, proc2);
},
[&](const DummyDataObject &, const auto &) {
Say(symbol1, symbol2,
"Dummy argument '%s' is a data object; the corresponding"
" argument in the interface body is not"_err_en_US);
},
[&](const DummyProcedure &, const auto &) {
Say(symbol1, symbol2,
"Dummy argument '%s' is a procedure; the corresponding"
" argument in the interface body is not"_err_en_US);
},
[&](const auto &, const auto &) {
llvm_unreachable("Dummy arguments are not data objects or"
"procedures");
},
},
common::visit(
common::visitors{
[&](const DummyDataObject &obj1, const DummyDataObject &obj2) {
CheckDummyDataObject(symbol1, symbol2, obj1, obj2);
},
[&](const DummyProcedure &proc1, const DummyProcedure &proc2) {
CheckDummyProcedure(symbol1, symbol2, proc1, proc2);
},
[&](const DummyDataObject &, const auto &) {
Say(symbol1, symbol2,
"Dummy argument '%s' is a data object; the corresponding"
" argument in the interface body is not"_err_en_US);
},
[&](const DummyProcedure &, const auto &) {
Say(symbol1, symbol2,
"Dummy argument '%s' is a procedure; the corresponding"
" argument in the interface body is not"_err_en_US);
},
[&](const auto &, const auto &) {
llvm_unreachable("Dummy arguments are not data objects or"
"procedures");
},
},
arg1.u, arg2.u);
}

View File

@ -430,7 +430,7 @@ public:
}
void Check(const parser::ForallAssignmentStmt &stmt) {
const evaluate::Assignment *assignment{std::visit(
const evaluate::Assignment *assignment{common::visit(
common::visitors{[&](const auto &x) { return GetAssignment(x); }},
stmt.u)};
if (assignment) {
@ -441,23 +441,24 @@ public:
std::get_if<evaluate::ProcedureRef>(&assignment->u)}) {
CheckForImpureCall(*proc);
}
std::visit(common::visitors{
[](const evaluate::Assignment::Intrinsic &) {},
[&](const evaluate::ProcedureRef &proc) {
CheckForImpureCall(proc);
},
[&](const evaluate::Assignment::BoundsSpec &bounds) {
for (const auto &bound : bounds) {
CheckForImpureCall(SomeExpr{bound});
}
},
[&](const evaluate::Assignment::BoundsRemapping &bounds) {
for (const auto &bound : bounds) {
CheckForImpureCall(SomeExpr{bound.first});
CheckForImpureCall(SomeExpr{bound.second});
}
},
},
common::visit(
common::visitors{
[](const evaluate::Assignment::Intrinsic &) {},
[&](const evaluate::ProcedureRef &proc) {
CheckForImpureCall(proc);
},
[&](const evaluate::Assignment::BoundsSpec &bounds) {
for (const auto &bound : bounds) {
CheckForImpureCall(SomeExpr{bound});
}
},
[&](const evaluate::Assignment::BoundsRemapping &bounds) {
for (const auto &bound : bounds) {
CheckForImpureCall(SomeExpr{bound.first});
CheckForImpureCall(SomeExpr{bound.second});
}
},
},
assignment->u);
}
}
@ -737,7 +738,7 @@ private:
SymbolVector indexVars{context_.GetIndexVars(IndexVarKind::FORALL)};
if (!indexVars.empty()) {
UnorderedSymbolSet symbols{evaluate::CollectSymbols(assignment.lhs)};
std::visit(
common::visit(
common::visitors{
[&](const evaluate::Assignment::BoundsSpec &spec) {
for (const auto &bound : spec) {
@ -828,7 +829,7 @@ static parser::CharBlock GetConstructPosition(const A &a) {
}
static parser::CharBlock GetNodePosition(const ConstructNode &construct) {
return std::visit(
return common::visit(
[&](const auto &x) { return GetConstructPosition(*x); }, construct);
}
@ -859,24 +860,24 @@ static bool ConstructIsDoConcurrent(const ConstructNode &construct) {
// leave DO CONCURRENT, CRITICAL, or CHANGE TEAM constructs.
void DoForallChecker::CheckForBadLeave(
StmtType stmtType, const ConstructNode &construct) const {
std::visit(common::visitors{
[&](const parser::DoConstruct *doConstructPtr) {
if (doConstructPtr->IsDoConcurrent()) {
// C1135 and C1167 -- CYCLE and EXIT statements can't leave
// a DO CONCURRENT
SayBadLeave(stmtType, "DO CONCURRENT", construct);
}
},
[&](const parser::CriticalConstruct *) {
// C1135 and C1168 -- similarly, for CRITICAL
SayBadLeave(stmtType, "CRITICAL", construct);
},
[&](const parser::ChangeTeamConstruct *) {
// C1135 and C1168 -- similarly, for CHANGE TEAM
SayBadLeave(stmtType, "CHANGE TEAM", construct);
},
[](const auto *) {},
},
common::visit(common::visitors{
[&](const parser::DoConstruct *doConstructPtr) {
if (doConstructPtr->IsDoConcurrent()) {
// C1135 and C1167 -- CYCLE and EXIT statements can't
// leave a DO CONCURRENT
SayBadLeave(stmtType, "DO CONCURRENT", construct);
}
},
[&](const parser::CriticalConstruct *) {
// C1135 and C1168 -- similarly, for CRITICAL
SayBadLeave(stmtType, "CRITICAL", construct);
},
[&](const parser::ChangeTeamConstruct *) {
// C1135 and C1168 -- similarly, for CHANGE TEAM
SayBadLeave(stmtType, "CHANGE TEAM", construct);
},
[](const auto *) {},
},
construct);
}

View File

@ -204,7 +204,7 @@ void IoChecker::Enter(const parser::FileUnitNumber &) {
void IoChecker::Enter(const parser::Format &spec) {
SetSpecifier(IoSpecKind::Fmt);
flags_.set(Flag::FmtOrNml);
std::visit(
common::visit(
common::visitors{
[&](const parser::Label &) { flags_.set(Flag::LabelFmt); },
[&](const parser::Star &) { flags_.set(Flag::StarFmt); },

View File

@ -23,7 +23,7 @@ void NullifyChecker::Leave(const parser::NullifyStmt &nullifyStmt) {
parser::ContextualMessages messages{
*context_.location(), &context_.messages()};
for (const parser::PointerObject &pointerObject : nullifyStmt.v) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Name &name) {
const Symbol *symbol{name.symbol};

View File

@ -262,7 +262,7 @@ void OmpStructureChecker::CheckPredefinedAllocatorRestriction(
const parser::CharBlock &source,
const parser::OmpObjectList &ompObjectList) {
for (const auto &ompObject : ompObjectList.v) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &designator) {
if (const auto *dataRef{
@ -420,54 +420,55 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
// current context yet.
// TODO: Check for declare simd regions.
bool eligibleSIMD{false};
std::visit(Fortran::common::visitors{
// Allow `!$OMP ORDERED SIMD`
[&](const parser::OpenMPBlockConstruct &c) {
const auto &beginBlockDir{
std::get<parser::OmpBeginBlockDirective>(c.t)};
const auto &beginDir{
std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
if (beginDir.v == llvm::omp::Directive::OMPD_ordered) {
const auto &clauses{
std::get<parser::OmpClauseList>(beginBlockDir.t)};
for (const auto &clause : clauses.v) {
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
eligibleSIMD = true;
break;
}
}
}
},
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
const auto &dir{
std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
if (dir.v == llvm::omp::Directive::OMPD_ordered) {
const auto &clauses{std::get<parser::OmpClauseList>(c.t)};
for (const auto &clause : clauses.v) {
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
eligibleSIMD = true;
break;
}
}
}
},
// Allowing SIMD construct
[&](const parser::OpenMPLoopConstruct &c) {
const auto &beginLoopDir{
std::get<parser::OmpBeginLoopDirective>(c.t)};
const auto &beginDir{
std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
if ((beginDir.v == llvm::omp::Directive::OMPD_simd) ||
(beginDir.v == llvm::omp::Directive::OMPD_do_simd)) {
eligibleSIMD = true;
}
},
[&](const parser::OpenMPAtomicConstruct &c) {
// Allow `!$OMP ATOMIC`
eligibleSIMD = true;
},
[&](const auto &c) {},
},
common::visit(Fortran::common::visitors{
// Allow `!$OMP ORDERED SIMD`
[&](const parser::OpenMPBlockConstruct &c) {
const auto &beginBlockDir{
std::get<parser::OmpBeginBlockDirective>(c.t)};
const auto &beginDir{
std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
if (beginDir.v == llvm::omp::Directive::OMPD_ordered) {
const auto &clauses{
std::get<parser::OmpClauseList>(beginBlockDir.t)};
for (const auto &clause : clauses.v) {
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
eligibleSIMD = true;
break;
}
}
}
},
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
const auto &dir{
std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
if (dir.v == llvm::omp::Directive::OMPD_ordered) {
const auto &clauses{
std::get<parser::OmpClauseList>(c.t)};
for (const auto &clause : clauses.v) {
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
eligibleSIMD = true;
break;
}
}
}
},
// Allowing SIMD construct
[&](const parser::OpenMPLoopConstruct &c) {
const auto &beginLoopDir{
std::get<parser::OmpBeginLoopDirective>(c.t)};
const auto &beginDir{
std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
if ((beginDir.v == llvm::omp::Directive::OMPD_simd) ||
(beginDir.v == llvm::omp::Directive::OMPD_do_simd)) {
eligibleSIMD = true;
}
},
[&](const parser::OpenMPAtomicConstruct &c) {
// Allow `!$OMP ATOMIC`
eligibleSIMD = true;
},
[&](const auto &c) {},
},
c.u);
if (!eligibleSIMD) {
context_.Say(parser::FindSourceLocation(c),
@ -482,7 +483,7 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
// 2.12.5 Target Construct Restriction
bool eligibleTarget{true};
llvm::omp::Directive ineligibleTargetDir;
std::visit(
common::visit(
common::visitors{
[&](const parser::OpenMPBlockConstruct &c) {
const auto &beginBlockDir{
@ -495,7 +496,7 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
}
},
[&](const parser::OpenMPStandaloneConstruct &c) {
std::visit(
common::visit(
common::visitors{
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
const auto &dir{
@ -881,7 +882,7 @@ void OmpStructureChecker::Leave(const parser::OmpEndSectionsDirective &x) {
void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
const parser::OmpObjectList &objList) {
for (const auto &ompObject : objList.v) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &) {
if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
@ -1442,7 +1443,7 @@ void OmpStructureChecker::CheckAtomicUpdateAssignmentStmt(
const parser::AssignmentStmt &assignment) {
const auto &expr{std::get<parser::Expr>(assignment.t)};
const auto &var{std::get<parser::Variable>(assignment.t)};
std::visit(
common::visit(
common::visitors{
[&](const common::Indirection<parser::FunctionReference> &x) {
const auto &procedureDesignator{
@ -1542,7 +1543,7 @@ void OmpStructureChecker::CheckAtomicMemoryOrderClause(
}
void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
std::visit(
common::visit(
common::visitors{
[&](const parser::OmpAtomic &atomicConstruct) {
const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
@ -1704,7 +1705,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
if (!threadprivateAllowedSet.test(type)) {
if (const auto *objList{GetOmpObjectList(*clause)}) {
for (const auto &ompObject : objList->v) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &) {
if (const auto *name{
@ -1831,7 +1832,7 @@ bool OmpStructureChecker::CheckReductionOperators(
const auto &definedOp{std::get<0>(x.v.t)};
bool ok = false;
std::visit(
common::visit(
common::visitors{
[&](const parser::DefinedOperator &dOpr) {
const auto &intrinsicOp{
@ -2023,7 +2024,7 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
llvm::omp::Directive::OMPD_threadprivate,
llvm::omp::Directive::OMPD_declare_target};
for (const auto &ompObject : objList.v) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &designator) {
if (const auto *dataRef{
@ -2360,7 +2361,7 @@ llvm::StringRef OmpStructureChecker::getDirectiveName(
}
void OmpStructureChecker::CheckDependList(const parser::DataRef &d) {
std::visit(
common::visit(
common::visitors{
[&](const common::Indirection<parser::ArrayElement> &elem) {
// Check if the base element is valid on Depend Clause
@ -2631,7 +2632,7 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
// TODO:: Generate the tuples using TableGen.
// Handle other constructs with OmpObjectList such as OpenMPThreadprivate.
return std::visit(
return common::visit(
common::visitors{
[&](const auto &x) -> const parser::OmpObjectList * {
using Ty = std::decay_t<decltype(x)>;

View File

@ -60,7 +60,7 @@ void SelectRankConstructChecker::Leave(
std::get<parser::Statement<parser::SelectRankCaseStmt>>(rankCase.t)};
const auto &rank{
std::get<parser::SelectRankCaseStmt::Rank>(rankCaseStmt.statement.t)};
std::visit(
common::visit(
common::visitors{
[&](const parser::Default &) { // C1153
if (!defaultRankFound) {
@ -123,7 +123,7 @@ void SelectRankConstructChecker::Leave(
const SomeExpr *SelectRankConstructChecker::GetExprFromSelector(
const parser::Selector &selector) {
return std::visit([](const auto &x) { return GetExpr(x); }, selector.u);
return common::visit([](const auto &x) { return GetExpr(x); }, selector.u);
}
} // namespace Fortran::semantics

View File

@ -51,7 +51,7 @@ private:
std::optional<evaluate::DynamicType> GetGuardType(
const parser::TypeGuardStmt::Guard &guard) {
return std::visit(
return common::visit(
common::visitors{
[](const parser::Default &)
-> std::optional<evaluate::DynamicType> {
@ -75,7 +75,7 @@ private:
const evaluate::DynamicType &guardDynamicType) {
const parser::TypeGuardStmt &typeGuardStmt{stmt.statement};
const auto &guard{std::get<parser::TypeGuardStmt::Guard>(typeGuardStmt.t)};
return std::visit(
return common::visit(
common::visitors{
[](const parser::Default &) { return true; },
[&](const parser::TypeSpec &typeSpec) {
@ -159,10 +159,10 @@ private:
void SetGuardType(std::optional<evaluate::DynamicType> guardTypeDynamic) {
const auto &guard{GetGuardFromStmt(stmt)};
std::visit(common::visitors{
[&](const parser::Default &) {},
[&](const auto &) { guardType_ = *guardTypeDynamic; },
},
common::visit(common::visitors{
[&](const parser::Default &) {},
[&](const auto &) { guardType_ = *guardTypeDynamic; },
},
guard.u);
}
@ -268,6 +268,6 @@ void SelectTypeChecker::Enter(const parser::SelectTypeConstruct &construct) {
const SomeExpr *SelectTypeChecker::GetExprFromSelector(
const parser::Selector &selector) {
return std::visit([](const auto &x) { return GetExpr(x); }, selector.u);
return common::visit([](const auto &x) { return GetExpr(x); }, selector.u);
}
} // namespace Fortran::semantics

View File

@ -123,7 +123,7 @@ private:
template <typename DSV>
bool DataInitializationCompiler<DSV>::Scan(
const parser::DataStmtObject &object) {
return std::visit(
return common::visit(
common::visitors{
[&](const common::Indirection<parser::Variable> &var) {
return Scan(var.value());
@ -218,7 +218,7 @@ bool DataInitializationCompiler<DSV>::Scan(const parser::DataImpliedDo &ido) {
template <typename DSV>
bool DataInitializationCompiler<DSV>::Scan(
const parser::DataIDoObject &object) {
return std::visit(
return common::visit(
common::visitors{
[&](const parser::Scalar<common::Indirection<parser::Designator>>
&var) { return Scan(var.thing.value()); },

View File

@ -288,7 +288,7 @@ MaybeExpr ExpressionAnalyzer::ApplySubscripts(
if (subscripts.empty()) {
return std::nullopt; // error recovery
}
return std::visit(
return common::visit(
common::visitors{
[&](SymbolRef &&symbol) {
return CompleteSubscripts(ArrayRef{symbol, std::move(subscripts)});
@ -337,7 +337,7 @@ static void FixMisparsedSubstring(const parser::Designator &d) {
if (!std::get<2>(triplet->t) /* no stride */ &&
++iter == arrElement.subscripts.end() /* one subscript */) {
if (Symbol *
symbol{std::visit(
symbol{common::visit(
common::visitors{
[](parser::Name &n) { return n.symbol; },
[](common::Indirection<parser::StructureComponent>
@ -397,7 +397,7 @@ int ExpressionAnalyzer::AnalyzeKindParam(
if (!kindParam) {
return defaultKind;
}
return std::visit(
return common::visit(
common::visitors{
[](std::uint64_t k) { return static_cast<int>(k); },
[&](const parser::Scalar<
@ -839,7 +839,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
if (MaybeExpr string{Analyze(std::get<parser::CharLiteralConstant>(x.t))}) {
if (auto *charExpr{std::get_if<Expr<SomeCharacter>>(&string->u)}) {
Expr<SubscriptInteger> length{
std::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); },
common::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); },
charExpr->u)};
if (!lower) {
lower = Expr<SubscriptInteger>{1};
@ -848,7 +848,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
upper = Expr<SubscriptInteger>{
static_cast<std::int64_t>(ToInt64(length).value())};
}
return std::visit(
return common::visit(
[&](auto &&ckExpr) -> MaybeExpr {
using Result = ResultType<decltype(ckExpr)>;
auto *cp{std::get_if<Constant<Result>>(&ckExpr.u)};
@ -902,7 +902,7 @@ std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart(
std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
const parser::SectionSubscript &ss) {
return std::visit(
return common::visit(
common::visitors{
[&](const parser::SubscriptTriplet &t) -> std::optional<Subscript> {
const auto &lower{std::get<0>(t.t)};
@ -981,7 +981,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) {
// Type parameter inquiries apply to data references, but don't depend
// on any trailing (co)subscripts.
static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) {
return std::visit(
return common::visit(
common::visitors{
[](SymbolRef &&symbol) { return NamedEntity{symbol}; },
[](Component &&component) {
@ -1074,7 +1074,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
if (kind == MiscKind::ComplexPartRe || kind == MiscKind::ComplexPartIm) {
if (auto *zExpr{std::get_if<Expr<SomeComplex>>(&base->u)}) {
if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*zExpr))}) {
Expr<SomeReal> realExpr{std::visit(
Expr<SomeReal> realExpr{common::visit(
[&](const auto &z) {
using PartType = typename ResultType<decltype(z)>::Part;
auto part{kind == MiscKind::ComplexPartRe
@ -1148,7 +1148,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
}
for (const auto &imageSelSpec :
std::get<std::list<parser::ImageSelectorSpec>>(x.imageSelector.t)) {
std::visit(
common::visit(
common::visitors{
[&](const auto &x) { Analyze(x.v); },
},
@ -1185,7 +1185,7 @@ ArrayConstructorValues<T> MakeSpecific(
ArrayConstructorValues<SomeType> &&from) {
ArrayConstructorValues<T> to;
for (ArrayConstructorValue<SomeType> &x : from) {
std::visit(
common::visit(
common::visitors{
[&](common::CopyableIndirection<Expr<SomeType>> &&expr) {
auto *typed{UnwrapExpr<Expr<T>>(expr.value())};
@ -1334,7 +1334,7 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) {
if (Expr<SomeCharacter> * charExpr{UnwrapExpr<Expr<SomeCharacter>>(*x)}) {
CHECK(xType.category() == TypeCategory::Character);
xType.length =
std::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
common::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
}
if (!type_) {
// If there is no explicit type-spec in an array constructor, the type
@ -1395,7 +1395,7 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) {
}
void ArrayConstructorContext::Add(const parser::AcValue &x) {
std::visit(
common::visit(
common::visitors{
[&](const parser::AcValue::Triplet &triplet) { Add(triplet); },
[&](const common::Indirection<parser::Expr> &expr) {
@ -1818,7 +1818,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
static std::optional<parser::CharBlock> GetPassName(
const semantics::Symbol &proc) {
return std::visit(
return common::visit(
[](const auto &details) {
if constexpr (std::is_base_of_v<semantics::WithPassArg,
std::decay_t<decltype(details)>>) {
@ -1957,7 +1957,7 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
static bool CheckCompatibleArgument(bool isElemental,
const ActualArgument &actual, const characteristics::DummyArgument &dummy) {
const auto *expr{actual.UnwrapExpr()};
return std::visit(
return common::visit(
common::visitors{
[&](const characteristics::DummyDataObject &x) {
if (x.attrs.test(characteristics::DummyDataObject::Attr::Pointer) &&
@ -2152,7 +2152,7 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(
const parser::ProcedureDesignator &pd, ActualArguments &&arguments,
bool isSubroutine, bool mightBeStructureConstructor)
-> std::optional<CalleeAndArguments> {
return std::visit(
return common::visit(
common::visitors{
[&](const parser::Name &name) {
return GetCalleeAndArguments(name, std::move(arguments),
@ -2304,7 +2304,7 @@ static const Symbol *AssumedTypePointerOrAllocatableDummy(const A &object) {
// point it is is not guaranteed that it has been checked the object has
// POINTER or ALLOCATABLE attribute, so do not assume nullptr can be directly
// returned.
return std::visit(
return common::visit(
common::visitors{
[&](const parser::StructureComponent &x) {
return AssumedTypeDummy(x.component);
@ -2458,29 +2458,30 @@ const Assignment *ExpressionAnalyzer::Analyze(
new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter);
} else {
Assignment assignment{std::move(*lhs), std::move(*rhs)};
std::visit(common::visitors{
[&](const std::list<parser::BoundsRemapping> &list) {
Assignment::BoundsRemapping bounds;
for (const auto &elem : list) {
auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
if (lower && upper) {
bounds.emplace_back(Fold(std::move(*lower)),
Fold(std::move(*upper)));
}
}
assignment.u = std::move(bounds);
},
[&](const std::list<parser::BoundsSpec> &list) {
Assignment::BoundsSpec bounds;
for (const auto &bound : list) {
if (auto lower{AsSubscript(Analyze(bound.v))}) {
bounds.emplace_back(Fold(std::move(*lower)));
}
}
assignment.u = std::move(bounds);
},
},
common::visit(
common::visitors{
[&](const std::list<parser::BoundsRemapping> &list) {
Assignment::BoundsRemapping bounds;
for (const auto &elem : list) {
auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
if (lower && upper) {
bounds.emplace_back(
Fold(std::move(*lower)), Fold(std::move(*upper)));
}
}
assignment.u = std::move(bounds);
},
[&](const std::list<parser::BoundsSpec> &list) {
Assignment::BoundsSpec bounds;
for (const auto &bound : list) {
if (auto lower{AsSubscript(Analyze(bound.v))}) {
bounds.emplace_back(Fold(std::move(*lower)));
}
}
assignment.u = std::move(bounds);
},
},
std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
x.typedAssignment.Reset(
new GenericAssignmentWrapper{std::move(assignment)},
@ -2690,7 +2691,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
if (!analyzer.fatalErrors()) {
if (analyzer.IsIntrinsicConcat()) {
analyzer.CheckForNullPointer();
return std::visit(
return common::visit(
[&](auto &&x, auto &&y) -> MaybeExpr {
using T = ResultType<decltype(x)>;
if constexpr (std::is_same_v<T, ResultType<decltype(y)>>) {
@ -2874,12 +2875,12 @@ static void FixMisparsedFunctionReference(
auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
if (Symbol *
origSymbol{
std::visit(common::visitors{
[&](parser::Name &name) { return name.symbol; },
[&](parser::ProcComponentRef &pcr) {
return pcr.v.thing.component.symbol;
},
},
common::visit(common::visitors{
[&](parser::Name &name) { return name.symbol; },
[&](parser::ProcComponentRef &pcr) {
return pcr.v.thing.component.symbol;
},
},
proc.u)}) {
Symbol &symbol{origSymbol->GetUltimate()};
if (symbol.has<semantics::ObjectEntityDetails>() ||
@ -3023,7 +3024,7 @@ Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
if (!selector) {
return Expr<SubscriptInteger>{defaultKind};
}
return std::visit(
return common::visit(
common::visitors{
[&](const parser::ScalarIntConstantExpr &x) {
if (MaybeExpr kind{Analyze(x)}) {
@ -3213,7 +3214,7 @@ void ArgumentAnalyzer::Analyze(
// be detected and represented (they're not expressions).
// TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
std::optional<ActualArgument> actual;
std::visit(
common::visit(
common::visitors{
[&](const common::Indirection<parser::Expr> &x) {
actual = AnalyzeExpr(x.value());

View File

@ -259,78 +259,79 @@ static llvm::raw_ostream &PutGenericName(
// procedures, type-bound generics, final procedures) which go to typeBindings.
void ModFileWriter::PutSymbol(
llvm::raw_ostream &typeBindings, const Symbol &symbol) {
std::visit(common::visitors{
[&](const ModuleDetails &) { /* should be current module */ },
[&](const DerivedTypeDetails &) { PutDerivedType(symbol); },
[&](const SubprogramDetails &) { PutSubprogram(symbol); },
[&](const GenericDetails &x) {
if (symbol.owner().IsDerivedType()) {
// generic binding
for (const Symbol &proc : x.specificProcs()) {
PutGenericName(typeBindings << "generic::", symbol)
<< "=>" << proc.name() << '\n';
}
} else {
PutGeneric(symbol);
if (x.specific()) {
PutSymbol(typeBindings, *x.specific());
}
if (x.derivedType()) {
PutSymbol(typeBindings, *x.derivedType());
}
}
},
[&](const UseDetails &) { PutUse(symbol); },
[](const UseErrorDetails &) {},
[&](const ProcBindingDetails &x) {
bool deferred{symbol.attrs().test(Attr::DEFERRED)};
typeBindings << "procedure";
if (deferred) {
typeBindings << '(' << x.symbol().name() << ')';
}
PutPassName(typeBindings, x.passName());
auto attrs{symbol.attrs()};
if (x.passName()) {
attrs.reset(Attr::PASS);
}
PutAttrs(typeBindings, attrs);
typeBindings << "::" << symbol.name();
if (!deferred && x.symbol().name() != symbol.name()) {
typeBindings << "=>" << x.symbol().name();
}
typeBindings << '\n';
},
[&](const NamelistDetails &x) {
decls_ << "namelist/" << symbol.name();
char sep{'/'};
for (const Symbol &object : x.objects()) {
decls_ << sep << object.name();
sep = ',';
}
decls_ << '\n';
},
[&](const CommonBlockDetails &x) {
decls_ << "common/" << symbol.name();
char sep = '/';
for (const auto &object : x.objects()) {
decls_ << sep << object->name();
sep = ',';
}
decls_ << '\n';
if (symbol.attrs().test(Attr::BIND_C)) {
PutAttrs(decls_, symbol.attrs(), x.bindName(), ""s);
decls_ << "::/" << symbol.name() << "/\n";
}
},
[](const HostAssocDetails &) {},
[](const MiscDetails &) {},
[&](const auto &) {
PutEntity(decls_, symbol);
if (symbol.test(Symbol::Flag::OmpThreadprivate)) {
decls_ << "!$omp threadprivate(" << symbol.name() << ")\n";
}
},
},
common::visit(
common::visitors{
[&](const ModuleDetails &) { /* should be current module */ },
[&](const DerivedTypeDetails &) { PutDerivedType(symbol); },
[&](const SubprogramDetails &) { PutSubprogram(symbol); },
[&](const GenericDetails &x) {
if (symbol.owner().IsDerivedType()) {
// generic binding
for (const Symbol &proc : x.specificProcs()) {
PutGenericName(typeBindings << "generic::", symbol)
<< "=>" << proc.name() << '\n';
}
} else {
PutGeneric(symbol);
if (x.specific()) {
PutSymbol(typeBindings, *x.specific());
}
if (x.derivedType()) {
PutSymbol(typeBindings, *x.derivedType());
}
}
},
[&](const UseDetails &) { PutUse(symbol); },
[](const UseErrorDetails &) {},
[&](const ProcBindingDetails &x) {
bool deferred{symbol.attrs().test(Attr::DEFERRED)};
typeBindings << "procedure";
if (deferred) {
typeBindings << '(' << x.symbol().name() << ')';
}
PutPassName(typeBindings, x.passName());
auto attrs{symbol.attrs()};
if (x.passName()) {
attrs.reset(Attr::PASS);
}
PutAttrs(typeBindings, attrs);
typeBindings << "::" << symbol.name();
if (!deferred && x.symbol().name() != symbol.name()) {
typeBindings << "=>" << x.symbol().name();
}
typeBindings << '\n';
},
[&](const NamelistDetails &x) {
decls_ << "namelist/" << symbol.name();
char sep{'/'};
for (const Symbol &object : x.objects()) {
decls_ << sep << object.name();
sep = ',';
}
decls_ << '\n';
},
[&](const CommonBlockDetails &x) {
decls_ << "common/" << symbol.name();
char sep = '/';
for (const auto &object : x.objects()) {
decls_ << sep << object->name();
sep = ',';
}
decls_ << '\n';
if (symbol.attrs().test(Attr::BIND_C)) {
PutAttrs(decls_, symbol.attrs(), x.bindName(), ""s);
decls_ << "::/" << symbol.name() << "/\n";
}
},
[](const HostAssocDetails &) {},
[](const MiscDetails &) {},
[&](const auto &) {
PutEntity(decls_, symbol);
if (symbol.test(Symbol::Flag::OmpThreadprivate)) {
decls_ << "!$omp threadprivate(" << symbol.name() << ")\n";
}
},
},
symbol.details());
}
@ -601,7 +602,7 @@ void CollectSymbols(
}
void ModFileWriter::PutEntity(llvm::raw_ostream &os, const Symbol &symbol) {
std::visit(
common::visit(
common::visitors{
[&](const ObjectEntityDetails &) { PutObjectEntity(os, symbol); },
[&](const ProcEntityDetails &) { PutProcEntity(os, symbol); },
@ -1114,27 +1115,27 @@ void SubprogramSymbolCollector::DoSymbol(
if (!needSet_.insert(symbol).second) {
return; // already done
}
std::visit(common::visitors{
[this](const ObjectEntityDetails &details) {
for (const ShapeSpec &spec : details.shape()) {
DoBound(spec.lbound());
DoBound(spec.ubound());
}
for (const ShapeSpec &spec : details.coshape()) {
DoBound(spec.lbound());
DoBound(spec.ubound());
}
if (const Symbol * commonBlock{details.commonBlock()}) {
DoSymbol(*commonBlock);
}
},
[this](const CommonBlockDetails &details) {
for (const auto &object : details.objects()) {
DoSymbol(*object);
}
},
[](const auto &) {},
},
common::visit(common::visitors{
[this](const ObjectEntityDetails &details) {
for (const ShapeSpec &spec : details.shape()) {
DoBound(spec.lbound());
DoBound(spec.ubound());
}
for (const ShapeSpec &spec : details.coshape()) {
DoBound(spec.lbound());
DoBound(spec.ubound());
}
if (const Symbol * commonBlock{details.commonBlock()}) {
DoSymbol(*commonBlock);
}
},
[this](const CommonBlockDetails &details) {
for (const auto &object : details.objects()) {
DoSymbol(*object);
}
},
[](const auto &) {},
},
symbol.details());
if (!symbol.has<UseDetails>()) {
DoType(symbol.GetType());

View File

@ -117,7 +117,7 @@ template <typename T> bool PointerAssignmentChecker::Check(const T &) {
template <typename T>
bool PointerAssignmentChecker::Check(const evaluate::Expr<T> &x) {
return std::visit([&](const auto &x) { return Check(x); }, x.u);
return common::visit([&](const auto &x) { return Check(x); }, x.u);
}
bool PointerAssignmentChecker::Check(const SomeExpr &rhs) {
@ -128,7 +128,7 @@ bool PointerAssignmentChecker::Check(const SomeExpr &rhs) {
Say("A coindexed object may not be a pointer target"_err_en_US);
return false;
} else {
return std::visit([&](const auto &x) { return Check(x); }, rhs.u);
return common::visit([&](const auto &x) { return Check(x); }, rhs.u);
}
}
@ -322,7 +322,7 @@ static bool CheckPointerBounds(
const SomeExpr &lhs{assignment.lhs};
const SomeExpr &rhs{assignment.rhs};
bool isBoundsRemapping{false};
std::size_t numBounds{std::visit(
std::size_t numBounds{common::visit(
common::visitors{
[&](const evaluate::Assignment::BoundsSpec &bounds) {
return bounds.size();

View File

@ -88,7 +88,7 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
if (subps) {
for (const auto &subp :
std::get<std::list<parser::InternalSubprogram>>(subps->t)) {
std::visit(
common::visit(
[&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); },
subp.u);
}
@ -111,7 +111,7 @@ static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) {
if (subps) {
for (const auto &subp :
std::get<std::list<parser::ModuleSubprogram>>(subps->t)) {
std::visit(
common::visit(
[&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); },
subp.u);
}
@ -120,7 +120,7 @@ static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) {
}
ProgramTree ProgramTree::Build(const parser::ProgramUnit &x) {
return std::visit([](const auto &y) { return Build(y.value()); }, x.u);
return common::visit([](const auto &y) { return Build(y.value()); }, x.u);
}
ProgramTree ProgramTree::Build(const parser::MainProgram &x) {
@ -200,17 +200,17 @@ Symbol::Flag ProgramTree::GetSubpFlag() const {
bool ProgramTree::HasModulePrefix() const {
using ListType = std::list<parser::PrefixSpec>;
const auto *prefixes{
std::visit(common::visitors{
[](const parser::Statement<parser::FunctionStmt> *x) {
return &std::get<ListType>(x->statement.t);
},
[](const parser::Statement<parser::SubroutineStmt> *x) {
return &std::get<ListType>(x->statement.t);
},
[](const auto *) -> const ListType * { return nullptr; },
},
stmt_)};
const auto *prefixes{common::visit(
common::visitors{
[](const parser::Statement<parser::FunctionStmt> *x) {
return &std::get<ListType>(x->statement.t);
},
[](const parser::Statement<parser::SubroutineStmt> *x) {
return &std::get<ListType>(x->statement.t);
},
[](const auto *) -> const ListType * { return nullptr; },
},
stmt_)};
if (prefixes) {
for (const auto &prefix : *prefixes) {
if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) {
@ -222,7 +222,7 @@ bool ProgramTree::HasModulePrefix() const {
}
ProgramTree::Kind ProgramTree::GetKind() const {
return std::visit(
return common::visit(
common::visitors{
[](const parser::Statement<parser::ProgramStmt> *) {
return Kind::Program;

View File

@ -364,18 +364,18 @@ public:
return false;
}
bool Pre(const parser::OmpLinearClause &x) {
std::visit(common::visitors{
[&](const parser::OmpLinearClause::WithoutModifier
&linearWithoutModifier) {
ResolveOmpNameList(
linearWithoutModifier.names, Symbol::Flag::OmpLinear);
},
[&](const parser::OmpLinearClause::WithModifier
&linearWithModifier) {
ResolveOmpNameList(
linearWithModifier.names, Symbol::Flag::OmpLinear);
},
},
common::visit(common::visitors{
[&](const parser::OmpLinearClause::WithoutModifier
&linearWithoutModifier) {
ResolveOmpNameList(linearWithoutModifier.names,
Symbol::Flag::OmpLinear);
},
[&](const parser::OmpLinearClause::WithModifier
&linearWithModifier) {
ResolveOmpNameList(
linearWithModifier.names, Symbol::Flag::OmpLinear);
},
},
x.u);
return false;
}
@ -756,7 +756,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
static bool IsLastNameArray(const parser::Designator &designator) {
const auto &name{GetLastName(designator)};
const evaluate::DataRef dataRef{*(name.symbol)};
return std::visit(
return common::visit(
common::visitors{
[](const evaluate::SymbolRef &ref) { return ref->Rank() > 0; },
[](const evaluate::ArrayRef &aref) {
@ -771,7 +771,7 @@ static bool IsLastNameArray(const parser::Designator &designator) {
void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
const parser::AccObjectList &objectList) {
for (const auto &accObject : objectList.v) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &designator) {
if (!IsLastNameArray(designator)) {
@ -798,7 +798,7 @@ void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
void AccAttributeVisitor::DoNotAllowAssumedSizedArray(
const parser::AccObjectList &objectList) {
for (const auto &accObject : objectList.v) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &designator) {
const auto &name{GetLastName(designator)};
@ -883,7 +883,7 @@ void AccAttributeVisitor::PrivatizeAssociatedLoopIndex(
void AccAttributeVisitor::EnsureAllocatableOrPointer(
const llvm::acc::Clause clause, const parser::AccObjectList &objectList) {
for (const auto &accObject : objectList.v) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &designator) {
const auto &lastName{GetLastName(designator)};
@ -977,7 +977,7 @@ void AccAttributeVisitor::ResolveAccObjectList(
void AccAttributeVisitor::ResolveAccObject(
const parser::AccObject &accObject, Symbol::Flag accFlag) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &designator) {
if (const auto *name{GetDesignatorNameIfDataRef(designator)}) {
@ -1572,7 +1572,7 @@ void OmpAttributeVisitor::ResolveOmpObjectList(
void OmpAttributeVisitor::ResolveOmpObject(
const parser::OmpObject &ompObject, Symbol::Flag ompFlag) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Designator &designator) {
if (const auto *name{GetDesignatorNameIfDataRef(designator)}) {

View File

@ -126,7 +126,7 @@ void GenericSpecInfo::Analyze(const parser::DefinedOpName &name) {
void GenericSpecInfo::Analyze(const parser::GenericSpec &x) {
symbolName_ = x.source;
kind_ = std::visit(
kind_ = common::visit(
common::visitors{
[&](const parser::Name &y) -> GenericKind {
parseName_ = &y;
@ -134,7 +134,7 @@ void GenericSpecInfo::Analyze(const parser::GenericSpec &x) {
return GenericKind::OtherKind::Name;
},
[&](const parser::DefinedOperator &y) {
return std::visit(
return common::visit(
common::visitors{
[&](const parser::DefinedOpName &z) -> GenericKind {
Analyze(z);
@ -265,19 +265,20 @@ ArraySpec AnalyzeCoarraySpec(
}
ArraySpec ArraySpecAnalyzer::Analyze(const parser::ComponentArraySpec &x) {
std::visit([this](const auto &y) { Analyze(y); }, x.u);
common::visit([this](const auto &y) { Analyze(y); }, x.u);
CHECK(!arraySpec_.empty());
return arraySpec_;
}
ArraySpec ArraySpecAnalyzer::Analyze(const parser::ArraySpec &x) {
std::visit(common::visitors{
[&](const parser::AssumedSizeSpec &y) {
Analyze(std::get<std::list<parser::ExplicitShapeSpec>>(y.t));
Analyze(std::get<parser::AssumedImpliedSpec>(y.t));
},
[&](const parser::ImpliedShapeSpec &y) { Analyze(y.v); },
[&](const auto &y) { Analyze(y); },
},
common::visit(common::visitors{
[&](const parser::AssumedSizeSpec &y) {
Analyze(
std::get<std::list<parser::ExplicitShapeSpec>>(y.t));
Analyze(std::get<parser::AssumedImpliedSpec>(y.t));
},
[&](const parser::ImpliedShapeSpec &y) { Analyze(y.v); },
[&](const auto &y) { Analyze(y); },
},
x.u);
CHECK(!arraySpec_.empty());
return arraySpec_;
@ -289,7 +290,7 @@ ArraySpec ArraySpecAnalyzer::AnalyzeDeferredShapeSpecList(
return arraySpec_;
}
ArraySpec ArraySpecAnalyzer::Analyze(const parser::CoarraySpec &x) {
std::visit(
common::visit(
common::visitors{
[&](const parser::DeferredCoshapeSpecList &y) { MakeDeferred(y.v); },
[&](const parser::ExplicitCoshapeSpec &y) {
@ -495,7 +496,7 @@ const EquivalenceObject *EquivalenceSets::Find(
}
bool EquivalenceSets::CheckDesignator(const parser::Designator &designator) {
return std::visit(
return common::visit(
common::visitors{
[&](const parser::DataRef &x) {
return CheckDataRef(designator.source, x);
@ -520,7 +521,7 @@ bool EquivalenceSets::CheckDesignator(const parser::Designator &designator) {
bool EquivalenceSets::CheckDataRef(
const parser::CharBlock &source, const parser::DataRef &x) {
return std::visit(
return common::visit(
common::visitors{
[&](const parser::Name &name) { return CheckObject(name); },
[&](const common::Indirection<parser::StructureComponent> &) {
@ -532,7 +533,7 @@ bool EquivalenceSets::CheckDataRef(
[&](const common::Indirection<parser::ArrayElement> &elem) {
bool ok{CheckDataRef(source, elem.value().base)};
for (const auto &subscript : elem.value().subscripts) {
ok &= std::visit(
ok &= common::visit(
common::visitors{
[&](const parser::SubscriptTriplet &) {
context_.Say(source, // C924, R872

View File

@ -17,6 +17,7 @@
#include "flang/Common/default-kinds.h"
#include "flang/Common/indirection.h"
#include "flang/Common/restorer.h"
#include "flang/Common/visit.h"
#include "flang/Evaluate/characteristics.h"
#include "flang/Evaluate/check-expression.h"
#include "flang/Evaluate/common.h"
@ -1633,11 +1634,11 @@ bool AttrsVisitor::SetPassNameOn(Symbol &symbol) {
if (!passName_) {
return false;
}
std::visit(common::visitors{
[&](ProcEntityDetails &x) { x.set_passName(*passName_); },
[&](ProcBindingDetails &x) { x.set_passName(*passName_); },
[](auto &) { common::die("unexpected pass name"); },
},
common::visit(common::visitors{
[&](ProcEntityDetails &x) { x.set_passName(*passName_); },
[&](ProcBindingDetails &x) { x.set_passName(*passName_); },
[](auto &) { common::die("unexpected pass name"); },
},
symbol.details());
return true;
}
@ -1841,20 +1842,20 @@ void ImplicitRulesVisitor::Post(const parser::ParameterStmt &) {
bool ImplicitRulesVisitor::Pre(const parser::ImplicitStmt &x) {
bool result{
std::visit(common::visitors{
[&](const std::list<ImplicitNoneNameSpec> &y) {
return HandleImplicitNone(y);
},
[&](const std::list<parser::ImplicitSpec> &) {
if (prevImplicitNoneType_) {
Say("IMPLICIT statement after IMPLICIT NONE or "
"IMPLICIT NONE(TYPE) statement"_err_en_US);
return false;
}
implicitRules_->set_isImplicitNoneType(false);
return true;
},
},
common::visit(common::visitors{
[&](const std::list<ImplicitNoneNameSpec> &y) {
return HandleImplicitNone(y);
},
[&](const std::list<parser::ImplicitSpec> &) {
if (prevImplicitNoneType_) {
Say("IMPLICIT statement after IMPLICIT NONE or "
"IMPLICIT NONE(TYPE) statement"_err_en_US);
return false;
}
implicitRules_->set_isImplicitNoneType(false);
return true;
},
},
x.u)};
prevImplicit_ = currStmtSource();
return result;
@ -2288,17 +2289,17 @@ void ScopeHandler::EraseSymbol(const parser::Name &name) {
static bool NeedsType(const Symbol &symbol) {
return !symbol.GetType() &&
std::visit(common::visitors{
[](const EntityDetails &) { return true; },
[](const ObjectEntityDetails &) { return true; },
[](const AssocEntityDetails &) { return true; },
[&](const ProcEntityDetails &p) {
return symbol.test(Symbol::Flag::Function) &&
!symbol.attrs().test(Attr::INTRINSIC) &&
!p.interface().type() && !p.interface().symbol();
},
[](const auto &) { return false; },
},
common::visit(common::visitors{
[](const EntityDetails &) { return true; },
[](const ObjectEntityDetails &) { return true; },
[](const AssocEntityDetails &) { return true; },
[&](const ProcEntityDetails &p) {
return symbol.test(Symbol::Flag::Function) &&
!symbol.attrs().test(Attr::INTRINSIC) &&
!p.interface().type() && !p.interface().symbol();
},
[](const auto &) { return false; },
},
symbol.details());
}
@ -2529,18 +2530,18 @@ void ScopeHandler::MakeExternal(Symbol &symbol) {
// ModuleVisitor implementation
bool ModuleVisitor::Pre(const parser::Only &x) {
std::visit(common::visitors{
[&](const Indirection<parser::GenericSpec> &generic) {
GenericSpecInfo genericSpecInfo{generic.value()};
AddUseOnly(genericSpecInfo.symbolName());
AddUse(genericSpecInfo);
},
[&](const parser::Name &name) {
AddUseOnly(name.source);
Resolve(name, AddUse(name.source, name.source).use);
},
[&](const parser::Rename &rename) { Walk(rename); },
},
common::visit(common::visitors{
[&](const Indirection<parser::GenericSpec> &generic) {
GenericSpecInfo genericSpecInfo{generic.value()};
AddUseOnly(genericSpecInfo.symbolName());
AddUse(genericSpecInfo);
},
[&](const parser::Name &name) {
AddUseOnly(name.source);
Resolve(name, AddUse(name.source, name.source).use);
},
[&](const parser::Rename &rename) { Walk(rename); },
},
x.u);
return false;
}
@ -2605,14 +2606,14 @@ void ModuleVisitor::Post(const parser::UseStmt &x) {
// then add a use for each public name that was not renamed.
std::set<SourceName> useNames;
for (const auto &rename : *list) {
std::visit(common::visitors{
[&](const parser::Rename::Names &names) {
useNames.insert(std::get<1>(names.t).source);
},
[&](const parser::Rename::Operators &ops) {
useNames.insert(std::get<1>(ops.t).v.source);
},
},
common::visit(common::visitors{
[&](const parser::Rename::Names &names) {
useNames.insert(std::get<1>(names.t).source);
},
[&](const parser::Rename::Operators &ops) {
useNames.insert(std::get<1>(ops.t).v.source);
},
},
rename.u);
}
for (const auto &[name, symbol] : *useModuleScope_) {
@ -3356,7 +3357,7 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
auto &effectiveResultName{*(resultName ? resultName : &name)};
resultSymbol = FindInScope(currScope(), effectiveResultName);
if (resultSymbol) { // C1574
std::visit(
common::visit(
common::visitors{[](EntityDetails &x) { x.set_funcResult(true); },
[](ObjectEntityDetails &x) { x.set_funcResult(true); },
[](ProcEntityDetails &x) { x.set_funcResult(true); },
@ -3387,7 +3388,7 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
Symbol *dummy{FindSymbol(*dummyName)};
if (dummy) {
std::visit(
common::visit(
common::visitors{[](EntityDetails &x) { x.set_isDummy(); },
[](ObjectEntityDetails &x) { x.set_isDummy(); },
[](ProcEntityDetails &x) { x.set_isDummy(); },
@ -5653,7 +5654,7 @@ bool DeclarationVisitor::OkToAddComponent(
ParamValue DeclarationVisitor::GetParamValue(
const parser::TypeParamValue &x, common::TypeParamAttr attr) {
return std::visit(
return common::visit(
common::visitors{
[=](const parser::ScalarIntExpr &x) { // C704
return ParamValue{EvaluateIntExpr(x), attr};
@ -5812,7 +5813,7 @@ bool ConstructVisitor::Pre(const parser::DataImpliedDo &x) {
// statement so that the predicate IsInitialized() will be true
// during semantic analysis before the symbol's initializer is constructed.
bool ConstructVisitor::Pre(const parser::DataIDoObject &x) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Scalar<Indirection<parser::Designator>> &y) {
Walk(y.thing.value());
@ -5828,20 +5829,21 @@ bool ConstructVisitor::Pre(const parser::DataIDoObject &x) {
}
bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
std::visit(common::visitors{
[&](const Indirection<parser::Variable> &y) {
Walk(y.value());
const parser::Name &first{parser::GetFirstName(y.value())};
if (first.symbol) {
first.symbol->set(Symbol::Flag::InDataStmt);
}
},
[&](const parser::DataImpliedDo &y) {
PushScope(Scope::Kind::ImpliedDos, nullptr);
Walk(y);
PopScope();
},
},
common::visit(common::visitors{
[&](const Indirection<parser::Variable> &y) {
Walk(y.value());
const parser::Name &first{
parser::GetFirstName(y.value())};
if (first.symbol) {
first.symbol->set(Symbol::Flag::InDataStmt);
}
},
[&](const parser::DataImpliedDo &y) {
PushScope(Scope::Kind::ImpliedDos, nullptr);
Walk(y);
PopScope();
},
},
x.u);
return false;
}
@ -6121,9 +6123,9 @@ void ConstructVisitor::SetTypeFromAssociation(Symbol &symbol) {
evaluate::UnwrapExpr<evaluate::Expr<evaluate::SomeCharacter>>(
expr)}) {
symbol.SetType(ToDeclTypeSpec(std::move(*type),
FoldExpr(
std::visit([](const auto &kindChar) { return kindChar.LEN(); },
charExpr->u))));
FoldExpr(common::visit(
[](const auto &kindChar) { return kindChar.LEN(); },
charExpr->u))));
} else {
symbol.SetType(ToDeclTypeSpec(std::move(*type)));
}
@ -6146,14 +6148,14 @@ void ConstructVisitor::SetAttrsFromAssociation(Symbol &symbol) {
ConstructVisitor::Selector ConstructVisitor::ResolveSelector(
const parser::Selector &x) {
return std::visit(common::visitors{
[&](const parser::Expr &expr) {
return Selector{expr.source, EvaluateExpr(x)};
},
[&](const parser::Variable &var) {
return Selector{var.GetSource(), EvaluateExpr(x)};
},
},
return common::visit(common::visitors{
[&](const parser::Expr &expr) {
return Selector{expr.source, EvaluateExpr(x)};
},
[&](const parser::Variable &var) {
return Selector{var.GetSource(), EvaluateExpr(x)};
},
},
x.u);
}
@ -6283,7 +6285,7 @@ const parser::Name *DeclarationVisitor::ResolveStructureComponent(
const parser::Name *DeclarationVisitor::ResolveDesignator(
const parser::Designator &x) {
return std::visit(
return common::visit(
common::visitors{
[&](const parser::DataRef &x) { return ResolveDataRef(x); },
[&](const parser::Substring &x) {
@ -6295,7 +6297,7 @@ const parser::Name *DeclarationVisitor::ResolveDesignator(
const parser::Name *DeclarationVisitor::ResolveDataRef(
const parser::DataRef &x) {
return std::visit(
return common::visit(
common::visitors{
[=](const parser::Name &y) { return ResolveName(y); },
[=](const Indirection<parser::StructureComponent> &y) {
@ -6514,7 +6516,7 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
if (auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) {
// TODO: check C762 - all bounds and type parameters of component
// are colons or constant expressions if component is initialized
std::visit(
common::visit(
common::visitors{
[&](const parser::ConstantExpr &expr) {
NonPointerInitialization(name, expr);
@ -6624,7 +6626,7 @@ void DeclarationVisitor::NonPointerInitialization(
void ResolveNamesVisitor::HandleCall(
Symbol::Flag procFlag, const parser::Call &call) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Name &x) { HandleProcedureName(procFlag, x); },
[&](const parser::ProcComponentRef &x) { Walk(x); },
@ -6803,7 +6805,7 @@ bool ModuleVisitor::Pre(const parser::AccessStmt &x) {
defaultAccess_ = accessAttr;
} else {
for (const auto &accessId : accessIds) {
std::visit(
common::visit(
common::visitors{
[=](const parser::Name &y) {
Resolve(y, SetAccess(y.source, accessAttr));
@ -6890,7 +6892,7 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
// Initial processing on specification constructs, before visiting them.
void ResolveNamesVisitor::PreSpecificationConstruct(
const parser::SpecificationConstruct &spec) {
std::visit(
common::visit(
common::visitors{
[&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {
CreateGeneric(std::get<parser::GenericSpec>(y.statement.value().t));
@ -7093,21 +7095,21 @@ bool ResolveNamesVisitor::Pre(const parser::ImplicitStmt &x) {
}
void ResolveNamesVisitor::Post(const parser::PointerObject &x) {
std::visit(common::visitors{
[&](const parser::Name &x) { ResolveName(x); },
[&](const parser::StructureComponent &x) {
ResolveStructureComponent(x);
},
},
common::visit(common::visitors{
[&](const parser::Name &x) { ResolveName(x); },
[&](const parser::StructureComponent &x) {
ResolveStructureComponent(x);
},
},
x.u);
}
void ResolveNamesVisitor::Post(const parser::AllocateObject &x) {
std::visit(common::visitors{
[&](const parser::Name &x) { ResolveName(x); },
[&](const parser::StructureComponent &x) {
ResolveStructureComponent(x);
},
},
common::visit(common::visitors{
[&](const parser::Name &x) { ResolveName(x); },
[&](const parser::StructureComponent &x) {
ResolveStructureComponent(x);
},
},
x.u);
}
@ -7240,7 +7242,7 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
Scope &scope{currScope()};
node.set_scope(scope);
AddSubpNames(node);
std::visit(
common::visit(
[&](const auto *x) {
if (x) {
Walk(*x);

View File

@ -120,7 +120,7 @@ void RewriteMutator::Post(parser::IoUnit &x) {
// the I/O unit in situ to a FileUnitNumber so that automatic expression
// constraint checking will be applied.
auto source{var->GetSource()};
auto expr{std::visit(
auto expr{common::visit(
[](auto &&indirection) {
return parser::Expr{std::move(indirection)};
},
@ -159,7 +159,7 @@ void RewriteMutator::Post(parser::ReadStmt &x) {
const parser::Name &last{parser::GetLastName(*var)};
DeclTypeSpec *type{last.symbol ? last.symbol->GetType() : nullptr};
if (type && type->category() == DeclTypeSpec::Character) {
x.format = std::visit(
x.format = common::visit(
[](auto &&indirection) {
return parser::Expr{std::move(indirection)};
},

View File

@ -499,7 +499,7 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
for (const auto &pair : dtScope) {
const Symbol &symbol{*pair.second};
auto locationRestorer{common::ScopedSet(location_, symbol.name())};
std::visit(
common::visit(
common::visitors{
[&](const TypeParamDetails &) {
// already handled above in declaration order
@ -979,30 +979,30 @@ RuntimeTableBuilder::DescribeBindings(const Scope &dtScope, Scope &scope) {
void RuntimeTableBuilder::DescribeGeneric(const GenericDetails &generic,
std::map<int, evaluate::StructureConstructor> &specials) {
std::visit(common::visitors{
[&](const GenericKind::OtherKind &k) {
if (k == GenericKind::OtherKind::Assignment) {
for (auto ref : generic.specificProcs()) {
DescribeSpecialProc(specials, *ref, true,
false /*!final*/, std::nullopt);
}
}
},
[&](const GenericKind::DefinedIo &io) {
switch (io) {
case GenericKind::DefinedIo::ReadFormatted:
case GenericKind::DefinedIo::ReadUnformatted:
case GenericKind::DefinedIo::WriteFormatted:
case GenericKind::DefinedIo::WriteUnformatted:
for (auto ref : generic.specificProcs()) {
DescribeSpecialProc(
specials, *ref, false, false /*!final*/, io);
}
break;
}
},
[](const auto &) {},
},
common::visit(common::visitors{
[&](const GenericKind::OtherKind &k) {
if (k == GenericKind::OtherKind::Assignment) {
for (auto ref : generic.specificProcs()) {
DescribeSpecialProc(specials, *ref, true,
false /*!final*/, std::nullopt);
}
}
},
[&](const GenericKind::DefinedIo &io) {
switch (io) {
case GenericKind::DefinedIo::ReadFormatted:
case GenericKind::DefinedIo::ReadUnformatted:
case GenericKind::DefinedIo::WriteFormatted:
case GenericKind::DefinedIo::WriteUnformatted:
for (auto ref : generic.specificProcs()) {
DescribeSpecialProc(
specials, *ref, false, false /*!final*/, io);
}
break;
}
},
[](const auto &) {},
},
generic.kind().u);
}

View File

@ -223,7 +223,7 @@ void GenericDetails::CopyFrom(const GenericDetails &from) {
// The name of the kind of details for this symbol.
// This is primarily for debugging.
std::string DetailsToString(const Details &details) {
return std::visit(
return common::visit(
common::visitors{
[](const UnknownDetails &) { return "Unknown"; },
[](const MainProgramDetails &) { return "MainProgram"; },
@ -261,7 +261,7 @@ bool Symbol::CanReplaceDetails(const Details &details) const {
if (has<UnknownDetails>()) {
return true; // can always replace UnknownDetails
} else {
return std::visit(
return common::visit(
common::visitors{
[](const UseErrorDetails &) { return true; },
[&](const ObjectEntityDetails &) { return has<EntityDetails>(); },
@ -291,14 +291,14 @@ void Symbol::ReplaceName(const SourceName &name) {
}
void Symbol::SetType(const DeclTypeSpec &type) {
std::visit(common::visitors{
[&](EntityDetails &x) { x.set_type(type); },
[&](ObjectEntityDetails &x) { x.set_type(type); },
[&](AssocEntityDetails &x) { x.set_type(type); },
[&](ProcEntityDetails &x) { x.interface().set_type(type); },
[&](TypeParamDetails &x) { x.set_type(type); },
[](auto &) {},
},
common::visit(common::visitors{
[&](EntityDetails &x) { x.set_type(type); },
[&](ObjectEntityDetails &x) { x.set_type(type); },
[&](AssocEntityDetails &x) { x.set_type(type); },
[&](ProcEntityDetails &x) { x.interface().set_type(type); },
[&](TypeParamDetails &x) { x.set_type(type); },
[](auto &) {},
},
details_);
}
@ -306,7 +306,7 @@ template <typename T>
constexpr bool HasBindName{std::is_convertible_v<T, const WithBindName *>};
const std::string *Symbol::GetBindName() const {
return std::visit(
return common::visit(
[&](auto &x) -> const std::string * {
if constexpr (HasBindName<decltype(&x)>) {
return x.bindName();
@ -318,7 +318,7 @@ const std::string *Symbol::GetBindName() const {
}
void Symbol::SetBindName(std::string &&name) {
std::visit(
common::visit(
[&](auto &x) {
if constexpr (HasBindName<decltype(&x)>) {
x.set_bindName(std::move(name));
@ -330,7 +330,7 @@ void Symbol::SetBindName(std::string &&name) {
}
bool Symbol::IsFuncResult() const {
return std::visit(
return common::visit(
common::visitors{[](const EntityDetails &x) { return x.isFuncResult(); },
[](const ObjectEntityDetails &x) { return x.isFuncResult(); },
[](const ProcEntityDetails &x) { return x.isFuncResult(); },
@ -345,7 +345,7 @@ bool Symbol::IsObjectArray() const {
}
bool Symbol::IsSubprogram() const {
return std::visit(
return common::visit(
common::visitors{
[](const SubprogramDetails &) { return true; },
[](const SubprogramNameDetails &) { return true; },
@ -444,7 +444,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const GenericDetails &x) {
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) {
os << DetailsToString(details);
std::visit( //
common::visit( //
common::visitors{
[&](const UnknownDetails &) {},
[&](const MainProgramDetails &) {},
@ -667,7 +667,7 @@ bool GenericKind::IsOperator() const {
}
std::string GenericKind::ToString() const {
return std::visit(
return common::visit(
common::visitors {
[](const OtherKind &x) { return EnumToString(x); },
[](const DefinedIo &x) { return AsFortran(x).ToString(); },

View File

@ -428,7 +428,7 @@ const evaluate::Assignment *GetAssignment(
}
const Symbol *FindInterface(const Symbol &symbol) {
return std::visit(
return common::visit(
common::visitors{
[](const ProcEntityDetails &details) {
return details.interface().symbol();
@ -440,7 +440,7 @@ const Symbol *FindInterface(const Symbol &symbol) {
}
const Symbol *FindSubprogram(const Symbol &symbol) {
return std::visit(
return common::visit(
common::visitors{
[&](const ProcEntityDetails &details) -> const Symbol * {
if (const Symbol * interface{details.interface().symbol()}) {
@ -932,7 +932,7 @@ public:
return false;
}
bool operator()(const parser::Statement<parser::ActionStmt> &stmt) {
return std::visit(*this, stmt.statement.u);
return common::visit(*this, stmt.statement.u);
}
private:
@ -943,14 +943,14 @@ private:
};
bool IsImageControlStmt(const parser::ExecutableConstruct &construct) {
return std::visit(ImageControlStmtHelper{}, construct.u);
return common::visit(ImageControlStmtHelper{}, construct.u);
}
std::optional<parser::MessageFixedText> GetImageControlStmtCoarrayMsg(
const parser::ExecutableConstruct &construct) {
if (const auto *actionStmt{
std::get_if<parser::Statement<parser::ActionStmt>>(&construct.u)}) {
return std::visit(
return common::visit(
common::visitors{
[](const common::Indirection<parser::AllocateStmt> &)
-> std::optional<parser::MessageFixedText> {
@ -978,7 +978,7 @@ std::optional<parser::MessageFixedText> GetImageControlStmtCoarrayMsg(
parser::CharBlock GetImageControlStmtLocation(
const parser::ExecutableConstruct &executableConstruct) {
return std::visit(
return common::visit(
common::visitors{
[](const common::Indirection<parser::ChangeTeamConstruct>
&construct) {
@ -1447,7 +1447,7 @@ bool InCommonBlock(const Symbol &symbol) {
const std::optional<parser::Name> &MaybeGetNodeName(
const ConstructNode &construct) {
return std::visit(
return common::visit(
common::visitors{
[&](const parser::BlockConstruct *blockConstruct)
-> const std::optional<parser::Name> & {

View File

@ -455,26 +455,26 @@ int ExternalFormattedIoStatementState<DIR, CHAR>::EndIoStatement() {
}
std::optional<DataEdit> IoStatementState::GetNextDataEdit(int n) {
return std::visit(
return common::visit(
[&](auto &x) { return x.get().GetNextDataEdit(*this, n); }, u_);
}
bool IoStatementState::Emit(
const char *data, std::size_t n, std::size_t elementBytes) {
return std::visit(
return common::visit(
[=](auto &x) { return x.get().Emit(data, n, elementBytes); }, u_);
}
bool IoStatementState::Emit(const char *data, std::size_t n) {
return std::visit([=](auto &x) { return x.get().Emit(data, n); }, u_);
return common::visit([=](auto &x) { return x.get().Emit(data, n); }, u_);
}
bool IoStatementState::Emit(const char16_t *data, std::size_t chars) {
return std::visit([=](auto &x) { return x.get().Emit(data, chars); }, u_);
return common::visit([=](auto &x) { return x.get().Emit(data, chars); }, u_);
}
bool IoStatementState::Emit(const char32_t *data, std::size_t chars) {
return std::visit([=](auto &x) { return x.get().Emit(data, chars); }, u_);
return common::visit([=](auto &x) { return x.get().Emit(data, chars); }, u_);
}
template <typename CHAR>
@ -503,55 +503,57 @@ bool IoStatementState::EmitEncoded(const CHAR *data0, std::size_t chars) {
bool IoStatementState::Receive(
char *data, std::size_t n, std::size_t elementBytes) {
return std::visit(
return common::visit(
[=](auto &x) { return x.get().Receive(data, n, elementBytes); }, u_);
}
std::size_t IoStatementState::GetNextInputBytes(const char *&p) {
return std::visit([&](auto &x) { return x.get().GetNextInputBytes(p); }, u_);
return common::visit(
[&](auto &x) { return x.get().GetNextInputBytes(p); }, u_);
}
bool IoStatementState::AdvanceRecord(int n) {
return std::visit([=](auto &x) { return x.get().AdvanceRecord(n); }, u_);
return common::visit([=](auto &x) { return x.get().AdvanceRecord(n); }, u_);
}
void IoStatementState::BackspaceRecord() {
std::visit([](auto &x) { x.get().BackspaceRecord(); }, u_);
common::visit([](auto &x) { x.get().BackspaceRecord(); }, u_);
}
void IoStatementState::HandleRelativePosition(std::int64_t n) {
std::visit([=](auto &x) { x.get().HandleRelativePosition(n); }, u_);
common::visit([=](auto &x) { x.get().HandleRelativePosition(n); }, u_);
}
void IoStatementState::HandleAbsolutePosition(std::int64_t n) {
std::visit([=](auto &x) { x.get().HandleAbsolutePosition(n); }, u_);
common::visit([=](auto &x) { x.get().HandleAbsolutePosition(n); }, u_);
}
void IoStatementState::CompleteOperation() {
std::visit([](auto &x) { x.get().CompleteOperation(); }, u_);
common::visit([](auto &x) { x.get().CompleteOperation(); }, u_);
}
int IoStatementState::EndIoStatement() {
return std::visit([](auto &x) { return x.get().EndIoStatement(); }, u_);
return common::visit([](auto &x) { return x.get().EndIoStatement(); }, u_);
}
ConnectionState &IoStatementState::GetConnectionState() {
return std::visit(
return common::visit(
[](auto &x) -> ConnectionState & { return x.get().GetConnectionState(); },
u_);
}
MutableModes &IoStatementState::mutableModes() {
return std::visit(
return common::visit(
[](auto &x) -> MutableModes & { return x.get().mutableModes(); }, u_);
}
bool IoStatementState::BeginReadingRecord() {
return std::visit([](auto &x) { return x.get().BeginReadingRecord(); }, u_);
return common::visit(
[](auto &x) { return x.get().BeginReadingRecord(); }, u_);
}
IoErrorHandler &IoStatementState::GetIoErrorHandler() const {
return std::visit(
return common::visit(
[](auto &x) -> IoErrorHandler & {
return static_cast<IoErrorHandler &>(x.get());
},
@ -559,7 +561,8 @@ IoErrorHandler &IoStatementState::GetIoErrorHandler() const {
}
ExternalFileUnit *IoStatementState::GetExternalFileUnit() const {
return std::visit([](auto &x) { return x.get().GetExternalFileUnit(); }, u_);
return common::visit(
[](auto &x) { return x.get().GetExternalFileUnit(); }, u_);
}
std::optional<char32_t> IoStatementState::GetCurrentChar(
@ -587,7 +590,7 @@ std::optional<char32_t> IoStatementState::GetCurrentChar(
}
bool IoStatementState::EmitRepeated(char ch, std::size_t n) {
return std::visit(
return common::visit(
[=](auto &x) {
for (std::size_t j{0}; j < n; ++j) {
if (!x.get().Emit(&ch, 1)) {
@ -683,22 +686,24 @@ bool IoStatementState::CheckForEndOfRecord() {
bool IoStatementState::Inquire(
InquiryKeywordHash inquiry, char *out, std::size_t chars) {
return std::visit(
return common::visit(
[&](auto &x) { return x.get().Inquire(inquiry, out, chars); }, u_);
}
bool IoStatementState::Inquire(InquiryKeywordHash inquiry, bool &out) {
return std::visit([&](auto &x) { return x.get().Inquire(inquiry, out); }, u_);
return common::visit(
[&](auto &x) { return x.get().Inquire(inquiry, out); }, u_);
}
bool IoStatementState::Inquire(
InquiryKeywordHash inquiry, std::int64_t id, bool &out) {
return std::visit(
return common::visit(
[&](auto &x) { return x.get().Inquire(inquiry, id, out); }, u_);
}
bool IoStatementState::Inquire(InquiryKeywordHash inquiry, std::int64_t &n) {
return std::visit([&](auto &x) { return x.get().Inquire(inquiry, n); }, u_);
return common::visit(
[&](auto &x) { return x.get().Inquire(inquiry, n); }, u_);
}
void IoStatementState::GotChar(int n) {

View File

@ -16,6 +16,7 @@
#include "format.h"
#include "internal-unit.h"
#include "io-error.h"
#include "flang/Common/visit.h"
#include "flang/Runtime/descriptor.h"
#include "flang/Runtime/io-api.h"
#include <functional>
@ -113,7 +114,7 @@ public:
// N.B.: this also works with base classes
template <typename A> A *get_if() const {
return std::visit(
return common::visit(
[](auto &x) -> A * {
if constexpr (std::is_convertible_v<decltype(x.get()), A &>) {
return &x.get();