aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-11-12 13:28:06 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2014-11-12 13:28:06 +0100
commit1304953e4fa46305d1ce0b884bf2f58e08409ff3 (patch)
tree551c242f138ac032ded6f0171ee39700e6ea032e /gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c
parent6a3cbe90926bbe62fcbce85dc735cbf077fd0f0b (diff)
downloadgcc-1304953e4fa46305d1ce0b884bf2f58e08409ff3.zip
gcc-1304953e4fa46305d1ce0b884bf2f58e08409ff3.tar.gz
gcc-1304953e4fa46305d1ce0b884bf2f58e08409ff3.tar.bz2
re PR c/59708 (clang-compatible checked arithmetic builtins)
PR c/59708 * builtin-attrs.def (ATTR_NOTHROW_TYPEGENERIC_LEAF): New attribute. * builtins.c (fold_builtin_arith_overflow): New function. (fold_builtin_3): Use it. * builtins.def (BUILT_IN_ADD_OVERFLOW, BUILT_IN_SUB_OVERFLOW, BUILT_IN_MUL_OVERFLOW, BUILT_IN_SADD_OVERFLOW, BUILT_IN_SADDL_OVERFLOW, BUILT_IN_SADDLL_OVERFLOW, BUILT_IN_SSUB_OVERFLOW, BUILT_IN_SSUBL_OVERFLOW, BUILT_IN_SSUBLL_OVERFLOW, BUILT_IN_SMUL_OVERFLOW, BUILT_IN_SMULL_OVERFLOW, BUILT_IN_SMULLL_OVERFLOW, BUILT_IN_UADDL_OVERFLOW, BUILT_IN_UADDLL_OVERFLOW, BUILT_IN_USUB_OVERFLOW, BUILT_IN_USUBL_OVERFLOW, BUILT_IN_USUBLL_OVERFLOW, BUILT_IN_UMUL_OVERFLOW, BUILT_IN_UMULL_OVERFLOW, BUILT_IN_UMULLL_OVERFLOW): New built-in functions. * builtin-types.def (BT_PTR_UINT, BT_PTR_ULONG, BT_PTR_LONGLONG, BT_FN_BOOL_INT_INT_INTPTR, BT_FN_BOOL_LONG_LONG_LONGPTR, BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, BT_FN_BOOL_UINT_UINT_UINTPTR, BT_FN_BOOL_ULONG_ULONG_ULONGPTR, BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, BT_FN_BOOL_VAR): New. * expr.c (write_complex_part): Remove prototype, no longer static. * expr.h (write_complex_part): New prototype. * function.c (aggregate_value_p): For internal functions return 0. * gimple-fold.c (arith_overflowed_p): New functions. (gimple_fold_call): Fold {ADD,SUB,MUL}_OVERFLOW internal calls. * gimple-fold.h (arith_overflowed_p): New prototype. * tree-ssa-dce.c: Include tree-ssa-propagate.h and gimple-fold.h. (find_non_realpart_uses, maybe_optimize_arith_overflow): New functions. (eliminate_unnecessary_stmts): Transform {ADD,SUB,MUL}_OVERFLOW into COMPLEX_CST/COMPLEX_EXPR if IMAGPART_EXPR of the result is never used. * gimplify.c (gimplify_call_expr): Handle gimplification of internal calls with lhs. * internal-fn.c (get_range_pos_neg, get_min_precision, expand_arith_overflow_result_store): New functions. (ubsan_expand_si_overflow_addsub_check): Renamed to ... (expand_addsub_overflow): ... this. Add LOC, LHS, ARG0, ARG1, UNSR_P, UNS0_P, UNS1_P, IS_UBSAN arguments, remove STMT argument. Handle ADD_OVERFLOW and SUB_OVERFLOW expansion. (ubsan_expand_si_overflow_neg_check): Renamed to ... (expand_neg_overflow): ... this. Add LOC, LHS, ARG1, IS_UBSAN arguments, remove STMT argument. Handle SUB_OVERFLOW with 0 as first argument expansion. (ubsan_expand_si_overflow_mul_check): Renamed to ... (expand_mul_overflow): ... this. Add LOC, LHS, ARG0, ARG1, UNSR_P, UNS0_P, UNS1_P, IS_UBSAN arguments, remove STMT argument. Handle MUL_OVERFLOW expansion. (expand_UBSAN_CHECK_ADD): Use expand_addsub_overflow, prepare arguments for it. (expand_UBSAN_CHECK_SUB): Use expand_addsub_overflow or expand_neg_overflow, prepare arguments for it. (expand_UBSAN_CHECK_MUL): Use expand_mul_overflow, prepare arguments for it. (expand_arith_overflow, expand_ADD_OVERFLOW, expand_SUB_OVERFLOW, expand_MUL_OVERFLOW): New functions. * internal-fn.def (ADD_OVERFLOW, SUB_OVERFLOW, MUL_OVERFLOW): New internal functions. * tree-vrp.c (check_for_binary_op_overflow): New function. (extract_range_basic): Handle {REAL,IMAG}PART_EXPR if the operand is SSA_NAME set by {ADD,SUB,MUL}_OVERFLOW internal functions. (simplify_internal_call_using_ranges): Handle {ADD,SUB,MUL}_OVERFLOW internal functions. * optabs.def (umulv4_optab): New optab. * config/i386/i386.md (umulv<mode>4, <u>mulvqi4): New define_expands. (*umulv<mode>4, *<u>mulvqi4): New define_insns. * doc/extend.texi (Integer Overflow Builtins): Document __builtin_*_overflow. c-family/ * c-common.c (check_builtin_function_arguments): Handle BUILT_IN_{ADD,SUB,MUL}_OVERFLOW. testsuite/ * c-c++-common/builtin-arith-overflow-1.c: New test. * c-c++-common/torture/builtin-arith-overflow-10.c: New test. * c-c++-common/torture/builtin-arith-overflow-11.c: New test. * c-c++-common/torture/builtin-arith-overflow-12.c: New test. * c-c++-common/torture/builtin-arith-overflow-12.h: New file. * c-c++-common/torture/builtin-arith-overflow-13.c: New test. * c-c++-common/torture/builtin-arith-overflow-14.c: New test. * c-c++-common/torture/builtin-arith-overflow-15.c: New test. * c-c++-common/torture/builtin-arith-overflow-16.c: New test. * c-c++-common/torture/builtin-arith-overflow-17.c: New test. * c-c++-common/torture/builtin-arith-overflow-18.c: New test. * c-c++-common/torture/builtin-arith-overflow-1.c: New test. * c-c++-common/torture/builtin-arith-overflow-1.h: New file. * c-c++-common/torture/builtin-arith-overflow-2.c: New test. * c-c++-common/torture/builtin-arith-overflow-3.c: New test. * c-c++-common/torture/builtin-arith-overflow-4.c: New test. * c-c++-common/torture/builtin-arith-overflow-5.c: New test. * c-c++-common/torture/builtin-arith-overflow-6.c: New test. * c-c++-common/torture/builtin-arith-overflow-7.c: New test. * c-c++-common/torture/builtin-arith-overflow-8.c: New test. * c-c++-common/torture/builtin-arith-overflow-9.c: New test. * c-c++-common/torture/builtin-arith-overflow.h: New file. * gcc.dg/builtin-arith-overflow-1.c: New test. * gcc.dg/builtin-arith-overflow-2.c: New test. From-SVN: r217415
Diffstat (limited to 'gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c')
-rw-r--r--gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c b/gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c
new file mode 100644
index 0000000..b9c1517
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c
@@ -0,0 +1,132 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-optimized -g" } */
+
+/* SUB_OVERFLOW should be folded into unsigned subtraction,
+ because ovf is never used. */
+__attribute__((noinline, noclone)) int
+fn1 (int x, unsigned int y)
+{
+ int res;
+ int ovf = __builtin_sub_overflow (x, y, &res);
+ int res2 = res;
+ int res3 = res2 - 2;
+ (void) ovf;
+ return res;
+}
+
+/* MUL_OVERFLOW should be folded into unsigned multiplication,
+ because ovf is never used. */
+__attribute__((noinline, noclone)) int
+fn2 (char x, long int y)
+{
+ short int res;
+ int ovf = __builtin_mul_overflow (x, y, &res);
+ int res2 = res;
+ int res3 = res2 - 2;
+ (void) ovf;
+ return res;
+}
+
+#if __SIZEOF_INT__ > __SIZEOF_SHORT__ && __SIZEOF_INT__ > 1
+/* ADD_OVERFLOW should be folded into unsigned addition,
+ because it never overflows. */
+__attribute__((noinline, noclone)) int
+fn3 (char x, unsigned short y, int *ovf)
+{
+ int res;
+ *ovf = __builtin_add_overflow (x, y, &res);
+ return res;
+}
+#endif
+
+/* MUL_OVERFLOW should be folded into unsigned multiplication,
+ because it never overflows. */
+__attribute__((noinline, noclone)) long int
+fn4 (long int x, long int y, int *ovf)
+{
+ long int res;
+ x &= 65535;
+ y = (y & 65535) - 32768;
+ *ovf = __builtin_mul_overflow (x, y, &res);
+ return res;
+}
+
+#if __SIZEOF_INT__ > 1
+/* MUL_OVERFLOW should be folded into unsigned multiplication,
+ because it always overflows. */
+__attribute__((noinline, noclone)) signed char
+fn5 (long int x, long int y, int *ovf)
+{
+ signed char res;
+ x = (x & 63) + (__SCHAR_MAX__ / 4);
+ y = (y & 3) + 5;
+ *ovf = __builtin_mul_overflow (x, y, &res);
+ return res;
+}
+#endif
+
+/* ADD_OVERFLOW should be folded into unsigned additrion,
+ because it never overflows. */
+__attribute__((noinline, noclone)) unsigned char
+fn6 (unsigned char x, unsigned char y, int *ovf)
+{
+ unsigned char res;
+ x = (x & 63) + ((unsigned char) ~0 - 66);
+ y = (y & 3);
+ *ovf = __builtin_add_overflow (x, y, &res);
+ return res;
+}
+
+/* ADD_OVERFLOW should be folded into unsigned additrion,
+ because it always overflows. */
+__attribute__((noinline, noclone)) unsigned char
+fn7 (unsigned char x, unsigned char y, int *ovf)
+{
+ unsigned char res;
+ x = (x & 15) + ((unsigned char) ~0 - 15);
+ y = (y & 3) + 16;
+ *ovf = __builtin_add_overflow (x, y, &res);
+ return res;
+}
+
+int
+main ()
+{
+ int ovf;
+ if (fn1 (-10, __INT_MAX__) != (int) (-10U - __INT_MAX__)
+ || fn2 (0, 0) != 0
+ || fn2 (32, 16383) != (short int) 524256ULL)
+ __builtin_abort ();
+#if __SIZEOF_INT__ > __SIZEOF_SHORT__ && __SIZEOF_INT__ > 1
+ if (fn3 (__SCHAR_MAX__, (unsigned short) ~0, &ovf) != (int) (__SCHAR_MAX__ + (unsigned short) ~0)
+ || ovf
+ || fn3 (-__SCHAR_MAX__ - 1, 0, &ovf) != (int) (-__SCHAR_MAX__ - 1)
+ || ovf)
+ __builtin_abort ();
+#endif
+ if (fn4 (65535, 0, &ovf) != 65535L * -32768 || ovf)
+ __builtin_abort ();
+#if __SIZEOF_INT__ > 1
+ if (fn5 (0, 0, &ovf) != (signed char) (__SCHAR_MAX__ / 4 * 5)
+ || !ovf
+ || fn5 (63, 3, &ovf) != (signed char) ((__SCHAR_MAX__ / 4 + 63) * 8)
+ || !ovf)
+ __builtin_abort ();
+#endif
+ if (fn6 (0, 0, &ovf) != (unsigned char) ~0 - 66
+ || ovf
+ || fn6 (63, 3, &ovf) != (unsigned char) ~0
+ || ovf)
+ __builtin_abort ();
+ if (fn7 (0, 0, &ovf) != 0
+ || !ovf
+ || fn7 (63, 3, &ovf) != 18
+ || !ovf)
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "ADD_OVERFLOW" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "SUB_OVERFLOW" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "MUL_OVERFLOW" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */