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

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