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

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