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

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