summaryrefslogtreecommitdiff
path: root/gcc/convert.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/convert.c')
-rw-r--r--gcc/convert.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/gcc/convert.c b/gcc/convert.c
index f54b6d9adfe..48f3f944c71 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "flags.h"
#include "convert.h"
+#include "diagnostic-core.h"
#include "toplev.h"
#include "langhooks.h"
@@ -768,13 +769,19 @@ convert_to_integer (tree type, tree expr)
|| ex_form == LSHIFT_EXPR
/* If we have !flag_wrapv, and either ARG0 or
ARG1 is of a signed type, we have to do
- PLUS_EXPR or MINUS_EXPR in an unsigned
- type. Otherwise, we would introduce
+ PLUS_EXPR, MINUS_EXPR or MULT_EXPR in an unsigned
+ type in case the operation in outprec precision
+ could overflow. Otherwise, we would introduce
signed-overflow undefinedness. */
|| ((!TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
|| !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1)))
+ && ((TYPE_PRECISION (TREE_TYPE (arg0)) * 2u
+ > outprec)
+ || (TYPE_PRECISION (TREE_TYPE (arg1)) * 2u
+ > outprec))
&& (ex_form == PLUS_EXPR
- || ex_form == MINUS_EXPR)))
+ || ex_form == MINUS_EXPR
+ || ex_form == MULT_EXPR)))
typex = unsigned_type_for (typex);
else
typex = signed_type_for (typex);