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

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