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")
/* 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)
/* 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)
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) \
#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)
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)
/* 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)
/* { 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" } */
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;
}
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;
{ 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]" }
}
#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;
}
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" } */
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" } */
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" } */
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" } */
--- /dev/null
+/* 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;
+}
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" } */
/* { 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 ();
if (t4 == 0)
__builtin_abort ();
- void *t5 = __builtin_strncpy (d, s, n);
+ void *t5 = __builtin_strncpy (dn, s, n);
if (t5 == 0)
__builtin_abort ();
__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 ();
}