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

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