[PATCH v2 0/7] MR10273: vcruntime140: Initial C++ support.
-- v2: vcruntime140: Add type_info vtbl to the import library. vcruntime140: Add support for MSVC thread-safe constructor initialization. vcruntime140: Add __type_info_root_node implementation. vcruntime140: Add new and delete operators implementation to CRT library. include: Import C++ headers from LLVM version 8.0.1. configure: Check for C++17 support. makefiles: Add support for C++ sources. https://gitlab.winehq.org/wine/wine/-/merge_requests/10273
From: Alexandre Julliard <julliard@winehq.org> With help from Jacek Caban. --- configure | 366 ++++++++++++++++++++++++------------------- configure.ac | 15 +- tools/make_makefiles | 8 +- tools/makedep.c | 76 +++++++-- 4 files changed, 288 insertions(+), 177 deletions(-) diff --git a/configure b/configure index 6ffc2a8e580..02649853799 100755 --- a/configure +++ b/configure @@ -807,8 +807,11 @@ x86_64_STRIP x86_64_TARGET x86_64_DEBUG x86_64_LDFLAGS +x86_64_EXTRACXXFLAGS x86_64_EXTRACFLAGS +x86_64_CXXFLAGS x86_64_CFLAGS +x86_64_CXX x86_64_CC i386_DISABLED_SUBDIRS i386_DELAYLOADFLAG @@ -816,8 +819,11 @@ i386_STRIP i386_TARGET i386_DEBUG i386_LDFLAGS +i386_EXTRACXXFLAGS i386_EXTRACFLAGS +i386_CXXFLAGS i386_CFLAGS +i386_CXX i386_CC arm64ec_DISABLED_SUBDIRS arm64ec_DELAYLOADFLAG @@ -825,8 +831,11 @@ arm64ec_STRIP arm64ec_TARGET arm64ec_DEBUG arm64ec_LDFLAGS +arm64ec_EXTRACXXFLAGS arm64ec_EXTRACFLAGS +arm64ec_CXXFLAGS arm64ec_CFLAGS +arm64ec_CXX arm64ec_CC arm_DISABLED_SUBDIRS arm_DELAYLOADFLAG @@ -834,8 +843,11 @@ arm_STRIP arm_TARGET arm_DEBUG arm_LDFLAGS +arm_EXTRACXXFLAGS arm_EXTRACFLAGS +arm_CXXFLAGS arm_CFLAGS +arm_CXX arm_CC aarch64_DISABLED_SUBDIRS aarch64_DELAYLOADFLAG @@ -843,8 +855,11 @@ aarch64_STRIP aarch64_TARGET aarch64_DEBUG aarch64_LDFLAGS +aarch64_EXTRACXXFLAGS aarch64_EXTRACFLAGS +aarch64_CXXFLAGS aarch64_CFLAGS +aarch64_CXX aarch64_CC HOST_ARCH toolsext @@ -7680,6 +7695,20 @@ then : else case e in #( e) eval "${wine_arch}_LDFLAGS=\$CROSSLDFLAGS" ;; esac +fi + if eval test \${${wine_arch}_CXX+y} +then : + +else case e in #( + e) eval ${wine_arch}_CXX=\$${wine_arch}_CC ;; +esac +fi + if eval test \${${wine_arch}_CXXFLAGS+y} +then : + +else case e in #( + e) eval ${wine_arch}_CXXFLAGS=\$${wine_arch}_CFLAGS ;; +esac fi eval CC=\$${wine_arch}_CC eval CFLAGS=\$${wine_arch}_CFLAGS @@ -8175,46 +8204,6 @@ printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_var"\" = x"yes" then : CFLAGS="$CFLAGS -Werror=unsupported-floating-point-opt" -fi } - { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wdeclaration-after-statement" | sed "$as_sed_sh"` -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wdeclaration-after-statement" >&5 -printf %s "checking whether $CC supports -Wdeclaration-after-statement... " >&6; } -if eval test \${$as_ac_var+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) ac_wine_try_cflags_saved=$CFLAGS -ac_wine_try_cflags_saved_exeext=$ac_exeext -CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -Wdeclaration-after-statement" -ac_exeext=".exe" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -void *__os_arm64x_dispatch_ret = 0; -const unsigned int _load_config_used[0x50] = { sizeof(_load_config_used) }; -#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION -#error Too old clang version -#endif -int __cdecl mainCRTStartup(void) { return 0; } -_ACEOF -if ac_fn_c_try_link "$LINENO" -then : - eval "$as_ac_var=yes" -else case e in #( - e) eval "$as_ac_var=no" ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext -CFLAGS=$ac_wine_try_cflags_saved -ac_exeext=$ac_wine_try_cflags_saved_exeext ;; -esac -fi -eval ac_res=\$$as_ac_var - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } -if eval test \"x\$"$as_ac_var"\" = x"yes" -then : - as_fn_append ${wine_arch}_EXTRACFLAGS " -Wdeclaration-after-statement" fi } { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wempty-body" | sed "$as_sed_sh"` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wempty-body" >&5 @@ -8455,46 +8444,6 @@ printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_var"\" = x"yes" then : as_fn_append ${wine_arch}_EXTRACFLAGS " -Wshift-overflow=2" -fi } - { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wstrict-prototypes" | sed "$as_sed_sh"` -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wstrict-prototypes" >&5 -printf %s "checking whether $CC supports -Wstrict-prototypes... " >&6; } -if eval test \${$as_ac_var+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) ac_wine_try_cflags_saved=$CFLAGS -ac_wine_try_cflags_saved_exeext=$ac_exeext -CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -Wstrict-prototypes" -ac_exeext=".exe" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -void *__os_arm64x_dispatch_ret = 0; -const unsigned int _load_config_used[0x50] = { sizeof(_load_config_used) }; -#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION -#error Too old clang version -#endif -int __cdecl mainCRTStartup(void) { return 0; } -_ACEOF -if ac_fn_c_try_link "$LINENO" -then : - eval "$as_ac_var=yes" -else case e in #( - e) eval "$as_ac_var=no" ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext -CFLAGS=$ac_wine_try_cflags_saved -ac_exeext=$ac_wine_try_cflags_saved_exeext ;; -esac -fi -eval ac_res=\$$as_ac_var - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } -if eval test \"x\$"$as_ac_var"\" = x"yes" -then : - as_fn_append ${wine_arch}_EXTRACFLAGS " -Wstrict-prototypes" fi } { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wtype-limits" | sed "$as_sed_sh"` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wtype-limits" >&5 @@ -8735,46 +8684,6 @@ printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_var"\" = x"yes" then : as_fn_append ${wine_arch}_EXTRACFLAGS " -Wlogical-op" -fi } - { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wabsolute-value" | sed "$as_sed_sh"` -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wabsolute-value" >&5 -printf %s "checking whether $CC supports -Wabsolute-value... " >&6; } -if eval test \${$as_ac_var+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) ac_wine_try_cflags_saved=$CFLAGS -ac_wine_try_cflags_saved_exeext=$ac_exeext -CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -Wabsolute-value" -ac_exeext=".exe" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -void *__os_arm64x_dispatch_ret = 0; -const unsigned int _load_config_used[0x50] = { sizeof(_load_config_used) }; -#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION -#error Too old clang version -#endif -int __cdecl mainCRTStartup(void) { return 0; } -_ACEOF -if ac_fn_c_try_link "$LINENO" -then : - eval "$as_ac_var=yes" -else case e in #( - e) eval "$as_ac_var=no" ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext -CFLAGS=$ac_wine_try_cflags_saved -ac_exeext=$ac_wine_try_cflags_saved_exeext ;; -esac -fi -eval ac_res=\$$as_ac_var - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } -if eval test \"x\$"$as_ac_var"\" = x"yes" -then : - as_fn_append ${wine_arch}_EXTRACFLAGS " -Wabsolute-value" fi } { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wenum-enum-conversion" | sed "$as_sed_sh"` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wenum-enum-conversion" >&5 @@ -8897,46 +8806,6 @@ printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_var"\" = x"yes" then : as_fn_append ${wine_arch}_EXTRACFLAGS " -ffunction-sections" -fi } - { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-fasync-exceptions -DMIN_CLANG_VERSION=19" | sed "$as_sed_sh"` -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -fasync-exceptions -DMIN_CLANG_VERSION=19" >&5 -printf %s "checking whether $CC supports -fasync-exceptions -DMIN_CLANG_VERSION=19... " >&6; } -if eval test \${$as_ac_var+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) ac_wine_try_cflags_saved=$CFLAGS -ac_wine_try_cflags_saved_exeext=$ac_exeext -CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -fasync-exceptions -DMIN_CLANG_VERSION=19" -ac_exeext=".exe" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -void *__os_arm64x_dispatch_ret = 0; -const unsigned int _load_config_used[0x50] = { sizeof(_load_config_used) }; -#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION -#error Too old clang version -#endif -int __cdecl mainCRTStartup(void) { return 0; } -_ACEOF -if ac_fn_c_try_link "$LINENO" -then : - eval "$as_ac_var=yes" -else case e in #( - e) eval "$as_ac_var=no" ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext -CFLAGS=$ac_wine_try_cflags_saved -ac_exeext=$ac_wine_try_cflags_saved_exeext ;; -esac -fi -eval ac_res=\$$as_ac_var - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } -if eval test \"x\$"$as_ac_var"\" = x"yes" -then : - as_fn_append ${wine_arch}_EXTRACFLAGS " -fasync-exceptions" fi } { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-ffp-exception-behavior=maytrap" | sed "$as_sed_sh"` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -ffp-exception-behavior=maytrap" >&5 @@ -9621,6 +9490,168 @@ then : fi } test "x$enable_build_id" != xyes || as_fn_append ${wine_arch}_LDFLAGS " -Wl,--build-id" + eval ${wine_arch}_EXTRACXXFLAGS=\$${wine_arch}_EXTRACFLAGS + { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wdeclaration-after-statement" | sed "$as_sed_sh"` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wdeclaration-after-statement" >&5 +printf %s "checking whether $CC supports -Wdeclaration-after-statement... " >&6; } +if eval test \${$as_ac_var+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_wine_try_cflags_saved=$CFLAGS +ac_wine_try_cflags_saved_exeext=$ac_exeext +CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -Wdeclaration-after-statement" +ac_exeext=".exe" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void *__os_arm64x_dispatch_ret = 0; +const unsigned int _load_config_used[0x50] = { sizeof(_load_config_used) }; +#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION +#error Too old clang version +#endif +int __cdecl mainCRTStartup(void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "$as_ac_var=yes" +else case e in #( + e) eval "$as_ac_var=no" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS=$ac_wine_try_cflags_saved +ac_exeext=$ac_wine_try_cflags_saved_exeext ;; +esac +fi +eval ac_res=\$$as_ac_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } +if eval test \"x\$"$as_ac_var"\" = x"yes" +then : + as_fn_append ${wine_arch}_EXTRACFLAGS " -Wdeclaration-after-statement" +fi } + { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wstrict-prototypes" | sed "$as_sed_sh"` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wstrict-prototypes" >&5 +printf %s "checking whether $CC supports -Wstrict-prototypes... " >&6; } +if eval test \${$as_ac_var+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_wine_try_cflags_saved=$CFLAGS +ac_wine_try_cflags_saved_exeext=$ac_exeext +CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -Wstrict-prototypes" +ac_exeext=".exe" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void *__os_arm64x_dispatch_ret = 0; +const unsigned int _load_config_used[0x50] = { sizeof(_load_config_used) }; +#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION +#error Too old clang version +#endif +int __cdecl mainCRTStartup(void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "$as_ac_var=yes" +else case e in #( + e) eval "$as_ac_var=no" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS=$ac_wine_try_cflags_saved +ac_exeext=$ac_wine_try_cflags_saved_exeext ;; +esac +fi +eval ac_res=\$$as_ac_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } +if eval test \"x\$"$as_ac_var"\" = x"yes" +then : + as_fn_append ${wine_arch}_EXTRACFLAGS " -Wstrict-prototypes" +fi } + { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-Wabsolute-value" | sed "$as_sed_sh"` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wabsolute-value" >&5 +printf %s "checking whether $CC supports -Wabsolute-value... " >&6; } +if eval test \${$as_ac_var+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_wine_try_cflags_saved=$CFLAGS +ac_wine_try_cflags_saved_exeext=$ac_exeext +CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -Wabsolute-value" +ac_exeext=".exe" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void *__os_arm64x_dispatch_ret = 0; +const unsigned int _load_config_used[0x50] = { sizeof(_load_config_used) }; +#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION +#error Too old clang version +#endif +int __cdecl mainCRTStartup(void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "$as_ac_var=yes" +else case e in #( + e) eval "$as_ac_var=no" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS=$ac_wine_try_cflags_saved +ac_exeext=$ac_wine_try_cflags_saved_exeext ;; +esac +fi +eval ac_res=\$$as_ac_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } +if eval test \"x\$"$as_ac_var"\" = x"yes" +then : + as_fn_append ${wine_arch}_EXTRACFLAGS " -Wabsolute-value" +fi } + { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-fasync-exceptions -DMIN_CLANG_VERSION=19" | sed "$as_sed_sh"` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -fasync-exceptions -DMIN_CLANG_VERSION=19" >&5 +printf %s "checking whether $CC supports -fasync-exceptions -DMIN_CLANG_VERSION=19... " >&6; } +if eval test \${$as_ac_var+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_wine_try_cflags_saved=$CFLAGS +ac_wine_try_cflags_saved_exeext=$ac_exeext +CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -fasync-exceptions -DMIN_CLANG_VERSION=19" +ac_exeext=".exe" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void *__os_arm64x_dispatch_ret = 0; +const unsigned int _load_config_used[0x50] = { sizeof(_load_config_used) }; +#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION +#error Too old clang version +#endif +int __cdecl mainCRTStartup(void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "$as_ac_var=yes" +else case e in #( + e) eval "$as_ac_var=no" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS=$ac_wine_try_cflags_saved +ac_exeext=$ac_wine_try_cflags_saved_exeext ;; +esac +fi +eval ac_res=\$$as_ac_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } +if eval test \"x\$"$as_ac_var"\" = x"yes" +then : + as_fn_append ${wine_arch}_EXTRACFLAGS " -fasync-exceptions" +fi } + done CC=$saved_CC @@ -24455,8 +24486,11 @@ TARGETFLAGS = $TARGETFLAGS toolsext = $toolsext HOST_ARCH = $HOST_ARCH aarch64_CC = $aarch64_CC +aarch64_CXX = $aarch64_CXX aarch64_CFLAGS = $aarch64_CFLAGS +aarch64_CXXFLAGS = $aarch64_CXXFLAGS aarch64_EXTRACFLAGS = $aarch64_EXTRACFLAGS +aarch64_EXTRACXXFLAGS = $aarch64_EXTRACXXFLAGS aarch64_LDFLAGS = $aarch64_LDFLAGS aarch64_DEBUG = $aarch64_DEBUG aarch64_TARGET = $aarch64_TARGET @@ -24464,8 +24498,11 @@ aarch64_STRIP = $aarch64_STRIP aarch64_DELAYLOADFLAG = $aarch64_DELAYLOADFLAG aarch64_DISABLED_SUBDIRS = $aarch64_DISABLED_SUBDIRS arm_CC = $arm_CC +arm_CXX = $arm_CXX arm_CFLAGS = $arm_CFLAGS +arm_CXXFLAGS = $arm_CXXFLAGS arm_EXTRACFLAGS = $arm_EXTRACFLAGS +arm_EXTRACXXFLAGS = $arm_EXTRACXXFLAGS arm_LDFLAGS = $arm_LDFLAGS arm_DEBUG = $arm_DEBUG arm_TARGET = $arm_TARGET @@ -24473,8 +24510,11 @@ arm_STRIP = $arm_STRIP arm_DELAYLOADFLAG = $arm_DELAYLOADFLAG arm_DISABLED_SUBDIRS = $arm_DISABLED_SUBDIRS arm64ec_CC = $arm64ec_CC +arm64ec_CXX = $arm64ec_CXX arm64ec_CFLAGS = $arm64ec_CFLAGS +arm64ec_CXXFLAGS = $arm64ec_CXXFLAGS arm64ec_EXTRACFLAGS = $arm64ec_EXTRACFLAGS +arm64ec_EXTRACXXFLAGS = $arm64ec_EXTRACXXFLAGS arm64ec_LDFLAGS = $arm64ec_LDFLAGS arm64ec_DEBUG = $arm64ec_DEBUG arm64ec_TARGET = $arm64ec_TARGET @@ -24482,8 +24522,11 @@ arm64ec_STRIP = $arm64ec_STRIP arm64ec_DELAYLOADFLAG = $arm64ec_DELAYLOADFLAG arm64ec_DISABLED_SUBDIRS = $arm64ec_DISABLED_SUBDIRS i386_CC = $i386_CC +i386_CXX = $i386_CXX i386_CFLAGS = $i386_CFLAGS +i386_CXXFLAGS = $i386_CXXFLAGS i386_EXTRACFLAGS = $i386_EXTRACFLAGS +i386_EXTRACXXFLAGS = $i386_EXTRACXXFLAGS i386_LDFLAGS = $i386_LDFLAGS i386_DEBUG = $i386_DEBUG i386_TARGET = $i386_TARGET @@ -24491,8 +24534,11 @@ i386_STRIP = $i386_STRIP i386_DELAYLOADFLAG = $i386_DELAYLOADFLAG i386_DISABLED_SUBDIRS = $i386_DISABLED_SUBDIRS x86_64_CC = $x86_64_CC +x86_64_CXX = $x86_64_CXX x86_64_CFLAGS = $x86_64_CFLAGS +x86_64_CXXFLAGS = $x86_64_CXXFLAGS x86_64_EXTRACFLAGS = $x86_64_EXTRACFLAGS +x86_64_EXTRACXXFLAGS = $x86_64_EXTRACXXFLAGS x86_64_LDFLAGS = $x86_64_LDFLAGS x86_64_DEBUG = $x86_64_DEBUG x86_64_TARGET = $x86_64_TARGET diff --git a/configure.ac b/configure.ac index 78364d27346..a05f3e31e12 100644 --- a/configure.ac +++ b/configure.ac @@ -174,7 +174,7 @@ case "$host_cpu" in x86_64) HOST_ARCH=x86_64 ;; esac m4_set_add_all([_AC_SUBST_VARS],[HOST_ARCH]m4_foreach([cpu],[aarch64,arm,arm64ec,i386,x86_64], - [m4_foreach([var],[CC,CFLAGS,EXTRACFLAGS,LDFLAGS,DEBUG,TARGET,STRIP,DELAYLOADFLAG,DISABLED_SUBDIRS],[,cpu[_]var])])) + [m4_foreach([var],[CC,CXX,CFLAGS,CXXFLAGS,EXTRACFLAGS,EXTRACXXFLAGS,LDFLAGS,DEBUG,TARGET,STRIP,DELAYLOADFLAG,DISABLED_SUBDIRS],[,cpu[_]var])])) case $host_os in darwin*) @@ -446,6 +446,8 @@ do CPPFLAGS="" AS_VAR_SET_IF([${wine_arch}_CFLAGS],[],[AS_VAR_SET([${wine_arch}_CFLAGS],[${CROSSCFLAGS:-"-g -O2"}])]) AS_VAR_SET_IF([${wine_arch}_LDFLAGS],[],[AS_VAR_SET([${wine_arch}_LDFLAGS],[$CROSSLDFLAGS])]) + AS_VAR_SET_IF([${wine_arch}_CXX],[],[AS_VAR_COPY([${wine_arch}_CXX],[${wine_arch}_CC])]) + AS_VAR_SET_IF([${wine_arch}_CXXFLAGS],[],[AS_VAR_COPY([${wine_arch}_CXXFLAGS],[${wine_arch}_CFLAGS])]) AS_VAR_COPY([CC],[${wine_arch}_CC]) AS_VAR_COPY([CFLAGS],[${wine_arch}_CFLAGS]) AS_VAR_COPY([LDFLAGS],[${wine_arch}_LDFLAGS]) @@ -559,24 +561,20 @@ This is an error since --enable-archs=$wine_arch was requested.])]) WINE_TRY_PE_CFLAGS([-Werror=unused-command-line-argument],[CFLAGS="$CFLAGS -Werror=unused-command-line-argument"]) WINE_TRY_PE_CFLAGS([-Werror=ignored-optimization-argument],[CFLAGS="$CFLAGS -Werror=ignored-optimization-argument"]) WINE_TRY_PE_CFLAGS([-Werror=unsupported-floating-point-opt],[CFLAGS="$CFLAGS -Werror=unsupported-floating-point-opt"]) - WINE_TRY_PE_CFLAGS([-Wdeclaration-after-statement]) WINE_TRY_PE_CFLAGS([-Wempty-body]) WINE_TRY_PE_CFLAGS([-Wignored-qualifiers]) WINE_TRY_PE_CFLAGS([-Winit-self]) WINE_TRY_PE_CFLAGS([-Wpacked-not-aligned],[AS_VAR_APPEND(${wine_arch}_EXTRACFLAGS,[" -Wno-packed-not-aligned"])]) WINE_TRY_PE_CFLAGS([-Wmicrosoft-enum-forward-reference],[AS_VAR_APPEND(${wine_arch}_EXTRACFLAGS,[" -Wno-microsoft-enum-forward-reference"])]) WINE_TRY_PE_CFLAGS([-Wshift-overflow=2]) - WINE_TRY_PE_CFLAGS([-Wstrict-prototypes]) WINE_TRY_PE_CFLAGS([-Wtype-limits]) WINE_TRY_PE_CFLAGS([-Wunused-but-set-parameter]) WINE_TRY_PE_CFLAGS([-Wvla]) WINE_TRY_PE_CFLAGS([-Wwrite-strings]) WINE_TRY_PE_CFLAGS([-Wpointer-arith]) WINE_TRY_PE_CFLAGS([-Wlogical-op]) - WINE_TRY_PE_CFLAGS([-Wabsolute-value]) WINE_TRY_PE_CFLAGS([-Wenum-enum-conversion],[:],WINE_TRY_PE_CFLAGS([-Wenum-conversion])) WINE_TRY_PE_CFLAGS([-ffunction-sections]) - WINE_TRY_PE_CFLAGS([-fasync-exceptions -DMIN_CLANG_VERSION=19], AS_VAR_APPEND([${wine_arch}_EXTRACFLAGS],[" -fasync-exceptions"])) WINE_TRY_PE_CFLAGS([-ffp-exception-behavior=maytrap]) dnl clang had broken -fms-hotpatch support before version 18 (https://github.com/llvm/llvm-project/pull/77245) @@ -644,6 +642,13 @@ This is an error since --enable-archs=$wine_arch was requested.])]) dnl don't bother testing flags, compilation will fail afterwards test "x$enable_build_id" != xyes || AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" -Wl,--build-id"]) + dnl Options that differ between C and C++ + AS_VAR_COPY([${wine_arch}_EXTRACXXFLAGS],[${wine_arch}_EXTRACFLAGS]) + WINE_TRY_PE_CFLAGS([-Wdeclaration-after-statement]) + WINE_TRY_PE_CFLAGS([-Wstrict-prototypes]) + WINE_TRY_PE_CFLAGS([-Wabsolute-value]) + WINE_TRY_PE_CFLAGS([-fasync-exceptions -DMIN_CLANG_VERSION=19], AS_VAR_APPEND([${wine_arch}_EXTRACFLAGS],[" -fasync-exceptions"])) + done CC=$saved_CC diff --git a/tools/make_makefiles b/tools/make_makefiles index 5e925855d55..48c390fca1d 100755 --- a/tools/make_makefiles +++ b/tools/make_makefiles @@ -252,7 +252,7 @@ sub assign_sources_to_makefiles(@) my $subdir = $dir; while ($dir && !defined $makefiles{"$dir/Makefile.in"}) { $dir = dirname( $dir ); } - $subdir =~ s/^$dir\/?//; + $subdir =~ s/^\Q$dir\E\/?//; next unless $dir; die "no makefile found for $file\n" unless defined $makefiles{"$dir/Makefile.in"}; @@ -291,7 +291,11 @@ sub assign_sources_to_makefiles(@) { next unless $dir eq "dlls/winewayland.drv"; } - elsif ($name !~ /\.(S|c|desktop|in|inl|l|m|mc|po|rc|rh|sfd|svg|ver|x|y)$/) + elsif ($name =~ /^msvcrt\/[^.]+$/) # C++ header without extension + { + next unless $dir eq "include"; + } + elsif ($name !~ /\.(S|c|cpp|desktop|in|inl|l|m|mc|po|rc|rh|sfd|svg|ver|x|y)$/) { next; } diff --git a/tools/makedep.c b/tools/makedep.c index 8c6d8d58b58..bc099c6f6cb 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -97,7 +97,8 @@ struct incl_file #define FLAG_SFD_FONTS 0x00400000 /* sfd file generated bitmap fonts */ #define FLAG_C_IMPLIB 0x01000000 /* file is part of an import library */ #define FLAG_C_UNIX 0x02000000 /* file is part of a Unix library */ -#define FLAG_ARM64EC_X64 0x04000000 /* use x86_64 object on ARM64EC */ +#define FLAG_C_CXX 0x04000000 /* file uses C++ */ +#define FLAG_ARM64EC_X64 0x08000000 /* use x86_64 object on ARM64EC */ static const struct { @@ -181,7 +182,7 @@ static const char *delay_load_flags[MAX_ARCHS]; static struct strarray debug_flags[MAX_ARCHS]; static struct strarray target_flags[MAX_ARCHS]; static struct strarray extra_cflags[MAX_ARCHS]; -static struct strarray extra_cflags_extlib[MAX_ARCHS]; +static struct strarray extra_cxxflags[MAX_ARCHS]; static struct strarray disabled_dirs[MAX_ARCHS]; static unsigned int native_archs[MAX_ARCHS]; static unsigned int hybrid_archs[MAX_ARCHS]; @@ -1140,6 +1141,16 @@ static void parse_c_file( struct file *source, FILE *file ) } +/******************************************************************* + * parse_cxx_file + */ +static void parse_cxx_file( struct file *source, FILE *file ) +{ + source->flags |= FLAG_C_CXX; + parse_c_file( source, file ); +} + + /******************************************************************* * parse_rc_file */ @@ -1256,6 +1267,9 @@ static const struct { ".x", parse_c_file }, { ".y", parse_c_file }, { ".idl", parse_idl_file }, + { ".cpp", parse_cxx_file }, + { ".hpp", parse_cxx_file }, + { ".ipp", parse_cxx_file }, { ".rc", parse_rc_file }, { ".ver", parse_rc_file }, { ".in", parse_in_file }, @@ -1287,6 +1301,12 @@ static struct file *load_file( const char *name ) parse_functions[i].parse( file, f ); break; } + if (i == ARRAY_SIZE(parse_functions)) + { + /* check for C++ header with no extension */ + char *dir = strstr( name, "/msvcrt/" ); + if (dir && !strchr( dir, '.' )) parse_cxx_file( file, f ); + } fclose( f ); input_file_name = NULL; @@ -1658,7 +1678,7 @@ static void parse_file( struct makefile *make, struct incl_file *source, bool sr if (strendswith( file->name, ".m" )) file->flags |= FLAG_C_UNIX; if (file->flags & FLAG_C_UNIX) source->use_msvcrt = false; - else if (file->flags & FLAG_C_IMPLIB) source->use_msvcrt = true; + else if (file->flags & (FLAG_C_IMPLIB | FLAG_C_CXX)) source->use_msvcrt = true; if (source->sourcename) { @@ -2128,6 +2148,10 @@ static void get_dependencies( struct incl_file *file, struct incl_file *source ) if (file != source) { if (file->owner == source) return; /* already processed */ + if (!(source->file->flags & FLAG_C_CXX)) /* ignore C++ dependencies for non-C++ sources */ + { + if (file->file && (file->file->flags & FLAG_C_CXX)) return; + } if (file->type == INCL_IMPORTLIB) { if (!(source->file->flags & (FLAG_IDL_TYPELIB | FLAG_IDL_REGTYPELIB))) @@ -3489,6 +3513,10 @@ static void output_source_one_arch( struct makefile *make, struct incl_file *sou { if (!unix_lib_supported) return; } + else if (source->file->flags & FLAG_C_CXX) + { + return; + } else if (archs.count > 1 && is_using_msvcrt( make )) { if (!so_dll_supported) return; @@ -3517,11 +3545,23 @@ static void output_source_one_arch( struct makefile *make, struct incl_file *sou strarray_add( &cflags, "-D__arm64ec_x64__" ); strarray_addall( &cflags, get_expanded_make_var_array( top_makefile, "x86_64_EXTRACFLAGS" )); } + else if (source->file->flags & FLAG_C_CXX) + { + var_cc = arch_make_variable( "CXX", arch ); + var_cflags = arch_make_variable( "CXXFLAGS", arch ); + if (make->external) + strarray_addall( &cflags, remove_warning_flags( extra_cxxflags[arch] )); + else + strarray_addall( &cflags, extra_cxxflags[arch] ); + } else { var_cc = arch_make_variable( "CC", arch ); var_cflags = arch_make_variable( "CFLAGS", arch ); - strarray_addall( &cflags, make->external ? extra_cflags_extlib[arch] : extra_cflags[arch] ); + if (make->external) + strarray_addall( &cflags, remove_warning_flags( extra_cflags[arch] )); + else + strarray_addall( &cflags, extra_cflags[arch] ); } if (!arch) @@ -3604,6 +3644,12 @@ static void output_source_one_arch( struct makefile *make, struct incl_file *sou cmd->cmd = get_expanded_make_variable( make, "x86_64_CC" ); if (cflags) strarray_add( &cmd->args, cflags ); } + else if (source->file->flags & FLAG_C_CXX) + { + char *cflags = get_expanded_arch_var( make, "CXXFLAGS", arch ); + cmd->cmd = get_expanded_arch_var( make, "CXX", arch ); + if (cflags) strarray_add( &cmd->args, cflags ); + } else { char *cflags = get_expanded_arch_var( make, "CFLAGS", arch ); @@ -4168,13 +4214,23 @@ static void output_sources( struct makefile *make ) char *obj = xstrdup( source->name ); char *ext = get_extension( obj ); - if (!ext) fatal_error( "unsupported file type %s\n", source->name ); - *ext++ = 0; + if (ext) + { + *ext++ = 0; - for (j = 0; output_source_funcs[j].ext; j++) - if (!strcmp( ext, output_source_funcs[j].ext )) break; + for (j = 0; output_source_funcs[j].ext; j++) + if (!strcmp( ext, output_source_funcs[j].ext )) break; + + output_source_funcs[j].fn( make, source, obj ); + } + else + { + if (source->file->flags & FLAG_C_CXX) + output_source_h( make, source, obj ); + else + fatal_error( "unsupported file type %s\n", source->name ); + } - output_source_funcs[j].fn( make, source, obj ); strarray_addall_uniq( &make->dependencies, source->dependencies ); } @@ -4950,7 +5006,7 @@ int main( int argc, char *argv[] ) { arch_pe_dirs[arch] = strmake( "%s-windows", archs.str[arch] ); extra_cflags[arch] = get_expanded_arch_var_array( top_makefile, "EXTRACFLAGS", arch ); - extra_cflags_extlib[arch] = remove_warning_flags( extra_cflags[arch] ); + extra_cxxflags[arch] = get_expanded_arch_var_array( top_makefile, "EXTRACXXFLAGS", arch ); disabled_dirs[arch] = get_expanded_arch_var_array( top_makefile, "DISABLED_SUBDIRS", arch ); if (!is_multiarch( arch )) continue; delay_load_flags[arch] = get_expanded_arch_var( top_makefile, "DELAYLOADFLAG", arch ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10273
From: Alexandre Julliard <julliard@winehq.org> With help from Jacek Caban. --- aclocal.m4 | 884 ++++++++++++++++++++++++++++++++++++++++++++++++++- configure | 823 +++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 36 +++ 3 files changed, 1740 insertions(+), 3 deletions(-) diff --git a/aclocal.m4 b/aclocal.m4 index 873c707b657..11f8c855697 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -391,6 +391,884 @@ for msg in $wine_warnings; do done IFS="$ac_save_IFS"]) -dnl Local Variables: -dnl compile-command: "autoreconf --warnings=all" -dnl End: + +# C++ version tests copied from https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com> +# Copyright (c) 2012 Zack Weinberg <zackw@panix.com> +# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu> +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com> +# Copyright (c) 2015 Paul Norman <penorman@mac.com> +# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu> +# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com> +# Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com> +# Copyright (c) 2020 Jason Merrill <jason@redhat.com> +# Copyright (c) 2021, 2024 Jörn Heusipp <osmanx@problemloesungsmaschine.de> +# Copyright (c) 2015, 2022, 2023, 2024 Olly Betts +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11] +) + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14] +) + +dnl Test body for checking C++17 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17] +) + +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20] +) + +dnl Test body for checking C++23 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_23], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_23] +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplu... +// +// The value __cplusplus ought to have is available in _MSVC_LANG since +// Visual Studio 2015 Update 3: +// +// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros +// +// This was also the first MSVC version to support C++14 so we can't use the +// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having +// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later. +#elif __cplusplus < 201103L && !defined _MSC_VER + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L && !defined _MSC_VER + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + +#error "This is not a C++17 compiler" + +#else + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template<typename... Args> + int multiply(Args... args) + { + return (args * ... * 1); + } + + template<typename... Args> + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_typename_in_template_template_parameter + { + + template<template<typename> typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template <bool cond> + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template <typename T1, typename T2> + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template <auto n> + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template<typename T> + Bad + f(T*, T*); + + template<typename T1, typename T2> + Good + f(T1*, T2*); + + } + + namespace test_inline_variables + { + + template<class T> void f(T) + {} + + template<class T> inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + +]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L + +#error "This is not a C++20 compiler" + +#else + +#include <version> + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L + +]]) + + +dnl Tests for new features in C++23 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_23], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L + +#error "This is not a C++23 compiler" + +#else + +#include <version> + +namespace cxx23 +{ + +// As C++23 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx23 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L + +]]) diff --git a/configure b/configure index 02649853799..23249d70e21 100755 --- a/configure +++ b/configure @@ -7390,8 +7390,10 @@ then : fi saved_CC=$CC +saved_CXX=$CXX saved_CFLAGS=$CFLAGS saved_CPPFLAGS=$CPPFLAGS +saved_CXXFLAGS=$CXXFLAGS saved_LDFLAGS=$LDFLAGS { extra_arch=; unset extra_arch;} @@ -7711,7 +7713,9 @@ else case e in #( esac fi eval CC=\$${wine_arch}_CC + eval CXX=\$${wine_arch}_CXX eval CFLAGS=\$${wine_arch}_CFLAGS + eval CXXFLAGS=\$${wine_arch}_CXXFLAGS eval LDFLAGS=\$${wine_arch}_LDFLAGS eval "${wine_arch}_EXTRACFLAGS=\"-D__WINE_PE_BUILD -Wall\"" @@ -7837,6 +7841,7 @@ fi } as_fn_append ${wine_arch}_EXTRACFLAGS " $llvm_extra_cflags" as_fn_append ${wine_arch}_LDFLAGS " $llvm_extra_ldflags" CFLAGS="$CFLAGS $llvm_extra_cflags $llvm_cflags" + CXXFLAGS="$CXXFLAGS $llvm_extra_cflags $llvm_cflags" else as_wine_cv_crosscc=`printf "%s\n" "wine_cv_${wine_arch}_crosscc" | sed "$as_sed_sh"` @@ -7944,6 +7949,822 @@ printf "%s\n" "$res" >&6; } as_fn_append ${wine_arch}_CC " $res" ;; esac + as_wine_cv_crosscxx_cxx17=`printf "%s\n" "ac_cv_${wine_arch}_crosscxx_cxx17" | sed "$as_sed_sh"` + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++17 features" >&5 +printf %s "checking for $CXX option to enable C++17 features... " >&6; } + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +if eval test \${$as_wine_cv_crosscxx_cxx17+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) eval "$as_wine_cv_crosscxx_cxx17=no" + for arg in '' '-std=gnu++17' + do + test -z "$arg" || CXX="$CXX $arg" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplu... +// +// The value __cplusplus ought to have is available in _MSVC_LANG since +// Visual Studio 2015 Update 3: +// +// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros +// +// This was also the first MSVC version to support C++14 so we can't use the +// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having +// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later. +#elif __cplusplus < 201103L && !defined _MSC_VER + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + + + + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L && !defined _MSC_VER + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + +#error "This is not a C++17 compiler" + +#else + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template<typename... Args> + int multiply(Args... args) + { + return (args * ... * 1); + } + + template<typename... Args> + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_typename_in_template_template_parameter + { + + template<template<typename> typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template <bool cond> + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template <typename T1, typename T2> + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template <auto n> + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template<typename T> + Bad + f(T*, T*); + + template<typename T1, typename T2> + Good + f(T1*, T2*); + + } + + namespace test_inline_variables + { + + template<class T> void f(T) + {} + + template<class T> inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + eval "$as_wine_cv_crosscxx_cxx17=\$arg" +else case e in #( + e) eval "$as_wine_cv_crosscxx_cxx17=no" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + eval CXX=\$${wine_arch}_CXX + if eval test \"x\$"$as_wine_cv_crosscxx_cxx17"\" = x"no" +then : + +else case e in #( + e) break ;; +esac +fi + done ;; +esac +fi + + eval res=\$$as_wine_cv_crosscxx_cxx17 + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + case "x$res" in + x) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } ;; + xno) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } + if test ${enable_archs+y} +then : + as_fn_error $? "$wine_arch PE cross-compiler supporting C++17 not found. +This is an error since --enable-archs=$wine_arch was requested." "$LINENO" 5 +fi + continue + ;; + x*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $res" >&5 +printf "%s\n" "$res" >&6; } + as_fn_append ${wine_arch}_CXX " $res" ;; + esac + if test "x$wine_arch" = xi386 then : @@ -9655,8 +10476,10 @@ fi } done CC=$saved_CC +CXX=$saved_CXX CFLAGS=$saved_CFLAGS CPPFLAGS=$saved_CPPFLAGS +CXXFLAGS=$saved_CXXFLAGS LDFLAGS=$saved_LDFLAGS case $HOST_ARCH in diff --git a/configure.ac b/configure.ac index a05f3e31e12..72b9a85929a 100644 --- a/configure.ac +++ b/configure.ac @@ -396,8 +396,10 @@ AS_VAR_SET_IF([enable_archs], AS_VAR_IF([PE_ARCHS],[none],[cross_archs=]) saved_CC=$CC +saved_CXX=$CXX saved_CFLAGS=$CFLAGS saved_CPPFLAGS=$CPPFLAGS +saved_CXXFLAGS=$CXXFLAGS saved_LDFLAGS=$LDFLAGS AS_UNSET(extra_arch) @@ -449,7 +451,9 @@ do AS_VAR_SET_IF([${wine_arch}_CXX],[],[AS_VAR_COPY([${wine_arch}_CXX],[${wine_arch}_CC])]) AS_VAR_SET_IF([${wine_arch}_CXXFLAGS],[],[AS_VAR_COPY([${wine_arch}_CXXFLAGS],[${wine_arch}_CFLAGS])]) AS_VAR_COPY([CC],[${wine_arch}_CC]) + AS_VAR_COPY([CXX],[${wine_arch}_CXX]) AS_VAR_COPY([CFLAGS],[${wine_arch}_CFLAGS]) + AS_VAR_COPY([CXXFLAGS],[${wine_arch}_CXXFLAGS]) AS_VAR_COPY([LDFLAGS],[${wine_arch}_LDFLAGS]) AS_VAR_SET([${wine_arch}_EXTRACFLAGS],["-D__WINE_PE_BUILD -Wall"]) @@ -495,6 +499,7 @@ do AS_VAR_APPEND([${wine_arch}_EXTRACFLAGS],[" $llvm_extra_cflags"]) AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" $llvm_extra_ldflags"]) CFLAGS="$CFLAGS $llvm_extra_cflags $llvm_cflags" + CXXFLAGS="$CXXFLAGS $llvm_extra_cflags $llvm_cflags" else AS_VAR_PUSHDEF([wine_cv_crosscc], [wine_cv_${wine_arch}_crosscc]) AC_CACHE_CHECK([whether $CC works], wine_cv_crosscc, @@ -540,6 +545,35 @@ This is an error since --enable-archs=$wine_arch was requested.])]) AS_VAR_APPEND([${wine_arch}_CC],[" $res"]) ;; esac + AS_VAR_PUSHDEF([wine_cv_crosscxx_cxx17],[ac_cv_${wine_arch}_crosscxx_cxx17]) + AC_MSG_CHECKING([for $CXX option to enable C++17 features]) + AC_LANG_PUSH([C++]) + AC_CACHE_VAL([wine_cv_crosscxx_cxx17], + [AS_VAR_SET([wine_cv_crosscxx_cxx17],[no]) + for arg in '' '-std=gnu++17' + do + test -z "$arg" || CXX="$CXX $arg" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_17])], + [AS_VAR_SET([wine_cv_crosscxx_cxx17],[$arg])], + [AS_VAR_SET([wine_cv_crosscxx_cxx17],[no])]) + AS_VAR_COPY([CXX],[${wine_arch}_CXX]) + AS_VAR_IF([wine_cv_crosscxx_cxx17],[no],[],[break]) + done]) + AS_VAR_COPY([res],[wine_cv_crosscxx_cxx17]) + AC_LANG_POP([C++]) + AS_VAR_POPDEF([wine_cv_crosscxx_cxx17]) + case "x$res" in + x) AC_MSG_RESULT([none needed]) ;; + xno) AC_MSG_RESULT([unsupported]) + AS_VAR_SET_IF([enable_archs], + [AC_MSG_ERROR([$wine_arch PE cross-compiler supporting C++17 not found. +This is an error since --enable-archs=$wine_arch was requested.])]) + continue + ;; + x*) AC_MSG_RESULT([$res]) + AS_VAR_APPEND([${wine_arch}_CXX],[" $res"]) ;; + esac + AS_VAR_IF([wine_arch],[i386],[], [AS_VAR_PUSHDEF([wine_cv_seh_support],[ac_cv_${wine_arch}_seh_support]) AC_CACHE_CHECK([whether $CC supports SEH directives], wine_cv_seh_support, @@ -652,8 +686,10 @@ This is an error since --enable-archs=$wine_arch was requested.])]) done CC=$saved_CC +CXX=$saved_CXX CFLAGS=$saved_CFLAGS CPPFLAGS=$saved_CPPFLAGS +CXXFLAGS=$saved_CXXFLAGS LDFLAGS=$saved_LDFLAGS case $HOST_ARCH in -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10273
From: Jacek Caban <jacek@codeweavers.com> Based on libcxxabi. --- dlls/vcruntime140/Makefile.in | 3 +- dlls/vcruntime140/new.cpp | 170 ++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 dlls/vcruntime140/new.cpp diff --git a/dlls/vcruntime140/Makefile.in b/dlls/vcruntime140/Makefile.in index 1f99225ffe8..715242c80ad 100644 --- a/dlls/vcruntime140/Makefile.in +++ b/dlls/vcruntime140/Makefile.in @@ -2,4 +2,5 @@ MODULE = vcruntime140.dll IMPORTLIB = vcruntime140 SOURCES = \ - misc.c + misc.c \ + new.cpp diff --git a/dlls/vcruntime140/new.cpp b/dlls/vcruntime140/new.cpp new file mode 100644 index 00000000000..ef3ce48f415 --- /dev/null +++ b/dlls/vcruntime140/new.cpp @@ -0,0 +1,170 @@ +//===--------------------- stdlib_new_delete.cpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// This file implements the new and delete operators. +//===----------------------------------------------------------------------===// + +#include <new.h> +#include <vcruntime_exception.h> +#include <malloc.h> + +#if 0 +#pragma makedep implib +#endif + +void *operator new(size_t size) +{ + if (size == 0) + size = 1; + void* p; + while ((p = ::malloc(size)) == 0) + { + if (!_callnewh(size)) + throw std::bad_alloc(); + } + return p; +} + +void *operator new(size_t size, const std::nothrow_t&) noexcept +{ + void* p = 0; + try + { + p = ::operator new(size); + } + catch (...) + { + } + return p; +} + +void *operator new[](size_t size) +{ + return ::operator new(size); +} + +void *operator new[](size_t size, const std::nothrow_t&) noexcept +{ + void* p = 0; + try + { + p = ::operator new[](size); + } + catch (...) + { + } + return p; +} + +void operator delete(void* ptr) noexcept +{ + if (ptr) + ::free(ptr); +} + +void operator delete(void* ptr, const std::nothrow_t&) noexcept +{ + ::operator delete(ptr); +} + +void operator delete(void* ptr, size_t) noexcept +{ + ::operator delete(ptr); +} + +void operator delete[] (void* ptr) noexcept +{ + ::operator delete(ptr); +} + +void operator delete[] (void* ptr, const std::nothrow_t&) noexcept +{ + ::operator delete[](ptr); +} + +void operator delete[] (void* ptr, size_t) noexcept +{ + ::operator delete[](ptr); +} + +void *operator new(size_t size, std::align_val_t alignment) +{ + if (size == 0) + size = 1; + if (static_cast<size_t>(alignment) < sizeof(void*)) + alignment = std::align_val_t(sizeof(void*)); + void* p; + while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr) + { + if (!_callnewh(size)) + throw std::bad_alloc(); + } + return p; +} + +void *operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + void* p = 0; + try + { + p = ::operator new(size, alignment); + } + catch (...) + { + } + return p; +} + +void *operator new[](size_t size, std::align_val_t alignment) +{ + return ::operator new(size, alignment); +} + +void *operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + void* p = 0; + try + { + p = ::operator new[](size, alignment); + } + catch (...) + { + } + return p; +} + +void operator delete(void* ptr, std::align_val_t) noexcept +{ + if (ptr) + ::_aligned_free(ptr); +} + +void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + ::operator delete(ptr, alignment); +} + +void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept +{ + ::operator delete(ptr, alignment); +} + +void operator delete[] (void* ptr, std::align_val_t alignment) noexcept +{ + ::operator delete(ptr, alignment); +} + +void operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + ::operator delete[](ptr, alignment); +} + +void operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept +{ + ::operator delete[](ptr, alignment); +} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10273
From: Jacek Caban <jacek@codeweavers.com> --- dlls/vcruntime140/Makefile.in | 3 +- dlls/vcruntime140/typeinfo_root.cpp | 45 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 dlls/vcruntime140/typeinfo_root.cpp diff --git a/dlls/vcruntime140/Makefile.in b/dlls/vcruntime140/Makefile.in index 715242c80ad..30231e1b074 100644 --- a/dlls/vcruntime140/Makefile.in +++ b/dlls/vcruntime140/Makefile.in @@ -3,4 +3,5 @@ IMPORTLIB = vcruntime140 SOURCES = \ misc.c \ - new.cpp + new.cpp \ + typeinfo_root.cpp diff --git a/dlls/vcruntime140/typeinfo_root.cpp b/dlls/vcruntime140/typeinfo_root.cpp new file mode 100644 index 00000000000..018c292ee3f --- /dev/null +++ b/dlls/vcruntime140/typeinfo_root.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2026 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep implib +#endif + +#ifdef _MSC_VER + +#include "windef.h" +#include "winnt.h" +#include "wine/asm.h" + +struct __type_info_node +{ + SLIST_HEADER list; +}; + +__type_info_node __type_info_root_node = {}; + +extern "C" void __cdecl __std_type_info_destroy_list(SLIST_HEADER*); + +extern "C" void __cdecl __wine_destroy_type_info_list(void) +{ + __std_type_info_destroy_list(&__type_info_root_node.list); +} + +__ASM_SECTION_POINTER( ".section .CRT$XTY", __wine_destroy_type_info_list ) + +#endif -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10273
From: Jacek Caban <jacek@codeweavers.com> --- dlls/vcruntime140/Makefile.in | 1 + dlls/vcruntime140/init_thread.c | 83 +++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 dlls/vcruntime140/init_thread.c diff --git a/dlls/vcruntime140/Makefile.in b/dlls/vcruntime140/Makefile.in index 30231e1b074..a0004e52af6 100644 --- a/dlls/vcruntime140/Makefile.in +++ b/dlls/vcruntime140/Makefile.in @@ -2,6 +2,7 @@ MODULE = vcruntime140.dll IMPORTLIB = vcruntime140 SOURCES = \ + init_thread.c \ misc.c \ new.cpp \ typeinfo_root.cpp diff --git a/dlls/vcruntime140/init_thread.c b/dlls/vcruntime140/init_thread.c new file mode 100644 index 00000000000..6d73f85785f --- /dev/null +++ b/dlls/vcruntime140/init_thread.c @@ -0,0 +1,83 @@ +/* + * Thread-safe static constructor support functions. + * + * Copyright 2026 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep implib +#endif + +#ifdef __WINE_PE_BUILD + +#include <stdarg.h> +#include <limits.h> +#include "windef.h" +#include "winbase.h" + +static SRWLOCK init_lock; +static CONDITION_VARIABLE init_cv; + +int _Init_global_epoch = INT_MIN; +__thread int _Init_thread_epoch = INT_MIN; + +void _Init_thread_lock(void) +{ + AcquireSRWLockExclusive( &init_lock ); +} + +void _Init_thread_unlock(void) +{ + ReleaseSRWLockExclusive( &init_lock ); +} + +void _Init_thread_wait( DWORD timeout ) +{ + SleepConditionVariableSRW( &init_cv, &init_lock, timeout, 0 ); +} + +void _Init_thread_notify(void) +{ + WakeAllConditionVariable( &init_cv ); +} + +void _Init_thread_header( int *once ) +{ + _Init_thread_lock(); + while (*once == -1) _Init_thread_wait( INFINITE ); + if (*once) _Init_thread_epoch = _Init_global_epoch; + else *once = -1; + _Init_thread_unlock(); +} + +void _Init_thread_footer( int *once ) +{ + _Init_thread_lock(); + _Init_thread_epoch = *once = ++_Init_global_epoch; + _Init_thread_unlock(); + _Init_thread_notify(); +} + +void _Init_thread_abort( int *once ) +{ + _Init_thread_lock(); + *once = 0; + _Init_thread_unlock(); + _Init_thread_notify(); +} + +#endif -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10273
From: Jacek Caban <jacek@codeweavers.com> Clang does not generate RTTI/vtbl for this type. The vtable is referenced by ther classes’ RTTI. On MSVC, it is provided by the statically linked portion of vcruntime. --- dlls/vcruntime140/Makefile.in | 1 + dlls/vcruntime140/typeinfo.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 dlls/vcruntime140/typeinfo.c diff --git a/dlls/vcruntime140/Makefile.in b/dlls/vcruntime140/Makefile.in index a0004e52af6..f38bc1df6e5 100644 --- a/dlls/vcruntime140/Makefile.in +++ b/dlls/vcruntime140/Makefile.in @@ -5,4 +5,5 @@ SOURCES = \ init_thread.c \ misc.c \ new.cpp \ + typeinfo.c \ typeinfo_root.cpp diff --git a/dlls/vcruntime140/typeinfo.c b/dlls/vcruntime140/typeinfo.c new file mode 100644 index 00000000000..e5b59d85e29 --- /dev/null +++ b/dlls/vcruntime140/typeinfo.c @@ -0,0 +1,34 @@ +/* + * Copyright 2026 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep implib +#endif + +#ifdef __WINE_PE_BUILD + +#include <stdarg.h> +#include "../msvcrt/cxx.h" +#include "wine/asm.h" + +CREATE_TYPE_INFO_VTABLE + +asm( ".globl \"??_7type_info@@6B@\"\n" + "\"??_7type_info@@6B@\"=" __ASM_NAME("type_info_vtable") "\n" ); + +#endif -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10273
participants (3)
-
Alexandre Julliard -
Alexandre Julliard (@julliard) -
Jacek Caban