According to https://en.cppreference.com/w/c/chrono/localtime C11 added optional gmtime_s() and localtime_s() which conflict with the long standing MSVCRT/UCRT variants. I have no idea why they did this (C23 finally adds the traditional *_r() functions which are IIRC older than POSIX).

The attached patch provides the C11 variants if __STDC_WANT_LIB_EXT1__ is defined.

All 3 alternatives of the example below result in the same assembly code:

#define __STDC_WANT_LIB_EXT1__ 1
#include <time.h>

struct tm * localtime_chaos(const time_t * t, struct tm * tb)
{
#if __STDC_LIB_EXT1__ // C11, optional, requires __STDC_WANT_LIB_EXT1__
  return localtime_s(t, tb);
#elif defined(_POSIX_THREAD_SAFE_FUNCTIONS)
  return localtime_r(t, tb);
#elif defined(_WIN32) // assume MSVCRT/UCRT
  return (!localtime_s(tb, t) ? tb : 0);
#else
  #error giving up ...
#endif
}

--
Regards,
Christian

From fbcdb908526f31c8872f5e639af87a26187eab10 Mon Sep 17 00:00:00 2001
From: Christian Franke <[email protected]>
Date: Sat, 15 Jul 2023 18:42:42 +0200
Subject: [PATCH] headers: Add C11 variants of gmtime_s and localtime_s

Enable these only if __STDC_WANT_LIB_EXT1__ is defined to nonzero.
Then define __STDC_LIB_EXT1__ to indicate availability and hide
the incompatible MSVCRT/UCRT variants for C code.
Provide both variants for C++ code.

Signed-off-by: Christian Franke <[email protected]>
---
 mingw-w64-headers/crt/time.h | 44 ++++++++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/mingw-w64-headers/crt/time.h b/mingw-w64-headers/crt/time.h
index d70a70717..d50d43f55 100644
--- a/mingw-w64-headers/crt/time.h
+++ b/mingw-w64-headers/crt/time.h
@@ -247,9 +247,11 @@ static __inline int __CRTDECL timespec_get(struct 
timespec* _Ts, int _Base) { re
 #endif
 static __inline double __CRTDECL difftime(time_t _Time1,time_t _Time2)  { 
return _difftime32(_Time1,_Time2); }
 static __inline struct tm *__CRTDECL localtime(const time_t *_Time) { return 
_localtime32(_Time); }
-static __inline errno_t __CRTDECL localtime_s(struct tm *_Tm,const time_t 
*_Time) { return _localtime32_s(_Tm,_Time); }
 static __inline struct tm *__CRTDECL gmtime(const time_t *_Time) { return 
_gmtime32(_Time); }
-static __inline errno_t __CRTDECL gmtime_s(struct tm *_Tm, const time_t 
*_Time)   { return _gmtime32_s(_Tm, _Time); }
+#if !__STDC_WANT_LIB_EXT1__ || defined(__cplusplus) /* Conflict with C11 
variants */
+static __inline errno_t __CRTDECL localtime_s(struct tm *_Tm, const time_t 
*_Time) { return _localtime32_s(_Tm,_Time); }
+static __inline errno_t __CRTDECL gmtime_s(struct tm *_Tm, const time_t 
*_Time) { return _gmtime32_s(_Tm, _Time); }
+#endif
 static __inline char *__CRTDECL ctime(const time_t *_Time) { return 
_ctime32(_Time); }
 static __inline errno_t __CRTDECL ctime_s(char *_Buf,size_t _SizeInBytes,const 
time_t *_Time) { return _ctime32_s(_Buf,_SizeInBytes,_Time); }
 static __inline time_t __CRTDECL mktime(struct tm *_Tm) { return 
_mktime32(_Tm); }
@@ -261,9 +263,11 @@ static __inline int __CRTDECL timespec_get(struct 
timespec* _Ts, int _Base) { re
 #endif
 static __inline double __CRTDECL difftime(time_t _Time1,time_t _Time2) { 
return _difftime64(_Time1,_Time2); }
 static __inline struct tm *__CRTDECL localtime(const time_t *_Time) { return 
_localtime64(_Time); }
-static __inline errno_t __CRTDECL localtime_s(struct tm *_Tm,const time_t 
*_Time) { return _localtime64_s(_Tm,_Time); }
 static __inline struct tm *__CRTDECL gmtime(const time_t *_Time) { return 
_gmtime64(_Time); }
+#if !__STDC_WANT_LIB_EXT1__ || defined(__cplusplus) /* Conflict with C11 
variants */
+static __inline errno_t __CRTDECL localtime_s(struct tm *_Tm, const time_t 
*_Time) { return _localtime64_s(_Tm,_Time); }
 static __inline errno_t __CRTDECL gmtime_s(struct tm *_Tm, const time_t 
*_Time) { return _gmtime64_s(_Tm, _Time); }
+#endif
 static __inline char *__CRTDECL ctime(const time_t *_Time) { return 
_ctime64(_Time); }
 static __inline errno_t __CRTDECL ctime_s(char *_Buf,size_t _SizeInBytes,const 
time_t *_Time) { return _ctime64_s(_Buf,_SizeInBytes,_Time); }
 static __inline time_t __CRTDECL mktime(struct tm *_Tm) { return 
_mktime64(_Tm); }
@@ -309,12 +313,21 @@ struct timezone {
 #endif
 
 #ifdef _POSIX_THREAD_SAFE_FUNCTIONS
+#ifdef _USE_32BIT_TIME_T
 __forceinline struct tm *__CRTDECL localtime_r(const time_t *_Time, struct tm 
*_Tm) {
-  return localtime_s(_Tm, _Time) ? NULL : _Tm;
+  return _localtime32_s(_Tm, _Time) ? NULL : _Tm;
 }
 __forceinline struct tm *__CRTDECL gmtime_r(const time_t *_Time, struct tm 
*_Tm) {
-  return gmtime_s(_Tm, _Time) ? NULL : _Tm;
+  return _gmtime32_s(_Tm, _Time) ? NULL : _Tm;
 }
+#else
+__forceinline struct tm *__CRTDECL localtime_r(const time_t *_Time, struct tm 
*_Tm) {
+  return _localtime64_s(_Tm, _Time) ? NULL : _Tm;
+}
+__forceinline struct tm *__CRTDECL gmtime_r(const time_t *_Time, struct tm 
*_Tm) {
+  return _gmtime64_s(_Tm, _Time) ? NULL : _Tm;
+}
+#endif
 __forceinline char *__CRTDECL ctime_r(const time_t *_Time, char *_Str) {
   return ctime_s(_Str, 0x7fffffff, _Time) ? NULL : _Str;
 }
@@ -327,6 +340,27 @@ __forceinline char *__CRTDECL asctime_r(const struct tm 
*_Tm, char * _Str) {
 }
 #endif
 
+#if __STDC_WANT_LIB_EXT1__
+#define __STDC_LIB_EXT1__ 1
+/* Optional C11 functions are incompatible with the MSVC variants.
+   Both variants are provided for C++. */
+#ifdef _USE_32BIT_TIME_T
+__forceinline struct tm *__CRTDECL localtime_s(const time_t *_Time, struct tm 
*_Tm) {
+  return _localtime32_s(_Tm, _Time) ? NULL : _Tm;
+}
+__forceinline struct tm *__CRTDECL gmtime_s(const time_t *_Time, struct tm 
*_Tm) {
+  return _gmtime32_s(_Tm, _Time) ? NULL : _Tm;
+}
+#else
+__forceinline struct tm *__CRTDECL localtime_s(const time_t *_Time, struct tm 
*_Tm) {
+  return _localtime64_s(_Tm, _Time) ? NULL : _Tm;
+}
+__forceinline struct tm *__CRTDECL gmtime_s(const time_t *_Time, struct tm 
*_Tm) {
+  return _gmtime64_s(_Tm, _Time) ? NULL : _Tm;
+}
+#endif
+#endif
+
 /* POSIX 2008 says clock_gettime and timespec are defined in time.h header,
    but other systems - like Linux, Solaris, etc - tend to declare such
    recent extensions only if the following guards are met.  */
-- 
2.39.0

_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to