[flang] Pass tests
authorpeter klausler <pklausler@nvidia.com>
Mon, 1 Apr 2019 19:30:08 +0000 (12:30 -0700)
committerpeter klausler <pklausler@nvidia.com>
Mon, 1 Apr 2019 19:30:08 +0000 (12:30 -0700)
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
flang/lib/evaluate/complex.h
flang/lib/evaluate/formatting.cc
flang/lib/evaluate/formatting.h
flang/lib/evaluate/real.h
flang/lib/evaluate/static-data.h
flang/lib/semantics/expression.cc
flang/test/evaluate/expression.cc
flang/test/semantics/modfile13.f90

index b1d3bcc..1b67453 100644 (file)
@@ -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();
 }
 
index 26a47c1..53a13f9 100644 (file)
@@ -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.
index dff43d2..daaed49 100644 (file)
@@ -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<typename A> constexpr Precedence ToPrecedence{Precedence::Primary};
-template<typename T> constexpr Precedence ToPrecedence<Constant<T>>{Precedence::Constant};
+
+template<int KIND>
+constexpr Precedence ToPrecedence<Not<KIND>>{Precedence::NOT};
+template<int KIND>
+constexpr Precedence ToPrecedence<LogicalOperation<KIND>>{Precedence::Logical};
 template<typename T>
-constexpr Precedence ToPrecedence<Parentheses<T>>{Precedence::Parenthesize};
+constexpr Precedence ToPrecedence<Relational<T>>{Precedence::Relational};
 template<int KIND>
-constexpr Precedence ToPrecedence<ComplexConstructor<KIND>>{
-    Precedence::Parenthesize};
+constexpr Precedence ToPrecedence<Concat<KIND>>{Precedence::Additive};
 template<typename T>
-constexpr Precedence ToPrecedence<Negate<T>>{Precedence::Negate};
+constexpr Precedence ToPrecedence<Subtract<T>>{Precedence::Additive};
 template<typename T>
-constexpr Precedence ToPrecedence<Power<T>>{Precedence::Power};
+constexpr Precedence ToPrecedence<Add<T>>{Precedence::Additive};
 template<typename T>
-constexpr Precedence ToPrecedence<RealToIntPower<T>>{Precedence::Power};
+constexpr Precedence ToPrecedence<Divide<T>>{Precedence::Multiplicative};
 template<typename T>
 constexpr Precedence ToPrecedence<Multiply<T>>{Precedence::Multiplicative};
 template<typename T>
-constexpr Precedence ToPrecedence<Divide<T>>{Precedence::Multiplicative};
+constexpr Precedence ToPrecedence<RealToIntPower<T>>{Precedence::Power};
 template<typename T>
-constexpr Precedence ToPrecedence<Add<T>>{Precedence::Additive};
+constexpr Precedence ToPrecedence<Power<T>>{Precedence::Power};
 template<typename T>
-constexpr Precedence ToPrecedence<Subtract<T>>{Precedence::Additive};
-template<int KIND>
-constexpr Precedence ToPrecedence<Concat<KIND>>{Precedence::Additive};
+constexpr Precedence ToPrecedence<Negate<T>>{Precedence::Negate};
 template<typename T>
-constexpr Precedence ToPrecedence<Relational<T>>{Precedence::Relational};
-template<int KIND>
-constexpr Precedence ToPrecedence<LogicalOperation<KIND>>{Precedence::Logical};
+constexpr Precedence ToPrecedence<Constant<T>>{Precedence::Constant};
+template<typename T>
+constexpr Precedence ToPrecedence<Parentheses<T>>{Precedence::Parenthesize};
 template<int KIND>
-constexpr Precedence ToPrecedence<Not<KIND>>{Precedence::NOT};
+constexpr Precedence ToPrecedence<ComplexConstructor<KIND>>{
+    Precedence::Parenthesize};
 
 template<typename T>
 static constexpr Precedence GetPrecedence(const Expr<T> &expr) {
@@ -203,55 +205,45 @@ static constexpr Precedence GetPrecedence(const Expr<SomeType> &expr) {
       expr.u);
 }
 
+template<typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
+  static constexpr TypeCategory cat{T::category};
+  if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) {
+    if (expr.Rank() == 0) {
+      if (const auto *p{UnwrapExpr<Constant<T>>(expr)}) {
+        CHECK(p->size() == 1);
+        return (**p).IsNegative();
+      }
+    }
+  }
+  return false;
+}
+
+template<TypeCategory CAT>
+static bool IsNegatedScalarConstant(const Expr<SomeKind<CAT>> &expr) {
+  return std::visit(
+      [](const auto &x) { return IsNegatedScalarConstant(x); }, expr.u);
+}
+
 template<typename D, typename R, typename... O>
 std::ostream &Operation<D, R, O...>::AsFortran(std::ostream &o) const {
-  static constexpr Precedence lhsPrec{ToPrecedence<Operand<0>>};
+  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<D>};
-    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<Constant<Operand<0>>>(left())};
-        CHECK(p != nullptr);
-        lhsParens |= p->size() == 1 && (*p)->IsNegative();
-      }
-    }
-    if (lhsParens) {
-      o << '(';
-    }
-    o << left();
-    if (lhsParens) {
-      o << ')';
-    }
-    static constexpr Precedence rhsPrec{ToPrecedence<Operand<1>>};
-    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<Constant<Operand<1>>>(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<T> &implDo) {
 }
 
 template<typename T>
-std::ostream &EmitArray(std::ostream &o, const ArrayConstructorValues<T> &values) {
+std::ostream &EmitArray(
+    std::ostream &o, const ArrayConstructorValues<T> &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_) << '(';
index 21dd0fe..0da63c1 100644 (file)
 #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 <optional>
 #include <ostream>
index 591e69a..fd2aabb 100644 (file)
@@ -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.
index 6c8bf52..0db4d7d 100644 (file)
@@ -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.
index 2226c56..27c8174 100644 (file)
@@ -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
index de28e67..3b83b2c 100644 (file)
@@ -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};
index 16348c6..96dd7b6 100644 (file)
@@ -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.