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

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