On Sat, 14 Jun 2025, Jeremy Drake via Cygwin wrote: > Consider the following -std=c++20: > #include <pthread.h> > > constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER; > > With g++ 12.4.0, this succeeds, but with clang 20.1.6 it fails: > pthreadtest.cpp:3:27: error: variable does not have a constant initializer > 3 | constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER; > | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ > pthreadtest.cpp:3:1: note: required by 'constinit' specifier here > 3 | constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER; > | ^~~~~~~~~ > pthreadtest.cpp:3:33: note: cast that performs the conversions of a > reinterpret_cast is not allowed in a constant expression > 3 | constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER; > | ^ > /usr/include/pthread.h:49:35: note: expanded from macro > 'PTHREAD_MUTEX_INITIALIZER' > 49 | #define PTHREAD_MUTEX_INITIALIZER PTHREAD_NORMAL_MUTEX_INITIALIZER_NP > | ^ > /usr/include/pthread.h:47:45: note: expanded from macro > 'PTHREAD_NORMAL_MUTEX_INITIALIZER_NP' > 47 | #define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (pthread_mutex_t)19 > | ^ > 1 error generated. > > It seems the standard disallows this sort of cast pretty comprehensively. > Is there some way that Cygwin's pthread initializer macros can be made > compatible with constinit?
I was thinking changing the typedef to be uintptr_t instead of a pointer would allow constinit initialization to a constant integer, and be the same ABI-wise, but it would probably change C++ mangled names for functions taking those types as parameters. What did work for me, and I'll admit it's pretty gross, is #include <pthread.h> #ifdef __i386__ #define SYMPREFIX "_" #else #define SYMPREFIX "" #endif __asm__( SYMPREFIX "__pthread_normal_mutex_initializer_np=19"); extern "C" struct __pthread_mutex_t __pthread_normal_mutex_initializer_np; #undef PTHREAD_NORMAL_MUTEX_INITIALIZER_NP #define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (&__pthread_normal_mutex_initializer_np) constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER; Basically, hiding the value from the compiler and making it think it is in fact dealing with a real pointer. -- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple