[flang-commits] [flang] 2ab9990 - [flang] Add & use a better visit()

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Mar 25 13:15:30 PDT 2022


Author: Peter Klausler
Date: 2022-03-25T13:15:20-07:00
New Revision: 2ab9990c9eb79682a4d4b183dfbc7612d3e55328

URL: https://github.com/llvm/llvm-project/commit/2ab9990c9eb79682a4d4b183dfbc7612d3e55328
DIFF: https://github.com/llvm/llvm-project/commit/2ab9990c9eb79682a4d4b183dfbc7612d3e55328.diff

LOG: [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

Added: 
    flang/include/flang/Common/visit.h

Modified: 
    flang/include/flang/Common/idioms.h
    flang/include/flang/Common/template.h
    flang/include/flang/Common/unwrap.h
    flang/include/flang/Evaluate/expression.h
    flang/include/flang/Evaluate/fold-designator.h
    flang/include/flang/Evaluate/initial-image.h
    flang/include/flang/Evaluate/shape.h
    flang/include/flang/Evaluate/tools.h
    flang/include/flang/Evaluate/traverse.h
    flang/include/flang/Parser/parse-tree-visitor.h
    flang/include/flang/Parser/tools.h
    flang/include/flang/Semantics/expression.h
    flang/include/flang/Semantics/symbol.h
    flang/include/flang/Semantics/tools.h
    flang/lib/Evaluate/call.cpp
    flang/lib/Evaluate/characteristics.cpp
    flang/lib/Evaluate/check-expression.cpp
    flang/lib/Evaluate/expression.cpp
    flang/lib/Evaluate/fold-designator.cpp
    flang/lib/Evaluate/fold-implementation.h
    flang/lib/Evaluate/fold-integer.cpp
    flang/lib/Evaluate/fold-logical.cpp
    flang/lib/Evaluate/fold-real.cpp
    flang/lib/Evaluate/fold.cpp
    flang/lib/Evaluate/formatting.cpp
    flang/lib/Evaluate/shape.cpp
    flang/lib/Evaluate/tools.cpp
    flang/lib/Evaluate/type.cpp
    flang/lib/Evaluate/variable.cpp
    flang/lib/Parser/message.cpp
    flang/lib/Parser/parse-tree.cpp
    flang/lib/Parser/provenance.cpp
    flang/lib/Parser/tools.cpp
    flang/lib/Parser/unparse.cpp
    flang/lib/Semantics/canonicalize-do.cpp
    flang/lib/Semantics/check-allocate.cpp
    flang/lib/Semantics/check-call.cpp
    flang/lib/Semantics/check-case.cpp
    flang/lib/Semantics/check-data.cpp
    flang/lib/Semantics/check-deallocate.cpp
    flang/lib/Semantics/check-declarations.cpp
    flang/lib/Semantics/check-do-forall.cpp
    flang/lib/Semantics/check-io.cpp
    flang/lib/Semantics/check-nullify.cpp
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-select-rank.cpp
    flang/lib/Semantics/check-select-type.cpp
    flang/lib/Semantics/data-to-inits.cpp
    flang/lib/Semantics/expression.cpp
    flang/lib/Semantics/mod-file.cpp
    flang/lib/Semantics/pointer-assignment.cpp
    flang/lib/Semantics/program-tree.cpp
    flang/lib/Semantics/resolve-directives.cpp
    flang/lib/Semantics/resolve-names-utils.cpp
    flang/lib/Semantics/resolve-names.cpp
    flang/lib/Semantics/rewrite-parse-tree.cpp
    flang/lib/Semantics/runtime-type-info.cpp
    flang/lib/Semantics/symbol.cpp
    flang/lib/Semantics/tools.cpp
    flang/runtime/io-stmt.cpp
    flang/runtime/io-stmt.h

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Common/idioms.h b/flang/include/flang/Common/idioms.h
index 84a8fd5be4cba..1a086162f1e2a 100644
--- a/flang/include/flang/Common/idioms.h
+++ b/flang/include/flang/Common/idioms.h
@@ -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) { ... },
 //         ...

diff  --git a/flang/include/flang/Common/template.h b/flang/include/flang/Common/template.h
index f31b0afa97fb7..2a9958f74db38 100644
--- a/flang/include/flang/Common/template.h
+++ b/flang/include/flang/Common/template.h
@@ -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));
 }
 

diff  --git a/flang/include/flang/Common/unwrap.h b/flang/include/flang/Common/unwrap.h
index b6ea4a1546096..edb343d77b537 100644
--- a/flang/include/flang/Common/unwrap.h
+++ b/flang/include/flang/Common/unwrap.h
@@ -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);
   }
 

diff  --git a/flang/include/flang/Common/visit.h b/flang/include/flang/Common/visit.h
new file mode 100644
index 0000000000000..db68fdbbf1099
--- /dev/null
+++ b/flang/include/flang/Common/visit.h
@@ -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_

diff  --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h
index f24750e4f0944..90309affbe257 100644
--- a/flang/include/flang/Evaluate/expression.h
+++ b/flang/include/flang/Evaluate/expression.h
@@ -646,7 +646,7 @@ template <> class Relational<SomeType> {
   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;

diff  --git a/flang/include/flang/Evaluate/fold-designator.h b/flang/include/flang/Evaluate/fold-designator.h
index 457e86d4fdad9..f246bd12020e0 100644
--- a/flang/include/flang/Evaluate/fold-designator.h
+++ b/flang/include/flang/Evaluate/fold-designator.h
@@ -67,7 +67,7 @@ class DesignatorFolder {
 
   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 @@ class DesignatorFolder {
   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 @@ class DesignatorFolder {
   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>()}) {

diff  --git a/flang/include/flang/Evaluate/initial-image.h b/flang/include/flang/Evaluate/initial-image.h
index 596b1f77d1790..fcc18835418a8 100644
--- a/flang/include/flang/Evaluate/initial-image.h
+++ b/flang/include/flang/Evaluate/initial-image.h
@@ -88,7 +88,7 @@ class InitialImage {
   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);
   }
 

diff  --git a/flang/include/flang/Evaluate/shape.h b/flang/include/flang/Evaluate/shape.h
index 246f346dcc327..378c0d6734f40 100644
--- a/flang/include/flang/Evaluate/shape.h
+++ b/flang/include/flang/Evaluate/shape.h
@@ -167,7 +167,7 @@ class GetShapeHelper
   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{

diff  --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index ae6772a871070..5523b1bf035b2 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -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 @@ class ScalarConstantExpander {
     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));
   }
 

diff  --git a/flang/include/flang/Evaluate/traverse.h b/flang/include/flang/Evaluate/traverse.h
index 7a5a4ec9ff873..d7efa17f60bd0 100644
--- a/flang/include/flang/Evaluate/traverse.h
+++ b/flang/include/flang/Evaluate/traverse.h
@@ -78,7 +78,7 @@ template <typename Visitor, typename Result> class Traverse {
   }
   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);

diff  --git a/flang/include/flang/Parser/parse-tree-visitor.h b/flang/include/flang/Parser/parse-tree-visitor.h
index 179d9c263378b..4e749d3c8b4e1 100644
--- a/flang/include/flang/Parser/parse-tree-visitor.h
+++ b/flang/include/flang/Parser/parse-tree-visitor.h
@@ -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);
   }
 }

diff  --git a/flang/include/flang/Parser/tools.h b/flang/include/flang/Parser/tools.h
index 0261d8f0cf48e..48c6ab56dd9fd 100644
--- a/flang/include/flang/Parser/tools.h
+++ b/flang/include/flang/Parser/tools.h
@@ -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>

diff  --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h
index fd649308d7d66..e3b1ad7ec21ee 100644
--- a/flang/include/flang/Semantics/expression.h
+++ b/flang/include/flang/Semantics/expression.h
@@ -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 @@ class ExpressionAnalyzer {
     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

diff  --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 40753a8c084a4..2482dc336ba3d 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -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 @@ class Symbol {
   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 @@ class Symbol {
   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 @@ class Symbol {
   }
 
   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(); },

diff  --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index 90d8d1d3d9555..c3f278c881d8d 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -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);
 }

diff  --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp
index 9328ff79852ec..75bc3939c00ee 100644
--- a/flang/lib/Evaluate/call.cpp
+++ b/flang/lib/Evaluate/call.cpp
@@ -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(); },

diff  --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp
index e79c563c136f2..474c6080a0861 100644
--- a/flang/lib/Evaluate/characteristics.cpp
+++ b/flang/lib/Evaluate/characteristics.cpp
@@ -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; // 
diff erent 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));

diff  --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp
index bdff5f20892d4..4678fbe77594b 100644
--- a/flang/lib/Evaluate/check-expression.cpp
+++ b/flang/lib/Evaluate/check-expression.cpp
@@ -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 @@ class IsInitialDataTargetHelper
         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 @@ class ArrayConstantBoundChanger {
         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
   }

diff  --git a/flang/lib/Evaluate/expression.cpp b/flang/lib/Evaluate/expression.cpp
index 1f255e61f37a9..3ea99c8962eac 100644
--- a/flang/lib/Evaluate/expression.cpp
+++ b/flang/lib/Evaluate/expression.cpp
@@ -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

diff  --git a/flang/lib/Evaluate/fold-designator.cpp b/flang/lib/Evaluate/fold-designator.cpp
index f3e1cf40cb8ac..2b07e34c77886 100644
--- a/flang/lib/Evaluate/fold-designator.cpp
+++ b/flang/lib/Evaluate/fold-designator.cpp
@@ -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>{

diff  --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h
index 34a4ce8cf5701..2e12b502d0fc0 100644
--- a/flang/lib/Evaluate/fold-implementation.h
+++ b/flang/lib/Evaluate/fold-implementation.h
@@ -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 @@ template <typename T> class ArrayConstructorFolder {
     }
   }
   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));

diff  --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp
index ff2504e971ff7..635182c0822f4 100644
--- a/flang/lib/Evaluate/fold-integer.cpp
+++ b/flang/lib/Evaluate/fold-integer.cpp
@@ -37,7 +37,7 @@ class GetConstantArrayLboundHelper {
 
   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);
 }
 

diff  --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp
index 34a7639ba32d1..fe18ae211bd2a 100644
--- a/flang/lib/Evaluate/fold-logical.cpp
+++ b/flang/lib/Evaluate/fold-logical.cpp
@@ -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))};
       },

diff  --git a/flang/lib/Evaluate/fold-real.cpp b/flang/lib/Evaluate/fold-real.cpp
index 4ae8cc207d1c2..ae3f9259724f0 100644
--- a/flang/lib/Evaluate/fold-real.cpp
+++ b/flang/lib/Evaluate/fold-real.cpp
@@ -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,

diff  --git a/flang/lib/Evaluate/fold.cpp b/flang/lib/Evaluate/fold.cpp
index f3c2e6ca1c563..ae8b586f47175 100644
--- a/flang/lib/Evaluate/fold.cpp
+++ b/flang/lib/Evaluate/fold.cpp
@@ -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));
 }
 

diff  --git a/flang/lib/Evaluate/formatting.cpp b/flang/lib/Evaluate/formatting.cpp
index e5b44779100e3..646d4bc5b2f7c 100644
--- a/flang/lib/Evaluate/formatting.cpp
+++ b/flang/lib/Evaluate/formatting.cpp
@@ -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) << '=');

diff  --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp
index 0eefd935de801..6c75b0f08cec5 100644
--- a/flang/lib/Evaluate/shape.cpp
+++ b/flang/lib/Evaluate/shape.cpp
@@ -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()) {

diff  --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 68b2a40d48c5d..9802dc2f8825f 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -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;
                        },

diff  --git a/flang/lib/Evaluate/type.cpp b/flang/lib/Evaluate/type.cpp
index 22ea3ea27ad29..3ccb25b94010e 100644
--- a/flang/lib/Evaluate/type.cpp
+++ b/flang/lib/Evaluate/type.cpp
@@ -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);

diff  --git a/flang/lib/Evaluate/variable.cpp b/flang/lib/Evaluate/variable.cpp
index 4788fc50e0759..b19effa980233 100644
--- a/flang/lib/Evaluate/variable.cpp
+++ b/flang/lib/Evaluate/variable.cpp
@@ -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(); },

diff  --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 63515fd2e0fa5..c77f1b37aa175 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -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();

diff  --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index b81a659364f06..4edb3c67ba92b 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -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;

diff  --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp
index e2364d3f8a562..a46111c6b1a8b 100644
--- a/flang/lib/Parser/provenance.cpp
+++ b/flang/lib/Parser/provenance.cpp
@@ -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 ";

diff  --git a/flang/lib/Parser/tools.cpp b/flang/lib/Parser/tools.cpp
index 2db832ab715fa..899fb0f069a93 100644
--- a/flang/lib/Parser/tools.cpp
+++ b/flang/lib/Parser/tools.cpp
@@ -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);

diff  --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 4a66d528f407c..3d25099b6cd07 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -165,7 +165,7 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
         (!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 @@ class UnparseVisitor {
   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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
   }
   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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
   }
   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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
       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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
   }
   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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
   }
   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 @@ class UnparseVisitor {
         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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
   }
   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 @@ class UnparseVisitor {
   }
 
   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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
         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 @@ class UnparseVisitor {
 
   // 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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
 
   // 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 @@ class UnparseVisitor {
     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 @@ class UnparseVisitor {
   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 @@ class UnparseVisitor {
   }
   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) {

diff  --git a/flang/lib/Semantics/canonicalize-do.cpp b/flang/lib/Semantics/canonicalize-do.cpp
index 797fb27b2b14c..6aab4b7bc49dd 100644
--- a/flang/lib/Semantics/canonicalize-do.cpp
+++ b/flang/lib/Semantics/canonicalize-do.cpp
@@ -24,7 +24,7 @@ class CanonicalizationOfDoLoops {
     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

diff  --git a/flang/lib/Semantics/check-allocate.cpp b/flang/lib/Semantics/check-allocate.cpp
index 8a3a23ad4f8c2..95b8bc3ddacee 100644
--- a/flang/lib/Semantics/check-allocate.cpp
+++ b/flang/lib/Semantics/check-allocate.cpp
@@ -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

diff  --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 3f39e064e6d6e..e3442b1b37f5d 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -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());

diff  --git a/flang/lib/Semantics/check-case.cpp b/flang/lib/Semantics/check-case.cpp
index 3c52de8306b69..e62d91b95f41a 100644
--- a/flang/lib/Semantics/check-case.cpp
+++ b/flang/lib/Semantics/check-case.cpp
@@ -43,7 +43,7 @@ template <typename T> class CaseValues {
     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 @@ template <typename T> class CaseValues {
 
   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);
   }
 

diff  --git a/flang/lib/Semantics/check-data.cpp b/flang/lib/Semantics/check-data.cpp
index a63e9b27d1928..955998bedc0c4 100644
--- a/flang/lib/Semantics/check-data.cpp
+++ b/flang/lib/Semantics/check-data.cpp
@@ -129,7 +129,7 @@ class DataVarChecker : public evaluate::AllTraverse<DataVarChecker, true> {
   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);
 }
 

diff  --git a/flang/lib/Semantics/check-deallocate.cpp b/flang/lib/Semantics/check-deallocate.cpp
index 03c2d6ebdddac..5452abb73c78b 100644
--- a/flang/lib/Semantics/check-deallocate.cpp
+++ b/flang/lib/Semantics/check-deallocate.cpp
@@ -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) {

diff  --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 924cd5e55caba..8f67f621e7b6d 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -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);
                  },

diff  --git a/flang/lib/Semantics/check-do-forall.cpp b/flang/lib/Semantics/check-do-forall.cpp
index e1cc4266e8024..992193bd4a854 100644
--- a/flang/lib/Semantics/check-do-forall.cpp
+++ b/flang/lib/Semantics/check-do-forall.cpp
@@ -430,7 +430,7 @@ class DoContext {
   }
 
   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 @@ class DoContext {
               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 @@ class DoContext {
     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);
 }
 

diff  --git a/flang/lib/Semantics/check-io.cpp b/flang/lib/Semantics/check-io.cpp
index 2bb6678e6e177..129ad91599828 100644
--- a/flang/lib/Semantics/check-io.cpp
+++ b/flang/lib/Semantics/check-io.cpp
@@ -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); },

diff  --git a/flang/lib/Semantics/check-nullify.cpp b/flang/lib/Semantics/check-nullify.cpp
index 4c6e78e7f7e3e..d98bbdb075a86 100644
--- a/flang/lib/Semantics/check-nullify.cpp
+++ b/flang/lib/Semantics/check-nullify.cpp
@@ -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};

diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 88d2a6d399908..65ea131d16c34 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -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)>;

diff  --git a/flang/lib/Semantics/check-select-rank.cpp b/flang/lib/Semantics/check-select-rank.cpp
index 595c17fa7211a..dc63e3616f8ca 100644
--- a/flang/lib/Semantics/check-select-rank.cpp
+++ b/flang/lib/Semantics/check-select-rank.cpp
@@ -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

diff  --git a/flang/lib/Semantics/check-select-type.cpp b/flang/lib/Semantics/check-select-type.cpp
index ce675fa2f1dbe..0c06cbae87725 100644
--- a/flang/lib/Semantics/check-select-type.cpp
+++ b/flang/lib/Semantics/check-select-type.cpp
@@ -51,7 +51,7 @@ class TypeCaseValues {
 
   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 @@ class TypeCaseValues {
       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 @@ class TypeCaseValues {
 
     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

diff  --git a/flang/lib/Semantics/data-to-inits.cpp b/flang/lib/Semantics/data-to-inits.cpp
index 6bdbf5f6549fd..0a294f7a7295b 100644
--- a/flang/lib/Semantics/data-to-inits.cpp
+++ b/flang/lib/Semantics/data-to-inits.cpp
@@ -122,7 +122,7 @@ class DataInitializationCompiler {
 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()); },

diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 342f34164f176..24f26c2fe9aa8 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -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());

diff  --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index 10d56b2c75eaf..d19dc5cf1b403 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -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());

diff  --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp
index 2b065253bdc70..d55fa16001335 100644
--- a/flang/lib/Semantics/pointer-assignment.cpp
+++ b/flang/lib/Semantics/pointer-assignment.cpp
@@ -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();

diff  --git a/flang/lib/Semantics/program-tree.cpp b/flang/lib/Semantics/program-tree.cpp
index 9d76cfad83805..e96a6c4c07d82 100644
--- a/flang/lib/Semantics/program-tree.cpp
+++ b/flang/lib/Semantics/program-tree.cpp
@@ -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;

diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index f6e9ae9f2c5ec..517ef6ebecd9f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -364,18 +364,18 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
     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)}) {

diff  --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp
index 2d8f2c16bb8b3..7aab69401bb48 100644
--- a/flang/lib/Semantics/resolve-names-utils.cpp
+++ b/flang/lib/Semantics/resolve-names-utils.cpp
@@ -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

diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index cf7bebcfd656b..6da43ab0e8921 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -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);

diff  --git a/flang/lib/Semantics/rewrite-parse-tree.cpp b/flang/lib/Semantics/rewrite-parse-tree.cpp
index 071a668de7fd0..289a4e1d6e9ba 100644
--- a/flang/lib/Semantics/rewrite-parse-tree.cpp
+++ b/flang/lib/Semantics/rewrite-parse-tree.cpp
@@ -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)};
             },

diff  --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp
index 007567ff83f28..d24b844bd7b58 100644
--- a/flang/lib/Semantics/runtime-type-info.cpp
+++ b/flang/lib/Semantics/runtime-type-info.cpp
@@ -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);
 }
 

diff  --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp
index ad80f901fb72c..f874904d9e3da 100644
--- a/flang/lib/Semantics/symbol.cpp
+++ b/flang/lib/Semantics/symbol.cpp
@@ -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(); },

diff  --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index 9bad51dd4371b..997ea566f07b3 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -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 @@ class ImageControlStmtHelper {
     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 @@ class ImageControlStmtHelper {
 };
 
 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> & {

diff  --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index ec824d9b3cdff..ade7f9cb4a59c 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -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) {

diff  --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 0ed14e5ad6a4d..7133b1b83a4c7 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -16,6 +16,7 @@
 #include "format.h"
 #include "internal-unit.h"
 #include "io-error.h"
+#include "flang/Common/visit.h"
 #include "flang/Runtime/descriptor.h"
 #include "flang/Runtime/io-api.h"
 #include <functional>
@@ -113,7 +114,7 @@ class IoStatementState {
 
   // 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();


        


More information about the flang-commits mailing list