diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def
index 7af5e92cbd0f16c358edb7781395f6106f2cb44a..850efea11ca0a59a41002d93dfa93e41fab7161d 100644
--- a/gcc/builtin-attrs.def
+++ b/gcc/builtin-attrs.def
@@ -100,6 +100,7 @@ DEF_ATTR_IDENT (ATTR_FORMAT, "format")
 DEF_ATTR_IDENT (ATTR_FORMAT_ARG, "format_arg")
 DEF_ATTR_IDENT (ATTR_MALLOC, "malloc")
 DEF_ATTR_IDENT (ATTR_NONNULL, "nonnull")
+DEF_ATTR_IDENT (ATTR_NONNULL_IF_NONZERO, "nonnull_if_nonzero")
 DEF_ATTR_IDENT (ATTR_NORETURN, "noreturn")
 DEF_ATTR_IDENT (ATTR_NOTHROW, "nothrow")
 DEF_ATTR_IDENT (ATTR_LEAF, "leaf")
@@ -233,6 +234,18 @@ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_4, ATTR_NONNULL, ATTR_LIST_4, \
 /* Nothrow functions whose fifth parameter is a nonnull pointer.  */
 DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_5, ATTR_NONNULL, ATTR_LIST_5, \
 			ATTR_NOTHROW_LIST)
+/* Nothrow leaf functions whose selected pointer parameter(s) are conditionally
+   nonnull.  */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_IF12_LEAF, ATTR_NONNULL_IF_NONZERO, \
+			ATTR_LIST_1_2, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_IF13_LEAF, ATTR_NONNULL_IF_NONZERO, \
+			ATTR_LIST_1_3, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_IF123_LEAF, ATTR_NONNULL_IF_NONZERO, \
+			ATTR_LIST_2_3, ATTR_NOTHROW_NONNULL_IF13_LEAF)
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_IF23_LEAF, ATTR_NONNULL_IF_NONZERO, \
+			ATTR_LIST_2_3, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_IF23_LEAF, ATTR_NONNULL, \
+			ATTR_LIST_1, ATTR_NOTHROW_NONNULL_IF23_LEAF)
 
 /* Same as ATTR_NONNULL_1.  */
 DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_1, ATTR_NONNULL, ATTR_LIST_1, ATTR_NULL)
@@ -300,6 +313,14 @@ DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL, ATTR_PURE, ATTR_NULL, \
 /* Nothrow pure leaf functions whose pointer parameter(s) are all nonnull.  */
 DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_LEAF, ATTR_PURE, ATTR_NULL, \
 			ATTR_NOTHROW_NONNULL_LEAF)
+/* Nothrow pure leaf functions whose selected pointer parameter(s) are
+   conditionally nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_IF12_LEAF, ATTR_PURE, ATTR_NULL, \
+			ATTR_NOTHROW_NONNULL_IF12_LEAF)
+DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_IF13_LEAF, ATTR_PURE, ATTR_NULL, \
+			ATTR_NOTHROW_NONNULL_IF13_LEAF)
+DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_IF123_LEAF, ATTR_PURE, ATTR_NULL, \
+			ATTR_NOTHROW_NONNULL_IF123_LEAF)
 /* Nothrow malloc functions whose pointer parameter(s) are all nonnull.  */
 DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL, ATTR_WARN_UNUSED_RESULT, ATTR_NULL, \
 			ATTR_NOTHROW_NONNULL)
@@ -310,6 +331,14 @@ DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF, ATTR_WARN_UNUS
 			ATTR_NOTHROW_NONNULL_LEAF)
 DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF, ATTR_MALLOC, ATTR_NULL, \
 			ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
+/* Nothrow malloc leaf functions whose selected pointer parameter(s) are
+   conditionally nonnull.  */
+DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_IF12_LEAF, \
+			ATTR_WARN_UNUSED_RESULT, ATTR_NULL, \
+			ATTR_NOTHROW_NONNULL_IF12_LEAF)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_IF12_LEAF, \
+			ATTR_MALLOC, ATTR_NULL, \
+			ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_IF12_LEAF)
 
 /* Construct a tree for the format attribute (and implicitly nonnull).  */
 #define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES)				 \
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 89fc74654ca74ecce49971da40d466ad1644ccac..ff470051e54ebcd5b1ca225c939a9e4ad03c7cce 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -846,19 +846,19 @@ DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CTAN, "ctan", CPROJ_TYPE, ATTR_MATHFN_F
 #undef CPROJ_TYPE
 
 /* Category: string/memory builtins.  */
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_BCMP, "bcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_BCOPY, "bcopy", BT_FN_VOID_CONST_PTR_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_BZERO, "bzero", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_BCMP, "bcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_IF123_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_BCOPY, "bcopy", BT_FN_VOID_CONST_PTR_PTR_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_BZERO, "bzero", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_NONNULL_IF12_LEAF)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_INDEX, "index", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN        (BUILT_IN_MEMCHR, "memchr", BT_FN_PTR_CONST_PTR_INT_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN        (BUILT_IN_MEMCMP, "memcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN	       (BUILT_IN_MEMCPY, "memcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN	       (BUILT_IN_MEMMOVE, "memmove", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMPCPY, "mempcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
-DEF_LIB_BUILTIN	       (BUILT_IN_MEMSET, "memset", BT_FN_PTR_PTR_INT_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN        (BUILT_IN_MEMCHR, "memchr", BT_FN_PTR_CONST_PTR_INT_SIZE, ATTR_PURE_NOTHROW_NONNULL_IF13_LEAF)
+DEF_LIB_BUILTIN        (BUILT_IN_MEMCMP, "memcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_IF123_LEAF)
+DEF_LIB_BUILTIN	       (BUILT_IN_MEMCPY, "memcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
+DEF_LIB_BUILTIN	       (BUILT_IN_MEMMOVE, "memmove", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMPCPY, "mempcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
+DEF_LIB_BUILTIN	       (BUILT_IN_MEMSET, "memset", BT_FN_PTR_PTR_INT_SIZE, ATTR_NOTHROW_NONNULL_IF13_LEAF)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_RINDEX, "rindex", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_STPCPY, "stpcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_RETNONNULL_NOTHROW_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_STPNCPY, "stpncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_STPNCPY, "stpncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRCASECMP, "strcasecmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
 DEF_LIB_BUILTIN        (BUILT_IN_STRCAT, "strcat", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_LEAF)
 DEF_LIB_BUILTIN        (BUILT_IN_STRCHR, "strchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
@@ -866,13 +866,13 @@ DEF_LIB_BUILTIN        (BUILT_IN_STRCMP, "strcmp", BT_FN_INT_CONST_STRING_CONST_
 DEF_LIB_BUILTIN        (BUILT_IN_STRCPY, "strcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_LEAF)
 DEF_LIB_BUILTIN        (BUILT_IN_STRCSPN, "strcspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
 DEF_C23_BUILTIN        (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
-DEF_C23_BUILTIN        (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
+DEF_C23_BUILTIN        (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_IF12_LEAF)
 DEF_LIB_BUILTIN        (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRNCASECMP, "strncasecmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN        (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN        (BUILT_IN_STRNCMP, "strncmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN        (BUILT_IN_STRNCPY, "strncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRNLEN, "strnlen", BT_FN_SIZE_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRNCASECMP, "strncasecmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_IF123_LEAF)
+DEF_LIB_BUILTIN        (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_1_IF23_LEAF)
+DEF_LIB_BUILTIN        (BUILT_IN_STRNCMP, "strncmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_IF123_LEAF)
+DEF_LIB_BUILTIN        (BUILT_IN_STRNCPY, "strncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRNLEN, "strnlen", BT_FN_SIZE_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_IF12_LEAF)
 DEF_LIB_BUILTIN        (BUILT_IN_STRPBRK, "strpbrk", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
 DEF_LIB_BUILTIN        (BUILT_IN_STRRCHR, "strrchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
 DEF_LIB_BUILTIN        (BUILT_IN_STRSPN, "strspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
@@ -1148,16 +1148,16 @@ DEF_BUILTIN_STUB (BUILT_IN_STRNCMP_EQ, "__builtin_strncmp_eq")
 /* Object size checking builtins.  */
 DEF_GCC_BUILTIN	       (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN	       (BUILT_IN_DYNAMIC_OBJECT_SIZE, "dynamic_object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMSET_CHK, "__memset_chk", BT_FN_PTR_PTR_INT_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_MEMSET_CHK, "__memset_chk", BT_FN_PTR_PTR_INT_SIZE_SIZE, ATTR_NOTHROW_NONNULL_IF13_LEAF)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_STPCPY_CHK, "__stpcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_STPNCPY_CHK, "__stpncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_STPNCPY_CHK, "__stpncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRCAT_CHK, "__strcat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRCPY_CHK, "__strcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRNCPY_CHK, "__strncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_1_IF23_LEAF)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRNCPY_CHK, "__strncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_IF123_LEAF)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_SNPRINTF_CHK, "__snprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_5_6)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_SPRINTF_CHK, "__sprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR, ATTR_NOTHROW_NONNULL_1_FORMAT_PRINTF_4_5)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_VSNPRINTF_CHK, "__vsnprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_NOTHROW_5_0)
diff --git a/gcc/testsuite/c-c++-common/ubsan/nonnull-1.c b/gcc/testsuite/c-c++-common/ubsan/nonnull-1.c
index d3063ca4a6fcb890186e3fcd152ac63fc1a3cb40..635ffdc4b712e93f1944a438f18c7543c6a6f2c2 100644
--- a/gcc/testsuite/c-c++-common/ubsan/nonnull-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/nonnull-1.c
@@ -34,5 +34,4 @@ main ()
 
 /* { dg-output "\.c:13:\[0-9]*:\[^\n\r]*null pointer returned from function declared to never return null\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*\.c:29:\[0-9]*:\[^\n\r]*null pointer passed as argument 1, which is declared to never be null\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*\.c:30:\[0-9]*:\[^\n\r]*null pointer passed as argument 3, which is declared to never be null\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*\.c:31:\[0-9]*:\[^\n\r]*null pointer passed as argument 1, which is declared to never be null" } */
+/* { dg-output "\[^\n\r]*\.c:30:\[0-9]*:\[^\n\r]*null pointer passed as argument 3, which is declared to never be null" } */
diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-14.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-14.c
index cc536d714313e8d3fd33733251f65d7b89c0ec73..f361550c1e29eb3bbd07cec4d4ec39223642657f 100644
--- a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-14.c
+++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-14.c
@@ -45,8 +45,14 @@ int test_builtin_calls (size_t n)
   r += strcmp ((char*)0, "");               // { dg-warning "\\\[-Wnonnull]" }
   r += strcmp ("", (char*)0);               // { dg-warning "\\\[-Wnonnull]" }
 
-  r += strncmp ((char*)0, "", n);           // { dg-warning "\\\[-Wnonnull]" }
-  r += strncmp ("", (char*)0, n);           // { dg-warning "\\\[-Wnonnull]" }
+  r += strncmp ((char*)0, "", 1);           // { dg-warning "\\\[-Wnonnull]" }
+  r += strncmp ("", (char*)0, 1);           // { dg-warning "\\\[-Wnonnull]" }
+
+  r += strncmp ((char*)0, "", n);
+  r += strncmp ("", (char*)0, n);
+
+  r += strncmp ((char*)0, "", 0);
+  r += strncmp ("", (char*)0, 0);
 
   return r;
 }
diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-15.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-15.c
index 3c32a5fc54559c011ea9d77fb2ab42a261bb5d36..e9750cfb94f2489c64d672e87be7305b6cce01df 100644
--- a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-15.c
+++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-15.c
@@ -30,8 +30,14 @@ int test_builtin_calls_fe (size_t n)
   r += strcmp ((char*)0, "");               // { dg-warning "\\\[-Wnonnull]" }
   r += strcmp ("", (char*)0);               // { dg-warning "\\\[-Wnonnull]" }
 
-  r += strncmp ((char*)0, "", n);           // { dg-warning "\\\[-Wnonnull]" }
-  r += strncmp ("", (char*)0, n);           // { dg-warning "\\\[-Wnonnull]" }
+  r += strncmp ((char*)0, "", 1);           // { dg-warning "\\\[-Wnonnull]" }
+  r += strncmp ("", (char*)0, 1);           // { dg-warning "\\\[-Wnonnull]" }
+
+  r += strncmp ((char*)0, "", n);
+  r += strncmp ("", (char*)0, n);
+
+  r += strncmp ((char*)0, "", 0);
+  r += strncmp ("", (char*)0, 0);
 
   r += strlen ((char*)0);                   // { dg-warning "\\\[-Wnonnull]" }
   return r;
diff --git a/gcc/testsuite/gcc.dg/Wnonnull-2.c b/gcc/testsuite/gcc.dg/Wnonnull-2.c
index d870473d5a92acd36bcdd71d5a11e6ef691abf9a..646c460bdbb69d2553b56663d6770f35ddc0e475 100644
--- a/gcc/testsuite/gcc.dg/Wnonnull-2.c
+++ b/gcc/testsuite/gcc.dg/Wnonnull-2.c
@@ -4,52 +4,122 @@
    { dg-do compile }
    { dg-options "-O0 -Wall" } */
 
-void zero0 (void *p, unsigned n)
+void
+zero0 (void *p, unsigned n)
 {
-  __builtin_memset (0, 0, n);           // { dg-warning "\\\[-Wnonnull]" }
+  __builtin_memset (0, 0, 0);
+  __builtin_memset (0, 0, n);
+  __builtin_memset (0, 0, 1);           // { dg-warning "\\\[-Wnonnull]" }
 }
 
-void zero1 (void *p, unsigned n)
+void
+zero1 (void *p, unsigned n)
 {
-  __builtin_bzero (0, n);               // { dg-warning "\\\[-Wnonnull]" }
+  __builtin_bzero (0, 0);
+  __builtin_bzero (0, n);
+  __builtin_bzero (0, 2);               // { dg-warning "\\\[-Wnonnull]" }
 }
 
-void copy0 (void *p, const void *q, unsigned n)
+void
+copy0 (void *p, const void *q, unsigned n)
 {
-  __builtin_memcpy (0, q, n);           // { dg-warning "\\\[-Wnonnull]" }
+  __builtin_memcpy (0, q, 0);
+  __builtin_memcpy (0, q, n);
+  __builtin_memcpy (0, q, 3);           // { dg-warning "\\\[-Wnonnull]" }
 }
 
-void copy1 (void *p, const void *q, unsigned n)
+void
+copy1 (void *p, const void *q, unsigned n)
 {
-  __builtin_memcpy (0, q, n);           // { dg-warning "\\\[-Wnonnull]" }
+  __builtin_memcpy (p, 0, 0);
+  __builtin_memcpy (p, 0, n);
+  __builtin_memcpy (p, 0, 4);           // { dg-warning "\\\[-Wnonnull]" }
 }
 
-void copy2 (void *p, const void *q, unsigned n)
+void
+copy2 (void *p, const void *q, unsigned n)
 {
-  __builtin_bcopy (q, 0, n);            // { dg-warning "\\\[-Wnonnull]" }
+  __builtin_bcopy (0, p, 0);
+  __builtin_bcopy (0, p, n);
+  __builtin_bcopy (0, p, 5);            // { dg-warning "\\\[-Wnonnull]" }
 }
 
-void copy3 (void *p, const void *q, unsigned n)
+void
+copy3 (void *p, const void *q, unsigned n)
 {
-  __builtin_bcopy (q, 0, n);            // { dg-warning "\\\[-Wnonnull]" }
+  __builtin_bcopy (q, 0, 0);
+  __builtin_bcopy (q, 0, n);
+  __builtin_bcopy (q, 0, 6);            // { dg-warning "\\\[-Wnonnull]" }
 }
 
-int cmp0 (const void *p, const void *q, unsigned n)
+int
+cmp0 (const void *p, const void *q, unsigned n)
 {
-  return __builtin_memcmp (0, q, n);    // { dg-warning "\\\[-Wnonnull]" }
+  return __builtin_memcmp (0, q, 0);
 }
 
-int cmp1 (const void *p, const void *q, unsigned n)
+int
+cmp1 (const void *p, const void *q, unsigned n)
 {
-  return __builtin_memcmp (0, q, n);    // { dg-warning "\\\[-Wnonnull]" }
+  return __builtin_memcmp (0, q, 0);
 }
 
-int cmp2 (const void *p, const void *q, unsigned n)
+int
+cmp2 (const void *p, const void *q, unsigned n)
 {
-  return __builtin_bcmp (0, q, n);      // { dg-warning "\\\[-Wnonnull]" }
+  return __builtin_bcmp (0, q, 0);
 }
 
-int cmp3 (const void *p, const void *q, unsigned n)
+int
+cmp3 (const void *p, const void *q, unsigned n)
 {
-  return __builtin_bcmp (p, 0, n);      // { dg-warning "\\\[-Wnonnull]" }
+  return __builtin_bcmp (p, 0, 0);
+}
+
+int
+cmp4 (const void *p, const void *q, unsigned n)
+{
+  return __builtin_memcmp (0, q, n);
+}
+
+int
+cmp5 (const void *p, const void *q, unsigned n)
+{
+  return __builtin_memcmp (0, q, n);
+}
+
+int
+cmp6 (const void *p, const void *q, unsigned n)
+{
+  return __builtin_bcmp (0, q, n);
+}
+
+int
+cmp7 (const void *p, const void *q, unsigned n)
+{
+  return __builtin_bcmp (p, 0, n);
+}
+
+int
+cmp8 (const void *p, const void *q, unsigned n)
+{
+  return __builtin_memcmp (0, q, 41);    // { dg-warning "\\\[-Wnonnull]" }
+}
+
+int
+cmp9 (const void *p, const void *q, unsigned n)
+{
+  return __builtin_memcmp (0, q, 42);    // { dg-warning "\\\[-Wnonnull]" }
+}
+
+int
+cmp10 (const void *p, const void *q, unsigned n)
+{
+  return __builtin_bcmp (0, q, 43);      // { dg-warning "\\\[-Wnonnull]" }
+}
+
+int
+cmp11 (const void *p, const void *q, unsigned n)
+{
+  return __builtin_bcmp (p, 0, 44);      // { dg-warning "\\\[-Wnonnull]" }
 }
diff --git a/gcc/testsuite/gcc.dg/Wnonnull-3.c b/gcc/testsuite/gcc.dg/Wnonnull-3.c
index ad016df93319906f677eddc5490f3ad503452cc8..b11c9dcf1a2922ffad892eb39ec68f852475ddd4 100644
--- a/gcc/testsuite/gcc.dg/Wnonnull-3.c
+++ b/gcc/testsuite/gcc.dg/Wnonnull-3.c
@@ -6,66 +6,164 @@
 
 #define NOIPA __attribute__ ((noipa))
 
-NOIPA void zero0 (void *p, unsigned n)
+NOIPA void
+zero0 (void *p, unsigned n)
 {
   if (p == 0)
+    __builtin_memset (p, 0, 0);
+  if (p == 0)
+    __builtin_memset (p, 0, n);
+  if (p == 0 && n != 0)
     __builtin_memset (p, 0, n);         // { dg-warning "\\\[-Wnonnull]" }
 }
 
-NOIPA void zero1 (void *p, unsigned n)
+NOIPA void
+zero1 (void *p, unsigned n)
 {
   if (p == 0)
+    __builtin_bzero (p, 0);
+  if (p == 0)
+    __builtin_bzero (p, n);
+  if (p == 0 && n != 0)
     __builtin_bzero (p, n);             // { dg-warning "\\\[-Wnonnull]" }
 }
 
-NOIPA void copy0 (void *p, const void *q, unsigned n)
+NOIPA void
+copy0 (void *p, const void *q, unsigned n)
 {
   if (p == 0)
+    __builtin_memcpy (p, q, 0);
+  if (p == 0)
+    __builtin_memcpy (p, q, n);
+  if (p == 0 && n != 0)
     __builtin_memcpy (p, q, n);         // { dg-warning "\\\[-Wnonnull]" }
 }
 
-NOIPA void copy1 (void *p, const void *q, unsigned n)
+NOIPA void
+copy1 (void *p, const void *q, unsigned n)
 {
   if (q == 0)
+    __builtin_memcpy (p, q, 0);
+  if (q == 0)
+    __builtin_memcpy (p, q, n);
+  if (q == 0 && n != 0)
     __builtin_memcpy (p, q, n);         // { dg-warning "\\\[-Wnonnull]" }
 }
 
-NOIPA void copy2 (void *p, const void *q, unsigned n)
+NOIPA void
+copy2 (void *p, const void *q, unsigned n)
 {
   if (p == 0)
+    __builtin_bcopy (q, p, 0);
+  if (p == 0)
+    __builtin_bcopy (q, p, n);
+  if (p == 0 && n != 0)
     __builtin_bcopy (q, p, n);          // { dg-warning "\\\[-Wnonnull]" }
 }
 
-NOIPA void copy3 (void *p, const void *q, unsigned n)
+NOIPA void
+copy3 (void *p, const void *q, unsigned n)
 {
   if (q == 0)
+    __builtin_bcopy (q, p, 0);
+  if (q == 0)
+    __builtin_bcopy (q, p, n);
+  if (q == 0 && n != 0)
     __builtin_bcopy (q, p, n);          // { dg-warning "\\\[-Wnonnull]" }
 }
 
-NOIPA int cmp0 (const void *p, const void *q, unsigned n)
+NOIPA int
+cmp0 (const void *p, const void *q, unsigned n)
 {
   if (p == 0)
-    return __builtin_memcmp (p, q, n);  // { dg-warning "\\\[-Wnonnull]" }
+    return __builtin_memcmp (p, q, 0);
   return 0;
 }
 
-NOIPA int cmp1 (const void *p, const void *q, unsigned n)
+NOIPA int
+cmp1 (const void *p, const void *q, unsigned n)
 {
   if (q == 0)
-    return __builtin_memcmp (p, q, n);  // { dg-warning "\\\[-Wnonnull]" }
+    return __builtin_memcmp (p, q, 0);
   return 0;
 }
 
-NOIPA int cmp2 (const void *p, const void *q, unsigned n)
+NOIPA int
+cmp2 (const void *p, const void *q, unsigned n)
 {
   if (p == 0)
-    return __builtin_bcmp (p, q, n);    // { dg-warning "\\\[-Wnonnull]" }
+    return __builtin_bcmp (p, q, 0);
+  return 0;
+}
+
+NOIPA int
+cmp3 (const void *p, const void *q, unsigned n)
+{
+  if (q == 0)
+    return __builtin_bcmp (p, q, 0);
+  return 0;
+}
+
+NOIPA int
+cmp4 (const void *p, const void *q, unsigned n)
+{
+  if (p == 0)
+    return __builtin_memcmp (p, q, n);
+  return 0;
+}
+
+NOIPA int
+cmp5 (const void *p, const void *q, unsigned n)
+{
+  if (q == 0)
+    return __builtin_memcmp (p, q, n);
   return 0;
 }
 
-NOIPA int cmp3 (const void *p, const void *q, unsigned n)
+NOIPA int
+cmp6 (const void *p, const void *q, unsigned n)
+{
+  if (p == 0)
+    return __builtin_bcmp (p, q, n);
+  return 0;
+}
+
+NOIPA int
+cmp7 (const void *p, const void *q, unsigned n)
 {
   if (q == 0)
+    return __builtin_bcmp (p, q, n);
+  return 0;
+}
+
+NOIPA int
+cmp8 (const void *p, const void *q, unsigned n)
+{
+  if (p == 0 && n != 0)
+    return __builtin_memcmp (p, q, n);  // { dg-warning "\\\[-Wnonnull]" }
+  return 0;
+}
+
+NOIPA int
+cmp9 (const void *p, const void *q, unsigned n)
+{
+  if (q == 0 && n != 0)
+    return __builtin_memcmp (p, q, n);  // { dg-warning "\\\[-Wnonnull]" }
+  return 0;
+}
+
+NOIPA int
+cmp10 (const void *p, const void *q, unsigned n)
+{
+  if (p == 0 && n != 0)
+    return __builtin_bcmp (p, q, n);    // { dg-warning "\\\[-Wnonnull]" }
+  return 0;
+}
+
+NOIPA int
+cmp11 (const void *p, const void *q, unsigned n)
+{
+  if (q == 0 && n != 0)
     return __builtin_bcmp (p, q, n);    // { dg-warning "\\\[-Wnonnull]" }
   return 0;
 }
diff --git a/gcc/testsuite/gcc.dg/builtins-nonnull.c b/gcc/testsuite/gcc.dg/builtins-nonnull.c
index f8c482e9825110d6b83b91bbbc5b35ae32eceab5..d59579d78c8e5ae52c8de5036b17e1c0fbdb7d86 100644
--- a/gcc/testsuite/gcc.dg/builtins-nonnull.c
+++ b/gcc/testsuite/gcc.dg/builtins-nonnull.c
@@ -24,6 +24,9 @@ void sink (int, ...);
 
 void test_memfuncs (void *s, unsigned n)
 {
+  if (n == 0)
+    return;
+
   /* Bzero is not declared attribute nonnull (maybe it should be?)
      but it's transformed into a call to memset() which is.  */
   bzero (null (), n);             /* { dg-warning "argument 1 null where non-null expected" } */
@@ -51,6 +54,9 @@ void test_memfuncs (void *s, unsigned n)
 
 void test_memfuncs_chk (void *s, unsigned n)
 {
+  if (n == 0)
+    return;
+
   T (memcpy (null (), s, n));     /* { dg-warning "argument 1 null where non-null expected" } */
   T (memcpy (s, null (), n));     /* { dg-warning "argument 2 null where non-null expected" } */
 
@@ -76,6 +82,9 @@ void test_memfuncs_chk (void *s, unsigned n)
 
 void test_strfuncs (char *s, unsigned n)
 {
+  if (n == 0)
+    return;
+
   T (strcat (null (), s));        /* { dg-warning "argument 1 null where non-null expected" } */
   T (strcat (s, null ()));        /* { dg-warning "argument 2 null where non-null expected" } */
 
@@ -119,6 +128,9 @@ void test_strfuncs (char *s, unsigned n)
 
 void test_strfuncs_chk (char *s, unsigned n)
 {
+  if (n == 0)
+    return;
+
   T (strcat (null (), s));        /* { dg-warning "argument 1 null where non-null expected" } */
   T (strcat (s, null ()));        /* { dg-warning "argument 2 null where non-null expected" } */
 
diff --git a/gcc/testsuite/gcc.dg/nonnull-11.c b/gcc/testsuite/gcc.dg/nonnull-11.c
new file mode 100644
index 0000000000000000000000000000000000000000..976022aa2249a470b5e385488cbea7d3d5483849
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/nonnull-11.c
@@ -0,0 +1,56 @@
+/* Test for the "nonnull" function attribute on builtins.  Use the
+   "__builtin_" style below so we don't need prototypes.  */
+/* { dg-do compile } */
+/* { dg-options "-Wnonnull" } */
+
+#include <stddef.h>
+
+void
+use (void *x, size_t y)
+{
+  (void) x;
+  (void) y;
+}
+
+void *
+foo (void *p, char *s)
+{
+  __builtin_bzero (NULL, 0);
+  __builtin_bcopy (NULL, p, 0);
+  __builtin_bcopy (p, NULL, 0);
+  __builtin_bcmp (NULL, p, 0);
+  __builtin_bcmp (p, NULL, 0);
+
+  __builtin_memcpy (p, NULL, 0);
+  __builtin_memcpy (NULL, p, 0);
+  __builtin_memmove (p, NULL, 0);
+  __builtin_memmove (NULL, p, 0);
+  __builtin_memcmp (p, NULL, 0);
+  __builtin_memcmp (NULL, p, 0);
+  __builtin_memset (NULL, 0, 0);
+  __builtin_mempcpy (p, NULL, 0);
+  __builtin_mempcpy (NULL, p, 0);
+
+  __builtin_strncat (NULL, s, 0);  /* { dg-warning "null" "null pointer check" } */
+  __builtin_strncat (s, NULL, 0);
+  __builtin_stpncpy (NULL, s, 0);
+  __builtin_stpncpy (s, NULL, 0);
+  __builtin_strncpy (NULL, s, 0);
+  __builtin_strncpy (s, NULL, 0);
+  __builtin_strncasecmp (NULL, s, 0);
+  __builtin_strncasecmp (s, NULL, 0);
+  __builtin_strncmp (NULL, s, 0);
+  __builtin_strncmp (s, NULL, 0);
+  void *p1 = __builtin_strndup (NULL, 0);
+
+  size_t n = __builtin_strnlen (NULL, 16);  /* { dg-warning "null" "null pointer check" } */
+  use (NULL, n);
+  n = __builtin_strnlen (NULL, 0);
+  use (NULL, n);
+
+  void *q = __builtin_memchr (NULL, ' ', 16);  /* { dg-warning "null" "null pointer check" } */
+  use (q, 0);
+  q = __builtin_memchr (NULL, ' ', 0);
+  use (q, 0);
+  return p1;
+}
diff --git a/gcc/testsuite/gcc.dg/nonnull-3.c b/gcc/testsuite/gcc.dg/nonnull-3.c
index c52fe2c830c800a4e2126be2fb4f9859ae21692d..fc12cb0c3620a5b5235409a9dda1d185513b56dc 100644
--- a/gcc/testsuite/gcc.dg/nonnull-3.c
+++ b/gcc/testsuite/gcc.dg/nonnull-3.c
@@ -9,11 +9,11 @@
 void
 foo (void *p, char *s)
 {
-  __builtin_bzero (NULL, 0);  /* { dg-warning "null" "pr80936" } */
-  __builtin_bcopy (NULL, p, 0);  /* { dg-warning "null" "pr80936" } */
-  __builtin_bcopy (p, NULL, 0);  /* { dg-warning "null" "pr80936" } */
-  __builtin_bcmp (NULL, p, 0);  /* { dg-warning "null" "pr80936" } */
-  __builtin_bcmp (p, NULL, 0);  /* { dg-warning "null" "pr80936" } */
+  __builtin_bzero (NULL, 16);  /* { dg-warning "null" "pr80936" } */
+  __builtin_bcopy (NULL, p, 16);  /* { dg-warning "null" "pr80936" } */
+  __builtin_bcopy (p, NULL, 16);  /* { dg-warning "null" "pr80936" } */
+  __builtin_bcmp (NULL, p, 16);  /* { dg-warning "null" "pr80936" } */
+  __builtin_bcmp (p, NULL, 16);  /* { dg-warning "null" "pr80936" } */
   __builtin_index (NULL, 16);  /* { dg-warning "null" "null pointer check" } */
   __builtin_rindex (NULL, 16);  /* { dg-warning "null" "null pointer check" } */
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr78154.c b/gcc/testsuite/gcc.dg/tree-ssa/pr78154.c
index 3ba8f64e2664bbd9570f28df6699838e01ef8379..4fc300792bb6f01e282a68d8b4be7be7c1883680 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr78154.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr78154.c
@@ -2,17 +2,20 @@
 /* { dg-options "-O2 -fdump-tree-evrp-slim -fdelete-null-pointer-checks" } */
 /* { dg-skip-if "" { keeps_null_pointer_checks } } */
 
-void f(void *d, const void *s, __SIZE_TYPE__ n)
+void f(void *d, void *dn, const void *s, __SIZE_TYPE__ n)
 {
-  void *t1 = __builtin_memcpy (d, s, n);
+  if (!dn)
+    return;
+
+  void *t1 = __builtin_memcpy (dn, s, n);
   if (t1 == 0)
     __builtin_abort ();
 
-  void *t2 = __builtin_memmove (d, s, n);
+  void *t2 = __builtin_memmove (dn, s, n);
   if (t2 == 0)
     __builtin_abort ();
 
-  void *t3 = __builtin_memset (d, 0, n);
+  void *t3 = __builtin_memset (dn, 0, n);
   if (t3 == 0)
     __builtin_abort ();
 
@@ -20,7 +23,7 @@ void f(void *d, const void *s, __SIZE_TYPE__ n)
   if (t4 == 0)
     __builtin_abort ();
 
-  void *t5 = __builtin_strncpy (d, s, n);
+  void *t5 = __builtin_strncpy (dn, s, n);
   if (t5 == 0)
     __builtin_abort ();
 
@@ -37,7 +40,25 @@ void f(void *d, const void *s, __SIZE_TYPE__ n)
     __builtin_abort ();
 
   void *t9 = __builtin_stpncpy (d, s, n);
-  if (t9 == 0)
+  /* We can't handle this one anymore, as stpncpy (NULL, s, 0)
+     can return NULL and it doesn't always return the first argument.  */
+  if (0 && t9 == 0)
+    __builtin_abort ();
+
+  void *t10 = __builtin_memcpy (d, s, 42);
+  if (t10 == 0)
+    __builtin_abort ();
+
+  void *t11 = __builtin_memmove (d, s, 42);
+  if (t11 == 0)
+    __builtin_abort ();
+
+  void *t12 = __builtin_memset (d, 0, 42);
+  if (t12 == 0)
+    __builtin_abort ();
+
+  void *t13 = __builtin_strncpy (d, s, 42);
+  if (t13 == 0)
     __builtin_abort ();
 }