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

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