diff mbox

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

Message ID 5759B6CE.9090900@gmail.com
State New
Headers show

Commit Message

Martin Sebor June 9, 2016, 6:34 p.m. UTC
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

Comments

Jeff Law June 9, 2016, 9:27 p.m. UTC | #1
On 06/09/2016 12:34 PM, Martin Sebor wrote:
> 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
>
>
> gcc-71392.diff
>
>
> 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.
OK for the trunk.

THanks,
Jeff
Richard Biener June 10, 2016, 7:02 a.m. UTC | #2
On Thu, 9 Jun 2016, Martin Sebor wrote:

> 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.

The LTO bits are ok.

Richard.

> 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
> 
>
Eric Botcazou June 11, 2016, 7:12 a.m. UTC | #3
> 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.

3 out of 5 ChangeLog entries are incorrect:

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.


Prefixes of files must always be relative to the ChangeLog's directory:

gcc/ada/ChangeLog:

	PR c/71392
	* gcc-interface/utils.c (handle_nonnull_attribute): ...

gcc/c-family/ChangeLog:

	PR c/71392
	* c-common.c (handle_nonnull_attribute):...

gcc/lto/ChangeLog:

	PR c/71392
	* lto-lang.c (handle_nonnull_attribute): ...
diff mbox

Patch

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