[tz] [PROPOSED] Use ‘restrict’ more consistently with standards

Paul Eggert eggert at cs.ucla.edu
Tue Dec 20 07:31:09 UTC 2022

Previously, I assumed that if the declaration of a function F
declared an argument via ‘T *restrict ARG’ then the compiler could
take advantage of the ‘restrict’ when compiling F’s definition.
However, apparently this is not the case: a top-level ‘restrict’
like that has no effect semantically unless it’s present in F’s
definition.  Fix this by using ‘restrict’ consistently in both
declarations and definitions of functions where POSIX or the
NetBSD API specifies ‘restrict’.  (As an exception, do not use
‘restrict’ in tzfree’s argument as this appears to be a typo in
NetBSD.)  Do not bother using ‘restrict’ in internal functions, as
this change is for consistency not for optimization.  This change
was prompted by a bug report for compiling on MS-Windows; see
Although the change does not fix the MS-Windows situation, the
idea is to fix the MS-Windows issue another way.
* asctime.c (asctime_r):
* localtime.c (localtime_rz, localtime_r, gmtime_r, mktime_z):
* private.h (asctime) [HAVE_INCOMPATIBLE_CTIME_R]:
* strftime.c (strftime_l, strftime):
Use ‘restrict’ consistently when POSIX or tzcode’s doc say so.
 NEWS        | 4 ++++
 asctime.c   | 2 +-
 localtime.c | 9 +++++----
 private.h   | 2 +-
 strftime.c  | 6 ++++--
 5 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/NEWS b/NEWS
index 98cc14f..9b2d202 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,10 @@ Unreleased, experimental changes
     '[[noreturn]] static void usage(void);' as strict C23 requires.
     (Problem reported by Houge Langley.)
+    The code's functions now constrain their arguments with the C
+    'restrict' keyword consistently with their documentation.
+    This may allow future optimizations.
 Release 2022g - 2022-11-29 08:58:31 -0800
diff --git a/asctime.c b/asctime.c
index c84fe8c..375c913 100644
--- a/asctime.c
+++ b/asctime.c
@@ -61,7 +61,7 @@ static char buf_ctime[sizeof buf_asctime];
 char *
-asctime_r(register const struct tm *timeptr, char *buf)
+asctime_r(struct tm const *restrict timeptr, char *restrict buf)
 	static const char	wday_name[][4] = {
 		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
diff --git a/localtime.c b/localtime.c
index f1a8598..9b5d0a5 100644
--- a/localtime.c
+++ b/localtime.c
@@ -1628,7 +1628,8 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
 struct tm *
-localtime_rz(struct state *sp, time_t const *timep, struct tm *tmp)
+localtime_rz(struct state *restrict sp, time_t const *restrict timep,
+	     struct tm *restrict tmp)
   return localsub(sp, timep, 0, tmp);
@@ -1660,7 +1661,7 @@ localtime(const time_t *timep)
 struct tm *
-localtime_r(const time_t *timep, struct tm *tmp)
+localtime_r(const time_t *restrict timep, struct tm *restrict tmp)
   return localtime_tzset(timep, tmp, false);
@@ -1693,7 +1694,7 @@ gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const *sp, time_t const *timep,
 struct tm *
-gmtime_r(const time_t *timep, struct tm *tmp)
+gmtime_r(time_t const *restrict timep, struct tm *restrict tmp)
   return gmtsub(gmtptr, timep, 0, tmp);
@@ -2297,7 +2298,7 @@ mktime_tzname(struct state *sp, struct tm *tmp, bool setname)
-mktime_z(struct state *sp, struct tm *tmp)
+mktime_z(struct state *restrict sp, struct tm *restrict tmp)
   return mktime_tzname(sp, tmp, false);
diff --git a/private.h b/private.h
index 7ddf4e5..5043cb8 100644
--- a/private.h
+++ b/private.h
@@ -920,7 +920,7 @@ static_assert(! TYPE_SIGNED(time_t) || ! SIGNED_PADDING_CHECK_NEEDED
 #undef asctime_r
 #undef ctime_r
-char *asctime_r(struct tm const *, char *);
+char *asctime_r(struct tm const *restrict, char *restrict);
 char *ctime_r(time_t const *, char *);
diff --git a/strftime.c b/strftime.c
index b23b610..df16983 100644
--- a/strftime.c
+++ b/strftime.c
@@ -116,7 +116,8 @@ static char *	_yconv(int, int, bool, bool, char *, char const *);
-strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
+strftime_l(char *restrict s, size_t maxsize, char const *restrict format,
+	   struct tm const *restrict t,
 	   ATTRIBUTE_MAYBE_UNUSED locale_t locale)
   /* Just call strftime, as only the C locale is supported.  */
@@ -125,7 +126,8 @@ strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
-strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
+strftime(char *restrict s, size_t maxsize, char const *restrict format,
+	 struct tm const *restrict t)
 	char *	p;
 	int saved_errno = errno;

More information about the tz mailing list