@@ -40,23 +40,23 @@ localtime_r \- transform date and time to broken-down time or ASCII
.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 "[static 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 "[static restrict 26]);"
.PP
-.BI "char *ctime(const time_t *" timep );
-.BI "char *ctime_r(const time_t *restrict " timep ,
-.BI " char " buf "[static 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 "[static 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
@@ -41,6 +41,7 @@ strftime \- format date and time
.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 );
@@ -36,6 +36,7 @@ strptime \- convert a string representation of time to a time tm structure
.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
@@ -29,8 +29,8 @@ timegm, timelocal \- inverses of gmtime and localtime
.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
C2X changes 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. However, that forces the use 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 standard 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> --- man3/ctime.3 | 26 +++++++++++++------------- man3/strftime.3 | 1 + man3/strptime.3 | 1 + man3/timegm.3 | 4 ++-- 4 files changed, 17 insertions(+), 15 deletions(-)