From 9e9b9f077661f9679aa1311c5d3c41a01efed8f0 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Mon, 1 Apr 2019 12:30:08 -0700 Subject: [PATCH] [flang] Pass tests Original-commit: flang-compiler/f18@ffb057f262c63e877f5bebc9604f795804bc1042 Reviewed-on: https://github.com/flang-compiler/f18/pull/371 Tree-same-pre-rewrite: false --- flang/lib/FIR/statements.cc | 2 +- flang/lib/evaluate/complex.h | 2 +- flang/lib/evaluate/formatting.cc | 162 ++++++++++++++--------------- flang/lib/evaluate/formatting.h | 9 ++ flang/lib/evaluate/real.h | 2 +- flang/lib/evaluate/static-data.h | 2 +- flang/lib/semantics/expression.cc | 4 +- flang/test/evaluate/expression.cc | 4 +- flang/test/semantics/modfile13.f90 | 2 +- 9 files changed, 98 insertions(+), 91 deletions(-) diff --git a/flang/lib/FIR/statements.cc b/flang/lib/FIR/statements.cc index b1d3bccacb68..1b67453e4f0a 100644 --- a/flang/lib/FIR/statements.cc +++ b/flang/lib/FIR/statements.cc @@ -30,7 +30,7 @@ Addressable_impl *GetAddressable(Statement *stmt) { static std::string dump(const Expression &e) { std::stringstream stringStream; - stringStream << e.v; + stringStream << e; return stringStream.str(); } diff --git a/flang/lib/evaluate/complex.h b/flang/lib/evaluate/complex.h index 26a47c14435e..53a13f94cafa 100644 --- a/flang/lib/evaluate/complex.h +++ b/flang/lib/evaluate/complex.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +// Copyright (c) 2018-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. diff --git a/flang/lib/evaluate/formatting.cc b/flang/lib/evaluate/formatting.cc index dff43d253cf6..daaed498f9a8 100644 --- a/flang/lib/evaluate/formatting.cc +++ b/flang/lib/evaluate/formatting.cc @@ -133,50 +133,52 @@ std::ostream &ProcedureRef::AsFortran(std::ostream &o) const { // Operator precedence formatting; insert parentheses around operands // only when necessary. -enum class Precedence { - Primary, // don't parenthesize - Constant, // parenthesize if negative integer/real operand - Parenthesize, // (x), (real, imaginary) - DefinedUnary, - Negate, - Power, // ** which is right-associative - Multiplicative, // *, / - Additive, // +, -, // - Relational, +enum class Precedence { // in increasing order of precedence + DefinedBinary, + NOT, // which binds *less* tightly in Fortran than logicals & relations Logical, // .OR., .AND., .EQV., .NEQV. - NOT, // yes, this binds less tightly in Fortran than .OR./.AND./&c. do - DefinedBinary + Relational, + Additive, // +, -, // + Multiplicative, // *, / + Power, // **, which is right-associative unlike the other dyadic operators + Negate, + DefinedUnary, + Parenthesize, // (x), (real, imaginary) + Constant, // parenthesize if negative integer/real operand + Primary, // don't parenthesize }; template constexpr Precedence ToPrecedence{Precedence::Primary}; -template constexpr Precedence ToPrecedence>{Precedence::Constant}; + +template +constexpr Precedence ToPrecedence>{Precedence::NOT}; +template +constexpr Precedence ToPrecedence>{Precedence::Logical}; +template +constexpr Precedence ToPrecedence>{Precedence::Relational}; +template +constexpr Precedence ToPrecedence>{Precedence::Additive}; +template +constexpr Precedence ToPrecedence>{Precedence::Additive}; +template +constexpr Precedence ToPrecedence>{Precedence::Additive}; +template +constexpr Precedence ToPrecedence>{Precedence::Multiplicative}; +template +constexpr Precedence ToPrecedence>{Precedence::Multiplicative}; +template +constexpr Precedence ToPrecedence>{Precedence::Power}; +template +constexpr Precedence ToPrecedence>{Precedence::Power}; +template +constexpr Precedence ToPrecedence>{Precedence::Negate}; +template +constexpr Precedence ToPrecedence>{Precedence::Constant}; template constexpr Precedence ToPrecedence>{Precedence::Parenthesize}; template constexpr Precedence ToPrecedence>{ Precedence::Parenthesize}; -template -constexpr Precedence ToPrecedence>{Precedence::Negate}; -template -constexpr Precedence ToPrecedence>{Precedence::Power}; -template -constexpr Precedence ToPrecedence>{Precedence::Power}; -template -constexpr Precedence ToPrecedence>{Precedence::Multiplicative}; -template -constexpr Precedence ToPrecedence>{Precedence::Multiplicative}; -template -constexpr Precedence ToPrecedence>{Precedence::Additive}; -template -constexpr Precedence ToPrecedence>{Precedence::Additive}; -template -constexpr Precedence ToPrecedence>{Precedence::Additive}; -template -constexpr Precedence ToPrecedence>{Precedence::Relational}; -template -constexpr Precedence ToPrecedence>{Precedence::Logical}; -template -constexpr Precedence ToPrecedence>{Precedence::NOT}; template static constexpr Precedence GetPrecedence(const Expr &expr) { @@ -203,55 +205,45 @@ static constexpr Precedence GetPrecedence(const Expr &expr) { expr.u); } +template static bool IsNegatedScalarConstant(const Expr &expr) { + static constexpr TypeCategory cat{T::category}; + if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) { + if (expr.Rank() == 0) { + if (const auto *p{UnwrapExpr>(expr)}) { + CHECK(p->size() == 1); + return (**p).IsNegative(); + } + } + } + return false; +} + +template +static bool IsNegatedScalarConstant(const Expr> &expr) { + return std::visit( + [](const auto &x) { return IsNegatedScalarConstant(x); }, expr.u); +} + template std::ostream &Operation::AsFortran(std::ostream &o) const { - static constexpr Precedence lhsPrec{ToPrecedence>}; + Precedence lhsPrec{GetPrecedence(left())}; o << derived().Prefix(); if constexpr (operands == 1) { - bool parens{lhsPrec != Precedence::Primary}; - if (parens) { - o << '('; - } - o << left(); - if (parens) { - o << ')'; - } + bool parens{lhsPrec < Precedence::Constant}; + o << (parens ? "(" : "") << left() << (parens ? ")" : ""); } else { static constexpr Precedence thisPrec{ToPrecedence}; - bool lhsParens{lhsPrec == Precedence::Parenthesize || lhsPrec > thisPrec || - (lhsPrec == thisPrec && lhsPrec == Precedence::Power)}; - if constexpr (lhsPrec == Precedence::Constant && thisPrec != Precedence::Additive) { - static constexpr TypeCategory cat{Operand<0>::Result::category}; - if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) { - const auto *p{UnwrapExpr>>(left())}; - CHECK(p != nullptr); - lhsParens |= p->size() == 1 && (*p)->IsNegative(); - } - } - if (lhsParens) { - o << '('; - } - o << left(); - if (lhsParens) { - o << ')'; - } - static constexpr Precedence rhsPrec{ToPrecedence>}; - bool rhsParens{rhsPrec == Precedence::Parenthesize || rhsPrec == Precedence::Negate || rhsPrec > thisPrec}; - if constexpr (rhsPrec == Precedence::Constant) { - static constexpr TypeCategory cat{Operand<1>::Result::category}; - if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) { - const auto *p{UnwrapExpr>>(right())}; - CHECK(p != nullptr); - rhsParens |= p->size() == 1 && (*p)->IsNegative(); - } - } - if (rhsParens) { - o << '('; - } - o << derived().Infix() << right(); - if (rhsParens) { - o << ')'; - } + bool lhsParens{lhsPrec == Precedence::Parenthesize || lhsPrec < thisPrec || + (lhsPrec == thisPrec && lhsPrec == Precedence::Power) || + (thisPrec != Precedence::Additive && lhsPrec == Precedence::Constant && + IsNegatedScalarConstant(left()))}; + o << (lhsParens ? "(" : "") << left() << (lhsParens ? ")" : ""); + o << derived().Infix(); + Precedence rhsPrec{GetPrecedence(right())}; + bool rhsParens{rhsPrec == Precedence::Parenthesize || + rhsPrec == Precedence::Negate || rhsPrec < thisPrec || + (rhsPrec == Precedence::Constant && IsNegatedScalarConstant(right()))}; + o << (rhsParens ? "(" : "") << right() << (rhsParens ? ")" : ""); } return o << derived().Suffix(); } @@ -323,7 +315,8 @@ std::ostream &EmitArray(std::ostream &o, const ImpliedDo &implDo) { } template -std::ostream &EmitArray(std::ostream &o, const ArrayConstructorValues &values) { +std::ostream &EmitArray( + std::ostream &o, const ArrayConstructorValues &values) { const char *sep{""}; for (const auto &value : values.values()) { o << sep; @@ -498,7 +491,9 @@ std::ostream &Triplet::AsFortran(std::ostream &o) const { return o; } -std::ostream &Subscript::AsFortran(std::ostream &o) const { return EmitVar(o, u); } +std::ostream &Subscript::AsFortran(std::ostream &o) const { + return EmitVar(o, u); +} std::ostream &ArrayRef::AsFortran(std::ostream &o) const { EmitVar(o, base_); @@ -532,12 +527,15 @@ std::ostream &CoarrayRef::AsFortran(std::ostream &o) const { separator = ','; } if (team_.has_value()) { - EmitVar(o << separator, team_, teamIsTeamNumber_ ? "TEAM_NUMBER=" : "TEAM="); + EmitVar( + o << separator, team_, teamIsTeamNumber_ ? "TEAM_NUMBER=" : "TEAM="); } return o << ']'; } -std::ostream &DataRef::AsFortran(std::ostream &o) const { return EmitVar(o, u); } +std::ostream &DataRef::AsFortran(std::ostream &o) const { + return EmitVar(o, u); +} std::ostream &Substring::AsFortran(std::ostream &o) const { EmitVar(o, parent_) << '('; diff --git a/flang/lib/evaluate/formatting.h b/flang/lib/evaluate/formatting.h index 21dd0fe5fa54..0da63c130137 100644 --- a/flang/lib/evaluate/formatting.h +++ b/flang/lib/evaluate/formatting.h @@ -15,6 +15,15 @@ #ifndef FORTRAN_EVALUATE_FORMATTING_H_ #define FORTRAN_EVALUATE_FORMATTING_H_ +// It is inconvenient in C++ to have std::ostream::operator<<() as a direct +// friend function of a class template with many instantiations, so the +// various representational class templates in lib/evaluate format themselves +// via AsFortran(std::ostream &) member functions, which the operator<<() +// overload below will call. +// +// This header is meant to be included by the headers that define the several +// representational class templates that need it, not by external clients. + #include "../common/indirection.h" #include #include diff --git a/flang/lib/evaluate/real.h b/flang/lib/evaluate/real.h index 591e69a46388..fd2aabbd0957 100644 --- a/flang/lib/evaluate/real.h +++ b/flang/lib/evaluate/real.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +// Copyright (c) 2018-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. diff --git a/flang/lib/evaluate/static-data.h b/flang/lib/evaluate/static-data.h index 6c8bf52aaf62..0db4d7dc5287 100644 --- a/flang/lib/evaluate/static-data.h +++ b/flang/lib/evaluate/static-data.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +// Copyright (c) 2018-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. diff --git a/flang/lib/semantics/expression.cc b/flang/lib/semantics/expression.cc index 2226c56b030a..27c8174b686c 100644 --- a/flang/lib/semantics/expression.cc +++ b/flang/lib/semantics/expression.cc @@ -1951,7 +1951,7 @@ void ExprChecker::Enter(const parser::Expr &expr) { if (!expr.typedExpr) { if (MaybeExpr checked{AnalyzeExpr(context_, expr)}) { #if PMKDEBUG -// checked->AsFortran(std::cout << "checked expression: ") << '\n'; +// std::cout << "checked expression: " << *checked << '\n'; #endif expr.typedExpr.reset( new evaluate::GenericExprWrapper{std::move(*checked)}); @@ -1967,7 +1967,7 @@ void ExprChecker::Enter(const parser::Expr &expr) { void ExprChecker::Enter(const parser::Variable &var) { #if PMKDEBUG if (MaybeExpr checked{AnalyzeExpr(context_, var)}) { -// checked->AsFortran(std::cout << "checked variable: ") << '\n'; +// std::cout << "checked variable: " << *checked << '\n'; #else if (AnalyzeExpr(context_, var)) { #endif diff --git a/flang/test/evaluate/expression.cc b/flang/test/evaluate/expression.cc index de28e6725cfe..3b83b2c52397 100644 --- a/flang/test/evaluate/expression.cc +++ b/flang/test/evaluate/expression.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +// Copyright (c) 2018-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. @@ -37,7 +37,7 @@ int main() { MATCH("-1_4", AsFortran(-DefaultIntegerExpr{1})); auto ex1{ DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * -DefaultIntegerExpr{4}}; - MATCH("2_4+3_4*(-4_4))", AsFortran(ex1)); + MATCH("2_4+3_4*(-4_4)", AsFortran(ex1)); Fortran::parser::CharBlock src; Fortran::parser::ContextualMessages messages{src, nullptr}; FoldingContext context{messages}; diff --git a/flang/test/semantics/modfile13.f90 b/flang/test/semantics/modfile13.f90 index 16348c686c19..96dd7b66c596 100644 --- a/flang/test/semantics/modfile13.f90 +++ b/flang/test/semantics/modfile13.f90 @@ -1,4 +1,4 @@ -! Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +! Copyright (c) 2018-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.