This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PING] [PATCH] c/71392 - SEGV calling integer overflow built-ins with a null pointer


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)
 {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]