[flang] array constructor folding with test
authorpeter klausler <pklausler@nvidia.com>
Tue, 29 Jan 2019 18:22:18 +0000 (10:22 -0800)
committerpeter klausler <pklausler@nvidia.com>
Thu, 31 Jan 2019 17:59:34 +0000 (09:59 -0800)
Original-commit: flang-compiler/f18@37e7a8e666eae80d4d5485e8c9c59bfb23d08fa9
Reviewed-on: https://github.com/flang-compiler/f18/pull/271
Tree-same-pre-rewrite: false

flang/lib/evaluate/constant.cc
flang/lib/evaluate/fold.cc
flang/test/semantics/CMakeLists.txt
flang/test/semantics/modfile18.f90 [new file with mode: 0644]

index 6a8ec01..2cde28b 100644 (file)
 namespace Fortran::evaluate {
 template<typename T>
 std::ostream &Constant<T>::AsFortran(std::ostream &o) const {
+  if (Rank() > 1) {
+    o << "reshape(";
+  }
   if (Rank() > 0) {
-    o << "reshape([" << GetType().AsFortran() << "::";
+    o << '[' << GetType().AsFortran() << "::";
   }
+  bool first{true};
   for (const auto &value : values_) {
+    if (first) {
+      first = false;
+    } else {
+      o << ',';
+    }
     if constexpr (T::category == TypeCategory::Integer) {
       o << value.SignedDecimal() << '_' << T::kind;
     } else if constexpr (T::category == TypeCategory::Real ||
@@ -42,7 +51,10 @@ std::ostream &Constant<T>::AsFortran(std::ostream &o) const {
     }
   }
   if (Rank() > 0) {
-    o << "],shape=";
+    o << ']';
+  }
+  if (Rank() > 1) {
+    o << ",shape=";
     char ch{'['};
     for (auto dim : shape_) {
       o << ch << dim;
index bfc6114..fec3b5f 100644 (file)
@@ -223,14 +223,14 @@ Expr<ImpliedDoIndex::Result> FoldOperation(
 
 template<typename T> class ArrayConstructorFolder {
 public:
-  explicit ArrayConstructorFolder(const FoldingContext &c) : context_{c} {
-    context_.impliedDos.clear();
-  }
+  explicit ArrayConstructorFolder(const FoldingContext &c) : context_{c} {}
+
   Expr<T> FoldArray(ArrayConstructor<T> &&array) {
     if (FoldArray(array.values)) {
       std::int64_t n = elements_.size();
-      return Expr<T>{
+      Expr<T> result{
           Constant<T>{std::move(elements_), std::vector<std::int64_t>{n}}};
+      return result;
     } else {
       return Expr<T>{std::move(array)};
     }
@@ -246,7 +246,10 @@ private:
       std::vector<std::int64_t> index(shape.size(), 1);
       for (std::size_t n{c->size()}; n-- > 0;) {
         elements_.push_back(c->At(index));
-        for (int d{0}; d < rank && ++index[d] <= shape[d]; ++d) {
+        for (int d{0}; d < rank; ++d) {
+          if (++index[d] <= shape[d]) {
+            break;
+          }
           index[d] = 1;
         }
       }
@@ -302,7 +305,6 @@ Expr<T> FoldOperation(FoldingContext &context, ArrayConstructor<T> &&array) {
 
 Expr<SomeDerived> FoldOperation(
     FoldingContext &context, ArrayConstructor<SomeDerived> &&array) {
-  // TODO pmk: derived type array constructor folding (no Scalar<T> to use)
   return Expr<SomeDerived>{std::move(array)};
 }
 
index 9487194..eb3d26f 100644 (file)
@@ -103,6 +103,7 @@ set(MODFILE_TESTS
   modfile15.f90
   modfile16.f90
   modfile17.f90
+  modfile18.f90
 )
 
 set(LABEL_TESTS
diff --git a/flang/test/semantics/modfile18.f90 b/flang/test/semantics/modfile18.f90
new file mode 100644 (file)
index 0000000..c8b654e
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (c) 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.
+! You may obtain a copy of the License at
+!
+!     http://www.apache.org/licenses/LICENSE-2.0
+!
+! Unless required by applicable law or agreed to in writing, software
+! distributed under the License is distributed on an "AS IS" BASIS,
+! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+! See the License for the specific language governing permissions and
+! limitations under the License.
+
+! Tests folding of array constructors
+
+module m
+  real, parameter :: a0 = 1.0_8
+  real, parameter :: a1(2) = [real::2.0, 3.0]
+  real, parameter :: a2(2) = [4.0, 5.0]
+  real, parameter :: a3(0) = [real::]
+  real, parameter :: a4(55) = [real::((1.0*k,k=1,j),j=1,10)]
+  real, parameter :: a5(:) = [6.0, 7.0, 8.0]
+  real, parameter :: a6(2) = [9, 10]
+  real, parameter :: a7(6) = [([(1.0*k,k=1,j)],j=1,3)]
+end module m
+
+!Expect: m.mod
+!module m
+!real(4),parameter::a0=1._8
+!real(4),parameter::a1(1_8:2_8)=[Real(4)::2._4,3._4]
+!real(4),parameter::a2(1_8:2_8)=[Real(4)::4._4,5._4]
+!real(4),parameter::a3(1_8:0_8)=[Real(4)::]
+!real(4),parameter::a4(1_8:55_8)=[Real(4)::1._4,1._4,2._4,1._4,2._4,3._4,1._4,2._4,3._4,4._4,1._4,2._4,3._4,4._4,5._4,1._4,2._4,3._4,4._4,5._4,6._4,1._4,2._4,3._4,4._4,5._4,6._4,7._4,1._4,2._4,3._4,4._4,5._4,6._4,7._4,8._4,1._4,2._4,3._4,4._4,5._4,6._4,7._4,8._4,9._4,1._4,2._4,3._4,4._4,5._4,6._4,7._4,8._4,9._4,1.e1_4]
+!real(4),parameter::a5(1_8:)=[Real(4)::6._4,7._4,8._4]
+!real(4),parameter::a6(1_8:2_8)=[Integer(4)::9_4,10_4]
+!real(4),parameter::a7(1_8:6_8)=[Real(4)::1._4,1._4,2._4,1._4,2._4,3._4]
+!end