From e1db3e830b1c0e9ce846696d744af7883c23f150 Mon Sep 17 00:00:00 2001
From: Fritz Reese <fritzoreese@gmail.com>
Date: Fri, 23 Sep 2016 11:02:22 -0400
Subject: [PATCH 4/4] Enable .XOR. as a logical operator with new flag -fdec-logical-xor.

	gcc/fortran/
	* lang.opt, invoke.texi, gfortran.texi: New flag -fdec-logical-xor.
	* options.c (set_dec_flags): Enable with -fdec.
	* match.c (gfc_match_intrinsic_op): Match .XOR. and .NEQV. identically.

	gcc/testsuite/gfortran.dg/
	* dec_logical_xor.f90
---
 gcc/fortran/gfortran.texi                     |   11 ++++++-
 gcc/fortran/invoke.texi                       |    8 ++++-
 gcc/fortran/lang.opt                          |    4 ++
 gcc/fortran/match.c                           |   12 +++++++
 gcc/fortran/options.c                         |    1 +
 gcc/testsuite/gfortran.dg/dec_logical_xor.f90 |   40 +++++++++++++++++++++++++
 6 files changed, 74 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/dec_logical_xor.f90

diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 64d5fd5..4ee8cc7 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -1467,6 +1467,7 @@ without warning.
 * Form feed as whitespace::
 * TYPE as an alias for PRINT::
 * %LOC as an rvalue::
+* .XOR. operator::
 @end menu
 
 @node Old-style kind specifications
@@ -2556,6 +2557,15 @@ integer :: i
 call sub(%loc(i))
 @end smallexample
 
+@node .XOR. operator
+@subsection .XOR. operator
+@cindex operators, xor
+
+GNU Fortran supports @code{.XOR.} as a logical operator with the flag
+@code{-fdec-logical-xor} for compatibility with legacy code. @code{.XOR.} is
+equivalent to @code{.NEQV.}; the output is true if and only if the inputs
+differ.
+
 
 @node Extensions not implemented in GNU Fortran
 @section Extensions not implemented in GNU Fortran
@@ -2580,7 +2590,6 @@ code that uses them running with the GNU Fortran compiler.
 * Variable FORMAT expressions::
 @c * Q edit descriptor::
 @c * TYPE and ACCEPT I/O Statements::
-@c * .XOR. operator::
 @c * CARRIAGECONTROL, DEFAULTFILE, DISPOSE and RECORDTYPE I/O specifiers::
 @c * Omitted arguments in procedure call::
 * Alternate complex function syntax::
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 558dca6..eb7cf77 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -117,7 +117,7 @@ by type.  Explanations are in the following sections.
 @gccoptlist{-fall-intrinsics -fbackslash -fcray-pointer -fd-lines-as-code @gol
 -fd-lines-as-comments @gol
 -fdec -fdec-structure -fdec-intrinsic-ints -fdec-static -fdec-math @gol
--fdec-feed -fdec-type-print -fdec-loc-rval @gol
+-fdec-feed -fdec-type-print -fdec-loc-rval -fdec-logical-xor @gol
 -fdefault-double-8 -fdefault-integer-8 @gol
 -fdefault-real-8 -fdollar-ok -ffixed-line-length-@var{n} @gol
 -ffixed-line-length-none -ffree-form -ffree-line-length-@var{n} @gol
@@ -244,6 +244,7 @@ Other flags enabled by this switch are:
 @option{-fdollar-ok} @option{-fcray-pointer} @option{-fdec-structure}
 @option{-fdec-intrinsic-ints} @option{-fdec-static} @option{-fdec-math}
 @option{-fdec-feed} @option{-fdec-type-print} @option{-fdec-loc-rval}
+@option{-fdec-logical-xor}
 
 @item -fdec-structure
 @opindex @code{fdec-structure}
@@ -257,6 +258,11 @@ instead where possible.
 Enable B/I/J/K kind variants of existing integer functions (e.g. BIAND, IIAND,
 JIAND, etc...). For a complete list of intrinsics see the full documentation.
 
+@item -fdec-logical-xor
+@opindex @code{fdec-logical-xor}
+Enable @code{.XOR.} as a logical operator for compatibility with legacy code.
+It is equivalent to the standard @code{.NEQV.}, which is preferred in new code.
+
 @item -fdec-math
 @opindex @code{fdec-math}
 Enable legacy math intrinsics such as COTAN and degree-valued trigonometric
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 4b88349..8916225 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -428,6 +428,10 @@ fdec-intrinsic-ints
 Fortran Var(flag_dec_intrinsic_ints)
 Enable kind-specific variants of integer intrinsic functions.
 
+fdec-logical-xor
+Fortran Var(flag_dec_logical_xor)
+Enable .XOR. as a logical operator for compatibility.
+
 fdec-math
 Fortran Var(flag_dec_math)
 Enable legacy math intrinsics for compatibility.
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 067f27c..1810d16 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -960,6 +960,18 @@ gfc_match_intrinsic_op (gfc_intrinsic_op *result)
 	    }
 	  break;
 
+	case 'x':
+	  if (flag_dec_logical_xor
+	      && gfc_next_ascii_char () == 'o'
+	      && gfc_next_ascii_char () == 'r'
+	      && gfc_next_ascii_char () == '.')
+	    {
+	      /* Matched ".xor." - equivalent to ".neqv.".  */
+	      *result = INTRINSIC_NEQV;
+	      return MATCH_YES;
+	    }
+	  break;
+
 	default:
 	  break;
 	}
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index a26b630..5ac0dff 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -59,6 +59,7 @@ set_dec_flags (int value)
     flag_dec_feed = value;
     flag_dec_type_print = value;
     flag_dec_loc_rval = value;
+    flag_dec_logical_xor = value;
 }
 
 
diff --git a/gcc/testsuite/gfortran.dg/dec_logical_xor.f90 b/gcc/testsuite/gfortran.dg/dec_logical_xor.f90
new file mode 100644
index 0000000..631fbc0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_logical_xor.f90
@@ -0,0 +1,40 @@
+! { dg-options "-fdec-logical-xor" }
+! { dg-do "run" }
+!
+! Test logical .XOR. operator with -fdec-logical-xor.
+!
+
+implicit none
+
+logical :: in1, in2, neqv_out, lxor_out, truth_table(2)
+integer :: i, j, ixor_out, ieor_out
+
+truth_table(1) = .true.
+truth_table(2) = .false.
+do i = 1,2
+  do j = 1,2
+    in1 = truth_table(j)
+    in2 = truth_table(i)
+
+    ! make sure logical xor works
+    neqv_out = in1 .neqv. in2
+    lxor_out = in1 .xor. in2
+
+    if ( neqv_out .neqv. lxor_out ) then
+      print *, "(",in1,in2,") .neqv.: ",neqv_out,"  .xor.: ",lxor_out
+      call abort()
+    endif
+
+    ! make sure we didn't break xor() intrinsic
+    ixor_out = xor(i*7, j*5)
+    ieor_out = ieor(i*7, j*5)
+
+    if ( ixor_out .ne. ieor_out ) then
+      print *, "(",in1,in2,") ieor(): ",ieor_out,"  xor(): ",ixor_out
+      call abort()
+    endif
+
+  enddo
+enddo
+
+end
-- 
1.7.1

