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

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