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

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