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

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