Blame SOURCES/gcc11-fortran-flogical-as-integer.patch

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