Index: gcc/fortran/intrinsic.texi =================================================================== --- gcc/fortran/intrinsic.texi (revision 272261) +++ gcc/fortran/intrinsic.texi (working copy) @@ -9689,10 +9689,10 @@ @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 @@ @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 @@ @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 @@ @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 @@ @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 Index: gcc/fortran/trans-intrinsic.c =================================================================== --- gcc/fortran/trans-intrinsic.c (revision 272261) +++ gcc/fortran/trans-intrinsic.c (working copy) @@ -6346,6 +6346,7 @@ bool arithmetic) { tree args[2], type, num_bits, cond; + tree bigshift; gfc_conv_intrinsic_function_args (se, expr, args, 2); @@ -6365,6 +6366,18 @@ 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 @@ 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))