[flang] Work around a gcc-7.2 specific build bug by recoding with a better approach

Original-commit: flang-compiler/f18@bc2b4015b0
Reviewed-on: https://github.com/flang-compiler/f18/pull/785
This commit is contained in:
peter klausler 2019-10-22 10:34:05 -07:00
parent 4f761d601e
commit f3ae44f645
4 changed files with 23 additions and 32 deletions

View File

@ -28,9 +28,9 @@ namespace Fortran::evaluate {
// able to fold it (yet) into a known constant value; specifically,
// the expression may reference derived type kind parameters whose values
// are not yet known.
class IsConstantExprHelper : public AllTraverse<IsConstantExprHelper> {
class IsConstantExprHelper : public AllTraverse<IsConstantExprHelper, true> {
public:
using Base = AllTraverse<IsConstantExprHelper>;
using Base = AllTraverse<IsConstantExprHelper, true>;
IsConstantExprHelper() : Base{*this} {}
using Base::operator();
@ -76,8 +76,8 @@ template bool IsConstantExpr(const Expr<SomeInteger> &);
// This code determines whether an expression is allowable as the static
// data address used to initialize a pointer with "=> x". See C765.
struct IsInitialDataTargetHelper
: public AllTraverse<IsInitialDataTargetHelper> {
using Base = AllTraverse<IsInitialDataTargetHelper>;
: public AllTraverse<IsInitialDataTargetHelper, true> {
using Base = AllTraverse<IsInitialDataTargetHelper, true>;
using Base::operator();
explicit IsInitialDataTargetHelper(parser::ContextualMessages &m)
: Base{*this}, messages_{m} {}

View File

@ -660,33 +660,20 @@ bool IsProcedurePointer(const Expr<SomeType> &expr) {
}
// IsNullPointer()
static bool IsNullPointer(const ProcedureRef &call) {
auto *intrinsic{call.proc().GetSpecificIntrinsic()};
return intrinsic &&
intrinsic->characteristics.value().attrs.test(
characteristics::Procedure::Attr::NullPointer);
}
template<TypeCategory CAT, int KIND>
bool IsNullPointer(const Expr<Type<CAT, KIND>> &expr) {
const auto *call{std::get_if<FunctionRef<Type<CAT, KIND>>>(&expr.u)};
return call && IsNullPointer(*call);
}
template<TypeCategory CAT> bool IsNullPointer(const Expr<SomeKind<CAT>> &expr) {
return std::visit([](const auto &x) { return IsNullPointer(x); }, expr.u);
}
bool IsNullPointer(const Expr<SomeDerived> &expr) {
const auto *call{std::get_if<FunctionRef<SomeDerived>>(&expr.u)};
return call && IsNullPointer(*call);
}
struct IsNullPointerHelper : public AllTraverse<IsNullPointerHelper, false> {
using Base = AllTraverse<IsNullPointerHelper, false>;
IsNullPointerHelper() : Base(*this) {}
using Base::operator();
bool operator()(const ProcedureRef &call) const {
auto *intrinsic{call.proc().GetSpecificIntrinsic()};
return intrinsic &&
intrinsic->characteristics.value().attrs.test(
characteristics::Procedure::Attr::NullPointer);
}
bool operator()(const NullPointer &) const { return true; }
};
bool IsNullPointer(const Expr<SomeType> &expr) {
return std::visit(
common::visitors{
[](const NullPointer &) { return true; },
[](const BOZLiteralConstant &) { return false; },
[](const ProcedureDesignator &) { return false; },
[](const auto &x) { return IsNullPointer(x); },
},
expr.u);
return IsNullPointerHelper{}(expr);
}
// GetLastTarget()

View File

@ -247,11 +247,12 @@ private:
// For validity checks across an expression: if any operator() result is
// false, so is the overall result.
template<typename Visitor, typename Base = Traverse<Visitor, bool>>
template<typename Visitor, bool DefaultValue,
typename Base = Traverse<Visitor, bool>>
struct AllTraverse : public Base {
AllTraverse(Visitor &v) : Base{v} {}
using Base::operator();
static bool Default() { return true; }
static bool Default() { return DefaultValue; }
static bool Combine(bool x, bool y) { return x && y; }
};

View File

@ -64,6 +64,7 @@ add_executable(integer-test
target_link_libraries(integer-test
FortranEvaluateTesting
FortranEvaluate
FortranSemantics
)
add_executable(intrinsics-test
@ -85,6 +86,8 @@ add_executable(logical-test
target_link_libraries(logical-test
FortranEvaluateTesting
FortranEvaluate
FortranSemantics
)
# GCC -fno-exceptions breaks the fenv.h interfaces needed to capture