[flang] merge with master
authorpeter klausler <pklausler@nvidia.com>
Wed, 24 Oct 2018 00:05:24 +0000 (17:05 -0700)
committerpeter klausler <pklausler@nvidia.com>
Fri, 26 Oct 2018 22:19:10 +0000 (15:19 -0700)
Original-commit: flang-compiler/f18@53f15da06aab657e94ecea342ef77a07e5e38a27
Reviewed-on: https://github.com/flang-compiler/f18/pull/219
Tree-same-pre-rewrite: false

flang/lib/evaluate/fold.h
flang/lib/semantics/expression.cc
flang/tools/f18/f18.cc

index 2ea8953..a490404 100644 (file)
@@ -43,81 +43,98 @@ template<typename A> Expr<ResultType<A>> Fold(FoldingContext &, A &&x) {
 
 template<typename A> Expr<A> Fold(FoldingContext &context, Expr<A> &&expr) {
   static_assert(A::isSpecificIntrinsicType);
-  return std::visit([&](auto &&x) -> Expr<A> { return Fold(context, std::move(x)); }, std::move(expr.u));
+  return std::visit(
+      [&](auto &&x) -> Expr<A> { return Fold(context, std::move(x)); },
+      std::move(expr.u));
 }
 
 template<TypeCategory CAT>
-Expr<SomeKind<CAT>>
-Fold(FoldingContext &context, Expr<SomeKind<CAT>> &&expr) {
-  return std::visit([&](auto &&x) -> Expr<SomeKind<CAT>> {
-    if constexpr (CAT == TypeCategory::Derived) {
-      return Fold(context, std::move(x));
-    } else {
-      return Expr<SomeKind<CAT>>{Fold(context, std::move(x))};
-    }
-  }, std::move(expr.u));
+Expr<SomeKind<CAT>> Fold(FoldingContext &context, Expr<SomeKind<CAT>> &&expr) {
+  return std::visit(
+      [&](auto &&x) -> Expr<SomeKind<CAT>> {
+        if constexpr (CAT == TypeCategory::Derived) {
+          return Fold(context, std::move(x));
+        } else {
+          return Expr<SomeKind<CAT>>{Fold(context, std::move(x))};
+        }
+      },
+      std::move(expr.u));
 }
 
-template<> inline Expr<SomeType> Fold(FoldingContext &context, Expr<SomeType> &&expr) {
-  return std::visit([&](auto &&x) -> Expr<SomeType> {
-    if constexpr (std::is_same_v<std::decay_t<decltype(x)>, BOZLiteralConstant>) {
-      return std::move(expr);
-    } else {
-      return Expr<SomeType>{Fold(context, std::move(x))};
-    }
-  }, std::move(expr.u));
+template<>
+inline Expr<SomeType> Fold(FoldingContext &context, Expr<SomeType> &&expr) {
+  return std::visit(
+      [&](auto &&x) -> Expr<SomeType> {
+        if constexpr (std::is_same_v<std::decay_t<decltype(x)>,
+                          BOZLiteralConstant>) {
+          return std::move(expr);
+        } else {
+          return Expr<SomeType>{Fold(context, std::move(x))};
+        }
+      },
+      std::move(expr.u));
 }
 
 // Unary operations
 
-template<typename TO, TypeCategory FROMCAT> Expr<TO> Fold(FoldingContext &context, Convert<TO, FROMCAT> &&convert) {
-  return std::visit([&](auto &kindExpr) -> Expr<TO> {
-    kindExpr = Fold(context, std::move(kindExpr));
-    using Operand = ResultType<decltype(kindExpr)>;
-    if (const auto *c{std::get_if<Constant<Operand>>(&kindExpr.u)}) {
-      if constexpr (TO::category == TypeCategory::Integer) {
-        if constexpr (Operand::category == TypeCategory::Integer) {
-          auto converted{Scalar<TO>::ConvertSigned(c->value)};
-          if (converted.overflow) {
-            context.messages.Say("INTEGER(%d) to INTEGER(%d) conversion overflowed"_en_US, Operand::kind, TO::kind);
-          }
-          return Expr<TO>{Constant<TO>{std::move(converted.value)}};
-        } else if constexpr (Operand::category == TypeCategory::Real) {
-          auto converted{c->value.template ToInteger<Scalar<TO>>()};
-          if (converted.flags.test(RealFlag::InvalidArgument)) {
-            context.messages.Say(
-                "REAL(%d) to INTEGER(%d) conversion: invalid argument"_en_US, Operand::kind, TO::kind);
-          } else if (converted.flags.test(RealFlag::Overflow)) {
-            context.messages.Say(
-                "REAL(%d) to INTEGER(%d) conversion overflowed"_en_US, Operand::kind, TO::kind);
-          }
-          return Expr<TO>{Constant<TO>{std::move(converted.value)}};
-        }
-      } else if constexpr (TO::category == TypeCategory::Real) {
-        if constexpr (Operand::category == TypeCategory::Integer) {
-          auto converted{Scalar<TO>::FromInteger(c->value)};
-          if (!converted.flags.empty()) {
-            char buffer[64];
-            std::snprintf(buffer, sizeof buffer, "INTEGER(%d) to REAL(%d) conversion", Operand::kind, TO::kind);
-            RealFlagWarnings(context, converted.flags, buffer);
-          }
-          return Expr<TO>{Constant<TO>{std::move(converted.value)}};
-        } else if constexpr (Operand::category == TypeCategory::Real) {
-          auto converted{Scalar<TO>::Convert(c->value)};
-          if (!converted.flags.empty()) {
-            char buffer[64];
-            std::snprintf(buffer, sizeof buffer, "REAL(%d) to REAL(%d) conversion", Operand::kind, TO::kind);
-            RealFlagWarnings(context, converted.flags, buffer);
+template<typename TO, TypeCategory FROMCAT>
+Expr<TO> Fold(FoldingContext &context, Convert<TO, FROMCAT> &&convert) {
+  return std::visit(
+      [&](auto &kindExpr) -> Expr<TO> {
+        kindExpr = Fold(context, std::move(kindExpr));
+        using Operand = ResultType<decltype(kindExpr)>;
+        if (const auto *c{std::get_if<Constant<Operand>>(&kindExpr.u)}) {
+          if constexpr (TO::category == TypeCategory::Integer) {
+            if constexpr (Operand::category == TypeCategory::Integer) {
+              auto converted{Scalar<TO>::ConvertSigned(c->value)};
+              if (converted.overflow) {
+                context.messages.Say(
+                    "INTEGER(%d) to INTEGER(%d) conversion overflowed"_en_US,
+                    Operand::kind, TO::kind);
+              }
+              return Expr<TO>{Constant<TO>{std::move(converted.value)}};
+            } else if constexpr (Operand::category == TypeCategory::Real) {
+              auto converted{c->value.template ToInteger<Scalar<TO>>()};
+              if (converted.flags.test(RealFlag::InvalidArgument)) {
+                context.messages.Say(
+                    "REAL(%d) to INTEGER(%d) conversion: invalid argument"_en_US,
+                    Operand::kind, TO::kind);
+              } else if (converted.flags.test(RealFlag::Overflow)) {
+                context.messages.Say(
+                    "REAL(%d) to INTEGER(%d) conversion overflowed"_en_US,
+                    Operand::kind, TO::kind);
+              }
+              return Expr<TO>{Constant<TO>{std::move(converted.value)}};
+            }
+          } else if constexpr (TO::category == TypeCategory::Real) {
+            if constexpr (Operand::category == TypeCategory::Integer) {
+              auto converted{Scalar<TO>::FromInteger(c->value)};
+              if (!converted.flags.empty()) {
+                char buffer[64];
+                std::snprintf(buffer, sizeof buffer,
+                    "INTEGER(%d) to REAL(%d) conversion", Operand::kind,
+                    TO::kind);
+                RealFlagWarnings(context, converted.flags, buffer);
+              }
+              return Expr<TO>{Constant<TO>{std::move(converted.value)}};
+            } else if constexpr (Operand::category == TypeCategory::Real) {
+              auto converted{Scalar<TO>::Convert(c->value)};
+              if (!converted.flags.empty()) {
+                char buffer[64];
+                std::snprintf(buffer, sizeof buffer,
+                    "REAL(%d) to REAL(%d) conversion", Operand::kind, TO::kind);
+                RealFlagWarnings(context, converted.flags, buffer);
+              }
+              return Expr<TO>{Constant<TO>{std::move(converted.value)}};
+            }
+          } else if constexpr (TO::category == TypeCategory::Logical &&
+              Operand::category == TypeCategory::Logical) {
+            return Expr<TO>{Constant<TO>{c->value.IsTrue()}};
           }
-          return Expr<TO>{Constant<TO>{std::move(converted.value)}};
         }
-      } else if constexpr (TO::category == TypeCategory::Logical &&
-                           Operand::category == TypeCategory::Logical) {
-        return Expr<TO>{Constant<TO>{c->value.IsTrue()}};
-      }
-    }
-    return Expr<TO>{std::move(convert)};
-  }, convert.left().u);
+        return Expr<TO>{std::move(convert)};
+      },
+      convert.left().u);
 }
 
 template<typename T> Expr<T> Fold(FoldingContext &context, Negate<T> &&x) {
@@ -131,13 +148,17 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Negate<T> &&x) {
       }
       return Expr<T>{Constant<T>{std::move(negated.value)}};
     } else {
-      return Expr<T>{Constant<T>{c->value.Negate()}};  // REAL & COMPLEX negation: no exceptions possible
+      return Expr<T>{Constant<T>{
+          c->value
+              .Negate()}};  // REAL & COMPLEX negation: no exceptions possible
     }
   }
   return Expr<T>{std::move(x)};
 }
 
-template<int KIND> Expr<Type<TypeCategory::Real, KIND>> Fold(FoldingContext &context, ComplexComponent<KIND> &&x) {
+template<int KIND>
+Expr<Type<TypeCategory::Real, KIND>> Fold(
+    FoldingContext &context, ComplexComponent<KIND> &&x) {
   using Operand = Type<TypeCategory::Complex, KIND>;
   using Part = Type<TypeCategory::Real, KIND>;
   auto &operand{x.left()};
@@ -152,7 +173,9 @@ template<int KIND> Expr<Type<TypeCategory::Real, KIND>> Fold(FoldingContext &con
   return Expr<Part>{std::move(x)};
 }
 
-template<int KIND> Expr<Type<TypeCategory::Logical, KIND>> Fold(FoldingContext &context, Not<KIND> &&x) {
+template<int KIND>
+Expr<Type<TypeCategory::Logical, KIND>> Fold(
+    FoldingContext &context, Not<KIND> &&x) {
   using Ty = Type<TypeCategory::Logical, KIND>;
   auto &operand{x.left()};
   operand = Fold(context, std::move(operand));
@@ -164,8 +187,9 @@ template<int KIND> Expr<Type<TypeCategory::Logical, KIND>> Fold(FoldingContext &
 
 // Binary (dyadic) operations
 
-template<typename T1, typename T2> std::optional<std::pair<Scalar<T1>, Scalar<T2>>>
-FoldOperands(FoldingContext &context, Expr<T1> &x, Expr<T2> &y) {
+template<typename T1, typename T2>
+std::optional<std::pair<Scalar<T1>, Scalar<T2>>> FoldOperands(
+    FoldingContext &context, Expr<T1> &x, Expr<T2> &y) {
   x = Fold(context, std::move(x));
   y = Fold(context, std::move(y));
   if (const auto *xc{std::get_if<Constant<T1>>(&x.u)}) {
@@ -198,7 +222,8 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Subtract<T> &&x) {
     if constexpr (T::category == TypeCategory::Integer) {
       auto difference{folded->first.SubtractSigned(folded->second)};
       if (difference.overflow) {
-        context.messages.Say("INTEGER(%d) subtraction overflowed"_en_US, T::kind);
+        context.messages.Say(
+            "INTEGER(%d) subtraction overflowed"_en_US, T::kind);
       }
       return Expr<T>{Constant<T>{difference.value}};
     } else {
@@ -215,7 +240,8 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Multiply<T> &&x) {
     if constexpr (T::category == TypeCategory::Integer) {
       auto product{folded->first.MultiplySigned(folded->second)};
       if (product.SignedMultiplicationOverflowed()) {
-        context.messages.Say("INTEGER(%d) multiplication overflowed"_en_US, T::kind);
+        context.messages.Say(
+            "INTEGER(%d) multiplication overflowed"_en_US, T::kind);
       }
       return Expr<T>{Constant<T>{product.lower}};
     } else {
@@ -252,7 +278,8 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Power<T> &&x) {
     if constexpr (T::category == TypeCategory::Integer) {
       auto power{folded->first.Power(folded->second)};
       if (power.divisionByZero) {
-        context.messages.Say("INTEGER(%d) zero to negative power"_en_US, T::kind);
+        context.messages.Say(
+            "INTEGER(%d) zero to negative power"_en_US, T::kind);
       } else if (power.overflow) {
         context.messages.Say("INTEGER(%d) power overflowed"_en_US, T::kind);
       } else if (power.zeroToZero) {
@@ -266,16 +293,19 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Power<T> &&x) {
   return Expr<T>{std::move(x)};
 }
 
-template<typename T> Expr<T> Fold(FoldingContext &context, RealToIntPower<T> &&x) {
-  return std::visit([&](auto &y) -> Expr<T> {
-    if (auto folded{FoldOperands(context, x.left(), y)}) {
-      auto power{evaluate::IntPower(folded->first, folded->second)};
-      RealFlagWarnings(context, power.flags, "power with INTEGER exponent");
-      return Expr<T>{Constant<T>{power.value}};
-    } else {
-      return Expr<T>{std::move(x)};
-    }
-  }, x.right().u);
+template<typename T>
+Expr<T> Fold(FoldingContext &context, RealToIntPower<T> &&x) {
+  return std::visit(
+      [&](auto &y) -> Expr<T> {
+        if (auto folded{FoldOperands(context, x.left(), y)}) {
+          auto power{evaluate::IntPower(folded->first, folded->second)};
+          RealFlagWarnings(context, power.flags, "power with INTEGER exponent");
+          return Expr<T>{Constant<T>{power.value}};
+        } else {
+          return Expr<T>{std::move(x)};
+        }
+      },
+      x.right().u);
 }
 
 template<typename T> Expr<T> Fold(FoldingContext &context, Extremum<T> &&x) {
@@ -285,7 +315,9 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Extremum<T> &&x) {
         return Expr<T>{Constant<T>{folded->first}};
       }
     } else if constexpr (T::category == TypeCategory::Real) {
-      if (folded->first.IsNotANumber() || (folded->first.Compare(folded->second) == Relation::Less) == (x.ordering == Ordering::Less)) {
+      if (folded->first.IsNotANumber() ||
+          (folded->first.Compare(folded->second) == Relation::Less) ==
+              (x.ordering == Ordering::Less)) {
         return Expr<T>{Constant<T>{folded->first}};
       }
     } else {
@@ -298,5 +330,5 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Extremum<T> &&x) {
   return Expr<T>{std::move(x)};
 }
 
-}
+}  // namespace Fortran::evaluate
 #endif  // FORTRAN_EVALUATE_FOLD_H_
index 83ab777..16fb59e 100644 (file)
@@ -111,7 +111,7 @@ struct CallAndArguments {
 // member function that converts parse trees into (usually) generic
 // expressions.
 struct ExprAnalyzer {
-  ExprAnalyzer(semantics::SemanticsContext &context) : context{context} {}
+  explicit ExprAnalyzer(semantics::SemanticsContext &ctx) : context{ctx} {}
 
   MaybeExpr Analyze(const parser::Expr &);
   MaybeExpr Analyze(const parser::CharLiteralConstantSubstring &);
@@ -832,8 +832,8 @@ std::optional<CallAndArguments> ExprAnalyzer::Procedure(
                       } else {
                         CallCharacteristics cc{n.source};
                         if (std::optional<SpecificCall> specificCall{
-                                intrinsics.Probe(
-                                    cc, arguments, &context.messages)}) {
+                                context.intrinsics().Probe(cc, arguments,
+                                    &context.foldingContext().messages)}) {
                           return {CallAndArguments{
                               ProcedureDesignator{
                                   std::move(specificCall->specificIntrinsic)},
index 1b4e746..db14134 100644 (file)
@@ -492,7 +492,6 @@ int main(int argc, char *const argv[]) {
     driver.pgf90Args.push_back("-Mbackslash");
   }
 
-
   Fortran::semantics::SemanticsContext semanticsContext{defaultKinds};
   semanticsContext.set_moduleDirectory(driver.moduleDirectory)
       .set_searchDirectories(driver.searchDirectories)