Blame SOURCES/0002-Convert-LOGICAL-to-INTEGER-for-arithmetic-ops-and-vi.patch

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