[flang] Add & use a better visit()

Adds flang/include/flang/Common/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.

Differential Revision: https://reviews.llvm.org/D122441
This commit is contained in:
Peter Klausler 2022-03-23 14:05:50 -07:00
parent e25f4e4c4a
commit 2ab9990c9e
62 changed files with 1427 additions and 1297 deletions

View File

@ -23,6 +23,7 @@
#error g++ >= 7.2 is required #error g++ >= 7.2 is required
#endif #endif
#include "visit.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include <functional> #include <functional>
#include <list> #include <list>
@ -49,8 +50,8 @@ using namespace std::literals::string_literals;
namespace Fortran::common { namespace Fortran::common {
// Helper templates for combining a list of lambdas into an anonymous // Helper templates for combining a list of lambdas into an anonymous
// struct for use with std::visit() on a std::variant<> sum type. // struct for use with common::visit() on a std::variant<> sum type.
// E.g.: std::visit(visitors{ // E.g.: common::visit(visitors{
// [&](const firstType &x) { ... }, // [&](const firstType &x) { ... },
// [&](const secondType &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 // 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. // source variant must all be allowed in the destination variant type.
template <typename TOV, typename FROMV> TOV CopyVariant(const FROMV &u) { 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 // 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. // source variant must all be allowed in the destination variant type.
template <typename TOV, typename FROMV> template <typename TOV, typename FROMV>
common::IfNoLvalue<TOV, FROMV> MoveVariant(FROMV &&u) { common::IfNoLvalue<TOV, FROMV> MoveVariant(FROMV &&u) {
return std::visit( return common::visit(
[](auto &&x) -> TOV { return {std::move(x)}; }, std::move(u)); [](auto &&x) -> TOV { return {std::move(x)}; }, std::move(u));
} }

View File

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

View File

@ -0,0 +1,94 @@
//===-- 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
#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) EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
static constexpr DynamicType GetType() { return Result::GetType(); } static constexpr DynamicType GetType() { return Result::GetType(); }
int Rank() const { 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; llvm::raw_ostream &AsFortran(llvm::raw_ostream &o) const;
common::MapTemplate<Relational, DirectlyComparableTypes> u; common::MapTemplate<Relational, DirectlyComparableTypes> u;

View File

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

View File

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

View File

@ -167,7 +167,7 @@ private:
template <typename T> template <typename T>
MaybeExtentExpr GetArrayConstructorValueExtent( MaybeExtentExpr GetArrayConstructorValueExtent(
const ArrayConstructorValue<T> &value) const { const ArrayConstructorValue<T> &value) const {
return std::visit( return common::visit(
common::visitors{ common::visitors{
[&](const Expr<T> &x) -> MaybeExtentExpr { [&](const Expr<T> &x) -> MaybeExtentExpr {
if (auto xShape{ 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) { 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) { template <typename A> bool IsAssumedRank(const std::optional<A> &x) {
return x && IsAssumedRank(*x); return x && IsAssumedRank(*x);
@ -100,7 +100,7 @@ template <typename A> bool IsCoarray(const Designator<A> &designator) {
return false; return false;
} }
template <typename T> bool IsCoarray(const Expr<T> &expr) { 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) { template <typename A> bool IsCoarray(const std::optional<A> &x) {
return x && IsCoarray(*x); return x && IsCoarray(*x);
@ -177,11 +177,11 @@ auto UnwrapExpr(B &x) -> common::Constify<A, B> * {
return UnwrapExpr<A>(*expr); return UnwrapExpr<A>(*expr);
} }
} else if constexpr (std::is_same_v<Ty, Expr<SomeType>>) { } 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>) { } else if constexpr (!common::HasMember<A, TypelessExpression>) {
if constexpr (std::is_same_v<Ty, Expr<ResultType<A>>> || if constexpr (std::is_same_v<Ty, Expr<ResultType<A>>> ||
std::is_same_v<Ty, Expr<SomeKind<ResultType<A>::category>>>) { 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; return nullptr;
@ -217,15 +217,17 @@ auto UnwrapConvertedExpr(B &x) -> common::Constify<A, B> * {
return UnwrapConvertedExpr<A>(*expr); return UnwrapConvertedExpr<A>(*expr);
} }
} else if constexpr (std::is_same_v<Ty, Expr<SomeType>>) { } 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>) { } else if constexpr (!common::HasMember<A, TypelessExpression>) {
using Result = ResultType<A>; using Result = ResultType<A>;
if constexpr (std::is_same_v<Ty, Expr<Result>> || if constexpr (std::is_same_v<Ty, Expr<Result>> ||
std::is_same_v<Ty, Expr<SomeKind<Result::category>>>) { 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>> || } else if constexpr (std::is_same_v<Ty, Parentheses<Result>> ||
std::is_same_v<Ty, Convert<Result, Result::category>>) { std::is_same_v<Ty, Convert<Result, Result::category>>) {
return std::visit( return common::visit(
[](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.left().u); [](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.left().u);
} }
} }
@ -262,7 +264,7 @@ common::IfNoLvalue<std::optional<DataRef>, A> ExtractDataRef(
template <typename T> template <typename T>
std::optional<DataRef> ExtractDataRef( std::optional<DataRef> ExtractDataRef(
const Designator<T> &d, bool intoSubstring = false) { const Designator<T> &d, bool intoSubstring = false) {
return std::visit( return common::visit(
[=](const auto &x) -> std::optional<DataRef> { [=](const auto &x) -> std::optional<DataRef> {
if constexpr (common::HasMember<decltype(x), decltype(DataRef::u)>) { if constexpr (common::HasMember<decltype(x), decltype(DataRef::u)>) {
return DataRef{x}; return DataRef{x};
@ -279,7 +281,7 @@ std::optional<DataRef> ExtractDataRef(
template <typename T> template <typename T>
std::optional<DataRef> ExtractDataRef( std::optional<DataRef> ExtractDataRef(
const Expr<T> &expr, bool intoSubstring = false) { const Expr<T> &expr, bool intoSubstring = false) {
return std::visit( return common::visit(
[=](const auto &x) { return ExtractDataRef(x, intoSubstring); }, expr.u); [=](const auto &x) { return ExtractDataRef(x, intoSubstring); }, expr.u);
} }
template <typename A> template <typename A>
@ -328,7 +330,7 @@ bool IsArrayElement(const Expr<T> &expr, bool intoSubstring = true,
template <typename A> template <typename A>
std::optional<NamedEntity> ExtractNamedEntity(const A &x) { std::optional<NamedEntity> ExtractNamedEntity(const A &x) {
if (auto dataRef{ExtractDataRef(x, true)}) { if (auto dataRef{ExtractDataRef(x, true)}) {
return std::visit( return common::visit(
common::visitors{ common::visitors{
[](SymbolRef &&symbol) -> std::optional<NamedEntity> { [](SymbolRef &&symbol) -> std::optional<NamedEntity> {
return NamedEntity{symbol}; return NamedEntity{symbol};
@ -354,10 +356,10 @@ struct ExtractCoindexedObjectHelper {
std::optional<CoarrayRef> operator()(const CoarrayRef &x) const { return x; } std::optional<CoarrayRef> operator()(const CoarrayRef &x) const { return x; }
template <typename A> template <typename A>
std::optional<CoarrayRef> operator()(const Expr<A> &expr) const { 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 { 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 { std::optional<CoarrayRef> operator()(const NamedEntity &named) const {
if (const Component * component{named.UnwrapComponent()}) { if (const Component * component{named.UnwrapComponent()}) {
@ -449,7 +451,7 @@ Expr<TO> ConvertToType(Expr<SomeKind<FROMCAT>> &&x) {
ConvertToType<Part>(std::move(x)), Expr<Part>{Constant<Part>{zero}}}}; ConvertToType<Part>(std::move(x)), Expr<Part>{Constant<Part>{zero}}}};
} else if constexpr (FROMCAT == TypeCategory::Complex) { } else if constexpr (FROMCAT == TypeCategory::Complex) {
// Extract and convert the real component of a complex value // Extract and convert the real component of a complex value
return std::visit( return common::visit(
[&](auto &&z) { [&](auto &&z) {
using ZType = ResultType<decltype(z)>; using ZType = ResultType<decltype(z)>;
using Part = typename ZType::Part; using Part = typename ZType::Part;
@ -503,7 +505,7 @@ common::IfNoLvalue<Expr<Type<TC, TK>>, FROM> ConvertTo(
template <TypeCategory TC, typename FROM> template <TypeCategory TC, typename FROM>
common::IfNoLvalue<Expr<SomeKind<TC>>, FROM> ConvertTo( common::IfNoLvalue<Expr<SomeKind<TC>>, FROM> ConvertTo(
const Expr<SomeKind<TC>> &to, FROM &&from) { const Expr<SomeKind<TC>> &to, FROM &&from) {
return std::visit( return common::visit(
[&](const auto &toKindExpr) { [&](const auto &toKindExpr) {
using KindExpr = std::decay_t<decltype(toKindExpr)>; using KindExpr = std::decay_t<decltype(toKindExpr)>;
return AsCategoryExpr( return AsCategoryExpr(
@ -515,7 +517,7 @@ common::IfNoLvalue<Expr<SomeKind<TC>>, FROM> ConvertTo(
template <typename FROM> template <typename FROM>
common::IfNoLvalue<Expr<SomeType>, FROM> ConvertTo( common::IfNoLvalue<Expr<SomeType>, FROM> ConvertTo(
const Expr<SomeType> &to, FROM &&from) { const Expr<SomeType> &to, FROM &&from) {
return std::visit( return common::visit(
[&](const auto &toCatExpr) { [&](const auto &toCatExpr) {
return AsGenericExpr(ConvertTo(toCatExpr, std::move(from))); return AsGenericExpr(ConvertTo(toCatExpr, std::move(from)));
}, },
@ -565,7 +567,7 @@ using SameKindExprs =
template <TypeCategory CAT> template <TypeCategory CAT>
SameKindExprs<CAT, 2> AsSameKindExprs( SameKindExprs<CAT, 2> AsSameKindExprs(
Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) { Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) {
return std::visit( return common::visit(
[&](auto &&kx, auto &&ky) -> SameKindExprs<CAT, 2> { [&](auto &&kx, auto &&ky) -> SameKindExprs<CAT, 2> {
using XTy = ResultType<decltype(kx)>; using XTy = ResultType<decltype(kx)>;
using YTy = ResultType<decltype(ky)>; using YTy = ResultType<decltype(ky)>;
@ -626,7 +628,7 @@ Expr<SPECIFIC> Combine(Expr<SPECIFIC> &&x, Expr<SPECIFIC> &&y) {
template <template <typename> class OPR, TypeCategory CAT> template <template <typename> class OPR, TypeCategory CAT>
Expr<SomeKind<CAT>> PromoteAndCombine( Expr<SomeKind<CAT>> PromoteAndCombine(
Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) { Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) {
return std::visit( return common::visit(
[](auto &&xy) { [](auto &&xy) {
using Ty = ResultType<decltype(xy[0])>; using Ty = ResultType<decltype(xy[0])>;
return AsCategoryExpr( return AsCategoryExpr(
@ -727,7 +729,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) { 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); [](auto &xk) { return Expr<SomeKind<C>>{-std::move(xk)}; }, x.u);
} }
@ -872,7 +874,7 @@ std::optional<BaseObject> GetBaseObject(const Designator<T> &x) {
} }
template <typename T> template <typename T>
std::optional<BaseObject> GetBaseObject(const Expr<T> &x) { 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> template <typename A>
std::optional<BaseObject> GetBaseObject(const std::optional<A> &x) { std::optional<BaseObject> GetBaseObject(const std::optional<A> &x) {
@ -1012,7 +1014,8 @@ public:
return Expand(std::move(x.left())); // Constant<> can be parenthesized return Expand(std::move(x.left())); // Constant<> can be parenthesized
} }
template <typename T> Expr<T> Expand(Expr<T> &&x) { 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)); std::move(x.u));
} }

View File

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

View File

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

View File

@ -62,7 +62,7 @@ struct UnwrapperHelper {
template <typename A, typename... Bs> template <typename A, typename... Bs>
static const A *Unwrap(const std::variant<Bs...> &x) { 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> template <typename A, typename B>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,7 +30,7 @@ template <int KIND>
std::optional<Expr<SubscriptInteger>> std::optional<Expr<SubscriptInteger>>
Expr<Type<TypeCategory::Character, KIND>>::LEN() const { Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
using T = std::optional<Expr<SubscriptInteger>>; using T = std::optional<Expr<SubscriptInteger>>;
return std::visit( return common::visit(
common::visitors{ common::visitors{
[](const Constant<Result> &c) -> T { [](const Constant<Result> &c) -> T {
return AsExpr(Constant<SubscriptInteger>{c.LEN()}); 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 ArrayConstructor<Result> &a) -> T { return a.LEN(); },
[](const Parentheses<Result> &x) { return x.left().LEN(); }, [](const Parentheses<Result> &x) { return x.left().LEN(); },
[](const Convert<Result> &x) { [](const Convert<Result> &x) {
return std::visit( return common::visit(
[&](const auto &kx) { return kx.LEN(); }, x.left().u); [&](const auto &kx) { return kx.LEN(); }, x.left().u);
}, },
[](const Concat<KIND> &c) -> T { [](const Concat<KIND> &c) -> T {
@ -84,7 +84,7 @@ std::optional<DynamicType> ExpressionBase<A>::GetType() const {
if constexpr (IsLengthlessIntrinsicType<Result>) { if constexpr (IsLengthlessIntrinsicType<Result>) {
return Result::GetType(); return Result::GetType();
} else { } else {
return std::visit( return common::visit(
[&](const auto &x) -> std::optional<DynamicType> { [&](const auto &x) -> std::optional<DynamicType> {
if constexpr (!common::HasMember<decltype(x), TypelessExpression>) { if constexpr (!common::HasMember<decltype(x), TypelessExpression>) {
return x.GetType(); return x.GetType();
@ -96,7 +96,7 @@ std::optional<DynamicType> ExpressionBase<A>::GetType() const {
} }
template <typename A> int ExpressionBase<A>::Rank() const { template <typename A> int ExpressionBase<A>::Rank() const {
return std::visit( return common::visit(
[](const auto &x) { [](const auto &x) {
if constexpr (common::HasMember<decltype(x), TypelessExpression>) { if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
return 0; return 0;
@ -309,19 +309,19 @@ void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *p) {
} }
template <TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const { 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; }, [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
u); u);
} }
int Expr<SomeCharacter>::GetKind() const { int Expr<SomeCharacter>::GetKind() const {
return std::visit( return common::visit(
[](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; }, [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
u); u);
} }
std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const { 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 #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 lower{lowerBounds->at(dim)};
ConstantSubscript extent{extents->at(dim)}; ConstantSubscript extent{extents->at(dim)};
ConstantSubscript upper{lower + extent - 1}; ConstantSubscript upper{lower + extent - 1};
if (!std::visit( if (!common::visit(
common::visitors{ common::visitors{
[&](const IndirectSubscriptIntegerExpr &expr) { [&](const IndirectSubscriptIntegerExpr &expr) {
auto folded{ auto folded{
@ -169,7 +169,7 @@ std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator(
std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator( std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator(
const DataRef &dataRef, ConstantSubscript which) { const DataRef &dataRef, ConstantSubscript which) {
return std::visit( return common::visit(
[&](const auto &x) { return FoldDesignator(x, which); }, dataRef.u); [&](const auto &x) { return FoldDesignator(x, which); }, dataRef.u);
} }
@ -315,7 +315,7 @@ std::optional<Expr<SomeType>> OffsetToDesignator(FoldingContext &context,
// Pick a COMPLEX component // Pick a COMPLEX component
auto part{ auto part{
offset == 0 ? ComplexPart::Part::RE : ComplexPart::Part::IM}; offset == 0 ? ComplexPart::Part::RE : ComplexPart::Part::IM};
return std::visit( return common::visit(
[&](const auto &z) -> std::optional<Expr<SomeType>> { [&](const auto &z) -> std::optional<Expr<SomeType>> {
using PartType = typename ResultType<decltype(z)>::Part; using PartType = typename ResultType<decltype(z)>::Part;
return AsGenericExpr(Designator<PartType>{ComplexPart{ return AsGenericExpr(Designator<PartType>{ComplexPart{
@ -327,7 +327,7 @@ std::optional<Expr<SomeType>> OffsetToDesignator(FoldingContext &context,
std::get_if<Expr<SomeCharacter>>(&result->u)}) { std::get_if<Expr<SomeCharacter>>(&result->u)}) {
if (offset > 0 || size != static_cast<std::size_t>(*elementBytes)) { if (offset > 0 || size != static_cast<std::size_t>(*elementBytes)) {
// Select a substring // Select a substring
return std::visit( return common::visit(
[&](const auto &x) -> std::optional<Expr<SomeType>> { [&](const auto &x) -> std::optional<Expr<SomeType>> {
using T = typename std::decay_t<decltype(x)>::Result; using T = typename std::decay_t<decltype(x)>::Result;
return AsGenericExpr(Designator<T>{ return AsGenericExpr(Designator<T>{

View File

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

View File

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

View File

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

View File

@ -133,7 +133,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
} }
} else if (name == "scale") { } else if (name == "scale") {
if (const auto *byExpr{UnwrapExpr<Expr<SomeInteger>>(args[1])}) { if (const auto *byExpr{UnwrapExpr<Expr<SomeInteger>>(args[1])}) {
return std::visit( return common::visit(
[&](const auto &byVal) { [&](const auto &byVal) {
using TBY = ResultType<decltype(byVal)>; using TBY = ResultType<decltype(byVal)>;
return FoldElementalIntrinsic<T, T, TBY>(context, return FoldElementalIntrinsic<T, T, TBY>(context,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,7 +24,7 @@ public:
std::vector<LabelInfo> stack; std::vector<LabelInfo> stack;
for (auto i{block.begin()}, end{block.end()}; i != end; ++i) { for (auto i{block.begin()}, end{block.end()}; i != end; ++i) {
if (auto *executableConstruct{std::get_if<ExecutableConstruct>(&i->u)}) { if (auto *executableConstruct{std::get_if<ExecutableConstruct>(&i->u)}) {
std::visit( common::visit(
common::visitors{ common::visitors{
[](auto &) {}, [](auto &) {},
// Labels on end-stmt of constructs are accepted by f18 as an // 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}; const parser::Expr *parserSourceExpr{nullptr};
for (const parser::AllocOpt &allocOpt : for (const parser::AllocOpt &allocOpt :
std::get<std::list<parser::AllocOpt>>(allocateStmt.t)) { std::get<std::list<parser::AllocOpt>>(allocateStmt.t)) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::StatOrErrmsg &statOrErr) { [&](const parser::StatOrErrmsg &statOrErr) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::StatVariable &) { [&](const parser::StatVariable &) {
if (info.gotStat) { // C943 if (info.gotStat) { // C943

View File

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

View File

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

View File

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

View File

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

View File

@ -205,7 +205,7 @@ void CheckHelper::Check(const Symbol &symbol) {
const DeclTypeSpec *type{symbol.GetType()}; const DeclTypeSpec *type{symbol.GetType()};
const DerivedTypeSpec *derived{type ? type->AsDerived() : nullptr}; const DerivedTypeSpec *derived{type ? type->AsDerived() : nullptr};
bool isDone{false}; bool isDone{false};
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const UseDetails &x) { isDone = true; }, [&](const UseDetails &x) { isDone = true; },
[&](const HostAssocDetails &x) { [&](const HostAssocDetails &x) {
@ -1144,12 +1144,12 @@ void CheckHelper::CheckHostAssoc(
void CheckHelper::CheckGeneric( void CheckHelper::CheckGeneric(
const Symbol &symbol, const GenericDetails &details) { const Symbol &symbol, const GenericDetails &details) {
CheckSpecificsAreDistinguishable(symbol, details); CheckSpecificsAreDistinguishable(symbol, details);
std::visit(common::visitors{ common::visit(common::visitors{
[&](const GenericKind::DefinedIo &io) { [&](const GenericKind::DefinedIo &io) {
CheckDefinedIoProc(symbol, details, io); CheckDefinedIoProc(symbol, details, io);
}, },
[](const auto &) {}, [](const auto &) {},
}, },
details.kind().u); details.kind().u);
} }
@ -1186,7 +1186,7 @@ static bool ConflictsWithIntrinsicOperator(
auto arg0{std::get<DummyDataObject>(proc.dummyArguments[0].u).type}; auto arg0{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
auto type0{arg0.type()}; auto type0{arg0.type()};
if (proc.dummyArguments.size() == 1) { // unary if (proc.dummyArguments.size() == 1) { // unary
return std::visit( return common::visit(
common::visitors{ common::visitors{
[&](common::NumericOperator) { return IsIntrinsicNumeric(type0); }, [&](common::NumericOperator) { return IsIntrinsicNumeric(type0); },
[&](common::LogicalOperator) { return IsIntrinsicLogical(type0); }, [&](common::LogicalOperator) { return IsIntrinsicLogical(type0); },
@ -1198,7 +1198,7 @@ static bool ConflictsWithIntrinsicOperator(
auto arg1{std::get<DummyDataObject>(proc.dummyArguments[1].u).type}; auto arg1{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
auto type1{arg1.type()}; auto type1{arg1.type()};
int rank1{arg1.Rank()}; int rank1{arg1.Rank()};
return std::visit( return common::visit(
common::visitors{ common::visitors{
[&](common::NumericOperator) { [&](common::NumericOperator) {
return IsIntrinsicNumeric(type0, rank0, type1, rank1); return IsIntrinsicNumeric(type0, rank0, type1, rank1);
@ -1262,27 +1262,27 @@ std::optional<parser::MessageFixedText> CheckHelper::CheckNumberOfArgs(
return std::nullopt; return std::nullopt;
} }
std::size_t min{2}, max{2}; // allowed number of args; default is binary std::size_t min{2}, max{2}; // allowed number of args; default is binary
std::visit(common::visitors{ common::visit(common::visitors{
[&](const common::NumericOperator &x) { [&](const common::NumericOperator &x) {
if (x == common::NumericOperator::Add || if (x == common::NumericOperator::Add ||
x == common::NumericOperator::Subtract) { x == common::NumericOperator::Subtract) {
min = 1; // + and - are unary or binary min = 1; // + and - are unary or binary
} }
}, },
[&](const common::LogicalOperator &x) { [&](const common::LogicalOperator &x) {
if (x == common::LogicalOperator::Not) { if (x == common::LogicalOperator::Not) {
min = 1; // .NOT. is unary min = 1; // .NOT. is unary
max = 1; max = 1;
} }
}, },
[](const common::RelationalOperator &) { [](const common::RelationalOperator &) {
// all are binary // all are binary
}, },
[](const GenericKind::OtherKind &x) { [](const GenericKind::OtherKind &x) {
CHECK(x == GenericKind::OtherKind::Concat); CHECK(x == GenericKind::OtherKind::Concat);
}, },
[](const auto &) { DIE("expected intrinsic operator"); }, [](const auto &) { DIE("expected intrinsic operator"); },
}, },
kind.u); kind.u);
if (nargs >= min && nargs <= max) { if (nargs >= min && nargs <= max) {
return std::nullopt; return std::nullopt;
@ -2189,7 +2189,7 @@ void SubprogramMatchHelper::Check(
void SubprogramMatchHelper::CheckDummyArg(const Symbol &symbol1, void SubprogramMatchHelper::CheckDummyArg(const Symbol &symbol1,
const Symbol &symbol2, const DummyArgument &arg1, const Symbol &symbol2, const DummyArgument &arg1,
const DummyArgument &arg2) { const DummyArgument &arg2) {
std::visit(common::visitors{ common::visit(common::visitors{
[&](const DummyDataObject &obj1, const DummyDataObject &obj2) { [&](const DummyDataObject &obj1, const DummyDataObject &obj2) {
CheckDummyDataObject(symbol1, symbol2, obj1, obj2); CheckDummyDataObject(symbol1, symbol2, obj1, obj2);
}, },

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -364,18 +364,18 @@ public:
return false; return false;
} }
bool Pre(const parser::OmpLinearClause &x) { bool Pre(const parser::OmpLinearClause &x) {
std::visit(common::visitors{ common::visit(common::visitors{
[&](const parser::OmpLinearClause::WithoutModifier [&](const parser::OmpLinearClause::WithoutModifier
&linearWithoutModifier) { &linearWithoutModifier) {
ResolveOmpNameList( ResolveOmpNameList(linearWithoutModifier.names,
linearWithoutModifier.names, Symbol::Flag::OmpLinear); Symbol::Flag::OmpLinear);
}, },
[&](const parser::OmpLinearClause::WithModifier [&](const parser::OmpLinearClause::WithModifier
&linearWithModifier) { &linearWithModifier) {
ResolveOmpNameList( ResolveOmpNameList(
linearWithModifier.names, Symbol::Flag::OmpLinear); linearWithModifier.names, Symbol::Flag::OmpLinear);
}, },
}, },
x.u); x.u);
return false; return false;
} }
@ -756,7 +756,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
static bool IsLastNameArray(const parser::Designator &designator) { static bool IsLastNameArray(const parser::Designator &designator) {
const auto &name{GetLastName(designator)}; const auto &name{GetLastName(designator)};
const evaluate::DataRef dataRef{*(name.symbol)}; const evaluate::DataRef dataRef{*(name.symbol)};
return std::visit( return common::visit(
common::visitors{ common::visitors{
[](const evaluate::SymbolRef &ref) { return ref->Rank() > 0; }, [](const evaluate::SymbolRef &ref) { return ref->Rank() > 0; },
[](const evaluate::ArrayRef &aref) { [](const evaluate::ArrayRef &aref) {
@ -771,7 +771,7 @@ static bool IsLastNameArray(const parser::Designator &designator) {
void AccAttributeVisitor::AllowOnlyArrayAndSubArray( void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
const parser::AccObjectList &objectList) { const parser::AccObjectList &objectList) {
for (const auto &accObject : objectList.v) { for (const auto &accObject : objectList.v) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::Designator &designator) { [&](const parser::Designator &designator) {
if (!IsLastNameArray(designator)) { if (!IsLastNameArray(designator)) {
@ -798,7 +798,7 @@ void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
void AccAttributeVisitor::DoNotAllowAssumedSizedArray( void AccAttributeVisitor::DoNotAllowAssumedSizedArray(
const parser::AccObjectList &objectList) { const parser::AccObjectList &objectList) {
for (const auto &accObject : objectList.v) { for (const auto &accObject : objectList.v) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::Designator &designator) { [&](const parser::Designator &designator) {
const auto &name{GetLastName(designator)}; const auto &name{GetLastName(designator)};
@ -883,7 +883,7 @@ void AccAttributeVisitor::PrivatizeAssociatedLoopIndex(
void AccAttributeVisitor::EnsureAllocatableOrPointer( void AccAttributeVisitor::EnsureAllocatableOrPointer(
const llvm::acc::Clause clause, const parser::AccObjectList &objectList) { const llvm::acc::Clause clause, const parser::AccObjectList &objectList) {
for (const auto &accObject : objectList.v) { for (const auto &accObject : objectList.v) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::Designator &designator) { [&](const parser::Designator &designator) {
const auto &lastName{GetLastName(designator)}; const auto &lastName{GetLastName(designator)};
@ -977,7 +977,7 @@ void AccAttributeVisitor::ResolveAccObjectList(
void AccAttributeVisitor::ResolveAccObject( void AccAttributeVisitor::ResolveAccObject(
const parser::AccObject &accObject, Symbol::Flag accFlag) { const parser::AccObject &accObject, Symbol::Flag accFlag) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::Designator &designator) { [&](const parser::Designator &designator) {
if (const auto *name{GetDesignatorNameIfDataRef(designator)}) { if (const auto *name{GetDesignatorNameIfDataRef(designator)}) {
@ -1572,7 +1572,7 @@ void OmpAttributeVisitor::ResolveOmpObjectList(
void OmpAttributeVisitor::ResolveOmpObject( void OmpAttributeVisitor::ResolveOmpObject(
const parser::OmpObject &ompObject, Symbol::Flag ompFlag) { const parser::OmpObject &ompObject, Symbol::Flag ompFlag) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::Designator &designator) { [&](const parser::Designator &designator) {
if (const auto *name{GetDesignatorNameIfDataRef(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) { void GenericSpecInfo::Analyze(const parser::GenericSpec &x) {
symbolName_ = x.source; symbolName_ = x.source;
kind_ = std::visit( kind_ = common::visit(
common::visitors{ common::visitors{
[&](const parser::Name &y) -> GenericKind { [&](const parser::Name &y) -> GenericKind {
parseName_ = &y; parseName_ = &y;
@ -134,7 +134,7 @@ void GenericSpecInfo::Analyze(const parser::GenericSpec &x) {
return GenericKind::OtherKind::Name; return GenericKind::OtherKind::Name;
}, },
[&](const parser::DefinedOperator &y) { [&](const parser::DefinedOperator &y) {
return std::visit( return common::visit(
common::visitors{ common::visitors{
[&](const parser::DefinedOpName &z) -> GenericKind { [&](const parser::DefinedOpName &z) -> GenericKind {
Analyze(z); Analyze(z);
@ -265,19 +265,20 @@ ArraySpec AnalyzeCoarraySpec(
} }
ArraySpec ArraySpecAnalyzer::Analyze(const parser::ComponentArraySpec &x) { 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()); CHECK(!arraySpec_.empty());
return arraySpec_; return arraySpec_;
} }
ArraySpec ArraySpecAnalyzer::Analyze(const parser::ArraySpec &x) { ArraySpec ArraySpecAnalyzer::Analyze(const parser::ArraySpec &x) {
std::visit(common::visitors{ common::visit(common::visitors{
[&](const parser::AssumedSizeSpec &y) { [&](const parser::AssumedSizeSpec &y) {
Analyze(std::get<std::list<parser::ExplicitShapeSpec>>(y.t)); Analyze(
Analyze(std::get<parser::AssumedImpliedSpec>(y.t)); 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); }, [&](const parser::ImpliedShapeSpec &y) { Analyze(y.v); },
}, [&](const auto &y) { Analyze(y); },
},
x.u); x.u);
CHECK(!arraySpec_.empty()); CHECK(!arraySpec_.empty());
return arraySpec_; return arraySpec_;
@ -289,7 +290,7 @@ ArraySpec ArraySpecAnalyzer::AnalyzeDeferredShapeSpecList(
return arraySpec_; return arraySpec_;
} }
ArraySpec ArraySpecAnalyzer::Analyze(const parser::CoarraySpec &x) { ArraySpec ArraySpecAnalyzer::Analyze(const parser::CoarraySpec &x) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::DeferredCoshapeSpecList &y) { MakeDeferred(y.v); }, [&](const parser::DeferredCoshapeSpecList &y) { MakeDeferred(y.v); },
[&](const parser::ExplicitCoshapeSpec &y) { [&](const parser::ExplicitCoshapeSpec &y) {
@ -495,7 +496,7 @@ const EquivalenceObject *EquivalenceSets::Find(
} }
bool EquivalenceSets::CheckDesignator(const parser::Designator &designator) { bool EquivalenceSets::CheckDesignator(const parser::Designator &designator) {
return std::visit( return common::visit(
common::visitors{ common::visitors{
[&](const parser::DataRef &x) { [&](const parser::DataRef &x) {
return CheckDataRef(designator.source, x); return CheckDataRef(designator.source, x);
@ -520,7 +521,7 @@ bool EquivalenceSets::CheckDesignator(const parser::Designator &designator) {
bool EquivalenceSets::CheckDataRef( bool EquivalenceSets::CheckDataRef(
const parser::CharBlock &source, const parser::DataRef &x) { const parser::CharBlock &source, const parser::DataRef &x) {
return std::visit( return common::visit(
common::visitors{ common::visitors{
[&](const parser::Name &name) { return CheckObject(name); }, [&](const parser::Name &name) { return CheckObject(name); },
[&](const common::Indirection<parser::StructureComponent> &) { [&](const common::Indirection<parser::StructureComponent> &) {
@ -532,7 +533,7 @@ bool EquivalenceSets::CheckDataRef(
[&](const common::Indirection<parser::ArrayElement> &elem) { [&](const common::Indirection<parser::ArrayElement> &elem) {
bool ok{CheckDataRef(source, elem.value().base)}; bool ok{CheckDataRef(source, elem.value().base)};
for (const auto &subscript : elem.value().subscripts) { for (const auto &subscript : elem.value().subscripts) {
ok &= std::visit( ok &= common::visit(
common::visitors{ common::visitors{
[&](const parser::SubscriptTriplet &) { [&](const parser::SubscriptTriplet &) {
context_.Say(source, // C924, R872 context_.Say(source, // C924, R872

View File

@ -17,6 +17,7 @@
#include "flang/Common/default-kinds.h" #include "flang/Common/default-kinds.h"
#include "flang/Common/indirection.h" #include "flang/Common/indirection.h"
#include "flang/Common/restorer.h" #include "flang/Common/restorer.h"
#include "flang/Common/visit.h"
#include "flang/Evaluate/characteristics.h" #include "flang/Evaluate/characteristics.h"
#include "flang/Evaluate/check-expression.h" #include "flang/Evaluate/check-expression.h"
#include "flang/Evaluate/common.h" #include "flang/Evaluate/common.h"
@ -1588,11 +1589,11 @@ bool AttrsVisitor::SetPassNameOn(Symbol &symbol) {
if (!passName_) { if (!passName_) {
return false; return false;
} }
std::visit(common::visitors{ common::visit(common::visitors{
[&](ProcEntityDetails &x) { x.set_passName(*passName_); }, [&](ProcEntityDetails &x) { x.set_passName(*passName_); },
[&](ProcBindingDetails &x) { x.set_passName(*passName_); }, [&](ProcBindingDetails &x) { x.set_passName(*passName_); },
[](auto &) { common::die("unexpected pass name"); }, [](auto &) { common::die("unexpected pass name"); },
}, },
symbol.details()); symbol.details());
return true; return true;
} }
@ -1796,20 +1797,20 @@ void ImplicitRulesVisitor::Post(const parser::ParameterStmt &) {
bool ImplicitRulesVisitor::Pre(const parser::ImplicitStmt &x) { bool ImplicitRulesVisitor::Pre(const parser::ImplicitStmt &x) {
bool result{ bool result{
std::visit(common::visitors{ common::visit(common::visitors{
[&](const std::list<ImplicitNoneNameSpec> &y) { [&](const std::list<ImplicitNoneNameSpec> &y) {
return HandleImplicitNone(y); return HandleImplicitNone(y);
}, },
[&](const std::list<parser::ImplicitSpec> &) { [&](const std::list<parser::ImplicitSpec> &) {
if (prevImplicitNoneType_) { if (prevImplicitNoneType_) {
Say("IMPLICIT statement after IMPLICIT NONE or " Say("IMPLICIT statement after IMPLICIT NONE or "
"IMPLICIT NONE(TYPE) statement"_err_en_US); "IMPLICIT NONE(TYPE) statement"_err_en_US);
return false; return false;
} }
implicitRules_->set_isImplicitNoneType(false); implicitRules_->set_isImplicitNoneType(false);
return true; return true;
}, },
}, },
x.u)}; x.u)};
prevImplicit_ = currStmtSource(); prevImplicit_ = currStmtSource();
return result; return result;
@ -2208,17 +2209,17 @@ void ScopeHandler::EraseSymbol(const parser::Name &name) {
static bool NeedsType(const Symbol &symbol) { static bool NeedsType(const Symbol &symbol) {
return !symbol.GetType() && return !symbol.GetType() &&
std::visit(common::visitors{ common::visit(common::visitors{
[](const EntityDetails &) { return true; }, [](const EntityDetails &) { return true; },
[](const ObjectEntityDetails &) { return true; }, [](const ObjectEntityDetails &) { return true; },
[](const AssocEntityDetails &) { return true; }, [](const AssocEntityDetails &) { return true; },
[&](const ProcEntityDetails &p) { [&](const ProcEntityDetails &p) {
return symbol.test(Symbol::Flag::Function) && return symbol.test(Symbol::Flag::Function) &&
!symbol.attrs().test(Attr::INTRINSIC) && !symbol.attrs().test(Attr::INTRINSIC) &&
!p.interface().type() && !p.interface().symbol(); !p.interface().type() && !p.interface().symbol();
}, },
[](const auto &) { return false; }, [](const auto &) { return false; },
}, },
symbol.details()); symbol.details());
} }
@ -2446,18 +2447,18 @@ void ScopeHandler::MakeExternal(Symbol &symbol) {
// ModuleVisitor implementation // ModuleVisitor implementation
bool ModuleVisitor::Pre(const parser::Only &x) { bool ModuleVisitor::Pre(const parser::Only &x) {
std::visit(common::visitors{ common::visit(common::visitors{
[&](const Indirection<parser::GenericSpec> &generic) { [&](const Indirection<parser::GenericSpec> &generic) {
GenericSpecInfo genericSpecInfo{generic.value()}; GenericSpecInfo genericSpecInfo{generic.value()};
AddUseOnly(genericSpecInfo.symbolName()); AddUseOnly(genericSpecInfo.symbolName());
AddUse(genericSpecInfo); AddUse(genericSpecInfo);
}, },
[&](const parser::Name &name) { [&](const parser::Name &name) {
AddUseOnly(name.source); AddUseOnly(name.source);
Resolve(name, AddUse(name.source, name.source).use); Resolve(name, AddUse(name.source, name.source).use);
}, },
[&](const parser::Rename &rename) { Walk(rename); }, [&](const parser::Rename &rename) { Walk(rename); },
}, },
x.u); x.u);
return false; return false;
} }
@ -2522,14 +2523,14 @@ void ModuleVisitor::Post(const parser::UseStmt &x) {
// then add a use for each public name that was not renamed. // then add a use for each public name that was not renamed.
std::set<SourceName> useNames; std::set<SourceName> useNames;
for (const auto &rename : *list) { for (const auto &rename : *list) {
std::visit(common::visitors{ common::visit(common::visitors{
[&](const parser::Rename::Names &names) { [&](const parser::Rename::Names &names) {
useNames.insert(std::get<1>(names.t).source); useNames.insert(std::get<1>(names.t).source);
}, },
[&](const parser::Rename::Operators &ops) { [&](const parser::Rename::Operators &ops) {
useNames.insert(std::get<1>(ops.t).v.source); useNames.insert(std::get<1>(ops.t).v.source);
}, },
}, },
rename.u); rename.u);
} }
for (const auto &[name, symbol] : *useModuleScope_) { for (const auto &[name, symbol] : *useModuleScope_) {
@ -3224,7 +3225,7 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
auto &effectiveResultName{*(resultName ? resultName : &name)}; auto &effectiveResultName{*(resultName ? resultName : &name)};
resultSymbol = FindInScope(currScope(), effectiveResultName); resultSymbol = FindInScope(currScope(), effectiveResultName);
if (resultSymbol) { // C1574 if (resultSymbol) { // C1574
std::visit( common::visit(
common::visitors{[](EntityDetails &x) { x.set_funcResult(true); }, common::visitors{[](EntityDetails &x) { x.set_funcResult(true); },
[](ObjectEntityDetails &x) { x.set_funcResult(true); }, [](ObjectEntityDetails &x) { x.set_funcResult(true); },
[](ProcEntityDetails &x) { x.set_funcResult(true); }, [](ProcEntityDetails &x) { x.set_funcResult(true); },
@ -3255,7 +3256,7 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) { if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
Symbol *dummy{FindSymbol(*dummyName)}; Symbol *dummy{FindSymbol(*dummyName)};
if (dummy) { if (dummy) {
std::visit( common::visit(
common::visitors{[](EntityDetails &x) { x.set_isDummy(); }, common::visitors{[](EntityDetails &x) { x.set_isDummy(); },
[](ObjectEntityDetails &x) { x.set_isDummy(); }, [](ObjectEntityDetails &x) { x.set_isDummy(); },
[](ProcEntityDetails &x) { x.set_isDummy(); }, [](ProcEntityDetails &x) { x.set_isDummy(); },
@ -5493,7 +5494,7 @@ bool DeclarationVisitor::OkToAddComponent(
ParamValue DeclarationVisitor::GetParamValue( ParamValue DeclarationVisitor::GetParamValue(
const parser::TypeParamValue &x, common::TypeParamAttr attr) { const parser::TypeParamValue &x, common::TypeParamAttr attr) {
return std::visit( return common::visit(
common::visitors{ common::visitors{
[=](const parser::ScalarIntExpr &x) { // C704 [=](const parser::ScalarIntExpr &x) { // C704
return ParamValue{EvaluateIntExpr(x), attr}; return ParamValue{EvaluateIntExpr(x), attr};
@ -5652,7 +5653,7 @@ bool ConstructVisitor::Pre(const parser::DataImpliedDo &x) {
// statement so that the predicate IsInitialized() will be true // statement so that the predicate IsInitialized() will be true
// during semantic analysis before the symbol's initializer is constructed. // during semantic analysis before the symbol's initializer is constructed.
bool ConstructVisitor::Pre(const parser::DataIDoObject &x) { bool ConstructVisitor::Pre(const parser::DataIDoObject &x) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::Scalar<Indirection<parser::Designator>> &y) { [&](const parser::Scalar<Indirection<parser::Designator>> &y) {
Walk(y.thing.value()); Walk(y.thing.value());
@ -5668,20 +5669,21 @@ bool ConstructVisitor::Pre(const parser::DataIDoObject &x) {
} }
bool ConstructVisitor::Pre(const parser::DataStmtObject &x) { bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
std::visit(common::visitors{ common::visit(common::visitors{
[&](const Indirection<parser::Variable> &y) { [&](const Indirection<parser::Variable> &y) {
Walk(y.value()); Walk(y.value());
const parser::Name &first{parser::GetFirstName(y.value())}; const parser::Name &first{
if (first.symbol) { parser::GetFirstName(y.value())};
first.symbol->set(Symbol::Flag::InDataStmt); if (first.symbol) {
} first.symbol->set(Symbol::Flag::InDataStmt);
}, }
[&](const parser::DataImpliedDo &y) { },
PushScope(Scope::Kind::ImpliedDos, nullptr); [&](const parser::DataImpliedDo &y) {
Walk(y); PushScope(Scope::Kind::ImpliedDos, nullptr);
PopScope(); Walk(y);
}, PopScope();
}, },
},
x.u); x.u);
return false; return false;
} }
@ -5961,9 +5963,9 @@ void ConstructVisitor::SetTypeFromAssociation(Symbol &symbol) {
evaluate::UnwrapExpr<evaluate::Expr<evaluate::SomeCharacter>>( evaluate::UnwrapExpr<evaluate::Expr<evaluate::SomeCharacter>>(
expr)}) { expr)}) {
symbol.SetType(ToDeclTypeSpec(std::move(*type), symbol.SetType(ToDeclTypeSpec(std::move(*type),
FoldExpr( FoldExpr(common::visit(
std::visit([](const auto &kindChar) { return kindChar.LEN(); }, [](const auto &kindChar) { return kindChar.LEN(); },
charExpr->u)))); charExpr->u))));
} else { } else {
symbol.SetType(ToDeclTypeSpec(std::move(*type))); symbol.SetType(ToDeclTypeSpec(std::move(*type)));
} }
@ -5986,14 +5988,14 @@ void ConstructVisitor::SetAttrsFromAssociation(Symbol &symbol) {
ConstructVisitor::Selector ConstructVisitor::ResolveSelector( ConstructVisitor::Selector ConstructVisitor::ResolveSelector(
const parser::Selector &x) { const parser::Selector &x) {
return std::visit(common::visitors{ return common::visit(common::visitors{
[&](const parser::Expr &expr) { [&](const parser::Expr &expr) {
return Selector{expr.source, EvaluateExpr(x)}; return Selector{expr.source, EvaluateExpr(x)};
}, },
[&](const parser::Variable &var) { [&](const parser::Variable &var) {
return Selector{var.GetSource(), EvaluateExpr(x)}; return Selector{var.GetSource(), EvaluateExpr(x)};
}, },
}, },
x.u); x.u);
} }
@ -6123,7 +6125,7 @@ const parser::Name *DeclarationVisitor::ResolveStructureComponent(
const parser::Name *DeclarationVisitor::ResolveDesignator( const parser::Name *DeclarationVisitor::ResolveDesignator(
const parser::Designator &x) { const parser::Designator &x) {
return std::visit( return common::visit(
common::visitors{ common::visitors{
[&](const parser::DataRef &x) { return ResolveDataRef(x); }, [&](const parser::DataRef &x) { return ResolveDataRef(x); },
[&](const parser::Substring &x) { [&](const parser::Substring &x) {
@ -6135,7 +6137,7 @@ const parser::Name *DeclarationVisitor::ResolveDesignator(
const parser::Name *DeclarationVisitor::ResolveDataRef( const parser::Name *DeclarationVisitor::ResolveDataRef(
const parser::DataRef &x) { const parser::DataRef &x) {
return std::visit( return common::visit(
common::visitors{ common::visitors{
[=](const parser::Name &y) { return ResolveName(y); }, [=](const parser::Name &y) { return ResolveName(y); },
[=](const Indirection<parser::StructureComponent> &y) { [=](const Indirection<parser::StructureComponent> &y) {
@ -6343,7 +6345,7 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
if (auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) { if (auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) {
// TODO: check C762 - all bounds and type parameters of component // TODO: check C762 - all bounds and type parameters of component
// are colons or constant expressions if component is initialized // are colons or constant expressions if component is initialized
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::ConstantExpr &expr) { [&](const parser::ConstantExpr &expr) {
NonPointerInitialization(name, expr); NonPointerInitialization(name, expr);
@ -6454,7 +6456,7 @@ void DeclarationVisitor::NonPointerInitialization(
void ResolveNamesVisitor::HandleCall( void ResolveNamesVisitor::HandleCall(
Symbol::Flag procFlag, const parser::Call &call) { Symbol::Flag procFlag, const parser::Call &call) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::Name &x) { HandleProcedureName(procFlag, x); }, [&](const parser::Name &x) { HandleProcedureName(procFlag, x); },
[&](const parser::ProcComponentRef &x) { Walk(x); }, [&](const parser::ProcComponentRef &x) { Walk(x); },
@ -6631,7 +6633,7 @@ bool ModuleVisitor::Pre(const parser::AccessStmt &x) {
defaultAccess_ = accessAttr; defaultAccess_ = accessAttr;
} else { } else {
for (const auto &accessId : accessIds) { for (const auto &accessId : accessIds) {
std::visit( common::visit(
common::visitors{ common::visitors{
[=](const parser::Name &y) { [=](const parser::Name &y) {
Resolve(y, SetAccess(y.source, accessAttr)); Resolve(y, SetAccess(y.source, accessAttr));
@ -6718,7 +6720,7 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
// Initial processing on specification constructs, before visiting them. // Initial processing on specification constructs, before visiting them.
void ResolveNamesVisitor::PreSpecificationConstruct( void ResolveNamesVisitor::PreSpecificationConstruct(
const parser::SpecificationConstruct &spec) { const parser::SpecificationConstruct &spec) {
std::visit( common::visit(
common::visitors{ common::visitors{
[&](const parser::Statement<Indirection<parser::GenericStmt>> &y) { [&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {
CreateGeneric(std::get<parser::GenericSpec>(y.statement.value().t)); CreateGeneric(std::get<parser::GenericSpec>(y.statement.value().t));
@ -6907,21 +6909,21 @@ bool ResolveNamesVisitor::Pre(const parser::ImplicitStmt &x) {
} }
void ResolveNamesVisitor::Post(const parser::PointerObject &x) { void ResolveNamesVisitor::Post(const parser::PointerObject &x) {
std::visit(common::visitors{ common::visit(common::visitors{
[&](const parser::Name &x) { ResolveName(x); }, [&](const parser::Name &x) { ResolveName(x); },
[&](const parser::StructureComponent &x) { [&](const parser::StructureComponent &x) {
ResolveStructureComponent(x); ResolveStructureComponent(x);
}, },
}, },
x.u); x.u);
} }
void ResolveNamesVisitor::Post(const parser::AllocateObject &x) { void ResolveNamesVisitor::Post(const parser::AllocateObject &x) {
std::visit(common::visitors{ common::visit(common::visitors{
[&](const parser::Name &x) { ResolveName(x); }, [&](const parser::Name &x) { ResolveName(x); },
[&](const parser::StructureComponent &x) { [&](const parser::StructureComponent &x) {
ResolveStructureComponent(x); ResolveStructureComponent(x);
}, },
}, },
x.u); x.u);
} }
@ -7054,7 +7056,7 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
Scope &scope{currScope()}; Scope &scope{currScope()};
node.set_scope(scope); node.set_scope(scope);
AddSubpNames(node); AddSubpNames(node);
std::visit( common::visit(
[&](const auto *x) { [&](const auto *x) {
if (x) { if (x) {
Walk(*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 // the I/O unit in situ to a FileUnitNumber so that automatic expression
// constraint checking will be applied. // constraint checking will be applied.
auto source{var->GetSource()}; auto source{var->GetSource()};
auto expr{std::visit( auto expr{common::visit(
[](auto &&indirection) { [](auto &&indirection) {
return parser::Expr{std::move(indirection)}; return parser::Expr{std::move(indirection)};
}, },
@ -159,7 +159,7 @@ void RewriteMutator::Post(parser::ReadStmt &x) {
const parser::Name &last{parser::GetLastName(*var)}; const parser::Name &last{parser::GetLastName(*var)};
DeclTypeSpec *type{last.symbol ? last.symbol->GetType() : nullptr}; DeclTypeSpec *type{last.symbol ? last.symbol->GetType() : nullptr};
if (type && type->category() == DeclTypeSpec::Character) { if (type && type->category() == DeclTypeSpec::Character) {
x.format = std::visit( x.format = common::visit(
[](auto &&indirection) { [](auto &&indirection) {
return parser::Expr{std::move(indirection)}; return parser::Expr{std::move(indirection)};
}, },

View File

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

View File

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

View File

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

View File

@ -450,26 +450,26 @@ int ExternalFormattedIoStatementState<DIR, CHAR>::EndIoStatement() {
} }
std::optional<DataEdit> IoStatementState::GetNextDataEdit(int n) { std::optional<DataEdit> IoStatementState::GetNextDataEdit(int n) {
return std::visit( return common::visit(
[&](auto &x) { return x.get().GetNextDataEdit(*this, n); }, u_); [&](auto &x) { return x.get().GetNextDataEdit(*this, n); }, u_);
} }
bool IoStatementState::Emit( bool IoStatementState::Emit(
const char *data, std::size_t n, std::size_t elementBytes) { 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_); [=](auto &x) { return x.get().Emit(data, n, elementBytes); }, u_);
} }
bool IoStatementState::Emit(const char *data, std::size_t n) { 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) { 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) { 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> template <typename CHAR>
@ -498,55 +498,57 @@ bool IoStatementState::EmitEncoded(const CHAR *data0, std::size_t chars) {
bool IoStatementState::Receive( bool IoStatementState::Receive(
char *data, std::size_t n, std::size_t elementBytes) { 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_); [=](auto &x) { return x.get().Receive(data, n, elementBytes); }, u_);
} }
std::size_t IoStatementState::GetNextInputBytes(const char *&p) { 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) { 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() { 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) { 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) { 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() { void IoStatementState::CompleteOperation() {
std::visit([](auto &x) { x.get().CompleteOperation(); }, u_); common::visit([](auto &x) { x.get().CompleteOperation(); }, u_);
} }
int IoStatementState::EndIoStatement() { 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() { ConnectionState &IoStatementState::GetConnectionState() {
return std::visit( return common::visit(
[](auto &x) -> ConnectionState & { return x.get().GetConnectionState(); }, [](auto &x) -> ConnectionState & { return x.get().GetConnectionState(); },
u_); u_);
} }
MutableModes &IoStatementState::mutableModes() { MutableModes &IoStatementState::mutableModes() {
return std::visit( return common::visit(
[](auto &x) -> MutableModes & { return x.get().mutableModes(); }, u_); [](auto &x) -> MutableModes & { return x.get().mutableModes(); }, u_);
} }
bool IoStatementState::BeginReadingRecord() { 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 { IoErrorHandler &IoStatementState::GetIoErrorHandler() const {
return std::visit( return common::visit(
[](auto &x) -> IoErrorHandler & { [](auto &x) -> IoErrorHandler & {
return static_cast<IoErrorHandler &>(x.get()); return static_cast<IoErrorHandler &>(x.get());
}, },
@ -554,7 +556,8 @@ IoErrorHandler &IoStatementState::GetIoErrorHandler() const {
} }
ExternalFileUnit *IoStatementState::GetExternalFileUnit() 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( std::optional<char32_t> IoStatementState::GetCurrentChar(
@ -582,7 +585,7 @@ std::optional<char32_t> IoStatementState::GetCurrentChar(
} }
bool IoStatementState::EmitRepeated(char ch, std::size_t n) { bool IoStatementState::EmitRepeated(char ch, std::size_t n) {
return std::visit( return common::visit(
[=](auto &x) { [=](auto &x) {
for (std::size_t j{0}; j < n; ++j) { for (std::size_t j{0}; j < n; ++j) {
if (!x.get().Emit(&ch, 1)) { if (!x.get().Emit(&ch, 1)) {
@ -678,22 +681,24 @@ bool IoStatementState::CheckForEndOfRecord() {
bool IoStatementState::Inquire( bool IoStatementState::Inquire(
InquiryKeywordHash inquiry, char *out, std::size_t chars) { InquiryKeywordHash inquiry, char *out, std::size_t chars) {
return std::visit( return common::visit(
[&](auto &x) { return x.get().Inquire(inquiry, out, chars); }, u_); [&](auto &x) { return x.get().Inquire(inquiry, out, chars); }, u_);
} }
bool IoStatementState::Inquire(InquiryKeywordHash inquiry, bool &out) { 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( bool IoStatementState::Inquire(
InquiryKeywordHash inquiry, std::int64_t id, bool &out) { InquiryKeywordHash inquiry, std::int64_t id, bool &out) {
return std::visit( return common::visit(
[&](auto &x) { return x.get().Inquire(inquiry, id, out); }, u_); [&](auto &x) { return x.get().Inquire(inquiry, id, out); }, u_);
} }
bool IoStatementState::Inquire(InquiryKeywordHash inquiry, std::int64_t &n) { 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) { void IoStatementState::GotChar(int n) {

View File

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