forked from OSchip/llvm-project
[flang] Prep for review
Original-commit: flang-compiler/f18@8be02a41c7 Reviewed-on: https://github.com/flang-compiler/f18/pull/755 Tree-same-pre-rewrite: false
This commit is contained in:
parent
686baf0b0e
commit
d8c9b50fd6
|
@ -81,7 +81,7 @@ endif()
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
if(CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
if(BUILD_WITH_CLANG_LIBRARIES)
|
if(BUILD_WITH_CLANG_LIBRARIES)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++ -I${BUILD_WITH_CLANG_LIBRARIES}/include/c++/v1")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++ -I${BUILD_WITH_CLANG_LIBRARIES}/include/c++/v1 -DCLANG_LIBRARIES")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -Wl,-rpath,${BUILD_WITH_CLANG_LIBRARIES}/lib -L${BUILD_WITH_CLANG_LIBRARIES}/lib")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -Wl,-rpath,${BUILD_WITH_CLANG_LIBRARIES}/lib -L${BUILD_WITH_CLANG_LIBRARIES}/lib")
|
||||||
else()
|
else()
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++")
|
||||||
|
|
|
@ -76,9 +76,8 @@ template bool IsConstantExpr(const Expr<SomeType> &);
|
||||||
// data address used to initialize a pointer with "=> x". See C765.
|
// data address used to initialize a pointer with "=> x". See C765.
|
||||||
// The caller is responsible for checking the base object symbol's
|
// The caller is responsible for checking the base object symbol's
|
||||||
// characteristics (TARGET, SAVE, &c.) since this code can't use GetUltimate().
|
// characteristics (TARGET, SAVE, &c.) since this code can't use GetUltimate().
|
||||||
class IsInitialDataTargetHelper
|
struct IsInitialDataTargetHelper
|
||||||
: public AllTraverse<IsInitialDataTargetHelper> {
|
: public AllTraverse<IsInitialDataTargetHelper> {
|
||||||
public:
|
|
||||||
using Base = AllTraverse<IsInitialDataTargetHelper>;
|
using Base = AllTraverse<IsInitialDataTargetHelper>;
|
||||||
using Base::operator();
|
using Base::operator();
|
||||||
IsInitialDataTargetHelper() : Base{*this} {}
|
IsInitialDataTargetHelper() : Base{*this} {}
|
||||||
|
@ -126,9 +125,6 @@ public:
|
||||||
return (*this)(x.left());
|
return (*this)(x.left());
|
||||||
}
|
}
|
||||||
bool operator()(const Relational<SomeType> &) const { return false; }
|
bool operator()(const Relational<SomeType> &) const { return false; }
|
||||||
|
|
||||||
private:
|
|
||||||
const semantics::Symbol &(*GetUltimate)(const semantics::Symbol &);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsInitialDataTarget(const Expr<SomeType> &x) {
|
bool IsInitialDataTarget(const Expr<SomeType> &x) {
|
||||||
|
|
|
@ -1,369 +0,0 @@
|
||||||
// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#ifndef FORTRAN_EVALUATE_DESCENDER_H_
|
|
||||||
#define FORTRAN_EVALUATE_DESCENDER_H_
|
|
||||||
|
|
||||||
// Helper friend class templates for Visitor::Visit() and Rewriter::Traverse().
|
|
||||||
|
|
||||||
#include "expression.h"
|
|
||||||
#include "../semantics/type.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace Fortran::evaluate {
|
|
||||||
|
|
||||||
template<typename VISITOR> class Descender {
|
|
||||||
public:
|
|
||||||
explicit Descender(VISITOR &v) : visitor_{v} {}
|
|
||||||
|
|
||||||
// Base cases
|
|
||||||
void Descend(const semantics::Symbol &) {}
|
|
||||||
void Descend(semantics::Symbol &) {}
|
|
||||||
template<typename T> void Descend(const Constant<T> &) {}
|
|
||||||
template<typename T> void Descend(Constant<T> &) {}
|
|
||||||
void Descend(const std::shared_ptr<StaticDataObject> &) {}
|
|
||||||
void Descend(std::shared_ptr<StaticDataObject> &) {}
|
|
||||||
void Descend(const ImpliedDoIndex &) {}
|
|
||||||
void Descend(ImpliedDoIndex &) {}
|
|
||||||
void Descend(const BOZLiteralConstant &) {}
|
|
||||||
void Descend(BOZLiteralConstant &) {}
|
|
||||||
void Descend(const NullPointer &) {}
|
|
||||||
void Descend(NullPointer &) {}
|
|
||||||
|
|
||||||
template<typename X> void Descend(const X *p) {
|
|
||||||
if (p != nullptr) {
|
|
||||||
Visit(*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template<typename X> void Descend(X *p) {
|
|
||||||
if (p != nullptr) {
|
|
||||||
Visit(*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename X> void Descend(const std::optional<X> &o) {
|
|
||||||
if (o.has_value()) {
|
|
||||||
Visit(*o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template<typename X> void Descend(std::optional<X> &o) {
|
|
||||||
if (o.has_value()) {
|
|
||||||
Visit(*o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename X, bool COPY>
|
|
||||||
void Descend(const common::Indirection<X, COPY> &p) {
|
|
||||||
Visit(p.value());
|
|
||||||
}
|
|
||||||
template<typename X, bool COPY>
|
|
||||||
void Descend(common::Indirection<X, COPY> &p) {
|
|
||||||
Visit(p.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename X, typename DELETER>
|
|
||||||
void Descend(const std::unique_ptr<X, DELETER> &p) {
|
|
||||||
if (p.get() != nullptr) {
|
|
||||||
Visit(*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template<typename X, typename DELETER>
|
|
||||||
void Descend(std::unique_ptr<X, DELETER> &p) {
|
|
||||||
if (p.get() != nullptr) {
|
|
||||||
Visit(*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... X> void Descend(const std::variant<X...> &u) {
|
|
||||||
std::visit([&](const auto &x) { Visit(x); }, u);
|
|
||||||
}
|
|
||||||
template<typename... X> void Descend(std::variant<X...> &u) {
|
|
||||||
std::visit([&](auto &x) { Visit(x); }, u);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename X> void Descend(const std::vector<X> &xs) {
|
|
||||||
for (const auto &x : xs) {
|
|
||||||
Visit(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template<typename X> void Descend(std::vector<X> &xs) {
|
|
||||||
for (auto &x : xs) {
|
|
||||||
Visit(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const GenericExprWrapper &w) { Visit(w.v); }
|
|
||||||
void Descend(GenericExprWrapper &w) { Visit(w.v); }
|
|
||||||
|
|
||||||
template<typename T> void Descend(const Expr<T> &expr) { Visit(expr.u); }
|
|
||||||
template<typename T> void Descend(Expr<T> &expr) { Visit(expr.u); }
|
|
||||||
|
|
||||||
template<typename D, typename R, typename X>
|
|
||||||
void Descend(const Operation<D, R, X> &op) {
|
|
||||||
Visit(op.left());
|
|
||||||
}
|
|
||||||
template<typename D, typename R, typename X>
|
|
||||||
void Descend(Operation<D, R, X> &op) {
|
|
||||||
Visit(op.left());
|
|
||||||
}
|
|
||||||
template<typename D, typename R, typename X, typename Y>
|
|
||||||
void Descend(const Operation<D, R, X, Y> &op) {
|
|
||||||
Visit(op.left());
|
|
||||||
Visit(op.right());
|
|
||||||
}
|
|
||||||
template<typename D, typename R, typename X, typename Y>
|
|
||||||
void Descend(Operation<D, R, X, Y> &op) {
|
|
||||||
Visit(op.left());
|
|
||||||
Visit(op.right());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const Relational<SomeType> &r) { Visit(r.u); }
|
|
||||||
void Descend(Relational<SomeType> &r) { Visit(r.u); }
|
|
||||||
|
|
||||||
template<typename R> void Descend(const ImpliedDo<R> &ido) {
|
|
||||||
Visit(ido.lower());
|
|
||||||
Visit(ido.upper());
|
|
||||||
Visit(ido.stride());
|
|
||||||
Visit(ido.values());
|
|
||||||
}
|
|
||||||
template<typename R> void Descend(ImpliedDo<R> &ido) {
|
|
||||||
Visit(ido.lower());
|
|
||||||
Visit(ido.upper());
|
|
||||||
Visit(ido.stride());
|
|
||||||
Visit(ido.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R> void Descend(const ArrayConstructorValue<R> &av) {
|
|
||||||
Visit(av.u);
|
|
||||||
}
|
|
||||||
template<typename R> void Descend(ArrayConstructorValue<R> &av) {
|
|
||||||
Visit(av.u);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R> void Descend(const ArrayConstructorValues<R> &avs) {
|
|
||||||
for (const auto &x : avs) {
|
|
||||||
Visit(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template<typename R> void Descend(ArrayConstructorValues<R> &avs) {
|
|
||||||
for (auto &x : avs) {
|
|
||||||
Visit(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int KIND>
|
|
||||||
void Descend(
|
|
||||||
const ArrayConstructor<Type<TypeCategory::Character, KIND>> &ac) {
|
|
||||||
const ArrayConstructorValues<Type<TypeCategory::Character, KIND>> &base{ac};
|
|
||||||
Visit(base);
|
|
||||||
Visit(ac.LEN());
|
|
||||||
}
|
|
||||||
template<int KIND>
|
|
||||||
void Descend(ArrayConstructor<Type<TypeCategory::Character, KIND>> &ac) {
|
|
||||||
ArrayConstructorValues<Type<TypeCategory::Character, KIND>> &base{ac};
|
|
||||||
Visit(base);
|
|
||||||
Visit(ac.LEN());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const semantics::ParamValue ¶m) {
|
|
||||||
Visit(param.GetExplicit());
|
|
||||||
}
|
|
||||||
void Descend(semantics::ParamValue ¶m) { Visit(param.GetExplicit()); }
|
|
||||||
|
|
||||||
void Descend(const semantics::DerivedTypeSpec &derived) {
|
|
||||||
for (const auto &pair : derived.parameters()) {
|
|
||||||
Visit(pair.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Descend(semantics::DerivedTypeSpec &derived) {
|
|
||||||
for (const auto &pair : derived.parameters()) {
|
|
||||||
Visit(pair.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const StructureConstructor &sc) {
|
|
||||||
Visit(sc.derivedTypeSpec());
|
|
||||||
for (const auto &pair : sc) {
|
|
||||||
Visit(pair.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Descend(StructureConstructor &sc) {
|
|
||||||
Visit(sc.derivedTypeSpec());
|
|
||||||
for (const auto &pair : sc) {
|
|
||||||
Visit(pair.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const BaseObject &object) { Visit(object.u); }
|
|
||||||
void Descend(BaseObject &object) { Visit(object.u); }
|
|
||||||
|
|
||||||
void Descend(const Component &component) {
|
|
||||||
Visit(component.base());
|
|
||||||
Visit(component.GetLastSymbol());
|
|
||||||
}
|
|
||||||
void Descend(Component &component) {
|
|
||||||
Visit(component.base());
|
|
||||||
Visit(component.GetLastSymbol());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const NamedEntity &x) {
|
|
||||||
if (const Component * c{x.UnwrapComponent()}) {
|
|
||||||
Visit(*c);
|
|
||||||
} else {
|
|
||||||
Visit(x.GetLastSymbol());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Descend(NamedEntity &x) {
|
|
||||||
if (Component * c{x.UnwrapComponent()}) {
|
|
||||||
Visit(*c);
|
|
||||||
} else {
|
|
||||||
Visit(x.GetLastSymbol());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int KIND> void Descend(const TypeParamInquiry<KIND> &inq) {
|
|
||||||
Visit(inq.base());
|
|
||||||
Visit(inq.parameter());
|
|
||||||
}
|
|
||||||
template<int KIND> void Descend(TypeParamInquiry<KIND> &inq) {
|
|
||||||
Visit(inq.base());
|
|
||||||
Visit(inq.parameter());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const DescriptorInquiry &inq) { Visit(inq.base()); }
|
|
||||||
void Descend(DescriptorInquiry &inq) { Visit(inq.base()); }
|
|
||||||
|
|
||||||
void Descend(const Triplet &triplet) {
|
|
||||||
Visit(triplet.lower());
|
|
||||||
Visit(triplet.upper());
|
|
||||||
Visit(triplet.stride());
|
|
||||||
}
|
|
||||||
void Descend(Triplet &triplet) {
|
|
||||||
if (auto x{triplet.lower()}) {
|
|
||||||
Visit(*x);
|
|
||||||
triplet.set_lower(std::move(*x));
|
|
||||||
}
|
|
||||||
if (auto x{triplet.upper()}) {
|
|
||||||
Visit(*x);
|
|
||||||
triplet.set_upper(std::move(*x));
|
|
||||||
}
|
|
||||||
triplet.set_stride(Visit(triplet.stride()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const Subscript &sscript) { Visit(sscript.u); }
|
|
||||||
void Descend(Subscript &sscript) { Visit(sscript.u); }
|
|
||||||
|
|
||||||
void Descend(const ArrayRef &aref) {
|
|
||||||
Visit(aref.base());
|
|
||||||
Visit(aref.subscript());
|
|
||||||
}
|
|
||||||
void Descend(ArrayRef &aref) {
|
|
||||||
Visit(aref.base());
|
|
||||||
Visit(aref.subscript());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const CoarrayRef &caref) {
|
|
||||||
Visit(caref.base());
|
|
||||||
Visit(caref.subscript());
|
|
||||||
Visit(caref.cosubscript());
|
|
||||||
Visit(caref.stat());
|
|
||||||
Visit(caref.team());
|
|
||||||
}
|
|
||||||
void Descend(CoarrayRef &caref) {
|
|
||||||
Visit(caref.base());
|
|
||||||
Visit(caref.subscript());
|
|
||||||
Visit(caref.cosubscript());
|
|
||||||
if (auto x{caref.stat()}) {
|
|
||||||
Visit(*x);
|
|
||||||
caref.set_stat(std::move(*x));
|
|
||||||
}
|
|
||||||
if (auto x{caref.team()}) {
|
|
||||||
Visit(*x);
|
|
||||||
caref.set_team(std::move(*x), caref.teamIsTeamNumber());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const DataRef &data) { Visit(data.u); }
|
|
||||||
void Descend(DataRef &data) { Visit(data.u); }
|
|
||||||
|
|
||||||
void Descend(const ComplexPart &z) { Visit(z.complex()); }
|
|
||||||
void Descend(ComplexPart &z) { Visit(z.complex()); }
|
|
||||||
|
|
||||||
void Descend(const Substring &ss) {
|
|
||||||
Visit(ss.parent());
|
|
||||||
Visit(ss.lower());
|
|
||||||
Visit(ss.upper());
|
|
||||||
}
|
|
||||||
void Descend(Substring &ss) {
|
|
||||||
Visit(ss.parent());
|
|
||||||
auto lx{ss.lower()};
|
|
||||||
Visit(lx);
|
|
||||||
ss.set_lower(std::move(lx));
|
|
||||||
if (auto ux{ss.upper()}) {
|
|
||||||
Visit(ux);
|
|
||||||
ss.set_upper(std::move(*ux));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> void Descend(const Designator<T> &designator) {
|
|
||||||
Visit(designator.u);
|
|
||||||
}
|
|
||||||
template<typename T> void Descend(Designator<T> &designator) {
|
|
||||||
Visit(designator.u);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> void Descend(const Variable<T> &var) { Visit(var.u); }
|
|
||||||
template<typename T> void Descend(Variable<T> &var) { Visit(var.u); }
|
|
||||||
|
|
||||||
void Descend(const ActualArgument &arg) {
|
|
||||||
if (const auto *expr{arg.UnwrapExpr()}) {
|
|
||||||
Visit(*expr);
|
|
||||||
} else {
|
|
||||||
const semantics::Symbol *aType{arg.GetAssumedTypeDummy()};
|
|
||||||
Visit(*aType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Descend(ActualArgument &arg) {
|
|
||||||
if (auto *expr{arg.UnwrapExpr()}) {
|
|
||||||
Visit(*expr);
|
|
||||||
} else {
|
|
||||||
const semantics::Symbol *aType{arg.GetAssumedTypeDummy()};
|
|
||||||
Visit(*aType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Descend(const SpecificIntrinsic &) {}
|
|
||||||
void Descend(SpecificIntrinsic &) {}
|
|
||||||
|
|
||||||
void Descend(const ProcedureDesignator &p) { Visit(p.u); }
|
|
||||||
void Descend(ProcedureDesignator &p) { Visit(p.u); }
|
|
||||||
|
|
||||||
void Descend(const ProcedureRef &call) {
|
|
||||||
Visit(call.proc());
|
|
||||||
Visit(call.arguments());
|
|
||||||
}
|
|
||||||
void Descend(ProcedureRef &call) {
|
|
||||||
Visit(call.proc());
|
|
||||||
Visit(call.arguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<typename T> void Visit(const T &x) { return visitor_.Visit(x); }
|
|
||||||
template<typename T> void Visit(T &x) { x = visitor_.Traverse(std::move(x)); }
|
|
||||||
|
|
||||||
VISITOR &visitor_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif // FORTRAN_EVALUATE_DESCENDER_H_
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "characteristics.h"
|
#include "characteristics.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "constant.h"
|
#include "constant.h"
|
||||||
#include "descender.h"
|
|
||||||
#include "expression.h"
|
#include "expression.h"
|
||||||
#include "formatting.h"
|
#include "formatting.h"
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
|
|
@ -16,14 +16,14 @@
|
||||||
#define FORTRAN_EVALUATE_TRAVERSE_H_
|
#define FORTRAN_EVALUATE_TRAVERSE_H_
|
||||||
|
|
||||||
// A utility for scanning all of the constituent objects in an Expr<>
|
// A utility for scanning all of the constituent objects in an Expr<>
|
||||||
// expression representation with a sheaf of mutually-recursive functions.
|
// expression representation using a collection of mutually recursive
|
||||||
|
// functions to compose a function object.
|
||||||
//
|
//
|
||||||
// The class template Traverse<> below implements a function object that
|
// The class template Traverse<> below implements a function object that
|
||||||
// can handle every type that can appear in or around an Expr<>.
|
// can handle every type that can appear in or around an Expr<>.
|
||||||
// Each of its overloads for operator() should be viewed as a *default*
|
// Each of its overloads for operator() should be viewed as a *default*
|
||||||
// handler that can be overridden by the client. These default handlers
|
// handler; some of these must be overridden by the client to accomplish
|
||||||
// simply forward the constituents of the argument to the client's
|
// its particular task.
|
||||||
// visitor function object.
|
|
||||||
//
|
//
|
||||||
// The client (Visitor) of Traverse<Visitor,Result> must define:
|
// The client (Visitor) of Traverse<Visitor,Result> must define:
|
||||||
// - a member function "Result Default();"
|
// - a member function "Result Default();"
|
||||||
|
@ -32,13 +32,23 @@
|
||||||
// handler that reflects back into Traverse<Visitor, Result>
|
// handler that reflects back into Traverse<Visitor, Result>
|
||||||
// - overrides for "Result operator()"
|
// - overrides for "Result operator()"
|
||||||
//
|
//
|
||||||
// Boilerplate classes follow that ease construction of visitors.
|
// Boilerplate classes also appear below to ease construction of visitors.
|
||||||
// See CheckSpecificationExpr() in check-expression.cc for an example client.
|
// See CheckSpecificationExpr() in check-expression.cc for an example client.
|
||||||
|
//
|
||||||
|
// How this works:
|
||||||
|
// - The operator() overloads in Traverse<> invoke the visitor's Default() for
|
||||||
|
// expression leaf nodes. They invoke the visitor's operator() for the
|
||||||
|
// subtrees of interior nodes, and the visitor's Combine() to merge their
|
||||||
|
// results together.
|
||||||
|
// - The default operator() inherited into each visitor just reflects right
|
||||||
|
// back into Traverse<> to descend into subtrees.
|
||||||
|
// - Overloads of operator() in each visitor handle the cases of interest.
|
||||||
|
|
||||||
#include "expression.h"
|
#include "expression.h"
|
||||||
#include "../semantics/symbol.h"
|
#include "../semantics/symbol.h"
|
||||||
#include "../semantics/type.h"
|
#include "../semantics/type.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace Fortran::evaluate {
|
namespace Fortran::evaluate {
|
||||||
template<typename Visitor, typename Result> class Traverse {
|
template<typename Visitor, typename Result> class Traverse {
|
||||||
|
@ -249,40 +259,51 @@ private:
|
||||||
Traverse<Visitor, Result> traverse_;
|
Traverse<Visitor, Result> traverse_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Visitor, typename Base = TraverseBase<Visitor, bool>>
|
template<typename Visitor, typename Result = bool, bool isConjunction = true,
|
||||||
struct AllTraverse : public Base {
|
|
||||||
using Base::Base;
|
|
||||||
using Base::operator();
|
|
||||||
static constexpr bool Default() { return true; }
|
|
||||||
static constexpr bool Combine(bool x, bool y) { return x && y; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// For OR-combining default-false Boolean searches, pointers, and
|
|
||||||
// std::optional<> search results.
|
|
||||||
template<typename Visitor, typename Result = bool,
|
|
||||||
typename Base = TraverseBase<Visitor, Result>>
|
typename Base = TraverseBase<Visitor, Result>>
|
||||||
struct AnyTraverse : public Base {
|
struct CombiningTraverse : public Base {
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
using Base::operator();
|
using Base::operator();
|
||||||
static Result Combine(Result &&x, Result &&y) {
|
static Result Default() {
|
||||||
if (x) {
|
if constexpr (isConjunction && std::is_same_v<Result, bool>) {
|
||||||
return std::move(x);
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static Result Combine(Result &&x, Result &&y) {
|
||||||
|
if (static_cast<bool>(x) == isConjunction) {
|
||||||
return std::move(y);
|
return std::move(y);
|
||||||
|
} else {
|
||||||
|
return std::move(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// For validity checks across an expression: if any operator() is
|
||||||
|
// false, the result is false.
|
||||||
|
template<typename Visitor, typename Result = bool>
|
||||||
|
using AllTraverse = CombiningTraverse<Visitor, Result, true>;
|
||||||
|
|
||||||
|
// For searches over an expression: the first operator() result that
|
||||||
|
// is truthful is the final result. Works for Booleans, pointers,
|
||||||
|
// and std::optional<>.
|
||||||
|
template<typename Visitor, typename Result = bool>
|
||||||
|
using AnyTraverse = CombiningTraverse<Visitor, Result, false>;
|
||||||
|
|
||||||
template<typename Visitor, typename Set,
|
template<typename Visitor, typename Set,
|
||||||
typename Base = TraverseBase<Visitor, Set>>
|
typename Base = TraverseBase<Visitor, Set>>
|
||||||
struct SetTraverse : public Base {
|
struct SetTraverse : public Base {
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
using Base::operator();
|
using Base::operator();
|
||||||
static Set Combine(Set &&x, Set &&y) {
|
static Set Combine(Set &&x, Set &&y) {
|
||||||
// TODO: use x.merge(y) instead when clang headers support it
|
#if CLANG_LIBRARIES // no std::set::merge()
|
||||||
for (auto &value : y) {
|
for (auto &value : y) {
|
||||||
x.insert(std::move(value));
|
x.insert(std::move(value));
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
x.merge(y);
|
||||||
|
#endif
|
||||||
return std::move(x);
|
return std::move(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue