diff --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h --- a/flang/include/flang/Evaluate/expression.h +++ b/flang/include/flang/Evaluate/expression.h @@ -202,15 +202,11 @@ struct Convert : public Operation, TO, SomeKind> { // Fortran doesn't have conversions between kinds of CHARACTER apart from // assignments, and in those the data must be convertible to/from 7-bit ASCII. - // Conversions between kinds of COMPLEX are represented piecewise. static_assert(((TO::category == TypeCategory::Integer || TO::category == TypeCategory::Real) && (FROMCAT == TypeCategory::Integer || FROMCAT == TypeCategory::Real)) || - (TO::category == TypeCategory::Character && - FROMCAT == TypeCategory::Character) || - (TO::category == TypeCategory::Logical && - FROMCAT == TypeCategory::Logical)); + TO::category == FROMCAT); using Result = TO; using Operand = SomeKind; using Base = Operation; @@ -542,8 +538,7 @@ private: // N.B. Real->Complex and Complex->Real conversions are done with CMPLX - // and part access operations (resp.). Conversions between kinds of - // Complex are done via decomposition to Real and reconstruction. + // and part access operations (resp.). using Conversions = std::variant, Convert>; using Operations = std::variant, Parentheses, @@ -563,12 +558,10 @@ using Result = Type; EVALUATE_UNION_CLASS_BOILERPLATE(Expr) explicit Expr(const Scalar &x) : u{Constant{x}} {} - - // Note that many COMPLEX operations are represented as REAL operations - // over their components (viz., conversions, negation, add, and subtract). - using Operations = - std::variant, Multiply, Divide, - Power, RealToIntPower, ComplexConstructor>; + using Operations = std::variant, Negate, + Convert, Add, Subtract, + Multiply, Divide, Power, RealToIntPower, + ComplexConstructor>; using Others = std::variant, ArrayConstructor, Designator, FunctionRef>; @@ -614,6 +607,7 @@ using Operand = typename Base::template Operand<0>; static_assert(Operand::category == TypeCategory::Integer || Operand::category == TypeCategory::Real || + Operand::category == TypeCategory::Complex || Operand::category == TypeCategory::Character); CLASS_BOILERPLATE(Relational) Relational( @@ -625,9 +619,8 @@ }; template <> class Relational { - // COMPLEX data are compared piecewise. - using DirectlyComparableTypes = - common::CombineTuples; + using DirectlyComparableTypes = common::CombineTuples; public: using Result = LogicalResult; diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -331,49 +331,29 @@ template Expr ConvertToType(Expr> &&x) { static_assert(IsSpecificIntrinsicType); - if constexpr (FROMCAT != TO::category) { - if constexpr (TO::category == TypeCategory::Complex) { - using Part = typename TO::Part; - Scalar zero; - return Expr{ComplexConstructor{ - ConvertToType(std::move(x)), Expr{Constant{zero}}}}; - } else if constexpr (FROMCAT == TypeCategory::Complex) { - // Extract and convert the real component of a complex value - return std::visit( - [&](auto &&z) { - using ZType = ResultType; - using Part = typename ZType::Part; - return ConvertToType(Expr{ - Expr{ComplexComponent{false, std::move(z)}}}); - }, - std::move(x.u)); - } else { - return Expr{Convert{std::move(x)}}; - } - } else { - // Same type category + if constexpr (FROMCAT == TO::category) { if (auto *already{std::get_if>(&x.u)}) { return std::move(*already); - } - if constexpr (TO::category == TypeCategory::Complex) { - // Extract, convert, and recombine the components. - return Expr{std::visit( - [](auto &z) { - using FromType = ResultType; - using FromPart = typename FromType::Part; - using FromGeneric = SomeKind; - using ToPart = typename TO::Part; - Convert re{Expr{ - Expr{ComplexComponent{false, z}}}}; - Convert im{Expr{ - Expr{ComplexComponent{true, z}}}}; - return ComplexConstructor{ - AsExpr(std::move(re)), AsExpr(std::move(im))}; - }, - x.u)}; } else { - return Expr{Convert{std::move(x)}}; + return Expr{Convert{std::move(x)}}; } + } else if constexpr (TO::category == TypeCategory::Complex) { + using Part = typename TO::Part; + Scalar zero; + return Expr{ComplexConstructor{ + ConvertToType(std::move(x)), Expr{Constant{zero}}}}; + } else if constexpr (FROMCAT == TypeCategory::Complex) { + // Extract and convert the real component of a complex value + return std::visit( + [&](auto &&z) { + using ZType = ResultType; + using Part = typename ZType::Part; + return ConvertToType(Expr{ + Expr{ComplexComponent{false, std::move(z)}}}); + }, + std::move(x.u)); + } else { + return Expr{Convert{std::move(x)}}; } } @@ -523,24 +503,11 @@ } // Combine two expressions of the same specific numeric type with an operation -// to produce a new expression. Implements piecewise addition and subtraction -// for COMPLEX. +// to produce a new expression. template