diff options
author | Alejandro Colomar <alx.manpages@gmail.com> | 2021-10-20 21:49:15 +0200 |
---|---|---|
committer | Alejandro Colomar <alx.manpages@gmail.com> | 2022-09-05 04:13:31 +0200 |
commit | b830f9b63af54454f026341585f8d9e997ed851e (patch) | |
tree | eeff7627f6296b815bc316cf749837d610fa6dc5 | |
parent | dfd1f1fd252398f8b97fd719829f8f79b699809c (diff) |
ctime.3, strftime.3, strptime.3, timegm.3: SYNOPSIS: Add [[gnu::nonnull]] to <time.h> prototypes
A proposal for C2X proposed changing the prototypes of <time.h>
functions that accept a pointer that cannot be NULL, to use
'static', which clearly denotes that passing NULL is Undefined
Behavior.
For example, 'time_t mktime(struct tm tm[static 1]);'.
This change is backwards compatible, since array notation is just
syntactic sugar for pointers, and the Undefined Behavior in case
of a pointer already existed (in the wording); it just wasn't
clear from the prototype itself.
This proposal was finally not merged into the standard, as Jens
noted. But it points out a defficiency in the current prototype.
However, that proposal used of VLA (array) notation for something
that is *not* an array. It is cofusing, probably too much for
some programmers not so familiar with the difference between an
array and a pointer, and that happens more than we would like.
Even for programmers that clearly know the difference between an
array and a pointer, this is at least misleading.
That happens because the standard lacks a 'nonnull' attribute, and
only has that (VLA) way of expressing what GCC can express with
'[[gnu::nonnull]]' (a.k.a. '__attribute__((__nonnull__))').
Expressing that NULL pointers shall invoke Undefined Behavior in
the prototype of a function is *way* more readable than having to
read through the whole manual page text, so ideally we should also
follow the idea of expressing that. But we can make use of more
advanced techniques such as the GCC attribute, which help keep the
information that those pointers are actually pointers and not
arrays.
From the 2 different attribute notations, let's use the "C++" one,
which will be part of the standard in C2X (unlike __attribute__),
and is also shorter, which helps keep the SYNOPSIS short (mostly
one-liner prototypes).
See <http://www.open-std.org/JTC1/SC22/WG14/www/docs/n2417.pdf>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Cc: Jens Gustedt <jens.gustedt@loria.fr>
Cc: Glibc <libc-alpha@sourceware.org>
-rw-r--r-- | man3/ctime.3 | 26 | ||||
-rw-r--r-- | man3/strftime.3 | 1 | ||||
-rw-r--r-- | man3/strptime.3 | 1 | ||||
-rw-r--r-- | man3/timegm.3 | 4 |
4 files changed, 17 insertions, 15 deletions
diff --git a/man3/ctime.3 b/man3/ctime.3 index 1424c6baa..6d978b338 100644 --- a/man3/ctime.3 +++ b/man3/ctime.3 @@ -23,23 +23,23 @@ Standard C library .nf .B #include <time.h> .PP -.BI "char *asctime(const struct tm *" tm ); -.BI "char *asctime_r(const struct tm *restrict " tm , -.BI " char " buf "[restrict 26]);" +.BI "[[gnu::nonnull]] char *asctime(const struct tm *" tm ); +.BI "[[gnu::nonnull]] char *asctime_r(const struct tm *restrict " tm , +.BI " char " buf "[restrict 26]);" .PP -.BI "char *ctime(const time_t *" timep ); -.BI "char *ctime_r(const time_t *restrict " timep , -.BI " char " buf "[restrict 26]);" +.BI "[[gnu::nonnull]] char *ctime(const time_t *" timep ); +.BI "[[gnu::nonnull]] char *ctime_r(const time_t *restrict " timep , +.BI " char " buf "[restrict 26]);" .PP -.BI "struct tm *gmtime(const time_t *" timep ); -.BI "struct tm *gmtime_r(const time_t *restrict " timep , -.BI " struct tm *restrict " result ); +.BI "[[gnu::nonnull]] struct tm *gmtime(const time_t *" timep ); +.BI "[[gnu::nonnull]] struct tm *gmtime_r(const time_t *restrict " timep , +.BI " struct tm *restrict " result ); .PP -.BI "struct tm *localtime(const time_t *" timep ); -.BI "struct tm *localtime_r(const time_t *restrict " timep , -.BI " struct tm *restrict " result ); +.BI "[[gnu::nonnull]] struct tm *localtime(const time_t *" timep ); +.BI "[[gnu::nonnull]] struct tm *localtime_r(const time_t *restrict " timep , +.BI " struct tm *restrict " result ); .PP -.BI "time_t mktime(struct tm *" tm ); +.BI "[[gnu::nonnull]] time_t mktime(struct tm *" tm ); .fi .PP .RS -4 diff --git a/man3/strftime.3 b/man3/strftime.3 index 9a10275ca..f16d4a3f7 100644 --- a/man3/strftime.3 +++ b/man3/strftime.3 @@ -24,6 +24,7 @@ Standard C library .nf .B #include <time.h> .PP +.B [[gnu::nonnull]] .BI "size_t strftime(char *restrict " s ", size_t " max , .BI " const char *restrict " format , .BI " const struct tm *restrict " tm ); diff --git a/man3/strptime.3 b/man3/strptime.3 index e220f21b0..0b7fb1240 100644 --- a/man3/strptime.3 +++ b/man3/strptime.3 @@ -19,6 +19,7 @@ Standard C library .BR "#define _XOPEN_SOURCE" " /* See feature_test_macros(7) */" .B #include <time.h> .PP +.B [[gnu::nonnull]] .BI "char *strptime(const char *restrict " s ", const char *restrict " format , .BI " struct tm *restrict " tm ); .fi diff --git a/man3/timegm.3 b/man3/timegm.3 index d8dd7f4da..9e590878c 100644 --- a/man3/timegm.3 +++ b/man3/timegm.3 @@ -12,8 +12,8 @@ Standard C library .nf .B #include <time.h> .PP -.BI "time_t timelocal(struct tm *" tm ); -.BI "time_t timegm(struct tm *" tm ); +.BI "[[gnu::nonnull]] time_t timelocal(struct tm *" tm ); +.BI "[[gnu::nonnull]] time_t timegm(struct tm *" tm ); .PP .fi .RS -4 |