From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id 2497F3849ACF; Fri, 19 Apr 2024 22:13:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2497F3849ACF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1713564801; bh=OJFxJsl7FzzvSFve+ijnBKv5ggnmyBIh15Yd9886bVs=; h=From:To:Subject:Date:From; b=BG2G8d9KqIku7xxid6QIsKClewJA3dq8fmfrtEmNX2CaHQG65+Hmh/5nYjtBqsAPj A2YMDwRund/nolpd4oLbbMp84aRSvh0uqcZBW8+xHfzIuWqs2qkennon/al99tCoVV JS2Gcb3Pn+0YRr81rVZ1pUtgoXiZ4+Awz/vcAni0= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-10046] c-family: Allow arguments with NULLPTR_TYPE as sentinels [PR114780] X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/master X-Git-Oldrev: a39983bf58d3097c472252f6989d19b60909dd9a X-Git-Newrev: 2afdecccbaf5c5b1c7a235509b37092540906c02 Message-Id: <20240419221321.2497F3849ACF@sourceware.org> Date: Fri, 19 Apr 2024 22:13:21 +0000 (GMT) List-Id: https://gcc.gnu.org/g:2afdecccbaf5c5b1c7a235509b37092540906c02 commit r14-10046-g2afdecccbaf5c5b1c7a235509b37092540906c02 Author: Jakub Jelinek Date: Sat Apr 20 00:12:36 2024 +0200 c-family: Allow arguments with NULLPTR_TYPE as sentinels [PR114780] While in C++ the ellipsis argument conversions include "An argument that has type cv std::nullptr_t is converted to type void*" in C23 a nullptr_t argument is not promoted in any way, but va_arg description says: "the type of the next argument is nullptr_t and type is a pointer type that has the same representation and alignment requirements as a pointer to a character type." So, while in C++ check_function_sentinel will never see NULLPTR_TYPE, for C23 it can see that and currently we incorrectly warn about those. The only question is whether we should warn on any argument with nullptr_t type or just about nullptr (nullptr_t argument with integer_zerop value). Through undefined behavior guess one could pass non-NULL pointer that way, say by union { void *p; nullptr_t q; } u; u.p = &whatever; and pass u.q to ..., but valid code should always pass something that will read as (char *) 0 when read using va_arg (ap, char *), so I think it is better not to warn rather than warn in those cases. Note, clang seems to pass (void *)0 rather than expression of nullptr_t type to ellipsis in C23 mode as if it did the C++ ellipsis argument conversions, in that case guess not warning about that would be even safer, but what GCC does I think follows the spec more closely, even when in a valid program one shouldn't be able to observe the difference. 2024-04-20 Jakub Jelinek PR c/114780 * c-common.cc (check_function_sentinel): Allow as sentinel any argument of NULLPTR_TYPE. * gcc.dg/format/sentinel-2.c: New test. Diff: --- gcc/c-family/c-common.cc | 1 + gcc/testsuite/gcc.dg/format/sentinel-2.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 6fa8243b02b..01e3d247fc2 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -5783,6 +5783,7 @@ check_function_sentinel (const_tree fntype, int nargs, tree *argarray) sentinel = fold_for_warn (argarray[nargs - 1 - pos]); if ((!POINTER_TYPE_P (TREE_TYPE (sentinel)) || !integer_zerop (sentinel)) + && TREE_CODE (TREE_TYPE (sentinel)) != NULLPTR_TYPE /* Although __null (in C++) is only an integer we allow it nevertheless, as we are guaranteed that it's exactly as wide as a pointer, and we don't want to force diff --git a/gcc/testsuite/gcc.dg/format/sentinel-2.c b/gcc/testsuite/gcc.dg/format/sentinel-2.c new file mode 100644 index 00000000000..4c29f6fb818 --- /dev/null +++ b/gcc/testsuite/gcc.dg/format/sentinel-2.c @@ -0,0 +1,21 @@ +/* PR c/114780 */ +/* { dg-do compile } */ +/* { dg-options "-std=c23 -Wformat" } */ + +#include + +[[gnu::sentinel]] void foo (int, ...); +[[gnu::sentinel]] void bar (...); + +void +baz (nullptr_t p) +{ + foo (1, 2, nullptr); + foo (3, 4, 5, p); + bar (nullptr); + bar (p); + foo (6, 7, 0); // { dg-warning "missing sentinel in function call" } + bar (0); // { dg-warning "missing sentinel in function call" } + foo (8, 9, NULL); + bar (NULL); +}