aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorHarald Anlauf <anlauf@gmx.de>2019-06-14 18:41:20 +0000
committerHarald Anlauf <anlauf@gcc.gnu.org>2019-06-14 18:41:20 +0000
commitd0442491d506497f9c7e8bfa6f0e9edb16d21306 (patch)
treec3615319bcfcff103f8bbc0cd88ef23de4955beb /gcc/fortran
parenta8566e938ca4c6d5c8a631397e15216d0d6a720f (diff)
downloadgcc-d0442491d506497f9c7e8bfa6f0e9edb16d21306.zip
gcc-d0442491d506497f9c7e8bfa6f0e9edb16d21306.tar.gz
gcc-d0442491d506497f9c7e8bfa6f0e9edb16d21306.tar.bz2
re PR fortran/90577 (FAIL: gfortran.dg/lrshift_1.f90 with -O(2|3) and -flto)
2019-06-14 Harald Anlauf <anlauf@gmx.de> PR fortran/90577 PR fortran/90578 * trans-intrinsic.c (gfc_conv_intrinsic_shift): Properly distinguish logical/arithmetic shifts. * intrinsic.texi: Update documentation for SHIFTR/SHIFTL/SHIFTA (Fortran 2008) and LSHIFT/RSHIFT (GNU extensions). PR fortran/90577 PR fortran/90578 * gfortran.dg/lrshift_1.f90: Adjust testcase. * gfortran.dg/shiftalr_3.f90: New testcase. From-SVN: r272309
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog9
-rw-r--r--gcc/fortran/intrinsic.texi46
-rw-r--r--gcc/fortran/trans-intrinsic.c15
3 files changed, 47 insertions, 23 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 9a82b9b..def1810 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,12 @@
+2019-06-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/90577
+ PR fortran/90578
+ * trans-intrinsic.c (gfc_conv_intrinsic_shift): Properly
+ distinguish logical/arithmetic shifts.
+ * intrinsic.texi: Update documentation for SHIFTR/SHIFTL/SHIFTA
+ (Fortran 2008) and LSHIFT/RSHIFT (GNU extensions).
+
2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/89646
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index f3f4c00..f390761 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -9689,10 +9689,10 @@ The return value is a @code{INTEGER(4)} variable.
@table @asis
@item @emph{Description}:
@code{LSHIFT} returns a value corresponding to @var{I} with all of the
-bits shifted left by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the left end are lost; zeros are shifted in from
-the opposite end.
+bits shifted left by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the left end are
+lost; zeros are shifted in from the opposite end.
This function has been superseded by the @code{ISHFT} intrinsic, which
is standard in Fortran 95 and later, and the @code{SHIFTL} intrinsic,
@@ -12244,11 +12244,12 @@ The value returned is equal to
@table @asis
@item @emph{Description}:
@code{RSHIFT} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost. The fill is arithmetic: the
-bits shifted in from the left end are equal to the leftmost bit, which in
-two's complement representation is the sign bit.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost. The fill is arithmetic: the bits shifted in from the left
+end are equal to the leftmost bit, which in two's complement
+representation is the sign bit.
This function has been superseded by the @code{SHIFTA} intrinsic, which
is standard in Fortran 2008 and later.
@@ -12783,11 +12784,12 @@ END PROGRAM
@table @asis
@item @emph{Description}:
@code{SHIFTA} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost. The fill is arithmetic: the
-bits shifted in from the left end are equal to the leftmost bit, which in
-two's complement representation is the sign bit.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} that be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost. The fill is arithmetic: the bits shifted in from the left
+end are equal to the leftmost bit, which in two's complement
+representation is the sign bit.
@item @emph{Standard}:
Fortran 2008 and later
@@ -12823,10 +12825,10 @@ The return value is of type @code{INTEGER} and of the same kind as
@table @asis
@item @emph{Description}:
@code{SHIFTL} returns a value corresponding to @var{I} with all of the
-bits shifted left by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the left end are lost, and bits shifted in from
-the right end are set to 0.
+bits shifted left by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the left end are
+lost, and bits shifted in from the right end are set to 0.
@item @emph{Standard}:
Fortran 2008 and later
@@ -12862,10 +12864,10 @@ The return value is of type @code{INTEGER} and of the same kind as
@table @asis
@item @emph{Description}:
@code{SHIFTR} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost, and bits shifted in from
-the left end are set to 0.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost, and bits shifted in from the left end are set to 0.
@item @emph{Standard}:
Fortran 2008 and later
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index f6edd68..cc041f9 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -6346,6 +6346,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
bool arithmetic)
{
tree args[2], type, num_bits, cond;
+ tree bigshift;
gfc_conv_intrinsic_function_args (se, expr, args, 2);
@@ -6365,6 +6366,18 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
if (!arithmetic)
se->expr = fold_convert (type, se->expr);
+ if (!arithmetic)
+ bigshift = build_int_cst (type, 0);
+ else
+ {
+ tree nonneg = fold_build2_loc (input_location, GE_EXPR,
+ logical_type_node, args[0],
+ build_int_cst (TREE_TYPE (args[0]), 0));
+ bigshift = fold_build3_loc (input_location, COND_EXPR, type, nonneg,
+ build_int_cst (type, 0),
+ build_int_cst (type, -1));
+ }
+
/* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
gcc requires a shift width < BIT_SIZE(I), so we have to catch this
special case. */
@@ -6373,7 +6386,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
args[1], num_bits);
se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
- build_int_cst (type, 0), se->expr);
+ bigshift, se->expr);
}
/* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))