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

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