[tz] [PROPOSED] Try to check longstanding padding assumptions

Paul Eggert eggert at cs.ucla.edu
Thu Dec 8 02:57:54 UTC 2022


This is helpful only when porting to oddball platforms in some
situations where time_t is signed and has padding bits.  (Even C23
allows these platforms.)  Formerly tzcode would silently have
undefined runtime behavior on such platforms; with this patch, there
is likely a compile-time diagnostic instead.
* private.h (static_assert): New macro, defined for pre-C23 compilers.
(SIGNED_PADDING_CHECK_NEEDED): New constant.
Try to check that TIME_T_MIN and TIME_T_MAX are actually the min and
max time_t values.
---
 private.h | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/private.h b/private.h
index 1d6ddf7..7ddf4e5 100644
--- a/private.h
+++ b/private.h
@@ -43,6 +43,10 @@
 # include <stdbool.h>
 #endif
 
+#if __STDC_VERSION__ < 202311
+# define static_assert(cond) extern int static_assert_check[(cond) ? 1 : -1]
+#endif
+
 /*
 ** zdump has been made independent of the rest of the time
 ** conversion package to increase confidence in the verification it provides.
@@ -833,10 +837,23 @@ ATTRIBUTE_REPRODUCIBLE time_t time2posix_z(timezone_t, time_t);
 		int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
 		default: TIME_T_MAX_NO_PADDING)			    \
      : (time_t) -1)
+enum { SIGNED_PADDING_CHECK_NEEDED
+         = _Generic((time_t) 0,
+		    signed char: false, short: false,
+		    int: false, long: false, long long: false,
+		    default: true) };
 #else
 # define TIME_T_MIN TIME_T_MIN_NO_PADDING
 # define TIME_T_MAX TIME_T_MAX_NO_PADDING
-#endif
+enum { SIGNED_PADDING_CHECK_NEEDED = true };
+#endif
+/* Try to check the padding assumptions.  Although TIME_T_MAX and the
+   following check can both have undefined behavior on oddball
+   platforms due to shifts exceeding widths of signed integers, these
+   platforms' compilers are likely to diagnose these issues in integer
+   constant expressions, so it shouldn't hurt to check statically.  */
+static_assert(! TYPE_SIGNED(time_t) || ! SIGNED_PADDING_CHECK_NEEDED
+	      || TIME_T_MAX >> (TYPE_BIT(time_t) - 2) == 1);
 
 /*
 ** 302 / 1000 is log10(2.0) rounded up.
-- 
2.38.1



More information about the tz mailing list