c7b8388
From 9b45f3063dfd2b893e7963a4828c1b0afecdc68a Mon Sep 17 00:00:00 2001
c7b8388
From: Mark Eggleston <markeggleston@gcc.gnu.org>
c7b8388
Date: Fri, 22 Jan 2021 12:41:46 +0000
c7b8388
Subject: [PATCH 02/10] Convert LOGICAL to INTEGER for arithmetic ops, and vice
c7b8388
 versa
c7b8388
c7b8388
We allow converting LOGICAL types to INTEGER when doing arithmetic
c7b8388
operations, and converting INTEGER types to LOGICAL for use in
c7b8388
boolean operations.
c7b8388
c7b8388
This feature is enabled with the -flogical-as-integer flag.
c7b8388
c7b8388
Note: using this feature will disable bitwise logical operations enabled by
c7b8388
-fdec.
c7b8388
---
c7b8388
 gcc/fortran/lang.opt                          |  4 ++
c7b8388
 gcc/fortran/resolve.c                         | 55 ++++++++++++++++++-
c7b8388
 .../logical_to_integer_and_vice_versa_1.f     | 31 +++++++++++
c7b8388
 .../logical_to_integer_and_vice_versa_2.f     | 31 +++++++++++
c7b8388
 .../logical_to_integer_and_vice_versa_3.f     | 33 +++++++++++
c7b8388
 .../logical_to_integer_and_vice_versa_4.f     | 33 +++++++++++
c7b8388
 6 files changed, 186 insertions(+), 1 deletion(-)
c7b8388
 create mode 100644 gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_1.f
c7b8388
 create mode 100644 gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_2.f
c7b8388
 create mode 100644 gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_3.f
c7b8388
 create mode 100644 gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_4.f
c7b8388
c7b8388
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
c7b8388
index 52bd522051e..c4da248f07c 100644
c7b8388
--- a/gcc/fortran/lang.opt
c7b8388
+++ b/gcc/fortran/lang.opt
c7b8388
@@ -497,6 +497,10 @@ fdec-static
c7b8388
 Fortran Var(flag_dec_static)
c7b8388
 Enable DEC-style STATIC and AUTOMATIC attributes.
c7b8388
 
c7b8388
+flogical-as-integer
c7b8388
+Fortran Var(flag_logical_as_integer)
c7b8388
+Convert from integer to logical or logical to integer for arithmetic operations.
c7b8388
+
c7b8388
 fdefault-double-8
c7b8388
 Fortran Var(flag_default_double)
c7b8388
 Set the default double precision kind to an 8 byte wide type.
c7b8388
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
c7b8388
index c075d0fa0c4..4b90cb59902 100644
c7b8388
--- a/gcc/fortran/resolve.c
c7b8388
+++ b/gcc/fortran/resolve.c
c7b8388
@@ -3915,7 +3915,6 @@ lookup_uop_fuzzy (const char *op, gfc_symtree *uop)
c7b8388
   return gfc_closest_fuzzy_match (op, candidates);
c7b8388
 }
c7b8388
 
c7b8388
-
c7b8388
 /* Callback finding an impure function as an operand to an .and. or
c7b8388
    .or.  expression.  Remember the last function warned about to
c7b8388
    avoid double warnings when recursing.  */
c7b8388
@@ -3975,6 +3974,22 @@ convert_hollerith_to_character (gfc_expr *e)
c7b8388
     }
c7b8388
 }
c7b8388
 
c7b8388
+/* If E is a logical, convert it to an integer and issue a warning
c7b8388
+   for the conversion.  */
c7b8388
+
c7b8388
+static void
c7b8388
+convert_integer_to_logical (gfc_expr *e)
c7b8388
+{
c7b8388
+  if (e->ts.type == BT_INTEGER)
c7b8388
+    {
c7b8388
+      /* Convert to LOGICAL */
c7b8388
+      gfc_typespec t;
c7b8388
+      t.type = BT_LOGICAL;
c7b8388
+      t.kind = 1;
c7b8388
+      gfc_convert_type_warn (e, &t, 2, 1);
c7b8388
+    }
c7b8388
+}
c7b8388
+
c7b8388
 /* Convert to numeric and issue a warning for the conversion.  */
c7b8388
 
c7b8388
 static void
c7b8388
@@ -3987,6 +4002,22 @@ convert_to_numeric (gfc_expr *a, gfc_expr *b)
c7b8388
   gfc_convert_type_warn (a, &t, 2, 1);
c7b8388
 }
c7b8388
 
c7b8388
+/* If E is a logical, convert it to an integer and issue a warning
c7b8388
+   for the conversion.  */
c7b8388
+
c7b8388
+static void
c7b8388
+convert_logical_to_integer (gfc_expr *e)
c7b8388
+{
c7b8388
+  if (e->ts.type == BT_LOGICAL)
c7b8388
+    {
c7b8388
+      /* Convert to INTEGER */
c7b8388
+      gfc_typespec t;
c7b8388
+      t.type = BT_INTEGER;
c7b8388
+      t.kind = 1;
c7b8388
+      gfc_convert_type_warn (e, &t, 2, 1);
c7b8388
+    }
c7b8388
+}
c7b8388
+
c7b8388
 /* Resolve an operator expression node.  This can involve replacing the
c7b8388
    operation with a user defined function call.  */
c7b8388
 
c7b8388
@@ -4072,6 +4103,12 @@ resolve_operator (gfc_expr *e)
c7b8388
     case INTRINSIC_TIMES:
c7b8388
     case INTRINSIC_DIVIDE:
c7b8388
     case INTRINSIC_POWER:
c7b8388
+      if (flag_logical_as_integer)
c7b8388
+	{
c7b8388
+	  convert_logical_to_integer (op1);
c7b8388
+	  convert_logical_to_integer (op2);
c7b8388
+	}
c7b8388
+
c7b8388
       if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))
c7b8388
 	{
c7b8388
 	  gfc_type_convert_binary (e, 1);
c7b8388
@@ -4108,6 +4145,13 @@ resolve_operator (gfc_expr *e)
c7b8388
     case INTRINSIC_OR:
c7b8388
     case INTRINSIC_EQV:
c7b8388
     case INTRINSIC_NEQV:
c7b8388
+
c7b8388
+      if (flag_logical_as_integer)
c7b8388
+	{
c7b8388
+	  convert_integer_to_logical (op1);
c7b8388
+	  convert_integer_to_logical (op2);
c7b8388
+	}
c7b8388
+
c7b8388
       if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL)
c7b8388
 	{
c7b8388
 	  e->ts.type = BT_LOGICAL;
c7b8388
@@ -4158,6 +4202,9 @@ resolve_operator (gfc_expr *e)
c7b8388
 	  goto simplify_op;
c7b8388
 	}
c7b8388
 
c7b8388
+      if (flag_logical_as_integer)
c7b8388
+	convert_integer_to_logical (op1);
c7b8388
+
c7b8388
       if (op1->ts.type == BT_LOGICAL)
c7b8388
 	{
c7b8388
 	  e->ts.type = BT_LOGICAL;
c7b8388
@@ -4198,6 +4245,12 @@ resolve_operator (gfc_expr *e)
c7b8388
 	  convert_hollerith_to_character (op2);
c7b8388
 	}
c7b8388
 
c7b8388
+      if (flag_logical_as_integer)
c7b8388
+	{
c7b8388
+	  convert_logical_to_integer (op1);
c7b8388
+	  convert_logical_to_integer (op2);
c7b8388
+	}
c7b8388
+
c7b8388
       if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
c7b8388
 	  && op1->ts.kind == op2->ts.kind)
c7b8388
 	{
c7b8388
diff --git a/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_1.f b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_1.f
c7b8388
new file mode 100644
c7b8388
index 00000000000..938a91d9e9a
c7b8388
--- /dev/null
c7b8388
+++ b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_1.f
c7b8388
@@ -0,0 +1,31 @@
c7b8388
+! { dg-do run }
c7b8388
+! { dg-options "-std=legacy -flogical-as-integer" }
c7b8388
+!
c7b8388
+! Test conversion between logical and integer for logical operators
c7b8388
+!
c7b8388
+! Test case contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
c7b8388
+! Modified for -flogical-as-integer by Mark Eggleston
c7b8388
+! <mark.eggleston@codethink.com>
c7b8388
+!
c7b8388
+        PROGRAM logical_integer_conversion
c7b8388
+          LOGICAL lpos /.true./
c7b8388
+          INTEGER ineg/0/
c7b8388
+          INTEGER ires
c7b8388
+          LOGICAL lres
c7b8388
+
c7b8388
+          ! Test Logicals converted to Integers
c7b8388
+          if ((lpos.AND.ineg).EQ.1) STOP 3
c7b8388
+          if ((ineg.AND.lpos).NE.0) STOP 4
c7b8388
+          ires = (.true..AND.0)
c7b8388
+          if (ires.NE.0) STOP 5
c7b8388
+          ires = (1.AND..false.)
c7b8388
+          if (ires.EQ.1) STOP 6
c7b8388
+
c7b8388
+          ! Test Integers converted to Logicals
c7b8388
+          if (lpos.EQ.ineg) STOP 7
c7b8388
+          if (ineg.EQ.lpos) STOP 8
c7b8388
+          lres = (.true..EQ.0)
c7b8388
+          if (lres) STOP 9
c7b8388
+          lres = (1.EQ..false.)
c7b8388
+          if (lres) STOP 10
c7b8388
+        END
c7b8388
diff --git a/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_2.f b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_2.f
c7b8388
new file mode 100644
c7b8388
index 00000000000..9f146202ba5
c7b8388
--- /dev/null
c7b8388
+++ b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_2.f
c7b8388
@@ -0,0 +1,31 @@
c7b8388
+! { dg-do compile }
c7b8388
+! { dg-options "-std=legacy -flogical-as-integer -fno-logical-as-integer" }
c7b8388
+!
c7b8388
+! Based on logical_to_integer_and_vice_versa_1.f but with option disabled
c7b8388
+! to test for error messages.
c7b8388
+!
c7b8388
+! Test case contributed by by Mark Eggleston <mark.eggleston@codethink.com>
c7b8388
+!
c7b8388
+!
c7b8388
+        PROGRAM logical_integer_conversion
c7b8388
+          LOGICAL lpos /.true./
c7b8388
+          INTEGER ineg/0/
c7b8388
+          INTEGER ires
c7b8388
+          LOGICAL lres
c7b8388
+
c7b8388
+          ! Test Logicals converted to Integers
c7b8388
+          if ((lpos.AND.ineg).EQ.1) STOP 3 ! { dg-error "Operands of logical operator" }
c7b8388
+          if ((ineg.AND.lpos).NE.0) STOP 4 ! { dg-error "Operands of logical operator" }
c7b8388
+          ires = (.true..AND.0) ! { dg-error "Operands of logical operator" }
c7b8388
+          if (ires.NE.0) STOP 5
c7b8388
+          ires = (1.AND..false.) ! { dg-error "Operands of logical operator" }
c7b8388
+          if (ires.EQ.1) STOP 6
c7b8388
+
c7b8388
+          ! Test Integers converted to Logicals
c7b8388
+          if (lpos.EQ.ineg) STOP 7 ! { dg-error "Operands of comparison operator" }
c7b8388
+          if (ineg.EQ.lpos) STOP 8 ! { dg-error "Operands of comparison operator" }
c7b8388
+          lres = (.true..EQ.0) ! { dg-error "Operands of comparison operator" }
c7b8388
+          if (lres) STOP 9
c7b8388
+          lres = (1.EQ..false.) ! { dg-error "Operands of comparison operator" }
c7b8388
+          if (lres) STOP 10
c7b8388
+        END
c7b8388
diff --git a/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_3.f b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_3.f
c7b8388
new file mode 100644
c7b8388
index 00000000000..446873eb2dc
c7b8388
--- /dev/null
c7b8388
+++ b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_3.f
c7b8388
@@ -0,0 +1,33 @@
c7b8388
+! { dg-do compile }
c7b8388
+! { dg-options "-std=legacy -flogical-as-integer" }
c7b8388
+!
c7b8388
+! Test conversion between logical and integer for logical operators
c7b8388
+!
c7b8388
+        program test
c7b8388
+          logical f /.false./
c7b8388
+          logical t /.true./
c7b8388
+          real x
c7b8388
+
c7b8388
+          x = 7.7
c7b8388
+          x = x + t*3.0
c7b8388
+          if (abs(x - 10.7).gt.0.00001) stop 1
c7b8388
+          x = x + .false.*5.0
c7b8388
+          if (abs(x - 10.7).gt.0.00001) stop 2
c7b8388
+          x = x - .true.*5.0
c7b8388
+          if (abs(x - 5.7).gt.0.00001) stop 3
c7b8388
+          x = x + t
c7b8388
+          if (abs(x - 6.7).gt.0.00001) stop 4
c7b8388
+          x = x + f
c7b8388
+          if (abs(x - 6.7).gt.0.00001) stop 5
c7b8388
+          x = x - t
c7b8388
+          if (abs(x - 5.7).gt.0.00001) stop 6
c7b8388
+          x = x - f
c7b8388
+          if (abs(x - 5.7).gt.0.00001) stop 7
c7b8388
+          x = x**.true.
c7b8388
+          if (abs(x - 5.7).gt.0.00001) stop 8
c7b8388
+          x = x**.false.
c7b8388
+          if (abs(x - 1.0).gt.0.00001) stop 9
c7b8388
+          x = x/t
c7b8388
+          if (abs(x - 1.0).gt.0.00001) stop 10
c7b8388
+          if ((x/.false.).le.huge(x)) stop 11
c7b8388
+        end
c7b8388
diff --git a/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_4.f b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_4.f
c7b8388
new file mode 100644
c7b8388
index 00000000000..4301a4988d8
c7b8388
--- /dev/null
c7b8388
+++ b/gcc/testsuite/gfortran.dg/logical_to_integer_and_vice_versa_4.f
c7b8388
@@ -0,0 +1,33 @@
c7b8388
+! { dg-do compile }
c7b8388
+! { dg-options "-std=legacy -flogical-as-integer -fno-logical-as-integer" }
c7b8388
+!
c7b8388
+! Test conversion between logical and integer for logical operators
c7b8388
+!
c7b8388
+        program test
c7b8388
+          logical f /.false./
c7b8388
+          logical t /.true./
c7b8388
+          real x
c7b8388
+
c7b8388
+          x = 7.7
c7b8388
+          x = x + t*3.0 ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 10.7).gt.0.00001) stop 1
c7b8388
+          x = x + .false.*5.0 ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 10.7).gt.0.00001) stop 2
c7b8388
+          x = x - .true.*5.0 ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 5.7).gt.0.00001) stop 3
c7b8388
+          x = x + t ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 6.7).gt.0.00001) stop 4
c7b8388
+          x = x + f ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 6.7).gt.0.00001) stop 5
c7b8388
+          x = x - t ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 5.7).gt.0.00001) stop 6
c7b8388
+          x = x - f ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 5.7).gt.0.00001) stop 7
c7b8388
+          x = x**.true. ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 5.7).gt.0.00001) stop 8
c7b8388
+          x = x**.false. ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 1.0).gt.0.00001) stop 9
c7b8388
+          x = x/t ! { dg-error "Operands of binary numeric" }
c7b8388
+          if (abs(x - 1.0).gt.0.00001) stop 10
c7b8388
+          if ((x/.false.).le.huge(x)) stop 11 ! { dg-error "Operands of binary numeric" }
c7b8388
+        end
c7b8388
-- 
c7b8388
2.27.0
c7b8388