Attached is an updated version of the original patch described below to annotate with the nonnull attribute the Built-In Functions to Perform Arithmetic with Overflow Checking.
Since the machinery that's in place doesn't handle the attribute on type-generic built-ins changes to the (handle_nonnull_attribute function in Ada and LTO besides C were required so I CC the maintainers for these areas. Thanks Martin On 06/02/2016 05:22 PM, Martin Sebor wrote:
In a discussion of a patch in a this area (c/68120 and c++/70507) Jakub noticed that the integer arithmetic built-ins with overflow checking that expect a pointer to an integer as the last argument silently (i.e., without a warning) accept a null pointer. As the test case in the bug referenced in in subject shows, such calls then crash at runtime. The attached patch follows the same approach used by other built ins that take a pointer to an object (such as __built_strlen) to issue a -Wnonnull warning for such invalid calls. Martin
PR c/71392 - SEGV calling integer overflow built-ins with a null pointer gcc/ChangeLog: 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: PR c/71392 * gcc/ada/gcc-interface/utils.c (handle_nonnull_attribute): Accept the nonnull attribute in type-generic builtins. gcc/c-family/ChangeLog: PR c/71392 * gcc/c-family/c-common.c (handle_nonnull_attribute): Accept the nonnull attribute in type-generic builtins. gcc/lto/ChangeLog: PR c/71392 * gcc/lto/lto-lang.c (handle_nonnull_attribute): Accept the nonnull attribute in type-generic builtins. gcc/testsuite/ChangeLog: PR c/71392 * c-c++-common/builtin-arith-overflow-1.c: Add test cases. Index: gcc/ada/gcc-interface/utils.c =================================================================== --- gcc/ada/gcc-interface/utils.c (revision 237267) +++ gcc/ada/gcc-interface/utils.c (working copy) @@ -5833,10 +5833,14 @@ /* 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; Index: gcc/builtin-attrs.def =================================================================== --- gcc/builtin-attrs.def (revision 237267) +++ gcc/builtin-attrs.def (working copy) @@ -165,6 +165,7 @@ /* 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 @@ /* 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) Index: gcc/builtins.def =================================================================== --- gcc/builtins.def (revision 237267) +++ gcc/builtins.def (working copy) @@ -707,31 +707,31 @@ 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) Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 237268) +++ gcc/c-family/c-common.c (working copy) @@ -9040,10 +9040,14 @@ /* 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; Index: gcc/lto/lto-lang.c =================================================================== --- gcc/lto/lto-lang.c (revision 237267) +++ gcc/lto/lto-lang.c (working copy) @@ -352,10 +352,14 @@ /* 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) + || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type))) + return NULL_TREE; } Index: gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c =================================================================== --- gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c (revision 237268) +++ gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c (working copy) @@ -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" } */ @@ -13,6 +24,191 @@ } 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) { int x = __builtin_add_overflow (a, b, c, d); /* { dg-error "too many arguments to function" } */ @@ -27,10 +223,6 @@ 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) {