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

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