https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120520
--- Comment #3 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>: https://gcc.gnu.org/g:e33409a83251d057eb03b22e8f95f3ad7bf822e1 commit r16-1775-ge33409a83251d057eb03b22e8f95f3ad7bf822e1 Author: Jakub Jelinek <ja...@redhat.com> Date: Mon Jun 30 11:08:16 2025 +0200 Extend nonnull_if_nonzero attribute [PR120520] C2Y voted in the https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3466.pdf paper, which clarifies some of the conditional nonnull cases. For strncat/__strncat_chk no changes are necessary, we already use __attribute__((nonnull (1), nonnull_if_nonzero (2, 3))) attributes on the builtin and glibc can do the same too, meaning that first argument must be nonnull always and second must be nonnull if the third one is nonzero. The problem is with the fread/fwrite changes, where the paper adds: If size or nmemb is zero, +ptr may be a null pointer, fread returns zero and the contents of the array and the state of the stream remain unchanged. and ditto for fwrite, so the two argument nonnull_if_nonzero attribute isn't usable to express that, because whether the pointer can be null depends on 2 integral arguments rather than one. The following patch extends the nonnull_if_nonzero attribute, so that instead of requiring 2 arguments it allows 2 or 3, the first one is still the pointer argument index which sometimes must not be null and the other one or two are integral arguments, if there are 2, the invalid case is only if pointer is null and both the integral arguments are nonzero. 2025-06-30 Jakub Jelinek <ja...@redhat.com> PR c/120520 PR c/117023 gcc/ * builtin-attrs.def (DEF_LIST_INT_INT_INT): Define it and use for 1,2,3. (ATTR_NONNULL_IF123_LIST): New DEF_ATTR_TREE_LIST. (ATTR_NONNULL_4_IF123_LIST): Likewise. * builtins.def (BUILT_IN_FWRITE): Use ATTR_NONNULL_4_IF123_LIST instead of ATTR_NONNULL_LIST. (BUILT_IN_FWRITE_UNLOCKED): Likewise. * gimple.h (infer_nonnull_range_by_attribute): Add another optional tree * argument defaulted to NULL. * gimple.cc (infer_nonnull_range_by_attribute): Add OP3 argument, handle 3 argument nonnull_if_nonzero attribute. * builtins.cc (validate_arglist): Handle 3 argument nonnull_if_nonzero attribute. * tree-ssa-ccp.cc (pass_post_ipa_warn::execute): Likewise. * ubsan.cc (instrument_nonnull_arg): Adjust infer_nonnull_range_by_attribute caller, handle 3 argument nonnull_if_nonzero attribute. * gimple-range-infer.cc (gimple_infer_range::gimple_infer_range): Handle 3 argument nonnull_if_nonzero attribute. * doc/extend.texi (nonnull_if_nonzero): Document 3 argument version of the attribute. gcc/c-family/ * c-attribs.cc (c_common_gnu_attributes): Allow 2 or 3 arguments for nonnull_if_nonzero attribute instead of only 2. (handle_nonnull_if_nonzero_attribute): Handle 3 argument nonnull_if_nonzero. * c-common.cc (struct nonnull_arg_ctx): Rename other member to other1, add other2 member. (check_function_nonnull): Clear a if nonnull attribute has an argument. Adjust for nonnull_arg_ctx changes. Handle 3 argument nonnull_if_nonzero attribute. (check_nonnull_arg): Adjust for nonnull_arg_ctx changes, emit different diagnostics for 3 argument nonnull_if_nonzero attributes. (check_function_arguments): Adjust ctx var initialization. gcc/analyzer/ * sm-malloc.cc (malloc_state_machine::on_stmt): Handle 3 argument nonnull_if_nonzero attribute. gcc/testsuite/ * gcc.dg/nonnull-9.c: Tweak for 3 argument nonnull_if_nonzero attribute support, add further tests. * gcc.dg/nonnull-12.c: New test. * gcc.dg/nonnull-13.c: New test. * gcc.dg/nonnull-14.c: New test. * c-c++-common/ubsan/nonnull-8.c: New test. * c-c++-common/ubsan/nonnull-9.c: New test.