From: peter klausler Date: Tue, 18 Sep 2018 18:29:01 +0000 (-0700) Subject: [flang] Use dynamic default REAL kind for conversions that were static X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1322e6090f3c94dedfb4cfbf0624cecba464e116;p=platform%2Fupstream%2Fllvm.git [flang] Use dynamic default REAL kind for conversions that were static Original-commit: flang-compiler/f18@9a83fbbe95caf0596a4618938a177b0be1556acb Reviewed-on: https://github.com/flang-compiler/f18/pull/195 Tree-same-pre-rewrite: false --- diff --git a/flang/lib/evaluate/tools.cc b/flang/lib/evaluate/tools.cc index 13a3e42..41acb14 100644 --- a/flang/lib/evaluate/tools.cc +++ b/flang/lib/evaluate/tools.cc @@ -25,17 +25,18 @@ namespace Fortran::evaluate { // Conversions of complex component expressions to REAL. ConvertRealOperandsResult ConvertRealOperands( parser::ContextualMessages &messages, Expr &&x, - Expr &&y) { + Expr &&y, int defaultRealKind) { return std::visit( - common::visitors{ - [&](Expr &&ix, - Expr &&iy) -> ConvertRealOperandsResult { - // Can happen in a CMPLX() constructor. Per F'2018, - // both integer operands are converted to default REAL. - return {AsSameKindExprs( - AsCategoryExpr(ConvertToType(std::move(ix))), - AsCategoryExpr(ConvertToType(std::move(iy))))}; - }, + common::visitors{[&](Expr &&ix, Expr &&iy) + -> ConvertRealOperandsResult { + // Can happen in a CMPLX() constructor. Per F'2018, + // both integer operands are converted to default REAL. + return {AsSameKindExprs( + ConvertToKind( + defaultRealKind, std::move(ix)), + ConvertToKind( + defaultRealKind, std::move(iy)))}; + }, [&](Expr &&ix, Expr &&ry) -> ConvertRealOperandsResult { return {AsSameKindExprs( @@ -54,14 +55,18 @@ ConvertRealOperandsResult ConvertRealOperands( [&](Expr &&ix, BOZLiteralConstant &&by) -> ConvertRealOperandsResult { return {AsSameKindExprs( - AsCategoryExpr(ConvertToType(std::move(ix))), - AsCategoryExpr(ConvertToType(std::move(by))))}; + ConvertToKind( + defaultRealKind, std::move(ix)), + ConvertToKind( + defaultRealKind, std::move(by)))}; }, [&](BOZLiteralConstant &&bx, Expr &&iy) -> ConvertRealOperandsResult { return {AsSameKindExprs( - AsCategoryExpr(ConvertToType(std::move(bx))), - AsCategoryExpr(ConvertToType(std::move(iy))))}; + ConvertToKind( + defaultRealKind, std::move(bx)), + ConvertToKind( + defaultRealKind, std::move(iy)))}; }, [&](Expr &&rx, BOZLiteralConstant &&by) -> ConvertRealOperandsResult { @@ -118,9 +123,9 @@ std::optional> MixedRealLeft( std::optional> ConstructComplex( parser::ContextualMessages &messages, Expr &&real, - Expr &&imaginary) { + Expr &&imaginary, int defaultRealKind) { if (auto converted{ConvertRealOperands( - messages, std::move(real), std::move(imaginary))}) { + messages, std::move(real), std::move(imaginary), defaultRealKind)}) { return {std::visit( [](auto &&pair) { return MakeComplex(std::move(pair[0]), std::move(pair[1])); @@ -132,10 +137,10 @@ std::optional> ConstructComplex( std::optional> ConstructComplex( parser::ContextualMessages &messages, std::optional> &&real, - std::optional> &&imaginary) { + std::optional> &&imaginary, int defaultRealKind) { if (auto parts{common::AllPresent(std::move(real), std::move(imaginary))}) { return ConstructComplex(messages, std::move(std::get<0>(*parts)), - std::move(std::get<1>(*parts))); + std::move(std::get<1>(*parts)), defaultRealKind); } return std::nullopt; } diff --git a/flang/lib/evaluate/tools.h b/flang/lib/evaluate/tools.h index ba0453f..a0061c0 100644 --- a/flang/lib/evaluate/tools.h +++ b/flang/lib/evaluate/tools.h @@ -195,11 +195,34 @@ Expr> ConvertTo( to.u); } -template using SameExprs = std::array, N>; +// Convert an expression of some known category to a dynamically chosen +// kind of some category (usually but not necessarily distinct). +template struct ConvertToKindHelper { + using Result = std::optional>>; + static constexpr std::size_t Types{std::tuple_size_v>}; + ConvertToKindHelper(int k, VALUE &&x) : kind{k}, value{std::move(x)} {} + template Result Test() { + using Ty = std::tuple_element_t>; + if (kind == Ty::kind) { + return std::make_optional( + AsCategoryExpr(ConvertToType(std::move(value)))); + } + return std::nullopt; + } + int kind; + VALUE value; +}; + +template +Expr> ConvertToKind(int kind, VALUE &&x) { + return *common::SearchDynamicTypes( + ConvertToKindHelper{kind, std::move(x)}); +} // Given a type category CAT, SameKindExprs is a variant that // holds an arrays of expressions of the same supported kind in that // category. +template using SameExprs = std::array, N>; template struct SameKindExprsHelper { template using SameExprs = std::array, N>; }; @@ -240,17 +263,20 @@ SameKindExprs AsSameKindExprs( // same kind of REAL. using ConvertRealOperandsResult = std::optional>; -ConvertRealOperandsResult ConvertRealOperands( - parser::ContextualMessages &, Expr &&, Expr &&); +ConvertRealOperandsResult ConvertRealOperands(parser::ContextualMessages &, + Expr &&, Expr &&, + int defaultRealKind = DefaultReal::kind); // Per F'2018 R718, if both components are INTEGER, they are both converted // to default REAL and the result is default COMPLEX. Otherwise, the // kind of the result is the kind of most precise REAL component, and the other // component is converted if necessary to its type. -std::optional> ConstructComplex( - parser::ContextualMessages &, Expr &&, Expr &&); std::optional> ConstructComplex(parser::ContextualMessages &, - std::optional> &&, std::optional> &&); + Expr &&, Expr &&, + int defaultRealKind = DefaultReal::kind); +std::optional> ConstructComplex(parser::ContextualMessages &, + std::optional> &&, std::optional> &&, + int defaultRealKind = DefaultReal::kind); template Expr> ScalarConstantToExpr(const A &x) { using Ty = TypeOf; diff --git a/flang/lib/semantics/expression.cc b/flang/lib/semantics/expression.cc index eb71847..accc561 100644 --- a/flang/lib/semantics/expression.cc +++ b/flang/lib/semantics/expression.cc @@ -422,8 +422,9 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::ComplexPart &x) { } MaybeExpr ExprAnalyzer::Analyze(const parser::ComplexLiteralConstant &z) { - return AsMaybeExpr(ConstructComplex( - context.messages, Analyze(std::get<0>(z.t)), Analyze(std::get<1>(z.t)))); + return AsMaybeExpr( + ConstructComplex(context.messages, Analyze(std::get<0>(z.t)), + Analyze(std::get<1>(z.t)), defaults.defaultRealKind)); } MaybeExpr ExprAnalyzer::Analyze(const parser::CharLiteralConstant &x) { @@ -871,7 +872,7 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::Subtract &x) { MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::ComplexConstructor &x) { return AsMaybeExpr(ConstructComplex(context.messages, AnalyzeHelper(*this, *std::get<0>(x.t)), - AnalyzeHelper(*this, *std::get<1>(x.t)))); + AnalyzeHelper(*this, *std::get<1>(x.t)), defaults.defaultRealKind)); } MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::Concat &x) {