From d8c9b50fd64351ff0f38ea8e0d89adbd034144a7 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 20 Sep 2019 11:02:17 -0700 Subject: [PATCH] [flang] Prep for review Original-commit: flang-compiler/f18@8be02a41c7e0312a95ee4ea399318eb20c45ccce Reviewed-on: https://github.com/flang-compiler/f18/pull/755 Tree-same-pre-rewrite: false --- flang/CMakeLists.txt | 2 +- flang/lib/evaluate/check-expression.cc | 6 +- flang/lib/evaluate/descender.h | 369 ------------------------- flang/lib/evaluate/fold.cc | 1 - flang/lib/evaluate/traverse.h | 63 +++-- 5 files changed, 44 insertions(+), 397 deletions(-) delete mode 100644 flang/lib/evaluate/descender.h diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index 0b92e0c0deed..2a9b20b69009 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -81,7 +81,7 @@ endif() if(CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 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") else() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++") diff --git a/flang/lib/evaluate/check-expression.cc b/flang/lib/evaluate/check-expression.cc index 6827db01ab40..ccb039b100dd 100644 --- a/flang/lib/evaluate/check-expression.cc +++ b/flang/lib/evaluate/check-expression.cc @@ -76,9 +76,8 @@ template bool IsConstantExpr(const Expr &); // data address used to initialize a pointer with "=> x". See C765. // The caller is responsible for checking the base object symbol's // characteristics (TARGET, SAVE, &c.) since this code can't use GetUltimate(). -class IsInitialDataTargetHelper +struct IsInitialDataTargetHelper : public AllTraverse { -public: using Base = AllTraverse; using Base::operator(); IsInitialDataTargetHelper() : Base{*this} {} @@ -126,9 +125,6 @@ public: return (*this)(x.left()); } bool operator()(const Relational &) const { return false; } - -private: - const semantics::Symbol &(*GetUltimate)(const semantics::Symbol &); }; bool IsInitialDataTarget(const Expr &x) { diff --git a/flang/lib/evaluate/descender.h b/flang/lib/evaluate/descender.h deleted file mode 100644 index 9b81c14c7151..000000000000 --- a/flang/lib/evaluate/descender.h +++ /dev/null @@ -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 - -namespace Fortran::evaluate { - -template class Descender { -public: - explicit Descender(VISITOR &v) : visitor_{v} {} - - // Base cases - void Descend(const semantics::Symbol &) {} - void Descend(semantics::Symbol &) {} - template void Descend(const Constant &) {} - template void Descend(Constant &) {} - void Descend(const std::shared_ptr &) {} - void Descend(std::shared_ptr &) {} - void Descend(const ImpliedDoIndex &) {} - void Descend(ImpliedDoIndex &) {} - void Descend(const BOZLiteralConstant &) {} - void Descend(BOZLiteralConstant &) {} - void Descend(const NullPointer &) {} - void Descend(NullPointer &) {} - - template void Descend(const X *p) { - if (p != nullptr) { - Visit(*p); - } - } - template void Descend(X *p) { - if (p != nullptr) { - Visit(*p); - } - } - - template void Descend(const std::optional &o) { - if (o.has_value()) { - Visit(*o); - } - } - template void Descend(std::optional &o) { - if (o.has_value()) { - Visit(*o); - } - } - - template - void Descend(const common::Indirection &p) { - Visit(p.value()); - } - template - void Descend(common::Indirection &p) { - Visit(p.value()); - } - - template - void Descend(const std::unique_ptr &p) { - if (p.get() != nullptr) { - Visit(*p); - } - } - template - void Descend(std::unique_ptr &p) { - if (p.get() != nullptr) { - Visit(*p); - } - } - - template void Descend(const std::variant &u) { - std::visit([&](const auto &x) { Visit(x); }, u); - } - template void Descend(std::variant &u) { - std::visit([&](auto &x) { Visit(x); }, u); - } - - template void Descend(const std::vector &xs) { - for (const auto &x : xs) { - Visit(x); - } - } - template void Descend(std::vector &xs) { - for (auto &x : xs) { - Visit(x); - } - } - - void Descend(const GenericExprWrapper &w) { Visit(w.v); } - void Descend(GenericExprWrapper &w) { Visit(w.v); } - - template void Descend(const Expr &expr) { Visit(expr.u); } - template void Descend(Expr &expr) { Visit(expr.u); } - - template - void Descend(const Operation &op) { - Visit(op.left()); - } - template - void Descend(Operation &op) { - Visit(op.left()); - } - template - void Descend(const Operation &op) { - Visit(op.left()); - Visit(op.right()); - } - template - void Descend(Operation &op) { - Visit(op.left()); - Visit(op.right()); - } - - void Descend(const Relational &r) { Visit(r.u); } - void Descend(Relational &r) { Visit(r.u); } - - template void Descend(const ImpliedDo &ido) { - Visit(ido.lower()); - Visit(ido.upper()); - Visit(ido.stride()); - Visit(ido.values()); - } - template void Descend(ImpliedDo &ido) { - Visit(ido.lower()); - Visit(ido.upper()); - Visit(ido.stride()); - Visit(ido.values()); - } - - template void Descend(const ArrayConstructorValue &av) { - Visit(av.u); - } - template void Descend(ArrayConstructorValue &av) { - Visit(av.u); - } - - template void Descend(const ArrayConstructorValues &avs) { - for (const auto &x : avs) { - Visit(x); - } - } - template void Descend(ArrayConstructorValues &avs) { - for (auto &x : avs) { - Visit(x); - } - } - - template - void Descend( - const ArrayConstructor> &ac) { - const ArrayConstructorValues> &base{ac}; - Visit(base); - Visit(ac.LEN()); - } - template - void Descend(ArrayConstructor> &ac) { - ArrayConstructorValues> &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 void Descend(const TypeParamInquiry &inq) { - Visit(inq.base()); - Visit(inq.parameter()); - } - template void Descend(TypeParamInquiry &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 void Descend(const Designator &designator) { - Visit(designator.u); - } - template void Descend(Designator &designator) { - Visit(designator.u); - } - - template void Descend(const Variable &var) { Visit(var.u); } - template void Descend(Variable &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 void Visit(const T &x) { return visitor_.Visit(x); } - template void Visit(T &x) { x = visitor_.Traverse(std::move(x)); } - - VISITOR &visitor_; -}; - -} -#endif // FORTRAN_EVALUATE_DESCENDER_H_ diff --git a/flang/lib/evaluate/fold.cc b/flang/lib/evaluate/fold.cc index 114d428c8778..211bf05efdd1 100644 --- a/flang/lib/evaluate/fold.cc +++ b/flang/lib/evaluate/fold.cc @@ -17,7 +17,6 @@ #include "characteristics.h" #include "common.h" #include "constant.h" -#include "descender.h" #include "expression.h" #include "formatting.h" #include "host.h" diff --git a/flang/lib/evaluate/traverse.h b/flang/lib/evaluate/traverse.h index 9705c1fc6bb1..a2fba6248444 100644 --- a/flang/lib/evaluate/traverse.h +++ b/flang/lib/evaluate/traverse.h @@ -16,14 +16,14 @@ #define FORTRAN_EVALUATE_TRAVERSE_H_ // 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 // can handle every type that can appear in or around an Expr<>. // Each of its overloads for operator() should be viewed as a *default* -// handler that can be overridden by the client. These default handlers -// simply forward the constituents of the argument to the client's -// visitor function object. +// handler; some of these must be overridden by the client to accomplish +// its particular task. // // The client (Visitor) of Traverse must define: // - a member function "Result Default();" @@ -32,13 +32,23 @@ // handler that reflects back into Traverse // - 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. +// +// 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 "../semantics/symbol.h" #include "../semantics/type.h" #include +#include namespace Fortran::evaluate { template class Traverse { @@ -249,40 +259,51 @@ private: Traverse traverse_; }; -template> -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> -struct AnyTraverse : public Base { +struct CombiningTraverse : public Base { using Base::Base; using Base::operator(); - static Result Combine(Result &&x, Result &&y) { - if (x) { - return std::move(x); + static Result Default() { + if constexpr (isConjunction && std::is_same_v) { + return true; } else { + return {}; + } + } + static Result Combine(Result &&x, Result &&y) { + if (static_cast(x) == isConjunction) { 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 +using AllTraverse = CombiningTraverse; + +// For searches over an expression: the first operator() result that +// is truthful is the final result. Works for Booleans, pointers, +// and std::optional<>. +template +using AnyTraverse = CombiningTraverse; + template> struct SetTraverse : public Base { using Base::Base; using Base::operator(); 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) { x.insert(std::move(value)); } +#else + x.merge(y); +#endif return std::move(x); } };