Blame SOURCES/0003-Convert-LOGICAL-to-INTEGER-for-arithmetic-ops-and-vi.patch

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