[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:
peter klausler 2019-09-20 11:02:17 -07:00
parent 686baf0b0e
commit d8c9b50fd6
5 changed files with 44 additions and 397 deletions

View File

@ -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++")

View File

@ -76,9 +76,8 @@ template bool IsConstantExpr(const Expr<SomeType> &);
// 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<IsInitialDataTargetHelper> {
public:
using Base = AllTraverse<IsInitialDataTargetHelper>;
using Base::operator();
IsInitialDataTargetHelper() : Base{*this} {}
@ -126,9 +125,6 @@ public:
return (*this)(x.left());
}
bool operator()(const Relational<SomeType> &) const { return false; }
private:
const semantics::Symbol &(*GetUltimate)(const semantics::Symbol &);
};
bool IsInitialDataTarget(const Expr<SomeType> &x) {

View File

@ -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 &param) {
Visit(param.GetExplicit());
}
void Descend(semantics::ParamValue &param) { 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_

View File

@ -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"

View File

@ -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<Visitor,Result> must define:
// - a member function "Result Default();"
@ -32,13 +32,23 @@
// handler that reflects back into Traverse<Visitor, Result>
// - 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 <set>
#include <type_traits>
namespace Fortran::evaluate {
template<typename Visitor, typename Result> class Traverse {
@ -249,40 +259,51 @@ private:
Traverse<Visitor, Result> traverse_;
};
template<typename Visitor, typename Base = TraverseBase<Visitor, bool>>
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,
template<typename Visitor, typename Result = bool, bool isConjunction = true,
typename Base = TraverseBase<Visitor, Result>>
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<Result, bool>) {
return true;
} else {
return {};
}
}
static Result Combine(Result &&x, Result &&y) {
if (static_cast<bool>(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<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,
typename Base = TraverseBase<Visitor, Set>>
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);
}
};