From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id 977203858417; Sun, 21 Apr 2024 04:09:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 977203858417 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1713672588; bh=AciCPCNrZ3eys4J040lJvAaGYM89q6YMYV5WT9txyuQ=; h=From:To:Subject:Date:From; b=LrMx6PICEr+T7+ZYru2bCxg91ljhaRSp/h/T8rHLYXqw348sHj1bckG2ii2LZp0+G lsVvYxMi7SNZIS2ZH5xfrtCA3iPNynnubLQEfT7A7jyczojzG8HuJes9z8jj02Ry/K Zh5GeVKjm4IK/SYcF5fAanlFBa6gIQHQRcHKAgMw= 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 r13-8637] c-family: Allow arguments with NULLPTR_TYPE as sentinels [PR114780] X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/releases/gcc-13 X-Git-Oldrev: ab3b83afc149edda11fa3c7cbb3815606731003b X-Git-Newrev: e802786436851b1f5efca21a14d4f41c83c83f4f Message-Id: <20240421040948.977203858417@sourceware.org> Date: Sun, 21 Apr 2024 04:09:48 +0000 (GMT) List-Id: https://gcc.gnu.org/g:e802786436851b1f5efca21a14d4f41c83c83f4f commit r13-8637-ge802786436851b1f5efca21a14d4f41c83c83f4f 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. (cherry picked from commit 2afdecccbaf5c5b1c7a235509b37092540906c02) 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 aae397ed755..d423cbbacae 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -5703,6 +5703,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..eeff4b2f4bb --- /dev/null +++ b/gcc/testsuite/gcc.dg/format/sentinel-2.c @@ -0,0 +1,21 @@ +/* PR c/114780 */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -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); +}