aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-01-10 13:53:17 -0500
committerJason Merrill <jason@gcc.gnu.org>2020-01-10 13:53:17 -0500
commit337ea6b216afd412b85f3fda78a36467ffe4a817 (patch)
treede398d158f61994e8448352cca3d5cddabccf119 /gcc/cp
parente0804c9b5efdf17bbfb692a787df36b86f71af8d (diff)
downloadgcc-337ea6b216afd412b85f3fda78a36467ffe4a817.zip
gcc-337ea6b216afd412b85f3fda78a36467ffe4a817.tar.gz
gcc-337ea6b216afd412b85f3fda78a36467ffe4a817.tar.bz2
Shorten right-shift again in C++.
Back in SVN r131862 richi removed this code to fix PR 34235, but didn't remove the parallel code from the C front-end because the bug had previously been fixed in r44080. This patch copies the code from C again. * typeck.c (cp_build_binary_op): Restore short_shift code. From-SVN: r280128
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog2
-rw-r--r--gcc/cp/typeck.c38
2 files changed, 40 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1a36cd3..1dad238 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,7 @@
2020-01-10 Jason Merrill <jason@redhat.com>
+ * typeck.c (cp_build_binary_op): Restore short_shift code.
+
PR c++/93143 - incorrect tree sharing with constexpr.
* constexpr.c (cxx_eval_outermost_constant_expr): Don't assume
CONSTRUCTORs are already unshared.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 9f4f535..7b653ceb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4452,6 +4452,10 @@ cp_build_binary_op (const op_location_t &location,
Also implies COMMON. */
int short_compare = 0;
+ /* Nonzero if this is a right-shift operation, which can be computed on the
+ original short and then promoted if the operand is a promoted short. */
+ int short_shift = 0;
+
/* Nonzero means set RESULT_TYPE to the common type of the args. */
int common = 0;
@@ -4844,6 +4848,9 @@ cp_build_binary_op (const op_location_t &location,
}
else
{
+ if (!integer_zerop (op1))
+ short_shift = 1;
+
if (compare_tree_int (const_op1, TYPE_PRECISION (type0)) >= 0
&& (complain & tf_warning)
&& c_inhibit_evaluation_warnings == 0)
@@ -5586,6 +5593,37 @@ cp_build_binary_op (const op_location_t &location,
shorten == -1);
}
+ /* Shifts can be shortened if shifting right. */
+
+ if (short_shift)
+ {
+ int unsigned_arg;
+ tree arg0 = get_narrower (op0, &unsigned_arg);
+
+ final_type = result_type;
+
+ if (arg0 == op0 && final_type == TREE_TYPE (op0))
+ unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
+
+ if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
+ && tree_int_cst_sgn (op1) > 0
+ /* We can shorten only if the shift count is less than the
+ number of bits in the smaller type size. */
+ && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
+ /* We cannot drop an unsigned shift after sign-extension. */
+ && (!TYPE_UNSIGNED (final_type) || unsigned_arg))
+ {
+ /* Do an unsigned shift if the operand was zero-extended. */
+ result_type
+ = c_common_signed_or_unsigned_type (unsigned_arg,
+ TREE_TYPE (arg0));
+ /* Convert value-to-be-shifted to that type. */
+ if (TREE_TYPE (op0) != result_type)
+ op0 = convert (result_type, op0);
+ converted = 1;
+ }
+ }
+
/* Comparison operations are shortened too but differently.
They identify themselves by setting short_compare = 1. */