[flang] Fix LEN(char array), it is not elemental.
authorpeter klausler <pklausler@nvidia.com>
Tue, 4 Jun 2019 17:09:54 +0000 (10:09 -0700)
committerpeter klausler <pklausler@nvidia.com>
Tue, 4 Jun 2019 20:37:23 +0000 (13:37 -0700)
Original-commit: flang-compiler/f18@b44eb2e7b1fd8d86e95d3c24014e542bdb39877d
Reviewed-on: https://github.com/flang-compiler/f18/pull/477
Tree-same-pre-rewrite: false

flang/lib/evaluate/intrinsics.cc
flang/lib/evaluate/logical.h

index 81dc5a5..06ac427 100644 (file)
@@ -410,7 +410,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
         {{"array", Anything, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
         KINDInt, Rank::vector},
     {"leadz", {{"i", AnyInt}}, DefaultInt},
-    {"len", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
+    {"len", {{"string", AnyChar, Rank::anyOrAssumedRank}, SubscriptDefaultKIND},
+        KINDInt},
     {"len_trim", {{"string", AnyChar}, SubscriptDefaultKIND}, KINDInt},
     {"lge", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
     {"lgt", {{"string_a", SameChar}, {"string_b", SameChar}}, DefaultLogical},
@@ -733,7 +734,7 @@ static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
     {{"index", {{"string", DefaultChar}, {"substring", DefaultChar}},
         DefaultInt}},
     {{"isign", {{"a", DefaultInt}, {"b", DefaultInt}}, DefaultInt}, "sign"},
-    {{"len", {{"string", DefaultChar}}, DefaultInt}},
+    {{"len", {{"string", DefaultChar, Rank::anyOrAssumedRank}}, DefaultInt}},
     {{"log", {{"x", DefaultReal}}, DefaultReal}},
     {{"log10", {{"x", DefaultReal}}, DefaultReal}},
     {{"max0",
index e0007c5..c6eacd8 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.
 
 namespace Fortran::evaluate::value {
 
-template<int BITS> class Logical {
+template<int BITS, bool IS_LIKE_C = false> class Logical {
 public:
   static constexpr int bits{BITS};
+
+  // Module ISO_C_BINDING kind C_BOOL is LOGICAL(KIND=1) and must have
+  // C's bit representation (.TRUE. -> 1, .FALSE. -> 0).
+  static constexpr bool IsLikeC{BITS <= 8 || IS_LIKE_C};
+
   constexpr Logical() {}  // .FALSE.
   constexpr Logical(const Logical &that) = default;
-  constexpr Logical(bool truth) : word_{-std::uint64_t{truth}} {}
+  constexpr Logical(bool truth)
+    : word_{truth ? canonicalTrue : canonicalFalse} {}
   constexpr Logical &operator=(const Logical &) = default;
 
   template<int B> constexpr bool operator==(const Logical<B> &that) const {
@@ -33,9 +39,15 @@ public:
   }
 
   // For static expression evaluation, all the bits will have the same value.
-  constexpr bool IsTrue() const { return word_.BTEST(0); }
+  constexpr bool IsTrue() const {
+    if constexpr (IsLikeC) {
+      return !word_.IsZero();
+    } else {
+      return word_.BTEST(0);
+    }
+  }
 
-  constexpr Logical NOT() const { return {word_.NOT()}; }
+  constexpr Logical NOT() const { return {word_.IEOR(canonicalTrue)}; }
 
   constexpr Logical AND(const Logical &that) const {
     return {word_.IAND(that.word_)};
@@ -53,6 +65,8 @@ public:
 
 private:
   using Word = Integer<bits>;
+  static constexpr Word canonicalTrue{IsLikeC ? -std::uint64_t{1} : 1};
+  static constexpr Word canonicalFalse{0};
   constexpr Logical(const Word &w) : word_{w} {}
   Word word_;
 };