forked from OSchip/llvm-project
[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:
parent
e25f4e4c4a
commit
2ab9990c9e
|
@ -23,6 +23,7 @@
|
|||
#error g++ >= 7.2 is required
|
||||
#endif
|
||||
|
||||
#include "visit.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <functional>
|
||||
#include <list>
|
||||
|
@ -49,8 +50,8 @@ using namespace std::literals::string_literals;
|
|||
namespace Fortran::common {
|
||||
|
||||
// Helper templates for combining a list of lambdas into an anonymous
|
||||
// struct for use with std::visit() on a std::variant<> sum type.
|
||||
// E.g.: std::visit(visitors{
|
||||
// struct for use with common::visit() on a std::variant<> sum type.
|
||||
// E.g.: common::visit(visitors{
|
||||
// [&](const firstType &x) { ... },
|
||||
// [&](const secondType &x) { ... },
|
||||
// ...
|
||||
|
|
|
@ -118,14 +118,14 @@ template <typename A> const A *GetPtrFromOptional(const std::optional<A> &x) {
|
|||
// Copy a value from one variant type to another. The types allowed in the
|
||||
// source variant must all be allowed in the destination variant type.
|
||||
template <typename TOV, typename FROMV> TOV CopyVariant(const FROMV &u) {
|
||||
return std::visit([](const auto &x) -> TOV { return {x}; }, u);
|
||||
return common::visit([](const auto &x) -> TOV { return {x}; }, u);
|
||||
}
|
||||
|
||||
// Move a value from one variant type to another. The types allowed in the
|
||||
// source variant must all be allowed in the destination variant type.
|
||||
template <typename TOV, typename FROMV>
|
||||
common::IfNoLvalue<TOV, FROMV> MoveVariant(FROMV &&u) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &&x) -> TOV { return {std::move(x)}; }, std::move(u));
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "indirection.h"
|
||||
#include "reference-counted.h"
|
||||
#include "reference.h"
|
||||
#include "visit.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
@ -103,7 +104,7 @@ struct UnwrapperHelper {
|
|||
|
||||
template <typename A, typename... Bs>
|
||||
static A *Unwrap(std::variant<Bs...> &u) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &x) -> A * {
|
||||
using Ty = std::decay_t<decltype(Unwrap<A>(x))>;
|
||||
if constexpr (!std::is_const_v<std::remove_pointer_t<Ty>> ||
|
||||
|
@ -117,7 +118,7 @@ struct UnwrapperHelper {
|
|||
|
||||
template <typename A, typename... Bs>
|
||||
static auto Unwrap(const std::variant<Bs...> &u) -> std::add_const_t<A> * {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &x) -> std::add_const_t<A> * { return Unwrap<A>(x); }, u);
|
||||
}
|
||||
|
||||
|
|
|
@ -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_
|
|
@ -646,7 +646,7 @@ public:
|
|||
EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
|
||||
static constexpr DynamicType GetType() { return Result::GetType(); }
|
||||
int Rank() const {
|
||||
return std::visit([](const auto &x) { return x.Rank(); }, u);
|
||||
return common::visit([](const auto &x) { return x.Rank(); }, u);
|
||||
}
|
||||
llvm::raw_ostream &AsFortran(llvm::raw_ostream &o) const;
|
||||
common::MapTemplate<Relational, DirectlyComparableTypes> u;
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
template <typename T>
|
||||
std::optional<OffsetSymbol> FoldDesignator(const Expr<T> &expr) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) { return FoldDesignator(x, elementNumber_++); },
|
||||
expr.u);
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ private:
|
|||
template <typename T>
|
||||
std::optional<OffsetSymbol> FoldDesignator(
|
||||
const Expr<T> &expr, ConstantSubscript which) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) { return FoldDesignator(x, which); }, expr.u);
|
||||
}
|
||||
|
||||
|
@ -110,14 +110,14 @@ private:
|
|||
template <typename T>
|
||||
std::optional<OffsetSymbol> FoldDesignator(
|
||||
const Designator<T> &designator, ConstantSubscript which) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) { return FoldDesignator(x, which); }, designator.u);
|
||||
}
|
||||
template <int KIND>
|
||||
std::optional<OffsetSymbol> FoldDesignator(
|
||||
const Designator<Type<TypeCategory::Character, KIND>> &designator,
|
||||
ConstantSubscript which) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const Substring &ss) {
|
||||
if (const auto *dataRef{ss.GetParentIf<DataRef>()}) {
|
||||
|
|
|
@ -88,7 +88,7 @@ public:
|
|||
template <typename T>
|
||||
Result Add(ConstantSubscript offset, std::size_t bytes, const Expr<T> &x,
|
||||
FoldingContext &c) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &y) { return Add(offset, bytes, y, c); }, x.u);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ private:
|
|||
template <typename T>
|
||||
MaybeExtentExpr GetArrayConstructorValueExtent(
|
||||
const ArrayConstructorValue<T> &value) const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const Expr<T> &x) -> MaybeExtentExpr {
|
||||
if (auto xShape{
|
||||
|
|
|
@ -83,7 +83,7 @@ template <typename A> bool IsAssumedRank(const Designator<A> &designator) {
|
|||
}
|
||||
}
|
||||
template <typename T> bool IsAssumedRank(const Expr<T> &expr) {
|
||||
return std::visit([](const auto &x) { return IsAssumedRank(x); }, expr.u);
|
||||
return common::visit([](const auto &x) { return IsAssumedRank(x); }, expr.u);
|
||||
}
|
||||
template <typename A> bool IsAssumedRank(const std::optional<A> &x) {
|
||||
return x && IsAssumedRank(*x);
|
||||
|
@ -100,7 +100,7 @@ template <typename A> bool IsCoarray(const Designator<A> &designator) {
|
|||
return false;
|
||||
}
|
||||
template <typename T> bool IsCoarray(const Expr<T> &expr) {
|
||||
return std::visit([](const auto &x) { return IsCoarray(x); }, expr.u);
|
||||
return common::visit([](const auto &x) { return IsCoarray(x); }, expr.u);
|
||||
}
|
||||
template <typename A> bool IsCoarray(const std::optional<A> &x) {
|
||||
return x && IsCoarray(*x);
|
||||
|
@ -177,11 +177,11 @@ auto UnwrapExpr(B &x) -> common::Constify<A, B> * {
|
|||
return UnwrapExpr<A>(*expr);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<Ty, Expr<SomeType>>) {
|
||||
return std::visit([](auto &x) { return UnwrapExpr<A>(x); }, x.u);
|
||||
return common::visit([](auto &x) { return UnwrapExpr<A>(x); }, x.u);
|
||||
} else if constexpr (!common::HasMember<A, TypelessExpression>) {
|
||||
if constexpr (std::is_same_v<Ty, Expr<ResultType<A>>> ||
|
||||
std::is_same_v<Ty, Expr<SomeKind<ResultType<A>::category>>>) {
|
||||
return std::visit([](auto &x) { return UnwrapExpr<A>(x); }, x.u);
|
||||
return common::visit([](auto &x) { return UnwrapExpr<A>(x); }, x.u);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -217,15 +217,17 @@ auto UnwrapConvertedExpr(B &x) -> common::Constify<A, B> * {
|
|||
return UnwrapConvertedExpr<A>(*expr);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<Ty, Expr<SomeType>>) {
|
||||
return std::visit([](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.u);
|
||||
return common::visit(
|
||||
[](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.u);
|
||||
} else if constexpr (!common::HasMember<A, TypelessExpression>) {
|
||||
using Result = ResultType<A>;
|
||||
if constexpr (std::is_same_v<Ty, Expr<Result>> ||
|
||||
std::is_same_v<Ty, Expr<SomeKind<Result::category>>>) {
|
||||
return std::visit([](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.u);
|
||||
return common::visit(
|
||||
[](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.u);
|
||||
} else if constexpr (std::is_same_v<Ty, Parentheses<Result>> ||
|
||||
std::is_same_v<Ty, Convert<Result, Result::category>>) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &x) { return UnwrapConvertedExpr<A>(x); }, x.left().u);
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +264,7 @@ common::IfNoLvalue<std::optional<DataRef>, A> ExtractDataRef(
|
|||
template <typename T>
|
||||
std::optional<DataRef> ExtractDataRef(
|
||||
const Designator<T> &d, bool intoSubstring = false) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[=](const auto &x) -> std::optional<DataRef> {
|
||||
if constexpr (common::HasMember<decltype(x), decltype(DataRef::u)>) {
|
||||
return DataRef{x};
|
||||
|
@ -279,7 +281,7 @@ std::optional<DataRef> ExtractDataRef(
|
|||
template <typename T>
|
||||
std::optional<DataRef> ExtractDataRef(
|
||||
const Expr<T> &expr, bool intoSubstring = false) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[=](const auto &x) { return ExtractDataRef(x, intoSubstring); }, expr.u);
|
||||
}
|
||||
template <typename A>
|
||||
|
@ -328,7 +330,7 @@ bool IsArrayElement(const Expr<T> &expr, bool intoSubstring = true,
|
|||
template <typename A>
|
||||
std::optional<NamedEntity> ExtractNamedEntity(const A &x) {
|
||||
if (auto dataRef{ExtractDataRef(x, true)}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](SymbolRef &&symbol) -> std::optional<NamedEntity> {
|
||||
return NamedEntity{symbol};
|
||||
|
@ -354,10 +356,10 @@ struct ExtractCoindexedObjectHelper {
|
|||
std::optional<CoarrayRef> operator()(const CoarrayRef &x) const { return x; }
|
||||
template <typename A>
|
||||
std::optional<CoarrayRef> operator()(const Expr<A> &expr) const {
|
||||
return std::visit(*this, expr.u);
|
||||
return common::visit(*this, expr.u);
|
||||
}
|
||||
std::optional<CoarrayRef> operator()(const DataRef &dataRef) const {
|
||||
return std::visit(*this, dataRef.u);
|
||||
return common::visit(*this, dataRef.u);
|
||||
}
|
||||
std::optional<CoarrayRef> operator()(const NamedEntity &named) const {
|
||||
if (const Component * component{named.UnwrapComponent()}) {
|
||||
|
@ -449,7 +451,7 @@ Expr<TO> ConvertToType(Expr<SomeKind<FROMCAT>> &&x) {
|
|||
ConvertToType<Part>(std::move(x)), Expr<Part>{Constant<Part>{zero}}}};
|
||||
} else if constexpr (FROMCAT == TypeCategory::Complex) {
|
||||
// Extract and convert the real component of a complex value
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&z) {
|
||||
using ZType = ResultType<decltype(z)>;
|
||||
using Part = typename ZType::Part;
|
||||
|
@ -503,7 +505,7 @@ common::IfNoLvalue<Expr<Type<TC, TK>>, FROM> ConvertTo(
|
|||
template <TypeCategory TC, typename FROM>
|
||||
common::IfNoLvalue<Expr<SomeKind<TC>>, FROM> ConvertTo(
|
||||
const Expr<SomeKind<TC>> &to, FROM &&from) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &toKindExpr) {
|
||||
using KindExpr = std::decay_t<decltype(toKindExpr)>;
|
||||
return AsCategoryExpr(
|
||||
|
@ -515,7 +517,7 @@ common::IfNoLvalue<Expr<SomeKind<TC>>, FROM> ConvertTo(
|
|||
template <typename FROM>
|
||||
common::IfNoLvalue<Expr<SomeType>, FROM> ConvertTo(
|
||||
const Expr<SomeType> &to, FROM &&from) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &toCatExpr) {
|
||||
return AsGenericExpr(ConvertTo(toCatExpr, std::move(from)));
|
||||
},
|
||||
|
@ -565,7 +567,7 @@ using SameKindExprs =
|
|||
template <TypeCategory CAT>
|
||||
SameKindExprs<CAT, 2> AsSameKindExprs(
|
||||
Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&kx, auto &&ky) -> SameKindExprs<CAT, 2> {
|
||||
using XTy = ResultType<decltype(kx)>;
|
||||
using YTy = ResultType<decltype(ky)>;
|
||||
|
@ -626,7 +628,7 @@ Expr<SPECIFIC> Combine(Expr<SPECIFIC> &&x, Expr<SPECIFIC> &&y) {
|
|||
template <template <typename> class OPR, TypeCategory CAT>
|
||||
Expr<SomeKind<CAT>> PromoteAndCombine(
|
||||
Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &&xy) {
|
||||
using Ty = ResultType<decltype(xy[0])>;
|
||||
return AsCategoryExpr(
|
||||
|
@ -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) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](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>
|
||||
std::optional<BaseObject> GetBaseObject(const Expr<T> &x) {
|
||||
return std::visit([](const auto &y) { return GetBaseObject(y); }, x.u);
|
||||
return common::visit([](const auto &y) { return GetBaseObject(y); }, x.u);
|
||||
}
|
||||
template <typename A>
|
||||
std::optional<BaseObject> GetBaseObject(const std::optional<A> &x) {
|
||||
|
@ -1012,7 +1014,8 @@ public:
|
|||
return Expand(std::move(x.left())); // Constant<> can be parenthesized
|
||||
}
|
||||
template <typename T> Expr<T> Expand(Expr<T> &&x) {
|
||||
return std::visit([&](auto &&x) { return Expr<T>{Expand(std::move(x))}; },
|
||||
return common::visit(
|
||||
[&](auto &&x) { return Expr<T>{Expand(std::move(x))}; },
|
||||
std::move(x.u));
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
}
|
||||
template <typename... A>
|
||||
Result operator()(const std::variant<A...> &u) const {
|
||||
return std::visit(visitor_, u);
|
||||
return common::visit(visitor_, u);
|
||||
}
|
||||
template <typename A> Result operator()(const std::vector<A> &x) const {
|
||||
return CombineContents(x);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
|
||||
|
||||
#include "parse-tree.h"
|
||||
#include "flang/Common/visit.h"
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
@ -133,14 +134,14 @@ void Walk(std::tuple<A...> &x, M &mutator) {
|
|||
template <typename V, typename... A>
|
||||
void Walk(const std::variant<A...> &x, V &visitor) {
|
||||
if (visitor.Pre(x)) {
|
||||
std::visit([&](const auto &y) { Walk(y, visitor); }, x);
|
||||
common::visit([&](const auto &y) { Walk(y, visitor); }, x);
|
||||
visitor.Post(x);
|
||||
}
|
||||
}
|
||||
template <typename M, typename... A>
|
||||
void Walk(std::variant<A...> &x, M &mutator) {
|
||||
if (mutator.Pre(x)) {
|
||||
std::visit([&](auto &y) { Walk(y, mutator); }, x);
|
||||
common::visit([&](auto &y) { Walk(y, mutator); }, x);
|
||||
mutator.Post(x);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ struct UnwrapperHelper {
|
|||
|
||||
template <typename A, typename... Bs>
|
||||
static const A *Unwrap(const std::variant<Bs...> &x) {
|
||||
return std::visit([](const auto &y) { return Unwrap<A>(y); }, x);
|
||||
return common::visit([](const auto &y) { return Unwrap<A>(y); }, x);
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "flang/Common/Fortran.h"
|
||||
#include "flang/Common/indirection.h"
|
||||
#include "flang/Common/restorer.h"
|
||||
#include "flang/Common/visit.h"
|
||||
#include "flang/Evaluate/characteristics.h"
|
||||
#include "flang/Evaluate/check-expression.h"
|
||||
#include "flang/Evaluate/expression.h"
|
||||
|
@ -299,11 +300,7 @@ private:
|
|||
return Analyze(x.u); // default case
|
||||
}
|
||||
template <typename... As> MaybeExpr Analyze(const std::variant<As...> &u) {
|
||||
return std::visit(
|
||||
[&](const auto &x) {
|
||||
return Analyze(x);
|
||||
},
|
||||
u);
|
||||
return common::visit([&](const auto &x) { return Analyze(x); }, u);
|
||||
}
|
||||
|
||||
// Analysis subroutines
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "flang/Common/Fortran.h"
|
||||
#include "flang/Common/enum-set.h"
|
||||
#include "flang/Common/reference.h"
|
||||
#include "flang/Common/visit.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
@ -602,24 +603,24 @@ public:
|
|||
bool IsSubprogram() const;
|
||||
bool IsFromModFile() const;
|
||||
bool HasExplicitInterface() const {
|
||||
return std::visit(common::visitors{
|
||||
[](const SubprogramDetails &) { return true; },
|
||||
[](const SubprogramNameDetails &) { return true; },
|
||||
[&](const ProcEntityDetails &x) {
|
||||
return attrs_.test(Attr::INTRINSIC) ||
|
||||
x.HasExplicitInterface();
|
||||
},
|
||||
[](const ProcBindingDetails &x) {
|
||||
return x.symbol().HasExplicitInterface();
|
||||
},
|
||||
[](const UseDetails &x) {
|
||||
return x.symbol().HasExplicitInterface();
|
||||
},
|
||||
[](const HostAssocDetails &x) {
|
||||
return x.symbol().HasExplicitInterface();
|
||||
},
|
||||
[](const auto &) { return false; },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](const SubprogramDetails &) { return true; },
|
||||
[](const SubprogramNameDetails &) { return true; },
|
||||
[&](const ProcEntityDetails &x) {
|
||||
return attrs_.test(Attr::INTRINSIC) ||
|
||||
x.HasExplicitInterface();
|
||||
},
|
||||
[](const ProcBindingDetails &x) {
|
||||
return x.symbol().HasExplicitInterface();
|
||||
},
|
||||
[](const UseDetails &x) {
|
||||
return x.symbol().HasExplicitInterface();
|
||||
},
|
||||
[](const HostAssocDetails &x) {
|
||||
return x.symbol().HasExplicitInterface();
|
||||
},
|
||||
[](const auto &) { return false; },
|
||||
},
|
||||
details_);
|
||||
}
|
||||
|
||||
|
@ -627,7 +628,7 @@ public:
|
|||
bool operator!=(const Symbol &that) const { return !(*this == that); }
|
||||
|
||||
int Rank() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const SubprogramDetails &sd) {
|
||||
return sd.isFunction() ? sd.result().Rank() : 0;
|
||||
|
@ -656,7 +657,7 @@ public:
|
|||
}
|
||||
|
||||
int Corank() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const SubprogramDetails &sd) {
|
||||
return sd.isFunction() ? sd.result().Corank() : 0;
|
||||
|
@ -772,7 +773,7 @@ inline DeclTypeSpec *Symbol::GetType() {
|
|||
const_cast<const Symbol *>(this)->GetType());
|
||||
}
|
||||
inline const DeclTypeSpec *Symbol::GetType() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const EntityDetails &x) { return x.type(); },
|
||||
[](const ObjectEntityDetails &x) { return x.type(); },
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// canonically for use in semantic checking.
|
||||
|
||||
#include "flang/Common/Fortran.h"
|
||||
#include "flang/Common/visit.h"
|
||||
#include "flang/Evaluate/expression.h"
|
||||
#include "flang/Evaluate/shape.h"
|
||||
#include "flang/Evaluate/type.h"
|
||||
|
@ -240,7 +241,7 @@ const Symbol *FindExternallyVisibleObject(
|
|||
template <typename T>
|
||||
const Symbol *FindExternallyVisibleObject(
|
||||
const evaluate::Expr<T> &expr, const Scope &scope) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) { return FindExternallyVisibleObject(x, scope); },
|
||||
expr.u);
|
||||
}
|
||||
|
|
|
@ -157,18 +157,19 @@ const Component *ProcedureDesignator::GetComponent() const {
|
|||
}
|
||||
|
||||
const Symbol *ProcedureDesignator::GetSymbol() const {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return &*symbol; },
|
||||
[](const common::CopyableIndirection<Component> &c) {
|
||||
return &c.value().GetLastSymbol();
|
||||
},
|
||||
[](const auto &) -> const Symbol * { return nullptr; },
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](SymbolRef symbol) { return &*symbol; },
|
||||
[](const common::CopyableIndirection<Component> &c) {
|
||||
return &c.value().GetLastSymbol();
|
||||
},
|
||||
[](const auto &) -> const Symbol * { return nullptr; },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
std::string ProcedureDesignator::GetName() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const SpecificIntrinsic &i) { return i.name; },
|
||||
[](const Symbol &symbol) { return symbol.name().ToString(); },
|
||||
|
|
|
@ -69,7 +69,7 @@ TypeAndShape &TypeAndShape::Rewrite(FoldingContext &context) {
|
|||
std::optional<TypeAndShape> TypeAndShape::Characterize(
|
||||
const semantics::Symbol &symbol, FoldingContext &context) {
|
||||
const auto &ultimate{symbol.GetUltimate()};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const semantics::ProcEntityDetails &proc) {
|
||||
const semantics::ProcInterface &interface{proc.interface()};
|
||||
|
@ -392,7 +392,7 @@ static std::optional<Procedure> CharacterizeProcedure(
|
|||
result.attrs.test(Procedure::Attr::Elemental))) {
|
||||
result.attrs.set(Procedure::Attr::Pure);
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const semantics::SubprogramDetails &subp)
|
||||
-> std::optional<Procedure> {
|
||||
|
@ -578,7 +578,7 @@ static std::optional<DummyArgument> CharacterizeDummyArgument(
|
|||
|
||||
std::optional<DummyArgument> DummyArgument::FromActual(
|
||||
std::string &&name, const Expr<SomeType> &expr, FoldingContext &context) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const BOZLiteralConstant &) {
|
||||
return std::make_optional<DummyArgument>(std::move(name),
|
||||
|
@ -619,7 +619,7 @@ std::optional<DummyArgument> DummyArgument::FromActual(
|
|||
}
|
||||
|
||||
bool DummyArgument::IsOptional() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const DummyDataObject &data) {
|
||||
return data.attrs.test(DummyDataObject::Attr::Optional);
|
||||
|
@ -633,35 +633,36 @@ bool DummyArgument::IsOptional() const {
|
|||
}
|
||||
|
||||
void DummyArgument::SetOptional(bool value) {
|
||||
std::visit(common::visitors{
|
||||
[value](DummyDataObject &data) {
|
||||
data.attrs.set(DummyDataObject::Attr::Optional, value);
|
||||
},
|
||||
[value](DummyProcedure &proc) {
|
||||
proc.attrs.set(DummyProcedure::Attr::Optional, value);
|
||||
},
|
||||
[](AlternateReturn &) { DIE("cannot set optional"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[value](DummyDataObject &data) {
|
||||
data.attrs.set(DummyDataObject::Attr::Optional, value);
|
||||
},
|
||||
[value](DummyProcedure &proc) {
|
||||
proc.attrs.set(DummyProcedure::Attr::Optional, value);
|
||||
},
|
||||
[](AlternateReturn &) { DIE("cannot set optional"); },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
void DummyArgument::SetIntent(common::Intent intent) {
|
||||
std::visit(common::visitors{
|
||||
[intent](DummyDataObject &data) { data.intent = intent; },
|
||||
[intent](DummyProcedure &proc) { proc.intent = intent; },
|
||||
[](AlternateReturn &) { DIE("cannot set intent"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[intent](DummyDataObject &data) { data.intent = intent; },
|
||||
[intent](DummyProcedure &proc) { proc.intent = intent; },
|
||||
[](AlternateReturn &) { DIE("cannot set intent"); },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
common::Intent DummyArgument::GetIntent() const {
|
||||
return std::visit(common::visitors{
|
||||
[](const DummyDataObject &data) { return data.intent; },
|
||||
[](const DummyProcedure &proc) { return proc.intent; },
|
||||
[](const AlternateReturn &) -> common::Intent {
|
||||
DIE("Alternate returns have no intent");
|
||||
},
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const DummyDataObject &data) { return data.intent; },
|
||||
[](const DummyProcedure &proc) { return proc.intent; },
|
||||
[](const AlternateReturn &) -> common::Intent {
|
||||
DIE("Alternate returns have no intent");
|
||||
},
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
|
@ -685,7 +686,7 @@ llvm::raw_ostream &DummyArgument::Dump(llvm::raw_ostream &o) const {
|
|||
if (pass) {
|
||||
o << " PASS";
|
||||
}
|
||||
std::visit([&](const auto &x) { x.Dump(o); }, u);
|
||||
common::visit([&](const auto &x) { x.Dump(o); }, u);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
@ -798,12 +799,12 @@ bool FunctionResult::IsCompatibleWith(const FunctionResult &actual) const {
|
|||
|
||||
llvm::raw_ostream &FunctionResult::Dump(llvm::raw_ostream &o) const {
|
||||
attrs.Dump(o, EnumToString);
|
||||
std::visit(common::visitors{
|
||||
[&](const TypeAndShape &ts) { ts.Dump(o); },
|
||||
[&](const CopyableIndirection<Procedure> &p) {
|
||||
p.value().Dump(o << " procedure(") << ')';
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const TypeAndShape &ts) { ts.Dump(o); },
|
||||
[&](const CopyableIndirection<Procedure> &p) {
|
||||
p.value().Dump(o << " procedure(") << ')';
|
||||
},
|
||||
},
|
||||
u);
|
||||
return o;
|
||||
}
|
||||
|
@ -1135,7 +1136,7 @@ bool DistinguishUtils::Distinguishable(
|
|||
if (x.u.index() != y.u.index()) {
|
||||
return true; // different kind: data/proc/alt-return
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const DummyDataObject &z) {
|
||||
return Distinguishable(z, std::get<DummyDataObject>(y.u));
|
||||
|
@ -1197,7 +1198,7 @@ bool DistinguishUtils::Distinguishable(
|
|||
if (x.u.index() != y.u.index()) {
|
||||
return true; // one is data object, one is procedure
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const TypeAndShape &z) {
|
||||
return Distinguishable(z, std::get<TypeAndShape>(y.u));
|
||||
|
|
|
@ -173,13 +173,13 @@ struct IsActuallyConstantHelper {
|
|||
return (*this)(x.left());
|
||||
}
|
||||
template <typename T> bool operator()(const Expr<T> &x) {
|
||||
return std::visit([=](const auto &y) { return (*this)(y); }, x.u);
|
||||
return common::visit([this](const auto &y) { return (*this)(y); }, x.u);
|
||||
}
|
||||
bool operator()(const Expr<SomeType> &x) {
|
||||
if (IsNullPointer(x)) {
|
||||
return true;
|
||||
}
|
||||
return std::visit([this](const auto &y) { return (*this)(y); }, x.u);
|
||||
return common::visit([this](const auto &y) { return (*this)(y); }, x.u);
|
||||
}
|
||||
template <typename A> bool operator()(const A *x) { return x && (*this)(*x); }
|
||||
template <typename A> bool operator()(const std::optional<A> &x) {
|
||||
|
@ -254,13 +254,13 @@ public:
|
|||
IsConstantExpr(x.stride());
|
||||
}
|
||||
bool operator()(const Subscript &x) const {
|
||||
return std::visit(common::visitors{
|
||||
[&](const Triplet &t) { return (*this)(t); },
|
||||
[&](const auto &y) {
|
||||
return y.value().Rank() == 0 &&
|
||||
IsConstantExpr(y.value());
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[&](const Triplet &t) { return (*this)(t); },
|
||||
[&](const auto &y) {
|
||||
return y.value().Rank() == 0 &&
|
||||
IsConstantExpr(y.value());
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
bool operator()(const CoarrayRef &) const { return false; }
|
||||
|
@ -332,7 +332,7 @@ bool IsInitialDataTarget(
|
|||
|
||||
bool IsInitialProcedureTarget(const semantics::Symbol &symbol) {
|
||||
const auto &ultimate{symbol.GetUltimate()};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const semantics::SubprogramDetails &subp) {
|
||||
return !subp.isDummy();
|
||||
|
@ -381,7 +381,7 @@ public:
|
|||
std::move(x.left())); // Constant<> can be parenthesized
|
||||
}
|
||||
template <typename T> Expr<T> ChangeLbounds(Expr<T> &&x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&x) { return Expr<T>{ChangeLbounds(std::move(x))}; },
|
||||
std::move(x.u)); // recurse until we hit a constant
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ template <int KIND>
|
|||
std::optional<Expr<SubscriptInteger>>
|
||||
Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
|
||||
using T = std::optional<Expr<SubscriptInteger>>;
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const Constant<Result> &c) -> T {
|
||||
return AsExpr(Constant<SubscriptInteger>{c.LEN()});
|
||||
|
@ -38,7 +38,7 @@ Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
|
|||
[](const ArrayConstructor<Result> &a) -> T { return a.LEN(); },
|
||||
[](const Parentheses<Result> &x) { return x.left().LEN(); },
|
||||
[](const Convert<Result> &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &kx) { return kx.LEN(); }, x.left().u);
|
||||
},
|
||||
[](const Concat<KIND> &c) -> T {
|
||||
|
@ -84,7 +84,7 @@ std::optional<DynamicType> ExpressionBase<A>::GetType() const {
|
|||
if constexpr (IsLengthlessIntrinsicType<Result>) {
|
||||
return Result::GetType();
|
||||
} else {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) -> std::optional<DynamicType> {
|
||||
if constexpr (!common::HasMember<decltype(x), TypelessExpression>) {
|
||||
return x.GetType();
|
||||
|
@ -96,7 +96,7 @@ std::optional<DynamicType> ExpressionBase<A>::GetType() const {
|
|||
}
|
||||
|
||||
template <typename A> int ExpressionBase<A>::Rank() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &x) {
|
||||
if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
|
||||
return 0;
|
||||
|
@ -309,19 +309,19 @@ void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *p) {
|
|||
}
|
||||
|
||||
template <TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
|
||||
u);
|
||||
}
|
||||
|
||||
int Expr<SomeCharacter>::GetKind() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
|
||||
u);
|
||||
}
|
||||
|
||||
std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
|
||||
return std::visit([](const auto &kx) { return kx.LEN(); }, u);
|
||||
return common::visit([](const auto &kx) { return kx.LEN(); }, u);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER // disable bogus warning about missing definitions
|
||||
|
|
|
@ -70,7 +70,7 @@ std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator(
|
|||
ConstantSubscript lower{lowerBounds->at(dim)};
|
||||
ConstantSubscript extent{extents->at(dim)};
|
||||
ConstantSubscript upper{lower + extent - 1};
|
||||
if (!std::visit(
|
||||
if (!common::visit(
|
||||
common::visitors{
|
||||
[&](const IndirectSubscriptIntegerExpr &expr) {
|
||||
auto folded{
|
||||
|
@ -169,7 +169,7 @@ std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator(
|
|||
|
||||
std::optional<OffsetSymbol> DesignatorFolder::FoldDesignator(
|
||||
const DataRef &dataRef, ConstantSubscript which) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) { return FoldDesignator(x, which); }, dataRef.u);
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ std::optional<Expr<SomeType>> OffsetToDesignator(FoldingContext &context,
|
|||
// Pick a COMPLEX component
|
||||
auto part{
|
||||
offset == 0 ? ComplexPart::Part::RE : ComplexPart::Part::IM};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &z) -> std::optional<Expr<SomeType>> {
|
||||
using PartType = typename ResultType<decltype(z)>::Part;
|
||||
return AsGenericExpr(Designator<PartType>{ComplexPart{
|
||||
|
@ -327,7 +327,7 @@ std::optional<Expr<SomeType>> OffsetToDesignator(FoldingContext &context,
|
|||
std::get_if<Expr<SomeCharacter>>(&result->u)}) {
|
||||
if (offset > 0 || size != static_cast<std::size_t>(*elementBytes)) {
|
||||
// Select a substring
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) -> std::optional<Expr<SomeType>> {
|
||||
using T = typename std::decay_t<decltype(x)>::Result;
|
||||
return AsGenericExpr(Designator<T>{
|
||||
|
|
|
@ -303,7 +303,7 @@ std::optional<Constant<T>> Folder<T>::ApplyComponent(
|
|||
template <typename T>
|
||||
std::optional<Constant<T>> Folder<T>::GetConstantComponent(Component &component,
|
||||
const std::vector<Constant<SubscriptInteger>> *subscripts) {
|
||||
if (std::optional<Constant<SomeDerived>> structures{std::visit(
|
||||
if (std::optional<Constant<SomeDerived>> structures{common::visit(
|
||||
common::visitors{
|
||||
[&](const Symbol &symbol) {
|
||||
return Folder<SomeDerived>{context_}.GetNamedConstant(symbol);
|
||||
|
@ -342,7 +342,7 @@ template <typename T> Expr<T> Folder<T>::Folding(Designator<T> &&designator) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](SymbolRef &&symbol) {
|
||||
if (auto constant{GetNamedConstant(*symbol)}) {
|
||||
|
@ -523,7 +523,7 @@ template <typename A, typename B>
|
|||
std::optional<std::vector<A>> GetIntegerVector(const B &x) {
|
||||
static_assert(std::is_integral_v<A>);
|
||||
if (const auto *someInteger{UnwrapExpr<Expr<SomeInteger>>(x)}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &typedExpr) -> std::optional<std::vector<A>> {
|
||||
using T = ResultType<decltype(typedExpr)>;
|
||||
if (const auto *constant{UnwrapConstantValue<T>(typedExpr)}) {
|
||||
|
@ -1039,10 +1039,10 @@ Expr<T> RewriteSpecificMINorMAX(
|
|||
return Fold(context, ConvertToType<T>(AsCategoryExpr(std::move(maxRef))));
|
||||
}};
|
||||
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(*resultTypeArg)}) {
|
||||
return std::visit(insertConversion, sx->u);
|
||||
return common::visit(insertConversion, sx->u);
|
||||
}
|
||||
auto &sx{DEREF(UnwrapExpr<Expr<SomeInteger>>(*resultTypeArg))};
|
||||
return std::visit(insertConversion, sx.u);
|
||||
return common::visit(insertConversion, sx.u);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -1164,7 +1164,7 @@ private:
|
|||
}
|
||||
}
|
||||
bool FoldArray(const ArrayConstructorValue<T> &x) {
|
||||
return std::visit([&](const auto &y) { return FoldArray(y); }, x.u);
|
||||
return common::visit([&](const auto &y) { return FoldArray(y); }, x.u);
|
||||
}
|
||||
bool FoldArray(const ArrayConstructorValues<T> &xs) {
|
||||
for (const auto &x : xs) {
|
||||
|
@ -1227,7 +1227,7 @@ template <TypeCategory CAT>
|
|||
std::enable_if_t<CAT != TypeCategory::Derived,
|
||||
std::optional<Expr<SomeKind<CAT>>>>
|
||||
AsFlatArrayConstructor(const Expr<SomeKind<CAT>> &expr) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &kindExpr) -> std::optional<Expr<SomeKind<CAT>>> {
|
||||
if (auto flattened{AsFlatArrayConstructor(kindExpr)}) {
|
||||
return Expr<SomeKind<CAT>>{std::move(*flattened)};
|
||||
|
@ -1268,7 +1268,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
|
|||
Expr<OPERAND> &&values) {
|
||||
ArrayConstructor<RESULT> result{values};
|
||||
if constexpr (common::HasMember<OPERAND, AllIntrinsicCategoryTypes>) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
[&](auto &&kindExpr) {
|
||||
using kindType = ResultType<decltype(kindExpr)>;
|
||||
auto &aConst{std::get<ArrayConstructor<kindType>>(kindExpr.u)};
|
||||
|
@ -1309,7 +1309,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
|
|||
auto result{ArrayConstructorFromMold<RESULT>(leftValues, std::move(length))};
|
||||
auto &leftArrConst{std::get<ArrayConstructor<LEFT>>(leftValues.u)};
|
||||
if constexpr (common::HasMember<RIGHT, AllIntrinsicCategoryTypes>) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
[&](auto &&kindExpr) {
|
||||
using kindType = ResultType<decltype(kindExpr)>;
|
||||
|
||||
|
@ -1366,7 +1366,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
|
|||
const Expr<LEFT> &leftScalar, Expr<RIGHT> &&rightValues) {
|
||||
auto result{ArrayConstructorFromMold<RESULT>(leftScalar, std::move(length))};
|
||||
if constexpr (common::HasMember<RIGHT, AllIntrinsicCategoryTypes>) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
[&](auto &&kindExpr) {
|
||||
using kindType = ResultType<decltype(kindExpr)>;
|
||||
auto &rightArrConst{std::get<ArrayConstructor<kindType>>(kindExpr.u)};
|
||||
|
@ -1518,7 +1518,7 @@ Expr<TO> FoldOperation(
|
|||
FoldingContext &context;
|
||||
Convert<TO, FROMCAT> &convert;
|
||||
} msvcWorkaround{context, convert};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&msvcWorkaround](auto &kindExpr) -> Expr<TO> {
|
||||
using Operand = ResultType<decltype(kindExpr)>;
|
||||
// This variable is a workaround for msvc which emits an error when
|
||||
|
@ -1839,7 +1839,7 @@ Expr<T> FoldOperation(FoldingContext &context, RealToIntPower<T> &&x) {
|
|||
if (auto array{ApplyElementwise(context, x)}) {
|
||||
return *array;
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &y) -> Expr<T> {
|
||||
if (auto folded{OperandsAreConstants(x.left(), y)}) {
|
||||
auto power{evaluate::IntPower(folded->first, folded->second)};
|
||||
|
@ -1897,7 +1897,7 @@ Expr<Type<TypeCategory::Real, KIND>> ToReal(
|
|||
FoldingContext &context, Expr<SomeType> &&expr) {
|
||||
using Result = Type<TypeCategory::Real, KIND>;
|
||||
std::optional<Expr<Result>> result;
|
||||
std::visit(
|
||||
common::visit(
|
||||
[&](auto &&x) {
|
||||
using From = std::decay_t<decltype(x)>;
|
||||
if constexpr (std::is_same_v<From, BOZLiteralConstant>) {
|
||||
|
@ -1924,7 +1924,7 @@ Expr<Type<TypeCategory::Real, KIND>> ToReal(
|
|||
|
||||
template <typename T>
|
||||
Expr<T> ExpressionBase<T>::Rewrite(FoldingContext &context, Expr<T> &&expr) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&x) -> Expr<T> {
|
||||
if constexpr (IsSpecificIntrinsicType<T>) {
|
||||
return FoldOperation(context, std::move(x));
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
|
||||
template <typename T> ConstantSubscript GetLbound(const Expr<T> &x) {
|
||||
// recurse through Expr<T>'a until we hit a constant
|
||||
return std::visit([&](const auto &inner) { return GetLbound(inner); },
|
||||
return common::visit([&](const auto &inner) { return GetLbound(inner); },
|
||||
// [&](const auto &) { return 0; },
|
||||
x.u);
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
common::RoundingMode mode{name == "ceiling" ? common::RoundingMode::Up
|
||||
: name == "floor" ? common::RoundingMode::Down
|
||||
: common::RoundingMode::TiesAwayFromZero};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &kx) {
|
||||
using TR = ResultType<decltype(kx)>;
|
||||
return FoldElementalIntrinsic<T, TR>(context, std::move(funcRef),
|
||||
|
@ -452,19 +452,19 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
return FoldCount<T>(context, std::move(funcRef));
|
||||
} else if (name == "digits") {
|
||||
if (const auto *cx{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
|
||||
return Expr<T>{std::visit(
|
||||
return Expr<T>{common::visit(
|
||||
[](const auto &kx) {
|
||||
return Scalar<ResultType<decltype(kx)>>::DIGITS;
|
||||
},
|
||||
cx->u)};
|
||||
} else if (const auto *cx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
|
||||
return Expr<T>{std::visit(
|
||||
return Expr<T>{common::visit(
|
||||
[](const auto &kx) {
|
||||
return Scalar<ResultType<decltype(kx)>>::DIGITS;
|
||||
},
|
||||
cx->u)};
|
||||
} else if (const auto *cx{UnwrapExpr<Expr<SomeComplex>>(args[0])}) {
|
||||
return Expr<T>{std::visit(
|
||||
return Expr<T>{common::visit(
|
||||
[](const auto &kx) {
|
||||
return Scalar<typename ResultType<decltype(kx)>::Part>::DIGITS;
|
||||
},
|
||||
|
@ -486,7 +486,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
}));
|
||||
} else if (name == "exponent") {
|
||||
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&funcRef, &context](const auto &x) -> Expr<T> {
|
||||
using TR = typename std::decay_t<decltype(x)>::Result;
|
||||
return FoldElementalIntrinsic<T, TR>(context, std::move(funcRef),
|
||||
|
@ -510,7 +510,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
"Character in intrinsic function %s must have length one"_warn_en_US,
|
||||
name);
|
||||
} else {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&funcRef, &context](const auto &str) -> Expr<T> {
|
||||
using Char = typename std::decay_t<decltype(str)>::Result;
|
||||
return FoldElementalIntrinsic<T, Char>(context,
|
||||
|
@ -566,7 +566,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
}));
|
||||
} else if (name == "index" || name == "scan" || name == "verify") {
|
||||
if (auto *charExpr{UnwrapExpr<Expr<SomeCharacter>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &kch) -> Expr<T> {
|
||||
using TC = typename std::decay_t<decltype(kch)>::Result;
|
||||
if (UnwrapExpr<Expr<SomeLogical>>(args[2])) { // BACK=
|
||||
|
@ -603,7 +603,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
}
|
||||
} else if (name == "int") {
|
||||
if (auto *expr{UnwrapExpr<Expr<SomeType>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&x) -> Expr<T> {
|
||||
using From = std::decay_t<decltype(x)>;
|
||||
if constexpr (std::is_same_v<From, BOZLiteralConstant> ||
|
||||
|
@ -646,7 +646,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
} else if (name == "leadz" || name == "trailz" || name == "poppar" ||
|
||||
name == "popcnt") {
|
||||
if (auto *sn{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&funcRef, &context, &name](const auto &n) -> Expr<T> {
|
||||
using TI = typename std::decay_t<decltype(n)>::Result;
|
||||
if (name == "poppar") {
|
||||
|
@ -676,7 +676,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
}
|
||||
} else if (name == "len") {
|
||||
if (auto *charExpr{UnwrapExpr<Expr<SomeCharacter>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &kx) {
|
||||
if (auto len{kx.LEN()}) {
|
||||
if (IsScopeInvariantExpr(*len)) {
|
||||
|
@ -694,7 +694,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
}
|
||||
} else if (name == "len_trim") {
|
||||
if (auto *charExpr{UnwrapExpr<Expr<SomeCharacter>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &kch) -> Expr<T> {
|
||||
using TC = typename std::decay_t<decltype(kch)>::Result;
|
||||
return FoldElementalIntrinsic<T, TC>(context, std::move(funcRef),
|
||||
|
@ -720,7 +720,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
return RewriteSpecificMINorMAX(context, std::move(funcRef));
|
||||
} else if (name == "maxexponent") {
|
||||
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &x) {
|
||||
using TR = typename std::decay_t<decltype(x)>::Result;
|
||||
return Expr<T>{Scalar<TR>::MAXEXPONENT};
|
||||
|
@ -743,7 +743,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
return RewriteSpecificMINorMAX(context, std::move(funcRef));
|
||||
} else if (name == "minexponent") {
|
||||
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &x) {
|
||||
using TR = typename std::decay_t<decltype(x)>::Result;
|
||||
return Expr<T>{Scalar<TR>::MINEXPONENT};
|
||||
|
@ -785,13 +785,13 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
context, std::move(funcRef), &Scalar<T>::NOT);
|
||||
} else if (name == "precision") {
|
||||
if (const auto *cx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
|
||||
return Expr<T>{std::visit(
|
||||
return Expr<T>{common::visit(
|
||||
[](const auto &kx) {
|
||||
return Scalar<ResultType<decltype(kx)>>::PRECISION;
|
||||
},
|
||||
cx->u)};
|
||||
} else if (const auto *cx{UnwrapExpr<Expr<SomeComplex>>(args[0])}) {
|
||||
return Expr<T>{std::visit(
|
||||
return Expr<T>{common::visit(
|
||||
[](const auto &kx) {
|
||||
return Scalar<typename ResultType<decltype(kx)>::Part>::PRECISION;
|
||||
},
|
||||
|
@ -803,19 +803,19 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
|
|||
return Expr<T>{2};
|
||||
} else if (name == "range") {
|
||||
if (const auto *cx{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
|
||||
return Expr<T>{std::visit(
|
||||
return Expr<T>{common::visit(
|
||||
[](const auto &kx) {
|
||||
return Scalar<ResultType<decltype(kx)>>::RANGE;
|
||||
},
|
||||
cx->u)};
|
||||
} else if (const auto *cx{UnwrapExpr<Expr<SomeReal>>(args[0])}) {
|
||||
return Expr<T>{std::visit(
|
||||
return Expr<T>{common::visit(
|
||||
[](const auto &kx) {
|
||||
return Scalar<ResultType<decltype(kx)>>::RANGE;
|
||||
},
|
||||
cx->u)};
|
||||
} else if (const auto *cx{UnwrapExpr<Expr<SomeComplex>>(args[0])}) {
|
||||
return Expr<T>{std::visit(
|
||||
return Expr<T>{common::visit(
|
||||
[](const auto &kx) {
|
||||
return Scalar<typename ResultType<decltype(kx)>::Part>::RANGE;
|
||||
},
|
||||
|
@ -1016,7 +1016,7 @@ Expr<TypeParamInquiry::Result> FoldOperation(
|
|||
}
|
||||
|
||||
std::optional<std::int64_t> ToInt64(const Expr<SomeInteger> &expr) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &kindExpr) { return ToInt64(kindExpr); }, expr.u);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
|
|||
}));
|
||||
} else if (name == "btest") {
|
||||
if (const auto *ix{UnwrapExpr<Expr<SomeInteger>>(args[0])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) {
|
||||
using IT = ResultType<decltype(x)>;
|
||||
return FoldElementalIntrinsic<T, IT, SameInt>(context,
|
||||
|
@ -212,7 +212,7 @@ Expr<LogicalResult> FoldOperation(
|
|||
|
||||
Expr<LogicalResult> FoldOperation(
|
||||
FoldingContext &context, Relational<SomeType> &&relation) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&x) {
|
||||
return Expr<LogicalResult>{FoldOperation(context, std::move(x))};
|
||||
},
|
||||
|
|
|
@ -133,7 +133,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
|
|||
}
|
||||
} else if (name == "scale") {
|
||||
if (const auto *byExpr{UnwrapExpr<Expr<SomeInteger>>(args[1])}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &byVal) {
|
||||
using TBY = ResultType<decltype(byVal)>;
|
||||
return FoldElementalIntrinsic<T, T, TBY>(context,
|
||||
|
|
|
@ -21,7 +21,7 @@ characteristics::TypeAndShape Fold(
|
|||
std::optional<Constant<SubscriptInteger>> GetConstantSubscript(
|
||||
FoldingContext &context, Subscript &ss, const NamedEntity &base, int dim) {
|
||||
ss = FoldOperation(context, std::move(ss));
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](IndirectSubscriptIntegerExpr &expr)
|
||||
-> std::optional<Constant<SubscriptInteger>> {
|
||||
|
@ -119,16 +119,16 @@ Triplet FoldOperation(FoldingContext &context, Triplet &&triplet) {
|
|||
}
|
||||
|
||||
Subscript FoldOperation(FoldingContext &context, Subscript &&subscript) {
|
||||
return std::visit(common::visitors{
|
||||
[&](IndirectSubscriptIntegerExpr &&expr) {
|
||||
expr.value() = Fold(context, std::move(expr.value()));
|
||||
return Subscript(std::move(expr));
|
||||
},
|
||||
[&](Triplet &&triplet) {
|
||||
return Subscript(
|
||||
FoldOperation(context, std::move(triplet)));
|
||||
},
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](IndirectSubscriptIntegerExpr &&expr) {
|
||||
expr.value() = Fold(context, std::move(expr.value()));
|
||||
return Subscript(std::move(expr));
|
||||
},
|
||||
[&](Triplet &&triplet) {
|
||||
return Subscript(FoldOperation(context, std::move(triplet)));
|
||||
},
|
||||
},
|
||||
std::move(subscript.u));
|
||||
}
|
||||
|
||||
|
@ -162,12 +162,13 @@ CoarrayRef FoldOperation(FoldingContext &context, CoarrayRef &&coarrayRef) {
|
|||
}
|
||||
|
||||
DataRef FoldOperation(FoldingContext &context, DataRef &&dataRef) {
|
||||
return std::visit(common::visitors{
|
||||
[&](SymbolRef symbol) { return DataRef{*symbol}; },
|
||||
[&](auto &&x) {
|
||||
return DataRef{FoldOperation(context, std::move(x))};
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[&](SymbolRef symbol) { return DataRef{*symbol}; },
|
||||
[&](auto &&x) {
|
||||
return DataRef{
|
||||
FoldOperation(context, std::move(x))};
|
||||
},
|
||||
},
|
||||
std::move(dataRef.u));
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ llvm::raw_ostream &ActualArgument::AsFortran(llvm::raw_ostream &o) const {
|
|||
if (keyword_) {
|
||||
o << keyword_->ToString() << '=';
|
||||
}
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const common::CopyableIndirection<Expr<SomeType>> &expr) {
|
||||
expr.value().AsFortran(o);
|
||||
|
@ -227,7 +227,7 @@ template <typename T> static Precedence ToPrecedence(const Constant<T> &x) {
|
|||
return Precedence::Top;
|
||||
}
|
||||
template <typename T> static Precedence ToPrecedence(const Expr<T> &expr) {
|
||||
return std::visit([](const auto &x) { return ToPrecedence(x); }, expr.u);
|
||||
return common::visit([](const auto &x) { return ToPrecedence(x); }, expr.u);
|
||||
}
|
||||
|
||||
template <typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
|
||||
|
@ -242,7 +242,7 @@ template <typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
|
|||
|
||||
template <TypeCategory CAT>
|
||||
static bool IsNegatedScalarConstant(const Expr<SomeKind<CAT>> &expr) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &x) { return IsNegatedScalarConstant(x); }, expr.u);
|
||||
}
|
||||
|
||||
|
@ -373,7 +373,7 @@ llvm::raw_ostream &Convert<TO, FROMCAT>::AsFortran(llvm::raw_ostream &o) const {
|
|||
}
|
||||
|
||||
llvm::raw_ostream &Relational<SomeType>::AsFortran(llvm::raw_ostream &o) const {
|
||||
std::visit([&](const auto &rel) { rel.AsFortran(o); }, u);
|
||||
common::visit([&](const auto &rel) { rel.AsFortran(o); }, u);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
@ -404,7 +404,7 @@ llvm::raw_ostream &EmitArray(
|
|||
const char *sep{""};
|
||||
for (const auto &value : values) {
|
||||
o << sep;
|
||||
std::visit([&](const auto &x) { EmitArray(o, x); }, value.u);
|
||||
common::visit([&](const auto &x) { EmitArray(o, x); }, value.u);
|
||||
sep = ",";
|
||||
}
|
||||
return o;
|
||||
|
@ -444,17 +444,17 @@ std::string ExpressionBase<RESULT>::AsFortran() const {
|
|||
template <typename RESULT>
|
||||
llvm::raw_ostream &ExpressionBase<RESULT>::AsFortran(
|
||||
llvm::raw_ostream &o) const {
|
||||
std::visit(common::visitors{
|
||||
[&](const BOZLiteralConstant &x) {
|
||||
o << "z'" << x.Hexadecimal() << "'";
|
||||
},
|
||||
[&](const NullPointer &) { o << "NULL()"; },
|
||||
[&](const common::CopyableIndirection<Substring> &s) {
|
||||
s.value().AsFortran(o);
|
||||
},
|
||||
[&](const ImpliedDoIndex &i) { o << i.name.ToString(); },
|
||||
[&](const auto &x) { x.AsFortran(o); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const BOZLiteralConstant &x) {
|
||||
o << "z'" << x.Hexadecimal() << "'";
|
||||
},
|
||||
[&](const NullPointer &) { o << "NULL()"; },
|
||||
[&](const common::CopyableIndirection<Substring> &s) {
|
||||
s.value().AsFortran(o);
|
||||
},
|
||||
[&](const ImpliedDoIndex &i) { o << i.name.ToString(); },
|
||||
[&](const auto &x) { x.AsFortran(o); },
|
||||
},
|
||||
derived().u);
|
||||
return o;
|
||||
}
|
||||
|
@ -608,7 +608,7 @@ llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::shared_ptr<A> &p) {
|
|||
|
||||
template <typename... A>
|
||||
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::variant<A...> &u) {
|
||||
std::visit([&](const auto &x) { EmitVar(o, x); }, u);
|
||||
common::visit([&](const auto &x) { EmitVar(o, x); }, u);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
@ -629,10 +629,10 @@ llvm::raw_ostream &Component::AsFortran(llvm::raw_ostream &o) const {
|
|||
}
|
||||
|
||||
llvm::raw_ostream &NamedEntity::AsFortran(llvm::raw_ostream &o) const {
|
||||
std::visit(common::visitors{
|
||||
[&](SymbolRef s) { EmitVar(o, s); },
|
||||
[&](const Component &c) { c.AsFortran(o); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](SymbolRef s) { EmitVar(o, s); },
|
||||
[&](const Component &c) { c.AsFortran(o); },
|
||||
},
|
||||
u_);
|
||||
return o;
|
||||
}
|
||||
|
@ -712,10 +712,10 @@ llvm::raw_ostream &ProcedureDesignator::AsFortran(llvm::raw_ostream &o) const {
|
|||
|
||||
template <typename T>
|
||||
llvm::raw_ostream &Designator<T>::AsFortran(llvm::raw_ostream &o) const {
|
||||
std::visit(common::visitors{
|
||||
[&](SymbolRef symbol) { EmitVar(o, symbol); },
|
||||
[&](const auto &x) { x.AsFortran(o); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](SymbolRef symbol) { EmitVar(o, symbol); },
|
||||
[&](const auto &x) { x.AsFortran(o); },
|
||||
},
|
||||
u);
|
||||
return o;
|
||||
}
|
||||
|
@ -752,7 +752,7 @@ llvm::raw_ostream &DescriptorInquiry::AsFortran(llvm::raw_ostream &o) const {
|
|||
}
|
||||
|
||||
llvm::raw_ostream &Assignment::AsFortran(llvm::raw_ostream &o) const {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const Assignment::Intrinsic &) {
|
||||
rhs.AsFortran(lhs.AsFortran(o) << '=');
|
||||
|
|
|
@ -480,7 +480,7 @@ MaybeExtentExpr GetExtent(
|
|||
|
||||
MaybeExtentExpr GetExtent(
|
||||
const Subscript &subscript, const NamedEntity &base, int dimension) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const Triplet &triplet) -> MaybeExtentExpr {
|
||||
MaybeExtentExpr upper{triplet.upper()};
|
||||
|
@ -650,7 +650,7 @@ Shape GetUBOUNDs(FoldingContext &context, const NamedEntity &base) {
|
|||
Shape GetUBOUNDs(const NamedEntity &base) { return GetUBOUNDs(nullptr, base); }
|
||||
|
||||
auto GetShapeHelper::operator()(const Symbol &symbol) const -> Result {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const semantics::ObjectEntityDetails &object) {
|
||||
if (IsImpliedShape(symbol) && object.init()) {
|
||||
|
|
|
@ -40,7 +40,7 @@ std::optional<Expr<SomeType>> AsGenericExpr(const Symbol &symbol) {
|
|||
}
|
||||
|
||||
Expr<SomeType> Parenthesize(Expr<SomeType> &&expr) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&x) {
|
||||
using T = std::decay_t<decltype(x)>;
|
||||
if constexpr (common::HasMember<T, TypelessExpression>) {
|
||||
|
@ -48,7 +48,7 @@ Expr<SomeType> Parenthesize(Expr<SomeType> &&expr) {
|
|||
} else if constexpr (std::is_same_v<T, Expr<SomeDerived>>) {
|
||||
return AsGenericExpr(Parentheses<SomeDerived>{std::move(x)});
|
||||
} else {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &&y) {
|
||||
using T = ResultType<decltype(y)>;
|
||||
return AsGenericExpr(Parentheses<T>{std::move(y)});
|
||||
|
@ -69,7 +69,7 @@ std::optional<DataRef> ExtractDataRef(
|
|||
}
|
||||
|
||||
std::optional<DataRef> ExtractSubstringBase(const Substring &substring) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const DataRef &x) -> std::optional<DataRef> { return x; },
|
||||
[&](const StaticDataObject::Pointer &) -> std::optional<DataRef> {
|
||||
|
@ -108,7 +108,7 @@ auto IsVariableHelper::operator()(const ProcedureDesignator &x) const
|
|||
ConvertRealOperandsResult ConvertRealOperands(
|
||||
parser::ContextualMessages &messages, Expr<SomeType> &&x,
|
||||
Expr<SomeType> &&y, int defaultRealKind) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](Expr<SomeInteger> &&ix,
|
||||
Expr<SomeInteger> &&iy) -> ConvertRealOperandsResult {
|
||||
|
@ -190,7 +190,7 @@ std::optional<Expr<SomeType>> Package(
|
|||
template <template <typename> class OPR>
|
||||
std::optional<Expr<SomeType>> MixedRealLeft(
|
||||
Expr<SomeReal> &&rx, Expr<SomeInteger> &&iy) {
|
||||
return Package(std::visit(
|
||||
return Package(common::visit(
|
||||
[&](auto &&rxk) -> Expr<SomeReal> {
|
||||
using resultType = ResultType<decltype(rxk)>;
|
||||
if constexpr (std::is_same_v<OPR<resultType>, Power<resultType>>) {
|
||||
|
@ -210,7 +210,7 @@ std::optional<Expr<SomeComplex>> ConstructComplex(
|
|||
Expr<SomeType> &&imaginary, int defaultRealKind) {
|
||||
if (auto converted{ConvertRealOperands(
|
||||
messages, std::move(real), std::move(imaginary), defaultRealKind)}) {
|
||||
return {std::visit(
|
||||
return {common::visit(
|
||||
[](auto &&pair) {
|
||||
return MakeComplex(std::move(pair[0]), std::move(pair[1]));
|
||||
},
|
||||
|
@ -230,7 +230,7 @@ std::optional<Expr<SomeComplex>> ConstructComplex(
|
|||
}
|
||||
|
||||
Expr<SomeReal> GetComplexPart(const Expr<SomeComplex> &z, bool isImaginary) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &zk) {
|
||||
static constexpr int kind{ResultType<decltype(zk)>::kind};
|
||||
return AsCategoryExpr(ComplexComponent<kind>{isImaginary, zk});
|
||||
|
@ -243,7 +243,7 @@ Expr<SomeReal> GetComplexPart(const Expr<SomeComplex> &z, bool isImaginary) {
|
|||
// the highest precision of REAL and COMPLEX operands as required by Fortran
|
||||
// 2018 10.9.1.3.
|
||||
Expr<SomeComplex> PromoteRealToComplex(Expr<SomeReal> &&someX) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &&x) {
|
||||
using RT = ResultType<decltype(x)>;
|
||||
return AsCategoryExpr(ComplexConstructor<RT::kind>{
|
||||
|
@ -289,7 +289,7 @@ std::optional<Expr<SomeType>> MixedComplexLeft(
|
|||
std::is_same_v<OPR<LargestReal>, Power<LargestReal>>) {
|
||||
// COMPLEX**INTEGER is a special case that doesn't convert the exponent.
|
||||
static_assert(RCAT == TypeCategory::Integer);
|
||||
return Package(std::visit(
|
||||
return Package(common::visit(
|
||||
[&](auto &&zxk) {
|
||||
using Ty = ResultType<decltype(zxk)>;
|
||||
return AsCategoryExpr(
|
||||
|
@ -358,7 +358,7 @@ template <template <typename> class OPR>
|
|||
std::optional<Expr<SomeType>> NumericOperation(
|
||||
parser::ContextualMessages &messages, Expr<SomeType> &&x,
|
||||
Expr<SomeType> &&y, int defaultRealKind) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](Expr<SomeInteger> &&ix, Expr<SomeInteger> &&iy) {
|
||||
return Package(PromoteAndCombine<OPR, TypeCategory::Integer>(
|
||||
|
@ -373,7 +373,7 @@ std::optional<Expr<SomeType>> NumericOperation(
|
|||
return MixedRealLeft<OPR>(std::move(rx), std::move(iy));
|
||||
},
|
||||
[](Expr<SomeInteger> &&ix, Expr<SomeReal> &&ry) {
|
||||
return Package(std::visit(
|
||||
return Package(common::visit(
|
||||
[&](auto &&ryk) -> Expr<SomeReal> {
|
||||
using resultType = ResultType<decltype(ryk)>;
|
||||
return AsCategoryExpr(
|
||||
|
@ -450,7 +450,7 @@ template std::optional<Expr<SomeType>> NumericOperation<Subtract>(
|
|||
|
||||
std::optional<Expr<SomeType>> Negation(
|
||||
parser::ContextualMessages &messages, Expr<SomeType> &&x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](BOZLiteralConstant &&) {
|
||||
messages.Say("BOZ literal cannot be negated"_err_en_US);
|
||||
|
@ -491,7 +491,7 @@ std::optional<Expr<SomeType>> Negation(
|
|||
}
|
||||
|
||||
Expr<SomeLogical> LogicalNegation(Expr<SomeLogical> &&x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &&xk) { return AsCategoryExpr(LogicalNegation(std::move(xk))); },
|
||||
std::move(x.u));
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ Expr<SomeLogical> LogicalNegation(Expr<SomeLogical> &&x) {
|
|||
template <TypeCategory CAT>
|
||||
Expr<LogicalResult> PromoteAndRelate(
|
||||
RelationalOperator opr, Expr<SomeKind<CAT>> &&x, Expr<SomeKind<CAT>> &&y) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[=](auto &&xy) {
|
||||
return PackageRelation(opr, std::move(xy[0]), std::move(xy[1]));
|
||||
},
|
||||
|
@ -508,7 +508,7 @@ Expr<LogicalResult> PromoteAndRelate(
|
|||
|
||||
std::optional<Expr<LogicalResult>> Relate(parser::ContextualMessages &messages,
|
||||
RelationalOperator opr, Expr<SomeType> &&x, Expr<SomeType> &&y) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[=](Expr<SomeInteger> &&ix,
|
||||
Expr<SomeInteger> &&iy) -> std::optional<Expr<LogicalResult>> {
|
||||
|
@ -554,7 +554,7 @@ std::optional<Expr<LogicalResult>> Relate(parser::ContextualMessages &messages,
|
|||
AsGenericExpr(ConvertTo(zy, std::move(rx))), std::move(y));
|
||||
},
|
||||
[&](Expr<SomeCharacter> &&cx, Expr<SomeCharacter> &&cy) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&cxk,
|
||||
auto &&cyk) -> std::optional<Expr<LogicalResult>> {
|
||||
using Ty = ResultType<decltype(cxk)>;
|
||||
|
@ -580,7 +580,7 @@ std::optional<Expr<LogicalResult>> Relate(parser::ContextualMessages &messages,
|
|||
Expr<SomeLogical> BinaryLogicalOperation(
|
||||
LogicalOperator opr, Expr<SomeLogical> &&x, Expr<SomeLogical> &&y) {
|
||||
CHECK(opr != LogicalOperator::Not);
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[=](auto &&xy) {
|
||||
using Ty = ResultType<decltype(xy[0])>;
|
||||
return Expr<SomeLogical>{BinaryLogicalOperation<Ty::kind>(
|
||||
|
@ -592,7 +592,7 @@ Expr<SomeLogical> BinaryLogicalOperation(
|
|||
template <TypeCategory TO>
|
||||
std::optional<Expr<SomeType>> ConvertToNumeric(int kind, Expr<SomeType> &&x) {
|
||||
static_assert(common::IsNumericTypeCategory(TO));
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[=](auto &&cx) -> std::optional<Expr<SomeType>> {
|
||||
using cxType = std::decay_t<decltype(cx)>;
|
||||
if constexpr (!common::HasMember<cxType, TypelessExpression>) {
|
||||
|
@ -632,7 +632,7 @@ std::optional<Expr<SomeType>> ConvertToType(
|
|||
auto converted{
|
||||
ConvertToKind<TypeCategory::Character>(type.kind(), std::move(*cx))};
|
||||
if (auto length{type.GetCharLength()}) {
|
||||
converted = std::visit(
|
||||
converted = common::visit(
|
||||
[&](auto &&x) {
|
||||
using Ty = std::decay_t<decltype(x)>;
|
||||
using CharacterType = typename Ty::Result;
|
||||
|
@ -732,15 +732,15 @@ bool IsFunction(const Expr<SomeType> &expr) {
|
|||
}
|
||||
|
||||
bool IsProcedurePointerTarget(const Expr<SomeType> &expr) {
|
||||
return std::visit(common::visitors{
|
||||
[](const NullPointer &) { return true; },
|
||||
[](const ProcedureDesignator &) { return true; },
|
||||
[](const ProcedureRef &) { return true; },
|
||||
[&](const auto &) {
|
||||
const Symbol *last{GetLastSymbol(expr)};
|
||||
return last && IsProcedurePointer(*last);
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](const NullPointer &) { return true; },
|
||||
[](const ProcedureDesignator &) { return true; },
|
||||
[](const ProcedureRef &) { return true; },
|
||||
[&](const auto &) {
|
||||
const Symbol *last{GetLastSymbol(expr)};
|
||||
return last && IsProcedurePointer(*last);
|
||||
},
|
||||
},
|
||||
expr.u);
|
||||
}
|
||||
|
||||
|
@ -755,7 +755,7 @@ inline const ProcedureRef *UnwrapProcedureRef(const FunctionRef<T> &func) {
|
|||
|
||||
template <typename T>
|
||||
inline const ProcedureRef *UnwrapProcedureRef(const Expr<T> &expr) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &x) { return UnwrapProcedureRef(x); }, expr.u);
|
||||
}
|
||||
|
||||
|
@ -792,7 +792,7 @@ struct IsNullPointerHelper {
|
|||
return (*this)(x.left());
|
||||
}
|
||||
template <typename T> bool operator()(const Expr<T> &x) const {
|
||||
return std::visit(*this, x.u);
|
||||
return common::visit(*this, x.u);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1019,7 +1019,8 @@ static const Symbol *GetLastPointerSymbol(const CoarrayRef &x) {
|
|||
return nullptr;
|
||||
}
|
||||
const Symbol *GetLastPointerSymbol(const DataRef &x) {
|
||||
return std::visit([](const auto &y) { return GetLastPointerSymbol(y); }, x.u);
|
||||
return common::visit(
|
||||
[](const auto &y) { return GetLastPointerSymbol(y); }, x.u);
|
||||
}
|
||||
|
||||
template <TypeCategory TO, TypeCategory FROM>
|
||||
|
@ -1030,7 +1031,7 @@ static std::optional<Expr<SomeType>> DataConstantConversionHelper(
|
|||
if (auto sized{
|
||||
Fold(context, ConvertToType(sizedType, Expr<SomeType>{expr}))}) {
|
||||
if (const auto *someExpr{UnwrapExpr<Expr<SomeKind<FROM>>>(*sized)}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &w) -> std::optional<Expr<SomeType>> {
|
||||
using FromType = typename std::decay_t<decltype(w)>::Result;
|
||||
static constexpr int kind{FromType::kind};
|
||||
|
@ -1210,18 +1211,19 @@ bool IsPureProcedure(const Scope &scope) {
|
|||
bool IsFunction(const Symbol &symbol) {
|
||||
const Symbol &ultimate{symbol.GetUltimate()};
|
||||
return ultimate.test(Symbol::Flag::Function) ||
|
||||
std::visit(common::visitors{
|
||||
[](const SubprogramDetails &x) { return x.isFunction(); },
|
||||
[](const ProcEntityDetails &x) {
|
||||
const auto &ifc{x.interface()};
|
||||
return ifc.type() ||
|
||||
(ifc.symbol() && IsFunction(*ifc.symbol()));
|
||||
},
|
||||
[](const ProcBindingDetails &x) {
|
||||
return IsFunction(x.symbol());
|
||||
},
|
||||
[](const auto &) { return false; },
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[](const SubprogramDetails &x) { return x.isFunction(); },
|
||||
[](const ProcEntityDetails &x) {
|
||||
const auto &ifc{x.interface()};
|
||||
return ifc.type() ||
|
||||
(ifc.symbol() && IsFunction(*ifc.symbol()));
|
||||
},
|
||||
[](const ProcBindingDetails &x) {
|
||||
return IsFunction(x.symbol());
|
||||
},
|
||||
[](const auto &) { return false; },
|
||||
},
|
||||
ultimate.details());
|
||||
}
|
||||
|
||||
|
@ -1231,14 +1233,14 @@ bool IsFunction(const Scope &scope) {
|
|||
}
|
||||
|
||||
bool IsProcedure(const Symbol &symbol) {
|
||||
return std::visit(common::visitors{
|
||||
[](const SubprogramDetails &) { return true; },
|
||||
[](const SubprogramNameDetails &) { return true; },
|
||||
[](const ProcEntityDetails &) { return true; },
|
||||
[](const GenericDetails &) { return true; },
|
||||
[](const ProcBindingDetails &) { return true; },
|
||||
[](const auto &) { return false; },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](const SubprogramDetails &) { return true; },
|
||||
[](const SubprogramNameDetails &) { return true; },
|
||||
[](const ProcEntityDetails &) { return true; },
|
||||
[](const GenericDetails &) { return true; },
|
||||
[](const ProcBindingDetails &) { return true; },
|
||||
[](const auto &) { return false; },
|
||||
},
|
||||
symbol.GetUltimate().details());
|
||||
}
|
||||
|
||||
|
@ -1352,7 +1354,7 @@ bool IsSaved(const Symbol &original) {
|
|||
}
|
||||
|
||||
bool IsDummy(const Symbol &symbol) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{[](const EntityDetails &x) { return x.isDummy(); },
|
||||
[](const ObjectEntityDetails &x) { return x.isDummy(); },
|
||||
[](const ProcEntityDetails &x) { return x.isDummy(); },
|
||||
|
@ -1481,7 +1483,7 @@ static const Symbol *FindFunctionResult(
|
|||
if (!seen.insert(root).second) {
|
||||
return nullptr; // don't loop
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{[](const SubprogramDetails &subp) {
|
||||
return subp.isFunction() ? &subp.result() : nullptr;
|
||||
},
|
||||
|
|
|
@ -55,7 +55,7 @@ static bool IsDescriptor(const ProcEntityDetails &details) {
|
|||
}
|
||||
|
||||
bool IsDescriptor(const Symbol &symbol) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const ObjectEntityDetails &d) {
|
||||
return IsAllocatableOrPointer(symbol) || IsDescriptor(d);
|
||||
|
|
|
@ -145,7 +145,7 @@ std::optional<Expr<SubscriptInteger>> Substring::upper() const {
|
|||
if (upper_) {
|
||||
return upper_.value().value();
|
||||
} else {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const DataRef &dataRef) { return dataRef.LEN(); },
|
||||
[](const StaticDataObject::Pointer &object)
|
||||
|
@ -208,7 +208,7 @@ std::optional<Expr<SomeCharacter>> Substring::Fold(FoldingContext &context) {
|
|||
}
|
||||
std::optional<Expr<SomeCharacter>> result;
|
||||
if (strings) {
|
||||
result = std::visit(
|
||||
result = common::visit(
|
||||
[&](const auto &expr) -> std::optional<Expr<SomeCharacter>> {
|
||||
using Type = typename std::decay_t<decltype(expr)>::Result;
|
||||
if (const auto *cc{std::get_if<Constant<Type>>(&expr.u)}) {
|
||||
|
@ -281,7 +281,7 @@ static std::optional<Expr<SubscriptInteger>> SymbolLEN(const Symbol &symbol) {
|
|||
}
|
||||
|
||||
std::optional<Expr<SubscriptInteger>> BaseObject::LEN() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const Symbol &symbol) { return SymbolLEN(symbol); },
|
||||
[](const StaticDataObject::Pointer &object)
|
||||
|
@ -309,10 +309,10 @@ std::optional<Expr<SubscriptInteger>> CoarrayRef::LEN() const {
|
|||
}
|
||||
|
||||
std::optional<Expr<SubscriptInteger>> DataRef::LEN() const {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return SymbolLEN(symbol); },
|
||||
[](const auto &x) { return x.LEN(); },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return SymbolLEN(symbol); },
|
||||
[](const auto &x) { return x.LEN(); },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
|
@ -329,10 +329,10 @@ std::optional<Expr<SubscriptInteger>> Substring::LEN() const {
|
|||
template <typename T>
|
||||
std::optional<Expr<SubscriptInteger>> Designator<T>::LEN() const {
|
||||
if constexpr (T::category == TypeCategory::Character) {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return SymbolLEN(symbol); },
|
||||
[](const auto &x) { return x.LEN(); },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return SymbolLEN(symbol); },
|
||||
[](const auto &x) { return x.LEN(); },
|
||||
},
|
||||
u);
|
||||
} else {
|
||||
common::die("Designator<non-char>::LEN() called");
|
||||
|
@ -342,7 +342,7 @@ std::optional<Expr<SubscriptInteger>> Designator<T>::LEN() const {
|
|||
|
||||
std::optional<Expr<SubscriptInteger>> ProcedureDesignator::LEN() const {
|
||||
using T = std::optional<Expr<SubscriptInteger>>;
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](SymbolRef symbol) -> T { return SymbolLEN(symbol); },
|
||||
[](const common::CopyableIndirection<Component> &c) -> T {
|
||||
|
@ -367,10 +367,10 @@ std::optional<Expr<SubscriptInteger>> ProcedureDesignator::LEN() const {
|
|||
|
||||
// Rank()
|
||||
int BaseObject::Rank() const {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return symbol->Rank(); },
|
||||
[](const StaticDataObject::Pointer &) { return 0; },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return symbol->Rank(); },
|
||||
[](const StaticDataObject::Pointer &) { return 0; },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
|
@ -382,20 +382,20 @@ int Component::Rank() const {
|
|||
}
|
||||
|
||||
int NamedEntity::Rank() const {
|
||||
return std::visit(common::visitors{
|
||||
[](const SymbolRef s) { return s->Rank(); },
|
||||
[](const Component &c) { return c.Rank(); },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](const SymbolRef s) { return s->Rank(); },
|
||||
[](const Component &c) { return c.Rank(); },
|
||||
},
|
||||
u_);
|
||||
}
|
||||
|
||||
int Subscript::Rank() const {
|
||||
return std::visit(common::visitors{
|
||||
[](const IndirectSubscriptIntegerExpr &x) {
|
||||
return x.value().Rank();
|
||||
},
|
||||
[](const Triplet &) { return 1; },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](const IndirectSubscriptIntegerExpr &x) {
|
||||
return x.value().Rank();
|
||||
},
|
||||
[](const Triplet &) { return 1; },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
|
@ -426,28 +426,29 @@ int CoarrayRef::Rank() const {
|
|||
}
|
||||
|
||||
int DataRef::Rank() const {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return symbol->Rank(); },
|
||||
[](const auto &x) { return x.Rank(); },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return symbol->Rank(); },
|
||||
[](const auto &x) { return x.Rank(); },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
int Substring::Rank() const {
|
||||
return std::visit(common::visitors{
|
||||
[](const DataRef &dataRef) { return dataRef.Rank(); },
|
||||
[](const StaticDataObject::Pointer &) { return 0; },
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const DataRef &dataRef) { return dataRef.Rank(); },
|
||||
[](const StaticDataObject::Pointer &) { return 0; },
|
||||
},
|
||||
parent_);
|
||||
}
|
||||
|
||||
int ComplexPart::Rank() const { return complex_.Rank(); }
|
||||
|
||||
template <typename T> int Designator<T>::Rank() const {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return symbol->Rank(); },
|
||||
[](const auto &x) { return x.Rank(); },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return symbol->Rank(); },
|
||||
[](const auto &x) { return x.Rank(); },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
|
@ -457,38 +458,39 @@ const Symbol &Component::GetFirstSymbol() const {
|
|||
}
|
||||
|
||||
const Symbol &NamedEntity::GetFirstSymbol() const {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef s) -> const Symbol & { return s; },
|
||||
[](const Component &c) -> const Symbol & {
|
||||
return c.GetFirstSymbol();
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SymbolRef s) -> const Symbol & { return s; },
|
||||
[](const Component &c) -> const Symbol & {
|
||||
return c.GetFirstSymbol();
|
||||
},
|
||||
},
|
||||
u_);
|
||||
}
|
||||
|
||||
const Symbol &NamedEntity::GetLastSymbol() const {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef s) -> const Symbol & { return s; },
|
||||
[](const Component &c) -> const Symbol & {
|
||||
return c.GetLastSymbol();
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SymbolRef s) -> const Symbol & { return s; },
|
||||
[](const Component &c) -> const Symbol & {
|
||||
return c.GetLastSymbol();
|
||||
},
|
||||
},
|
||||
u_);
|
||||
}
|
||||
|
||||
const Component *NamedEntity::UnwrapComponent() const {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef) -> const Component * { return nullptr; },
|
||||
[](const Component &c) { return &c; },
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](SymbolRef) -> const Component * { return nullptr; },
|
||||
[](const Component &c) { return &c; },
|
||||
},
|
||||
u_);
|
||||
}
|
||||
|
||||
Component *NamedEntity::UnwrapComponent() {
|
||||
return std::visit(common::visitors{
|
||||
[](SymbolRef &) -> Component * { return nullptr; },
|
||||
[](Component &c) { return &c; },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SymbolRef &) -> Component * { return nullptr; },
|
||||
[](Component &c) { return &c; },
|
||||
},
|
||||
u_);
|
||||
}
|
||||
|
||||
|
@ -499,35 +501,35 @@ const Symbol &ArrayRef::GetFirstSymbol() const {
|
|||
const Symbol &ArrayRef::GetLastSymbol() const { return base_.GetLastSymbol(); }
|
||||
|
||||
const Symbol &DataRef::GetFirstSymbol() const {
|
||||
return *std::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return &*symbol; },
|
||||
[](const auto &x) { return &x.GetFirstSymbol(); },
|
||||
},
|
||||
return *common::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return &*symbol; },
|
||||
[](const auto &x) { return &x.GetFirstSymbol(); },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
const Symbol &DataRef::GetLastSymbol() const {
|
||||
return *std::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return &*symbol; },
|
||||
[](const auto &x) { return &x.GetLastSymbol(); },
|
||||
},
|
||||
return *common::visit(common::visitors{
|
||||
[](SymbolRef symbol) { return &*symbol; },
|
||||
[](const auto &x) { return &x.GetLastSymbol(); },
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
BaseObject Substring::GetBaseObject() const {
|
||||
return std::visit(common::visitors{
|
||||
[](const DataRef &dataRef) {
|
||||
return BaseObject{dataRef.GetFirstSymbol()};
|
||||
},
|
||||
[](StaticDataObject::Pointer pointer) {
|
||||
return BaseObject{std::move(pointer)};
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](const DataRef &dataRef) {
|
||||
return BaseObject{dataRef.GetFirstSymbol()};
|
||||
},
|
||||
[](StaticDataObject::Pointer pointer) {
|
||||
return BaseObject{std::move(pointer)};
|
||||
},
|
||||
},
|
||||
parent_);
|
||||
}
|
||||
|
||||
const Symbol *Substring::GetLastSymbol() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const DataRef &dataRef) { return &dataRef.GetLastSymbol(); },
|
||||
[](const auto &) -> const Symbol * { return nullptr; },
|
||||
|
@ -536,7 +538,7 @@ const Symbol *Substring::GetLastSymbol() const {
|
|||
}
|
||||
|
||||
template <typename T> BaseObject Designator<T>::GetBaseObject() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](SymbolRef symbol) { return BaseObject{symbol}; },
|
||||
[](const Substring &sstring) { return sstring.GetBaseObject(); },
|
||||
|
@ -554,7 +556,7 @@ template <typename T> BaseObject Designator<T>::GetBaseObject() const {
|
|||
}
|
||||
|
||||
template <typename T> const Symbol *Designator<T>::GetLastSymbol() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](SymbolRef symbol) { return &*symbol; },
|
||||
[](const Substring &sstring) { return sstring.GetLastSymbol(); },
|
||||
|
|
|
@ -85,7 +85,7 @@ const char *MessageFormattedText::Convert(CharBlock x) {
|
|||
}
|
||||
|
||||
std::string MessageExpectedText::ToString() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](CharBlock cb) {
|
||||
return MessageFormattedText("expected '%s'"_err_en_US, cb)
|
||||
|
@ -124,13 +124,13 @@ std::string MessageExpectedText::ToString() const {
|
|||
}
|
||||
|
||||
bool MessageExpectedText::Merge(const MessageExpectedText &that) {
|
||||
return std::visit(common::visitors{
|
||||
[](SetOfChars &s1, const SetOfChars &s2) {
|
||||
s1 = s1.Union(s2);
|
||||
return true;
|
||||
},
|
||||
[](const auto &, const auto &) { return false; },
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[](SetOfChars &s1, const SetOfChars &s2) {
|
||||
s1 = s1.Union(s2);
|
||||
return true;
|
||||
},
|
||||
[](const auto &, const auto &) { return false; },
|
||||
},
|
||||
u_, that.u_);
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ bool Message::SortBefore(const Message &that) const {
|
|||
// free and needs to be deferred, and many messages created during parsing
|
||||
// are speculative. Messages with ProvenanceRange locations are ordered
|
||||
// before others for sorting.
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](CharBlock cb1, CharBlock cb2) {
|
||||
return cb1.begin() < cb2.begin();
|
||||
|
@ -158,7 +158,7 @@ bool Message::SortBefore(const Message &that) const {
|
|||
bool Message::IsFatal() const { return severity() == Severity::Error; }
|
||||
|
||||
Severity Message::severity() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const MessageExpectedText &) { return Severity::Error; },
|
||||
[](const MessageFixedText &x) { return x.severity(); },
|
||||
|
@ -168,7 +168,7 @@ Severity Message::severity() const {
|
|||
}
|
||||
|
||||
std::string Message::ToString() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const MessageFixedText &t) {
|
||||
return t.text().NULTerminatedToString();
|
||||
|
@ -193,7 +193,7 @@ void Message::ResolveProvenances(const AllCookedSources &allCooked) {
|
|||
|
||||
std::optional<ProvenanceRange> Message::GetProvenanceRange(
|
||||
const AllCookedSources &allCooked) const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](CharBlock cb) { return allCooked.GetProvenanceRange(cb); },
|
||||
[](const ProvenanceRange &pr) { return std::make_optional(pr); },
|
||||
|
@ -259,7 +259,7 @@ bool Message::Merge(const Message &that) {
|
|||
return AtSameLocation(that) &&
|
||||
(!that.attachment_.get() ||
|
||||
attachment_.get() == that.attachment_.get()) &&
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[](MessageExpectedText &e1, const MessageExpectedText &e2) {
|
||||
return e1.Merge(e2);
|
||||
|
@ -287,7 +287,7 @@ Message &Message::Attach(std::unique_ptr<Message> &&m) {
|
|||
}
|
||||
|
||||
bool Message::AtSameLocation(const Message &that) const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](CharBlock cb1, CharBlock cb2) {
|
||||
return cb1.begin() == cb2.begin();
|
||||
|
|
|
@ -32,7 +32,7 @@ CommonStmt::CommonStmt(std::optional<Name> &&name,
|
|||
|
||||
// R901 designator
|
||||
bool Designator::EndsInBareName() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const DataRef &dr) {
|
||||
return std::holds_alternative<Name>(dr.u) ||
|
||||
|
@ -120,11 +120,11 @@ template <typename T> T WithSource(CharBlock source, T &&x) {
|
|||
}
|
||||
|
||||
static Expr ActualArgToExpr(ActualArgSpec &arg) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](common::Indirection<Expr> &y) { return std::move(y.value()); },
|
||||
[&](common::Indirection<Variable> &y) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](common::Indirection<Designator> &z) {
|
||||
return WithSource(
|
||||
|
@ -147,7 +147,7 @@ Designator FunctionReference::ConvertToArrayElementRef() {
|
|||
for (auto &arg : std::get<std::list<ActualArgSpec>>(v.t)) {
|
||||
args.emplace_back(ActualArgToExpr(arg));
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const Name &name) {
|
||||
return WithSource(
|
||||
|
@ -231,7 +231,7 @@ Statement<ActionStmt> StmtFunctionStmt::ConvertToAssignment() {
|
|||
}
|
||||
|
||||
CharBlock Variable::GetSource() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const common::Indirection<Designator> &des) {
|
||||
return des.value().source;
|
||||
|
|
|
@ -232,7 +232,7 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
|
|||
}
|
||||
CHECK(IsValid(*range));
|
||||
const Origin &origin{MapToOrigin(range->start())};
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const Inclusion &inc) {
|
||||
o << inc.source.path();
|
||||
|
@ -294,23 +294,24 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
|
|||
const SourceFile *AllSources::GetSourceFile(
|
||||
Provenance at, std::size_t *offset) const {
|
||||
const Origin &origin{MapToOrigin(at)};
|
||||
return std::visit(common::visitors{
|
||||
[&](const Inclusion &inc) {
|
||||
if (offset) {
|
||||
*offset = origin.covers.MemberOffset(at);
|
||||
}
|
||||
return &inc.source;
|
||||
},
|
||||
[&](const Macro &) {
|
||||
return GetSourceFile(origin.replaces.start(), offset);
|
||||
},
|
||||
[offset](const CompilerInsertion &) {
|
||||
if (offset) {
|
||||
*offset = 0;
|
||||
}
|
||||
return static_cast<const SourceFile *>(nullptr);
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[&](const Inclusion &inc) {
|
||||
if (offset) {
|
||||
*offset = origin.covers.MemberOffset(at);
|
||||
}
|
||||
return &inc.source;
|
||||
},
|
||||
[&](const Macro &) {
|
||||
return GetSourceFile(
|
||||
origin.replaces.start(), offset);
|
||||
},
|
||||
[offset](const CompilerInsertion &) {
|
||||
if (offset) {
|
||||
*offset = 0;
|
||||
}
|
||||
return static_cast<const SourceFile *>(nullptr);
|
||||
},
|
||||
},
|
||||
origin.u);
|
||||
}
|
||||
|
||||
|
@ -325,7 +326,7 @@ const char *AllSources::GetSource(ProvenanceRange range) const {
|
|||
std::optional<SourcePosition> AllSources::GetSourcePosition(
|
||||
Provenance prov) const {
|
||||
const Origin &origin{MapToOrigin(prov)};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const Inclusion &inc) -> std::optional<SourcePosition> {
|
||||
std::size_t offset{origin.covers.MemberOffset(prov)};
|
||||
|
@ -400,7 +401,7 @@ AllSources::Origin::Origin(ProvenanceRange r, const std::string &text)
|
|||
: u{CompilerInsertion{text}}, covers{r} {}
|
||||
|
||||
const char &AllSources::Origin::operator[](std::size_t n) const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[n](const Inclusion &inc) -> const char & {
|
||||
return inc.source.content()[n];
|
||||
|
@ -511,23 +512,23 @@ llvm::raw_ostream &AllSources::Dump(llvm::raw_ostream &o) const {
|
|||
o << " ";
|
||||
DumpRange(o, m.covers);
|
||||
o << " -> ";
|
||||
std::visit(common::visitors{
|
||||
[&](const Inclusion &inc) {
|
||||
if (inc.isModule) {
|
||||
o << "module ";
|
||||
}
|
||||
o << "file " << inc.source.path();
|
||||
},
|
||||
[&](const Macro &mac) { o << "macro " << mac.expansion; },
|
||||
[&](const CompilerInsertion &ins) {
|
||||
o << "compiler '" << ins.text << '\'';
|
||||
if (ins.text.length() == 1) {
|
||||
int ch = ins.text[0];
|
||||
o << "(0x";
|
||||
o.write_hex(ch & 0xff) << ")";
|
||||
}
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const Inclusion &inc) {
|
||||
if (inc.isModule) {
|
||||
o << "module ";
|
||||
}
|
||||
o << "file " << inc.source.path();
|
||||
},
|
||||
[&](const Macro &mac) { o << "macro " << mac.expansion; },
|
||||
[&](const CompilerInsertion &ins) {
|
||||
o << "compiler '" << ins.text << '\'';
|
||||
if (ins.text.length() == 1) {
|
||||
int ch = ins.text[0];
|
||||
o << "(0x";
|
||||
o.write_hex(ch & 0xff) << ")";
|
||||
}
|
||||
},
|
||||
},
|
||||
m.u);
|
||||
if (IsValid(m.replaces)) {
|
||||
o << " replaces ";
|
||||
|
|
|
@ -17,7 +17,7 @@ const Name &GetLastName(const StructureComponent &x) {
|
|||
}
|
||||
|
||||
const Name &GetLastName(const DataRef &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const Name &name) -> const Name & { return name; },
|
||||
[](const common::Indirection<StructureComponent> &sc)
|
||||
|
@ -36,7 +36,7 @@ const Name &GetLastName(const Substring &x) {
|
|||
}
|
||||
|
||||
const Name &GetLastName(const Designator &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &y) -> const Name & { return GetLastName(y); }, x.u);
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ const Name &GetLastName(const ProcComponentRef &x) {
|
|||
}
|
||||
|
||||
const Name &GetLastName(const ProcedureDesignator &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &y) -> const Name & { return GetLastName(y); }, x.u);
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ const Name &GetLastName(const Call &x) {
|
|||
const Name &GetLastName(const FunctionReference &x) { return GetLastName(x.v); }
|
||||
|
||||
const Name &GetLastName(const Variable &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &indirection) -> const Name & {
|
||||
return GetLastName(indirection.value());
|
||||
},
|
||||
|
@ -64,7 +64,7 @@ const Name &GetLastName(const Variable &x) {
|
|||
}
|
||||
|
||||
const Name &GetLastName(const AllocateObject &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &y) -> const Name & { return GetLastName(y); }, x.u);
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ const Name &GetFirstName(const StructureComponent &x) {
|
|||
}
|
||||
|
||||
const Name &GetFirstName(const DataRef &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const Name &name) -> const Name & { return name; },
|
||||
[](const common::Indirection<StructureComponent> &sc)
|
||||
|
@ -94,7 +94,7 @@ const Name &GetFirstName(const Substring &x) {
|
|||
}
|
||||
|
||||
const Name &GetFirstName(const Designator &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &y) -> const Name & { return GetFirstName(y); }, x.u);
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ const Name &GetFirstName(const ProcComponentRef &x) {
|
|||
}
|
||||
|
||||
const Name &GetFirstName(const ProcedureDesignator &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &y) -> const Name & { return GetFirstName(y); }, x.u);
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ const Name &GetFirstName(const FunctionReference &x) {
|
|||
}
|
||||
|
||||
const Name &GetFirstName(const Variable &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &indirect) -> const Name & {
|
||||
return GetFirstName(indirect.value());
|
||||
},
|
||||
|
@ -124,7 +124,7 @@ const Name &GetFirstName(const Variable &x) {
|
|||
}
|
||||
|
||||
const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &base) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const Name &) -> const CoindexedNamedObject * { return nullptr; },
|
||||
[](const common::Indirection<CoindexedNamedObject> &x)
|
||||
|
@ -137,19 +137,19 @@ const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &base) {
|
|||
}
|
||||
const CoindexedNamedObject *GetCoindexedNamedObject(
|
||||
const Designator &designator) {
|
||||
return std::visit(common::visitors{
|
||||
[](const DataRef &x) -> const CoindexedNamedObject * {
|
||||
return GetCoindexedNamedObject(x);
|
||||
},
|
||||
[](const Substring &x) -> const CoindexedNamedObject * {
|
||||
return GetCoindexedNamedObject(
|
||||
std::get<DataRef>(x.t));
|
||||
},
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const DataRef &x) -> const CoindexedNamedObject * {
|
||||
return GetCoindexedNamedObject(x);
|
||||
},
|
||||
[](const Substring &x) -> const CoindexedNamedObject * {
|
||||
return GetCoindexedNamedObject(std::get<DataRef>(x.t));
|
||||
},
|
||||
},
|
||||
designator.u);
|
||||
}
|
||||
const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &variable) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const common::Indirection<Designator> &designator)
|
||||
-> const CoindexedNamedObject * {
|
||||
|
@ -161,7 +161,7 @@ const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &variable) {
|
|||
}
|
||||
const CoindexedNamedObject *GetCoindexedNamedObject(
|
||||
const AllocateObject &allocateObject) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const StructureComponent &x) -> const CoindexedNamedObject * {
|
||||
return GetCoindexedNamedObject(x.base);
|
||||
|
|
|
@ -165,7 +165,7 @@ public:
|
|||
Word("INTEGER");
|
||||
}
|
||||
void Unparse(const KindSelector &x) { // R706
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const ScalarIntConstantExpr &y) {
|
||||
Put('('), Word("KIND="), Walk(y), Put(')');
|
||||
|
@ -196,16 +196,16 @@ public:
|
|||
Walk(", LEN=", x.length), Put(')');
|
||||
}
|
||||
void Unparse(const LengthSelector &x) { // R722
|
||||
std::visit(common::visitors{
|
||||
[&](const TypeParamValue &y) {
|
||||
Put('('), Word("LEN="), Walk(y), Put(')');
|
||||
},
|
||||
[&](const CharLength &y) { Put('*'), Walk(y); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const TypeParamValue &y) {
|
||||
Put('('), Word("LEN="), Walk(y), Put(')');
|
||||
},
|
||||
[&](const CharLength &y) { Put('*'), Walk(y); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const CharLength &x) { // R723
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const TypeParamValue &y) { Put('('), Walk(y), Put(')'); },
|
||||
[&](const std::int64_t &y) { Walk(y); },
|
||||
|
@ -271,7 +271,7 @@ public:
|
|||
(!std::holds_alternative<DeclarationTypeSpec::Record>(dts.u) &&
|
||||
std::none_of(
|
||||
decls.begin(), decls.end(), [](const ComponentOrFill &c) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const ComponentDecl &d) {
|
||||
const auto &init{
|
||||
|
@ -295,19 +295,19 @@ public:
|
|||
void Unparse(const Pointer &) { Word("POINTER"); }
|
||||
void Unparse(const Contiguous &) { Word("CONTIGUOUS"); }
|
||||
void Before(const ComponentAttrSpec &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const CoarraySpec &) { Word("CODIMENSION["); },
|
||||
[&](const ComponentArraySpec &) { Word("DIMENSION("); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const CoarraySpec &) { Word("CODIMENSION["); },
|
||||
[&](const ComponentArraySpec &) { Word("DIMENSION("); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Post(const ComponentAttrSpec &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const CoarraySpec &) { Put(']'); },
|
||||
[&](const ComponentArraySpec &) { Put(')'); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const CoarraySpec &) { Put(']'); },
|
||||
[&](const ComponentArraySpec &) { Put(')'); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const ComponentDecl &x) { // R739
|
||||
|
@ -323,10 +323,11 @@ public:
|
|||
Walk("*", std::get<std::optional<CharLength>>(x.t));
|
||||
}
|
||||
void Unparse(const ComponentArraySpec &x) { // R740
|
||||
std::visit(common::visitors{
|
||||
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
|
||||
[&](const DeferredShapeSpecList &y) { Walk(y); },
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
|
||||
[&](const DeferredShapeSpecList &y) { Walk(y); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const ProcComponentDefStmt &x) { // R741
|
||||
|
@ -340,14 +341,15 @@ public:
|
|||
}
|
||||
void Unparse(const Pass &x) { Word("PASS"), Walk("(", x.v, ")"); }
|
||||
void Unparse(const Initialization &x) { // R743 & R805
|
||||
std::visit(common::visitors{
|
||||
[&](const ConstantExpr &y) { Put(" = "), Walk(y); },
|
||||
[&](const NullInit &y) { Put(" => "), Walk(y); },
|
||||
[&](const InitialDataTarget &y) { Put(" => "), Walk(y); },
|
||||
[&](const std::list<common::Indirection<DataStmtValue>> &y) {
|
||||
Walk("/", y, ", ", "/");
|
||||
},
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const ConstantExpr &y) { Put(" = "), Walk(y); },
|
||||
[&](const NullInit &y) { Put(" => "), Walk(y); },
|
||||
[&](const InitialDataTarget &y) { Put(" => "), Walk(y); },
|
||||
[&](const std::list<common::Indirection<DataStmtValue>> &y) {
|
||||
Walk("/", y, ", ", "/");
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const PrivateStmt &) { // R745
|
||||
|
@ -487,19 +489,19 @@ public:
|
|||
Put(' '), Walk(std::get<std::list<EntityDecl>>(x.t), ", ");
|
||||
}
|
||||
void Before(const AttrSpec &x) { // R802
|
||||
std::visit(common::visitors{
|
||||
[&](const CoarraySpec &) { Word("CODIMENSION["); },
|
||||
[&](const ArraySpec &) { Word("DIMENSION("); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const CoarraySpec &) { Word("CODIMENSION["); },
|
||||
[&](const ArraySpec &) { Word("DIMENSION("); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Post(const AttrSpec &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const CoarraySpec &) { Put(']'); },
|
||||
[&](const ArraySpec &) { Put(')'); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const CoarraySpec &) { Put(']'); },
|
||||
[&](const ArraySpec &) { Put(')'); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const EntityDecl &x) { // R803
|
||||
|
@ -516,10 +518,10 @@ public:
|
|||
Word("BIND(C"), Walk(", NAME=", x.v), Put(')');
|
||||
}
|
||||
void Unparse(const CoarraySpec &x) { // R809
|
||||
std::visit(common::visitors{
|
||||
[&](const DeferredCoshapeSpecList &y) { Walk(y); },
|
||||
[&](const ExplicitCoshapeSpec &y) { Walk(y); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const DeferredCoshapeSpecList &y) { Walk(y); },
|
||||
[&](const ExplicitCoshapeSpec &y) { Walk(y); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const DeferredCoshapeSpecList &x) { // R810
|
||||
|
@ -539,14 +541,15 @@ public:
|
|||
Walk(std::get<SpecificationExpr>(x.t));
|
||||
}
|
||||
void Unparse(const ArraySpec &x) { // R815
|
||||
std::visit(common::visitors{
|
||||
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
|
||||
[&](const std::list<AssumedShapeSpec> &y) { Walk(y, ","); },
|
||||
[&](const DeferredShapeSpecList &y) { Walk(y); },
|
||||
[&](const AssumedSizeSpec &y) { Walk(y); },
|
||||
[&](const ImpliedShapeSpec &y) { Walk(y); },
|
||||
[&](const AssumedRankSpec &y) { Walk(y); },
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const std::list<ExplicitShapeSpec> &y) { Walk(y, ","); },
|
||||
[&](const std::list<AssumedShapeSpec> &y) { Walk(y, ","); },
|
||||
[&](const DeferredShapeSpecList &y) { Walk(y); },
|
||||
[&](const AssumedSizeSpec &y) { Walk(y); },
|
||||
[&](const ImpliedShapeSpec &y) { Walk(y); },
|
||||
[&](const AssumedRankSpec &y) { Walk(y); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Post(const AssumedShapeSpec &) { Put(':'); } // R819
|
||||
|
@ -681,12 +684,13 @@ public:
|
|||
}
|
||||
void Unparse(const ImplicitStmt &x) { // R863
|
||||
Word("IMPLICIT ");
|
||||
std::visit(common::visitors{
|
||||
[&](const std::list<ImplicitSpec> &y) { Walk(y, ", "); },
|
||||
[&](const std::list<ImplicitStmt::ImplicitNoneNameSpec> &y) {
|
||||
Word("NONE"), Walk(" (", y, ", ", ")");
|
||||
},
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const std::list<ImplicitSpec> &y) { Walk(y, ", "); },
|
||||
[&](const std::list<ImplicitStmt::ImplicitNoneNameSpec> &y) {
|
||||
Word("NONE"), Walk(" (", y, ", ", ")");
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const ImplicitSpec &x) { // R864
|
||||
|
@ -800,11 +804,11 @@ public:
|
|||
Walk(", ", std::get<std::list<AllocOpt>>(x.t), ", "), Put(')');
|
||||
}
|
||||
void Before(const AllocOpt &x) { // R928, R931
|
||||
std::visit(common::visitors{
|
||||
[&](const AllocOpt::Mold &) { Word("MOLD="); },
|
||||
[&](const AllocOpt::Source &) { Word("SOURCE="); },
|
||||
[](const StatOrErrmsg &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const AllocOpt::Mold &) { Word("MOLD="); },
|
||||
[&](const AllocOpt::Source &) { Word("SOURCE="); },
|
||||
[](const StatOrErrmsg &) {},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const Allocation &x) { // R932
|
||||
|
@ -829,10 +833,10 @@ public:
|
|||
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
|
||||
}
|
||||
void Before(const StatOrErrmsg &x) { // R942 & R1165
|
||||
std::visit(common::visitors{
|
||||
[&](const StatVariable &) { Word("STAT="); },
|
||||
[&](const MsgVariable &) { Word("ERRMSG="); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const StatVariable &) { Word("STAT="); },
|
||||
[&](const MsgVariable &) { Word("ERRMSG="); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
|
||||
|
@ -887,7 +891,7 @@ public:
|
|||
Put('\n');
|
||||
} else {
|
||||
Walk(std::get<DataRef>(x.t));
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const std::list<BoundsRemapping> &y) {
|
||||
Put('('), Walk(y), Put(')');
|
||||
|
@ -991,12 +995,12 @@ public:
|
|||
Word("DO "), Walk(std::get<std::optional<LoopControl>>(x.t));
|
||||
}
|
||||
void Unparse(const LoopControl &x) { // R1123
|
||||
std::visit(common::visitors{
|
||||
[&](const ScalarLogicalExpr &y) {
|
||||
Word("WHILE ("), Walk(y), Put(')');
|
||||
},
|
||||
[&](const auto &y) { Walk(y); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const ScalarLogicalExpr &y) {
|
||||
Word("WHILE ("), Walk(y), Put(')');
|
||||
},
|
||||
[&](const auto &y) { Walk(y); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const ConcurrentHeader &x) { // R1125
|
||||
|
@ -1060,12 +1064,12 @@ public:
|
|||
Outdent(), Word("END SELECT"), Walk(" ", x.v);
|
||||
}
|
||||
void Unparse(const CaseSelector &x) { // R1145
|
||||
std::visit(common::visitors{
|
||||
[&](const std::list<CaseValueRange> &y) {
|
||||
Put('('), Walk(y), Put(')');
|
||||
},
|
||||
[&](const Default &) { Word("DEFAULT"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const std::list<CaseValueRange> &y) {
|
||||
Put('('), Walk(y), Put(')');
|
||||
},
|
||||
[&](const Default &) { Word("DEFAULT"); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const CaseValueRange::Range &x) { // R1146
|
||||
|
@ -1078,13 +1082,13 @@ public:
|
|||
}
|
||||
void Unparse(const SelectRankCaseStmt &x) { // R1150
|
||||
Outdent(), Word("RANK ");
|
||||
std::visit(common::visitors{
|
||||
[&](const ScalarIntConstantExpr &y) {
|
||||
Put('('), Walk(y), Put(')');
|
||||
},
|
||||
[&](const Star &) { Put("(*)"); },
|
||||
[&](const Default &) { Word("DEFAULT"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const ScalarIntConstantExpr &y) {
|
||||
Put('('), Walk(y), Put(')');
|
||||
},
|
||||
[&](const Star &) { Put("(*)"); },
|
||||
[&](const Default &) { Word("DEFAULT"); },
|
||||
},
|
||||
std::get<SelectRankCaseStmt::Rank>(x.t).u);
|
||||
Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
|
||||
}
|
||||
|
@ -1098,7 +1102,7 @@ public:
|
|||
Walk(" ", std::get<std::optional<Name>>(x.t)), Indent();
|
||||
}
|
||||
void Unparse(const TypeGuardStmt::Guard &x) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const TypeSpec &y) { Word("TYPE IS ("), Walk(y), Put(')'); },
|
||||
[&](const DerivedTypeSpec &y) {
|
||||
|
@ -1150,10 +1154,10 @@ public:
|
|||
Walk(", ", std::get<std::list<StatOrErrmsg>>(x.t), ", "), Put(')');
|
||||
}
|
||||
void Before(const EventWaitStmt::EventWaitSpec &x) { // R1173, R1174
|
||||
std::visit(common::visitors{
|
||||
[&](const ScalarIntExpr &) { Word("UNTIL_COUNT="); },
|
||||
[](const StatOrErrmsg &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const ScalarIntExpr &) { Word("UNTIL_COUNT="); },
|
||||
[](const StatOrErrmsg &) {},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const EventWaitStmt &x) { // R1170
|
||||
|
@ -1168,10 +1172,10 @@ public:
|
|||
Put(')');
|
||||
}
|
||||
void Before(const FormTeamStmt::FormTeamSpec &x) { // R1176, R1178
|
||||
std::visit(common::visitors{
|
||||
[&](const ScalarIntExpr &) { Word("NEW_INDEX="); },
|
||||
[](const StatOrErrmsg &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const ScalarIntExpr &) { Word("NEW_INDEX="); },
|
||||
[](const StatOrErrmsg &) {},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const LockStmt &x) { // R1179
|
||||
|
@ -1180,7 +1184,7 @@ public:
|
|||
Put(')');
|
||||
}
|
||||
void Before(const LockStmt::LockStat &x) { // R1180
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const ScalarLogicalVariable &) { Word("ACQUIRED_LOCK="); },
|
||||
[](const StatOrErrmsg &) {},
|
||||
|
@ -1197,57 +1201,57 @@ public:
|
|||
Word("OPEN ("), Walk(x.v, ", "), Put(')');
|
||||
}
|
||||
bool Pre(const ConnectSpec &x) { // R1205
|
||||
return std::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) {
|
||||
Word("UNIT=");
|
||||
return true;
|
||||
},
|
||||
[&](const FileNameExpr &) {
|
||||
Word("FILE=");
|
||||
return true;
|
||||
},
|
||||
[&](const ConnectSpec::CharExpr &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const MsgVariable &) {
|
||||
Word("IOMSG=");
|
||||
return true;
|
||||
},
|
||||
[&](const StatVariable &) {
|
||||
Word("IOSTAT=");
|
||||
return true;
|
||||
},
|
||||
[&](const ConnectSpec::Recl &) {
|
||||
Word("RECL=");
|
||||
return true;
|
||||
},
|
||||
[&](const ConnectSpec::Newunit &) {
|
||||
Word("NEWUNIT=");
|
||||
return true;
|
||||
},
|
||||
[&](const ErrLabel &) {
|
||||
Word("ERR=");
|
||||
return true;
|
||||
},
|
||||
[&](const StatusExpr &) {
|
||||
Word("STATUS=");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) {
|
||||
Word("UNIT=");
|
||||
return true;
|
||||
},
|
||||
[&](const FileNameExpr &) {
|
||||
Word("FILE=");
|
||||
return true;
|
||||
},
|
||||
[&](const ConnectSpec::CharExpr &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const MsgVariable &) {
|
||||
Word("IOMSG=");
|
||||
return true;
|
||||
},
|
||||
[&](const StatVariable &) {
|
||||
Word("IOSTAT=");
|
||||
return true;
|
||||
},
|
||||
[&](const ConnectSpec::Recl &) {
|
||||
Word("RECL=");
|
||||
return true;
|
||||
},
|
||||
[&](const ConnectSpec::Newunit &) {
|
||||
Word("NEWUNIT=");
|
||||
return true;
|
||||
},
|
||||
[&](const ErrLabel &) {
|
||||
Word("ERR=");
|
||||
return true;
|
||||
},
|
||||
[&](const StatusExpr &) {
|
||||
Word("STATUS=");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const CloseStmt &x) { // R1208
|
||||
Word("CLOSE ("), Walk(x.v, ", "), Put(')');
|
||||
}
|
||||
void Before(const CloseStmt::CloseSpec &x) { // R1209
|
||||
std::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) { Word("UNIT="); },
|
||||
[&](const StatVariable &) { Word("IOSTAT="); },
|
||||
[&](const MsgVariable &) { Word("IOMSG="); },
|
||||
[&](const ErrLabel &) { Word("ERR="); },
|
||||
[&](const StatusExpr &) { Word("STATUS="); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) { Word("UNIT="); },
|
||||
[&](const StatVariable &) { Word("IOSTAT="); },
|
||||
[&](const MsgVariable &) { Word("IOMSG="); },
|
||||
[&](const ErrLabel &) { Word("ERR="); },
|
||||
[&](const StatusExpr &) { Word("STATUS="); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const ReadStmt &x) { // R1210
|
||||
|
@ -1287,64 +1291,64 @@ public:
|
|||
Walk(", ", std::get<std::list<OutputItem>>(x.t), ", ");
|
||||
}
|
||||
bool Pre(const IoControlSpec &x) { // R1213
|
||||
return std::visit(common::visitors{
|
||||
[&](const IoUnit &) {
|
||||
Word("UNIT=");
|
||||
return true;
|
||||
},
|
||||
[&](const Format &) {
|
||||
Word("FMT=");
|
||||
return true;
|
||||
},
|
||||
[&](const Name &) {
|
||||
Word("NML=");
|
||||
return true;
|
||||
},
|
||||
[&](const IoControlSpec::CharExpr &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const IoControlSpec::Asynchronous &) {
|
||||
Word("ASYNCHRONOUS=");
|
||||
return true;
|
||||
},
|
||||
[&](const EndLabel &) {
|
||||
Word("END=");
|
||||
return true;
|
||||
},
|
||||
[&](const EorLabel &) {
|
||||
Word("EOR=");
|
||||
return true;
|
||||
},
|
||||
[&](const ErrLabel &) {
|
||||
Word("ERR=");
|
||||
return true;
|
||||
},
|
||||
[&](const IdVariable &) {
|
||||
Word("ID=");
|
||||
return true;
|
||||
},
|
||||
[&](const MsgVariable &) {
|
||||
Word("IOMSG=");
|
||||
return true;
|
||||
},
|
||||
[&](const StatVariable &) {
|
||||
Word("IOSTAT=");
|
||||
return true;
|
||||
},
|
||||
[&](const IoControlSpec::Pos &) {
|
||||
Word("POS=");
|
||||
return true;
|
||||
},
|
||||
[&](const IoControlSpec::Rec &) {
|
||||
Word("REC=");
|
||||
return true;
|
||||
},
|
||||
[&](const IoControlSpec::Size &) {
|
||||
Word("SIZE=");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[&](const IoUnit &) {
|
||||
Word("UNIT=");
|
||||
return true;
|
||||
},
|
||||
[&](const Format &) {
|
||||
Word("FMT=");
|
||||
return true;
|
||||
},
|
||||
[&](const Name &) {
|
||||
Word("NML=");
|
||||
return true;
|
||||
},
|
||||
[&](const IoControlSpec::CharExpr &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const IoControlSpec::Asynchronous &) {
|
||||
Word("ASYNCHRONOUS=");
|
||||
return true;
|
||||
},
|
||||
[&](const EndLabel &) {
|
||||
Word("END=");
|
||||
return true;
|
||||
},
|
||||
[&](const EorLabel &) {
|
||||
Word("EOR=");
|
||||
return true;
|
||||
},
|
||||
[&](const ErrLabel &) {
|
||||
Word("ERR=");
|
||||
return true;
|
||||
},
|
||||
[&](const IdVariable &) {
|
||||
Word("ID=");
|
||||
return true;
|
||||
},
|
||||
[&](const MsgVariable &) {
|
||||
Word("IOMSG=");
|
||||
return true;
|
||||
},
|
||||
[&](const StatVariable &) {
|
||||
Word("IOSTAT=");
|
||||
return true;
|
||||
},
|
||||
[&](const IoControlSpec::Pos &) {
|
||||
Word("POS=");
|
||||
return true;
|
||||
},
|
||||
[&](const IoControlSpec::Rec &) {
|
||||
Word("REC=");
|
||||
return true;
|
||||
},
|
||||
[&](const IoControlSpec::Size &) {
|
||||
Word("SIZE=");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const InputImpliedDo &x) { // R1218
|
||||
|
@ -1359,15 +1363,15 @@ public:
|
|||
Word("WAIT ("), Walk(x.v, ", "), Put(')');
|
||||
}
|
||||
void Before(const WaitSpec &x) { // R1223
|
||||
std::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) { Word("UNIT="); },
|
||||
[&](const EndLabel &) { Word("END="); },
|
||||
[&](const EorLabel &) { Word("EOR="); },
|
||||
[&](const ErrLabel &) { Word("ERR="); },
|
||||
[&](const IdExpr &) { Word("ID="); },
|
||||
[&](const MsgVariable &) { Word("IOMSG="); },
|
||||
[&](const StatVariable &) { Word("IOSTAT="); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) { Word("UNIT="); },
|
||||
[&](const EndLabel &) { Word("END="); },
|
||||
[&](const EorLabel &) { Word("EOR="); },
|
||||
[&](const ErrLabel &) { Word("ERR="); },
|
||||
[&](const IdExpr &) { Word("ID="); },
|
||||
[&](const MsgVariable &) { Word("IOMSG="); },
|
||||
[&](const StatVariable &) { Word("IOSTAT="); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const BackspaceStmt &x) { // R1224
|
||||
|
@ -1380,12 +1384,12 @@ public:
|
|||
Word("REWIND ("), Walk(x.v, ", "), Put(')');
|
||||
}
|
||||
void Before(const PositionOrFlushSpec &x) { // R1227 & R1229
|
||||
std::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) { Word("UNIT="); },
|
||||
[&](const MsgVariable &) { Word("IOMSG="); },
|
||||
[&](const StatVariable &) { Word("IOSTAT="); },
|
||||
[&](const ErrLabel &) { Word("ERR="); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) { Word("UNIT="); },
|
||||
[&](const MsgVariable &) { Word("IOMSG="); },
|
||||
[&](const StatVariable &) { Word("IOSTAT="); },
|
||||
[&](const ErrLabel &) { Word("ERR="); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const FlushStmt &x) { // R1228
|
||||
|
@ -1393,7 +1397,7 @@ public:
|
|||
}
|
||||
void Unparse(const InquireStmt &x) { // R1230
|
||||
Word("INQUIRE (");
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const InquireStmt::Iolength &y) {
|
||||
Word("IOLENGTH="), Walk(y.t, ") ");
|
||||
|
@ -1403,36 +1407,36 @@ public:
|
|||
x.u);
|
||||
}
|
||||
bool Pre(const InquireSpec &x) { // R1231
|
||||
return std::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) {
|
||||
Word("UNIT=");
|
||||
return true;
|
||||
},
|
||||
[&](const FileNameExpr &) {
|
||||
Word("FILE=");
|
||||
return true;
|
||||
},
|
||||
[&](const InquireSpec::CharVar &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const InquireSpec::IntVar &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const InquireSpec::LogVar &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const IdExpr &) {
|
||||
Word("ID=");
|
||||
return true;
|
||||
},
|
||||
[&](const ErrLabel &) {
|
||||
Word("ERR=");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[&](const FileUnitNumber &) {
|
||||
Word("UNIT=");
|
||||
return true;
|
||||
},
|
||||
[&](const FileNameExpr &) {
|
||||
Word("FILE=");
|
||||
return true;
|
||||
},
|
||||
[&](const InquireSpec::CharVar &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const InquireSpec::IntVar &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const InquireSpec::LogVar &y) {
|
||||
Walk(y.t, "=");
|
||||
return false;
|
||||
},
|
||||
[&](const IdExpr &) {
|
||||
Word("ID=");
|
||||
return true;
|
||||
},
|
||||
[&](const ErrLabel &) {
|
||||
Word("ERR=");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
|
||||
|
@ -1447,13 +1451,13 @@ public:
|
|||
if (x.repeatCount) {
|
||||
Walk(*x.repeatCount);
|
||||
}
|
||||
std::visit(common::visitors{
|
||||
[&](const std::string &y) { PutNormalized(y); },
|
||||
[&](const std::list<format::FormatItem> &y) {
|
||||
Walk("(", y, ",", ")");
|
||||
},
|
||||
[&](const auto &y) { Walk(y); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const std::string &y) { PutNormalized(y); },
|
||||
[&](const std::list<format::FormatItem> &y) {
|
||||
Walk("(", y, ",", ")");
|
||||
},
|
||||
[&](const auto &y) { Walk(y); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(
|
||||
|
@ -1566,19 +1570,21 @@ public:
|
|||
}
|
||||
void Unparse(const UseStmt &x) { // R1409
|
||||
Word("USE"), Walk(", ", x.nature), Put(" :: "), Walk(x.moduleName);
|
||||
std::visit(common::visitors{
|
||||
[&](const std::list<Rename> &y) { Walk(", ", y, ", "); },
|
||||
[&](const std::list<Only> &y) { Walk(", ONLY: ", y, ", "); },
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const std::list<Rename> &y) { Walk(", ", y, ", "); },
|
||||
[&](const std::list<Only> &y) { Walk(", ONLY: ", y, ", "); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const Rename &x) { // R1411
|
||||
std::visit(common::visitors{
|
||||
[&](const Rename::Names &y) { Walk(y.t, " => "); },
|
||||
[&](const Rename::Operators &y) {
|
||||
Word("OPERATOR("), Walk(y.t, ") => OPERATOR("), Put(")");
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const Rename::Names &y) { Walk(y.t, " => "); },
|
||||
[&](const Rename::Operators &y) {
|
||||
Word("OPERATOR("), Walk(y.t, ") => OPERATOR("),
|
||||
Put(")");
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const SubmoduleStmt &x) { // R1417
|
||||
|
@ -1598,12 +1604,12 @@ public:
|
|||
}
|
||||
|
||||
void Unparse(const InterfaceStmt &x) { // R1503
|
||||
std::visit(common::visitors{
|
||||
[&](const std::optional<GenericSpec> &y) {
|
||||
Word("INTERFACE"), Walk(" ", y);
|
||||
},
|
||||
[&](const Abstract &) { Word("ABSTRACT INTERFACE"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const std::optional<GenericSpec> &y) {
|
||||
Word("INTERFACE"), Walk(" ", y);
|
||||
},
|
||||
[&](const Abstract &) { Word("ABSTRACT INTERFACE"); },
|
||||
},
|
||||
x.u);
|
||||
Indent();
|
||||
}
|
||||
|
@ -1619,7 +1625,7 @@ public:
|
|||
Walk(std::get<std::list<Name>>(x.t), ", ");
|
||||
}
|
||||
void Before(const GenericSpec &x) { // R1508, R1509
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const DefinedOperator &) { Word("OPERATOR("); },
|
||||
[&](const GenericSpec::Assignment &) { Word("ASSIGNMENT(=)"); },
|
||||
|
@ -1640,10 +1646,10 @@ public:
|
|||
x.u);
|
||||
}
|
||||
void Post(const GenericSpec &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const DefinedOperator &) { Put(')'); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const DefinedOperator &) { Put(')'); },
|
||||
[](const auto &) {},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const GenericStmt &x) { // R1510
|
||||
|
@ -1767,7 +1773,7 @@ public:
|
|||
|
||||
// Directives, extensions, and deprecated constructs
|
||||
void Unparse(const CompilerDirective &x) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const std::list<CompilerDirective::IgnoreTKR> &tkr) {
|
||||
Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty
|
||||
|
@ -1852,12 +1858,12 @@ public:
|
|||
Word(AccDataModifier::EnumToString(x));
|
||||
}
|
||||
void Unparse(const AccBindClause &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const Name &y) { Put('('), Walk(y), Put(')'); },
|
||||
[&](const ScalarDefaultCharExpr &y) {
|
||||
Put('('), Walk(y), Put(')');
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const Name &y) { Put('('), Walk(y), Put(')'); },
|
||||
[&](const ScalarDefaultCharExpr &y) {
|
||||
Put('('), Walk(y), Put(')');
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const AccDefaultClause &x) {
|
||||
|
@ -1937,10 +1943,10 @@ public:
|
|||
EndOpenACC();
|
||||
}
|
||||
void Unparse(const AccObject &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const Designator &y) { Walk(y); },
|
||||
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const Designator &y) { Walk(y); },
|
||||
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const AccObjectList &x) { Walk(x.v, ","); }
|
||||
|
@ -1978,10 +1984,10 @@ public:
|
|||
|
||||
// OpenMP Clauses & Directives
|
||||
void Unparse(const OmpObject &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const Designator &y) { Walk(y); },
|
||||
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const Designator &y) { Walk(y); },
|
||||
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const OmpMapType::Always &) { Word("ALWAYS,"); }
|
||||
|
@ -2040,19 +2046,20 @@ public:
|
|||
Put(")");
|
||||
}
|
||||
bool Pre(const OmpDependClause &x) {
|
||||
return std::visit(common::visitors{
|
||||
[&](const OmpDependClause::Source &) {
|
||||
Word("SOURCE");
|
||||
return false;
|
||||
},
|
||||
[&](const OmpDependClause::Sink &y) {
|
||||
Word("SINK:");
|
||||
Walk(y.v);
|
||||
Put(")");
|
||||
return false;
|
||||
},
|
||||
[&](const OmpDependClause::InOut &) { return true; },
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const OmpDependClause::Source &) {
|
||||
Word("SOURCE");
|
||||
return false;
|
||||
},
|
||||
[&](const OmpDependClause::Sink &y) {
|
||||
Word("SINK:");
|
||||
Walk(y.v);
|
||||
Put(")");
|
||||
return false;
|
||||
},
|
||||
[&](const OmpDependClause::InOut &) { return true; },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const OmpDefaultmapClause &x) {
|
||||
|
@ -2346,37 +2353,38 @@ public:
|
|||
bool Pre(const OpenMPDeclarativeConstruct &x) {
|
||||
BeginOpenMP();
|
||||
Word("!$OMP ");
|
||||
return std::visit(common::visitors{
|
||||
[&](const OpenMPDeclarativeAllocate &z) {
|
||||
Word("ALLOCATE (");
|
||||
Walk(std::get<OmpObjectList>(z.t));
|
||||
Put(")");
|
||||
Walk(std::get<OmpClauseList>(z.t));
|
||||
Put("\n");
|
||||
EndOpenMP();
|
||||
return false;
|
||||
},
|
||||
[&](const OpenMPDeclareReductionConstruct &) {
|
||||
Word("DECLARE REDUCTION ");
|
||||
return true;
|
||||
},
|
||||
[&](const OpenMPDeclareSimdConstruct &y) {
|
||||
Word("DECLARE SIMD ");
|
||||
Walk("(", std::get<std::optional<Name>>(y.t), ")");
|
||||
Walk(std::get<OmpClauseList>(y.t));
|
||||
Put("\n");
|
||||
EndOpenMP();
|
||||
return false;
|
||||
},
|
||||
[&](const OpenMPDeclareTargetConstruct &) {
|
||||
Word("DECLARE TARGET ");
|
||||
return true;
|
||||
},
|
||||
[&](const OpenMPThreadprivate &) {
|
||||
Word("THREADPRIVATE (");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const OpenMPDeclarativeAllocate &z) {
|
||||
Word("ALLOCATE (");
|
||||
Walk(std::get<OmpObjectList>(z.t));
|
||||
Put(")");
|
||||
Walk(std::get<OmpClauseList>(z.t));
|
||||
Put("\n");
|
||||
EndOpenMP();
|
||||
return false;
|
||||
},
|
||||
[&](const OpenMPDeclareReductionConstruct &) {
|
||||
Word("DECLARE REDUCTION ");
|
||||
return true;
|
||||
},
|
||||
[&](const OpenMPDeclareSimdConstruct &y) {
|
||||
Word("DECLARE SIMD ");
|
||||
Walk("(", std::get<std::optional<Name>>(y.t), ")");
|
||||
Walk(std::get<OmpClauseList>(y.t));
|
||||
Put("\n");
|
||||
EndOpenMP();
|
||||
return false;
|
||||
},
|
||||
[&](const OpenMPDeclareTargetConstruct &) {
|
||||
Word("DECLARE TARGET ");
|
||||
return true;
|
||||
},
|
||||
[&](const OpenMPThreadprivate &) {
|
||||
Word("THREADPRIVATE (");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Post(const OpenMPDeclarativeConstruct &) {
|
||||
|
@ -2440,10 +2448,10 @@ public:
|
|||
}
|
||||
void Unparse(const OmpMemoryOrderClause &x) { Walk(x.v); }
|
||||
void Unparse(const OmpAtomicClause &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const OmpMemoryOrderClause &y) { Walk(y); },
|
||||
[&](const OmpClause &z) { Walk(z); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const OmpMemoryOrderClause &y) { Walk(y); },
|
||||
[&](const OmpClause &z) { Walk(z); },
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const OpenMPFlushConstruct &x) {
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
std::vector<LabelInfo> stack;
|
||||
for (auto i{block.begin()}, end{block.end()}; i != end; ++i) {
|
||||
if (auto *executableConstruct{std::get_if<ExecutableConstruct>(&i->u)}) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[](auto &) {},
|
||||
// Labels on end-stmt of constructs are accepted by f18 as an
|
||||
|
|
|
@ -128,10 +128,10 @@ static std::optional<AllocateCheckerInfo> CheckAllocateOptions(
|
|||
const parser::Expr *parserSourceExpr{nullptr};
|
||||
for (const parser::AllocOpt &allocOpt :
|
||||
std::get<std::list<parser::AllocOpt>>(allocateStmt.t)) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::StatOrErrmsg &statOrErr) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::StatVariable &) {
|
||||
if (info.gotStat) { // C943
|
||||
|
|
|
@ -666,7 +666,7 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
|
|||
}
|
||||
auto restorer{
|
||||
messages.SetLocation(arg.sourceLocation().value_or(messages.at()))};
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const characteristics::DummyDataObject &object) {
|
||||
ConvertBOZLiteralArg(arg, object.type.type());
|
||||
|
|
|
@ -43,7 +43,7 @@ private:
|
|||
const auto &stmt{std::get<parser::Statement<parser::CaseStmt>>(c.t)};
|
||||
const parser::CaseStmt &caseStmt{stmt.statement};
|
||||
const auto &selector{std::get<parser::CaseSelector>(caseStmt.t)};
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const std::list<parser::CaseValueRange> &ranges) {
|
||||
for (const auto &range : ranges) {
|
||||
|
@ -101,25 +101,26 @@ private:
|
|||
|
||||
using PairOfValues = std::pair<std::optional<Value>, std::optional<Value>>;
|
||||
PairOfValues ComputeBounds(const parser::CaseValueRange &range) {
|
||||
return std::visit(common::visitors{
|
||||
[&](const parser::CaseValue &x) {
|
||||
auto value{GetValue(x)};
|
||||
return PairOfValues{value, value};
|
||||
},
|
||||
[&](const parser::CaseValueRange::Range &x) {
|
||||
std::optional<Value> lo, hi;
|
||||
if (x.lower) {
|
||||
lo = GetValue(*x.lower);
|
||||
}
|
||||
if (x.upper) {
|
||||
hi = GetValue(*x.upper);
|
||||
}
|
||||
if ((x.lower && !lo) || (x.upper && !hi)) {
|
||||
return PairOfValues{}; // error case
|
||||
}
|
||||
return PairOfValues{std::move(lo), std::move(hi)};
|
||||
},
|
||||
},
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::CaseValue &x) {
|
||||
auto value{GetValue(x)};
|
||||
return PairOfValues{value, value};
|
||||
},
|
||||
[&](const parser::CaseValueRange::Range &x) {
|
||||
std::optional<Value> lo, hi;
|
||||
if (x.lower) {
|
||||
lo = GetValue(*x.lower);
|
||||
}
|
||||
if (x.upper) {
|
||||
hi = GetValue(*x.upper);
|
||||
}
|
||||
if ((x.lower && !lo) || (x.upper && !hi)) {
|
||||
return PairOfValues{}; // error case
|
||||
}
|
||||
return PairOfValues{std::move(lo), std::move(hi)};
|
||||
},
|
||||
},
|
||||
range.u);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ public:
|
|||
bool operator()(const evaluate::Subscript &subs) {
|
||||
DataVarChecker subscriptChecker{context_, source_};
|
||||
subscriptChecker.RestrictPointer();
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const evaluate::IndirectSubscriptIntegerExpr &expr) {
|
||||
return CheckSubscriptExpr(expr);
|
||||
|
@ -205,18 +205,19 @@ void DataChecker::Leave(const parser::DataIDoObject &object) {
|
|||
}
|
||||
|
||||
void DataChecker::Leave(const parser::DataStmtObject &dataObject) {
|
||||
std::visit(common::visitors{
|
||||
[](const parser::DataImpliedDo &) { // has own Enter()/Leave()
|
||||
},
|
||||
[&](const auto &var) {
|
||||
auto expr{exprAnalyzer_.Analyze(var)};
|
||||
if (!expr ||
|
||||
!DataVarChecker{exprAnalyzer_.context(),
|
||||
parser::FindSourceLocation(dataObject)}(*expr)) {
|
||||
currentSetHasFatalErrors_ = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[](const parser::DataImpliedDo &) { // has own Enter()/Leave()
|
||||
},
|
||||
[&](const auto &var) {
|
||||
auto expr{exprAnalyzer_.Analyze(var)};
|
||||
if (!expr ||
|
||||
!DataVarChecker{exprAnalyzer_.context(),
|
||||
parser::FindSourceLocation(dataObject)}(*expr)) {
|
||||
currentSetHasFatalErrors_ = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
dataObject.u);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Fortran::semantics {
|
|||
void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
|
||||
for (const parser::AllocateObject &allocateObject :
|
||||
std::get<std::list<parser::AllocateObject>>(deallocateStmt.t)) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Name &name) {
|
||||
auto const *symbol{name.symbol};
|
||||
|
@ -50,7 +50,7 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
|
|||
bool gotStat{false}, gotMsg{false};
|
||||
for (const parser::StatOrErrmsg &deallocOpt :
|
||||
std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t)) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::StatVariable &) {
|
||||
if (gotStat) {
|
||||
|
|
|
@ -205,7 +205,7 @@ void CheckHelper::Check(const Symbol &symbol) {
|
|||
const DeclTypeSpec *type{symbol.GetType()};
|
||||
const DerivedTypeSpec *derived{type ? type->AsDerived() : nullptr};
|
||||
bool isDone{false};
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const UseDetails &x) { isDone = true; },
|
||||
[&](const HostAssocDetails &x) {
|
||||
|
@ -1144,12 +1144,12 @@ void CheckHelper::CheckHostAssoc(
|
|||
void CheckHelper::CheckGeneric(
|
||||
const Symbol &symbol, const GenericDetails &details) {
|
||||
CheckSpecificsAreDistinguishable(symbol, details);
|
||||
std::visit(common::visitors{
|
||||
[&](const GenericKind::DefinedIo &io) {
|
||||
CheckDefinedIoProc(symbol, details, io);
|
||||
},
|
||||
[](const auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const GenericKind::DefinedIo &io) {
|
||||
CheckDefinedIoProc(symbol, details, io);
|
||||
},
|
||||
[](const auto &) {},
|
||||
},
|
||||
details.kind().u);
|
||||
}
|
||||
|
||||
|
@ -1186,7 +1186,7 @@ static bool ConflictsWithIntrinsicOperator(
|
|||
auto arg0{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
|
||||
auto type0{arg0.type()};
|
||||
if (proc.dummyArguments.size() == 1) { // unary
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](common::NumericOperator) { return IsIntrinsicNumeric(type0); },
|
||||
[&](common::LogicalOperator) { return IsIntrinsicLogical(type0); },
|
||||
|
@ -1198,7 +1198,7 @@ static bool ConflictsWithIntrinsicOperator(
|
|||
auto arg1{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
|
||||
auto type1{arg1.type()};
|
||||
int rank1{arg1.Rank()};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](common::NumericOperator) {
|
||||
return IsIntrinsicNumeric(type0, rank0, type1, rank1);
|
||||
|
@ -1262,27 +1262,27 @@ std::optional<parser::MessageFixedText> CheckHelper::CheckNumberOfArgs(
|
|||
return std::nullopt;
|
||||
}
|
||||
std::size_t min{2}, max{2}; // allowed number of args; default is binary
|
||||
std::visit(common::visitors{
|
||||
[&](const common::NumericOperator &x) {
|
||||
if (x == common::NumericOperator::Add ||
|
||||
x == common::NumericOperator::Subtract) {
|
||||
min = 1; // + and - are unary or binary
|
||||
}
|
||||
},
|
||||
[&](const common::LogicalOperator &x) {
|
||||
if (x == common::LogicalOperator::Not) {
|
||||
min = 1; // .NOT. is unary
|
||||
max = 1;
|
||||
}
|
||||
},
|
||||
[](const common::RelationalOperator &) {
|
||||
// all are binary
|
||||
},
|
||||
[](const GenericKind::OtherKind &x) {
|
||||
CHECK(x == GenericKind::OtherKind::Concat);
|
||||
},
|
||||
[](const auto &) { DIE("expected intrinsic operator"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const common::NumericOperator &x) {
|
||||
if (x == common::NumericOperator::Add ||
|
||||
x == common::NumericOperator::Subtract) {
|
||||
min = 1; // + and - are unary or binary
|
||||
}
|
||||
},
|
||||
[&](const common::LogicalOperator &x) {
|
||||
if (x == common::LogicalOperator::Not) {
|
||||
min = 1; // .NOT. is unary
|
||||
max = 1;
|
||||
}
|
||||
},
|
||||
[](const common::RelationalOperator &) {
|
||||
// all are binary
|
||||
},
|
||||
[](const GenericKind::OtherKind &x) {
|
||||
CHECK(x == GenericKind::OtherKind::Concat);
|
||||
},
|
||||
[](const auto &) { DIE("expected intrinsic operator"); },
|
||||
},
|
||||
kind.u);
|
||||
if (nargs >= min && nargs <= max) {
|
||||
return std::nullopt;
|
||||
|
@ -2189,7 +2189,7 @@ void SubprogramMatchHelper::Check(
|
|||
void SubprogramMatchHelper::CheckDummyArg(const Symbol &symbol1,
|
||||
const Symbol &symbol2, const DummyArgument &arg1,
|
||||
const DummyArgument &arg2) {
|
||||
std::visit(common::visitors{
|
||||
common::visit(common::visitors{
|
||||
[&](const DummyDataObject &obj1, const DummyDataObject &obj2) {
|
||||
CheckDummyDataObject(symbol1, symbol2, obj1, obj2);
|
||||
},
|
||||
|
|
|
@ -430,7 +430,7 @@ public:
|
|||
}
|
||||
|
||||
void Check(const parser::ForallAssignmentStmt &stmt) {
|
||||
const evaluate::Assignment *assignment{std::visit(
|
||||
const evaluate::Assignment *assignment{common::visit(
|
||||
common::visitors{[&](const auto &x) { return GetAssignment(x); }},
|
||||
stmt.u)};
|
||||
if (assignment) {
|
||||
|
@ -441,23 +441,24 @@ public:
|
|||
std::get_if<evaluate::ProcedureRef>(&assignment->u)}) {
|
||||
CheckForImpureCall(*proc);
|
||||
}
|
||||
std::visit(common::visitors{
|
||||
[](const evaluate::Assignment::Intrinsic &) {},
|
||||
[&](const evaluate::ProcedureRef &proc) {
|
||||
CheckForImpureCall(proc);
|
||||
},
|
||||
[&](const evaluate::Assignment::BoundsSpec &bounds) {
|
||||
for (const auto &bound : bounds) {
|
||||
CheckForImpureCall(SomeExpr{bound});
|
||||
}
|
||||
},
|
||||
[&](const evaluate::Assignment::BoundsRemapping &bounds) {
|
||||
for (const auto &bound : bounds) {
|
||||
CheckForImpureCall(SomeExpr{bound.first});
|
||||
CheckForImpureCall(SomeExpr{bound.second});
|
||||
}
|
||||
},
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[](const evaluate::Assignment::Intrinsic &) {},
|
||||
[&](const evaluate::ProcedureRef &proc) {
|
||||
CheckForImpureCall(proc);
|
||||
},
|
||||
[&](const evaluate::Assignment::BoundsSpec &bounds) {
|
||||
for (const auto &bound : bounds) {
|
||||
CheckForImpureCall(SomeExpr{bound});
|
||||
}
|
||||
},
|
||||
[&](const evaluate::Assignment::BoundsRemapping &bounds) {
|
||||
for (const auto &bound : bounds) {
|
||||
CheckForImpureCall(SomeExpr{bound.first});
|
||||
CheckForImpureCall(SomeExpr{bound.second});
|
||||
}
|
||||
},
|
||||
},
|
||||
assignment->u);
|
||||
}
|
||||
}
|
||||
|
@ -737,7 +738,7 @@ private:
|
|||
SymbolVector indexVars{context_.GetIndexVars(IndexVarKind::FORALL)};
|
||||
if (!indexVars.empty()) {
|
||||
UnorderedSymbolSet symbols{evaluate::CollectSymbols(assignment.lhs)};
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const evaluate::Assignment::BoundsSpec &spec) {
|
||||
for (const auto &bound : spec) {
|
||||
|
@ -828,7 +829,7 @@ static parser::CharBlock GetConstructPosition(const A &a) {
|
|||
}
|
||||
|
||||
static parser::CharBlock GetNodePosition(const ConstructNode &construct) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](const auto &x) { return GetConstructPosition(*x); }, construct);
|
||||
}
|
||||
|
||||
|
@ -859,24 +860,24 @@ static bool ConstructIsDoConcurrent(const ConstructNode &construct) {
|
|||
// leave DO CONCURRENT, CRITICAL, or CHANGE TEAM constructs.
|
||||
void DoForallChecker::CheckForBadLeave(
|
||||
StmtType stmtType, const ConstructNode &construct) const {
|
||||
std::visit(common::visitors{
|
||||
[&](const parser::DoConstruct *doConstructPtr) {
|
||||
if (doConstructPtr->IsDoConcurrent()) {
|
||||
// C1135 and C1167 -- CYCLE and EXIT statements can't leave
|
||||
// a DO CONCURRENT
|
||||
SayBadLeave(stmtType, "DO CONCURRENT", construct);
|
||||
}
|
||||
},
|
||||
[&](const parser::CriticalConstruct *) {
|
||||
// C1135 and C1168 -- similarly, for CRITICAL
|
||||
SayBadLeave(stmtType, "CRITICAL", construct);
|
||||
},
|
||||
[&](const parser::ChangeTeamConstruct *) {
|
||||
// C1135 and C1168 -- similarly, for CHANGE TEAM
|
||||
SayBadLeave(stmtType, "CHANGE TEAM", construct);
|
||||
},
|
||||
[](const auto *) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const parser::DoConstruct *doConstructPtr) {
|
||||
if (doConstructPtr->IsDoConcurrent()) {
|
||||
// C1135 and C1167 -- CYCLE and EXIT statements can't
|
||||
// leave a DO CONCURRENT
|
||||
SayBadLeave(stmtType, "DO CONCURRENT", construct);
|
||||
}
|
||||
},
|
||||
[&](const parser::CriticalConstruct *) {
|
||||
// C1135 and C1168 -- similarly, for CRITICAL
|
||||
SayBadLeave(stmtType, "CRITICAL", construct);
|
||||
},
|
||||
[&](const parser::ChangeTeamConstruct *) {
|
||||
// C1135 and C1168 -- similarly, for CHANGE TEAM
|
||||
SayBadLeave(stmtType, "CHANGE TEAM", construct);
|
||||
},
|
||||
[](const auto *) {},
|
||||
},
|
||||
construct);
|
||||
}
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ void IoChecker::Enter(const parser::FileUnitNumber &) {
|
|||
void IoChecker::Enter(const parser::Format &spec) {
|
||||
SetSpecifier(IoSpecKind::Fmt);
|
||||
flags_.set(Flag::FmtOrNml);
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Label &) { flags_.set(Flag::LabelFmt); },
|
||||
[&](const parser::Star &) { flags_.set(Flag::StarFmt); },
|
||||
|
|
|
@ -23,7 +23,7 @@ void NullifyChecker::Leave(const parser::NullifyStmt &nullifyStmt) {
|
|||
parser::ContextualMessages messages{
|
||||
*context_.location(), &context_.messages()};
|
||||
for (const parser::PointerObject &pointerObject : nullifyStmt.v) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Name &name) {
|
||||
const Symbol *symbol{name.symbol};
|
||||
|
|
|
@ -262,7 +262,7 @@ void OmpStructureChecker::CheckPredefinedAllocatorRestriction(
|
|||
const parser::CharBlock &source,
|
||||
const parser::OmpObjectList &ompObjectList) {
|
||||
for (const auto &ompObject : ompObjectList.v) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &designator) {
|
||||
if (const auto *dataRef{
|
||||
|
@ -420,54 +420,55 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
|
|||
// current context yet.
|
||||
// TODO: Check for declare simd regions.
|
||||
bool eligibleSIMD{false};
|
||||
std::visit(Fortran::common::visitors{
|
||||
// Allow `!$OMP ORDERED SIMD`
|
||||
[&](const parser::OpenMPBlockConstruct &c) {
|
||||
const auto &beginBlockDir{
|
||||
std::get<parser::OmpBeginBlockDirective>(c.t)};
|
||||
const auto &beginDir{
|
||||
std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
|
||||
if (beginDir.v == llvm::omp::Directive::OMPD_ordered) {
|
||||
const auto &clauses{
|
||||
std::get<parser::OmpClauseList>(beginBlockDir.t)};
|
||||
for (const auto &clause : clauses.v) {
|
||||
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
|
||||
eligibleSIMD = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
|
||||
const auto &dir{
|
||||
std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
|
||||
if (dir.v == llvm::omp::Directive::OMPD_ordered) {
|
||||
const auto &clauses{std::get<parser::OmpClauseList>(c.t)};
|
||||
for (const auto &clause : clauses.v) {
|
||||
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
|
||||
eligibleSIMD = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Allowing SIMD construct
|
||||
[&](const parser::OpenMPLoopConstruct &c) {
|
||||
const auto &beginLoopDir{
|
||||
std::get<parser::OmpBeginLoopDirective>(c.t)};
|
||||
const auto &beginDir{
|
||||
std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
|
||||
if ((beginDir.v == llvm::omp::Directive::OMPD_simd) ||
|
||||
(beginDir.v == llvm::omp::Directive::OMPD_do_simd)) {
|
||||
eligibleSIMD = true;
|
||||
}
|
||||
},
|
||||
[&](const parser::OpenMPAtomicConstruct &c) {
|
||||
// Allow `!$OMP ATOMIC`
|
||||
eligibleSIMD = true;
|
||||
},
|
||||
[&](const auto &c) {},
|
||||
},
|
||||
common::visit(Fortran::common::visitors{
|
||||
// Allow `!$OMP ORDERED SIMD`
|
||||
[&](const parser::OpenMPBlockConstruct &c) {
|
||||
const auto &beginBlockDir{
|
||||
std::get<parser::OmpBeginBlockDirective>(c.t)};
|
||||
const auto &beginDir{
|
||||
std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
|
||||
if (beginDir.v == llvm::omp::Directive::OMPD_ordered) {
|
||||
const auto &clauses{
|
||||
std::get<parser::OmpClauseList>(beginBlockDir.t)};
|
||||
for (const auto &clause : clauses.v) {
|
||||
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
|
||||
eligibleSIMD = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
|
||||
const auto &dir{
|
||||
std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
|
||||
if (dir.v == llvm::omp::Directive::OMPD_ordered) {
|
||||
const auto &clauses{
|
||||
std::get<parser::OmpClauseList>(c.t)};
|
||||
for (const auto &clause : clauses.v) {
|
||||
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
|
||||
eligibleSIMD = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Allowing SIMD construct
|
||||
[&](const parser::OpenMPLoopConstruct &c) {
|
||||
const auto &beginLoopDir{
|
||||
std::get<parser::OmpBeginLoopDirective>(c.t)};
|
||||
const auto &beginDir{
|
||||
std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
|
||||
if ((beginDir.v == llvm::omp::Directive::OMPD_simd) ||
|
||||
(beginDir.v == llvm::omp::Directive::OMPD_do_simd)) {
|
||||
eligibleSIMD = true;
|
||||
}
|
||||
},
|
||||
[&](const parser::OpenMPAtomicConstruct &c) {
|
||||
// Allow `!$OMP ATOMIC`
|
||||
eligibleSIMD = true;
|
||||
},
|
||||
[&](const auto &c) {},
|
||||
},
|
||||
c.u);
|
||||
if (!eligibleSIMD) {
|
||||
context_.Say(parser::FindSourceLocation(c),
|
||||
|
@ -482,7 +483,7 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
|
|||
// 2.12.5 Target Construct Restriction
|
||||
bool eligibleTarget{true};
|
||||
llvm::omp::Directive ineligibleTargetDir;
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::OpenMPBlockConstruct &c) {
|
||||
const auto &beginBlockDir{
|
||||
|
@ -495,7 +496,7 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
|
|||
}
|
||||
},
|
||||
[&](const parser::OpenMPStandaloneConstruct &c) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
|
||||
const auto &dir{
|
||||
|
@ -841,7 +842,7 @@ void OmpStructureChecker::Leave(const parser::OmpEndSectionsDirective &x) {
|
|||
void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
|
||||
const parser::OmpObjectList &objList) {
|
||||
for (const auto &ompObject : objList.v) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &) {
|
||||
if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
|
||||
|
@ -1358,7 +1359,7 @@ void OmpStructureChecker::CheckAtomicUpdateAssignmentStmt(
|
|||
const parser::AssignmentStmt &assignment) {
|
||||
const auto &expr{std::get<parser::Expr>(assignment.t)};
|
||||
const auto &var{std::get<parser::Variable>(assignment.t)};
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const common::Indirection<parser::FunctionReference> &x) {
|
||||
const auto &procedureDesignator{
|
||||
|
@ -1458,7 +1459,7 @@ void OmpStructureChecker::CheckAtomicMemoryOrderClause(
|
|||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::OmpAtomic &atomicConstruct) {
|
||||
const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
|
||||
|
@ -1620,7 +1621,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
|
|||
if (!threadprivateAllowedSet.test(type)) {
|
||||
if (const auto *objList{GetOmpObjectList(*clause)}) {
|
||||
for (const auto &ompObject : objList->v) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &) {
|
||||
if (const auto *name{
|
||||
|
@ -1746,7 +1747,7 @@ bool OmpStructureChecker::CheckReductionOperators(
|
|||
|
||||
const auto &definedOp{std::get<0>(x.v.t)};
|
||||
bool ok = false;
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::DefinedOperator &dOpr) {
|
||||
const auto &intrinsicOp{
|
||||
|
@ -1936,7 +1937,7 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
|
|||
llvm::omp::Directive::OMPD_threadprivate,
|
||||
llvm::omp::Directive::OMPD_declare_target};
|
||||
for (const auto &ompObject : objList.v) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &designator) {
|
||||
if (const auto *dataRef{
|
||||
|
@ -2273,7 +2274,7 @@ llvm::StringRef OmpStructureChecker::getDirectiveName(
|
|||
}
|
||||
|
||||
void OmpStructureChecker::CheckDependList(const parser::DataRef &d) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const common::Indirection<parser::ArrayElement> &elem) {
|
||||
// Check if the base element is valid on Depend Clause
|
||||
|
@ -2544,7 +2545,7 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
|
|||
|
||||
// TODO:: Generate the tuples using TableGen.
|
||||
// Handle other constructs with OmpObjectList such as OpenMPThreadprivate.
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const auto &x) -> const parser::OmpObjectList * {
|
||||
using Ty = std::decay_t<decltype(x)>;
|
||||
|
|
|
@ -60,7 +60,7 @@ void SelectRankConstructChecker::Leave(
|
|||
std::get<parser::Statement<parser::SelectRankCaseStmt>>(rankCase.t)};
|
||||
const auto &rank{
|
||||
std::get<parser::SelectRankCaseStmt::Rank>(rankCaseStmt.statement.t)};
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Default &) { // C1153
|
||||
if (!defaultRankFound) {
|
||||
|
@ -123,7 +123,7 @@ void SelectRankConstructChecker::Leave(
|
|||
|
||||
const SomeExpr *SelectRankConstructChecker::GetExprFromSelector(
|
||||
const parser::Selector &selector) {
|
||||
return std::visit([](const auto &x) { return GetExpr(x); }, selector.u);
|
||||
return common::visit([](const auto &x) { return GetExpr(x); }, selector.u);
|
||||
}
|
||||
|
||||
} // namespace Fortran::semantics
|
||||
|
|
|
@ -51,7 +51,7 @@ private:
|
|||
|
||||
std::optional<evaluate::DynamicType> GetGuardType(
|
||||
const parser::TypeGuardStmt::Guard &guard) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const parser::Default &)
|
||||
-> std::optional<evaluate::DynamicType> {
|
||||
|
@ -75,7 +75,7 @@ private:
|
|||
const evaluate::DynamicType &guardDynamicType) {
|
||||
const parser::TypeGuardStmt &typeGuardStmt{stmt.statement};
|
||||
const auto &guard{std::get<parser::TypeGuardStmt::Guard>(typeGuardStmt.t)};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const parser::Default &) { return true; },
|
||||
[&](const parser::TypeSpec &typeSpec) {
|
||||
|
@ -159,10 +159,10 @@ private:
|
|||
|
||||
void SetGuardType(std::optional<evaluate::DynamicType> guardTypeDynamic) {
|
||||
const auto &guard{GetGuardFromStmt(stmt)};
|
||||
std::visit(common::visitors{
|
||||
[&](const parser::Default &) {},
|
||||
[&](const auto &) { guardType_ = *guardTypeDynamic; },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const parser::Default &) {},
|
||||
[&](const auto &) { guardType_ = *guardTypeDynamic; },
|
||||
},
|
||||
guard.u);
|
||||
}
|
||||
|
||||
|
@ -268,6 +268,6 @@ void SelectTypeChecker::Enter(const parser::SelectTypeConstruct &construct) {
|
|||
|
||||
const SomeExpr *SelectTypeChecker::GetExprFromSelector(
|
||||
const parser::Selector &selector) {
|
||||
return std::visit([](const auto &x) { return GetExpr(x); }, selector.u);
|
||||
return common::visit([](const auto &x) { return GetExpr(x); }, selector.u);
|
||||
}
|
||||
} // namespace Fortran::semantics
|
||||
|
|
|
@ -122,7 +122,7 @@ private:
|
|||
template <typename DSV>
|
||||
bool DataInitializationCompiler<DSV>::Scan(
|
||||
const parser::DataStmtObject &object) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const common::Indirection<parser::Variable> &var) {
|
||||
return Scan(var.value());
|
||||
|
@ -214,7 +214,7 @@ bool DataInitializationCompiler<DSV>::Scan(const parser::DataImpliedDo &ido) {
|
|||
template <typename DSV>
|
||||
bool DataInitializationCompiler<DSV>::Scan(
|
||||
const parser::DataIDoObject &object) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Scalar<common::Indirection<parser::Designator>>
|
||||
&var) { return Scan(var.thing.value()); },
|
||||
|
|
|
@ -288,7 +288,7 @@ MaybeExpr ExpressionAnalyzer::ApplySubscripts(
|
|||
if (subscripts.empty()) {
|
||||
return std::nullopt; // error recovery
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](SymbolRef &&symbol) {
|
||||
return CompleteSubscripts(ArrayRef{symbol, std::move(subscripts)});
|
||||
|
@ -337,7 +337,7 @@ static void FixMisparsedSubstring(const parser::Designator &d) {
|
|||
if (!std::get<2>(triplet->t) /* no stride */ &&
|
||||
++iter == arrElement.subscripts.end() /* one subscript */) {
|
||||
if (Symbol *
|
||||
symbol{std::visit(
|
||||
symbol{common::visit(
|
||||
common::visitors{
|
||||
[](parser::Name &n) { return n.symbol; },
|
||||
[](common::Indirection<parser::StructureComponent>
|
||||
|
@ -397,7 +397,7 @@ int ExpressionAnalyzer::AnalyzeKindParam(
|
|||
if (!kindParam) {
|
||||
return defaultKind;
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](std::uint64_t k) { return static_cast<int>(k); },
|
||||
[&](const parser::Scalar<
|
||||
|
@ -841,7 +841,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
if (MaybeExpr string{Analyze(std::get<parser::CharLiteralConstant>(x.t))}) {
|
||||
if (auto *charExpr{std::get_if<Expr<SomeCharacter>>(&string->u)}) {
|
||||
Expr<SubscriptInteger> length{
|
||||
std::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); },
|
||||
common::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); },
|
||||
charExpr->u)};
|
||||
if (!lower) {
|
||||
lower = Expr<SubscriptInteger>{1};
|
||||
|
@ -850,7 +850,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
upper = Expr<SubscriptInteger>{
|
||||
static_cast<std::int64_t>(ToInt64(length).value())};
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&ckExpr) -> MaybeExpr {
|
||||
using Result = ResultType<decltype(ckExpr)>;
|
||||
auto *cp{std::get_if<Constant<Result>>(&ckExpr.u)};
|
||||
|
@ -904,7 +904,7 @@ std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart(
|
|||
|
||||
std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
|
||||
const parser::SectionSubscript &ss) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::SubscriptTriplet &t) -> std::optional<Subscript> {
|
||||
const auto &lower{std::get<0>(t.t)};
|
||||
|
@ -983,7 +983,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) {
|
|||
// Type parameter inquiries apply to data references, but don't depend
|
||||
// on any trailing (co)subscripts.
|
||||
static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](SymbolRef &&symbol) { return NamedEntity{symbol}; },
|
||||
[](Component &&component) {
|
||||
|
@ -1075,7 +1075,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
|
|||
if (kind == MiscKind::ComplexPartRe || kind == MiscKind::ComplexPartIm) {
|
||||
if (auto *zExpr{std::get_if<Expr<SomeComplex>>(&base->u)}) {
|
||||
if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*zExpr))}) {
|
||||
Expr<SomeReal> realExpr{std::visit(
|
||||
Expr<SomeReal> realExpr{common::visit(
|
||||
[&](const auto &z) {
|
||||
using PartType = typename ResultType<decltype(z)>::Part;
|
||||
auto part{kind == MiscKind::ComplexPartRe
|
||||
|
@ -1150,7 +1150,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
|
|||
}
|
||||
for (const auto &imageSelSpec :
|
||||
std::get<std::list<parser::ImageSelectorSpec>>(x.imageSelector.t)) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const auto &x) { Analyze(x.v); },
|
||||
},
|
||||
|
@ -1187,7 +1187,7 @@ ArrayConstructorValues<T> MakeSpecific(
|
|||
ArrayConstructorValues<SomeType> &&from) {
|
||||
ArrayConstructorValues<T> to;
|
||||
for (ArrayConstructorValue<SomeType> &x : from) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](common::CopyableIndirection<Expr<SomeType>> &&expr) {
|
||||
auto *typed{UnwrapExpr<Expr<T>>(expr.value())};
|
||||
|
@ -1336,7 +1336,7 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) {
|
|||
if (Expr<SomeCharacter> * charExpr{UnwrapExpr<Expr<SomeCharacter>>(*x)}) {
|
||||
CHECK(xType.category() == TypeCategory::Character);
|
||||
xType.length =
|
||||
std::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
|
||||
common::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
|
||||
}
|
||||
if (!type_) {
|
||||
// If there is no explicit type-spec in an array constructor, the type
|
||||
|
@ -1397,7 +1397,7 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) {
|
|||
}
|
||||
|
||||
void ArrayConstructorContext::Add(const parser::AcValue &x) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::AcValue::Triplet &triplet) { Add(triplet); },
|
||||
[&](const common::Indirection<parser::Expr> &expr) {
|
||||
|
@ -1820,7 +1820,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
|
||||
static std::optional<parser::CharBlock> GetPassName(
|
||||
const semantics::Symbol &proc) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](const auto &details) {
|
||||
if constexpr (std::is_base_of_v<semantics::WithPassArg,
|
||||
std::decay_t<decltype(details)>>) {
|
||||
|
@ -1959,7 +1959,7 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
|
|||
static bool CheckCompatibleArgument(bool isElemental,
|
||||
const ActualArgument &actual, const characteristics::DummyArgument &dummy) {
|
||||
const auto *expr{actual.UnwrapExpr()};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const characteristics::DummyDataObject &x) {
|
||||
if (x.attrs.test(characteristics::DummyDataObject::Attr::Pointer) &&
|
||||
|
@ -2154,7 +2154,7 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(
|
|||
const parser::ProcedureDesignator &pd, ActualArguments &&arguments,
|
||||
bool isSubroutine, bool mightBeStructureConstructor)
|
||||
-> std::optional<CalleeAndArguments> {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Name &name) {
|
||||
return GetCalleeAndArguments(name, std::move(arguments),
|
||||
|
@ -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
|
||||
// POINTER or ALLOCATABLE attribute, so do not assume nullptr can be directly
|
||||
// returned.
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::StructureComponent &x) {
|
||||
return AssumedTypeDummy(x.component);
|
||||
|
@ -2460,29 +2460,30 @@ const Assignment *ExpressionAnalyzer::Analyze(
|
|||
new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter);
|
||||
} else {
|
||||
Assignment assignment{std::move(*lhs), std::move(*rhs)};
|
||||
std::visit(common::visitors{
|
||||
[&](const std::list<parser::BoundsRemapping> &list) {
|
||||
Assignment::BoundsRemapping bounds;
|
||||
for (const auto &elem : list) {
|
||||
auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
|
||||
auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
|
||||
if (lower && upper) {
|
||||
bounds.emplace_back(Fold(std::move(*lower)),
|
||||
Fold(std::move(*upper)));
|
||||
}
|
||||
}
|
||||
assignment.u = std::move(bounds);
|
||||
},
|
||||
[&](const std::list<parser::BoundsSpec> &list) {
|
||||
Assignment::BoundsSpec bounds;
|
||||
for (const auto &bound : list) {
|
||||
if (auto lower{AsSubscript(Analyze(bound.v))}) {
|
||||
bounds.emplace_back(Fold(std::move(*lower)));
|
||||
}
|
||||
}
|
||||
assignment.u = std::move(bounds);
|
||||
},
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const std::list<parser::BoundsRemapping> &list) {
|
||||
Assignment::BoundsRemapping bounds;
|
||||
for (const auto &elem : list) {
|
||||
auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
|
||||
auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
|
||||
if (lower && upper) {
|
||||
bounds.emplace_back(
|
||||
Fold(std::move(*lower)), Fold(std::move(*upper)));
|
||||
}
|
||||
}
|
||||
assignment.u = std::move(bounds);
|
||||
},
|
||||
[&](const std::list<parser::BoundsSpec> &list) {
|
||||
Assignment::BoundsSpec bounds;
|
||||
for (const auto &bound : list) {
|
||||
if (auto lower{AsSubscript(Analyze(bound.v))}) {
|
||||
bounds.emplace_back(Fold(std::move(*lower)));
|
||||
}
|
||||
}
|
||||
assignment.u = std::move(bounds);
|
||||
},
|
||||
},
|
||||
std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
|
||||
x.typedAssignment.Reset(
|
||||
new GenericAssignmentWrapper{std::move(assignment)},
|
||||
|
@ -2692,7 +2693,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
|
|||
if (!analyzer.fatalErrors()) {
|
||||
if (analyzer.IsIntrinsicConcat()) {
|
||||
analyzer.CheckForNullPointer();
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &&x, auto &&y) -> MaybeExpr {
|
||||
using T = ResultType<decltype(x)>;
|
||||
if constexpr (std::is_same_v<T, ResultType<decltype(y)>>) {
|
||||
|
@ -2876,12 +2877,12 @@ static void FixMisparsedFunctionReference(
|
|||
auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
|
||||
if (Symbol *
|
||||
origSymbol{
|
||||
std::visit(common::visitors{
|
||||
[&](parser::Name &name) { return name.symbol; },
|
||||
[&](parser::ProcComponentRef &pcr) {
|
||||
return pcr.v.thing.component.symbol;
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](parser::Name &name) { return name.symbol; },
|
||||
[&](parser::ProcComponentRef &pcr) {
|
||||
return pcr.v.thing.component.symbol;
|
||||
},
|
||||
},
|
||||
proc.u)}) {
|
||||
Symbol &symbol{origSymbol->GetUltimate()};
|
||||
if (symbol.has<semantics::ObjectEntityDetails>() ||
|
||||
|
@ -3025,7 +3026,7 @@ Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
|
|||
if (!selector) {
|
||||
return Expr<SubscriptInteger>{defaultKind};
|
||||
}
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::ScalarIntConstantExpr &x) {
|
||||
if (MaybeExpr kind{Analyze(x)}) {
|
||||
|
@ -3215,7 +3216,7 @@ void ArgumentAnalyzer::Analyze(
|
|||
// be detected and represented (they're not expressions).
|
||||
// TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
|
||||
std::optional<ActualArgument> actual;
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const common::Indirection<parser::Expr> &x) {
|
||||
actual = AnalyzeExpr(x.value());
|
||||
|
|
|
@ -257,73 +257,74 @@ static llvm::raw_ostream &PutGenericName(
|
|||
// procedures, type-bound generics, final procedures) which go to typeBindings.
|
||||
void ModFileWriter::PutSymbol(
|
||||
llvm::raw_ostream &typeBindings, const Symbol &symbol) {
|
||||
std::visit(common::visitors{
|
||||
[&](const ModuleDetails &) { /* should be current module */ },
|
||||
[&](const DerivedTypeDetails &) { PutDerivedType(symbol); },
|
||||
[&](const SubprogramDetails &) { PutSubprogram(symbol); },
|
||||
[&](const GenericDetails &x) {
|
||||
if (symbol.owner().IsDerivedType()) {
|
||||
// generic binding
|
||||
for (const Symbol &proc : x.specificProcs()) {
|
||||
PutGenericName(typeBindings << "generic::", symbol)
|
||||
<< "=>" << proc.name() << '\n';
|
||||
}
|
||||
} else {
|
||||
PutGeneric(symbol);
|
||||
if (x.specific()) {
|
||||
PutSymbol(typeBindings, *x.specific());
|
||||
}
|
||||
if (x.derivedType()) {
|
||||
PutSymbol(typeBindings, *x.derivedType());
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const UseDetails &) { PutUse(symbol); },
|
||||
[](const UseErrorDetails &) {},
|
||||
[&](const ProcBindingDetails &x) {
|
||||
bool deferred{symbol.attrs().test(Attr::DEFERRED)};
|
||||
typeBindings << "procedure";
|
||||
if (deferred) {
|
||||
typeBindings << '(' << x.symbol().name() << ')';
|
||||
}
|
||||
PutPassName(typeBindings, x.passName());
|
||||
auto attrs{symbol.attrs()};
|
||||
if (x.passName()) {
|
||||
attrs.reset(Attr::PASS);
|
||||
}
|
||||
PutAttrs(typeBindings, attrs);
|
||||
typeBindings << "::" << symbol.name();
|
||||
if (!deferred && x.symbol().name() != symbol.name()) {
|
||||
typeBindings << "=>" << x.symbol().name();
|
||||
}
|
||||
typeBindings << '\n';
|
||||
},
|
||||
[&](const NamelistDetails &x) {
|
||||
decls_ << "namelist/" << symbol.name();
|
||||
char sep{'/'};
|
||||
for (const Symbol &object : x.objects()) {
|
||||
decls_ << sep << object.name();
|
||||
sep = ',';
|
||||
}
|
||||
decls_ << '\n';
|
||||
},
|
||||
[&](const CommonBlockDetails &x) {
|
||||
decls_ << "common/" << symbol.name();
|
||||
char sep = '/';
|
||||
for (const auto &object : x.objects()) {
|
||||
decls_ << sep << object->name();
|
||||
sep = ',';
|
||||
}
|
||||
decls_ << '\n';
|
||||
if (symbol.attrs().test(Attr::BIND_C)) {
|
||||
PutAttrs(decls_, symbol.attrs(), x.bindName(), ""s);
|
||||
decls_ << "::/" << symbol.name() << "/\n";
|
||||
}
|
||||
},
|
||||
[](const HostAssocDetails &) {},
|
||||
[](const MiscDetails &) {},
|
||||
[&](const auto &) { PutEntity(decls_, symbol); },
|
||||
},
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const ModuleDetails &) { /* should be current module */ },
|
||||
[&](const DerivedTypeDetails &) { PutDerivedType(symbol); },
|
||||
[&](const SubprogramDetails &) { PutSubprogram(symbol); },
|
||||
[&](const GenericDetails &x) {
|
||||
if (symbol.owner().IsDerivedType()) {
|
||||
// generic binding
|
||||
for (const Symbol &proc : x.specificProcs()) {
|
||||
PutGenericName(typeBindings << "generic::", symbol)
|
||||
<< "=>" << proc.name() << '\n';
|
||||
}
|
||||
} else {
|
||||
PutGeneric(symbol);
|
||||
if (x.specific()) {
|
||||
PutSymbol(typeBindings, *x.specific());
|
||||
}
|
||||
if (x.derivedType()) {
|
||||
PutSymbol(typeBindings, *x.derivedType());
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const UseDetails &) { PutUse(symbol); },
|
||||
[](const UseErrorDetails &) {},
|
||||
[&](const ProcBindingDetails &x) {
|
||||
bool deferred{symbol.attrs().test(Attr::DEFERRED)};
|
||||
typeBindings << "procedure";
|
||||
if (deferred) {
|
||||
typeBindings << '(' << x.symbol().name() << ')';
|
||||
}
|
||||
PutPassName(typeBindings, x.passName());
|
||||
auto attrs{symbol.attrs()};
|
||||
if (x.passName()) {
|
||||
attrs.reset(Attr::PASS);
|
||||
}
|
||||
PutAttrs(typeBindings, attrs);
|
||||
typeBindings << "::" << symbol.name();
|
||||
if (!deferred && x.symbol().name() != symbol.name()) {
|
||||
typeBindings << "=>" << x.symbol().name();
|
||||
}
|
||||
typeBindings << '\n';
|
||||
},
|
||||
[&](const NamelistDetails &x) {
|
||||
decls_ << "namelist/" << symbol.name();
|
||||
char sep{'/'};
|
||||
for (const Symbol &object : x.objects()) {
|
||||
decls_ << sep << object.name();
|
||||
sep = ',';
|
||||
}
|
||||
decls_ << '\n';
|
||||
},
|
||||
[&](const CommonBlockDetails &x) {
|
||||
decls_ << "common/" << symbol.name();
|
||||
char sep = '/';
|
||||
for (const auto &object : x.objects()) {
|
||||
decls_ << sep << object->name();
|
||||
sep = ',';
|
||||
}
|
||||
decls_ << '\n';
|
||||
if (symbol.attrs().test(Attr::BIND_C)) {
|
||||
PutAttrs(decls_, symbol.attrs(), x.bindName(), ""s);
|
||||
decls_ << "::/" << symbol.name() << "/\n";
|
||||
}
|
||||
},
|
||||
[](const HostAssocDetails &) {},
|
||||
[](const MiscDetails &) {},
|
||||
[&](const auto &) { PutEntity(decls_, symbol); },
|
||||
},
|
||||
symbol.details());
|
||||
}
|
||||
|
||||
|
@ -594,7 +595,7 @@ void CollectSymbols(
|
|||
}
|
||||
|
||||
void ModFileWriter::PutEntity(llvm::raw_ostream &os, const Symbol &symbol) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const ObjectEntityDetails &) { PutObjectEntity(os, symbol); },
|
||||
[&](const ProcEntityDetails &) { PutProcEntity(os, symbol); },
|
||||
|
@ -1105,27 +1106,27 @@ void SubprogramSymbolCollector::DoSymbol(
|
|||
if (!needSet_.insert(symbol).second) {
|
||||
return; // already done
|
||||
}
|
||||
std::visit(common::visitors{
|
||||
[this](const ObjectEntityDetails &details) {
|
||||
for (const ShapeSpec &spec : details.shape()) {
|
||||
DoBound(spec.lbound());
|
||||
DoBound(spec.ubound());
|
||||
}
|
||||
for (const ShapeSpec &spec : details.coshape()) {
|
||||
DoBound(spec.lbound());
|
||||
DoBound(spec.ubound());
|
||||
}
|
||||
if (const Symbol * commonBlock{details.commonBlock()}) {
|
||||
DoSymbol(*commonBlock);
|
||||
}
|
||||
},
|
||||
[this](const CommonBlockDetails &details) {
|
||||
for (const auto &object : details.objects()) {
|
||||
DoSymbol(*object);
|
||||
}
|
||||
},
|
||||
[](const auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[this](const ObjectEntityDetails &details) {
|
||||
for (const ShapeSpec &spec : details.shape()) {
|
||||
DoBound(spec.lbound());
|
||||
DoBound(spec.ubound());
|
||||
}
|
||||
for (const ShapeSpec &spec : details.coshape()) {
|
||||
DoBound(spec.lbound());
|
||||
DoBound(spec.ubound());
|
||||
}
|
||||
if (const Symbol * commonBlock{details.commonBlock()}) {
|
||||
DoSymbol(*commonBlock);
|
||||
}
|
||||
},
|
||||
[this](const CommonBlockDetails &details) {
|
||||
for (const auto &object : details.objects()) {
|
||||
DoSymbol(*object);
|
||||
}
|
||||
},
|
||||
[](const auto &) {},
|
||||
},
|
||||
symbol.details());
|
||||
if (!symbol.has<UseDetails>()) {
|
||||
DoType(symbol.GetType());
|
||||
|
|
|
@ -117,7 +117,7 @@ template <typename T> bool PointerAssignmentChecker::Check(const T &) {
|
|||
|
||||
template <typename T>
|
||||
bool PointerAssignmentChecker::Check(const evaluate::Expr<T> &x) {
|
||||
return std::visit([&](const auto &x) { return Check(x); }, x.u);
|
||||
return common::visit([&](const auto &x) { return Check(x); }, x.u);
|
||||
}
|
||||
|
||||
bool PointerAssignmentChecker::Check(const SomeExpr &rhs) {
|
||||
|
@ -128,7 +128,7 @@ bool PointerAssignmentChecker::Check(const SomeExpr &rhs) {
|
|||
Say("A coindexed object may not be a pointer target"_err_en_US);
|
||||
return false;
|
||||
} else {
|
||||
return std::visit([&](const auto &x) { return Check(x); }, rhs.u);
|
||||
return common::visit([&](const auto &x) { return Check(x); }, rhs.u);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,7 @@ static bool CheckPointerBounds(
|
|||
const SomeExpr &lhs{assignment.lhs};
|
||||
const SomeExpr &rhs{assignment.rhs};
|
||||
bool isBoundsRemapping{false};
|
||||
std::size_t numBounds{std::visit(
|
||||
std::size_t numBounds{common::visit(
|
||||
common::visitors{
|
||||
[&](const evaluate::Assignment::BoundsSpec &bounds) {
|
||||
return bounds.size();
|
||||
|
|
|
@ -88,7 +88,7 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
|
|||
if (subps) {
|
||||
for (const auto &subp :
|
||||
std::get<std::list<parser::InternalSubprogram>>(subps->t)) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
[&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); },
|
||||
subp.u);
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) {
|
|||
if (subps) {
|
||||
for (const auto &subp :
|
||||
std::get<std::list<parser::ModuleSubprogram>>(subps->t)) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
[&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); },
|
||||
subp.u);
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) {
|
|||
}
|
||||
|
||||
ProgramTree ProgramTree::Build(const parser::ProgramUnit &x) {
|
||||
return std::visit([](const auto &y) { return Build(y.value()); }, x.u);
|
||||
return common::visit([](const auto &y) { return Build(y.value()); }, x.u);
|
||||
}
|
||||
|
||||
ProgramTree ProgramTree::Build(const parser::MainProgram &x) {
|
||||
|
@ -200,17 +200,17 @@ Symbol::Flag ProgramTree::GetSubpFlag() const {
|
|||
|
||||
bool ProgramTree::HasModulePrefix() const {
|
||||
using ListType = std::list<parser::PrefixSpec>;
|
||||
const auto *prefixes{
|
||||
std::visit(common::visitors{
|
||||
[](const parser::Statement<parser::FunctionStmt> *x) {
|
||||
return &std::get<ListType>(x->statement.t);
|
||||
},
|
||||
[](const parser::Statement<parser::SubroutineStmt> *x) {
|
||||
return &std::get<ListType>(x->statement.t);
|
||||
},
|
||||
[](const auto *) -> const ListType * { return nullptr; },
|
||||
},
|
||||
stmt_)};
|
||||
const auto *prefixes{common::visit(
|
||||
common::visitors{
|
||||
[](const parser::Statement<parser::FunctionStmt> *x) {
|
||||
return &std::get<ListType>(x->statement.t);
|
||||
},
|
||||
[](const parser::Statement<parser::SubroutineStmt> *x) {
|
||||
return &std::get<ListType>(x->statement.t);
|
||||
},
|
||||
[](const auto *) -> const ListType * { return nullptr; },
|
||||
},
|
||||
stmt_)};
|
||||
if (prefixes) {
|
||||
for (const auto &prefix : *prefixes) {
|
||||
if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) {
|
||||
|
@ -222,7 +222,7 @@ bool ProgramTree::HasModulePrefix() const {
|
|||
}
|
||||
|
||||
ProgramTree::Kind ProgramTree::GetKind() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const parser::Statement<parser::ProgramStmt> *) {
|
||||
return Kind::Program;
|
||||
|
|
|
@ -364,18 +364,18 @@ public:
|
|||
return false;
|
||||
}
|
||||
bool Pre(const parser::OmpLinearClause &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const parser::OmpLinearClause::WithoutModifier
|
||||
&linearWithoutModifier) {
|
||||
ResolveOmpNameList(
|
||||
linearWithoutModifier.names, Symbol::Flag::OmpLinear);
|
||||
},
|
||||
[&](const parser::OmpLinearClause::WithModifier
|
||||
&linearWithModifier) {
|
||||
ResolveOmpNameList(
|
||||
linearWithModifier.names, Symbol::Flag::OmpLinear);
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const parser::OmpLinearClause::WithoutModifier
|
||||
&linearWithoutModifier) {
|
||||
ResolveOmpNameList(linearWithoutModifier.names,
|
||||
Symbol::Flag::OmpLinear);
|
||||
},
|
||||
[&](const parser::OmpLinearClause::WithModifier
|
||||
&linearWithModifier) {
|
||||
ResolveOmpNameList(
|
||||
linearWithModifier.names, Symbol::Flag::OmpLinear);
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
return false;
|
||||
}
|
||||
|
@ -756,7 +756,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
|
|||
static bool IsLastNameArray(const parser::Designator &designator) {
|
||||
const auto &name{GetLastName(designator)};
|
||||
const evaluate::DataRef dataRef{*(name.symbol)};
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const evaluate::SymbolRef &ref) { return ref->Rank() > 0; },
|
||||
[](const evaluate::ArrayRef &aref) {
|
||||
|
@ -771,7 +771,7 @@ static bool IsLastNameArray(const parser::Designator &designator) {
|
|||
void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
|
||||
const parser::AccObjectList &objectList) {
|
||||
for (const auto &accObject : objectList.v) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &designator) {
|
||||
if (!IsLastNameArray(designator)) {
|
||||
|
@ -798,7 +798,7 @@ void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
|
|||
void AccAttributeVisitor::DoNotAllowAssumedSizedArray(
|
||||
const parser::AccObjectList &objectList) {
|
||||
for (const auto &accObject : objectList.v) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &designator) {
|
||||
const auto &name{GetLastName(designator)};
|
||||
|
@ -883,7 +883,7 @@ void AccAttributeVisitor::PrivatizeAssociatedLoopIndex(
|
|||
void AccAttributeVisitor::EnsureAllocatableOrPointer(
|
||||
const llvm::acc::Clause clause, const parser::AccObjectList &objectList) {
|
||||
for (const auto &accObject : objectList.v) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &designator) {
|
||||
const auto &lastName{GetLastName(designator)};
|
||||
|
@ -977,7 +977,7 @@ void AccAttributeVisitor::ResolveAccObjectList(
|
|||
|
||||
void AccAttributeVisitor::ResolveAccObject(
|
||||
const parser::AccObject &accObject, Symbol::Flag accFlag) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &designator) {
|
||||
if (const auto *name{GetDesignatorNameIfDataRef(designator)}) {
|
||||
|
@ -1572,7 +1572,7 @@ void OmpAttributeVisitor::ResolveOmpObjectList(
|
|||
|
||||
void OmpAttributeVisitor::ResolveOmpObject(
|
||||
const parser::OmpObject &ompObject, Symbol::Flag ompFlag) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Designator &designator) {
|
||||
if (const auto *name{GetDesignatorNameIfDataRef(designator)}) {
|
||||
|
|
|
@ -126,7 +126,7 @@ void GenericSpecInfo::Analyze(const parser::DefinedOpName &name) {
|
|||
|
||||
void GenericSpecInfo::Analyze(const parser::GenericSpec &x) {
|
||||
symbolName_ = x.source;
|
||||
kind_ = std::visit(
|
||||
kind_ = common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Name &y) -> GenericKind {
|
||||
parseName_ = &y;
|
||||
|
@ -134,7 +134,7 @@ void GenericSpecInfo::Analyze(const parser::GenericSpec &x) {
|
|||
return GenericKind::OtherKind::Name;
|
||||
},
|
||||
[&](const parser::DefinedOperator &y) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::DefinedOpName &z) -> GenericKind {
|
||||
Analyze(z);
|
||||
|
@ -265,19 +265,20 @@ ArraySpec AnalyzeCoarraySpec(
|
|||
}
|
||||
|
||||
ArraySpec ArraySpecAnalyzer::Analyze(const parser::ComponentArraySpec &x) {
|
||||
std::visit([this](const auto &y) { Analyze(y); }, x.u);
|
||||
common::visit([this](const auto &y) { Analyze(y); }, x.u);
|
||||
CHECK(!arraySpec_.empty());
|
||||
return arraySpec_;
|
||||
}
|
||||
ArraySpec ArraySpecAnalyzer::Analyze(const parser::ArraySpec &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const parser::AssumedSizeSpec &y) {
|
||||
Analyze(std::get<std::list<parser::ExplicitShapeSpec>>(y.t));
|
||||
Analyze(std::get<parser::AssumedImpliedSpec>(y.t));
|
||||
},
|
||||
[&](const parser::ImpliedShapeSpec &y) { Analyze(y.v); },
|
||||
[&](const auto &y) { Analyze(y); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const parser::AssumedSizeSpec &y) {
|
||||
Analyze(
|
||||
std::get<std::list<parser::ExplicitShapeSpec>>(y.t));
|
||||
Analyze(std::get<parser::AssumedImpliedSpec>(y.t));
|
||||
},
|
||||
[&](const parser::ImpliedShapeSpec &y) { Analyze(y.v); },
|
||||
[&](const auto &y) { Analyze(y); },
|
||||
},
|
||||
x.u);
|
||||
CHECK(!arraySpec_.empty());
|
||||
return arraySpec_;
|
||||
|
@ -289,7 +290,7 @@ ArraySpec ArraySpecAnalyzer::AnalyzeDeferredShapeSpecList(
|
|||
return arraySpec_;
|
||||
}
|
||||
ArraySpec ArraySpecAnalyzer::Analyze(const parser::CoarraySpec &x) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::DeferredCoshapeSpecList &y) { MakeDeferred(y.v); },
|
||||
[&](const parser::ExplicitCoshapeSpec &y) {
|
||||
|
@ -495,7 +496,7 @@ const EquivalenceObject *EquivalenceSets::Find(
|
|||
}
|
||||
|
||||
bool EquivalenceSets::CheckDesignator(const parser::Designator &designator) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::DataRef &x) {
|
||||
return CheckDataRef(designator.source, x);
|
||||
|
@ -520,7 +521,7 @@ bool EquivalenceSets::CheckDesignator(const parser::Designator &designator) {
|
|||
|
||||
bool EquivalenceSets::CheckDataRef(
|
||||
const parser::CharBlock &source, const parser::DataRef &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Name &name) { return CheckObject(name); },
|
||||
[&](const common::Indirection<parser::StructureComponent> &) {
|
||||
|
@ -532,7 +533,7 @@ bool EquivalenceSets::CheckDataRef(
|
|||
[&](const common::Indirection<parser::ArrayElement> &elem) {
|
||||
bool ok{CheckDataRef(source, elem.value().base)};
|
||||
for (const auto &subscript : elem.value().subscripts) {
|
||||
ok &= std::visit(
|
||||
ok &= common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::SubscriptTriplet &) {
|
||||
context_.Say(source, // C924, R872
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "flang/Common/default-kinds.h"
|
||||
#include "flang/Common/indirection.h"
|
||||
#include "flang/Common/restorer.h"
|
||||
#include "flang/Common/visit.h"
|
||||
#include "flang/Evaluate/characteristics.h"
|
||||
#include "flang/Evaluate/check-expression.h"
|
||||
#include "flang/Evaluate/common.h"
|
||||
|
@ -1588,11 +1589,11 @@ bool AttrsVisitor::SetPassNameOn(Symbol &symbol) {
|
|||
if (!passName_) {
|
||||
return false;
|
||||
}
|
||||
std::visit(common::visitors{
|
||||
[&](ProcEntityDetails &x) { x.set_passName(*passName_); },
|
||||
[&](ProcBindingDetails &x) { x.set_passName(*passName_); },
|
||||
[](auto &) { common::die("unexpected pass name"); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](ProcEntityDetails &x) { x.set_passName(*passName_); },
|
||||
[&](ProcBindingDetails &x) { x.set_passName(*passName_); },
|
||||
[](auto &) { common::die("unexpected pass name"); },
|
||||
},
|
||||
symbol.details());
|
||||
return true;
|
||||
}
|
||||
|
@ -1796,20 +1797,20 @@ void ImplicitRulesVisitor::Post(const parser::ParameterStmt &) {
|
|||
|
||||
bool ImplicitRulesVisitor::Pre(const parser::ImplicitStmt &x) {
|
||||
bool result{
|
||||
std::visit(common::visitors{
|
||||
[&](const std::list<ImplicitNoneNameSpec> &y) {
|
||||
return HandleImplicitNone(y);
|
||||
},
|
||||
[&](const std::list<parser::ImplicitSpec> &) {
|
||||
if (prevImplicitNoneType_) {
|
||||
Say("IMPLICIT statement after IMPLICIT NONE or "
|
||||
"IMPLICIT NONE(TYPE) statement"_err_en_US);
|
||||
return false;
|
||||
}
|
||||
implicitRules_->set_isImplicitNoneType(false);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const std::list<ImplicitNoneNameSpec> &y) {
|
||||
return HandleImplicitNone(y);
|
||||
},
|
||||
[&](const std::list<parser::ImplicitSpec> &) {
|
||||
if (prevImplicitNoneType_) {
|
||||
Say("IMPLICIT statement after IMPLICIT NONE or "
|
||||
"IMPLICIT NONE(TYPE) statement"_err_en_US);
|
||||
return false;
|
||||
}
|
||||
implicitRules_->set_isImplicitNoneType(false);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
x.u)};
|
||||
prevImplicit_ = currStmtSource();
|
||||
return result;
|
||||
|
@ -2208,17 +2209,17 @@ void ScopeHandler::EraseSymbol(const parser::Name &name) {
|
|||
|
||||
static bool NeedsType(const Symbol &symbol) {
|
||||
return !symbol.GetType() &&
|
||||
std::visit(common::visitors{
|
||||
[](const EntityDetails &) { return true; },
|
||||
[](const ObjectEntityDetails &) { return true; },
|
||||
[](const AssocEntityDetails &) { return true; },
|
||||
[&](const ProcEntityDetails &p) {
|
||||
return symbol.test(Symbol::Flag::Function) &&
|
||||
!symbol.attrs().test(Attr::INTRINSIC) &&
|
||||
!p.interface().type() && !p.interface().symbol();
|
||||
},
|
||||
[](const auto &) { return false; },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[](const EntityDetails &) { return true; },
|
||||
[](const ObjectEntityDetails &) { return true; },
|
||||
[](const AssocEntityDetails &) { return true; },
|
||||
[&](const ProcEntityDetails &p) {
|
||||
return symbol.test(Symbol::Flag::Function) &&
|
||||
!symbol.attrs().test(Attr::INTRINSIC) &&
|
||||
!p.interface().type() && !p.interface().symbol();
|
||||
},
|
||||
[](const auto &) { return false; },
|
||||
},
|
||||
symbol.details());
|
||||
}
|
||||
|
||||
|
@ -2446,18 +2447,18 @@ void ScopeHandler::MakeExternal(Symbol &symbol) {
|
|||
// ModuleVisitor implementation
|
||||
|
||||
bool ModuleVisitor::Pre(const parser::Only &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const Indirection<parser::GenericSpec> &generic) {
|
||||
GenericSpecInfo genericSpecInfo{generic.value()};
|
||||
AddUseOnly(genericSpecInfo.symbolName());
|
||||
AddUse(genericSpecInfo);
|
||||
},
|
||||
[&](const parser::Name &name) {
|
||||
AddUseOnly(name.source);
|
||||
Resolve(name, AddUse(name.source, name.source).use);
|
||||
},
|
||||
[&](const parser::Rename &rename) { Walk(rename); },
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const Indirection<parser::GenericSpec> &generic) {
|
||||
GenericSpecInfo genericSpecInfo{generic.value()};
|
||||
AddUseOnly(genericSpecInfo.symbolName());
|
||||
AddUse(genericSpecInfo);
|
||||
},
|
||||
[&](const parser::Name &name) {
|
||||
AddUseOnly(name.source);
|
||||
Resolve(name, AddUse(name.source, name.source).use);
|
||||
},
|
||||
[&](const parser::Rename &rename) { Walk(rename); },
|
||||
},
|
||||
x.u);
|
||||
return false;
|
||||
}
|
||||
|
@ -2522,14 +2523,14 @@ void ModuleVisitor::Post(const parser::UseStmt &x) {
|
|||
// then add a use for each public name that was not renamed.
|
||||
std::set<SourceName> useNames;
|
||||
for (const auto &rename : *list) {
|
||||
std::visit(common::visitors{
|
||||
[&](const parser::Rename::Names &names) {
|
||||
useNames.insert(std::get<1>(names.t).source);
|
||||
},
|
||||
[&](const parser::Rename::Operators &ops) {
|
||||
useNames.insert(std::get<1>(ops.t).v.source);
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const parser::Rename::Names &names) {
|
||||
useNames.insert(std::get<1>(names.t).source);
|
||||
},
|
||||
[&](const parser::Rename::Operators &ops) {
|
||||
useNames.insert(std::get<1>(ops.t).v.source);
|
||||
},
|
||||
},
|
||||
rename.u);
|
||||
}
|
||||
for (const auto &[name, symbol] : *useModuleScope_) {
|
||||
|
@ -3224,7 +3225,7 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
|
|||
auto &effectiveResultName{*(resultName ? resultName : &name)};
|
||||
resultSymbol = FindInScope(currScope(), effectiveResultName);
|
||||
if (resultSymbol) { // C1574
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{[](EntityDetails &x) { x.set_funcResult(true); },
|
||||
[](ObjectEntityDetails &x) { x.set_funcResult(true); },
|
||||
[](ProcEntityDetails &x) { x.set_funcResult(true); },
|
||||
|
@ -3255,7 +3256,7 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
|
|||
if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
|
||||
Symbol *dummy{FindSymbol(*dummyName)};
|
||||
if (dummy) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{[](EntityDetails &x) { x.set_isDummy(); },
|
||||
[](ObjectEntityDetails &x) { x.set_isDummy(); },
|
||||
[](ProcEntityDetails &x) { x.set_isDummy(); },
|
||||
|
@ -5493,7 +5494,7 @@ bool DeclarationVisitor::OkToAddComponent(
|
|||
|
||||
ParamValue DeclarationVisitor::GetParamValue(
|
||||
const parser::TypeParamValue &x, common::TypeParamAttr attr) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[=](const parser::ScalarIntExpr &x) { // C704
|
||||
return ParamValue{EvaluateIntExpr(x), attr};
|
||||
|
@ -5652,7 +5653,7 @@ bool ConstructVisitor::Pre(const parser::DataImpliedDo &x) {
|
|||
// statement so that the predicate IsInitialized() will be true
|
||||
// during semantic analysis before the symbol's initializer is constructed.
|
||||
bool ConstructVisitor::Pre(const parser::DataIDoObject &x) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Scalar<Indirection<parser::Designator>> &y) {
|
||||
Walk(y.thing.value());
|
||||
|
@ -5668,20 +5669,21 @@ bool ConstructVisitor::Pre(const parser::DataIDoObject &x) {
|
|||
}
|
||||
|
||||
bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const Indirection<parser::Variable> &y) {
|
||||
Walk(y.value());
|
||||
const parser::Name &first{parser::GetFirstName(y.value())};
|
||||
if (first.symbol) {
|
||||
first.symbol->set(Symbol::Flag::InDataStmt);
|
||||
}
|
||||
},
|
||||
[&](const parser::DataImpliedDo &y) {
|
||||
PushScope(Scope::Kind::ImpliedDos, nullptr);
|
||||
Walk(y);
|
||||
PopScope();
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const Indirection<parser::Variable> &y) {
|
||||
Walk(y.value());
|
||||
const parser::Name &first{
|
||||
parser::GetFirstName(y.value())};
|
||||
if (first.symbol) {
|
||||
first.symbol->set(Symbol::Flag::InDataStmt);
|
||||
}
|
||||
},
|
||||
[&](const parser::DataImpliedDo &y) {
|
||||
PushScope(Scope::Kind::ImpliedDos, nullptr);
|
||||
Walk(y);
|
||||
PopScope();
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
return false;
|
||||
}
|
||||
|
@ -5961,9 +5963,9 @@ void ConstructVisitor::SetTypeFromAssociation(Symbol &symbol) {
|
|||
evaluate::UnwrapExpr<evaluate::Expr<evaluate::SomeCharacter>>(
|
||||
expr)}) {
|
||||
symbol.SetType(ToDeclTypeSpec(std::move(*type),
|
||||
FoldExpr(
|
||||
std::visit([](const auto &kindChar) { return kindChar.LEN(); },
|
||||
charExpr->u))));
|
||||
FoldExpr(common::visit(
|
||||
[](const auto &kindChar) { return kindChar.LEN(); },
|
||||
charExpr->u))));
|
||||
} else {
|
||||
symbol.SetType(ToDeclTypeSpec(std::move(*type)));
|
||||
}
|
||||
|
@ -5986,14 +5988,14 @@ void ConstructVisitor::SetAttrsFromAssociation(Symbol &symbol) {
|
|||
|
||||
ConstructVisitor::Selector ConstructVisitor::ResolveSelector(
|
||||
const parser::Selector &x) {
|
||||
return std::visit(common::visitors{
|
||||
[&](const parser::Expr &expr) {
|
||||
return Selector{expr.source, EvaluateExpr(x)};
|
||||
},
|
||||
[&](const parser::Variable &var) {
|
||||
return Selector{var.GetSource(), EvaluateExpr(x)};
|
||||
},
|
||||
},
|
||||
return common::visit(common::visitors{
|
||||
[&](const parser::Expr &expr) {
|
||||
return Selector{expr.source, EvaluateExpr(x)};
|
||||
},
|
||||
[&](const parser::Variable &var) {
|
||||
return Selector{var.GetSource(), EvaluateExpr(x)};
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
|
||||
|
@ -6123,7 +6125,7 @@ const parser::Name *DeclarationVisitor::ResolveStructureComponent(
|
|||
|
||||
const parser::Name *DeclarationVisitor::ResolveDesignator(
|
||||
const parser::Designator &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::DataRef &x) { return ResolveDataRef(x); },
|
||||
[&](const parser::Substring &x) {
|
||||
|
@ -6135,7 +6137,7 @@ const parser::Name *DeclarationVisitor::ResolveDesignator(
|
|||
|
||||
const parser::Name *DeclarationVisitor::ResolveDataRef(
|
||||
const parser::DataRef &x) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[=](const parser::Name &y) { return ResolveName(y); },
|
||||
[=](const Indirection<parser::StructureComponent> &y) {
|
||||
|
@ -6343,7 +6345,7 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
|
|||
if (auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) {
|
||||
// TODO: check C762 - all bounds and type parameters of component
|
||||
// are colons or constant expressions if component is initialized
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::ConstantExpr &expr) {
|
||||
NonPointerInitialization(name, expr);
|
||||
|
@ -6454,7 +6456,7 @@ void DeclarationVisitor::NonPointerInitialization(
|
|||
|
||||
void ResolveNamesVisitor::HandleCall(
|
||||
Symbol::Flag procFlag, const parser::Call &call) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Name &x) { HandleProcedureName(procFlag, x); },
|
||||
[&](const parser::ProcComponentRef &x) { Walk(x); },
|
||||
|
@ -6631,7 +6633,7 @@ bool ModuleVisitor::Pre(const parser::AccessStmt &x) {
|
|||
defaultAccess_ = accessAttr;
|
||||
} else {
|
||||
for (const auto &accessId : accessIds) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[=](const parser::Name &y) {
|
||||
Resolve(y, SetAccess(y.source, accessAttr));
|
||||
|
@ -6718,7 +6720,7 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
|
|||
// Initial processing on specification constructs, before visiting them.
|
||||
void ResolveNamesVisitor::PreSpecificationConstruct(
|
||||
const parser::SpecificationConstruct &spec) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {
|
||||
CreateGeneric(std::get<parser::GenericSpec>(y.statement.value().t));
|
||||
|
@ -6907,21 +6909,21 @@ bool ResolveNamesVisitor::Pre(const parser::ImplicitStmt &x) {
|
|||
}
|
||||
|
||||
void ResolveNamesVisitor::Post(const parser::PointerObject &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const parser::Name &x) { ResolveName(x); },
|
||||
[&](const parser::StructureComponent &x) {
|
||||
ResolveStructureComponent(x);
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const parser::Name &x) { ResolveName(x); },
|
||||
[&](const parser::StructureComponent &x) {
|
||||
ResolveStructureComponent(x);
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void ResolveNamesVisitor::Post(const parser::AllocateObject &x) {
|
||||
std::visit(common::visitors{
|
||||
[&](const parser::Name &x) { ResolveName(x); },
|
||||
[&](const parser::StructureComponent &x) {
|
||||
ResolveStructureComponent(x);
|
||||
},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const parser::Name &x) { ResolveName(x); },
|
||||
[&](const parser::StructureComponent &x) {
|
||||
ResolveStructureComponent(x);
|
||||
},
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
|
||||
|
@ -7054,7 +7056,7 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
|
|||
Scope &scope{currScope()};
|
||||
node.set_scope(scope);
|
||||
AddSubpNames(node);
|
||||
std::visit(
|
||||
common::visit(
|
||||
[&](const auto *x) {
|
||||
if (x) {
|
||||
Walk(*x);
|
||||
|
|
|
@ -120,7 +120,7 @@ void RewriteMutator::Post(parser::IoUnit &x) {
|
|||
// the I/O unit in situ to a FileUnitNumber so that automatic expression
|
||||
// constraint checking will be applied.
|
||||
auto source{var->GetSource()};
|
||||
auto expr{std::visit(
|
||||
auto expr{common::visit(
|
||||
[](auto &&indirection) {
|
||||
return parser::Expr{std::move(indirection)};
|
||||
},
|
||||
|
@ -159,7 +159,7 @@ void RewriteMutator::Post(parser::ReadStmt &x) {
|
|||
const parser::Name &last{parser::GetLastName(*var)};
|
||||
DeclTypeSpec *type{last.symbol ? last.symbol->GetType() : nullptr};
|
||||
if (type && type->category() == DeclTypeSpec::Character) {
|
||||
x.format = std::visit(
|
||||
x.format = common::visit(
|
||||
[](auto &&indirection) {
|
||||
return parser::Expr{std::move(indirection)};
|
||||
},
|
||||
|
|
|
@ -499,7 +499,7 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
|
|||
for (const auto &pair : dtScope) {
|
||||
const Symbol &symbol{*pair.second};
|
||||
auto locationRestorer{common::ScopedSet(location_, symbol.name())};
|
||||
std::visit(
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const TypeParamDetails &) {
|
||||
// already handled above in declaration order
|
||||
|
@ -979,30 +979,30 @@ RuntimeTableBuilder::DescribeBindings(const Scope &dtScope, Scope &scope) {
|
|||
|
||||
void RuntimeTableBuilder::DescribeGeneric(const GenericDetails &generic,
|
||||
std::map<int, evaluate::StructureConstructor> &specials) {
|
||||
std::visit(common::visitors{
|
||||
[&](const GenericKind::OtherKind &k) {
|
||||
if (k == GenericKind::OtherKind::Assignment) {
|
||||
for (auto ref : generic.specificProcs()) {
|
||||
DescribeSpecialProc(specials, *ref, true,
|
||||
false /*!final*/, std::nullopt);
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const GenericKind::DefinedIo &io) {
|
||||
switch (io) {
|
||||
case GenericKind::DefinedIo::ReadFormatted:
|
||||
case GenericKind::DefinedIo::ReadUnformatted:
|
||||
case GenericKind::DefinedIo::WriteFormatted:
|
||||
case GenericKind::DefinedIo::WriteUnformatted:
|
||||
for (auto ref : generic.specificProcs()) {
|
||||
DescribeSpecialProc(
|
||||
specials, *ref, false, false /*!final*/, io);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
[](const auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](const GenericKind::OtherKind &k) {
|
||||
if (k == GenericKind::OtherKind::Assignment) {
|
||||
for (auto ref : generic.specificProcs()) {
|
||||
DescribeSpecialProc(specials, *ref, true,
|
||||
false /*!final*/, std::nullopt);
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const GenericKind::DefinedIo &io) {
|
||||
switch (io) {
|
||||
case GenericKind::DefinedIo::ReadFormatted:
|
||||
case GenericKind::DefinedIo::ReadUnformatted:
|
||||
case GenericKind::DefinedIo::WriteFormatted:
|
||||
case GenericKind::DefinedIo::WriteUnformatted:
|
||||
for (auto ref : generic.specificProcs()) {
|
||||
DescribeSpecialProc(
|
||||
specials, *ref, false, false /*!final*/, io);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
[](const auto &) {},
|
||||
},
|
||||
generic.kind().u);
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ void GenericDetails::CopyFrom(const GenericDetails &from) {
|
|||
// The name of the kind of details for this symbol.
|
||||
// This is primarily for debugging.
|
||||
std::string DetailsToString(const Details &details) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const UnknownDetails &) { return "Unknown"; },
|
||||
[](const MainProgramDetails &) { return "MainProgram"; },
|
||||
|
@ -260,7 +260,7 @@ bool Symbol::CanReplaceDetails(const Details &details) const {
|
|||
if (has<UnknownDetails>()) {
|
||||
return true; // can always replace UnknownDetails
|
||||
} else {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const UseErrorDetails &) { return true; },
|
||||
[&](const ObjectEntityDetails &) { return has<EntityDetails>(); },
|
||||
|
@ -290,14 +290,14 @@ void Symbol::ReplaceName(const SourceName &name) {
|
|||
}
|
||||
|
||||
void Symbol::SetType(const DeclTypeSpec &type) {
|
||||
std::visit(common::visitors{
|
||||
[&](EntityDetails &x) { x.set_type(type); },
|
||||
[&](ObjectEntityDetails &x) { x.set_type(type); },
|
||||
[&](AssocEntityDetails &x) { x.set_type(type); },
|
||||
[&](ProcEntityDetails &x) { x.interface().set_type(type); },
|
||||
[&](TypeParamDetails &x) { x.set_type(type); },
|
||||
[](auto &) {},
|
||||
},
|
||||
common::visit(common::visitors{
|
||||
[&](EntityDetails &x) { x.set_type(type); },
|
||||
[&](ObjectEntityDetails &x) { x.set_type(type); },
|
||||
[&](AssocEntityDetails &x) { x.set_type(type); },
|
||||
[&](ProcEntityDetails &x) { x.interface().set_type(type); },
|
||||
[&](TypeParamDetails &x) { x.set_type(type); },
|
||||
[](auto &) {},
|
||||
},
|
||||
details_);
|
||||
}
|
||||
|
||||
|
@ -305,7 +305,7 @@ template <typename T>
|
|||
constexpr bool HasBindName{std::is_convertible_v<T, const WithBindName *>};
|
||||
|
||||
const std::string *Symbol::GetBindName() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &x) -> const std::string * {
|
||||
if constexpr (HasBindName<decltype(&x)>) {
|
||||
return x.bindName();
|
||||
|
@ -317,7 +317,7 @@ const std::string *Symbol::GetBindName() const {
|
|||
}
|
||||
|
||||
void Symbol::SetBindName(std::string &&name) {
|
||||
std::visit(
|
||||
common::visit(
|
||||
[&](auto &x) {
|
||||
if constexpr (HasBindName<decltype(&x)>) {
|
||||
x.set_bindName(std::move(name));
|
||||
|
@ -329,7 +329,7 @@ void Symbol::SetBindName(std::string &&name) {
|
|||
}
|
||||
|
||||
bool Symbol::IsFuncResult() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{[](const EntityDetails &x) { return x.isFuncResult(); },
|
||||
[](const ObjectEntityDetails &x) { return x.isFuncResult(); },
|
||||
[](const ProcEntityDetails &x) { return x.isFuncResult(); },
|
||||
|
@ -344,7 +344,7 @@ bool Symbol::IsObjectArray() const {
|
|||
}
|
||||
|
||||
bool Symbol::IsSubprogram() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const SubprogramDetails &) { return true; },
|
||||
[](const SubprogramNameDetails &) { return true; },
|
||||
|
@ -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) {
|
||||
os << DetailsToString(details);
|
||||
std::visit( //
|
||||
common::visit( //
|
||||
common::visitors{
|
||||
[&](const UnknownDetails &) {},
|
||||
[&](const MainProgramDetails &) {},
|
||||
|
@ -663,7 +663,7 @@ bool GenericKind::IsOperator() const {
|
|||
}
|
||||
|
||||
std::string GenericKind::ToString() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors {
|
||||
[](const OtherKind &x) { return EnumToString(x); },
|
||||
[](const DefinedIo &x) { return AsFortran(x).ToString(); },
|
||||
|
|
|
@ -426,7 +426,7 @@ const evaluate::Assignment *GetAssignment(
|
|||
}
|
||||
|
||||
const Symbol *FindInterface(const Symbol &symbol) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const ProcEntityDetails &details) {
|
||||
return details.interface().symbol();
|
||||
|
@ -438,7 +438,7 @@ const Symbol *FindInterface(const Symbol &symbol) {
|
|||
}
|
||||
|
||||
const Symbol *FindSubprogram(const Symbol &symbol) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const ProcEntityDetails &details) -> const Symbol * {
|
||||
if (const Symbol * interface{details.interface().symbol()}) {
|
||||
|
@ -916,7 +916,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
bool operator()(const parser::Statement<parser::ActionStmt> &stmt) {
|
||||
return std::visit(*this, stmt.statement.u);
|
||||
return common::visit(*this, stmt.statement.u);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -927,14 +927,14 @@ private:
|
|||
};
|
||||
|
||||
bool IsImageControlStmt(const parser::ExecutableConstruct &construct) {
|
||||
return std::visit(ImageControlStmtHelper{}, construct.u);
|
||||
return common::visit(ImageControlStmtHelper{}, construct.u);
|
||||
}
|
||||
|
||||
std::optional<parser::MessageFixedText> GetImageControlStmtCoarrayMsg(
|
||||
const parser::ExecutableConstruct &construct) {
|
||||
if (const auto *actionStmt{
|
||||
std::get_if<parser::Statement<parser::ActionStmt>>(&construct.u)}) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const common::Indirection<parser::AllocateStmt> &)
|
||||
-> std::optional<parser::MessageFixedText> {
|
||||
|
@ -962,7 +962,7 @@ std::optional<parser::MessageFixedText> GetImageControlStmtCoarrayMsg(
|
|||
|
||||
parser::CharBlock GetImageControlStmtLocation(
|
||||
const parser::ExecutableConstruct &executableConstruct) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[](const common::Indirection<parser::ChangeTeamConstruct>
|
||||
&construct) {
|
||||
|
@ -1431,7 +1431,7 @@ bool InCommonBlock(const Symbol &symbol) {
|
|||
|
||||
const std::optional<parser::Name> &MaybeGetNodeName(
|
||||
const ConstructNode &construct) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::BlockConstruct *blockConstruct)
|
||||
-> const std::optional<parser::Name> & {
|
||||
|
|
|
@ -450,26 +450,26 @@ int ExternalFormattedIoStatementState<DIR, CHAR>::EndIoStatement() {
|
|||
}
|
||||
|
||||
std::optional<DataEdit> IoStatementState::GetNextDataEdit(int n) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &x) { return x.get().GetNextDataEdit(*this, n); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::Emit(
|
||||
const char *data, std::size_t n, std::size_t elementBytes) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[=](auto &x) { return x.get().Emit(data, n, elementBytes); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::Emit(const char *data, std::size_t n) {
|
||||
return std::visit([=](auto &x) { return x.get().Emit(data, n); }, u_);
|
||||
return common::visit([=](auto &x) { return x.get().Emit(data, n); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::Emit(const char16_t *data, std::size_t chars) {
|
||||
return std::visit([=](auto &x) { return x.get().Emit(data, chars); }, u_);
|
||||
return common::visit([=](auto &x) { return x.get().Emit(data, chars); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::Emit(const char32_t *data, std::size_t chars) {
|
||||
return std::visit([=](auto &x) { return x.get().Emit(data, chars); }, u_);
|
||||
return common::visit([=](auto &x) { return x.get().Emit(data, chars); }, u_);
|
||||
}
|
||||
|
||||
template <typename CHAR>
|
||||
|
@ -498,55 +498,57 @@ bool IoStatementState::EmitEncoded(const CHAR *data0, std::size_t chars) {
|
|||
|
||||
bool IoStatementState::Receive(
|
||||
char *data, std::size_t n, std::size_t elementBytes) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[=](auto &x) { return x.get().Receive(data, n, elementBytes); }, u_);
|
||||
}
|
||||
|
||||
std::size_t IoStatementState::GetNextInputBytes(const char *&p) {
|
||||
return std::visit([&](auto &x) { return x.get().GetNextInputBytes(p); }, u_);
|
||||
return common::visit(
|
||||
[&](auto &x) { return x.get().GetNextInputBytes(p); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::AdvanceRecord(int n) {
|
||||
return std::visit([=](auto &x) { return x.get().AdvanceRecord(n); }, u_);
|
||||
return common::visit([=](auto &x) { return x.get().AdvanceRecord(n); }, u_);
|
||||
}
|
||||
|
||||
void IoStatementState::BackspaceRecord() {
|
||||
std::visit([](auto &x) { x.get().BackspaceRecord(); }, u_);
|
||||
common::visit([](auto &x) { x.get().BackspaceRecord(); }, u_);
|
||||
}
|
||||
|
||||
void IoStatementState::HandleRelativePosition(std::int64_t n) {
|
||||
std::visit([=](auto &x) { x.get().HandleRelativePosition(n); }, u_);
|
||||
common::visit([=](auto &x) { x.get().HandleRelativePosition(n); }, u_);
|
||||
}
|
||||
|
||||
void IoStatementState::HandleAbsolutePosition(std::int64_t n) {
|
||||
std::visit([=](auto &x) { x.get().HandleAbsolutePosition(n); }, u_);
|
||||
common::visit([=](auto &x) { x.get().HandleAbsolutePosition(n); }, u_);
|
||||
}
|
||||
|
||||
void IoStatementState::CompleteOperation() {
|
||||
std::visit([](auto &x) { x.get().CompleteOperation(); }, u_);
|
||||
common::visit([](auto &x) { x.get().CompleteOperation(); }, u_);
|
||||
}
|
||||
|
||||
int IoStatementState::EndIoStatement() {
|
||||
return std::visit([](auto &x) { return x.get().EndIoStatement(); }, u_);
|
||||
return common::visit([](auto &x) { return x.get().EndIoStatement(); }, u_);
|
||||
}
|
||||
|
||||
ConnectionState &IoStatementState::GetConnectionState() {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &x) -> ConnectionState & { return x.get().GetConnectionState(); },
|
||||
u_);
|
||||
}
|
||||
|
||||
MutableModes &IoStatementState::mutableModes() {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &x) -> MutableModes & { return x.get().mutableModes(); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::BeginReadingRecord() {
|
||||
return std::visit([](auto &x) { return x.get().BeginReadingRecord(); }, u_);
|
||||
return common::visit(
|
||||
[](auto &x) { return x.get().BeginReadingRecord(); }, u_);
|
||||
}
|
||||
|
||||
IoErrorHandler &IoStatementState::GetIoErrorHandler() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &x) -> IoErrorHandler & {
|
||||
return static_cast<IoErrorHandler &>(x.get());
|
||||
},
|
||||
|
@ -554,7 +556,8 @@ IoErrorHandler &IoStatementState::GetIoErrorHandler() const {
|
|||
}
|
||||
|
||||
ExternalFileUnit *IoStatementState::GetExternalFileUnit() const {
|
||||
return std::visit([](auto &x) { return x.get().GetExternalFileUnit(); }, u_);
|
||||
return common::visit(
|
||||
[](auto &x) { return x.get().GetExternalFileUnit(); }, u_);
|
||||
}
|
||||
|
||||
std::optional<char32_t> IoStatementState::GetCurrentChar(
|
||||
|
@ -582,7 +585,7 @@ std::optional<char32_t> IoStatementState::GetCurrentChar(
|
|||
}
|
||||
|
||||
bool IoStatementState::EmitRepeated(char ch, std::size_t n) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[=](auto &x) {
|
||||
for (std::size_t j{0}; j < n; ++j) {
|
||||
if (!x.get().Emit(&ch, 1)) {
|
||||
|
@ -678,22 +681,24 @@ bool IoStatementState::CheckForEndOfRecord() {
|
|||
|
||||
bool IoStatementState::Inquire(
|
||||
InquiryKeywordHash inquiry, char *out, std::size_t chars) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &x) { return x.get().Inquire(inquiry, out, chars); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::Inquire(InquiryKeywordHash inquiry, bool &out) {
|
||||
return std::visit([&](auto &x) { return x.get().Inquire(inquiry, out); }, u_);
|
||||
return common::visit(
|
||||
[&](auto &x) { return x.get().Inquire(inquiry, out); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::Inquire(
|
||||
InquiryKeywordHash inquiry, std::int64_t id, bool &out) {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[&](auto &x) { return x.get().Inquire(inquiry, id, out); }, u_);
|
||||
}
|
||||
|
||||
bool IoStatementState::Inquire(InquiryKeywordHash inquiry, std::int64_t &n) {
|
||||
return std::visit([&](auto &x) { return x.get().Inquire(inquiry, n); }, u_);
|
||||
return common::visit(
|
||||
[&](auto &x) { return x.get().Inquire(inquiry, n); }, u_);
|
||||
}
|
||||
|
||||
void IoStatementState::GotChar(int n) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "format.h"
|
||||
#include "internal-unit.h"
|
||||
#include "io-error.h"
|
||||
#include "flang/Common/visit.h"
|
||||
#include "flang/Runtime/descriptor.h"
|
||||
#include "flang/Runtime/io-api.h"
|
||||
#include <functional>
|
||||
|
@ -113,7 +114,7 @@ public:
|
|||
|
||||
// N.B.: this also works with base classes
|
||||
template <typename A> A *get_if() const {
|
||||
return std::visit(
|
||||
return common::visit(
|
||||
[](auto &x) -> A * {
|
||||
if constexpr (std::is_convertible_v<decltype(x.get()), A &>) {
|
||||
return &x.get();
|
||||
|
|
Loading…
Reference in New Issue