[PATCH] D83917: [flang] Fix a crash when a BOZ literal is used as a relational operator

Pete Steinfeld via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 20 07:46:30 PDT 2020


PeteSteinfeld updated this revision to Diff 279244.
PeteSteinfeld added a comment.

I discovered that there was another dereference of the nullopt type of a BOZ
literal.  In order to catch both dereferences, I convert all BOZ literals that
are operands in a relational expression to INTEGERs.  In practice, this means
that comparisons to numeric types do not produce errors while a comparison to a
CHARACTER or LOGICAL operand does produce an error.  This behavior matches most
of the other compilers I tested.  The exception is IBM's compiler, which allows
comparisons between BOZ literals and CHARACTER operands.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D83917/new/

https://reviews.llvm.org/D83917

Files:
  flang/lib/Semantics/expression.cpp
  flang/test/Semantics/resolve63.f90


Index: flang/test/Semantics/resolve63.f90
===================================================================
--- flang/test/Semantics/resolve63.f90
+++ flang/test/Semantics/resolve63.f90
@@ -44,10 +44,28 @@
   type(t) :: x, y
   real :: r
   logical :: l
+  integer :: iVar
+  complex :: cvar
+  character :: charVar
 contains
   subroutine test_relational()
     l = x == y  !OK
     l = x .eq. y  !OK
+    l = x .eq. y  !OK
+    l = iVar == z'fe' !OK
+    l = z'fe' == iVar !OK
+    l = r == z'fe' !OK
+    l = z'fe' == r !OK
+    l = cVar == z'fe' !OK
+    l = z'fe' == cVar !OK
+    !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types CHARACTER(KIND=1) and INTEGER(4)
+    l = charVar == z'fe'
+    !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types INTEGER(4) and CHARACTER(KIND=1)
+    l = z'fe' == charVar
+    !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types LOGICAL(4) and INTEGER(4)
+    l = l == z'fe' !OK
+    !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types INTEGER(4) and LOGICAL(4)
+    l = z'fe' == l !OK
     !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types TYPE(t) and REAL(4)
     l = x == r
   end
Index: flang/lib/Semantics/expression.cpp
===================================================================
--- flang/lib/Semantics/expression.cpp
+++ flang/lib/Semantics/expression.cpp
@@ -123,6 +123,7 @@
   }
   void Analyze(const parser::Variable &);
   void Analyze(const parser::ActualArgSpec &, bool isSubroutine);
+  void ConvertBOZToInt(std::size_t i);
 
   bool IsIntrinsicRelational(RelationalOperator) const;
   bool IsIntrinsicLogical() const;
@@ -2337,12 +2338,16 @@
   analyzer.Analyze(std::get<1>(x.t));
   if (analyzer.fatalErrors()) {
     return std::nullopt;
-  } else if (analyzer.IsIntrinsicRelational(opr)) {
-    return AsMaybeExpr(Relate(context.GetContextualMessages(), opr,
-        analyzer.MoveExpr(0), analyzer.MoveExpr(1)));
   } else {
-    return analyzer.TryDefinedOp(opr,
-        "Operands of %s must have comparable types; have %s and %s"_err_en_US);
+    analyzer.ConvertBOZToInt(0);
+    analyzer.ConvertBOZToInt(1);
+    if (analyzer.IsIntrinsicRelational(opr)) {
+      return AsMaybeExpr(Relate(context.GetContextualMessages(), opr,
+          analyzer.MoveExpr(0), analyzer.MoveExpr(1)));
+    } else {
+      return analyzer.TryDefinedOp(opr,
+          "Operands of %s must have comparable types; have %s and %s"_err_en_US);
+    }
   }
 }
 
@@ -3014,6 +3019,18 @@
   return i < actuals_.size() ? actuals_[i].value().Rank() : 0;
 }
 
+// If the argument at index i is a BOZ liter, convert its type to an INTEGER
+void ArgumentAnalyzer::ConvertBOZToInt(std::size_t i) {
+  if (IsBOZLiteral(i)) {
+    Expr<SomeType> &&argExpr{MoveExpr(i)};
+    auto *boz{std::get_if<BOZLiteralConstant>(&argExpr.u)};
+    MaybeExpr intExpr{ConvertToKind<TypeCategory::Integer>(
+        context_.context().GetDefaultKind(TypeCategory::Integer),
+        std::move(*boz))};
+    actuals_[i] = std::move(*intExpr);
+  }
+}
+
 // Report error resolving opr when there is a user-defined one available
 void ArgumentAnalyzer::SayNoMatch(const std::string &opr, bool isAssignment) {
   std::string type0{TypeAsFortran(0)};


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D83917.279244.patch
Type: text/x-patch
Size: 3275 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200720/b38f9567/attachment.bin>


More information about the llvm-commits mailing list