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

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