aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const-call.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fold-const-call.cc')
-rw-r--r--gcc/fold-const-call.cc41
1 files changed, 41 insertions, 0 deletions
diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc
index 663eae2..00ff4e4 100644
--- a/gcc/fold-const-call.cc
+++ b/gcc/fold-const-call.cc
@@ -1669,6 +1669,7 @@ fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
{
const char *p0, *p1;
char c;
+ tree_code subcode;
switch (fn)
{
case CFN_BUILT_IN_STRSPN:
@@ -1738,6 +1739,46 @@ fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
case CFN_FOLD_LEFT_PLUS:
return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
+ case CFN_UBSAN_CHECK_ADD:
+ case CFN_ADD_OVERFLOW:
+ subcode = PLUS_EXPR;
+ goto arith_overflow;
+
+ case CFN_UBSAN_CHECK_SUB:
+ case CFN_SUB_OVERFLOW:
+ subcode = MINUS_EXPR;
+ goto arith_overflow;
+
+ case CFN_UBSAN_CHECK_MUL:
+ case CFN_MUL_OVERFLOW:
+ subcode = MULT_EXPR;
+ goto arith_overflow;
+
+ arith_overflow:
+ if (integer_cst_p (arg0) && integer_cst_p (arg1))
+ {
+ tree itype
+ = TREE_CODE (type) == COMPLEX_TYPE ? TREE_TYPE (type) : type;
+ bool ovf = false;
+ tree r = int_const_binop (subcode, fold_convert (itype, arg0),
+ fold_convert (itype, arg1));
+ if (!r || TREE_CODE (r) != INTEGER_CST)
+ return NULL_TREE;
+ if (arith_overflowed_p (subcode, itype, arg0, arg1))
+ ovf = true;
+ if (TREE_OVERFLOW (r))
+ r = drop_tree_overflow (r);
+ if (itype == type)
+ {
+ if (ovf)
+ return NULL_TREE;
+ return r;
+ }
+ else
+ return build_complex (type, r, build_int_cst (itype, ovf));
+ }
+ return NULL_TREE;
+
default:
return fold_const_call_1 (fn, type, arg0, arg1);
}