From 4d926e34935942f5aa388388f441e61d7f007c99 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 10 Jun 2016 17:38:19 +0000 Subject: [PATCH] PR c/71392 - SEGV calling integer overflow built-ins with a null pointer gcc/ChangeLog: 2016-06-10 Martin Sebor PR c/71392 * builtin-attrs.def (ATTR_NOTHROW_NONNULL_LEAF_LIST): New macro. (ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF): Same. * builtins.def (BUILT_IN_SADD_OVERFLOW, BUILT_IN_SADDL_OVERFLOW): Use them. (BUILT_IN_SADDLL_OVERFLOW, BUILT_IN_SSUB_OVERFLOW): Same. (BUILT_IN_SSUBL_OVERFLOW, BUILT_IN_SSUBLL_OVERFLOW): Same. (BUILT_IN_SMUL_OVERFLOW, BUILT_IN_SMULL_OVERFLOW): Same. (BUILT_IN_SMULLL_OVERFLOW, BUILT_IN_UADD_OVERFLOW): Same. (BUILT_IN_UADDL_OVERFLOW, BUILT_IN_UADDLL_OVERFLOW): Same. (BUILT_IN_USUB_OVERFLOW, BUILT_IN_USUBL_OVERFLOW): Same. (BUILT_IN_USUBLL_OVERFLOW, BUILT_IN_UMUL_OVERFLOW): Same. (BUILT_IN_UMULL_OVERFLOW, BUILT_IN_UMULLL_OVERFLOW): gcc/ada/ChangeLog: 2016-06-10 Martin Sebor PR c/71392 * gcc/ada/gcc-interface/utils.c (handle_nonnull_attribute): Accept the nonnull attribute in type-generic builtins. gcc/c-family/ChangeLog: 2016-06-10 Martin Sebor PR c/71392 * gcc/c-family/c-common.c (handle_nonnull_attribute): Accept the nonnull attribute in type-generic builtins. gcc/lto/ChangeLog: 2016-06-10 Martin Sebor PR c/71392 * gcc/lto/lto-lang.c (handle_nonnull_attribute): Accept the nonnull attribute in type-generic builtins. gcc/testsuite/ChangeLog: 2016-06-10 Martin Sebor PR c/71392 * c-c++-common/builtin-arith-overflow-1.c: Add test cases. From-SVN: r237314 --- gcc/ChangeLog | 16 ++ gcc/ada/ChangeLog | 6 + gcc/ada/gcc-interface/utils.c | 8 +- gcc/builtin-attrs.def | 5 + gcc/builtins.def | 42 ++-- gcc/c-family/ChangeLog | 6 + gcc/c-family/c-common.c | 8 +- gcc/lto/ChangeLog | 6 + gcc/lto/lto-lang.c | 9 +- gcc/testsuite/ChangeLog | 5 + .../c-c++-common/builtin-arith-overflow-1.c | 202 +++++++++++++++++- 11 files changed, 281 insertions(+), 32 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34eb9e543d6..b4ce8dbaaaa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2016-06-10 Martin Sebor + + PR c/71392 + * builtin-attrs.def (ATTR_NOTHROW_NONNULL_LEAF_LIST): New macro. + (ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF): Same. + * builtins.def (BUILT_IN_SADD_OVERFLOW, BUILT_IN_SADDL_OVERFLOW): Use + them. + (BUILT_IN_SADDLL_OVERFLOW, BUILT_IN_SSUB_OVERFLOW): Same. + (BUILT_IN_SSUBL_OVERFLOW, BUILT_IN_SSUBLL_OVERFLOW): Same. + (BUILT_IN_SMUL_OVERFLOW, BUILT_IN_SMULL_OVERFLOW): Same. + (BUILT_IN_SMULLL_OVERFLOW, BUILT_IN_UADD_OVERFLOW): Same. + (BUILT_IN_UADDL_OVERFLOW, BUILT_IN_UADDLL_OVERFLOW): Same. + (BUILT_IN_USUB_OVERFLOW, BUILT_IN_USUBL_OVERFLOW): Same. + (BUILT_IN_USUBLL_OVERFLOW, BUILT_IN_UMUL_OVERFLOW): Same. + (BUILT_IN_UMULL_OVERFLOW, BUILT_IN_UMULLL_OVERFLOW): + 2016-06-10 Bernd Edlinger * config/arm/arm.h (pool_vector_label, diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 20edf04ee22..7576463b453 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2016-06-10 Martin Sebor + + PR c/71392 + * gcc/ada/gcc-interface/utils.c (handle_nonnull_attribute): Accept + the nonnull attribute in type-generic builtins. + 2016-06-06 Eric Botcazou * gcc-interface/decl.c (Gigi_Equivalent_Type): Make sure equivalent diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 831b6e035aa..1f1e4d3b814 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -5833,10 +5833,14 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), /* If no arguments are specified, all pointer arguments should be non-null. Verify a full prototype is given so that the arguments - will have the correct types when we actually check them later. */ + will have the correct types when we actually check them later. + Avoid diagnosing type-generic built-ins since those have no + prototype. */ if (!args) { - if (!prototype_p (type)) + if (!prototype_p (type) + && (!TYPE_ATTRIBUTES (type) + || !lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)))) { error ("nonnull attribute without arguments on a non-prototype"); *no_add_attrs = true; diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def index 089817a5c4d..99658883872 100644 --- a/gcc/builtin-attrs.def +++ b/gcc/builtin-attrs.def @@ -165,6 +165,7 @@ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL, ATTR_NONNULL, ATTR_NULL, \ /* Nothrow leaf functions whose pointer parameter(s) are all nonnull. */ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_LEAF, ATTR_NONNULL, ATTR_NULL, \ ATTR_NOTHROW_LEAF_LIST) +DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_LEAF_LIST, ATTR_LEAF, ATTR_NULL, ATTR_NOTHROW_NONNULL_LEAF) /* Nothrow functions whose first parameter is a nonnull pointer. */ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, \ ATTR_NOTHROW_LIST) @@ -183,6 +184,10 @@ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_5, ATTR_NONNULL, ATTR_LIST_5, \ /* Nothrow leaf functions which are type-generic. */ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_TYPEGENERIC_LEAF, ATTR_TYPEGENERIC, ATTR_NULL, \ ATTR_NOTHROW_LEAF_LIST) +/* Nothrow nonnull leaf functions that are type-generic. */ +DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF, + ATTR_TYPEGENERIC, ATTR_NULL, + ATTR_NOTHROW_NONNULL_LEAF) /* Nothrow const functions whose pointer parameter(s) are all nonnull. */ DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_NONNULL, ATTR_CONST, ATTR_NULL, \ ATTR_NOTHROW_NONNULL) diff --git a/gcc/builtins.def b/gcc/builtins.def index ca9bafcbf2f..33a7626b70a 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -707,31 +707,31 @@ DEF_C94_BUILTIN (BUILT_IN_TOWLOWER, "towlower", BT_FN_WINT_WINT, ATTR_PUR DEF_C94_BUILTIN (BUILT_IN_TOWUPPER, "towupper", BT_FN_WINT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST) /* Category: integer overflow checking builtins. */ -DEF_GCC_BUILTIN (BUILT_IN_ADD_OVERFLOW, "add_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_TYPEGENERIC_LEAF) -DEF_GCC_BUILTIN (BUILT_IN_SUB_OVERFLOW, "sub_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_TYPEGENERIC_LEAF) -DEF_GCC_BUILTIN (BUILT_IN_MUL_OVERFLOW, "mul_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_TYPEGENERIC_LEAF) +DEF_GCC_BUILTIN (BUILT_IN_ADD_OVERFLOW, "add_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF) +DEF_GCC_BUILTIN (BUILT_IN_SUB_OVERFLOW, "sub_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF) +DEF_GCC_BUILTIN (BUILT_IN_MUL_OVERFLOW, "mul_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF) DEF_GCC_BUILTIN (BUILT_IN_ADD_OVERFLOW_P, "add_overflow_p", BT_FN_BOOL_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) DEF_GCC_BUILTIN (BUILT_IN_SUB_OVERFLOW_P, "sub_overflow_p", BT_FN_BOOL_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) DEF_GCC_BUILTIN (BUILT_IN_MUL_OVERFLOW_P, "mul_overflow_p", BT_FN_BOOL_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) /* Clang compatibility. */ -DEF_GCC_BUILTIN (BUILT_IN_SADD_OVERFLOW, "sadd_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_SADDL_OVERFLOW, "saddl_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_SADDLL_OVERFLOW, "saddll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_SSUB_OVERFLOW, "ssub_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_SSUBL_OVERFLOW, "ssubl_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_SSUBLL_OVERFLOW, "ssubll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_SMUL_OVERFLOW, "smul_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_SMULL_OVERFLOW, "smull_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_SMULLL_OVERFLOW, "smulll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_UADD_OVERFLOW, "uadd_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_UADDL_OVERFLOW, "uaddl_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_UADDLL_OVERFLOW, "uaddll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_USUB_OVERFLOW, "usub_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_USUBL_OVERFLOW, "usubl_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_USUBLL_OVERFLOW, "usubll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_UMUL_OVERFLOW, "umul_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_UMULL_OVERFLOW, "umull_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_UMULLL_OVERFLOW, "umulll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SADD_OVERFLOW, "sadd_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SADDL_OVERFLOW, "saddl_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SADDLL_OVERFLOW, "saddll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SSUB_OVERFLOW, "ssub_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SSUBL_OVERFLOW, "ssubl_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SSUBLL_OVERFLOW, "ssubll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SMUL_OVERFLOW, "smul_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SMULL_OVERFLOW, "smull_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SMULLL_OVERFLOW, "smulll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_UADD_OVERFLOW, "uadd_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_UADDL_OVERFLOW, "uaddl_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_UADDLL_OVERFLOW, "uaddll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_USUB_OVERFLOW, "usub_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_USUBL_OVERFLOW, "usubl_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_USUBLL_OVERFLOW, "usubll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_UMUL_OVERFLOW, "umul_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_UMULL_OVERFLOW, "umull_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_UMULLL_OVERFLOW, "umulll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) /* Category: miscellaneous builtins. */ DEF_LIB_BUILTIN (BUILT_IN_ABORT, "abort", BT_FN_VOID, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 23ff800e41f..88cbd871d10 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2016-06-10 Martin Sebor + + PR c/71392 + * gcc/c-family/c-common.c (handle_nonnull_attribute): Accept + the nonnull attribute in type-generic builtins. + 2016-06-09 Martin Sebor PR c/70883 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 94005ff8260..85f3a03146e 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -9040,10 +9040,14 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), /* If no arguments are specified, all pointer arguments should be non-null. Verify a full prototype is given so that the arguments - will have the correct types when we actually check them later. */ + will have the correct types when we actually check them later. + Avoid diagnosing type-generic built-ins since those have no + prototype. */ if (!args) { - if (!prototype_p (type)) + if (!prototype_p (type) + && (!TYPE_ATTRIBUTES (type) + || !lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)))) { error ("nonnull attribute without arguments on a non-prototype"); *no_add_attrs = true; diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 06458d46033..9323a255151 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,9 @@ +2016-06-10 Martin Sebor + + PR c/71392 + * gcc/lto/lto-lang.c (handle_nonnull_attribute): Accept the nonnull + attribute in type-generic builtins. + 2016-05-16 Jan Hubicka * lto-partition.c (add_symbol_to_partition_1): Likewise. diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index b5efe3aab7e..301cf2124a6 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -352,10 +352,15 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), /* If no arguments are specified, all pointer arguments should be non-null. Verify a full prototype is given so that the arguments - will have the correct types when we actually check them later. */ + will have the correct types when we actually check them later. + Avoid diagnosing type-generic built-ins since those have no + prototype. */ if (!args) { - gcc_assert (prototype_p (type)); + gcc_assert (prototype_p (type) + || !TYPE_ATTRIBUTES (type) + || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type))); + return NULL_TREE; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b76e477d3e5..932567e1bd4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-06-10 Martin Sebor + + PR c/71392 + * c-c++-common/builtin-arith-overflow-1.c: Add test cases. + 2016-06-10 Jeff Law PR tree-optimization/71335 diff --git a/gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c b/gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c index 3332c4ec44d..3576748e1ee 100644 --- a/gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c +++ b/gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c @@ -1,7 +1,18 @@ +/* Test exercising invalid calls to arithmetic overflow checking built-ins, + including PR c/71392 - SEGV calling integer overflow built-ins with a null + pointer, (issuing a warning for such invocations). */ /* { dg-do compile } */ +/* { dg-additional-options "-Wnonnull" } + +/* Verify that calls with fewer or more than 3 arguments to the generic + __builtin_op_overflow functions are rejected. */ + +#ifndef __cplusplus +#define bool _Bool +#endif int -f1 (void) +generic_0 (void) { int x = __builtin_add_overflow (); /* { dg-error "too few arguments to function" } */ x += __builtin_sub_overflow (); /* { dg-error "too few arguments to function" } */ @@ -12,6 +23,191 @@ f1 (void) return x; } +int +generic_1 (int a) +{ + int x = __builtin_add_overflow (a); /* { dg-error "too few arguments to function" } */ + x += __builtin_sub_overflow (a); /* { dg-error "too few arguments to function" } */ + x += __builtin_mul_overflow (a); /* { dg-error "too few arguments to function" } */ + + /* Literal argument. */ + x += __builtin_add_overflow (1); /* { dg-error "too few arguments to function" } */ + x += __builtin_sub_overflow (2); /* { dg-error "too few arguments to function" } */ + x += __builtin_mul_overflow (3); /* { dg-error "too few arguments to function" } */ + return x; +} + +int +generic_2 (int a, int b) +{ + int x = __builtin_add_overflow (a, b);/* { dg-error "too few arguments to function" } */ + x += __builtin_sub_overflow (a, b); /* { dg-error "too few arguments to function" } */ + x += __builtin_mul_overflow (a, b); /* { dg-error "too few arguments to function" } */ + x += __builtin_add_overflow (a, 1); /* { dg-error "too few arguments to function" } */ + x += __builtin_sub_overflow (a, 2); /* { dg-error "too few arguments to function" } */ + x += __builtin_mul_overflow (a, 3); /* { dg-error "too few arguments to function" } */ + x += __builtin_add_overflow (4, b); /* { dg-error "too few arguments to function" } */ + x += __builtin_sub_overflow (5, b); /* { dg-error "too few arguments to function" } */ + x += __builtin_mul_overflow (6, b); /* { dg-error "too few arguments to function" } */ + return x; +} + +/* Verify that calls with the correct number of arguments to the generic + __builtin_op_overflow functions are accepted. */ + +int +generic_3 (int a, int b, int c) +{ + int x = __builtin_add_overflow (a, b, &c); + x += __builtin_sub_overflow (a, b, &c); + x += __builtin_mul_overflow (a, b, &c); + x += __builtin_add_overflow (a, 1, &c); + x += __builtin_sub_overflow (a, 2, &c); + x += __builtin_mul_overflow (a, 3, &c); + x += __builtin_add_overflow (4, b, &c); + x += __builtin_sub_overflow (5, b, &c); + x += __builtin_mul_overflow (6, b, &c); + x += __builtin_add_overflow (7, 8, &c); + x += __builtin_sub_overflow (9, 10, &c); + x += __builtin_mul_overflow (11, 12, &c); + + /* Verify that a null pointer to an integer is diagnosed. */ + + /* The following two are rejected due to c/71479 - error on + __builtin_add_overflow with bool or enum pointer as last argument. + + x += __builtin_add_overflow (0, 0, (bool *)0); + + enum E { e0 }; + x += __builtin_add_overflow (0, 0, (enum E *)0); + */ + + x += __builtin_sub_overflow (0, 0, (char *)0); /* { dg-warning "null argument" } */ + x += __builtin_add_overflow (0, 0, (short *)0); /* { dg-warning "null argument" } */ + x += __builtin_add_overflow (a, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_sub_overflow (a, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_mul_overflow (a, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_add_overflow (a, 1, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_sub_overflow (a, 2, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_mul_overflow (a, 3, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_add_overflow (4, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_sub_overflow (5, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_mul_overflow (6, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_add_overflow (7, 8, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_sub_overflow (9, 10, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_mul_overflow (11, 12, (int *)0); /* { dg-warning "null argument" } */ + + return x; +} + +int +generic_4 (int a, int b, int *c, int d) +{ + int x = __builtin_add_overflow (a, b, c, d); /* { dg-error "too many arguments to function" } */ + x += __builtin_sub_overflow (a, b, c, d, d, d); /* { dg-error "too many arguments to function" } */ + x += __builtin_sub_overflow (a, b, c, d); /* { dg-error "too many arguments to function" } */ + x += __builtin_mul_overflow (a, b, c, d); /* { dg-error "too many arguments to function" } */ + return x; +} + +/* Verify that calls with fewer or more than 3 arguments to the type + specific forms of the __builtin_op_overflow functions are rejected. */ + +int +generic_wrong_type (int a, int b) +{ + void *p = 0; + double d = 0; + int x = __builtin_add_overflow (a, b, p); /* { dg-error "does not have pointer to integer type" } */ + x += __builtin_sub_overflow (a, b, &p); /* { dg-error "does not have pointer to integer type" } */ + x += __builtin_mul_overflow (a, b, &d); /* { dg-error "does not have pointer to integer type" } */ + + /* Also verify literal arguments. */ + x += __builtin_add_overflow (1, 1, p); /* { dg-error "does not have pointer to integer type" } */ + x += __builtin_sub_overflow (1, 1, &p); /* { dg-error "does not have pointer to integer type" } */ + x += __builtin_mul_overflow (1, 1, &d); /* { dg-error "does not have pointer to integer type" } */ + return x; +} + +/* Verify that calls with fewer than 2 or more than 3 arguments to + the typed __builtin_op_overflow functions are rejected. */ +int +typed_0 (void) +{ + int x = __builtin_add_overflow (); /* { dg-error "too few arguments to function" } */ + x += __builtin_sub_overflow (); /* { dg-error "too few arguments to function" } */ + x += __builtin_mul_overflow (); /* { dg-error "too few arguments to function" } */ + return x; +} + +int +typed_1 (int a) +{ + int x = __builtin_sadd_overflow (a); /* { dg-error "too few arguments to function" } */ + x += __builtin_ssub_overflow (a); /* { dg-error "too few arguments to function" } */ + x += __builtin_smul_overflow (a); /* { dg-error "too few arguments to function" } */ + return x; +} + +int +typed_2 (int a, int b) +{ + int x = __builtin_sadd_overflow (a, b); /* { dg-error "too few arguments to function" } */ + x += __builtin_ssub_overflow (a, b); /* { dg-error "too few arguments to function" } */ + x += __builtin_smul_overflow (a, b); /* { dg-error "too few arguments to function" } */ + return x; +} + +/* Exercise PR c/71392 - SEGV calling integer overflow built-ins with + a null pointer. Verify that calls with a null argument are diagnosed + with -Wnonnull. */ + +int +typed_3_null (int a, int b) +{ + int x = 0; + + x += __builtin_sadd_overflow (a, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_uadd_overflow (a, b, (unsigned *)0); /* { dg-warning "null argument" } */ + + x += __builtin_saddl_overflow (a, b, (long *)0); /* { dg-warning "null argument" } */ + x += __builtin_uaddl_overflow (a, b, (unsigned long *)0); /* { dg-warning "null argument" } */ + + x += __builtin_saddll_overflow (a, b, (long long *)0); /* { dg-warning "null argument" } */ + x += __builtin_uaddll_overflow (a, b, (unsigned long long *)0); /* { dg-warning "null argument" } */ + + + x += __builtin_ssub_overflow (a, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_usub_overflow (a, b, (unsigned *)0); /* { dg-warning "null argument" } */ + + x += __builtin_ssubl_overflow (a, b, (long *)0); /* { dg-warning "null argument" } */ + x += __builtin_usubl_overflow (a, b, (unsigned long *)0); /* { dg-warning "null argument" } */ + + x += __builtin_ssubll_overflow (a, b, (long long *)0); /* { dg-warning "null argument" } */ + x += __builtin_usubll_overflow (a, b, (unsigned long long *)0); /* { dg-warning "null argument" } */ + + + x += __builtin_smul_overflow (a, b, (int *)0); /* { dg-warning "null argument" } */ + x += __builtin_umul_overflow (a, b, (unsigned *)0); /* { dg-warning "null argument" } */ + + x += __builtin_smull_overflow (a, b, (long *)0); /* { dg-warning "null argument" } */ + x += __builtin_umull_overflow (a, b, (unsigned long *)0); /* { dg-warning "null argument" } */ + + x += __builtin_smulll_overflow (a, b, (long long *)0); /* { dg-warning "null argument" } */ + x += __builtin_umulll_overflow (a, b, (unsigned long long *)0); /* { dg-warning "null argument" } */ + + return x; +} + +int +typed_4 (int a, int b, int *c, int d) +{ + int x = __builtin_sadd_overflow (a, b, c, d); /* { dg-error "too many arguments to function" } */ + x += __builtin_ssub_overflow (a, b, c, d); /* { dg-error "too many arguments to function" } */ + x += __builtin_smul_overflow (a, b, c, d); /* { dg-error "too many arguments to function" } */ + return x; +} + int f2 (int a, int b, int *c, int d) { @@ -27,10 +223,6 @@ f2 (int a, int b, int *c, int d) enum E { e0 = 0, e1 = 1 }; -#ifndef __cplusplus -#define bool _Bool -#endif - int f3 (float fa, int a, _Complex long int ca, double fb, void *pb, int b, enum E eb, bool bb, int *c) { -- 2.30.2