From 99278f86f5bc2b94bfd298593359b3731545c456 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 2 Apr 2026 19:46:16 +0700 Subject: [PATCH 1/7] prefer C11 atomics over ZEND_WIN32 locking mechanism (mfence instructions on every zend_atomic_*_load_ex) # Conflicts: # win32/build/confutils.js --- Zend/zend_atomic.c | 2 +- Zend/zend_atomic.h | 8 ++++---- win32/build/confutils.js | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Zend/zend_atomic.c b/Zend/zend_atomic.c index 5f6a7793beeab..4151e5e539de2 100644 --- a/Zend/zend_atomic.c +++ b/Zend/zend_atomic.c @@ -57,7 +57,7 @@ ZEND_API void zend_atomic_int_store(zend_atomic_int *obj, int desired) { zend_atomic_int_store_ex(obj, desired); } -#if defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS) +#if (defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS)) && !defined(HAVE_C11_ATOMICS) /* On these platforms it is non-const due to underlying APIs. */ ZEND_API bool zend_atomic_bool_load(zend_atomic_bool *obj) { return zend_atomic_bool_load_ex(obj); diff --git a/Zend/zend_atomic.h b/Zend/zend_atomic.h index 56422a721fdba..e50e0a518a77a 100644 --- a/Zend/zend_atomic.h +++ b/Zend/zend_atomic.h @@ -39,7 +39,7 @@ * and alignment purposes. */ -#if defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS) +#if (defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS)) && !defined(HAVE_C11_ATOMICS) typedef struct zend_atomic_bool_s { volatile char value; } zend_atomic_bool; @@ -68,7 +68,7 @@ typedef struct zend_atomic_int_s { BEGIN_EXTERN_C() -#ifdef ZEND_WIN32 +#if (defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS)) && !defined(HAVE_C11_ATOMICS) #ifndef InterlockedExchange8 #define InterlockedExchange8 _InterlockedExchange8 @@ -123,7 +123,7 @@ static zend_always_inline bool zend_atomic_int_compare_exchange_ex(zend_atomic_i } } -/* On this platform it is non-const due to Iterlocked API*/ +/* On this platform it is non-const due to Interlocked API */ static zend_always_inline bool zend_atomic_bool_load_ex(zend_atomic_bool *obj) { /* Or'ing with false won't change the value. */ return InterlockedOr8(&obj->value, false); @@ -376,7 +376,7 @@ ZEND_API bool zend_atomic_int_compare_exchange(zend_atomic_int *obj, int *expect ZEND_API void zend_atomic_bool_store(zend_atomic_bool *obj, bool desired); ZEND_API void zend_atomic_int_store(zend_atomic_int *obj, int desired); -#if defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS) +#if (defined(ZEND_WIN32) && !defined(HAVE_C11_ATOMICS)) || defined(HAVE_SYNC_ATOMICS) /* On these platforms it is non-const due to underlying APIs. */ ZEND_API bool zend_atomic_bool_load(zend_atomic_bool *obj); ZEND_API int zend_atomic_int_load(zend_atomic_int *obj); diff --git a/win32/build/confutils.js b/win32/build/confutils.js index 0930a86b741ca..261fc7888e365 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -3306,7 +3306,7 @@ function toolset_setup_common_cflags() ADD_FLAG("CFLAGS", "/Zc:wchar_t"); } else if (CLANG_TOOLSET) { - ADD_FLAG("CFLAGS", "-Wno-deprecated-declarations"); + ADD_FLAG("CFLAGS", "-Wno-deprecated-declarations -Wno-microsoft-enum-forward-reference"); if (TARGET_ARCH == 'x86') { ADD_FLAG('CFLAGS', '-m32'); } else { From adf28dfa0bdbeed0c278bc27bb5bc6793d7cabd5 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 2 Apr 2026 19:59:41 +0700 Subject: [PATCH 2/7] huh, fails CI --- Zend/zend_atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_atomic.h b/Zend/zend_atomic.h index e50e0a518a77a..bcbc6681c9289 100644 --- a/Zend/zend_atomic.h +++ b/Zend/zend_atomic.h @@ -68,7 +68,7 @@ typedef struct zend_atomic_int_s { BEGIN_EXTERN_C() -#if (defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS)) && !defined(HAVE_C11_ATOMICS) +#if defined(ZEND_WIN32) && !defined(HAVE_C11_ATOMICS) #ifndef InterlockedExchange8 #define InterlockedExchange8 _InterlockedExchange8 From 252711e6be6501553ff06542dc863e020201203c Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 2 Apr 2026 22:03:53 +0700 Subject: [PATCH 3/7] fix compiling (intl) C++ extensions --with-toolset=clang --- TSRM/TSRM.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h index 80d6cbad04435..ea13552c83747 100644 --- a/TSRM/TSRM.h +++ b/TSRM/TSRM.h @@ -175,9 +175,14 @@ TSRM_API bool tsrm_is_managed_thread(void); #define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)]) #define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element) #define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset))) +#ifdef __cplusplus +#define TSRMLS_MAIN_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR; } +#define TSRMLS_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE; } +#else #define TSRMLS_MAIN_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR; -#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL; #define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE; +#endif +#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL; #define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL; #define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache() #define TSRMLS_CACHE _tsrm_ls_cache From 1f99e935426a7204be81215f9aeac9294790b115 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 2 Apr 2026 22:28:15 +0700 Subject: [PATCH 4/7] add HAVE_PRESERVE_NONE for CLANG_TOOLSET on windows --- win32/build/confutils.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/win32/build/confutils.js b/win32/build/confutils.js index 261fc7888e365..8a12e2690f759 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -3319,7 +3319,11 @@ function toolset_setup_common_cflags() var vc_ver = probe_binary(PATH_PROG('cl', null)); ADD_FLAG("CFLAGS"," -fms-compatibility -fms-compatibility-version=" + vc_ver + " -fms-extensions"); - } + + if (CLANGVERS >= 1900 && (TARGET_ARCH === 'x64' || TARGET_ARCH === 'arm64')) { + AC_DEFINE('HAVE_PRESERVE_NONE', 1, 'Whether the compiler supports __attribute__((preserve_none))'); + } + } if (!CLANG_TOOLSET) { /* clang uses __builtin_*() instead */ From 4793c81842dd46cfa790a8bb428054af08e13507 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 2 Apr 2026 22:51:51 +0700 Subject: [PATCH 5/7] guard the double extern "C" { ... } for clang-only --- TSRM/TSRM.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h index ea13552c83747..135872f79ecc3 100644 --- a/TSRM/TSRM.h +++ b/TSRM/TSRM.h @@ -175,7 +175,7 @@ TSRM_API bool tsrm_is_managed_thread(void); #define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)]) #define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element) #define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset))) -#ifdef __cplusplus +#if defined(__cplusplus) && defined(__clang__) #define TSRMLS_MAIN_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR; } #define TSRMLS_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE; } #else From f9aa202ce51ca04e7a4ec823e6300f6be3b61873 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 2 Apr 2026 23:21:57 +0700 Subject: [PATCH 6/7] add clang x64 test --- .github/scripts/windows/build_task.bat | 1 + .github/workflows/test-suite.yml | 29 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/.github/scripts/windows/build_task.bat b/.github/scripts/windows/build_task.bat index b654794518496..70dd80c94336a 100644 --- a/.github/scripts/windows/build_task.bat +++ b/.github/scripts/windows/build_task.bat @@ -26,6 +26,7 @@ if %errorlevel% neq 0 exit /b 3 if "%THREAD_SAFE%" equ "0" set ADD_CONF=%ADD_CONF% --disable-zts if "%INTRINSICS%" neq "" set ADD_CONF=%ADD_CONF% --enable-native-intrinsics=%INTRINSICS% if "%ASAN%" equ "1" set ADD_CONF=%ADD_CONF% --enable-sanitizer --enable-debug-pack +if "%CLANG_TOOLSET%" equ "1" set ADD_CONF=%ADD_CONF% --with-toolset=clang rem C4018: comparison: signed/unsigned mismatch rem C4146: unary minus operator applied to unsigned type diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 9eeff1455f8f9..039ab8d5acdbb 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -962,6 +962,35 @@ jobs: run: .github/scripts/windows/build.bat - name: Test run: .github/scripts/windows/test.bat + WINDOWS_CLANG: + if: ${{ fromJson(inputs.branch).jobs.WINDOWS }} + name: "WINDOWS_X64_ZTS_CLANG" + runs-on: windows-2022 + env: + PHP_BUILD_CACHE_BASE_DIR: C:\build-cache + PHP_BUILD_OBJ_DIR: C:\obj + PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk + PHP_BUILD_SDK_BRANCH: php-sdk-2.5.0 + PHP_BUILD_CRT: ${{ fromJson(inputs.branch).jobs.WINDOWS.config.vs_crt_version }} + PLATFORM: x64 + THREAD_SAFE: "1" + INTRINSICS: "AVX2" + PARALLEL: -j2 + OPCACHE: "1" + CLANG_TOOLSET: "1" + steps: + - name: git config + run: git config --global core.autocrlf false && git config --global core.eol lf + - name: git checkout + uses: actions/checkout@v6 + with: + ref: ${{ fromJson(inputs.branch).ref }} + - name: Setup + uses: ./.github/actions/setup-windows + - name: Build + run: .github/scripts/windows/build.bat + - name: Test + run: .github/scripts/windows/test.bat FREEBSD: if: ${{ fromJson(inputs.branch).jobs.FREEBSD }} strategy: From 2be1443aa48455b72d1433d5006ed2f707de9622 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 2 Apr 2026 23:33:29 +0700 Subject: [PATCH 7/7] don't error on warnings with clang --- .github/scripts/windows/build_task.bat | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/scripts/windows/build_task.bat b/.github/scripts/windows/build_task.bat index 70dd80c94336a..9bc3f53463c37 100644 --- a/.github/scripts/windows/build_task.bat +++ b/.github/scripts/windows/build_task.bat @@ -32,7 +32,11 @@ rem C4018: comparison: signed/unsigned mismatch rem C4146: unary minus operator applied to unsigned type rem C4244: type conversion, possible loss of data rem C4267: 'size_t' type conversion, possible loss of data -set CFLAGS=/W3 /WX /wd4018 /wd4146 /wd4244 /wd4267 +if "%CLANG_TOOLSET%" equ "1" ( + set CFLAGS=/W3 /wd4018 /wd4146 /wd4244 /wd4267 +) else ( + set CFLAGS=/W3 /WX /wd4018 /wd4146 /wd4244 /wd4267 +) cmd /c configure.bat ^ --enable-snapshot-build ^