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

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