diff options
author | Harald Anlauf <anlauf@gmx.de> | 2023-02-27 21:37:11 +0100 |
---|---|---|
committer | Harald Anlauf <anlauf@gmx.de> | 2023-02-27 22:30:29 +0100 |
commit | 6cce953ebec274f1468d5d3a0697cf05bb43b8f6 (patch) | |
tree | 0cb73689f4ede61e1c284024071ead1e17d0e6c6 /gcc/fortran | |
parent | 8020c9c42349f51f75239b9d35a2be41848a97bd (diff) | |
download | gcc-6cce953ebec274f1468d5d3a0697cf05bb43b8f6.zip gcc-6cce953ebec274f1468d5d3a0697cf05bb43b8f6.tar.gz gcc-6cce953ebec274f1468d5d3a0697cf05bb43b8f6.tar.bz2 |
Fortran: fix corner case of IBITS intrinsic [PR108937]
gcc/fortran/ChangeLog:
PR fortran/108937
* trans-intrinsic.cc (gfc_conv_intrinsic_ibits): Handle corner case
LEN argument of IBITS equal to BITSIZE(I).
gcc/testsuite/ChangeLog:
PR fortran/108937
* gfortran.dg/ibits_2.f90: New test.
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/trans-intrinsic.cc | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 21eeb12..3cce9c0 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -6638,6 +6638,7 @@ gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr) tree type; tree tmp; tree mask; + tree num_bits, cond; gfc_conv_intrinsic_function_args (se, expr, args, 3); type = TREE_TYPE (args[0]); @@ -6678,8 +6679,17 @@ gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr) "in intrinsic IBITS", tmp1, tmp2, nbits); } + /* The Fortran standard allows (shift width) LEN <= BIT_SIZE(I), whereas + gcc requires a shift width < BIT_SIZE(I), so we have to catch this + special case. See also gfc_conv_intrinsic_ishft (). */ + num_bits = build_int_cst (TREE_TYPE (args[2]), TYPE_PRECISION (type)); + mask = build_int_cst (type, -1); mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]); + cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[2], + num_bits); + mask = fold_build3_loc (input_location, COND_EXPR, type, cond, + build_int_cst (type, 0), mask); mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask); tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]); |