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

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