From fd843977cd1f86e363194c7255447ea58fe6ef01 Mon Sep 17 00:00:00 2001 From: Cody Miller Date: Sat, 22 Aug 2026 14:22:49 -0700 Subject: [PATCH 01/85] Cody's original changes. --- stl/CMakeLists.txt | 4 +- stl/inc/__msvc_math.hpp | 678 ++++++++++++++++++++++++++ stl/inc/__msvc_stdlib.hpp | 836 ++++++++++++++++++++++++++++++++ stl/inc/cmath | 169 ++++--- stl/inc/cstdlib | 9 +- stl/inc/header-units.json | 2 + stl/inc/yvals_core.h | 23 + stl/msbuild/stl_2/amd64.exports | 4 + stl/msbuild/stl_2/arm64.exports | 4 + stl/msbuild/stl_2/i386.exports | 4 + stl/src/special_math.cpp | 37 ++ 11 files changed, 1686 insertions(+), 84 deletions(-) create mode 100644 stl/inc/__msvc_math.hpp create mode 100644 stl/inc/__msvc_stdlib.hpp diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index a8dbd7083bb..e767bb81dda 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -17,12 +17,14 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_heap_algorithms.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_int128.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_iter_core.hpp + ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_math.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_minmax.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_ostream.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_print.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_ranges_to.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_ranges_tuple_formatter.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_sanitizer_annotate_container.hpp + ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_stdlib.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_string_view.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_system_error_abi.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_threads_core.hpp @@ -397,7 +399,7 @@ add_compile_definitions(_CRTBLD _HAS_OLD_IOSTREAMS_MEMBERS=1) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "Embedded") add_compile_options(/nologo /WX /Gy - "$<$:/diagnostics:caret;/W4;/w14265;/w15038;/fastfail;/guard:cf;/Zp8;/std:c++latest;/permissive-;/Zc:preprocessor;/Zc:threadSafeInit-;/Zl>" + "$<$:/diagnostics:caret;/W4;/w14265;/w15038;/fastfail;/guard:cf;/Zp8;/std:c++latest;/permissive-;/Zc:preprocessor;/Zc:threadSafeInit-;/Zc:cmath-;/Zl>" "$<$,$>:/guard:ehcont>" "$<$,$>:/guard:signret>" "$<$:/W3;/quiet>" diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp new file mode 100644 index 00000000000..0229528fd9a --- /dev/null +++ b/stl/inc/__msvc_math.hpp @@ -0,0 +1,678 @@ +// __msvc_math.hpp internal header (core) + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// This lies outside of the inclusion guard because the UCRT's math.h allows +// for repeated inclusion with behavioral differences dictated by this macro. +// math.h can be included once without this macro defined and a second time +// with it defined, resulting in the nonstandard math constants being defined. +#ifdef _USE_MATH_DEFINES +#include +#endif + +#ifndef __MSVC_MATH_HPP +#define __MSVC_MATH_HPP + +// When a user writes `#include `, the MSVC frontend arranges for this +// file to be included first. Because this file is intended to supplant the +// CRT's math components, we define the _INC_MATH macro to neutralize the +// contents of math.h when it is processed after. _INC_MATH is used as the +// include guard for the CRT's math file and is an intended public API. +#define _INC_MATH + +#include + +#if _STL_COMPILER_PREPROCESSOR +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS 4163) // 'meow' not available as an intrinsic function +#pragma push_macro("new") + +_STL_DISABLE_CLANG_WARNINGS + +#define _STL_DEF_FUNC1(specs, name, ret, fptype) \ + extern "C" _NODISCARD specs ret name(fptype _Xx) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx); \ + } + +#define _STL_DEF_FUNC2(specs, name, ret, fptype) \ + extern "C" _NODISCARD specs ret name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx0, _Xx1); \ + } + +#define _STL_DEF_FUNC3(specs, name, ret, fptype) \ + extern "C" _NODISCARD specs ret name(fptype _Xx0, fptype _Xx1, fptype _Xx2) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx0, _Xx1, _Xx2); \ + } + +// `long double` and `double` are the same width on MSVC, so `long double` +// variants of math functions forward to the `long` variants. +#define _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) \ + extern "C" _NODISCARD specs long double name##l(long double _Xx0) noexcept /* strengthened */ { \ + return name(static_cast(_Xx0)); \ + } + +#define _STL_DEF_LDOUBLE_FORWARD_FUNC2(specs, name) \ + extern "C" _NODISCARD specs long double name##l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { \ + return name(static_cast(_Xx0), static_cast(_Xx1)); \ + } + +#define _STL_DEF_LDOUBLE_FORWARD_FUNC3(specs, name) \ + extern "C" _NODISCARD specs long double name##l( \ + long double _Xx0, long double _Xx1, long double _Xx2) noexcept /* strengthened */ { \ + return name(static_cast(_Xx0), static_cast(_Xx1), static_cast(_Xx2)); \ + } + +// N.B. Declarations stamped out by these macros are not noexcept because they +// are intended to match the definitions in the UCRT, which are not themselves +// noexcept. +#define _STL_DECLARE_FUNC1(specs, name, ret, fptype) extern "C" _NODISCARD specs ret name(fptype); + +#define _STL_DECLARE_FUNC2(specs, name, ret, fptype) extern "C" _NODISCARD specs ret name(fptype, fptype); + +// Defines three non-overloaded functions with signature `fp-type(fp-type)`. +// The names of the float and long double variants are suffixed with `f` and `l`, +// respectively. +#define _STL_DEF_FAMILY1(specs, name) \ + _STL_DEF_FUNC1(specs, name##f, float, float) \ + _STL_DEF_FUNC1(specs, name, double, double) \ + _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) + +// Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type)`. +// The names of the float and long double variants are suffixed with `f` and `l`, +// respectively. +#define _STL_DEF_FAMILY2(specs, name) \ + _STL_DEF_FUNC2(specs, name##f, float, float) \ + _STL_DEF_FUNC2(specs, name, double, double) \ + _STL_DEF_LDOUBLE_FORWARD_FUNC2(specs, name) + +// Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type)`. +// The names of the float and long double variants are suffixed with `f` and `l`, +// respectively. +#define _STL_DEF_FAMILY3(specs, name) \ + _STL_DEF_FUNC3(specs, name##f, float, float) \ + _STL_DEF_FUNC3(specs, name, double, double) \ + _STL_DEF_LDOUBLE_FORWARD_FUNC3(specs, name) + +// N.B. the static_cast in the body of the predicate functions is because the +// builtins return int. +#define _STL_DEF_PREDICATE1(specs, name, builtin, fptype) \ + _NODISCARD specs bool name(fptype _Xx) noexcept /* strengthened */ { \ + return static_cast(builtin(_Xx)); \ + } + +#define _STL_DEF_PREDICATE2(specs, name, builtin, fptype) \ + _NODISCARD specs bool name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ + return static_cast(builtin(_Xx0, _Xx1)); \ + } + +// Defines three overloaded functions with signature `bool(fp-type)`. +#define _STL_DEF_PREDICATE_FAMILY1(name, builtin) \ + _STL_DEF_PREDICATE1(_CONSTEXPR_CMATH23, name, builtin##f, float) \ + _STL_DEF_PREDICATE1(_CONSTEXPR_CMATH23, name, builtin, double) \ + _STL_DEF_PREDICATE1(_CONSTEXPR_CMATH23, name, builtin##l, long double) + +// Defines three overloaded functions with signature `bool(fp-type, fp-type)`. +#define _STL_DEF_PREDICATE_FAMILY2(name, builtin) \ + _STL_DEF_PREDICATE2(_CONSTEXPR_CMATH23, name, builtin##f, float) \ + _STL_DEF_PREDICATE2(_CONSTEXPR_CMATH23, name, builtin, double) \ + _STL_DEF_PREDICATE2(_CONSTEXPR_CMATH23, name, builtin##l, long double) + +// Defines three non-overloaded functions with signature `int-type(fp-type)`. +// The names of the float and long double variants are suffixed with `f` and `l`, +// respectively. +#define _STL_DEF_ROUNDING_FAMILY1(specs, name, ret) \ + _STL_DEF_FUNC1(specs, name##f, ret, float) \ + _STL_DEF_FUNC1(specs, name, ret, double) \ + _STL_DEF_FUNC1(specs, name##l, ret, long double) + +// **Declares** two non-overloaded functions with signature `fp-type(fp-type)`. +// A third function, corresponding to the `long double` variant of the function, +// is **defined** to call the double variant. These declarations are intended to +// match functions defined within the UCRT because libc does not yet implement +// them fully. +#define _STL_DECLARE_FAMILY1(specs, name) \ + _STL_DECLARE_FUNC1(specs, name##f, float, float) \ + _STL_DECLARE_FUNC1(specs, name, double, double) \ + _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) + +// Some functions that are needed for C++26 constexpr cmath are not yet +// implemented by libc. We polyfill the library with the UCRT and mark these +// functions with this macro. The resulting declarations are not able to be +// used during constant-evaluation yet. +#define _CONSTEXPR_CMATH26_NYI inline + +// On x86, when not using /arch:SSE2 or greater, floating point operations +// are performed using the x87 instruction set and FLT_EVAL_METHOD is 2. +// (When /fp:fast is used, floating point operations may be consistent, so +// we use the default types.) +#if defined(_M_IX86) && _M_IX86_FP < 2 && !defined(_M_FP_FAST) +using float_t = long double; +using double_t = long double; +#else +using float_t = float; +using double_t = double; +#endif + +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 +// The UCRT defines this to be MATH_ERRNO | MATH_ERREXCEPT, but we are unsure +// of the quality of errno handling in libc. We broadcast MATH_ERREXCEPT as a +// minimum, leaving extension to include MATH_ERRNO as an option in the future. +#define math_errhandling (MATH_ERREXCEPT) + +// These macro definitions were copied verbatim from the UCRT. The intent was +// to mirror their definitions exactly to avoid macro redefinition warnings. +#define _DENORM (-2) +#define _FINITE (-1) +#define _INFCODE 1 +#define _NANCODE 2 + +#define FP_INFINITE _INFCODE +#define FP_NAN _NANCODE +#define FP_NORMAL _FINITE +#define FP_SUBNORMAL _DENORM +#define FP_ZERO 0 + +#define _C2 1 // 0 if not 2's complement +#define FP_ILOGB0 (-0x7fffffff - _C2) +#define FP_ILOGBNAN 0x7fffffff + +// These macro definitions were _not_ copied verbatim from the UCRT because we +// are now able to take advantage of the __builtin_inf family. +#define INFINITY (__builtin_inff()) +#define HUGE_VALF (__builtin_inff()) +#define HUGE_VAL (__builtin_inf()) +#define HUGE_VALL (__builtin_infl()) +#define NAN (__builtin_nanf("")) + +extern "C" { +// The nan family of functions is not routed to builtins because the builtins +// require a string literal argument and so cannot uphold the interface of +// these functions. +_NODISCARD float nanf(const char*); +_NODISCARD double nan(const char*); +_NODISCARD long double nanl(const char*); +} + +// Under /Oi (implied by /O2), MSVC treats the following functions as intrinsics that +// cannot be redefined. We use #pragma function to instruct MSVC to treat them as regular +// functions that can be defined, but we first need to declare the function before we can +// do so. +extern "C" { +_NODISCARD _CONSTEXPR_CMATH23 float ceilf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double ceil(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double fabs(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float floorf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double floor(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float fmaxf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double fmax(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double fmaxl(long double, long double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float fminf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double fmin(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double fminl(long double, long double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float fmodf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double fmod(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float acosf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double acos(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float asinf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double asin(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float atanf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double atan(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float copysignf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double copysign(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float cosf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double cos(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float expf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double exp(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float logf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double log(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float log10f(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double log10(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float log2f(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double log2(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float powf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double pow(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float sinf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double sin(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float sqrtf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double sqrt(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float tanf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double tan(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float fmaf(float, float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double fma(double, double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double fmal(long double, long double, long double) noexcept; +} + +#pragma function(acosf, acos) +#pragma function(asinf, asin) +#pragma function(atanf, atan) +#pragma function(ceilf, ceil) +#pragma function(copysignf, copysign) +#pragma function(cosf, cos) +#pragma function(expf, exp) +#pragma function(fabs) +#pragma function(floorf, floor) +#pragma function(fmaf, fma, fmal) +#pragma function(fmaxf, fmax, fmaxl) +#pragma function(fminf, fmin, fminl) +#pragma function(fmodf, fmod) +#pragma function(log10f, log10) +#pragma function(log2f, log2) +#pragma function(logf, log) +#pragma function(powf, pow) +#pragma function(sinf, sin) +#pragma function(sqrtf, sqrt) +#pragma function(tanf, tan) + +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, ceil) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, logb) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, fabs) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, round) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, trunc) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, floor) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmod) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, remainder) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, copysign) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, nextafter) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fdim) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmax) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmin) +_STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, lround, long int) +_STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, llround, long long) +_STL_DEF_PREDICATE_FAMILY1(signbit, __builtin_signbit) +_STL_DEF_PREDICATE_FAMILY2(isgreater, __builtin_isgreater) +_STL_DEF_PREDICATE_FAMILY2(isless, __builtin_isless) +_STL_DEF_PREDICATE_FAMILY2(islessequal, __builtin_islessequal) +_STL_DEF_PREDICATE_FAMILY2(islessgreater, __builtin_islessgreater) +_STL_DEF_PREDICATE_FAMILY2(isgreaterequal, __builtin_isgreaterequal) +_STL_DEF_PREDICATE_FAMILY2(isunordered, __builtin_isunordered) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, acos) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, acosh) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, asin) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, asinh) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, atan) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, atanh) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, cbrt) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, cos) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, cosh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erf) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erfc) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, exp) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26, exp2) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, expm1) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, hypot) +_STL_DEF_FAMILY1(inline, nearbyint) + +extern "C" { +// libc does not yet implement lgamma or tgamma. Polyfilling with the UCRT's +// implementation pulls in the UCRT's fma, which results in linker errors due +// to our conflicting definition. Instead, we prearranged for implementations +// of lgamma and tgamma to be ready in the satellite lib. +// +// _CRT_SATELLITE_2 is commented out because it is undefined at the point of +// this header's inclusion. We'd normally address that by including yvals.h, +// but that makes this header non-core. Otherwise, this header can be a core +// header. The macro definition is empty in usage, so the comment has the same +// physical effect (though maybe a different mental effect). +_NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_lgammaf(float) noexcept; +_NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_lgamma(double) noexcept; +_NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_tgammaf(float) noexcept; +_NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_tgamma(double) noexcept; +} + +extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI float lgammaf(float _Xx) noexcept /* strengthened */ { + return __std_smf_lgammaf(_Xx); +} + +extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI double lgamma(double _Xx) noexcept /* strengthened */ { + return __std_smf_lgamma(_Xx); +} + +extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI long double lgammal(long double _Xx) noexcept /* strengthened */ { + return __std_smf_lgamma(static_cast(_Xx)); +} + +extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI float tgammaf(float _Xx) noexcept /* strengthened */ { + return __std_smf_tgammaf(_Xx); +} + +extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI double tgamma(double _Xx) noexcept /* strengthened */ { + return __std_smf_tgamma(_Xx); +} + +extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI long double tgammal(long double _Xx) noexcept /* strengthened */ { + return __std_smf_tgamma(static_cast(_Xx)); +} + +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log10) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log1p) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log2) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, pow) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sin) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, sinh) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sqrt) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, tan) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, tanh); +_STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) + +// The UCRT defines the following functions on x86 as inline functions that +// forward to their double siblings, so forward-declaring them without defining +// them does not a successful polyfill make. +extern "C" { +#pragma function(coshf, cosh, coshl) +_NODISCARD _CONSTEXPR_CMATH26_NYI float coshf(float _Xx) { + return __builtin_coshf(_Xx); +} + +#pragma function(sinhf, sinh, sinhl) +extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI float sinhf(float _Xx) { + return __builtin_sinhf(_Xx); +} + +#pragma function(tanhf, tanh, tanhl) +extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI float tanhf(float _Xx) { + return __builtin_tanhf(_Xx); +} +} + +extern "C++" { +_NODISCARD _CONSTEXPR_CMATH23 int fpclassify(float _Xx) noexcept /* strengthened */ { + return __builtin_fpclassifyf(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); +} + +_NODISCARD _CONSTEXPR_CMATH23 int fpclassify(double _Xx) noexcept /* strengthened */ { + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); +} + +_NODISCARD _CONSTEXPR_CMATH23 int fpclassify(long double _Xx) noexcept /* strengthened */ { + return __builtin_fpclassifyl(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isfinite(float _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) <= 0; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isfinite(double _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) <= 0; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isfinite(long double _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) <= 0; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isinf(float _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_INFINITE; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isinf(double _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_INFINITE; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isinf(long double _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_INFINITE; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isnan(float _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_NAN; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isnan(double _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_NAN; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isnan(long double _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_NAN; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isnormal(float _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_NORMAL; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isnormal(double _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_NORMAL; +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isnormal(long double _Xx) noexcept /* strengthened */ { + return fpclassify(_Xx) == FP_NORMAL; +} + +_NODISCARD _CONSTEXPR_CMATH23 float nexttowardf(float _Xx0, long double _Xx1) noexcept /* strengthened */ { + return __builtin_nexttowardf(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 double nexttoward(double _Xx0, long double _Xx1) noexcept /* strengthened */ { + return __builtin_nexttoward(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 long double nexttowardl(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { + return __builtin_nexttowardl(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 float frexpf(float _Xx0, int* _Xx1) noexcept /* strengthened */ { + return __builtin_frexpf(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 double frexp(double _Xx0, int* _Xx1) noexcept /* strengthened */ { + return __builtin_frexp(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 long double frexpl(long double _Xx0, int* _Xx1) noexcept /* strengthened */ { + return __builtin_frexpl(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 int ilogbf(float _Xx) noexcept /* strengthened */ { + return __builtin_ilogbf(_Xx); +} + +_NODISCARD _CONSTEXPR_CMATH23 int ilogb(double _Xx) noexcept /* strengthened */ { + return __builtin_ilogb(_Xx); +} + +_NODISCARD _CONSTEXPR_CMATH23 int ilogbl(long double _Xx) noexcept /* strengthened */ { + return __builtin_ilogbl(_Xx); +} + +_NODISCARD _CONSTEXPR_CMATH23 float ldexpf(float _Xx0, int _Xx1) noexcept /* strengthened */ { + return __builtin_ldexpf(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 double ldexp(double _Xx0, int _Xx1) noexcept /* strengthened */ { + return __builtin_ldexp(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 long double ldexpl(long double _Xx0, int _Xx1) noexcept /* strengthened */ { + return __builtin_ldexpl(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 float modff(float _Xx0, float* _Xx1) noexcept /* strengthened */ { + return __builtin_modff(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 double modf(double _Xx0, double* _Xx1) noexcept /* strengthened */ { + return __builtin_modf(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 long double modfl(long double _Xx0, long double* _Xx1) noexcept /* strengthened */ { + return __builtin_modfl(_Xx0, _Xx1); +} + +_NODISCARD inline long lrintf(float _Xx0) noexcept /* strengthened */ { + return __builtin_lrintf(_Xx0); +} + +_NODISCARD inline long lrint(double _Xx0) noexcept /* strengthened */ { + return __builtin_lrint(_Xx0); +} + +_NODISCARD inline long lrintl(long double _Xx0) noexcept /* strengthened */ { + return __builtin_lrintl(_Xx0); +} + +_NODISCARD inline long long llrintf(float _Xx0) noexcept /* strengthened */ { + return __builtin_llrintf(_Xx0); +} + +_NODISCARD inline long long llrint(double _Xx0) noexcept /* strengthened */ { + return __builtin_llrint(_Xx0); +} + +_NODISCARD inline long long llrintl(long double _Xx0) noexcept /* strengthened */ { + return __builtin_llrintl(_Xx0); +} + +_NODISCARD inline float rintf(float _Xx0) noexcept /* strengthened */ { + return __builtin_rintf(_Xx0); +} + +_NODISCARD inline double rint(double _Xx0) noexcept /* strengthened */ { + return __builtin_rint(_Xx0); +} + +_NODISCARD inline long double rintl(long double _Xx0) noexcept /* strengthened */ { + return __builtin_rintl(_Xx0); +} + +_NODISCARD _CONSTEXPR_CMATH23 float scalbnf(float _Xx0, int _Xx1) noexcept /* strengthened */ { + return __builtin_scalbnf(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 double scalbn(double _Xx0, int _Xx1) noexcept /* strengthened */ { + return __builtin_scalbn(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 long double scalbnl(long double _Xx0, int _Xx1) noexcept /* strengthened */ { + return __builtin_scalbnl(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 float scalblnf(float _Xx0, long _Xx1) noexcept /* strengthened */ { + return __builtin_scalblnf(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 double scalbln(double _Xx0, long _Xx1) noexcept /* strengthened */ { + return __builtin_scalbln(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 long double scalblnl(long double _Xx0, long _Xx1) noexcept /* strengthened */ { + return __builtin_scalblnl(_Xx0, _Xx1); +} + +_NODISCARD _CONSTEXPR_CMATH23 float remquof(float _Xx0, float _Xx1, int* _Xx2) noexcept /* strengthened */ { + return __builtin_remquof(_Xx0, _Xx1, _Xx2); +} + +_NODISCARD _CONSTEXPR_CMATH23 double remquo(double _Xx0, double _Xx1, int* _Xx2) noexcept /* strengthened */ { + return __builtin_remquo(_Xx0, _Xx1, _Xx2); +} + +_NODISCARD _CONSTEXPR_CMATH23 long double remquol(long double _Xx0, long double _Xx1, int* _Xx2) noexcept +/* strengthened */ { + return __builtin_remquol(_Xx0, _Xx1, _Xx2); +} + +// TRANSITION: Preserve the sign of zero when atan2 underflows. +// __builtin_atan2 can return +0 for tiny negative results. +_NODISCARD _CONSTEXPR_CMATH26 float atan2f(float _Xx0, float _Xx1) noexcept /* strengthened */ { + float _Result = static_cast(__builtin_atan2f(_Xx0, _Xx1)); + if (_Result == 0.0F && _Xx0 != 0.0F) { + return __builtin_copysignf(0.0F, _Xx0); + } + return _Result; +} + +_NODISCARD _CONSTEXPR_CMATH26 double atan2(double _Xx0, double _Xx1) noexcept /* strengthened */ { + double _Result = static_cast(__builtin_atan2(_Xx0, _Xx1)); + if (_Result == 0.0 && _Xx0 != 0.0) { + return __builtin_copysign(0.0, _Xx0); + } + return _Result; +} + +_NODISCARD _CONSTEXPR_CMATH26 long double atan2l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { + long double _Result = static_cast(__builtin_atan2l(_Xx0, _Xx1)); + if (_Result == 0.0L && _Xx0 != 0.0L) { + return __builtin_copysignl(0.0L, _Xx0); + } + return _Result; +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return isgreater(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return isgreaterequal(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool isless(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return isless(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return islessequal(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return islessgreater(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return isunordered(static_cast(_X0), static_cast(_X1)); +} +} // extern "C++" + +extern "C" { +_NODISCARD double _j0(double); +_NODISCARD double _j1(double); +_NODISCARD double _jn(int, double); +_NODISCARD double _y0(double); +_NODISCARD double _y1(double); +_NODISCARD double _yn(int, double); +} + +#if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES + +// These functions are included in the Open Group Standard Base Specifications. +extern "C" { +_NODISCARD double j0(double); +_NODISCARD double j1(double); +_NODISCARD double jn(int, double); +_NODISCARD double y0(double); +_NODISCARD double y1(double); +_NODISCARD double yn(int, double); +} + +#endif // defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES + +#undef _STL_DEF_FUNC1 +#undef _STL_DEF_FUNC2 +#undef _STL_DEF_FUNC3 +#undef _STL_DEF_LDOUBLE_FORWARD_FUNC1 +#undef _STL_DEF_LDOUBLE_FORWARD_FUNC2 +#undef _STL_DEF_LDOUBLE_FORWARD_FUNC3 +#undef _STL_DECLARE_FUNC1 +#undef _STL_DECLARE_FUNC2 +#undef _STL_DEF_FAMILY1 +#undef _STL_DEF_FAMILY2 +#undef _STL_DEF_FAMILY3 +#undef _STL_DEF_PREDICATE_FAMILY1 +#undef _STL_DEF_PREDICATE_FAMILY2 +#undef _STL_DEF_ROUNDING_FAMILY1 +#undef _STL_DECLARE_FAMILY1 +#undef _CONSTEXPR_CMATH26_NYI + +_STL_RESTORE_CLANG_WARNINGS +#pragma pop_macro("new") +#pragma warning(pop) +#pragma pack(pop) +#endif // _STL_COMPILER_PREPROCESSOR + +#endif // __MSVC_MATH_HPP diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp new file mode 100644 index 00000000000..8e86d79d2e6 --- /dev/null +++ b/stl/inc/__msvc_stdlib.hpp @@ -0,0 +1,836 @@ +// __msvc_stdlib.hpp internal header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef _MSVC_STDLIB_HPP +#define _MSVC_STDLIB_HPP + +// Prevent later inclusions of stdlib.h from having any effect. +#define _INC_STDLIB + +#include +#include +#include +#include +#include + +#pragma warning(push) +#pragma warning(disable : _UCRT_DISABLED_WARNINGS) +_UCRT_DISABLE_CLANG_WARNINGS + +_CRT_BEGIN_C_HEADER + + +#ifndef _countof +#define _countof __crt_countof +#endif + +// Minimum and maximum macros +#define __max(a, b) (((a) > (b)) ? (a) : (b)) +#define __min(a, b) (((a) < (b)) ? (a) : (b)) + +_ACRTIMP void __cdecl _swab(_Inout_updates_(_SizeInBytes) _Post_readable_size_(_SizeInBytes) char* _Buf1, + _Inout_updates_(_SizeInBytes) _Post_readable_size_(_SizeInBytes) char* _Buf2, _In_ int _SizeInBytes); + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + +#if _CRT_FUNCTIONS_REQUIRED +_ACRTIMP __declspec(noreturn) void __cdecl exit(_In_ int _Code); +_ACRTIMP __declspec(noreturn) void __cdecl _exit(_In_ int _Code); +_ACRTIMP __declspec(noreturn) void __cdecl _Exit(_In_ int _Code); +_ACRTIMP __declspec(noreturn) void __cdecl quick_exit(_In_ int _Code); +_ACRTIMP __declspec(noreturn) void __cdecl abort(void); +#endif // _CRT_FUNCTIONS_REQUIRED + +// Argument values for _set_abort_behavior(). +#define _WRITE_ABORT_MSG 0x1 // debug only, has no effect in release +#define _CALL_REPORTFAULT 0x2 + +_ACRTIMP unsigned int __cdecl _set_abort_behavior(_In_ unsigned int _Flags, _In_ unsigned int _Mask); + + +#ifndef _CRT_ONEXIT_T_DEFINED +#define _CRT_ONEXIT_T_DEFINED + +typedef int(__CRTDECL* _onexit_t)(void); +#ifdef _M_CEE +typedef int(__clrcall* _onexit_m_t)(void); +#endif +#endif + +#if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES +// Non-ANSI name for compatibility +#define onexit_t _onexit_t +#endif + + +#ifdef _M_CEE +#pragma warning(push) +#pragma warning(disable : 4985) // Attributes not present on previous declaration + +_Check_return_ int __clrcall _atexit_m_appdomain(_In_opt_ void(__clrcall* _Function)(void)); + +_onexit_m_t __clrcall _onexit_m_appdomain(_onexit_m_t _Function); + +#ifdef _M_CEE_MIXED +#ifdef __cplusplus +[System::Security::SecurityCritical] +#endif + _Check_return_ int __clrcall + _atexit_m(_In_opt_ void(__clrcall* _Function)(void)); + +_onexit_m_t __clrcall _onexit_m(_onexit_m_t _Function); +#else +#ifdef __cplusplus +[System::Security::SecurityCritical] +#endif + _Check_return_ inline int __clrcall + _atexit_m(_In_opt_ void(__clrcall* _Function)(void)) { + return _atexit_m_appdomain(_Function); +} + +inline _onexit_m_t __clrcall _onexit_m(_onexit_t _Function) { + return _onexit_m_appdomain(_Function); +} +#endif +#pragma warning(pop) +#endif + + +#ifdef _M_CEE_PURE +// In pure mode, atexit is the same as atexit_m_appdomain +extern "C++" { + +#ifdef __cplusplus +[System::Security::SecurityCritical] +#endif + inline int __clrcall + atexit(void(__clrcall* _Function)(void)) { + return _atexit_m_appdomain(_Function); +} + +inline _onexit_t __clrcall _onexit(_onexit_t _Function) { + return _onexit_m_appdomain(_Function); +} + +} // extern "C++" +#else +int __cdecl atexit(void(__cdecl*)(void)); +_onexit_t __cdecl _onexit(_In_opt_ _onexit_t _Func); +#endif + +int __cdecl at_quick_exit(void(__cdecl*)(void)); + +#ifndef _M_CEE_PURE +// a purecall handler procedure. Never returns normally +typedef void(__cdecl* _purecall_handler)(void); + +// Invalid parameter handler function pointer type +typedef void(__cdecl* _invalid_parameter_handler)( + wchar_t const*, wchar_t const*, wchar_t const*, unsigned int, uintptr_t); + +// Establishes a purecall handler +_VCRTIMP _purecall_handler __cdecl _set_purecall_handler(_In_opt_ _purecall_handler _Handler); + +_VCRTIMP _purecall_handler __cdecl _get_purecall_handler(void); + +// Establishes an invalid parameter handler +_ACRTIMP _invalid_parameter_handler __cdecl _set_invalid_parameter_handler( + _In_opt_ _invalid_parameter_handler _Handler); + +_ACRTIMP _invalid_parameter_handler __cdecl _get_invalid_parameter_handler(void); + +_ACRTIMP _invalid_parameter_handler __cdecl _set_thread_local_invalid_parameter_handler( + _In_opt_ _invalid_parameter_handler _Handler); + +_ACRTIMP _invalid_parameter_handler __cdecl _get_thread_local_invalid_parameter_handler(void); +#endif + + +#if defined __cplusplus && defined _M_CEE_PURE +extern "C++" { +typedef void(__clrcall* _purecall_handler)(void); +typedef _purecall_handler _purecall_handler_m; + +_MRTIMP _purecall_handler __cdecl _set_purecall_handler(_In_opt_ _purecall_handler _Handler); +} // extern "C++" +#endif + + +#define _OUT_TO_DEFAULT 0 +#define _OUT_TO_STDERR 1 +#define _OUT_TO_MSGBOX 2 +#define _REPORT_ERRMODE 3 + +_Check_return_opt_ _ACRTIMP int __cdecl _set_error_mode(_In_ int _Mode); + + +#if _CRT_FUNCTIONS_REQUIRED +_ACRTIMP int* __cdecl _errno(void); +#define errno (*_errno()) + +_ACRTIMP errno_t __cdecl _set_errno(_In_ int _Value); +_ACRTIMP errno_t __cdecl _get_errno(_Out_ int* _Value); + +_ACRTIMP unsigned long* __cdecl __doserrno(void); +#define _doserrno (*__doserrno()) + +_ACRTIMP errno_t __cdecl _set_doserrno(_In_ unsigned long _Value); +_ACRTIMP errno_t __cdecl _get_doserrno(_Out_ unsigned long* _Value); + +// This is non-const for backwards compatibility; do not modify it. +_ACRTIMP _CRT_INSECURE_DEPRECATE(strerror) +char** __cdecl __sys_errlist(void); +#define _sys_errlist (__sys_errlist()) + +_ACRTIMP _CRT_INSECURE_DEPRECATE(strerror) +int* __cdecl __sys_nerr(void); +#define _sys_nerr (*__sys_nerr()) + +_ACRTIMP void __cdecl perror(_In_opt_z_ char const* _ErrMsg); +#endif // _CRT_FUNCTIONS_REQUIRED + + +// These point to the executable module name. +_CRT_INSECURE_DEPRECATE_GLOBALS(_get_pgmptr) _ACRTIMP char** __cdecl __p__pgmptr(void); +_CRT_INSECURE_DEPRECATE_GLOBALS(_get_wpgmptr) _ACRTIMP wchar_t** __cdecl __p__wpgmptr(void); +_CRT_INSECURE_DEPRECATE_GLOBALS(_get_fmode) _ACRTIMP int* __cdecl __p__fmode(void); + +#ifdef _CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY +_CRT_INSECURE_DEPRECATE_GLOBALS(_get_pgmptr) extern char* _pgmptr; +_CRT_INSECURE_DEPRECATE_GLOBALS(_get_wpgmptr) extern wchar_t* _wpgmptr; +#ifndef _CORECRT_BUILD +_CRT_INSECURE_DEPRECATE_GLOBALS(_get_fmode) extern int _fmode; +#endif +#else +#define _pgmptr (*__p__pgmptr()) +#define _wpgmptr (*__p__wpgmptr()) +#define _fmode (*__p__fmode()) +#endif + +_Success_(return == 0) _ACRTIMP errno_t __cdecl _get_pgmptr(_Outptr_result_z_ char** _Value); + +_Success_(return == 0) _ACRTIMP errno_t __cdecl _get_wpgmptr(_Outptr_result_z_ wchar_t** _Value); + +_ACRTIMP errno_t __cdecl _set_fmode(_In_ int _Mode); + +_ACRTIMP errno_t __cdecl _get_fmode(_Out_ int* _PMode); + +typedef struct _div_t { + int quot; + int rem; +} div_t; + +typedef struct _ldiv_t { + long quot; + long rem; +} ldiv_t; + +typedef struct _lldiv_t { + long long quot; + long long rem; +} lldiv_t; + +extern "C" { + _Check_return_ constexpr int __cdecl abs(_In_ int) noexcept; + _Check_return_ constexpr long __cdecl labs(_In_ long) noexcept; + _Check_return_ constexpr long long __cdecl llabs(_In_ long long) noexcept; + _Check_return_ constexpr div_t __cdecl div(_In_ int, _In_ int) noexcept; + _Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long, _In_ long) noexcept; + _Check_return_ constexpr lldiv_t __cdecl lldiv(_In_ long long, _In_ long long) noexcept; +} + +#pragma warning(push) +#pragma warning(disable : 4163) // 'meow' not available as an intrinsic function +#pragma function(abs, labs, llabs) +#pragma function(div, ldiv, lldiv) +#pragma warning(pop) + +[[nodiscard]] _Check_return_ constexpr int __cdecl abs(_In_ int _Xx) noexcept /* strengthened */ { + return _Xx >= 0 ? _Xx : -_Xx; +} + +[[nodiscard]] _Check_return_ constexpr long __cdecl labs(_In_ long _Xx) noexcept /* strengthened */ { + return _Xx >= 0 ? _Xx : -_Xx; +} + +[[nodiscard]] _Check_return_ constexpr long long __cdecl llabs(_In_ long long _Xx) noexcept /* strengthened */ { + return _Xx >= 0 ? _Xx : -_Xx; +} + +[[nodiscard]] _Check_return_ constexpr div_t __cdecl div(_In_ int _Numerator, _In_ int _Denominator) noexcept /* strengthened */ { + return {_Numerator / _Denominator, _Numerator % _Denominator}; +} + +[[nodiscard]] _Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long _Numerator, _In_ long _Denominator) noexcept /* strengthened */ { + return {_Numerator / _Denominator, _Numerator % _Denominator}; +} + +[[nodiscard]] _Check_return_ constexpr lldiv_t __cdecl lldiv(_In_ long long _Numerator, _In_ long long _Denominator) noexcept +/* strengthened */ { + return {_Numerator / _Denominator, _Numerator % _Denominator}; +} + +_Check_return_ __int64 __cdecl _abs64(_In_ __int64 _Number); + +_Check_return_ unsigned short __cdecl _byteswap_ushort(_In_ unsigned short _Number); +_Check_return_ unsigned long __cdecl _byteswap_ulong(_In_ unsigned long _Number); +_Check_return_ unsigned __int64 __cdecl _byteswap_uint64(_In_ unsigned __int64 _Number); + +// These functions have declspecs in their declarations in the Windows headers, +// which cause PREfast to fire 6540. +#pragma warning(push) +#pragma warning(disable : 6540) + +unsigned int __cdecl _rotl(_In_ unsigned int _Value, _In_ int _Shift); + +_Check_return_ unsigned long __cdecl _lrotl(_In_ unsigned long _Value, _In_ int _Shift); + +unsigned __int64 __cdecl _rotl64(_In_ unsigned __int64 _Value, _In_ int _Shift); + +unsigned int __cdecl _rotr(_In_ unsigned int _Value, _In_ int _Shift); + +_Check_return_ unsigned long __cdecl _lrotr(_In_ unsigned long _Value, _In_ int _Shift); + +unsigned __int64 __cdecl _rotr64(_In_ unsigned __int64 _Value, _In_ int _Shift); + +#pragma warning(pop) + + +// Maximum value that can be returned by the rand function: +#define RAND_MAX 0x7fff + +_ACRTIMP void __cdecl srand(_In_ unsigned int _Seed); + +_Check_return_ _ACRTIMP int __cdecl rand(void); + +#if defined _CRT_RAND_S || defined _CRTBLD +_ACRTIMP errno_t __cdecl rand_s(_Out_ unsigned int* _RandomValue); +#endif + +extern "C++" { +[[nodiscard]] constexpr long abs(long const _X) noexcept /* strengthened */ { + return labs(_X); +} + +[[nodiscard]] constexpr long long abs(long long const _X) noexcept /* strengthened */ { + return llabs(_X); +} + +[[nodiscard]] constexpr ldiv_t div(long const _A1, long const _A2) noexcept /* strengthened */ { + return ldiv(_A1, _A2); +} + +[[nodiscard]] constexpr lldiv_t div(long long const _A1, long long const _A2) noexcept /* strengthened */ { + return lldiv(_A1, _A2); +} +} + +// Structs used to fool the compiler into not generating floating point +// instructions when copying and pushing [long] double values +#define _CRT_DOUBLE_DEC + +#ifndef _LDSUPPORT + +#pragma pack(push, 4) +typedef struct { + unsigned char ld[10]; +} _LDOUBLE; +#pragma pack(pop) + +#define _PTR_LD(x) ((unsigned char*) (&(x)->ld)) + +#else // _LDSUPPORT + +// push and pop long, which is #defined as __int64 by a spec2k test +#pragma push_macro("long") +#undef long +typedef long double _LDOUBLE; +#pragma pop_macro("long") + +#define _PTR_LD(x) ((unsigned char*) (x)) + +#endif // _LDSUPPORT + +typedef struct { + double x; +} _CRT_DOUBLE; + +typedef struct { + float f; +} _CRT_FLOAT; + +// push and pop long, which is #defined as __int64 by a spec2k test +#pragma push_macro("long") +#undef long + +typedef struct { + long double x; +} _LONGDOUBLE; + +#pragma pop_macro("long") + +#pragma pack(push, 4) +typedef struct { + unsigned char ld12[12]; +} _LDBL12; +#pragma pack(pop) + +_Check_return_ _ACRTIMP double __cdecl atof(_In_z_ char const* _String); +_Check_return_ _CRT_JIT_INTRINSIC _ACRTIMP int __cdecl atoi(_In_z_ char const* _String); +_Check_return_ _ACRTIMP long __cdecl atol(_In_z_ char const* _String); +_Check_return_ _ACRTIMP long long __cdecl atoll(_In_z_ char const* _String); +_Check_return_ _ACRTIMP __int64 __cdecl _atoi64(_In_z_ char const* _String); + +_Check_return_ _ACRTIMP double __cdecl _atof_l(_In_z_ char const* _String, _In_opt_ _locale_t _Locale); +_Check_return_ _ACRTIMP int __cdecl _atoi_l(_In_z_ char const* _String, _In_opt_ _locale_t _Locale); +_Check_return_ _ACRTIMP long __cdecl _atol_l(_In_z_ char const* _String, _In_opt_ _locale_t _Locale); +_Check_return_ _ACRTIMP long long __cdecl _atoll_l(_In_z_ char const* _String, _In_opt_ _locale_t _Locale); +_Check_return_ _ACRTIMP __int64 __cdecl _atoi64_l(_In_z_ char const* _String, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP int __cdecl _atoflt(_Out_ _CRT_FLOAT* _Result, _In_z_ char const* _String); +_Check_return_ _ACRTIMP int __cdecl _atodbl(_Out_ _CRT_DOUBLE* _Result, _In_z_ char* _String); +_Check_return_ _ACRTIMP int __cdecl _atoldbl(_Out_ _LDOUBLE* _Result, _In_z_ char* _String); + +_Check_return_ _ACRTIMP int __cdecl _atoflt_l( + _Out_ _CRT_FLOAT* _Result, _In_z_ char const* _String, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP int __cdecl _atodbl_l( + _Out_ _CRT_DOUBLE* _Result, _In_z_ char* _String, _In_opt_ _locale_t _Locale); + + +_Check_return_ _ACRTIMP int __cdecl _atoldbl_l( + _Out_ _LDOUBLE* _Result, _In_z_ char* _String, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP float __cdecl strtof(_In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr); + +_Check_return_ _ACRTIMP float __cdecl _strtof_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP double __cdecl strtod(_In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr); + +_Check_return_ _ACRTIMP double __cdecl _strtod_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP long double __cdecl strtold( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr); + +_Check_return_ _ACRTIMP long double __cdecl _strtold_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP long __cdecl strtol( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix); + +_Check_return_ _ACRTIMP long __cdecl _strtol_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP long long __cdecl strtoll( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix); + +_Check_return_ _ACRTIMP long long __cdecl _strtoll_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP unsigned long __cdecl strtoul( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix); + +_Check_return_ _ACRTIMP unsigned long __cdecl _strtoul_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP unsigned long long __cdecl strtoull( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix); + +_Check_return_ _ACRTIMP unsigned long long __cdecl _strtoull_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP __int64 __cdecl _strtoi64( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix); + +_Check_return_ _ACRTIMP __int64 __cdecl _strtoi64_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix, _In_opt_ _locale_t _Locale); + +_Check_return_ _ACRTIMP unsigned __int64 __cdecl _strtoui64( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix); + +_Check_return_ _ACRTIMP unsigned __int64 __cdecl _strtoui64_l( + _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix, _In_opt_ _locale_t _Locale); + +_Success_(return == 0) _Check_return_opt_ _ACRTIMP errno_t __cdecl _itoa_s( + _In_ int _Value, _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ int _Radix); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_1_1( + _Success_(return == 0) errno_t, _itoa_s, _In_ int, _Value, char, _Buffer, _In_ int, _Radix) + +__DEFINE_CPP_OVERLOAD_STANDARD_FUNC_1_1(char*, __RETURN_POLICY_DST, _ACRTIMP, _itoa, _In_ int, _Value, + _Pre_notnull_ _Post_z_, char, _Buffer, _In_ int, _Radix) + +_Success_(return == 0) _Check_return_opt_ _ACRTIMP errno_t __cdecl _ltoa_s( + _In_ long _Value, _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ int _Radix); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_1_1(errno_t, _ltoa_s, _In_ long, _Value, char, _Buffer, _In_ int, _Radix) + +__DEFINE_CPP_OVERLOAD_STANDARD_FUNC_1_1(char*, __RETURN_POLICY_DST, _ACRTIMP, _ltoa, _In_ long, _Value, + _Pre_notnull_ _Post_z_, char, _Buffer, _In_ int, _Radix) + +_Success_(return == 0) _Check_return_opt_ _ACRTIMP errno_t __cdecl _ultoa_s( + _In_ unsigned long _Value, _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ int _Radix); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_1_1(errno_t, _ultoa_s, _In_ unsigned long, _Value, char, _Buffer, _In_ int, _Radix) + +__DEFINE_CPP_OVERLOAD_STANDARD_FUNC_1_1(char*, __RETURN_POLICY_DST, _ACRTIMP, _ultoa, _In_ unsigned long, _Value, + _Pre_notnull_ _Post_z_, char, _Buffer, _In_ int, _Radix) + +_Success_(return == 0) _Check_return_opt_ _ACRTIMP errno_t __cdecl _i64toa_s( + _In_ __int64 _Value, _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ int _Radix); + +_Success_(return == 0) _CRT_INSECURE_DEPRECATE(_i64toa_s) _ACRTIMP + char* __cdecl _i64toa(_In_ __int64 _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); + +_Success_(return == 0) _Check_return_opt_ _ACRTIMP errno_t __cdecl _ui64toa_s(_In_ unsigned __int64 _Value, + _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ int _Radix); + +_CRT_INSECURE_DEPRECATE(_ui64toa_s) +_ACRTIMP char* __cdecl _ui64toa(_In_ unsigned __int64 _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); + + +// _CVTBUFSIZE is the maximum size for the per-thread conversion buffer. It +// should be at least as long as the number of digits in the largest double +// precision value (?.?e308 in IEEE arithmetic). We will use the same size +// buffer as is used in the printf support routines. +// +// (This value actually allows 40 additional decimal places; even though there +// are only 16 digits of accuracy in a double precision IEEE number, the user may +// ask for more to effect zero padding.) +#define _CVTBUFSIZE (309 + 40) // # of digits in max. dp value + slop + +_Success_(return == 0) _Check_return_wat_ _ACRTIMP errno_t __cdecl _ecvt_s(_Out_writes_z_(_BufferCount) char* _Buffer, + _In_ size_t _BufferCount, _In_ double _Value, _In_ int _DigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_4(errno_t, _ecvt_s, char, _Buffer, _In_ double, _Value, _In_ int, _DigitCount, + _Out_ int*, _PtDec, _Out_ int*, _PtSign) + +_Check_return_ _CRT_INSECURE_DEPRECATE(_ecvt_s) +_ACRTIMP char* __cdecl _ecvt(_In_ double _Value, _In_ int _DigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); + +_Success_(return == 0) _Check_return_wat_ _ACRTIMP errno_t + __cdecl _fcvt_s(_Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ double _Value, + _In_ int _FractionalDigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_4(_Success_(return == 0) errno_t, _fcvt_s, char, _Buffer, _In_ double, _Value, + _In_ int, _FractionalDigitCount, _Out_ int*, _PtDec, _Out_ int*, _PtSign) + +_Success_(return == 0) _Check_return_ _CRT_INSECURE_DEPRECATE(_fcvt_s) +_ACRTIMP char* __cdecl _fcvt(_In_ double _Value, _In_ int _FractionalDigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); + +_Success_(return == 0) _ACRTIMP errno_t __cdecl _gcvt_s( + _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ double _Value, _In_ int _DigitCount); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_2( + _Success_(return == 0) errno_t, _gcvt_s, char, _Buffer, _In_ double, _Value, _In_ int, _DigitCount) + +_CRT_INSECURE_DEPRECATE(_gcvt_s) +_ACRTIMP char* __cdecl _gcvt(_In_ double _Value, _In_ int _DigitCount, _Pre_notnull_ _Post_z_ char* _Buffer); + +// Maximum number of bytes in multi-byte character in the current locale +// (also defined in ctype.h). +#ifndef MB_CUR_MAX +#if defined _CRT_DISABLE_PERFCRIT_LOCKS && !defined _DLL +#define MB_CUR_MAX __mb_cur_max +#else +#define MB_CUR_MAX ___mb_cur_max_func() +#endif + +#ifdef _CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY +extern int __mb_cur_max; +#else +#define __mb_cur_max (___mb_cur_max_func()) +#endif + +_Post_satisfies_(return > 0 && return < MB_LEN_MAX) _ACRTIMP int __cdecl ___mb_cur_max_func(void); + +_Post_satisfies_(return > 0 && return < MB_LEN_MAX) _ACRTIMP int __cdecl ___mb_cur_max_l_func(_locale_t _Locale); +#endif + + +_Check_return_ _ACRTIMP int __cdecl mblen( + _In_reads_bytes_opt_(_MaxCount) _Pre_opt_z_ char const* _Ch, _In_ size_t _MaxCount); + +_Check_return_ _ACRTIMP int __cdecl _mblen_l( + _In_reads_bytes_opt_(_MaxCount) _Pre_opt_z_ char const* _Ch, _In_ size_t _MaxCount, _In_opt_ _locale_t _Locale); + +_Check_return_ _Post_satisfies_(return <= _String_length_(_String)) _ACRTIMP size_t + __cdecl _mbstrlen(_In_z_ char const* _String); + +_Check_return_ _Post_satisfies_(return <= _String_length_(_String) || return == (size_t) -1) _ACRTIMP size_t + __cdecl _mbstrlen_l(_In_z_ char const* _String, _In_opt_ _locale_t _Locale); + +_Check_return_ _Post_satisfies_( + (return <= _String_length_(_String) && return <= _MaxCount) || return == (size_t) -1) _ACRTIMP size_t + __cdecl _mbstrnlen(_In_z_ char const* _String, _In_ size_t _MaxCount); + +_Post_satisfies_( + (return <= _String_length_(_String) && return <= _MaxCount) || return == (size_t) -1) _Check_return_ _ACRTIMP size_t + __cdecl _mbstrnlen_l(_In_z_ char const* _String, _In_ size_t _MaxCount, _In_opt_ _locale_t _Locale); + +_Success_(return != -1) _ACRTIMP int __cdecl mbtowc(_Pre_notnull_ _Post_z_ wchar_t* _DstCh, + _In_reads_or_z_opt_(_SrcSizeInBytes) char const* _SrcCh, _In_ size_t _SrcSizeInBytes); + +_Success_(return != -1) _ACRTIMP int __cdecl _mbtowc_l(_Pre_notnull_ _Post_z_ wchar_t* _DstCh, + _In_reads_or_z_opt_(_SrcSizeInBytes) char const* _SrcCh, _In_ size_t _SrcSizeInBytes, _In_opt_ _locale_t _Locale); + +_Check_return_opt_ _ACRTIMP errno_t __cdecl mbstowcs_s(_Out_opt_ size_t* _PtNumOfCharConverted, + _Out_writes_to_opt_(_SizeInWords, *_PtNumOfCharConverted) wchar_t* _DstBuf, _In_ size_t _SizeInWords, + _In_reads_or_z_(_MaxCount) char const* _SrcBuf, _In_ size_t _MaxCount); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_1_2(errno_t, mbstowcs_s, _Out_opt_ size_t*, _PtNumOfCharConverted, _Post_z_ wchar_t, + _Dest, _In_z_ char const*, _Source, _In_ size_t, _MaxCount) + +__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE(_ACRTIMP, mbstowcs, _Out_writes_opt_z_(_MaxCount), wchar_t, _Dest, + _In_z_ char const*, _Source, _In_ size_t, _MaxCount) + +_Check_return_opt_ _ACRTIMP errno_t __cdecl _mbstowcs_s_l(_Out_opt_ size_t* _PtNumOfCharConverted, + _Out_writes_to_opt_(_SizeInWords, *_PtNumOfCharConverted) wchar_t* _DstBuf, _In_ size_t _SizeInWords, + _In_reads_or_z_(_MaxCount) char const* _SrcBuf, _In_ size_t _MaxCount, _In_opt_ _locale_t _Locale); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_1_3(errno_t, _mbstowcs_s_l, _Out_opt_ size_t*, _PtNumOfCharConverted, + _Post_z_ wchar_t, _Dest, _In_z_ char const*, _Source, _In_ size_t, _MaxCount, _In_opt_ _locale_t, _Locale) + +__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_3_SIZE_EX(_ACRTIMP, _mbstowcs_l, _mbstowcs_s_l, + _Out_writes_opt_z_(_Size) wchar_t, _Out_writes_z_(_MaxCount), wchar_t, _Dest, _In_z_ char const*, _Source, + _In_ size_t, _MaxCount, _In_opt_ _locale_t, _Locale) + + +_CRT_INSECURE_DEPRECATE(wctomb_s) +_ACRTIMP int __cdecl wctomb(_Out_writes_opt_z_(MB_LEN_MAX) char* _MbCh, _In_ wchar_t _WCh); + +_CRT_INSECURE_DEPRECATE(_wctomb_s_l) +_ACRTIMP int __cdecl _wctomb_l(_Pre_maybenull_ _Post_z_ char* _MbCh, _In_ wchar_t _WCh, _In_opt_ _locale_t _Locale); + +#if __STDC_WANT_SECURE_LIB__ + +_Check_return_wat_ _ACRTIMP errno_t __cdecl wctomb_s(_Out_opt_ int* _SizeConverted, + _Out_writes_bytes_to_opt_(_SizeInBytes, *_SizeConverted) char* _MbCh, _In_ rsize_t _SizeInBytes, _In_ wchar_t _WCh); + +#endif // __STDC_WANT_SECURE_LIB__ + +_Check_return_wat_ _ACRTIMP errno_t __cdecl _wctomb_s_l(_Out_opt_ int* _SizeConverted, + _Out_writes_opt_z_(_SizeInBytes) char* _MbCh, _In_ size_t _SizeInBytes, _In_ wchar_t _WCh, + _In_opt_ _locale_t _Locale); + +_Check_return_wat_ _ACRTIMP errno_t __cdecl wcstombs_s(_Out_opt_ size_t* _PtNumOfCharConverted, + _Out_writes_bytes_to_opt_(_DstSizeInBytes, *_PtNumOfCharConverted) char* _Dst, _In_ size_t _DstSizeInBytes, + _In_z_ wchar_t const* _Src, _In_ size_t _MaxCountInBytes); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_1_2(errno_t, wcstombs_s, _Out_opt_ size_t*, _PtNumOfCharConverted, + _Out_writes_bytes_opt_(_Size) char, _Dest, _In_z_ wchar_t const*, _Source, _In_ size_t, _MaxCount) + +__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE(_ACRTIMP, wcstombs, _Out_writes_opt_(_MaxCount), char, _Dest, + _In_z_ wchar_t const*, _Source, _In_ size_t, _MaxCount) + +_Check_return_wat_ _ACRTIMP errno_t __cdecl _wcstombs_s_l(_Out_opt_ size_t* _PtNumOfCharConverted, + _Out_writes_bytes_to_opt_(_DstSizeInBytes, *_PtNumOfCharConverted) char* _Dst, _In_ size_t _DstSizeInBytes, + _In_z_ wchar_t const* _Src, _In_ size_t _MaxCountInBytes, _In_opt_ _locale_t _Locale); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_1_3(errno_t, _wcstombs_s_l, _Out_opt_ size_t*, _PtNumOfCharConverted, + _Out_writes_opt_(_Size) char, _Dest, _In_z_ wchar_t const*, _Source, _In_ size_t, _MaxCount, _In_opt_ _locale_t, + _Locale) + +__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_3_SIZE_EX(_ACRTIMP, _wcstombs_l, _wcstombs_s_l, _Out_writes_opt_z_(_Size) char, + _Out_writes_(_MaxCount), char, _Dest, _In_z_ wchar_t const*, _Source, _In_ size_t, _MaxCount, _In_opt_ _locale_t, + _Locale) + +// Sizes for buffers used by the _makepath() and _splitpath() functions. +// note that the sizes include space for 0-terminator +#define _MAX_PATH 260 // max. length of full pathname +#define _MAX_DRIVE 3 // max. length of drive component +#define _MAX_DIR 256 // max. length of path component +#define _MAX_FNAME 256 // max. length of file name component +#define _MAX_EXT 256 // max. length of extension component + + +#pragma push_macro("_fullpath") +#undef _fullpath + +_Success_(return != 0) _Check_return_ _ACRTIMP _CRTALLOCATOR char* __cdecl _fullpath( + _Out_writes_opt_z_(_BufferCount) char* _Buffer, _In_z_ char const* _Path, _In_ size_t _BufferCount); + +#pragma pop_macro("_fullpath") + +_Check_return_wat_ _ACRTIMP errno_t __cdecl _makepath_s(_Out_writes_z_(_BufferCount) char* _Buffer, + _In_ size_t _BufferCount, _In_opt_z_ char const* _Drive, _In_opt_z_ char const* _Dir, + _In_opt_z_ char const* _Filename, _In_opt_z_ char const* _Ext); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_4(errno_t, _makepath_s, char, _Buffer, _In_opt_z_ char const*, _Drive, + _In_opt_z_ char const*, _Dir, _In_opt_z_ char const*, _Filename, _In_opt_z_ char const*, _Ext) + +__DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_4(void, __RETURN_POLICY_VOID, _ACRTIMP, _makepath, _Pre_notnull_ _Post_z_, char, + _Buffer, _In_opt_z_ char const*, _Drive, _In_opt_z_ char const*, _Dir, _In_opt_z_ char const*, _Filename, + _In_opt_z_ char const*, _Ext) + +_CRT_INSECURE_DEPRECATE(_splitpath_s) +_ACRTIMP void __cdecl _splitpath(_In_z_ char const* _FullPath, _Pre_maybenull_ _Post_z_ char* _Drive, + _Pre_maybenull_ _Post_z_ char* _Dir, _Pre_maybenull_ _Post_z_ char* _Filename, _Pre_maybenull_ _Post_z_ char* _Ext); + +_Check_return_wat_ _ACRTIMP errno_t __cdecl _splitpath_s(_In_z_ char const* _FullPath, + _Out_writes_opt_z_(_DriveCount) char* _Drive, _In_ size_t _DriveCount, _Out_writes_opt_z_(_DirCount) char* _Dir, + _In_ size_t _DirCount, _Out_writes_opt_z_(_FilenameCount) char* _Filename, _In_ size_t _FilenameCount, + _Out_writes_opt_z_(_ExtCount) char* _Ext, _In_ size_t _ExtCount); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_SPLITPATH(errno_t, _splitpath_s, char, _Dest) + +#if __STDC_WANT_SECURE_LIB__ + +_Check_return_opt_ _Success_(return == 0) _DCRTIMP errno_t __cdecl getenv_s(_Out_ size_t* _RequiredCount, + _Out_writes_opt_z_(_BufferCount) char* _Buffer, _In_ rsize_t _BufferCount, _In_z_ char const* _VarName); + +#endif // __STDC_WANT_SECURE_LIB__ + + +_ACRTIMP int* __cdecl __p___argc(void); +_ACRTIMP char*** __cdecl __p___argv(void); +_ACRTIMP wchar_t*** __cdecl __p___wargv(void); + +#ifdef _CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY +extern int __argc; +extern char** __argv; +extern wchar_t** __wargv; +#else +#define __argc (*__p___argc()) // Pointer to number of command line arguments +#define __argv (*__p___argv()) // Pointer to table of narrow command line arguments +#define __wargv (*__p___wargv()) // Pointer to table of wide command line arguments +#endif + +_DCRTIMP char*** __cdecl __p__environ(void); +_DCRTIMP wchar_t*** __cdecl __p__wenviron(void); + +#ifndef _CRT_BEST_PRACTICES_USAGE +#define _CRT_V12_LEGACY_FUNCTIONALITY +#endif + +#ifndef _CRT_V12_LEGACY_FUNCTIONALITY +// Deprecated symbol: Do not expose environment global pointers unless +// legacy access is specifically requested +#define _environ crt_usage_error__do_not_reference_global_pointer_directly__environ +#define _wenviron crt_usage_error__do_not_reference_global_pointer_directly__wenviron +#else +#define _environ (*__p__environ()) // Pointer to narrow environment table +#define _wenviron (*__p__wenviron()) // Pointer to wide environment table +#endif + + +// Sizes for buffers used by the getenv/putenv family of functions. +#define _MAX_ENV 32767 + + +#if _CRT_FUNCTIONS_REQUIRED + +_Check_return_ _CRT_INSECURE_DEPRECATE(_dupenv_s) +_DCRTIMP char* __cdecl getenv(_In_z_ char const* _VarName); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_1_1( + errno_t, getenv_s, _Out_ size_t*, _RequiredCount, char, _Buffer, _In_z_ char const*, _VarName) + +#if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) +#pragma push_macro("_dupenv_s") +#undef _dupenv_s +#endif + +_Check_return_opt_ _DCRTIMP errno_t __cdecl _dupenv_s(_Outptr_result_buffer_maybenull_(*_BufferCount) + _Outptr_result_maybenull_z_ char** _Buffer, + _Out_opt_ size_t* _BufferCount, _In_z_ char const* _VarName); + +#if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) +#pragma pop_macro("_dupenv_s") +#endif + +_DCRTIMP int __cdecl system(_In_opt_z_ char const* _Command); + +// The functions below have declspecs in their declarations in the Windows +// headers, causing PREfast to fire 6540 here +#pragma warning(push) +#pragma warning(disable : 6540) + +_Check_return_ _DCRTIMP int __cdecl _putenv(_In_z_ char const* _EnvString); + +_Check_return_wat_ _DCRTIMP errno_t __cdecl _putenv_s(_In_z_ char const* _Name, _In_z_ char const* _Value); + +#pragma warning(pop) + +_DCRTIMP errno_t __cdecl _searchenv_s(_In_z_ char const* _Filename, _In_z_ char const* _VarName, + _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount); + +__DEFINE_CPP_OVERLOAD_SECURE_FUNC_2_0( + errno_t, _searchenv_s, _In_z_ char const*, _Filename, _In_z_ char const*, _VarName, char, _Buffer) + +__DEFINE_CPP_OVERLOAD_STANDARD_FUNC_2_0(void, __RETURN_POLICY_VOID, _DCRTIMP, _searchenv, _In_z_ char const*, _Filename, + _In_z_ char const*, _VarName, _Pre_notnull_ _Post_z_, char, _Buffer) + +// The Win32 API SetErrorMode, Beep and Sleep should be used instead. +_CRT_OBSOLETE(SetErrorMode) +_DCRTIMP void __cdecl _seterrormode(_In_ int _Mode); + +_CRT_OBSOLETE(Beep) +_DCRTIMP void __cdecl _beep(_In_ unsigned _Frequency, _In_ unsigned _Duration); + +_CRT_OBSOLETE(Sleep) +_DCRTIMP void __cdecl _sleep(_In_ unsigned long _Duration); + +#endif // _CRT_FUNCTIONS_REQUIRED + +#if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES + +#ifndef __cplusplus +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#define sys_errlist _sys_errlist +#define sys_nerr _sys_nerr + +#pragma warning(push) +#pragma warning(disable : 4141) // Using deprecated twice + +_Check_return_ _CRT_NONSTDC_DEPRECATE(_ecvt) _CRT_INSECURE_DEPRECATE(_ecvt_s) _ACRTIMP + char* __cdecl ecvt(_In_ double _Value, _In_ int _DigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); + +_Check_return_ _CRT_NONSTDC_DEPRECATE(_fcvt) _CRT_INSECURE_DEPRECATE(_fcvt_s) _ACRTIMP + char* __cdecl fcvt(_In_ double _Value, _In_ int _FractionalDigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); + +_CRT_NONSTDC_DEPRECATE(_gcvt) +_CRT_INSECURE_DEPRECATE(_fcvt_s) _ACRTIMP + char* __cdecl gcvt(_In_ double _Value, _In_ int _DigitCount, _Pre_notnull_ _Post_z_ char* _DstBuf); + +_CRT_NONSTDC_DEPRECATE(_itoa) +_CRT_INSECURE_DEPRECATE(_itoa_s) _ACRTIMP + char* __cdecl itoa(_In_ int _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); + +_CRT_NONSTDC_DEPRECATE(_ltoa) +_CRT_INSECURE_DEPRECATE(_ltoa_s) _ACRTIMP + char* __cdecl ltoa(_In_ long _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); + + +_CRT_NONSTDC_DEPRECATE(_swab) +_ACRTIMP void __cdecl swab( + _Inout_updates_z_(_SizeInBytes) char* _Buf1, _Inout_updates_z_(_SizeInBytes) char* _Buf2, _In_ int _SizeInBytes); + +_CRT_NONSTDC_DEPRECATE(_ultoa) +_CRT_INSECURE_DEPRECATE(_ultoa_s) _ACRTIMP + char* __cdecl ultoa(_In_ unsigned long _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); + +#define environ _environ + +_Check_return_ _CRT_NONSTDC_DEPRECATE(_putenv) +_DCRTIMP int __cdecl putenv(_In_z_ char const* _EnvString); + +#pragma warning(pop) + +onexit_t __cdecl onexit(_In_opt_ onexit_t _Func); + +#endif // _CRT_INTERNAL_NONSTDC_NAMES + + +_CRT_END_C_HEADER +_UCRT_RESTORE_CLANG_WARNINGS +#pragma warning(pop) // _UCRT_DISABLED_WARNINGS +#endif // _MSVC_STDLIB_HPP diff --git a/stl/inc/cmath b/stl/inc/cmath index b805995d240..33231e32ab2 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -11,12 +11,21 @@ #include #include -#if !defined(__clang__) && !defined(_M_CEE) // TRANSITION, VSO-1663104 +#if !defined(__clang__) && !defined(_M_CEE) && !defined(_MSVC_CONSTEXPR_CMATH) // TRANSITION, VSO-1663104 #define _HAS_CMATH_INTRINSICS 1 #else // ^^^ intrinsics available / intrinsics unavailable vvv #define _HAS_CMATH_INTRINSICS 0 #endif // ^^^ intrinsics unavailable ^^^ +// MSVC provides builtins for math functions in C++23 and later if the user +// has not specified -Zc:cmath-. The compiler defines the macro below to make +// detection simpler. +#if defined(__clang__) || defined(_MSVC_CONSTEXPR_CMATH) +#define _HAS_CMATH_BUILTINS 1 +#else // ^^^ builtins available / builtins unavailable vvv +#define _HAS_CMATH_BUILTINS 0 +#endif + #if _HAS_CMATH_INTRINSICS #include _STL_INTRIN_HEADER #endif // _HAS_CMATH_INTRINSICS @@ -29,11 +38,11 @@ _STL_DISABLE_CLANG_WARNINGS #undef new _EXTERN_CXX_WORKAROUND -_NODISCARD _Check_return_ inline float acos(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float acos(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD acosf(_Xx); } -_NODISCARD _Check_return_ inline float acosh(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float acosh(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD acoshf(_Xx); } @@ -61,22 +70,23 @@ _NODISCARD _Check_return_ inline float cbrt(_In_ float _Xx) noexcept /* strength return _CSTD cbrtf(_Xx); } -_NODISCARD _Check_return_ inline float ceil(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float ceil(_In_ float _Xx) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __ceilf(_Xx); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_ceilf(_Xx); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD ceilf(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline float copysign(_In_ float _Number, _In_ float _Sign) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float copysign(_In_ float _Number, _In_ float _Sign) noexcept +/* strengthened */ { #if _HAS_CMATH_INTRINSICS return __copysignf(_Number, _Sign); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_copysignf(_Number, _Sign); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD copysignf(_Number, _Sign); #endif // ^^^ intrinsics unavailable ^^^ } @@ -109,41 +119,37 @@ _NODISCARD _Check_return_ inline float expm1(_In_ float _Xx) noexcept /* strengt return _CSTD expm1f(_Xx); } -_NODISCARD _Check_return_ inline float fabs(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fabs(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD fabsf(_Xx); } -_NODISCARD _Check_return_ inline float fdim(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fdim(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { return _CSTD fdimf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float floor(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float floor(_In_ float _Xx) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __floorf(_Xx); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_floorf(_Xx); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD floorf(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline float fma(_In_ float _Xx, _In_ float _Yx, _In_ float _Zx) noexcept /* strengthened */ { - return _CSTD fmaf(_Xx, _Yx, _Zx); -} - -_NODISCARD _Check_return_ inline float fmax(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fmax(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { return _CSTD fmaxf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float fmin(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fmin(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { return _CSTD fminf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float fmod(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fmod(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { return _CSTD fmodf(_Xx, _Yx); } -inline float frexp(_In_ float _Xx, _Out_ int* _Yx) noexcept /* strengthened */ { +_CONSTEXPR_CMATH23 float frexp(_In_ float _Xx, _Out_ int* _Yx) noexcept /* strengthened */ { return _CSTD frexpf(_Xx, _Yx); } @@ -151,11 +157,11 @@ _NODISCARD _Check_return_ inline float hypot(_In_ float _Xx, _In_ float _Yx) noe return _CSTD hypotf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline int ilogb(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 int ilogb(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD ilogbf(_Xx); } -_NODISCARD _Check_return_ inline float ldexp(_In_ float _Xx, _In_ int _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float ldexp(_In_ float _Xx, _In_ int _Yx) noexcept /* strengthened */ { return _CSTD ldexpf(_Xx, _Yx); } @@ -167,7 +173,7 @@ _NODISCARD _Check_return_ inline long long llrint(_In_ float _Xx) noexcept /* st return _CSTD llrintf(_Xx); } -_NODISCARD _Check_return_ inline long long llround(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long long llround(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD llroundf(_Xx); } @@ -187,7 +193,7 @@ _NODISCARD _Check_return_ inline float log2(_In_ float _Xx) noexcept /* strength return _CSTD log2f(_Xx); } -_NODISCARD _Check_return_ inline float logb(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float logb(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD logbf(_Xx); } @@ -195,7 +201,7 @@ _NODISCARD _Check_return_ inline long lrint(_In_ float _Xx) noexcept /* strength return _CSTD lrintf(_Xx); } -_NODISCARD _Check_return_ inline long lround(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long lround(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD lroundf(_Xx); } @@ -207,11 +213,13 @@ _NODISCARD _Check_return_ inline float nearbyint(_In_ float _Xx) noexcept /* str return _CSTD nearbyintf(_Xx); } -_NODISCARD _Check_return_ inline float nextafter(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float nextafter(_In_ float _Xx, _In_ float _Yx) noexcept +/* strengthened */ { return _CSTD nextafterf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float nexttoward(_In_ float _Xx, _In_ long double _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float nexttoward(_In_ float _Xx, _In_ long double _Yx) noexcept +/* strengthened */ { return _CSTD nexttowardf(_Xx, _Yx); } @@ -219,11 +227,12 @@ _NODISCARD _Check_return_ inline float pow(_In_ float _Xx, _In_ float _Yx) noexc return _CSTD powf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float remainder(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float remainder(_In_ float _Xx, _In_ float _Yx) noexcept +/* strengthened */ { return _CSTD remainderf(_Xx, _Yx); } -inline float remquo(_In_ float _Xx, _In_ float _Yx, _Out_ int* _Zx) noexcept /* strengthened */ { +_CONSTEXPR_CMATH23 float remquo(_In_ float _Xx, _In_ float _Yx, _Out_ int* _Zx) noexcept /* strengthened */ { return _CSTD remquof(_Xx, _Yx, _Zx); } @@ -231,21 +240,21 @@ _NODISCARD _Check_return_ inline float rint(_In_ float _Xx) noexcept /* strength return _CSTD rintf(_Xx); } -_NODISCARD _Check_return_ inline float round(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float round(_In_ float _Xx) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __roundf(_Xx); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_roundf(_Xx); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD roundf(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline float scalbln(_In_ float _Xx, _In_ long _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float scalbln(_In_ float _Xx, _In_ long _Yx) noexcept /* strengthened */ { return _CSTD scalblnf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float scalbn(_In_ float _Xx, _In_ int _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float scalbn(_In_ float _Xx, _In_ int _Yx) noexcept /* strengthened */ { return _CSTD scalbnf(_Xx, _Yx); } @@ -273,21 +282,21 @@ _NODISCARD _Check_return_ inline float tgamma(_In_ float _Xx) noexcept /* streng return _CSTD tgammaf(_Xx); } -_NODISCARD _Check_return_ inline float trunc(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float trunc(_In_ float _Xx) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __truncf(_Xx); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_truncf(_Xx); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD truncf(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline long double acos(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double acos(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD acosl(_Xx); } -_NODISCARD _Check_return_ inline long double acosh(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double acosh(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD acoshl(_Xx); } @@ -316,23 +325,24 @@ _NODISCARD _Check_return_ inline long double cbrt(_In_ long double _Xx) noexcept return _CSTD cbrtl(_Xx); } -_NODISCARD _Check_return_ inline long double ceil(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double ceil(_In_ long double _Xx) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __ceil(static_cast(_Xx)); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_ceill(_Xx); #else // ^^^ defined(__clang__) / intrinsics unavailable vvv return _CSTD ceill(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline long double copysign(_In_ long double _Number, _In_ long double _Sign) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double copysign( + _In_ long double _Number, _In_ long double _Sign) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __copysign(static_cast(_Number), static_cast(_Sign)); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_copysignl(_Number, _Sign); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD copysignl(_Number, _Sign); #endif // ^^^ intrinsics unavailable ^^^ } @@ -365,46 +375,41 @@ _NODISCARD _Check_return_ inline long double expm1(_In_ long double _Xx) noexcep return _CSTD expm1l(_Xx); } -_NODISCARD _Check_return_ inline long double fabs(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fabs(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD fabsl(_Xx); } -_NODISCARD _Check_return_ inline long double fdim(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fdim(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD fdiml(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double floor(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double floor(_In_ long double _Xx) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __floor(static_cast(_Xx)); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_floorl(_Xx); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD floorl(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline long double fma( - _In_ long double _Xx, _In_ long double _Yx, _In_ long double _Zx) noexcept /* strengthened */ { - return _CSTD fmal(_Xx, _Yx, _Zx); -} - -_NODISCARD _Check_return_ inline long double fmax(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fmax(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD fmaxl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double fmin(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fmin(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD fminl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double fmod(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fmod(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD fmodl(_Xx, _Yx); } -inline long double frexp(_In_ long double _Xx, _Out_ int* _Yx) noexcept /* strengthened */ { +_CONSTEXPR_CMATH23 long double frexp(_In_ long double _Xx, _Out_ int* _Yx) noexcept /* strengthened */ { return _CSTD frexpl(_Xx, _Yx); } @@ -413,11 +418,12 @@ _NODISCARD _Check_return_ inline long double hypot(_In_ long double _Xx, _In_ lo return _CSTD hypotl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline int ilogb(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 int ilogb(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD ilogbl(_Xx); } -_NODISCARD _Check_return_ inline long double ldexp(_In_ long double _Xx, _In_ int _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double ldexp(_In_ long double _Xx, _In_ int _Yx) noexcept +/* strengthened */ { return _CSTD ldexpl(_Xx, _Yx); } @@ -429,7 +435,7 @@ _NODISCARD _Check_return_ inline long long llrint(_In_ long double _Xx) noexcept return _CSTD llrintl(_Xx); } -_NODISCARD _Check_return_ inline long long llround(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long long llround(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD llroundl(_Xx); } @@ -449,7 +455,7 @@ _NODISCARD _Check_return_ inline long double log2(_In_ long double _Xx) noexcept return _CSTD log2l(_Xx); } -_NODISCARD _Check_return_ inline long double logb(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double logb(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD logbl(_Xx); } @@ -457,7 +463,7 @@ _NODISCARD _Check_return_ inline long lrint(_In_ long double _Xx) noexcept /* st return _CSTD lrintl(_Xx); } -_NODISCARD _Check_return_ inline long lround(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long lround(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD lroundl(_Xx); } @@ -469,12 +475,12 @@ _NODISCARD _Check_return_ inline long double nearbyint(_In_ long double _Xx) noe return _CSTD nearbyintl(_Xx); } -_NODISCARD _Check_return_ inline long double nextafter(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double nextafter(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD nextafterl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double nexttoward(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double nexttoward(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD nexttowardl(_Xx, _Yx); } @@ -484,12 +490,13 @@ _NODISCARD _Check_return_ inline long double pow(_In_ long double _Xx, _In_ long return _CSTD powl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double remainder(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double remainder(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD remainderl(_Xx, _Yx); } -inline long double remquo(_In_ long double _Xx, _In_ long double _Yx, _Out_ int* _Zx) noexcept /* strengthened */ { +_CONSTEXPR_CMATH23 long double remquo(_In_ long double _Xx, _In_ long double _Yx, _Out_ int* _Zx) noexcept +/* strengthened */ { return _CSTD remquol(_Xx, _Yx, _Zx); } @@ -497,21 +504,23 @@ _NODISCARD _Check_return_ inline long double rint(_In_ long double _Xx) noexcept return _CSTD rintl(_Xx); } -_NODISCARD _Check_return_ inline long double round(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double round(_In_ long double _Xx) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __round(static_cast(_Xx)); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_roundl(_Xx); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD roundl(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline long double scalbln(_In_ long double _Xx, _In_ long _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double scalbln(_In_ long double _Xx, _In_ long _Yx) noexcept +/* strengthened */ { return _CSTD scalblnl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double scalbn(_In_ long double _Xx, _In_ int _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double scalbn(_In_ long double _Xx, _In_ int _Yx) noexcept +/* strengthened */ { return _CSTD scalbnl(_Xx, _Yx); } @@ -539,12 +548,12 @@ _NODISCARD _Check_return_ inline long double tgamma(_In_ long double _Xx) noexce return _CSTD tgammal(_Xx); } -_NODISCARD _Check_return_ inline long double trunc(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double trunc(_In_ long double _Xx) noexcept /* strengthened */ { #if _HAS_CMATH_INTRINSICS return __trunc(static_cast(_Xx)); -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS return __builtin_truncl(_Xx); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD truncl(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -576,7 +585,7 @@ _NODISCARD _STD _Common_float_type_t<_Ty1, _Ty2> pow(_Ty1 _Left, _Ty2 _Right) no template && _STD is_arithmetic_v<_Ty2> && _STD is_arithmetic_v<_Ty3>, int> = 0> -_NODISCARD _STD _Common_float_type_t<_Ty1, _STD _Common_float_type_t<_Ty2, _Ty3>> fma( +_NODISCARD _CONSTEXPR_CMATH23 _STD _Common_float_type_t<_Ty1, _STD _Common_float_type_t<_Ty2, _Ty3>> fma( _Ty1 _Left, _Ty2 _Middle, _Ty3 _Right) noexcept /* strengthened */ { using _Common = _STD _Common_float_type_t<_Ty1, _STD _Common_float_type_t<_Ty2, _Ty3>>; if constexpr (_STD is_same_v<_Common, float>) { @@ -589,7 +598,8 @@ _NODISCARD _STD _Common_float_type_t<_Ty1, _STD _Common_float_type_t<_Ty2, _Ty3> } template && _STD is_arithmetic_v<_Ty2>, int> = 0> -_STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo) noexcept /* strengthened */ { +_CONSTEXPR_CMATH23 _STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo) noexcept +/* strengthened */ { using _Common = _STD _Common_float_type_t<_Ty1, _Ty2>; if constexpr (_STD is_same_v<_Common, float>) { return _CSTD remquof(static_cast<_Common>(_Left), static_cast<_Common>(_Right), _Pquo); @@ -915,6 +925,7 @@ _GENERIC_MATH_CLASSIFY1_RETV(isnan, false) #undef _GENERIC_MATH_CLASSIFY1_RETV_WCHAR_T #undef _GENERIC_MATH_CLASSIFY1_RETV_CHAR8_T #undef _GENERIC_MATH_CLASSIFY1_RETV +#undef _HAS_CMATH_BUILTINS #undef _HAS_CMATH_INTRINSICS _END_EXTERN_CXX_WORKAROUND diff --git a/stl/inc/cstdlib b/stl/inc/cstdlib index 1bf0509fe3b..5223449815b 100644 --- a/stl/inc/cstdlib +++ b/stl/inc/cstdlib @@ -6,9 +6,10 @@ #ifndef _CSTDLIB_ #define _CSTDLIB_ #include -#if _STL_COMPILER_PREPROCESSOR +#if _STL_COMPILER_PREPROCESSOR #include + #include #pragma pack(push, _CRT_PACKING) @@ -20,15 +21,15 @@ _STL_DISABLE_CLANG_WARNINGS _EXTERN_CXX_WORKAROUND // has abs(long) and abs(long long) -_NODISCARD _Check_return_ inline double abs(_In_ double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 double abs(_In_ double _Xx) noexcept /* strengthened */ { return _CSTD fabs(_Xx); } -_NODISCARD _Check_return_ inline float abs(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float abs(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD fabsf(_Xx); } -_NODISCARD _Check_return_ inline long double abs(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double abs(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD fabsl(_Xx); } _END_EXTERN_CXX_WORKAROUND diff --git a/stl/inc/header-units.json b/stl/inc/header-units.json index e94f92bd534..e751e304819 100644 --- a/stl/inc/header-units.json +++ b/stl/inc/header-units.json @@ -15,12 +15,14 @@ "__msvc_heap_algorithms.hpp", "__msvc_int128.hpp", "__msvc_iter_core.hpp", + "__msvc_math.hpp", "__msvc_minmax.hpp", "__msvc_ostream.hpp", "__msvc_print.hpp", "__msvc_ranges_to.hpp", "__msvc_ranges_tuple_formatter.hpp", "__msvc_sanitizer_annotate_container.hpp", + "__msvc_stdlib.hpp", "__msvc_string_view.hpp", "__msvc_system_error_abi.hpp", "__msvc_threads_core.hpp", diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 0b97223c6a0..b0f459531de 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -408,6 +408,7 @@ // P3142R0 Printing Blank Lines With println() // P3235R3 std::print More Types Faster With Less Memory // P3567R2 flat_meow Fixes +// P0533R9 constexpr for and // Parallel Algorithms Notes // C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. @@ -958,6 +959,22 @@ _EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC Compiler 19 #define _CONSTEXPR23 inline #endif // ^^^ inline (not constexpr) in C++20 and earlier ^^^ +// Math functions that became constexpr in C++23. Support is conditioned on whether +// -Zc:cmath- is specified. +#if _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) +#define _CONSTEXPR_CMATH23 constexpr +#else // ^^^ constexpr in C++23 and later / inline (not constexpr) in C++20 and earlier vvv +#define _CONSTEXPR_CMATH23 inline +#endif + +// Math functions that became constexpr in C++26. Support is conditioned on whether +// -Zc:cmath- is specified. +#if _HAS_CXX26 && defined(_MSVC_CONSTEXPR_CMATH) +#define _CONSTEXPR_CMATH26 constexpr +#else // ^^^ constexpr in C++26 and later / inline (not constexpr) in C++23 and earlier vvv +#define _CONSTEXPR_CMATH26 inline +#endif + // P2465R3 Standard Library Modules std And std.compat #ifdef _BUILD_STD_MODULE #if !_HAS_CXX20 @@ -1796,6 +1813,12 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_to_underlying 202102L #define __cpp_lib_tuple_like 202207L #define __cpp_lib_unreachable 202202L + +// MSVC conditionally suppports constexpr cmath under an "opt-out" model. +// The compiler defines the macro used below to detect support. +#if defined(_MSVC_CONSTEXPR_CMATH) +#define __cpp_lib_constexpr_cmath 202202L +#endif #endif // _HAS_CXX23 // macros with language mode sensitivity diff --git a/stl/msbuild/stl_2/amd64.exports b/stl/msbuild/stl_2/amd64.exports index 38ff0ff6a10..23c021f319b 100644 --- a/stl/msbuild/stl_2/amd64.exports +++ b/stl/msbuild/stl_2/amd64.exports @@ -34,6 +34,10 @@ __std_smf_laguerre __std_smf_laguerref __std_smf_legendre __std_smf_legendref +__std_smf_lgammaf +__std_smf_lgamma +__std_smf_tgammaf +__std_smf_tgamma __std_smf_riemann_zeta __std_smf_riemann_zetaf __std_smf_sph_bessel diff --git a/stl/msbuild/stl_2/arm64.exports b/stl/msbuild/stl_2/arm64.exports index 38ff0ff6a10..23c021f319b 100644 --- a/stl/msbuild/stl_2/arm64.exports +++ b/stl/msbuild/stl_2/arm64.exports @@ -34,6 +34,10 @@ __std_smf_laguerre __std_smf_laguerref __std_smf_legendre __std_smf_legendref +__std_smf_lgammaf +__std_smf_lgamma +__std_smf_tgammaf +__std_smf_tgamma __std_smf_riemann_zeta __std_smf_riemann_zetaf __std_smf_sph_bessel diff --git a/stl/msbuild/stl_2/i386.exports b/stl/msbuild/stl_2/i386.exports index c89459dedaf..571bec7b3e1 100644 --- a/stl/msbuild/stl_2/i386.exports +++ b/stl/msbuild/stl_2/i386.exports @@ -34,6 +34,10 @@ ___std_smf_laguerre@12 ___std_smf_laguerref@8 ___std_smf_legendre@12 ___std_smf_legendref@8 +___std_smf_lgamma@8 +___std_smf_lgammaf@4 +___std_smf_tgamma@8 +___std_smf_tgammaf@4 ___std_smf_riemann_zeta@8 ___std_smf_riemann_zetaf@4 ___std_smf_sph_bessel@12 diff --git a/stl/src/special_math.cpp b/stl/src/special_math.cpp index 0903f91cca4..320a7280dd3 100644 --- a/stl/src/special_math.cpp +++ b/stl/src/special_math.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -476,6 +477,42 @@ extern "C" { return _Boost_call([=] { return ::boost::math::sph_neumann(_Pn, _Px); }); } + +[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_lgammaf( + float _Px) noexcept { + if (_STD isnan(_Px)) { + return _Px; + } + + return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); +} + +[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_lgamma( + double _Px) noexcept { + if (_STD isnan(_Px)) { + return _Px; + } + + return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); +} + +[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_tgammaf( + float _Px) noexcept { + if (_STD isnan(_Px)) { + return _Px; + } + + return _Boost_call([=] { return ::boost::math::tgamma(_Px); }); +} + +[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_tgamma( + double _Px) noexcept { + if (_STD isnan(_Px)) { + return _Px; + } + + return _Boost_call([=] { return ::boost::math::tgamma(_Px); }); +} } // extern "C" namespace { From 2afc353e7d90e79c731f29a5d8b17dfaed1d71ab Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:34 -0700 Subject: [PATCH 02/85] clang-format, no manual changes. --- stl/inc/__msvc_stdlib.hpp | 78 +++++++++++++++++++-------------------- stl/inc/cstdlib | 1 - stl/inc/yvals_core.h | 2 +- stl/src/special_math.cpp | 14 +++---- 4 files changed, 45 insertions(+), 50 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 8e86d79d2e6..eda476a4a23 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -78,16 +78,14 @@ _onexit_m_t __clrcall _onexit_m_appdomain(_onexit_m_t _Function); #ifdef __cplusplus [System::Security::SecurityCritical] #endif - _Check_return_ int __clrcall - _atexit_m(_In_opt_ void(__clrcall* _Function)(void)); + _Check_return_ int __clrcall _atexit_m(_In_opt_ void(__clrcall* _Function)(void)); _onexit_m_t __clrcall _onexit_m(_onexit_m_t _Function); #else #ifdef __cplusplus [System::Security::SecurityCritical] #endif - _Check_return_ inline int __clrcall - _atexit_m(_In_opt_ void(__clrcall* _Function)(void)) { + _Check_return_ inline int __clrcall _atexit_m(_In_opt_ void(__clrcall* _Function)(void)) { return _atexit_m_appdomain(_Function); } @@ -106,8 +104,7 @@ extern "C++" { #ifdef __cplusplus [System::Security::SecurityCritical] #endif - inline int __clrcall - atexit(void(__clrcall* _Function)(void)) { + inline int __clrcall atexit(void(__clrcall* _Function)(void)) { return _atexit_m_appdomain(_Function); } @@ -234,12 +231,12 @@ typedef struct _lldiv_t { } lldiv_t; extern "C" { - _Check_return_ constexpr int __cdecl abs(_In_ int) noexcept; - _Check_return_ constexpr long __cdecl labs(_In_ long) noexcept; - _Check_return_ constexpr long long __cdecl llabs(_In_ long long) noexcept; - _Check_return_ constexpr div_t __cdecl div(_In_ int, _In_ int) noexcept; - _Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long, _In_ long) noexcept; - _Check_return_ constexpr lldiv_t __cdecl lldiv(_In_ long long, _In_ long long) noexcept; +_Check_return_ constexpr int __cdecl abs(_In_ int) noexcept; +_Check_return_ constexpr long __cdecl labs(_In_ long) noexcept; +_Check_return_ constexpr long long __cdecl llabs(_In_ long long) noexcept; +_Check_return_ constexpr div_t __cdecl div(_In_ int, _In_ int) noexcept; +_Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long, _In_ long) noexcept; +_Check_return_ constexpr lldiv_t __cdecl lldiv(_In_ long long, _In_ long long) noexcept; } #pragma warning(push) @@ -260,15 +257,18 @@ extern "C" { return _Xx >= 0 ? _Xx : -_Xx; } -[[nodiscard]] _Check_return_ constexpr div_t __cdecl div(_In_ int _Numerator, _In_ int _Denominator) noexcept /* strengthened */ { +[[nodiscard]] _Check_return_ constexpr div_t __cdecl div(_In_ int _Numerator, _In_ int _Denominator) noexcept +/* strengthened */ { return {_Numerator / _Denominator, _Numerator % _Denominator}; } -[[nodiscard]] _Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long _Numerator, _In_ long _Denominator) noexcept /* strengthened */ { +[[nodiscard]] _Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long _Numerator, _In_ long _Denominator) noexcept +/* strengthened */ { return {_Numerator / _Denominator, _Numerator % _Denominator}; } -[[nodiscard]] _Check_return_ constexpr lldiv_t __cdecl lldiv(_In_ long long _Numerator, _In_ long long _Denominator) noexcept +[[nodiscard]] _Check_return_ constexpr lldiv_t __cdecl lldiv( + _In_ long long _Numerator, _In_ long long _Denominator) noexcept /* strengthened */ { return {_Numerator / _Denominator, _Numerator % _Denominator}; } @@ -484,8 +484,8 @@ __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_1_1(char*, __RETURN_POLICY_DST, _ACRTIMP, _u _Success_(return == 0) _Check_return_opt_ _ACRTIMP errno_t __cdecl _i64toa_s( _In_ __int64 _Value, _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ int _Radix); -_Success_(return == 0) _CRT_INSECURE_DEPRECATE(_i64toa_s) _ACRTIMP - char* __cdecl _i64toa(_In_ __int64 _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); +_Success_(return == 0) _CRT_INSECURE_DEPRECATE(_i64toa_s) _ACRTIMP char* __cdecl _i64toa( + _In_ __int64 _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); _Success_(return == 0) _Check_return_opt_ _ACRTIMP errno_t __cdecl _ui64toa_s(_In_ unsigned __int64 _Value, _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ int _Radix); @@ -513,9 +513,9 @@ __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_4(errno_t, _ecvt_s, char, _Buffer, _In_ doub _Check_return_ _CRT_INSECURE_DEPRECATE(_ecvt_s) _ACRTIMP char* __cdecl _ecvt(_In_ double _Value, _In_ int _DigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); -_Success_(return == 0) _Check_return_wat_ _ACRTIMP errno_t - __cdecl _fcvt_s(_Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ double _Value, - _In_ int _FractionalDigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); +_Success_(return == 0) _Check_return_wat_ _ACRTIMP errno_t __cdecl _fcvt_s(_Out_writes_z_(_BufferCount) char* _Buffer, + _In_ size_t _BufferCount, _In_ double _Value, _In_ int _FractionalDigitCount, _Out_ int* _PtDec, + _Out_ int* _PtSign); __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_4(_Success_(return == 0) errno_t, _fcvt_s, char, _Buffer, _In_ double, _Value, _In_ int, _FractionalDigitCount, _Out_ int*, _PtDec, _Out_ int*, _PtSign) @@ -559,19 +559,19 @@ _Check_return_ _ACRTIMP int __cdecl mblen( _Check_return_ _ACRTIMP int __cdecl _mblen_l( _In_reads_bytes_opt_(_MaxCount) _Pre_opt_z_ char const* _Ch, _In_ size_t _MaxCount, _In_opt_ _locale_t _Locale); -_Check_return_ _Post_satisfies_(return <= _String_length_(_String)) _ACRTIMP size_t - __cdecl _mbstrlen(_In_z_ char const* _String); +_Check_return_ _Post_satisfies_(return <= _String_length_(_String)) _ACRTIMP size_t __cdecl _mbstrlen( + _In_z_ char const* _String); -_Check_return_ _Post_satisfies_(return <= _String_length_(_String) || return == (size_t) -1) _ACRTIMP size_t - __cdecl _mbstrlen_l(_In_z_ char const* _String, _In_opt_ _locale_t _Locale); +_Check_return_ _Post_satisfies_(return <= _String_length_(_String) || return == (size_t) -1) _ACRTIMP size_t __cdecl + _mbstrlen_l(_In_z_ char const* _String, _In_opt_ _locale_t _Locale); _Check_return_ _Post_satisfies_( - (return <= _String_length_(_String) && return <= _MaxCount) || return == (size_t) -1) _ACRTIMP size_t - __cdecl _mbstrnlen(_In_z_ char const* _String, _In_ size_t _MaxCount); + (return <= _String_length_(_String) && return <= _MaxCount) || return == (size_t) -1) _ACRTIMP size_t __cdecl + _mbstrnlen(_In_z_ char const* _String, _In_ size_t _MaxCount); -_Post_satisfies_( - (return <= _String_length_(_String) && return <= _MaxCount) || return == (size_t) -1) _Check_return_ _ACRTIMP size_t - __cdecl _mbstrnlen_l(_In_z_ char const* _String, _In_ size_t _MaxCount, _In_opt_ _locale_t _Locale); +_Post_satisfies_((return <= _String_length_(_String) && return <= _MaxCount) + || return == (size_t) -1) _Check_return_ _ACRTIMP size_t __cdecl + _mbstrnlen_l(_In_z_ char const* _String, _In_ size_t _MaxCount, _In_opt_ _locale_t _Locale); _Success_(return != -1) _ACRTIMP int __cdecl mbtowc(_Pre_notnull_ _Post_z_ wchar_t* _DstCh, _In_reads_or_z_opt_(_SrcSizeInBytes) char const* _SrcCh, _In_ size_t _SrcSizeInBytes); @@ -794,20 +794,20 @@ _DCRTIMP void __cdecl _sleep(_In_ unsigned long _Duration); _Check_return_ _CRT_NONSTDC_DEPRECATE(_ecvt) _CRT_INSECURE_DEPRECATE(_ecvt_s) _ACRTIMP char* __cdecl ecvt(_In_ double _Value, _In_ int _DigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); -_Check_return_ _CRT_NONSTDC_DEPRECATE(_fcvt) _CRT_INSECURE_DEPRECATE(_fcvt_s) _ACRTIMP - char* __cdecl fcvt(_In_ double _Value, _In_ int _FractionalDigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); +_Check_return_ _CRT_NONSTDC_DEPRECATE(_fcvt) _CRT_INSECURE_DEPRECATE(_fcvt_s) _ACRTIMP char* __cdecl fcvt( + _In_ double _Value, _In_ int _FractionalDigitCount, _Out_ int* _PtDec, _Out_ int* _PtSign); _CRT_NONSTDC_DEPRECATE(_gcvt) -_CRT_INSECURE_DEPRECATE(_fcvt_s) _ACRTIMP - char* __cdecl gcvt(_In_ double _Value, _In_ int _DigitCount, _Pre_notnull_ _Post_z_ char* _DstBuf); +_CRT_INSECURE_DEPRECATE(_fcvt_s) +_ACRTIMP char* __cdecl gcvt(_In_ double _Value, _In_ int _DigitCount, _Pre_notnull_ _Post_z_ char* _DstBuf); _CRT_NONSTDC_DEPRECATE(_itoa) -_CRT_INSECURE_DEPRECATE(_itoa_s) _ACRTIMP - char* __cdecl itoa(_In_ int _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); +_CRT_INSECURE_DEPRECATE(_itoa_s) +_ACRTIMP char* __cdecl itoa(_In_ int _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); _CRT_NONSTDC_DEPRECATE(_ltoa) -_CRT_INSECURE_DEPRECATE(_ltoa_s) _ACRTIMP - char* __cdecl ltoa(_In_ long _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); +_CRT_INSECURE_DEPRECATE(_ltoa_s) +_ACRTIMP char* __cdecl ltoa(_In_ long _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); _CRT_NONSTDC_DEPRECATE(_swab) @@ -815,8 +815,8 @@ _ACRTIMP void __cdecl swab( _Inout_updates_z_(_SizeInBytes) char* _Buf1, _Inout_updates_z_(_SizeInBytes) char* _Buf2, _In_ int _SizeInBytes); _CRT_NONSTDC_DEPRECATE(_ultoa) -_CRT_INSECURE_DEPRECATE(_ultoa_s) _ACRTIMP - char* __cdecl ultoa(_In_ unsigned long _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); +_CRT_INSECURE_DEPRECATE(_ultoa_s) +_ACRTIMP char* __cdecl ultoa(_In_ unsigned long _Value, _Pre_notnull_ _Post_z_ char* _Buffer, _In_ int _Radix); #define environ _environ diff --git a/stl/inc/cstdlib b/stl/inc/cstdlib index 5223449815b..22291d56744 100644 --- a/stl/inc/cstdlib +++ b/stl/inc/cstdlib @@ -9,7 +9,6 @@ #if _STL_COMPILER_PREPROCESSOR #include - #include #pragma pack(push, _CRT_PACKING) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index b0f459531de..93646fb2683 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1817,7 +1817,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // MSVC conditionally suppports constexpr cmath under an "opt-out" model. // The compiler defines the macro used below to detect support. #if defined(_MSVC_CONSTEXPR_CMATH) -#define __cpp_lib_constexpr_cmath 202202L +#define __cpp_lib_constexpr_cmath 202202L #endif #endif // _HAS_CXX23 diff --git a/stl/src/special_math.cpp b/stl/src/special_math.cpp index 320a7280dd3..496c044040e 100644 --- a/stl/src/special_math.cpp +++ b/stl/src/special_math.cpp @@ -30,12 +30,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include @@ -478,8 +478,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::sph_neumann(_Pn, _Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_lgammaf( - float _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_lgammaf(float _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } @@ -487,8 +486,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_lgamma( - double _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_lgamma(double _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } @@ -496,8 +494,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_tgammaf( - float _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_tgammaf(float _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } @@ -505,8 +502,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::tgamma(_Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_tgamma( - double _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_tgamma(double _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } From e5c43d4f2b6c75b618ab2f16aed4d7cc5438eaed Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:35 -0700 Subject: [PATCH 03/85] Sort exports. --- stl/msbuild/stl_2/amd64.exports | 6 +++--- stl/msbuild/stl_2/arm64.exports | 6 +++--- stl/msbuild/stl_2/i386.exports | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/msbuild/stl_2/amd64.exports b/stl/msbuild/stl_2/amd64.exports index 23c021f319b..30746a93093 100644 --- a/stl/msbuild/stl_2/amd64.exports +++ b/stl/msbuild/stl_2/amd64.exports @@ -34,10 +34,8 @@ __std_smf_laguerre __std_smf_laguerref __std_smf_legendre __std_smf_legendref -__std_smf_lgammaf __std_smf_lgamma -__std_smf_tgammaf -__std_smf_tgamma +__std_smf_lgammaf __std_smf_riemann_zeta __std_smf_riemann_zetaf __std_smf_sph_bessel @@ -46,3 +44,5 @@ __std_smf_sph_legendre __std_smf_sph_legendref __std_smf_sph_neumann __std_smf_sph_neumannf +__std_smf_tgamma +__std_smf_tgammaf diff --git a/stl/msbuild/stl_2/arm64.exports b/stl/msbuild/stl_2/arm64.exports index 23c021f319b..30746a93093 100644 --- a/stl/msbuild/stl_2/arm64.exports +++ b/stl/msbuild/stl_2/arm64.exports @@ -34,10 +34,8 @@ __std_smf_laguerre __std_smf_laguerref __std_smf_legendre __std_smf_legendref -__std_smf_lgammaf __std_smf_lgamma -__std_smf_tgammaf -__std_smf_tgamma +__std_smf_lgammaf __std_smf_riemann_zeta __std_smf_riemann_zetaf __std_smf_sph_bessel @@ -46,3 +44,5 @@ __std_smf_sph_legendre __std_smf_sph_legendref __std_smf_sph_neumann __std_smf_sph_neumannf +__std_smf_tgamma +__std_smf_tgammaf diff --git a/stl/msbuild/stl_2/i386.exports b/stl/msbuild/stl_2/i386.exports index 571bec7b3e1..04bf566c51c 100644 --- a/stl/msbuild/stl_2/i386.exports +++ b/stl/msbuild/stl_2/i386.exports @@ -36,8 +36,6 @@ ___std_smf_legendre@12 ___std_smf_legendref@8 ___std_smf_lgamma@8 ___std_smf_lgammaf@4 -___std_smf_tgamma@8 -___std_smf_tgammaf@4 ___std_smf_riemann_zeta@8 ___std_smf_riemann_zetaf@4 ___std_smf_sph_bessel@12 @@ -46,3 +44,5 @@ ___std_smf_sph_legendre@16 ___std_smf_sph_legendref@12 ___std_smf_sph_neumann@12 ___std_smf_sph_neumannf@8 +___std_smf_tgamma@8 +___std_smf_tgammaf@4 From 4b814496298d3cfb14abb47846e078ea1a81ac7c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:36 -0700 Subject: [PATCH 04/85] cstdlib: Undo unnecessary newline edits. --- stl/inc/cstdlib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/cstdlib b/stl/inc/cstdlib index 22291d56744..b3e1ca58a12 100644 --- a/stl/inc/cstdlib +++ b/stl/inc/cstdlib @@ -6,8 +6,8 @@ #ifndef _CSTDLIB_ #define _CSTDLIB_ #include - #if _STL_COMPILER_PREPROCESSOR + #include #include From f291717dd48ba69cd8752609e5b00f0337ff9838 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:37 -0700 Subject: [PATCH 05/85] special_math.cpp: Sort definitions. --- stl/src/special_math.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/stl/src/special_math.cpp b/stl/src/special_math.cpp index 496c044040e..9e27d2e1b46 100644 --- a/stl/src/special_math.cpp +++ b/stl/src/special_math.cpp @@ -409,6 +409,22 @@ extern "C" { return _Boost_call([=] { return ::boost::math::legendre_p(_Pl, _Px); }); } +[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_lgamma(double _Px) noexcept { + if (_STD isnan(_Px)) { + return _Px; + } + + return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); +} + +[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_lgammaf(float _Px) noexcept { + if (_STD isnan(_Px)) { + return _Px; + } + + return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); +} + [[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_riemann_zeta(const double _Px) noexcept { if (_STD isnan(_Px)) { return _Px; @@ -478,23 +494,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::sph_neumann(_Pn, _Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_lgammaf(float _Px) noexcept { - if (_STD isnan(_Px)) { - return _Px; - } - - return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); -} - -[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_lgamma(double _Px) noexcept { - if (_STD isnan(_Px)) { - return _Px; - } - - return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); -} - -[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_tgammaf(float _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_tgamma(double _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } @@ -502,7 +502,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::tgamma(_Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_tgamma(double _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_tgammaf(float _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } From a5c8a04f5c9e408f381c0ddc1d8c100b3fdd20c6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:39 -0700 Subject: [PATCH 06/85] special_math.cpp: Add const to parameters. --- stl/src/special_math.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/src/special_math.cpp b/stl/src/special_math.cpp index 9e27d2e1b46..5d46518953e 100644 --- a/stl/src/special_math.cpp +++ b/stl/src/special_math.cpp @@ -409,7 +409,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::legendre_p(_Pl, _Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_lgamma(double _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_lgamma(const double _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } @@ -417,7 +417,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_lgammaf(float _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_lgammaf(const float _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } @@ -494,7 +494,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::sph_neumann(_Pn, _Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_tgamma(double _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 double __stdcall __std_smf_tgamma(const double _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } @@ -502,7 +502,7 @@ extern "C" { return _Boost_call([=] { return ::boost::math::tgamma(_Px); }); } -[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_tgammaf(float _Px) noexcept { +[[nodiscard]] _CRT_SATELLITE_2 float __stdcall __std_smf_tgammaf(const float _Px) noexcept { if (_STD isnan(_Px)) { return _Px; } From 8c474dc1710f47c469ba36a2b3d2927b7b6509b1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:40 -0700 Subject: [PATCH 07/85] special_math.cpp: [Copilot review] Add TRANSITION comments for error handling in lgamma and tgamma. --- stl/src/special_math.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stl/src/special_math.cpp b/stl/src/special_math.cpp index 5d46518953e..81ec52414da 100644 --- a/stl/src/special_math.cpp +++ b/stl/src/special_math.cpp @@ -414,6 +414,7 @@ extern "C" { return _Px; } + // TRANSITION, investigate handling C23 7.12.1 "Treatment of error conditions" and 7.12.8.3 "The lgamma functions". return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); } @@ -422,6 +423,7 @@ extern "C" { return _Px; } + // TRANSITION, investigate handling C23 7.12.1 "Treatment of error conditions" and 7.12.8.3 "The lgamma functions". return _Boost_call([=] { return ::boost::math::lgamma(_Px); }); } @@ -499,6 +501,7 @@ extern "C" { return _Px; } + // TRANSITION, investigate handling C23 7.12.1 "Treatment of error conditions" and 7.12.8.4 "The tgamma functions". return _Boost_call([=] { return ::boost::math::tgamma(_Px); }); } @@ -507,6 +510,7 @@ extern "C" { return _Px; } + // TRANSITION, investigate handling C23 7.12.1 "Treatment of error conditions" and 7.12.8.4 "The tgamma functions". return _Boost_call([=] { return ::boost::math::tgamma(_Px); }); } } // extern "C" From 2a9a5704c5819d3f9e826a0533a5ac7e6d134673 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:42 -0700 Subject: [PATCH 08/85] yvals_core.h: Cleanups. --- stl/inc/yvals_core.h | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 93646fb2683..615e2e8f279 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -331,6 +331,7 @@ // P0401R6 Providing Size Feedback In The Allocator Interface // P0429R9 // P0448R4 +// P0533R9 constexpr For And // P0627R6 unreachable() // P0798R8 Monadic Operations For optional // P0881R7 @@ -408,7 +409,10 @@ // P3142R0 Printing Blank Lines With println() // P3235R3 std::print More Types Faster With Less Memory // P3567R2 flat_meow Fixes -// P0533R9 constexpr for and + +// _HAS_CXX26 controls: +// P1383R2 More constexpr For And +// (partial implementation) // Parallel Algorithms Notes // C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. @@ -959,21 +963,19 @@ _EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC Compiler 19 #define _CONSTEXPR23 inline #endif // ^^^ inline (not constexpr) in C++20 and earlier ^^^ -// Math functions that became constexpr in C++23. Support is conditioned on whether -// -Zc:cmath- is specified. +// Math functions that became constexpr in C++23 #if _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) #define _CONSTEXPR_CMATH23 constexpr -#else // ^^^ constexpr in C++23 and later / inline (not constexpr) in C++20 and earlier vvv +#else // ^^^ constexpr in C++23 and later / inline when /Zc:cmath- opts out of constexpr, and in C++20 and earlier vvv #define _CONSTEXPR_CMATH23 inline -#endif +#endif // ^^^ inline when /Zc:cmath- opts out of constexpr, and in C++20 and earlier ^^^ -// Math functions that became constexpr in C++26. Support is conditioned on whether -// -Zc:cmath- is specified. +// Math functions that became constexpr in C++26 #if _HAS_CXX26 && defined(_MSVC_CONSTEXPR_CMATH) #define _CONSTEXPR_CMATH26 constexpr -#else // ^^^ constexpr in C++26 and later / inline (not constexpr) in C++23 and earlier vvv +#else // ^^^ constexpr in C++26 and later / inline when /Zc:cmath- opts out of constexpr, and in C++23 and earlier vvv #define _CONSTEXPR_CMATH26 inline -#endif +#endif // ^^^ inline when /Zc:cmath- opts out of constexpr, and in C++23 and earlier ^^^ // P2465R3 Standard Library Modules std And std.compat #ifdef _BUILD_STD_MODULE @@ -1696,7 +1698,6 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_common_reference_wrapper 202302L #define __cpp_lib_concepts 202207L #define __cpp_lib_constexpr_algorithms 201806L -#define __cpp_lib_constexpr_complex 201711L #define __cpp_lib_constexpr_dynamic_alloc 201907L #define __cpp_lib_constexpr_functional 201907L #define __cpp_lib_constexpr_iterator 201811L @@ -1813,12 +1814,6 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_to_underlying 202102L #define __cpp_lib_tuple_like 202207L #define __cpp_lib_unreachable 202202L - -// MSVC conditionally suppports constexpr cmath under an "opt-out" model. -// The compiler defines the macro used below to detect support. -#if defined(_MSVC_CONSTEXPR_CMATH) -#define __cpp_lib_constexpr_cmath 202202L -#endif #endif // _HAS_CXX23 // macros with language mode sensitivity @@ -1836,6 +1831,20 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_chrono 201510L // P0092R1 floor(), ceil(), round(), abs() #endif +#if 0 && _HAS_CXX26 && defined(_MSVC_CONSTEXPR_CMATH) // TRANSITION, GH-3789 +#define __cpp_lib_constexpr_cmath 202306L // P1383R2 More constexpr For And +#elif _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) +// _MSVC_CONSTEXPR_CMATH is defined when MSVC supports constexpr , but not when /Zc:cmath- opts out. +// TRANSITION, Clang and EDG lack support for constexpr . +#define __cpp_lib_constexpr_cmath 202202L // P0533R9 constexpr For And +#endif + +#if 0 && _HAS_CXX26 && defined(_MSVC_CONSTEXPR_CMATH) // TRANSITION, GH-3789 +#define __cpp_lib_constexpr_complex 202306L // P1383R2 More constexpr For And +#elif _HAS_CXX20 +#define __cpp_lib_constexpr_complex 201711L // P0415R1 constexpr For (Again) +#endif + #if _HAS_CXX23 #define __cpp_lib_constexpr_memory 202202L // P2273R3 constexpr unique_ptr #elif _HAS_CXX20 From 6cd7b38267b01ba9e712fd66e9167f785a508721 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:43 -0700 Subject: [PATCH 09/85] __msvc_stdlib.hpp: __MSVC_STDLIB_HPP needs two underscores. --- stl/inc/__msvc_stdlib.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index eda476a4a23..9b64408f345 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -3,8 +3,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifndef _MSVC_STDLIB_HPP -#define _MSVC_STDLIB_HPP +#ifndef __MSVC_STDLIB_HPP +#define __MSVC_STDLIB_HPP // Prevent later inclusions of stdlib.h from having any effect. #define _INC_STDLIB @@ -833,4 +833,4 @@ onexit_t __cdecl onexit(_In_opt_ onexit_t _Func); _CRT_END_C_HEADER _UCRT_RESTORE_CLANG_WARNINGS #pragma warning(pop) // _UCRT_DISABLED_WARNINGS -#endif // _MSVC_STDLIB_HPP +#endif // __MSVC_STDLIB_HPP From 90ac69bb3f254824ce155ece00c1598c71e25552 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:44 -0700 Subject: [PATCH 10/85] __msvc_stdlib.hpp: Remove _M_CEE_PURE logic. --- stl/inc/__msvc_stdlib.hpp | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 9b64408f345..9d84f3d848b 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -97,30 +97,11 @@ inline _onexit_m_t __clrcall _onexit_m(_onexit_t _Function) { #endif -#ifdef _M_CEE_PURE -// In pure mode, atexit is the same as atexit_m_appdomain -extern "C++" { - -#ifdef __cplusplus -[System::Security::SecurityCritical] -#endif - inline int __clrcall atexit(void(__clrcall* _Function)(void)) { - return _atexit_m_appdomain(_Function); -} - -inline _onexit_t __clrcall _onexit(_onexit_t _Function) { - return _onexit_m_appdomain(_Function); -} - -} // extern "C++" -#else int __cdecl atexit(void(__cdecl*)(void)); _onexit_t __cdecl _onexit(_In_opt_ _onexit_t _Func); -#endif int __cdecl at_quick_exit(void(__cdecl*)(void)); -#ifndef _M_CEE_PURE // a purecall handler procedure. Never returns normally typedef void(__cdecl* _purecall_handler)(void); @@ -143,17 +124,6 @@ _ACRTIMP _invalid_parameter_handler __cdecl _set_thread_local_invalid_parameter_ _In_opt_ _invalid_parameter_handler _Handler); _ACRTIMP _invalid_parameter_handler __cdecl _get_thread_local_invalid_parameter_handler(void); -#endif - - -#if defined __cplusplus && defined _M_CEE_PURE -extern "C++" { -typedef void(__clrcall* _purecall_handler)(void); -typedef _purecall_handler _purecall_handler_m; - -_MRTIMP _purecall_handler __cdecl _set_purecall_handler(_In_opt_ _purecall_handler _Handler); -} // extern "C++" -#endif #define _OUT_TO_DEFAULT 0 From 7a674c7aea06d561d6d4417e7f7fd66090ae7545 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:45 -0700 Subject: [PATCH 11/85] __msvc_stdlib.hpp: Avoid macro-like params `_X`, `_A1`, `_A2`. --- stl/inc/__msvc_stdlib.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 9d84f3d848b..3a60fe642f2 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -281,20 +281,21 @@ _ACRTIMP errno_t __cdecl rand_s(_Out_ unsigned int* _RandomValue); #endif extern "C++" { -[[nodiscard]] constexpr long abs(long const _X) noexcept /* strengthened */ { - return labs(_X); +[[nodiscard]] constexpr long abs(long const _Xx) noexcept /* strengthened */ { + return labs(_Xx); } -[[nodiscard]] constexpr long long abs(long long const _X) noexcept /* strengthened */ { - return llabs(_X); +[[nodiscard]] constexpr long long abs(long long const _Xx) noexcept /* strengthened */ { + return llabs(_Xx); } -[[nodiscard]] constexpr ldiv_t div(long const _A1, long const _A2) noexcept /* strengthened */ { - return ldiv(_A1, _A2); +[[nodiscard]] constexpr ldiv_t div(long const _Numerator, long const _Denominator) noexcept /* strengthened */ { + return ldiv(_Numerator, _Denominator); } -[[nodiscard]] constexpr lldiv_t div(long long const _A1, long long const _A2) noexcept /* strengthened */ { - return lldiv(_A1, _A2); +[[nodiscard]] constexpr lldiv_t div(long long const _Numerator, long long const _Denominator) noexcept +/* strengthened */ { + return lldiv(_Numerator, _Denominator); } } From 38d94b8f209565bbdf82939e2712e8dde4b33209 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:46 -0700 Subject: [PATCH 12/85] __msvc_stdlib.hpp: This must be a core header because cstdlib is core. --- stl/inc/__msvc_stdlib.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 3a60fe642f2..51b92218685 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -1,4 +1,4 @@ -// __msvc_stdlib.hpp internal header +// __msvc_stdlib.hpp internal header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception From 85322ac9439136ce14c85009f4f333ae105e5cf9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:46 -0700 Subject: [PATCH 13/85] __msvc_stdlib.hpp: Drop `extern "C"` block, the whole header is `_CRT_BEGIN_C_HEADER`. --- stl/inc/__msvc_stdlib.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 51b92218685..94ec432a4f3 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -200,14 +200,12 @@ typedef struct _lldiv_t { long long rem; } lldiv_t; -extern "C" { _Check_return_ constexpr int __cdecl abs(_In_ int) noexcept; _Check_return_ constexpr long __cdecl labs(_In_ long) noexcept; _Check_return_ constexpr long long __cdecl llabs(_In_ long long) noexcept; _Check_return_ constexpr div_t __cdecl div(_In_ int, _In_ int) noexcept; _Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long, _In_ long) noexcept; _Check_return_ constexpr lldiv_t __cdecl lldiv(_In_ long long, _In_ long long) noexcept; -} #pragma warning(push) #pragma warning(disable : 4163) // 'meow' not available as an intrinsic function From 2787e02519728be2e10e270da532368c69d467c5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:47 -0700 Subject: [PATCH 14/85] __msvc_stdlib.hpp: Comment the end of extern "C++". --- stl/inc/__msvc_stdlib.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 94ec432a4f3..9ae28b1da22 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -295,7 +295,7 @@ extern "C++" { /* strengthened */ { return lldiv(_Numerator, _Denominator); } -} +} // extern "C++" // Structs used to fool the compiler into not generating floating point // instructions when copying and pushing [long] double values From 2ed01fa798fd5e604b756a657dd79e2844142bd0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:48 -0700 Subject: [PATCH 15/85] __msvc_stdlib.hpp: Comment how this file was derived, restore comments to reduce divergence. --- stl/inc/__msvc_stdlib.hpp | 62 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 9ae28b1da22..6e14f6a2698 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -3,6 +3,14 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// This file was derived from in the Windows 11 SDK (10.0.28000), with some alterations: +// * Formatted with clang-format. +// * Removed _M_CEE_PURE checks (never defined here). +// * Removed __cplusplus checks (always defined here). +// * Changed code to support the MSVC frontend intercepting inclusions of . +// * Changed code for C++23's P0533R9 "constexpr For And ". +// Avoid introducing further unnecessary divergence between and this file. + #ifndef __MSVC_STDLIB_HPP #define __MSVC_STDLIB_HPP @@ -26,13 +34,22 @@ _CRT_BEGIN_C_HEADER #define _countof __crt_countof #endif + // Minimum and maximum macros #define __max(a, b) (((a) > (b)) ? (a) : (b)) #define __min(a, b) (((a) < (b)) ? (a) : (b)) + _ACRTIMP void __cdecl _swab(_Inout_updates_(_SizeInBytes) _Post_readable_size_(_SizeInBytes) char* _Buf1, _Inout_updates_(_SizeInBytes) _Post_readable_size_(_SizeInBytes) char* _Buf2, _In_ int _SizeInBytes); + +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Exit and Abort +// +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// Argument values for exit() #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 @@ -102,6 +119,12 @@ _onexit_t __cdecl _onexit(_In_opt_ _onexit_t _Func); int __cdecl at_quick_exit(void(__cdecl*)(void)); + +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Global State (errno, global handlers, etc.) +// +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // a purecall handler procedure. Never returns normally typedef void(__cdecl* _purecall_handler)(void); @@ -126,6 +149,7 @@ _ACRTIMP _invalid_parameter_handler __cdecl _set_thread_local_invalid_parameter_ _ACRTIMP _invalid_parameter_handler __cdecl _get_thread_local_invalid_parameter_handler(void); +// Argument values for _set_error_mode(). #define _OUT_TO_DEFAULT 0 #define _OUT_TO_STDERR 1 #define _OUT_TO_MSGBOX 2 @@ -185,6 +209,12 @@ _ACRTIMP errno_t __cdecl _set_fmode(_In_ int _Mode); _ACRTIMP errno_t __cdecl _get_fmode(_Out_ int* _PMode); + +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Math +// +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ typedef struct _div_t { int quot; int rem; @@ -278,6 +308,7 @@ _Check_return_ _ACRTIMP int __cdecl rand(void); _ACRTIMP errno_t __cdecl rand_s(_Out_ unsigned int* _RandomValue); #endif + extern "C++" { [[nodiscard]] constexpr long abs(long const _Xx) noexcept /* strengthened */ { return labs(_Xx); @@ -297,6 +328,7 @@ extern "C++" { } } // extern "C++" + // Structs used to fool the compiler into not generating floating point // instructions when copying and pushing [long] double values #define _CRT_DOUBLE_DEC @@ -347,6 +379,12 @@ typedef struct { } _LDBL12; #pragma pack(pop) + +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Narrow String to Number Conversions +// +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ _Check_return_ _ACRTIMP double __cdecl atof(_In_z_ char const* _String); _Check_return_ _CRT_JIT_INTRINSIC _ACRTIMP int __cdecl atoi(_In_z_ char const* _String); _Check_return_ _ACRTIMP long __cdecl atol(_In_z_ char const* _String); @@ -425,6 +463,12 @@ _Check_return_ _ACRTIMP unsigned __int64 __cdecl _strtoui64( _Check_return_ _ACRTIMP unsigned __int64 __cdecl _strtoui64_l( _In_z_ char const* _String, _Out_opt_ _Deref_post_z_ char** _EndPtr, _In_ int _Radix, _In_opt_ _locale_t _Locale); + +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Number to Narrow String Conversions +// +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ _Success_(return == 0) _Check_return_opt_ _ACRTIMP errno_t __cdecl _itoa_s( _In_ int _Value, _Out_writes_z_(_BufferCount) char* _Buffer, _In_ size_t _BufferCount, _In_ int _Radix); @@ -501,6 +545,12 @@ __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_2( _CRT_INSECURE_DEPRECATE(_gcvt_s) _ACRTIMP char* __cdecl _gcvt(_In_ double _Value, _In_ int _DigitCount, _Pre_notnull_ _Post_z_ char* _Buffer); + +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Multibyte String Operations and Conversions +// +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Maximum number of bytes in multi-byte character in the current locale // (also defined in ctype.h). #ifndef MB_CUR_MAX @@ -609,6 +659,12 @@ __DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_3_SIZE_EX(_ACRTIMP, _wcstombs_l, _wcstomb _Out_writes_(_MaxCount), char, _Dest, _In_z_ wchar_t const*, _Source, _In_ size_t, _MaxCount, _In_opt_ _locale_t, _Locale) + +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Path Manipulation +// +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Sizes for buffers used by the _makepath() and _splitpath() functions. // note that the sizes include space for 0-terminator #define _MAX_PATH 260 // max. length of full pathname @@ -747,6 +803,12 @@ _DCRTIMP void __cdecl _sleep(_In_ unsigned long _Duration); #endif // _CRT_FUNCTIONS_REQUIRED + +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Non-ANSI Names for Compatibility +// +//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ #if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES #ifndef __cplusplus From ca2df3d4e3b8921ab546d1dfc0f641e2690d69c8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:49 -0700 Subject: [PATCH 16/85] __msvc_stdlib.hpp: Add and use `_CONSTEXPR_CSTDLIB23`. --- stl/inc/__msvc_stdlib.hpp | 48 +++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 6e14f6a2698..ddc503755b0 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -14,7 +14,7 @@ #ifndef __MSVC_STDLIB_HPP #define __MSVC_STDLIB_HPP -// Prevent later inclusions of stdlib.h from having any effect. +// Prevent later inclusions of from having any effect. #define _INC_STDLIB #include @@ -230,12 +230,19 @@ typedef struct _lldiv_t { long long rem; } lldiv_t; -_Check_return_ constexpr int __cdecl abs(_In_ int) noexcept; -_Check_return_ constexpr long __cdecl labs(_In_ long) noexcept; -_Check_return_ constexpr long long __cdecl llabs(_In_ long long) noexcept; -_Check_return_ constexpr div_t __cdecl div(_In_ int, _In_ int) noexcept; -_Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long, _In_ long) noexcept; -_Check_return_ constexpr lldiv_t __cdecl lldiv(_In_ long long, _In_ long long) noexcept; +// stdlib functions that became constexpr in C++23 +#if _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) +#define _CONSTEXPR_CSTDLIB23 constexpr +#else // ^^^ constexpr in C++23 and later / inline when /Zc:cmath- opts out of constexpr, and in C++20 and earlier vvv +#define _CONSTEXPR_CSTDLIB23 inline +#endif // ^^^ inline when /Zc:cmath- opts out of constexpr, and in C++20 and earlier ^^^ + +_Check_return_ _CONSTEXPR_CSTDLIB23 int __cdecl abs(_In_ int) noexcept; +_Check_return_ _CONSTEXPR_CSTDLIB23 long __cdecl labs(_In_ long) noexcept; +_Check_return_ _CONSTEXPR_CSTDLIB23 long long __cdecl llabs(_In_ long long) noexcept; +_Check_return_ _CONSTEXPR_CSTDLIB23 div_t __cdecl div(_In_ int, _In_ int) noexcept; +_Check_return_ _CONSTEXPR_CSTDLIB23 ldiv_t __cdecl ldiv(_In_ long, _In_ long) noexcept; +_Check_return_ _CONSTEXPR_CSTDLIB23 lldiv_t __cdecl lldiv(_In_ long long, _In_ long long) noexcept; #pragma warning(push) #pragma warning(disable : 4163) // 'meow' not available as an intrinsic function @@ -243,31 +250,31 @@ _Check_return_ constexpr lldiv_t __cdecl lldiv(_In_ long long, _In_ long long) n #pragma function(div, ldiv, lldiv) #pragma warning(pop) -[[nodiscard]] _Check_return_ constexpr int __cdecl abs(_In_ int _Xx) noexcept /* strengthened */ { +[[nodiscard]] _Check_return_ _CONSTEXPR_CSTDLIB23 int __cdecl abs(_In_ int _Xx) noexcept /* strengthened */ { return _Xx >= 0 ? _Xx : -_Xx; } -[[nodiscard]] _Check_return_ constexpr long __cdecl labs(_In_ long _Xx) noexcept /* strengthened */ { +[[nodiscard]] _Check_return_ _CONSTEXPR_CSTDLIB23 long __cdecl labs(_In_ long _Xx) noexcept /* strengthened */ { return _Xx >= 0 ? _Xx : -_Xx; } -[[nodiscard]] _Check_return_ constexpr long long __cdecl llabs(_In_ long long _Xx) noexcept /* strengthened */ { +[[nodiscard]] _Check_return_ _CONSTEXPR_CSTDLIB23 long long __cdecl llabs(_In_ long long _Xx) noexcept +/* strengthened */ { return _Xx >= 0 ? _Xx : -_Xx; } -[[nodiscard]] _Check_return_ constexpr div_t __cdecl div(_In_ int _Numerator, _In_ int _Denominator) noexcept +[[nodiscard]] _Check_return_ _CONSTEXPR_CSTDLIB23 div_t __cdecl div(_In_ int _Numerator, _In_ int _Denominator) noexcept /* strengthened */ { return {_Numerator / _Denominator, _Numerator % _Denominator}; } -[[nodiscard]] _Check_return_ constexpr ldiv_t __cdecl ldiv(_In_ long _Numerator, _In_ long _Denominator) noexcept -/* strengthened */ { +[[nodiscard]] _Check_return_ _CONSTEXPR_CSTDLIB23 ldiv_t __cdecl ldiv( + _In_ long _Numerator, _In_ long _Denominator) noexcept /* strengthened */ { return {_Numerator / _Denominator, _Numerator % _Denominator}; } -[[nodiscard]] _Check_return_ constexpr lldiv_t __cdecl lldiv( - _In_ long long _Numerator, _In_ long long _Denominator) noexcept -/* strengthened */ { +[[nodiscard]] _Check_return_ _CONSTEXPR_CSTDLIB23 lldiv_t __cdecl lldiv( + _In_ long long _Numerator, _In_ long long _Denominator) noexcept /* strengthened */ { return {_Numerator / _Denominator, _Numerator % _Denominator}; } @@ -310,19 +317,20 @@ _ACRTIMP errno_t __cdecl rand_s(_Out_ unsigned int* _RandomValue); extern "C++" { -[[nodiscard]] constexpr long abs(long const _Xx) noexcept /* strengthened */ { +[[nodiscard]] _CONSTEXPR_CSTDLIB23 long abs(long const _Xx) noexcept /* strengthened */ { return labs(_Xx); } -[[nodiscard]] constexpr long long abs(long long const _Xx) noexcept /* strengthened */ { +[[nodiscard]] _CONSTEXPR_CSTDLIB23 long long abs(long long const _Xx) noexcept /* strengthened */ { return llabs(_Xx); } -[[nodiscard]] constexpr ldiv_t div(long const _Numerator, long const _Denominator) noexcept /* strengthened */ { +[[nodiscard]] _CONSTEXPR_CSTDLIB23 ldiv_t div(long const _Numerator, long const _Denominator) noexcept +/* strengthened */ { return ldiv(_Numerator, _Denominator); } -[[nodiscard]] constexpr lldiv_t div(long long const _Numerator, long long const _Denominator) noexcept +[[nodiscard]] _CONSTEXPR_CSTDLIB23 lldiv_t div(long long const _Numerator, long long const _Denominator) noexcept /* strengthened */ { return lldiv(_Numerator, _Denominator); } From dbdaadeb6f0fd7d5336d22d827bfd3930fd37608 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:50 -0700 Subject: [PATCH 17/85] __msvc_math.hpp: Change comment about atan2 underflow to be permanent. --- stl/inc/__msvc_math.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 0229528fd9a..87041f82d37 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -572,7 +572,7 @@ _NODISCARD _CONSTEXPR_CMATH23 long double remquol(long double _Xx0, long double return __builtin_remquol(_Xx0, _Xx1, _Xx2); } -// TRANSITION: Preserve the sign of zero when atan2 underflows. +// Preserve the sign of zero when atan2 underflows. // __builtin_atan2 can return +0 for tiny negative results. _NODISCARD _CONSTEXPR_CMATH26 float atan2f(float _Xx0, float _Xx1) noexcept /* strengthened */ { float _Result = static_cast(__builtin_atan2f(_Xx0, _Xx1)); From 5ddf29ff5c2fcc117ad6caaf2afecbed21f37506 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:51 -0700 Subject: [PATCH 18/85] __msvc_math.hpp: Adjust push/pop to follow the usual pattern. --- stl/inc/__msvc_math.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 87041f82d37..00b01d24812 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -26,10 +26,12 @@ #if _STL_COMPILER_PREPROCESSOR #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) -#pragma warning(disable : _STL_DISABLED_WARNINGS 4163) // 'meow' not available as an intrinsic function +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") +#undef new -_STL_DISABLE_CLANG_WARNINGS +#pragma warning(disable : 4163) // 'meow' not available as an intrinsic function #define _STL_DEF_FUNC1(specs, name, ret, fptype) \ extern "C" _NODISCARD specs ret name(fptype _Xx) noexcept /* strengthened */ { \ @@ -669,8 +671,8 @@ _NODISCARD double yn(int, double); #undef _STL_DECLARE_FAMILY1 #undef _CONSTEXPR_CMATH26_NYI -_STL_RESTORE_CLANG_WARNINGS #pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #endif // _STL_COMPILER_PREPROCESSOR From 4c0ae561c46b84e85fe98904b409fa18f7ded63c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:52 -0700 Subject: [PATCH 19/85] __msvc_math.hpp: For exp2, `_STL_DECLARE_FAMILY1` should be paired with `_CONSTEXPR_CMATH26_NYI`. --- stl/inc/__msvc_math.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 00b01d24812..db3d077e060 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -302,7 +302,7 @@ _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, cosh) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erf) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erfc) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, exp) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26, exp2) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, exp2) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, expm1) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, hypot) _STL_DEF_FAMILY1(inline, nearbyint) From 14b2009ac45825b27a8e2031ee6879e87e67f29a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:52 -0700 Subject: [PATCH 20/85] __msvc_math.hpp: Make the whole header extern "C" by default, move the predicates within extern "C++". --- stl/inc/__msvc_math.hpp | 83 +++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 45 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index db3d077e060..93d1287f3d2 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -33,35 +33,37 @@ _STL_DISABLE_CLANG_WARNINGS #pragma warning(disable : 4163) // 'meow' not available as an intrinsic function -#define _STL_DEF_FUNC1(specs, name, ret, fptype) \ - extern "C" _NODISCARD specs ret name(fptype _Xx) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx); \ +extern "C" { + +#define _STL_DEF_FUNC1(specs, name, ret, fptype) \ + _NODISCARD specs ret name(fptype _Xx) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx); \ } -#define _STL_DEF_FUNC2(specs, name, ret, fptype) \ - extern "C" _NODISCARD specs ret name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx0, _Xx1); \ +#define _STL_DEF_FUNC2(specs, name, ret, fptype) \ + _NODISCARD specs ret name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx0, _Xx1); \ } -#define _STL_DEF_FUNC3(specs, name, ret, fptype) \ - extern "C" _NODISCARD specs ret name(fptype _Xx0, fptype _Xx1, fptype _Xx2) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx0, _Xx1, _Xx2); \ +#define _STL_DEF_FUNC3(specs, name, ret, fptype) \ + _NODISCARD specs ret name(fptype _Xx0, fptype _Xx1, fptype _Xx2) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx0, _Xx1, _Xx2); \ } // `long double` and `double` are the same width on MSVC, so `long double` // variants of math functions forward to the `long` variants. -#define _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) \ - extern "C" _NODISCARD specs long double name##l(long double _Xx0) noexcept /* strengthened */ { \ - return name(static_cast(_Xx0)); \ +#define _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) \ + _NODISCARD specs long double name##l(long double _Xx0) noexcept /* strengthened */ { \ + return name(static_cast(_Xx0)); \ } -#define _STL_DEF_LDOUBLE_FORWARD_FUNC2(specs, name) \ - extern "C" _NODISCARD specs long double name##l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { \ - return name(static_cast(_Xx0), static_cast(_Xx1)); \ +#define _STL_DEF_LDOUBLE_FORWARD_FUNC2(specs, name) \ + _NODISCARD specs long double name##l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { \ + return name(static_cast(_Xx0), static_cast(_Xx1)); \ } #define _STL_DEF_LDOUBLE_FORWARD_FUNC3(specs, name) \ - extern "C" _NODISCARD specs long double name##l( \ + _NODISCARD specs long double name##l( \ long double _Xx0, long double _Xx1, long double _Xx2) noexcept /* strengthened */ { \ return name(static_cast(_Xx0), static_cast(_Xx1), static_cast(_Xx2)); \ } @@ -69,9 +71,9 @@ _STL_DISABLE_CLANG_WARNINGS // N.B. Declarations stamped out by these macros are not noexcept because they // are intended to match the definitions in the UCRT, which are not themselves // noexcept. -#define _STL_DECLARE_FUNC1(specs, name, ret, fptype) extern "C" _NODISCARD specs ret name(fptype); +#define _STL_DECLARE_FUNC1(specs, name, ret, fptype) _NODISCARD specs ret name(fptype); -#define _STL_DECLARE_FUNC2(specs, name, ret, fptype) extern "C" _NODISCARD specs ret name(fptype, fptype); +#define _STL_DECLARE_FUNC2(specs, name, ret, fptype) _NODISCARD specs ret name(fptype, fptype); // Defines three non-overloaded functions with signature `fp-type(fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, @@ -189,20 +191,17 @@ using double_t = double; #define HUGE_VALL (__builtin_infl()) #define NAN (__builtin_nanf("")) -extern "C" { // The nan family of functions is not routed to builtins because the builtins // require a string literal argument and so cannot uphold the interface of // these functions. _NODISCARD float nanf(const char*); _NODISCARD double nan(const char*); _NODISCARD long double nanl(const char*); -} // Under /Oi (implied by /O2), MSVC treats the following functions as intrinsics that // cannot be redefined. We use #pragma function to instruct MSVC to treat them as regular // functions that can be defined, but we first need to declare the function before we can // do so. -extern "C" { _NODISCARD _CONSTEXPR_CMATH23 float ceilf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH23 double ceil(double) noexcept; _NODISCARD _CONSTEXPR_CMATH23 double fabs(double) noexcept; @@ -245,7 +244,6 @@ _NODISCARD _CONSTEXPR_CMATH26 double tan(double) noexcept; _NODISCARD _CONSTEXPR_CMATH23 float fmaf(float, float, float) noexcept; _NODISCARD _CONSTEXPR_CMATH23 double fma(double, double, double) noexcept; _NODISCARD _CONSTEXPR_CMATH23 long double fmal(long double, long double, long double) noexcept; -} #pragma function(acosf, acos) #pragma function(asinf, asin) @@ -283,13 +281,6 @@ _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmax) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmin) _STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, lround, long int) _STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, llround, long long) -_STL_DEF_PREDICATE_FAMILY1(signbit, __builtin_signbit) -_STL_DEF_PREDICATE_FAMILY2(isgreater, __builtin_isgreater) -_STL_DEF_PREDICATE_FAMILY2(isless, __builtin_isless) -_STL_DEF_PREDICATE_FAMILY2(islessequal, __builtin_islessequal) -_STL_DEF_PREDICATE_FAMILY2(islessgreater, __builtin_islessgreater) -_STL_DEF_PREDICATE_FAMILY2(isgreaterequal, __builtin_isgreaterequal) -_STL_DEF_PREDICATE_FAMILY2(isunordered, __builtin_isunordered) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, acos) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, acosh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, asin) @@ -307,7 +298,6 @@ _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, expm1) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, hypot) _STL_DEF_FAMILY1(inline, nearbyint) -extern "C" { // libc does not yet implement lgamma or tgamma. Polyfilling with the UCRT's // implementation pulls in the UCRT's fma, which results in linker errors due // to our conflicting definition. Instead, we prearranged for implementations @@ -322,29 +312,28 @@ _NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_lgammaf(float) noexcep _NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_lgamma(double) noexcept; _NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_tgammaf(float) noexcept; _NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_tgamma(double) noexcept; -} -extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI float lgammaf(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI float lgammaf(float _Xx) noexcept /* strengthened */ { return __std_smf_lgammaf(_Xx); } -extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI double lgamma(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI double lgamma(double _Xx) noexcept /* strengthened */ { return __std_smf_lgamma(_Xx); } -extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI long double lgammal(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI long double lgammal(long double _Xx) noexcept /* strengthened */ { return __std_smf_lgamma(static_cast(_Xx)); } -extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI float tgammaf(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI float tgammaf(float _Xx) noexcept /* strengthened */ { return __std_smf_tgammaf(_Xx); } -extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI double tgamma(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI double tgamma(double _Xx) noexcept /* strengthened */ { return __std_smf_tgamma(_Xx); } -extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI long double tgammal(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI long double tgammal(long double _Xx) noexcept /* strengthened */ { return __std_smf_tgamma(static_cast(_Xx)); } @@ -363,22 +352,20 @@ _STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) // The UCRT defines the following functions on x86 as inline functions that // forward to their double siblings, so forward-declaring them without defining // them does not a successful polyfill make. -extern "C" { #pragma function(coshf, cosh, coshl) _NODISCARD _CONSTEXPR_CMATH26_NYI float coshf(float _Xx) { return __builtin_coshf(_Xx); } #pragma function(sinhf, sinh, sinhl) -extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI float sinhf(float _Xx) { +_NODISCARD _CONSTEXPR_CMATH26_NYI float sinhf(float _Xx) { return __builtin_sinhf(_Xx); } #pragma function(tanhf, tanh, tanhl) -extern "C" _NODISCARD _CONSTEXPR_CMATH26_NYI float tanhf(float _Xx) { +_NODISCARD _CONSTEXPR_CMATH26_NYI float tanhf(float _Xx) { return __builtin_tanhf(_Xx); } -} extern "C++" { _NODISCARD _CONSTEXPR_CMATH23 int fpclassify(float _Xx) noexcept /* strengthened */ { @@ -441,6 +428,14 @@ _NODISCARD _CONSTEXPR_CMATH23 bool isnormal(long double _Xx) noexcept /* strengt return fpclassify(_Xx) == FP_NORMAL; } +_STL_DEF_PREDICATE_FAMILY1(signbit, __builtin_signbit) +_STL_DEF_PREDICATE_FAMILY2(isgreater, __builtin_isgreater) +_STL_DEF_PREDICATE_FAMILY2(isgreaterequal, __builtin_isgreaterequal) +_STL_DEF_PREDICATE_FAMILY2(isless, __builtin_isless) +_STL_DEF_PREDICATE_FAMILY2(islessequal, __builtin_islessequal) +_STL_DEF_PREDICATE_FAMILY2(islessgreater, __builtin_islessgreater) +_STL_DEF_PREDICATE_FAMILY2(isunordered, __builtin_isunordered) + _NODISCARD _CONSTEXPR_CMATH23 float nexttowardf(float _Xx0, long double _Xx1) noexcept /* strengthened */ { return __builtin_nexttowardf(_Xx0, _Xx1); } @@ -631,26 +626,22 @@ _NODISCARD _CONSTEXPR_CMATH23 bool isunordered(_Ty1 _X0, _Ty2 _X1) noexcept /* s } } // extern "C++" -extern "C" { _NODISCARD double _j0(double); _NODISCARD double _j1(double); _NODISCARD double _jn(int, double); _NODISCARD double _y0(double); _NODISCARD double _y1(double); _NODISCARD double _yn(int, double); -} #if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES // These functions are included in the Open Group Standard Base Specifications. -extern "C" { _NODISCARD double j0(double); _NODISCARD double j1(double); _NODISCARD double jn(int, double); _NODISCARD double y0(double); _NODISCARD double y1(double); _NODISCARD double yn(int, double); -} #endif // defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES @@ -671,6 +662,8 @@ _NODISCARD double yn(int, double); #undef _STL_DECLARE_FAMILY1 #undef _CONSTEXPR_CMATH26_NYI +} // extern "C" + #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) From 50418022b95554956944945d4a46348be6d8f3ea Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:53 -0700 Subject: [PATCH 21/85] __msvc_math.hpp: Fix overly-large extern "C++" scope: only the overloaded classification/comparison functions need this. --- stl/inc/__msvc_math.hpp | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 93d1287f3d2..c05d8942373 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -436,6 +436,37 @@ _STL_DEF_PREDICATE_FAMILY2(islessequal, __builtin_islessequal) _STL_DEF_PREDICATE_FAMILY2(islessgreater, __builtin_islessgreater) _STL_DEF_PREDICATE_FAMILY2(isunordered, __builtin_isunordered) +template +_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return isgreater(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return isgreaterequal(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool isless(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return isless(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return islessequal(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return islessgreater(static_cast(_X0), static_cast(_X1)); +} + +template +_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { + return isunordered(static_cast(_X0), static_cast(_X1)); +} +} // extern "C++" + _NODISCARD _CONSTEXPR_CMATH23 float nexttowardf(float _Xx0, long double _Xx1) noexcept /* strengthened */ { return __builtin_nexttowardf(_Xx0, _Xx1); } @@ -595,37 +626,6 @@ _NODISCARD _CONSTEXPR_CMATH26 long double atan2l(long double _Xx0, long double _ return _Result; } -template -_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return isgreater(static_cast(_X0), static_cast(_X1)); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return isgreaterequal(static_cast(_X0), static_cast(_X1)); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool isless(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return isless(static_cast(_X0), static_cast(_X1)); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return islessequal(static_cast(_X0), static_cast(_X1)); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return islessgreater(static_cast(_X0), static_cast(_X1)); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return isunordered(static_cast(_X0), static_cast(_X1)); -} -} // extern "C++" - _NODISCARD double _j0(double); _NODISCARD double _j1(double); _NODISCARD double _jn(int, double); From 0f0c21cb95cc79322145ff910d93932f5cdb0367 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:54 -0700 Subject: [PATCH 22/85] __msvc_math.hpp: Remove stray semicolon. --- stl/inc/__msvc_math.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index c05d8942373..019c834040e 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -346,7 +346,7 @@ _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sin) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, sinh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sqrt) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, tan) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, tanh); +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, tanh) _STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) // The UCRT defines the following functions on x86 as inline functions that From ecab06593a6369a866759995e9fdcc411c82f4ab Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:55 -0700 Subject: [PATCH 23/85] __msvc_math.hpp: Use macros to define ilogb, lrint, llrint, rint. --- stl/inc/__msvc_math.hpp | 50 ++++------------------------------------- 1 file changed, 4 insertions(+), 46 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 019c834040e..939a24ffe16 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -491,17 +491,7 @@ _NODISCARD _CONSTEXPR_CMATH23 long double frexpl(long double _Xx0, int* _Xx1) no return __builtin_frexpl(_Xx0, _Xx1); } -_NODISCARD _CONSTEXPR_CMATH23 int ilogbf(float _Xx) noexcept /* strengthened */ { - return __builtin_ilogbf(_Xx); -} - -_NODISCARD _CONSTEXPR_CMATH23 int ilogb(double _Xx) noexcept /* strengthened */ { - return __builtin_ilogb(_Xx); -} - -_NODISCARD _CONSTEXPR_CMATH23 int ilogbl(long double _Xx) noexcept /* strengthened */ { - return __builtin_ilogbl(_Xx); -} +_STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) _NODISCARD _CONSTEXPR_CMATH23 float ldexpf(float _Xx0, int _Xx1) noexcept /* strengthened */ { return __builtin_ldexpf(_Xx0, _Xx1); @@ -527,41 +517,9 @@ _NODISCARD _CONSTEXPR_CMATH23 long double modfl(long double _Xx0, long double* _ return __builtin_modfl(_Xx0, _Xx1); } -_NODISCARD inline long lrintf(float _Xx0) noexcept /* strengthened */ { - return __builtin_lrintf(_Xx0); -} - -_NODISCARD inline long lrint(double _Xx0) noexcept /* strengthened */ { - return __builtin_lrint(_Xx0); -} - -_NODISCARD inline long lrintl(long double _Xx0) noexcept /* strengthened */ { - return __builtin_lrintl(_Xx0); -} - -_NODISCARD inline long long llrintf(float _Xx0) noexcept /* strengthened */ { - return __builtin_llrintf(_Xx0); -} - -_NODISCARD inline long long llrint(double _Xx0) noexcept /* strengthened */ { - return __builtin_llrint(_Xx0); -} - -_NODISCARD inline long long llrintl(long double _Xx0) noexcept /* strengthened */ { - return __builtin_llrintl(_Xx0); -} - -_NODISCARD inline float rintf(float _Xx0) noexcept /* strengthened */ { - return __builtin_rintf(_Xx0); -} - -_NODISCARD inline double rint(double _Xx0) noexcept /* strengthened */ { - return __builtin_rint(_Xx0); -} - -_NODISCARD inline long double rintl(long double _Xx0) noexcept /* strengthened */ { - return __builtin_rintl(_Xx0); -} +_STL_DEF_ROUNDING_FAMILY1(inline, lrint, long) +_STL_DEF_ROUNDING_FAMILY1(inline, llrint, long long) +_STL_DEF_FAMILY1(inline, rint) _NODISCARD _CONSTEXPR_CMATH23 float scalbnf(float _Xx0, int _Xx1) noexcept /* strengthened */ { return __builtin_scalbnf(_Xx0, _Xx1); From 940178c0823b7c68f6955d7d8f08e7ae70aef61e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:56 -0700 Subject: [PATCH 24/85] __msvc_math.hpp: Expand the predicate macros, clean up their templates. --- stl/inc/__msvc_math.hpp | 140 +++++++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 51 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 939a24ffe16..c7a8a7d898e 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -99,30 +99,6 @@ extern "C" { _STL_DEF_FUNC3(specs, name, double, double) \ _STL_DEF_LDOUBLE_FORWARD_FUNC3(specs, name) -// N.B. the static_cast in the body of the predicate functions is because the -// builtins return int. -#define _STL_DEF_PREDICATE1(specs, name, builtin, fptype) \ - _NODISCARD specs bool name(fptype _Xx) noexcept /* strengthened */ { \ - return static_cast(builtin(_Xx)); \ - } - -#define _STL_DEF_PREDICATE2(specs, name, builtin, fptype) \ - _NODISCARD specs bool name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ - return static_cast(builtin(_Xx0, _Xx1)); \ - } - -// Defines three overloaded functions with signature `bool(fp-type)`. -#define _STL_DEF_PREDICATE_FAMILY1(name, builtin) \ - _STL_DEF_PREDICATE1(_CONSTEXPR_CMATH23, name, builtin##f, float) \ - _STL_DEF_PREDICATE1(_CONSTEXPR_CMATH23, name, builtin, double) \ - _STL_DEF_PREDICATE1(_CONSTEXPR_CMATH23, name, builtin##l, long double) - -// Defines three overloaded functions with signature `bool(fp-type, fp-type)`. -#define _STL_DEF_PREDICATE_FAMILY2(name, builtin) \ - _STL_DEF_PREDICATE2(_CONSTEXPR_CMATH23, name, builtin##f, float) \ - _STL_DEF_PREDICATE2(_CONSTEXPR_CMATH23, name, builtin, double) \ - _STL_DEF_PREDICATE2(_CONSTEXPR_CMATH23, name, builtin##l, long double) - // Defines three non-overloaded functions with signature `int-type(fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, // respectively. @@ -428,42 +404,106 @@ _NODISCARD _CONSTEXPR_CMATH23 bool isnormal(long double _Xx) noexcept /* strengt return fpclassify(_Xx) == FP_NORMAL; } -_STL_DEF_PREDICATE_FAMILY1(signbit, __builtin_signbit) -_STL_DEF_PREDICATE_FAMILY2(isgreater, __builtin_isgreater) -_STL_DEF_PREDICATE_FAMILY2(isgreaterequal, __builtin_isgreaterequal) -_STL_DEF_PREDICATE_FAMILY2(isless, __builtin_isless) -_STL_DEF_PREDICATE_FAMILY2(islessequal, __builtin_islessequal) -_STL_DEF_PREDICATE_FAMILY2(islessgreater, __builtin_islessgreater) -_STL_DEF_PREDICATE_FAMILY2(isunordered, __builtin_isunordered) +// N.B. static_cast is used when the builtin returns int. + +_NODISCARD _CONSTEXPR_CMATH23 bool signbit(float _Xx) noexcept /* strengthened */ { + return static_cast(__builtin_signbitf(_Xx)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool signbit(double _Xx) noexcept /* strengthened */ { + return static_cast(__builtin_signbit(_Xx)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool signbit(long double _Xx) noexcept /* strengthened */ { + return static_cast(__builtin_signbitl(_Xx)); +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(float _Xx0, float _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreaterf(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(double _Xx0, double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreater(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreaterl(_Xx0, _Xx1)); +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(float _Xx0, float _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreaterequalf(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(double _Xx0, double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreaterequal(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreaterequall(_Xx0, _Xx1)); +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isless(float _Xx0, float _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessf(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool isless(double _Xx0, double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isless(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool isless(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessl(_Xx0, _Xx1)); +} + +_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(float _Xx0, float _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessequalf(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(double _Xx0, double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessequal(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessequall(_Xx0, _Xx1)); +} + +_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(float _Xx0, float _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessgreaterf(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(double _Xx0, double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessgreater(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessgreaterl(_Xx0, _Xx1)); +} + +_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(float _Xx0, float _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isunorderedf(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(double _Xx0, double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isunordered(_Xx0, _Xx1)); +} +_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isunorderedl(_Xx0, _Xx1)); +} -template -_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return isgreater(static_cast(_X0), static_cast(_X1)); +template +_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreater(static_cast(_Xx0), static_cast(_Xx1))); } -template -_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return isgreaterequal(static_cast(_X0), static_cast(_X1)); +template +_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreaterequal(static_cast(_Xx0), static_cast(_Xx1))); } -template -_NODISCARD _CONSTEXPR_CMATH23 bool isless(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return isless(static_cast(_X0), static_cast(_X1)); +template +_NODISCARD _CONSTEXPR_CMATH23 bool isless(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isless(static_cast(_Xx0), static_cast(_Xx1))); } -template -_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return islessequal(static_cast(_X0), static_cast(_X1)); +template +_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessequal(static_cast(_Xx0), static_cast(_Xx1))); } -template -_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return islessgreater(static_cast(_X0), static_cast(_X1)); +template +_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessgreater(static_cast(_Xx0), static_cast(_Xx1))); } -template -_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(_Ty1 _X0, _Ty2 _X1) noexcept /* strengthened */ { - return isunordered(static_cast(_X0), static_cast(_X1)); +template +_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isunordered(static_cast(_Xx0), static_cast(_Xx1))); } } // extern "C++" @@ -614,8 +654,6 @@ _NODISCARD double yn(int, double); #undef _STL_DEF_FAMILY1 #undef _STL_DEF_FAMILY2 #undef _STL_DEF_FAMILY3 -#undef _STL_DEF_PREDICATE_FAMILY1 -#undef _STL_DEF_PREDICATE_FAMILY2 #undef _STL_DEF_ROUNDING_FAMILY1 #undef _STL_DECLARE_FAMILY1 #undef _CONSTEXPR_CMATH26_NYI From 468e78890f05423d684a5ebd027d63aa95de1ca2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:57 -0700 Subject: [PATCH 25/85] __msvc_math.hpp: Group the comparison templates with their other overloads. --- stl/inc/__msvc_math.hpp | 46 ++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index c7a8a7d898e..f5c5c8cb8a5 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -425,6 +425,10 @@ _NODISCARD _CONSTEXPR_CMATH23 bool isgreater(double _Xx0, double _Xx1) noexcept _NODISCARD _CONSTEXPR_CMATH23 bool isgreater(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_isgreaterl(_Xx0, _Xx1)); } +template +_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreater(static_cast(_Xx0), static_cast(_Xx1))); +} _NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(float _Xx0, float _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_isgreaterequalf(_Xx0, _Xx1)); @@ -435,6 +439,10 @@ _NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(double _Xx0, double _Xx1) noex _NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_isgreaterequall(_Xx0, _Xx1)); } +template +_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isgreaterequal(static_cast(_Xx0), static_cast(_Xx1))); +} _NODISCARD _CONSTEXPR_CMATH23 bool isless(float _Xx0, float _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_islessf(_Xx0, _Xx1)); @@ -445,6 +453,10 @@ _NODISCARD _CONSTEXPR_CMATH23 bool isless(double _Xx0, double _Xx1) noexcept /* _NODISCARD _CONSTEXPR_CMATH23 bool isless(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_islessl(_Xx0, _Xx1)); } +template +_NODISCARD _CONSTEXPR_CMATH23 bool isless(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_isless(static_cast(_Xx0), static_cast(_Xx1))); +} _NODISCARD _CONSTEXPR_CMATH23 bool islessequal(float _Xx0, float _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_islessequalf(_Xx0, _Xx1)); @@ -455,6 +467,10 @@ _NODISCARD _CONSTEXPR_CMATH23 bool islessequal(double _Xx0, double _Xx1) noexcep _NODISCARD _CONSTEXPR_CMATH23 bool islessequal(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_islessequall(_Xx0, _Xx1)); } +template +_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessequal(static_cast(_Xx0), static_cast(_Xx1))); +} _NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(float _Xx0, float _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_islessgreaterf(_Xx0, _Xx1)); @@ -465,6 +481,10 @@ _NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(double _Xx0, double _Xx1) noexc _NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_islessgreaterl(_Xx0, _Xx1)); } +template +_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { + return static_cast(__builtin_islessgreater(static_cast(_Xx0), static_cast(_Xx1))); +} _NODISCARD _CONSTEXPR_CMATH23 bool isunordered(float _Xx0, float _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_isunorderedf(_Xx0, _Xx1)); @@ -475,32 +495,6 @@ _NODISCARD _CONSTEXPR_CMATH23 bool isunordered(double _Xx0, double _Xx1) noexcep _NODISCARD _CONSTEXPR_CMATH23 bool isunordered(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_isunorderedl(_Xx0, _Xx1)); } - -template -_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreater(static_cast(_Xx0), static_cast(_Xx1))); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreaterequal(static_cast(_Xx0), static_cast(_Xx1))); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool isless(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isless(static_cast(_Xx0), static_cast(_Xx1))); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessequal(static_cast(_Xx0), static_cast(_Xx1))); -} - -template -_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessgreater(static_cast(_Xx0), static_cast(_Xx1))); -} - template _NODISCARD _CONSTEXPR_CMATH23 bool isunordered(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { return static_cast(__builtin_isunordered(static_cast(_Xx0), static_cast(_Xx1))); From 9aae10caf3f8c3f7da5358f481581851892fe8c5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:57 -0700 Subject: [PATCH 26/85] __msvc_math.hpp: Restore/overhaul `_STL_DEF_OVERLOADED_PREDICATE_FAMILY[12]` macros. --- stl/inc/__msvc_math.hpp | 133 ++++++++++++---------------------------- 1 file changed, 38 insertions(+), 95 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index f5c5c8cb8a5..eaea9e0c683 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -107,6 +107,33 @@ extern "C" { _STL_DEF_FUNC1(specs, name, ret, double) \ _STL_DEF_FUNC1(specs, name##l, ret, long double) +// N.B. static_cast is used when the builtin returns int. +#define _STL_DEF_OVERLOADED_PREDICATE1(specs, name, builtin, fptype) \ + _NODISCARD specs bool name(fptype _Xx) noexcept /* strengthened */ { \ + return static_cast(builtin(_Xx)); \ + } + +#define _STL_DEF_OVERLOADED_PREDICATE2(specs, name, builtin, fptype) \ + _NODISCARD specs bool name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ + return static_cast(builtin(_Xx0, _Xx1)); \ + } + +// Defines three overloaded functions with signature `bool(fp-type)`. +#define _STL_DEF_OVERLOADED_PREDICATE_FAMILY1(specs, name) \ + _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name##f, float) \ + _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name, double) \ + _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name##l, long double) + +// Defines four overloaded functions with signature `bool(fp-type, fp-type)`. +#define _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(specs, name) \ + _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name##f, float) \ + _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name, double) \ + _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name##l, long double) \ + template \ + _NODISCARD specs bool name(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { \ + return static_cast(__builtin_##name(static_cast(_Xx0), static_cast(_Xx1))); \ + } + // **Declares** two non-overloaded functions with signature `fp-type(fp-type)`. // A third function, corresponding to the `long double` variant of the function, // is **defined** to call the double variant. These declarations are intended to @@ -404,101 +431,13 @@ _NODISCARD _CONSTEXPR_CMATH23 bool isnormal(long double _Xx) noexcept /* strengt return fpclassify(_Xx) == FP_NORMAL; } -// N.B. static_cast is used when the builtin returns int. - -_NODISCARD _CONSTEXPR_CMATH23 bool signbit(float _Xx) noexcept /* strengthened */ { - return static_cast(__builtin_signbitf(_Xx)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool signbit(double _Xx) noexcept /* strengthened */ { - return static_cast(__builtin_signbit(_Xx)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool signbit(long double _Xx) noexcept /* strengthened */ { - return static_cast(__builtin_signbitl(_Xx)); -} - -_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(float _Xx0, float _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreaterf(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(double _Xx0, double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreater(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreaterl(_Xx0, _Xx1)); -} -template -_NODISCARD _CONSTEXPR_CMATH23 bool isgreater(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreater(static_cast(_Xx0), static_cast(_Xx1))); -} - -_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(float _Xx0, float _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreaterequalf(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(double _Xx0, double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreaterequal(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreaterequall(_Xx0, _Xx1)); -} -template -_NODISCARD _CONSTEXPR_CMATH23 bool isgreaterequal(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isgreaterequal(static_cast(_Xx0), static_cast(_Xx1))); -} - -_NODISCARD _CONSTEXPR_CMATH23 bool isless(float _Xx0, float _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessf(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool isless(double _Xx0, double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isless(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool isless(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessl(_Xx0, _Xx1)); -} -template -_NODISCARD _CONSTEXPR_CMATH23 bool isless(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isless(static_cast(_Xx0), static_cast(_Xx1))); -} - -_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(float _Xx0, float _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessequalf(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(double _Xx0, double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessequal(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessequall(_Xx0, _Xx1)); -} -template -_NODISCARD _CONSTEXPR_CMATH23 bool islessequal(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessequal(static_cast(_Xx0), static_cast(_Xx1))); -} - -_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(float _Xx0, float _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessgreaterf(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(double _Xx0, double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessgreater(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessgreaterl(_Xx0, _Xx1)); -} -template -_NODISCARD _CONSTEXPR_CMATH23 bool islessgreater(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_islessgreater(static_cast(_Xx0), static_cast(_Xx1))); -} - -_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(float _Xx0, float _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isunorderedf(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(double _Xx0, double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isunordered(_Xx0, _Xx1)); -} -_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isunorderedl(_Xx0, _Xx1)); -} -template -_NODISCARD _CONSTEXPR_CMATH23 bool isunordered(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { - return static_cast(__builtin_isunordered(static_cast(_Xx0), static_cast(_Xx1))); -} +_STL_DEF_OVERLOADED_PREDICATE_FAMILY1(_CONSTEXPR_CMATH23, signbit) +_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isgreater) +_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isgreaterequal) +_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isless) +_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, islessequal) +_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, islessgreater) +_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isunordered) } // extern "C++" _NODISCARD _CONSTEXPR_CMATH23 float nexttowardf(float _Xx0, long double _Xx1) noexcept /* strengthened */ { @@ -649,6 +588,10 @@ _NODISCARD double yn(int, double); #undef _STL_DEF_FAMILY2 #undef _STL_DEF_FAMILY3 #undef _STL_DEF_ROUNDING_FAMILY1 +#undef _STL_DEF_OVERLOADED_PREDICATE1 +#undef _STL_DEF_OVERLOADED_PREDICATE2 +#undef _STL_DEF_OVERLOADED_PREDICATE_FAMILY1 +#undef _STL_DEF_OVERLOADED_PREDICATE_FAMILY2 #undef _STL_DECLARE_FAMILY1 #undef _CONSTEXPR_CMATH26_NYI From 4bad1f272dbd318a60b25cbc14c915403062ac75 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:58 -0700 Subject: [PATCH 27/85] __msvc_math.hpp: Fix and unwrap comments. --- stl/inc/__msvc_math.hpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index eaea9e0c683..96cff0f0ec6 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -51,7 +51,7 @@ extern "C" { } // `long double` and `double` are the same width on MSVC, so `long double` -// variants of math functions forward to the `long` variants. +// variants of math functions forward to the `double` variants. #define _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) \ _NODISCARD specs long double name##l(long double _Xx0) noexcept /* strengthened */ { \ return name(static_cast(_Xx0)); \ @@ -76,32 +76,28 @@ extern "C" { #define _STL_DECLARE_FUNC2(specs, name, ret, fptype) _NODISCARD specs ret name(fptype, fptype); // Defines three non-overloaded functions with signature `fp-type(fp-type)`. -// The names of the float and long double variants are suffixed with `f` and `l`, -// respectively. +// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY1(specs, name) \ _STL_DEF_FUNC1(specs, name##f, float, float) \ _STL_DEF_FUNC1(specs, name, double, double) \ _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type)`. -// The names of the float and long double variants are suffixed with `f` and `l`, -// respectively. +// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY2(specs, name) \ _STL_DEF_FUNC2(specs, name##f, float, float) \ _STL_DEF_FUNC2(specs, name, double, double) \ _STL_DEF_LDOUBLE_FORWARD_FUNC2(specs, name) -// Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type)`. -// The names of the float and long double variants are suffixed with `f` and `l`, -// respectively. +// Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, fp-type)`. +// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY3(specs, name) \ _STL_DEF_FUNC3(specs, name##f, float, float) \ _STL_DEF_FUNC3(specs, name, double, double) \ _STL_DEF_LDOUBLE_FORWARD_FUNC3(specs, name) // Defines three non-overloaded functions with signature `int-type(fp-type)`. -// The names of the float and long double variants are suffixed with `f` and `l`, -// respectively. +// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_ROUNDING_FAMILY1(specs, name, ret) \ _STL_DEF_FUNC1(specs, name##f, ret, float) \ _STL_DEF_FUNC1(specs, name, ret, double) \ From 7613e00f1925449063a187e25bc57eca4f5c62e9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:18:59 -0700 Subject: [PATCH 28/85] __msvc_math.hpp: Attempt to always call `long double` builtins. --- stl/inc/__msvc_math.hpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 96cff0f0ec6..cc0be6b224b 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -57,17 +57,6 @@ extern "C" { return name(static_cast(_Xx0)); \ } -#define _STL_DEF_LDOUBLE_FORWARD_FUNC2(specs, name) \ - _NODISCARD specs long double name##l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { \ - return name(static_cast(_Xx0), static_cast(_Xx1)); \ - } - -#define _STL_DEF_LDOUBLE_FORWARD_FUNC3(specs, name) \ - _NODISCARD specs long double name##l( \ - long double _Xx0, long double _Xx1, long double _Xx2) noexcept /* strengthened */ { \ - return name(static_cast(_Xx0), static_cast(_Xx1), static_cast(_Xx2)); \ - } - // N.B. Declarations stamped out by these macros are not noexcept because they // are intended to match the definitions in the UCRT, which are not themselves // noexcept. @@ -80,21 +69,21 @@ extern "C" { #define _STL_DEF_FAMILY1(specs, name) \ _STL_DEF_FUNC1(specs, name##f, float, float) \ _STL_DEF_FUNC1(specs, name, double, double) \ - _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) + _STL_DEF_FUNC1(specs, name##l, long double, long double) // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY2(specs, name) \ _STL_DEF_FUNC2(specs, name##f, float, float) \ _STL_DEF_FUNC2(specs, name, double, double) \ - _STL_DEF_LDOUBLE_FORWARD_FUNC2(specs, name) + _STL_DEF_FUNC2(specs, name##l, long double, long double) // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY3(specs, name) \ _STL_DEF_FUNC3(specs, name##f, float, float) \ _STL_DEF_FUNC3(specs, name, double, double) \ - _STL_DEF_LDOUBLE_FORWARD_FUNC3(specs, name) + _STL_DEF_FUNC3(specs, name##l, long double, long double) // Defines three non-overloaded functions with signature `int-type(fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. @@ -576,8 +565,6 @@ _NODISCARD double yn(int, double); #undef _STL_DEF_FUNC2 #undef _STL_DEF_FUNC3 #undef _STL_DEF_LDOUBLE_FORWARD_FUNC1 -#undef _STL_DEF_LDOUBLE_FORWARD_FUNC2 -#undef _STL_DEF_LDOUBLE_FORWARD_FUNC3 #undef _STL_DECLARE_FUNC1 #undef _STL_DECLARE_FUNC2 #undef _STL_DEF_FAMILY1 From 4333fa03b02b2e3eabbfcf484c0a980864b6ba23 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:00 -0700 Subject: [PATCH 29/85] __msvc_math.hpp: Condense with `_STL_DEF_LASTARG_FAMILY2`. --- stl/inc/__msvc_math.hpp | 87 ++++++++++------------------------------- 1 file changed, 20 insertions(+), 67 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index cc0be6b224b..5be7bd32d0a 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -40,9 +40,9 @@ extern "C" { return __builtin_##name(_Xx); \ } -#define _STL_DEF_FUNC2(specs, name, ret, fptype) \ - _NODISCARD specs ret name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx0, _Xx1); \ +#define _STL_DEF_FUNC2(specs, name, ret, arg0, arg1) \ + _NODISCARD specs ret name(arg0 _Xx0, arg1 _Xx1) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx0, _Xx1); \ } #define _STL_DEF_FUNC3(specs, name, ret, fptype) \ @@ -73,10 +73,10 @@ extern "C" { // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. -#define _STL_DEF_FAMILY2(specs, name) \ - _STL_DEF_FUNC2(specs, name##f, float, float) \ - _STL_DEF_FUNC2(specs, name, double, double) \ - _STL_DEF_FUNC2(specs, name##l, long double, long double) +#define _STL_DEF_FAMILY2(specs, name) \ + _STL_DEF_FUNC2(specs, name##f, float, float, float) \ + _STL_DEF_FUNC2(specs, name, double, double, double) \ + _STL_DEF_FUNC2(specs, name##l, long double, long double, long double) // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. @@ -92,6 +92,13 @@ extern "C" { _STL_DEF_FUNC1(specs, name, ret, double) \ _STL_DEF_FUNC1(specs, name##l, ret, long double) +// Defines three non-overloaded functions with signature `fp-type(fp-type, lastarg)`. +// The names of the float and long double variants are suffixed with `f` and `l`, respectively. +#define _STL_DEF_LASTARG_FAMILY2(specs, name, lastarg) \ + _STL_DEF_FUNC2(specs, name##f, float, float, lastarg) \ + _STL_DEF_FUNC2(specs, name, double, double, lastarg) \ + _STL_DEF_FUNC2(specs, name##l, long double, long double, lastarg) + // N.B. static_cast is used when the builtin returns int. #define _STL_DEF_OVERLOADED_PREDICATE1(specs, name, builtin, fptype) \ _NODISCARD specs bool name(fptype _Xx) noexcept /* strengthened */ { \ @@ -425,43 +432,10 @@ _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, islessgreater) _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isunordered) } // extern "C++" -_NODISCARD _CONSTEXPR_CMATH23 float nexttowardf(float _Xx0, long double _Xx1) noexcept /* strengthened */ { - return __builtin_nexttowardf(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 double nexttoward(double _Xx0, long double _Xx1) noexcept /* strengthened */ { - return __builtin_nexttoward(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 long double nexttowardl(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - return __builtin_nexttowardl(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 float frexpf(float _Xx0, int* _Xx1) noexcept /* strengthened */ { - return __builtin_frexpf(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 double frexp(double _Xx0, int* _Xx1) noexcept /* strengthened */ { - return __builtin_frexp(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 long double frexpl(long double _Xx0, int* _Xx1) noexcept /* strengthened */ { - return __builtin_frexpl(_Xx0, _Xx1); -} - +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, nexttoward, long double) +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, frexp, int*) _STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) - -_NODISCARD _CONSTEXPR_CMATH23 float ldexpf(float _Xx0, int _Xx1) noexcept /* strengthened */ { - return __builtin_ldexpf(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 double ldexp(double _Xx0, int _Xx1) noexcept /* strengthened */ { - return __builtin_ldexp(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 long double ldexpl(long double _Xx0, int _Xx1) noexcept /* strengthened */ { - return __builtin_ldexpl(_Xx0, _Xx1); -} +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, ldexp, int) _NODISCARD _CONSTEXPR_CMATH23 float modff(float _Xx0, float* _Xx1) noexcept /* strengthened */ { return __builtin_modff(_Xx0, _Xx1); @@ -478,30 +452,8 @@ _NODISCARD _CONSTEXPR_CMATH23 long double modfl(long double _Xx0, long double* _ _STL_DEF_ROUNDING_FAMILY1(inline, lrint, long) _STL_DEF_ROUNDING_FAMILY1(inline, llrint, long long) _STL_DEF_FAMILY1(inline, rint) - -_NODISCARD _CONSTEXPR_CMATH23 float scalbnf(float _Xx0, int _Xx1) noexcept /* strengthened */ { - return __builtin_scalbnf(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 double scalbn(double _Xx0, int _Xx1) noexcept /* strengthened */ { - return __builtin_scalbn(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 long double scalbnl(long double _Xx0, int _Xx1) noexcept /* strengthened */ { - return __builtin_scalbnl(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 float scalblnf(float _Xx0, long _Xx1) noexcept /* strengthened */ { - return __builtin_scalblnf(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 double scalbln(double _Xx0, long _Xx1) noexcept /* strengthened */ { - return __builtin_scalbln(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 long double scalblnl(long double _Xx0, long _Xx1) noexcept /* strengthened */ { - return __builtin_scalblnl(_Xx0, _Xx1); -} +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbn, int) +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbln, long) _NODISCARD _CONSTEXPR_CMATH23 float remquof(float _Xx0, float _Xx1, int* _Xx2) noexcept /* strengthened */ { return __builtin_remquof(_Xx0, _Xx1, _Xx2); @@ -571,6 +523,7 @@ _NODISCARD double yn(int, double); #undef _STL_DEF_FAMILY2 #undef _STL_DEF_FAMILY3 #undef _STL_DEF_ROUNDING_FAMILY1 +#undef _STL_DEF_LASTARG_FAMILY2 #undef _STL_DEF_OVERLOADED_PREDICATE1 #undef _STL_DEF_OVERLOADED_PREDICATE2 #undef _STL_DEF_OVERLOADED_PREDICATE_FAMILY1 From 6e362aaaf4c724eaba9bfaadf110447dc1949777 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:01 -0700 Subject: [PATCH 30/85] __msvc_math.hpp: `_STL_DECLARE_FUNC2` was unused. --- stl/inc/__msvc_math.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 5be7bd32d0a..ce871e5e976 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -62,8 +62,6 @@ extern "C" { // noexcept. #define _STL_DECLARE_FUNC1(specs, name, ret, fptype) _NODISCARD specs ret name(fptype); -#define _STL_DECLARE_FUNC2(specs, name, ret, fptype) _NODISCARD specs ret name(fptype, fptype); - // Defines three non-overloaded functions with signature `fp-type(fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY1(specs, name) \ @@ -518,7 +516,6 @@ _NODISCARD double yn(int, double); #undef _STL_DEF_FUNC3 #undef _STL_DEF_LDOUBLE_FORWARD_FUNC1 #undef _STL_DECLARE_FUNC1 -#undef _STL_DECLARE_FUNC2 #undef _STL_DEF_FAMILY1 #undef _STL_DEF_FAMILY2 #undef _STL_DEF_FAMILY3 From 5224dd3c665dbefe6cbe6045575e4831924a4f10 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:02 -0700 Subject: [PATCH 31/85] __msvc_math.hpp: `_STL_DEF_ROUNDING_FAMILY1` => `_STL_DEF_RETURN_FAMILY1` --- stl/inc/__msvc_math.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index ce871e5e976..8891f8857c2 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -85,9 +85,9 @@ extern "C" { // Defines three non-overloaded functions with signature `int-type(fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. -#define _STL_DEF_ROUNDING_FAMILY1(specs, name, ret) \ - _STL_DEF_FUNC1(specs, name##f, ret, float) \ - _STL_DEF_FUNC1(specs, name, ret, double) \ +#define _STL_DEF_RETURN_FAMILY1(specs, name, ret) \ + _STL_DEF_FUNC1(specs, name##f, ret, float) \ + _STL_DEF_FUNC1(specs, name, ret, double) \ _STL_DEF_FUNC1(specs, name##l, ret, long double) // Defines three non-overloaded functions with signature `fp-type(fp-type, lastarg)`. @@ -272,8 +272,8 @@ _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, nextafter) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fdim) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmax) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmin) -_STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, lround, long int) -_STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, llround, long long) +_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, lround, long int) +_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, llround, long long) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, acos) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, acosh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, asin) @@ -432,7 +432,7 @@ _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isunordered) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, nexttoward, long double) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, frexp, int*) -_STL_DEF_ROUNDING_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) +_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, ldexp, int) _NODISCARD _CONSTEXPR_CMATH23 float modff(float _Xx0, float* _Xx1) noexcept /* strengthened */ { @@ -447,8 +447,8 @@ _NODISCARD _CONSTEXPR_CMATH23 long double modfl(long double _Xx0, long double* _ return __builtin_modfl(_Xx0, _Xx1); } -_STL_DEF_ROUNDING_FAMILY1(inline, lrint, long) -_STL_DEF_ROUNDING_FAMILY1(inline, llrint, long long) +_STL_DEF_RETURN_FAMILY1(inline, lrint, long) +_STL_DEF_RETURN_FAMILY1(inline, llrint, long long) _STL_DEF_FAMILY1(inline, rint) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbn, int) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbln, long) @@ -519,7 +519,7 @@ _NODISCARD double yn(int, double); #undef _STL_DEF_FAMILY1 #undef _STL_DEF_FAMILY2 #undef _STL_DEF_FAMILY3 -#undef _STL_DEF_ROUNDING_FAMILY1 +#undef _STL_DEF_RETURN_FAMILY1 #undef _STL_DEF_LASTARG_FAMILY2 #undef _STL_DEF_OVERLOADED_PREDICATE1 #undef _STL_DEF_OVERLOADED_PREDICATE2 From 636dc7c1e5751666a966d0ea5f1a9a5386a05d98 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:03 -0700 Subject: [PATCH 32/85] __msvc_math.hpp: `long int` => `long` --- stl/inc/__msvc_math.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 8891f8857c2..50309865fb3 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -272,7 +272,7 @@ _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, nextafter) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fdim) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmax) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmin) -_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, lround, long int) +_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, lround, long) _STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, llround, long long) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, acos) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, acosh) From addc709436203ba808985452d8de1f88ad1fd04e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:03 -0700 Subject: [PATCH 33/85] __msvc_math.hpp: Condense with `_STL_DEF_LASTARG_FAMILY3`. --- stl/inc/__msvc_math.hpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 50309865fb3..820b6a8dacc 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -45,9 +45,9 @@ extern "C" { return __builtin_##name(_Xx0, _Xx1); \ } -#define _STL_DEF_FUNC3(specs, name, ret, fptype) \ - _NODISCARD specs ret name(fptype _Xx0, fptype _Xx1, fptype _Xx2) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx0, _Xx1, _Xx2); \ +#define _STL_DEF_FUNC3(specs, name, ret, arg0, arg1, arg2) \ + _NODISCARD specs ret name(arg0 _Xx0, arg1 _Xx1, arg2 _Xx2) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx0, _Xx1, _Xx2); \ } // `long double` and `double` are the same width on MSVC, so `long double` @@ -78,10 +78,10 @@ extern "C" { // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. -#define _STL_DEF_FAMILY3(specs, name) \ - _STL_DEF_FUNC3(specs, name##f, float, float) \ - _STL_DEF_FUNC3(specs, name, double, double) \ - _STL_DEF_FUNC3(specs, name##l, long double, long double) +#define _STL_DEF_FAMILY3(specs, name) \ + _STL_DEF_FUNC3(specs, name##f, float, float, float, float) \ + _STL_DEF_FUNC3(specs, name, double, double, double, double) \ + _STL_DEF_FUNC3(specs, name##l, long double, long double, long double, long double) // Defines three non-overloaded functions with signature `int-type(fp-type)`. // The names of the float and long double variants are suffixed with `f` and `l`, respectively. @@ -97,6 +97,13 @@ extern "C" { _STL_DEF_FUNC2(specs, name, double, double, lastarg) \ _STL_DEF_FUNC2(specs, name##l, long double, long double, lastarg) +// Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, lastarg)`. +// The names of the float and long double variants are suffixed with `f` and `l`, respectively. +#define _STL_DEF_LASTARG_FAMILY3(specs, name, lastarg) \ + _STL_DEF_FUNC3(specs, name##f, float, float, float, lastarg) \ + _STL_DEF_FUNC3(specs, name, double, double, double, lastarg) \ + _STL_DEF_FUNC3(specs, name##l, long double, long double, long double, lastarg) + // N.B. static_cast is used when the builtin returns int. #define _STL_DEF_OVERLOADED_PREDICATE1(specs, name, builtin, fptype) \ _NODISCARD specs bool name(fptype _Xx) noexcept /* strengthened */ { \ @@ -452,19 +459,7 @@ _STL_DEF_RETURN_FAMILY1(inline, llrint, long long) _STL_DEF_FAMILY1(inline, rint) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbn, int) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbln, long) - -_NODISCARD _CONSTEXPR_CMATH23 float remquof(float _Xx0, float _Xx1, int* _Xx2) noexcept /* strengthened */ { - return __builtin_remquof(_Xx0, _Xx1, _Xx2); -} - -_NODISCARD _CONSTEXPR_CMATH23 double remquo(double _Xx0, double _Xx1, int* _Xx2) noexcept /* strengthened */ { - return __builtin_remquo(_Xx0, _Xx1, _Xx2); -} - -_NODISCARD _CONSTEXPR_CMATH23 long double remquol(long double _Xx0, long double _Xx1, int* _Xx2) noexcept -/* strengthened */ { - return __builtin_remquol(_Xx0, _Xx1, _Xx2); -} +_STL_DEF_LASTARG_FAMILY3(_CONSTEXPR_CMATH23, remquo, int*) // Preserve the sign of zero when atan2 underflows. // __builtin_atan2 can return +0 for tiny negative results. @@ -521,6 +516,7 @@ _NODISCARD double yn(int, double); #undef _STL_DEF_FAMILY3 #undef _STL_DEF_RETURN_FAMILY1 #undef _STL_DEF_LASTARG_FAMILY2 +#undef _STL_DEF_LASTARG_FAMILY3 #undef _STL_DEF_OVERLOADED_PREDICATE1 #undef _STL_DEF_OVERLOADED_PREDICATE2 #undef _STL_DEF_OVERLOADED_PREDICATE_FAMILY1 From 0d5b9330a0d7e1adfa50c3a463f38a0f26b25625 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:04 -0700 Subject: [PATCH 34/85] __msvc_math.hpp: Drop unnecessary comments about f/l suffixes. --- stl/inc/__msvc_math.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 820b6a8dacc..36bc3470467 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -63,42 +63,36 @@ extern "C" { #define _STL_DECLARE_FUNC1(specs, name, ret, fptype) _NODISCARD specs ret name(fptype); // Defines three non-overloaded functions with signature `fp-type(fp-type)`. -// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY1(specs, name) \ _STL_DEF_FUNC1(specs, name##f, float, float) \ _STL_DEF_FUNC1(specs, name, double, double) \ _STL_DEF_FUNC1(specs, name##l, long double, long double) // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type)`. -// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY2(specs, name) \ _STL_DEF_FUNC2(specs, name##f, float, float, float) \ _STL_DEF_FUNC2(specs, name, double, double, double) \ _STL_DEF_FUNC2(specs, name##l, long double, long double, long double) // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, fp-type)`. -// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_FAMILY3(specs, name) \ _STL_DEF_FUNC3(specs, name##f, float, float, float, float) \ _STL_DEF_FUNC3(specs, name, double, double, double, double) \ _STL_DEF_FUNC3(specs, name##l, long double, long double, long double, long double) // Defines three non-overloaded functions with signature `int-type(fp-type)`. -// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_RETURN_FAMILY1(specs, name, ret) \ _STL_DEF_FUNC1(specs, name##f, ret, float) \ _STL_DEF_FUNC1(specs, name, ret, double) \ _STL_DEF_FUNC1(specs, name##l, ret, long double) // Defines three non-overloaded functions with signature `fp-type(fp-type, lastarg)`. -// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_LASTARG_FAMILY2(specs, name, lastarg) \ _STL_DEF_FUNC2(specs, name##f, float, float, lastarg) \ _STL_DEF_FUNC2(specs, name, double, double, lastarg) \ _STL_DEF_FUNC2(specs, name##l, long double, long double, lastarg) // Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, lastarg)`. -// The names of the float and long double variants are suffixed with `f` and `l`, respectively. #define _STL_DEF_LASTARG_FAMILY3(specs, name, lastarg) \ _STL_DEF_FUNC3(specs, name##f, float, float, float, lastarg) \ _STL_DEF_FUNC3(specs, name, double, double, double, lastarg) \ From 09fadb76ab63f5c9230a487f8121885eba5fb43a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:05 -0700 Subject: [PATCH 35/85] __msvc_math.hpp: Cleanup signature comments. --- stl/inc/__msvc_math.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 36bc3470467..3e8a891b098 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -62,37 +62,37 @@ extern "C" { // noexcept. #define _STL_DECLARE_FUNC1(specs, name, ret, fptype) _NODISCARD specs ret name(fptype); -// Defines three non-overloaded functions with signature `fp-type(fp-type)`. +// Defines three non-overloaded functions with signature `fp-type (fp-type)`. #define _STL_DEF_FAMILY1(specs, name) \ _STL_DEF_FUNC1(specs, name##f, float, float) \ _STL_DEF_FUNC1(specs, name, double, double) \ _STL_DEF_FUNC1(specs, name##l, long double, long double) -// Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type)`. +// Defines three non-overloaded functions with signature `fp-type (fp-type, fp-type)`. #define _STL_DEF_FAMILY2(specs, name) \ _STL_DEF_FUNC2(specs, name##f, float, float, float) \ _STL_DEF_FUNC2(specs, name, double, double, double) \ _STL_DEF_FUNC2(specs, name##l, long double, long double, long double) -// Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, fp-type)`. +// Defines three non-overloaded functions with signature `fp-type (fp-type, fp-type, fp-type)`. #define _STL_DEF_FAMILY3(specs, name) \ _STL_DEF_FUNC3(specs, name##f, float, float, float, float) \ _STL_DEF_FUNC3(specs, name, double, double, double, double) \ _STL_DEF_FUNC3(specs, name##l, long double, long double, long double, long double) -// Defines three non-overloaded functions with signature `int-type(fp-type)`. +// Defines three non-overloaded functions with signature `ret (fp-type)`. #define _STL_DEF_RETURN_FAMILY1(specs, name, ret) \ _STL_DEF_FUNC1(specs, name##f, ret, float) \ _STL_DEF_FUNC1(specs, name, ret, double) \ _STL_DEF_FUNC1(specs, name##l, ret, long double) -// Defines three non-overloaded functions with signature `fp-type(fp-type, lastarg)`. +// Defines three non-overloaded functions with signature `fp-type (fp-type, lastarg)`. #define _STL_DEF_LASTARG_FAMILY2(specs, name, lastarg) \ _STL_DEF_FUNC2(specs, name##f, float, float, lastarg) \ _STL_DEF_FUNC2(specs, name, double, double, lastarg) \ _STL_DEF_FUNC2(specs, name##l, long double, long double, lastarg) -// Defines three non-overloaded functions with signature `fp-type(fp-type, fp-type, lastarg)`. +// Defines three non-overloaded functions with signature `fp-type (fp-type, fp-type, lastarg)`. #define _STL_DEF_LASTARG_FAMILY3(specs, name, lastarg) \ _STL_DEF_FUNC3(specs, name##f, float, float, float, lastarg) \ _STL_DEF_FUNC3(specs, name, double, double, double, lastarg) \ @@ -109,13 +109,13 @@ extern "C" { return static_cast(builtin(_Xx0, _Xx1)); \ } -// Defines three overloaded functions with signature `bool(fp-type)`. +// Defines three overloaded functions with signature `bool (fp-type)`. #define _STL_DEF_OVERLOADED_PREDICATE_FAMILY1(specs, name) \ _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name##f, float) \ _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name, double) \ _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name##l, long double) -// Defines four overloaded functions with signature `bool(fp-type, fp-type)`. +// Defines four overloaded functions with signature `bool (fp-type, fp-type)`. #define _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(specs, name) \ _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name##f, float) \ _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name, double) \ @@ -125,7 +125,7 @@ extern "C" { return static_cast(__builtin_##name(static_cast(_Xx0), static_cast(_Xx1))); \ } -// **Declares** two non-overloaded functions with signature `fp-type(fp-type)`. +// **Declares** two non-overloaded functions with signature `fp-type (fp-type)`. // A third function, corresponding to the `long double` variant of the function, // is **defined** to call the double variant. These declarations are intended to // match functions defined within the UCRT because libc does not yet implement From 0079154b27b95520395da791aef9dea5c4d15941 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:06 -0700 Subject: [PATCH 36/85] __msvc_math.hpp: Simplify `_STL_DECLARE_FAMILY1` by declaring all three, adding noexcept. --- stl/inc/__msvc_math.hpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 3e8a891b098..ff561f14e85 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -50,18 +50,6 @@ extern "C" { return __builtin_##name(_Xx0, _Xx1, _Xx2); \ } -// `long double` and `double` are the same width on MSVC, so `long double` -// variants of math functions forward to the `double` variants. -#define _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) \ - _NODISCARD specs long double name##l(long double _Xx0) noexcept /* strengthened */ { \ - return name(static_cast(_Xx0)); \ - } - -// N.B. Declarations stamped out by these macros are not noexcept because they -// are intended to match the definitions in the UCRT, which are not themselves -// noexcept. -#define _STL_DECLARE_FUNC1(specs, name, ret, fptype) _NODISCARD specs ret name(fptype); - // Defines three non-overloaded functions with signature `fp-type (fp-type)`. #define _STL_DEF_FAMILY1(specs, name) \ _STL_DEF_FUNC1(specs, name##f, float, float) \ @@ -125,15 +113,13 @@ extern "C" { return static_cast(__builtin_##name(static_cast(_Xx0), static_cast(_Xx1))); \ } -// **Declares** two non-overloaded functions with signature `fp-type (fp-type)`. -// A third function, corresponding to the `long double` variant of the function, -// is **defined** to call the double variant. These declarations are intended to -// match functions defined within the UCRT because libc does not yet implement -// them fully. -#define _STL_DECLARE_FAMILY1(specs, name) \ - _STL_DECLARE_FUNC1(specs, name##f, float, float) \ - _STL_DECLARE_FUNC1(specs, name, double, double) \ - _STL_DEF_LDOUBLE_FORWARD_FUNC1(specs, name) +// **Declares** three non-overloaded functions with signature `fp-type (fp-type)`. +// These declarations are intended to match functions defined within the UCRT +// because libc does not yet implement them fully. +#define _STL_DECLARE_FAMILY1(specs, name) \ + _NODISCARD specs float name##f(float) noexcept /* strengthened */; \ + _NODISCARD specs double name(double) noexcept /* strengthened */; \ + _NODISCARD specs long double name##l(long double) noexcept /* strengthened */; // Some functions that are needed for C++26 constexpr cmath are not yet // implemented by libc. We polyfill the library with the UCRT and mark these @@ -503,8 +489,6 @@ _NODISCARD double yn(int, double); #undef _STL_DEF_FUNC1 #undef _STL_DEF_FUNC2 #undef _STL_DEF_FUNC3 -#undef _STL_DEF_LDOUBLE_FORWARD_FUNC1 -#undef _STL_DECLARE_FUNC1 #undef _STL_DEF_FAMILY1 #undef _STL_DEF_FAMILY2 #undef _STL_DEF_FAMILY3 From 4e7fe44f9049981cd0c882683c1fa5b0dbae9d91 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:07 -0700 Subject: [PATCH 37/85] __msvc_math.hpp: Declare nanf/nan/nanl and define coshf/sinhf/tanhf as noexcept. --- stl/inc/__msvc_math.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index ff561f14e85..c00fc62c89f 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -174,9 +174,9 @@ using double_t = double; // The nan family of functions is not routed to builtins because the builtins // require a string literal argument and so cannot uphold the interface of // these functions. -_NODISCARD float nanf(const char*); -_NODISCARD double nan(const char*); -_NODISCARD long double nanl(const char*); +_NODISCARD float nanf(const char*) noexcept /* strengthened */; +_NODISCARD double nan(const char*) noexcept /* strengthened */; +_NODISCARD long double nanl(const char*) noexcept /* strengthened */; // Under /Oi (implied by /O2), MSVC treats the following functions as intrinsics that // cannot be redefined. We use #pragma function to instruct MSVC to treat them as regular @@ -333,17 +333,17 @@ _STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) // forward to their double siblings, so forward-declaring them without defining // them does not a successful polyfill make. #pragma function(coshf, cosh, coshl) -_NODISCARD _CONSTEXPR_CMATH26_NYI float coshf(float _Xx) { +_NODISCARD _CONSTEXPR_CMATH26_NYI float coshf(float _Xx) noexcept /* strengthened */ { return __builtin_coshf(_Xx); } #pragma function(sinhf, sinh, sinhl) -_NODISCARD _CONSTEXPR_CMATH26_NYI float sinhf(float _Xx) { +_NODISCARD _CONSTEXPR_CMATH26_NYI float sinhf(float _Xx) noexcept /* strengthened */ { return __builtin_sinhf(_Xx); } #pragma function(tanhf, tanh, tanhl) -_NODISCARD _CONSTEXPR_CMATH26_NYI float tanhf(float _Xx) { +_NODISCARD _CONSTEXPR_CMATH26_NYI float tanhf(float _Xx) noexcept /* strengthened */ { return __builtin_tanhf(_Xx); } From efadfdb8c7267b20825a95e182d88d43e04daf67 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:08 -0700 Subject: [PATCH 38/85] __msvc_math.hpp: Mark everything as `__cdecl`. --- stl/inc/__msvc_math.hpp | 216 ++++++++++++++++++++-------------------- 1 file changed, 109 insertions(+), 107 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index c00fc62c89f..841c8f86bea 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -35,19 +35,19 @@ _STL_DISABLE_CLANG_WARNINGS extern "C" { -#define _STL_DEF_FUNC1(specs, name, ret, fptype) \ - _NODISCARD specs ret name(fptype _Xx) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx); \ +#define _STL_DEF_FUNC1(specs, name, ret, fptype) \ + _NODISCARD specs ret __cdecl name(fptype _Xx) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx); \ } -#define _STL_DEF_FUNC2(specs, name, ret, arg0, arg1) \ - _NODISCARD specs ret name(arg0 _Xx0, arg1 _Xx1) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx0, _Xx1); \ +#define _STL_DEF_FUNC2(specs, name, ret, arg0, arg1) \ + _NODISCARD specs ret __cdecl name(arg0 _Xx0, arg1 _Xx1) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx0, _Xx1); \ } -#define _STL_DEF_FUNC3(specs, name, ret, arg0, arg1, arg2) \ - _NODISCARD specs ret name(arg0 _Xx0, arg1 _Xx1, arg2 _Xx2) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx0, _Xx1, _Xx2); \ +#define _STL_DEF_FUNC3(specs, name, ret, arg0, arg1, arg2) \ + _NODISCARD specs ret __cdecl name(arg0 _Xx0, arg1 _Xx1, arg2 _Xx2) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx0, _Xx1, _Xx2); \ } // Defines three non-overloaded functions with signature `fp-type (fp-type)`. @@ -87,14 +87,14 @@ extern "C" { _STL_DEF_FUNC3(specs, name##l, long double, long double, long double, lastarg) // N.B. static_cast is used when the builtin returns int. -#define _STL_DEF_OVERLOADED_PREDICATE1(specs, name, builtin, fptype) \ - _NODISCARD specs bool name(fptype _Xx) noexcept /* strengthened */ { \ - return static_cast(builtin(_Xx)); \ +#define _STL_DEF_OVERLOADED_PREDICATE1(specs, name, builtin, fptype) \ + _NODISCARD specs bool __cdecl name(fptype _Xx) noexcept /* strengthened */ { \ + return static_cast(builtin(_Xx)); \ } -#define _STL_DEF_OVERLOADED_PREDICATE2(specs, name, builtin, fptype) \ - _NODISCARD specs bool name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ - return static_cast(builtin(_Xx0, _Xx1)); \ +#define _STL_DEF_OVERLOADED_PREDICATE2(specs, name, builtin, fptype) \ + _NODISCARD specs bool __cdecl name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ + return static_cast(builtin(_Xx0, _Xx1)); \ } // Defines three overloaded functions with signature `bool (fp-type)`. @@ -109,17 +109,17 @@ extern "C" { _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name, double) \ _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name##l, long double) \ template \ - _NODISCARD specs bool name(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { \ + _NODISCARD specs bool __cdecl name(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { \ return static_cast(__builtin_##name(static_cast(_Xx0), static_cast(_Xx1))); \ } // **Declares** three non-overloaded functions with signature `fp-type (fp-type)`. // These declarations are intended to match functions defined within the UCRT // because libc does not yet implement them fully. -#define _STL_DECLARE_FAMILY1(specs, name) \ - _NODISCARD specs float name##f(float) noexcept /* strengthened */; \ - _NODISCARD specs double name(double) noexcept /* strengthened */; \ - _NODISCARD specs long double name##l(long double) noexcept /* strengthened */; +#define _STL_DECLARE_FAMILY1(specs, name) \ + _NODISCARD specs float __cdecl name##f(float) noexcept /* strengthened */; \ + _NODISCARD specs double __cdecl name(double) noexcept /* strengthened */; \ + _NODISCARD specs long double __cdecl name##l(long double) noexcept /* strengthened */; // Some functions that are needed for C++26 constexpr cmath are not yet // implemented by libc. We polyfill the library with the UCRT and mark these @@ -174,56 +174,56 @@ using double_t = double; // The nan family of functions is not routed to builtins because the builtins // require a string literal argument and so cannot uphold the interface of // these functions. -_NODISCARD float nanf(const char*) noexcept /* strengthened */; -_NODISCARD double nan(const char*) noexcept /* strengthened */; -_NODISCARD long double nanl(const char*) noexcept /* strengthened */; +_NODISCARD float __cdecl nanf(const char*) noexcept /* strengthened */; +_NODISCARD double __cdecl nan(const char*) noexcept /* strengthened */; +_NODISCARD long double __cdecl nanl(const char*) noexcept /* strengthened */; // Under /Oi (implied by /O2), MSVC treats the following functions as intrinsics that // cannot be redefined. We use #pragma function to instruct MSVC to treat them as regular // functions that can be defined, but we first need to declare the function before we can // do so. -_NODISCARD _CONSTEXPR_CMATH23 float ceilf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double ceil(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double fabs(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float floorf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double floor(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float fmaxf(float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double fmax(double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 long double fmaxl(long double, long double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float fminf(float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double fmin(double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 long double fminl(long double, long double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float fmodf(float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double fmod(double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float acosf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double acos(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float asinf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double asin(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float atanf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double atan(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float copysignf(float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double copysign(double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float cosf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double cos(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float expf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double exp(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float logf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double log(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float log10f(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double log10(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float log2f(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double log2(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float powf(float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double pow(double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float sinf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double sin(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float sqrtf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double sqrt(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float tanf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double tan(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float fmaf(float, float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double fma(double, double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 long double fmal(long double, long double, long double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl ceilf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl ceil(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fabs(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl floorf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl floor(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmaxf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmax(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fmaxl(long double, long double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fminf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmin(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fminl(long double, long double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmodf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmod(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl acosf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl acos(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl asinf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl asin(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl atanf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl copysignf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl copysign(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl cosf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl cos(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl expf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl exp(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl logf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl log(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl log10f(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl log10(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl log2f(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl log2(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl powf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl pow(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl sinf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl sin(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl sqrtf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl sqrt(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl tanf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl tan(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmaf(float, float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fma(double, double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fmal(long double, long double, long double) noexcept; #pragma function(acosf, acos) #pragma function(asinf, asin) @@ -293,27 +293,27 @@ _NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_lgamma(double) noexce _NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_tgammaf(float) noexcept; _NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_tgamma(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26_NYI float lgammaf(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl lgammaf(float _Xx) noexcept /* strengthened */ { return __std_smf_lgammaf(_Xx); } -_NODISCARD _CONSTEXPR_CMATH26_NYI double lgamma(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI double __cdecl lgamma(double _Xx) noexcept /* strengthened */ { return __std_smf_lgamma(_Xx); } -_NODISCARD _CONSTEXPR_CMATH26_NYI long double lgammal(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl lgammal(long double _Xx) noexcept /* strengthened */ { return __std_smf_lgamma(static_cast(_Xx)); } -_NODISCARD _CONSTEXPR_CMATH26_NYI float tgammaf(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tgammaf(float _Xx) noexcept /* strengthened */ { return __std_smf_tgammaf(_Xx); } -_NODISCARD _CONSTEXPR_CMATH26_NYI double tgamma(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI double __cdecl tgamma(double _Xx) noexcept /* strengthened */ { return __std_smf_tgamma(_Xx); } -_NODISCARD _CONSTEXPR_CMATH26_NYI long double tgammal(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl tgammal(long double _Xx) noexcept /* strengthened */ { return __std_smf_tgamma(static_cast(_Xx)); } @@ -333,78 +333,78 @@ _STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) // forward to their double siblings, so forward-declaring them without defining // them does not a successful polyfill make. #pragma function(coshf, cosh, coshl) -_NODISCARD _CONSTEXPR_CMATH26_NYI float coshf(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl coshf(float _Xx) noexcept /* strengthened */ { return __builtin_coshf(_Xx); } #pragma function(sinhf, sinh, sinhl) -_NODISCARD _CONSTEXPR_CMATH26_NYI float sinhf(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl sinhf(float _Xx) noexcept /* strengthened */ { return __builtin_sinhf(_Xx); } #pragma function(tanhf, tanh, tanhl) -_NODISCARD _CONSTEXPR_CMATH26_NYI float tanhf(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* strengthened */ { return __builtin_tanhf(_Xx); } extern "C++" { -_NODISCARD _CONSTEXPR_CMATH23 int fpclassify(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(float _Xx) noexcept /* strengthened */ { return __builtin_fpclassifyf(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); } -_NODISCARD _CONSTEXPR_CMATH23 int fpclassify(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(double _Xx) noexcept /* strengthened */ { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); } -_NODISCARD _CONSTEXPR_CMATH23 int fpclassify(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(long double _Xx) noexcept /* strengthened */ { return __builtin_fpclassifyl(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); } -_NODISCARD _CONSTEXPR_CMATH23 bool isfinite(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(float _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) <= 0; } -_NODISCARD _CONSTEXPR_CMATH23 bool isfinite(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) <= 0; } -_NODISCARD _CONSTEXPR_CMATH23 bool isfinite(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(long double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) <= 0; } -_NODISCARD _CONSTEXPR_CMATH23 bool isinf(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(float _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_INFINITE; } -_NODISCARD _CONSTEXPR_CMATH23 bool isinf(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_INFINITE; } -_NODISCARD _CONSTEXPR_CMATH23 bool isinf(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(long double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_INFINITE; } -_NODISCARD _CONSTEXPR_CMATH23 bool isnan(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(float _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NAN; } -_NODISCARD _CONSTEXPR_CMATH23 bool isnan(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NAN; } -_NODISCARD _CONSTEXPR_CMATH23 bool isnan(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(long double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NAN; } -_NODISCARD _CONSTEXPR_CMATH23 bool isnormal(float _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(float _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NORMAL; } -_NODISCARD _CONSTEXPR_CMATH23 bool isnormal(double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NORMAL; } -_NODISCARD _CONSTEXPR_CMATH23 bool isnormal(long double _Xx) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(long double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NORMAL; } @@ -422,15 +422,16 @@ _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, frexp, int*) _STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, ldexp, int) -_NODISCARD _CONSTEXPR_CMATH23 float modff(float _Xx0, float* _Xx1) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl modff(float _Xx0, float* _Xx1) noexcept /* strengthened */ { return __builtin_modff(_Xx0, _Xx1); } -_NODISCARD _CONSTEXPR_CMATH23 double modf(double _Xx0, double* _Xx1) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl modf(double _Xx0, double* _Xx1) noexcept /* strengthened */ { return __builtin_modf(_Xx0, _Xx1); } -_NODISCARD _CONSTEXPR_CMATH23 long double modfl(long double _Xx0, long double* _Xx1) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl modfl(long double _Xx0, long double* _Xx1) noexcept +/* strengthened */ { return __builtin_modfl(_Xx0, _Xx1); } @@ -443,7 +444,7 @@ _STL_DEF_LASTARG_FAMILY3(_CONSTEXPR_CMATH23, remquo, int*) // Preserve the sign of zero when atan2 underflows. // __builtin_atan2 can return +0 for tiny negative results. -_NODISCARD _CONSTEXPR_CMATH26 float atan2f(float _Xx0, float _Xx1) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl atan2f(float _Xx0, float _Xx1) noexcept /* strengthened */ { float _Result = static_cast(__builtin_atan2f(_Xx0, _Xx1)); if (_Result == 0.0F && _Xx0 != 0.0F) { return __builtin_copysignf(0.0F, _Xx0); @@ -451,7 +452,7 @@ _NODISCARD _CONSTEXPR_CMATH26 float atan2f(float _Xx0, float _Xx1) noexcept /* s return _Result; } -_NODISCARD _CONSTEXPR_CMATH26 double atan2(double _Xx0, double _Xx1) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan2(double _Xx0, double _Xx1) noexcept /* strengthened */ { double _Result = static_cast(__builtin_atan2(_Xx0, _Xx1)); if (_Result == 0.0 && _Xx0 != 0.0) { return __builtin_copysign(0.0, _Xx0); @@ -459,7 +460,8 @@ _NODISCARD _CONSTEXPR_CMATH26 double atan2(double _Xx0, double _Xx1) noexcept /* return _Result; } -_NODISCARD _CONSTEXPR_CMATH26 long double atan2l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26 long double __cdecl atan2l(long double _Xx0, long double _Xx1) noexcept +/* strengthened */ { long double _Result = static_cast(__builtin_atan2l(_Xx0, _Xx1)); if (_Result == 0.0L && _Xx0 != 0.0L) { return __builtin_copysignl(0.0L, _Xx0); @@ -467,22 +469,22 @@ _NODISCARD _CONSTEXPR_CMATH26 long double atan2l(long double _Xx0, long double _ return _Result; } -_NODISCARD double _j0(double); -_NODISCARD double _j1(double); -_NODISCARD double _jn(int, double); -_NODISCARD double _y0(double); -_NODISCARD double _y1(double); -_NODISCARD double _yn(int, double); +_NODISCARD double __cdecl _j0(double); +_NODISCARD double __cdecl _j1(double); +_NODISCARD double __cdecl _jn(int, double); +_NODISCARD double __cdecl _y0(double); +_NODISCARD double __cdecl _y1(double); +_NODISCARD double __cdecl _yn(int, double); #if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES // These functions are included in the Open Group Standard Base Specifications. -_NODISCARD double j0(double); -_NODISCARD double j1(double); -_NODISCARD double jn(int, double); -_NODISCARD double y0(double); -_NODISCARD double y1(double); -_NODISCARD double yn(int, double); +_NODISCARD double __cdecl j0(double); +_NODISCARD double __cdecl j1(double); +_NODISCARD double __cdecl jn(int, double); +_NODISCARD double __cdecl y0(double); +_NODISCARD double __cdecl y1(double); +_NODISCARD double __cdecl yn(int, double); #endif // defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES From 0993a52eb525bf08c2df20e400a2a544c77d4510 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:09 -0700 Subject: [PATCH 39/85] __msvc_math.hpp: Add incantations for atan2, lrint. --- stl/inc/__msvc_math.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 841c8f86bea..ba355576d38 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -199,6 +199,8 @@ _NODISCARD _CONSTEXPR_CMATH26 float __cdecl acosf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl acos(double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl asinf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl asin(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl atan2f(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan2(double, double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl atanf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan(double) noexcept; _NODISCARD _CONSTEXPR_CMATH23 float __cdecl copysignf(float, float) noexcept; @@ -213,6 +215,9 @@ _NODISCARD _CONSTEXPR_CMATH26 float __cdecl log10f(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl log10(double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl log2f(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl log2(double) noexcept; +_NODISCARD inline long __cdecl lrintf(float) noexcept; +_NODISCARD inline long __cdecl lrint(double) noexcept; +_NODISCARD inline long __cdecl lrintl(long double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl powf(float, float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl pow(double, double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl sinf(float) noexcept; @@ -227,6 +232,7 @@ _NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fmal(long double, long double, #pragma function(acosf, acos) #pragma function(asinf, asin) +#pragma function(atan2f, atan2) #pragma function(atanf, atan) #pragma function(ceilf, ceil) #pragma function(copysignf, copysign) @@ -241,6 +247,7 @@ _NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fmal(long double, long double, #pragma function(log10f, log10) #pragma function(log2f, log2) #pragma function(logf, log) +#pragma function(lrintf, lrint, lrintl) #pragma function(powf, pow) #pragma function(sinf, sin) #pragma function(sqrtf, sqrt) From 1a381d72dd714d7b50071f70ccbd9e5922290f34 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:09 -0700 Subject: [PATCH 40/85] __msvc_math.hpp: Reorder declarations to match sorted pragmas. --- stl/inc/__msvc_math.hpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index ba355576d38..a460758cb89 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -182,19 +182,6 @@ _NODISCARD long double __cdecl nanl(const char*) noexcept /* strengthened */; // cannot be redefined. We use #pragma function to instruct MSVC to treat them as regular // functions that can be defined, but we first need to declare the function before we can // do so. -_NODISCARD _CONSTEXPR_CMATH23 float __cdecl ceilf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double __cdecl ceil(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fabs(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float __cdecl floorf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double __cdecl floor(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmaxf(float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmax(double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fmaxl(long double, long double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fminf(float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmin(double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fminl(long double, long double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmodf(float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmod(double, double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl acosf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl acos(double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl asinf(float) noexcept; @@ -203,18 +190,34 @@ _NODISCARD _CONSTEXPR_CMATH26 float __cdecl atan2f(float, float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan2(double, double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl atanf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl ceilf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl ceil(double) noexcept; _NODISCARD _CONSTEXPR_CMATH23 float __cdecl copysignf(float, float) noexcept; _NODISCARD _CONSTEXPR_CMATH23 double __cdecl copysign(double, double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl cosf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl cos(double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl expf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl exp(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 float __cdecl logf(float) noexcept; -_NODISCARD _CONSTEXPR_CMATH26 double __cdecl log(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fabs(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl floorf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl floor(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmaf(float, float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fma(double, double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fmal(long double, long double, long double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmaxf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmax(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fmaxl(long double, long double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fminf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmin(double, double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fminl(long double, long double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmodf(float, float) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fmod(double, double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl log10f(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl log10(double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl log2f(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl log2(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 float __cdecl logf(float) noexcept; +_NODISCARD _CONSTEXPR_CMATH26 double __cdecl log(double) noexcept; _NODISCARD inline long __cdecl lrintf(float) noexcept; _NODISCARD inline long __cdecl lrint(double) noexcept; _NODISCARD inline long __cdecl lrintl(long double) noexcept; @@ -226,9 +229,6 @@ _NODISCARD _CONSTEXPR_CMATH26 float __cdecl sqrtf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl sqrt(double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl tanf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl tan(double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fmaf(float, float, float) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 double __cdecl fma(double, double, double) noexcept; -_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl fmal(long double, long double, long double) noexcept; #pragma function(acosf, acos) #pragma function(asinf, asin) From 709db19305a92874a5947f15cb64427d91f0cb93 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:10 -0700 Subject: [PATCH 41/85] __msvc_math.hpp: Reduce pragmas to what's necessary. --- stl/inc/__msvc_math.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index a460758cb89..f1b531b1edd 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -339,17 +339,17 @@ _STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) // The UCRT defines the following functions on x86 as inline functions that // forward to their double siblings, so forward-declaring them without defining // them does not a successful polyfill make. -#pragma function(coshf, cosh, coshl) +#pragma function(coshf) _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl coshf(float _Xx) noexcept /* strengthened */ { return __builtin_coshf(_Xx); } -#pragma function(sinhf, sinh, sinhl) +#pragma function(sinhf) _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl sinhf(float _Xx) noexcept /* strengthened */ { return __builtin_sinhf(_Xx); } -#pragma function(tanhf, tanh, tanhl) +#pragma function(tanhf) _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* strengthened */ { return __builtin_tanhf(_Xx); } From 715b38bdc2ce84883abe5d3c3730c5d0eb392540 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:11 -0700 Subject: [PATCH 42/85] __msvc_math.hpp: Comment cleanups. --- stl/inc/__msvc_math.hpp | 79 ++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index f1b531b1edd..714b14405f0 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -3,10 +3,9 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This lies outside of the inclusion guard because the UCRT's math.h allows -// for repeated inclusion with behavioral differences dictated by this macro. -// math.h can be included once without this macro defined and a second time -// with it defined, resulting in the nonstandard math constants being defined. +// This lies outside of the inclusion guard because the UCRT's math.h allows for repeated inclusion +// with behavioral differences dictated by this macro. math.h can be included once without this macro +// defined and a second time with it defined, resulting in the nonstandard math constants being defined. #ifdef _USE_MATH_DEFINES #include #endif @@ -14,11 +13,10 @@ #ifndef __MSVC_MATH_HPP #define __MSVC_MATH_HPP -// When a user writes `#include `, the MSVC frontend arranges for this -// file to be included first. Because this file is intended to supplant the -// CRT's math components, we define the _INC_MATH macro to neutralize the -// contents of math.h when it is processed after. _INC_MATH is used as the -// include guard for the CRT's math file and is an intended public API. +// When a user writes `#include `, the MSVC frontend arranges for this file to be included first. +// Because this file is intended to supersede the UCRT's math components, we define the _INC_MATH macro +// to neutralize the contents of math.h when it is processed after. _INC_MATH is used as the include guard +// for the UCRT's math.h and is an intended public API. #define _INC_MATH #include @@ -35,9 +33,9 @@ _STL_DISABLE_CLANG_WARNINGS extern "C" { -#define _STL_DEF_FUNC1(specs, name, ret, fptype) \ - _NODISCARD specs ret __cdecl name(fptype _Xx) noexcept /* strengthened */ { \ - return __builtin_##name(_Xx); \ +#define _STL_DEF_FUNC1(specs, name, ret, arg0) \ + _NODISCARD specs ret __cdecl name(arg0 _Xx) noexcept /* strengthened */ { \ + return __builtin_##name(_Xx); \ } #define _STL_DEF_FUNC2(specs, name, ret, arg0, arg1) \ @@ -113,24 +111,21 @@ extern "C" { return static_cast(__builtin_##name(static_cast(_Xx0), static_cast(_Xx1))); \ } -// **Declares** three non-overloaded functions with signature `fp-type (fp-type)`. -// These declarations are intended to match functions defined within the UCRT -// because libc does not yet implement them fully. +// *Declares* three non-overloaded functions with signature `fp-type (fp-type)`. +// These declarations are intended to match UCRT function definitions because libc does not yet implement them fully. #define _STL_DECLARE_FAMILY1(specs, name) \ _NODISCARD specs float __cdecl name##f(float) noexcept /* strengthened */; \ _NODISCARD specs double __cdecl name(double) noexcept /* strengthened */; \ _NODISCARD specs long double __cdecl name##l(long double) noexcept /* strengthened */; -// Some functions that are needed for C++26 constexpr cmath are not yet -// implemented by libc. We polyfill the library with the UCRT and mark these -// functions with this macro. The resulting declarations are not able to be -// used during constant-evaluation yet. +// Some functions that are needed for C++26 constexpr cmath are not yet implemented by libc. +// We polyfill the library with the UCRT and mark these functions with this macro. +// The resulting declarations are not able to be used during constant-evaluation yet. #define _CONSTEXPR_CMATH26_NYI inline -// On x86, when not using /arch:SSE2 or greater, floating point operations -// are performed using the x87 instruction set and FLT_EVAL_METHOD is 2. -// (When /fp:fast is used, floating point operations may be consistent, so -// we use the default types.) +// On x86, when not using /arch:SSE2 or greater, floating-point operations are performed +// using the x87 instruction set and FLT_EVAL_METHOD is 2. (When /fp:fast is used, +// floating-point operations may be consistent, so we use the default types.) #if defined(_M_IX86) && _M_IX86_FP < 2 && !defined(_M_FP_FAST) using float_t = long double; using double_t = long double; @@ -141,9 +136,8 @@ using double_t = double; #define MATH_ERRNO 1 #define MATH_ERREXCEPT 2 -// The UCRT defines this to be MATH_ERRNO | MATH_ERREXCEPT, but we are unsure -// of the quality of errno handling in libc. We broadcast MATH_ERREXCEPT as a -// minimum, leaving extension to include MATH_ERRNO as an option in the future. +// The UCRT defines this to be MATH_ERRNO | MATH_ERREXCEPT, but we're unsure of the quality of errno handling in libc. +// We broadcast MATH_ERREXCEPT as a minimum, keeping MATH_ERRNO as a potential future option. #define math_errhandling (MATH_ERREXCEPT) // These macro definitions were copied verbatim from the UCRT. The intent was @@ -163,7 +157,7 @@ using double_t = double; #define FP_ILOGB0 (-0x7fffffff - _C2) #define FP_ILOGBNAN 0x7fffffff -// These macro definitions were _not_ copied verbatim from the UCRT because we +// These macro definitions were *not* copied verbatim from the UCRT because we // are now able to take advantage of the __builtin_inf family. #define INFINITY (__builtin_inff()) #define HUGE_VALF (__builtin_inff()) @@ -172,16 +166,14 @@ using double_t = double; #define NAN (__builtin_nanf("")) // The nan family of functions is not routed to builtins because the builtins -// require a string literal argument and so cannot uphold the interface of -// these functions. +// require a string literal argument and so cannot uphold the interface of these functions. _NODISCARD float __cdecl nanf(const char*) noexcept /* strengthened */; _NODISCARD double __cdecl nan(const char*) noexcept /* strengthened */; _NODISCARD long double __cdecl nanl(const char*) noexcept /* strengthened */; -// Under /Oi (implied by /O2), MSVC treats the following functions as intrinsics that -// cannot be redefined. We use #pragma function to instruct MSVC to treat them as regular -// functions that can be defined, but we first need to declare the function before we can -// do so. +// Under /Oi (implied by /O2), MSVC treats the following functions as intrinsics that cannot be redefined. +// We use `#pragma function` to instruct MSVC to treat them as regular functions that can be defined, +// but we first need to declare them. _NODISCARD _CONSTEXPR_CMATH26 float __cdecl acosf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl acos(double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl asinf(float) noexcept; @@ -285,16 +277,14 @@ _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, expm1) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, hypot) _STL_DEF_FAMILY1(inline, nearbyint) -// libc does not yet implement lgamma or tgamma. Polyfilling with the UCRT's -// implementation pulls in the UCRT's fma, which results in linker errors due -// to our conflicting definition. Instead, we prearranged for implementations -// of lgamma and tgamma to be ready in the satellite lib. +// libc does not yet implement lgamma or tgamma. Polyfilling with the UCRT's implementation +// pulls in the UCRT's fma, which results in linker errors due to our conflicting definition. +// Instead, we prearranged for implementations of lgamma and tgamma to be ready in the satellite lib. // -// _CRT_SATELLITE_2 is commented out because it is undefined at the point of -// this header's inclusion. We'd normally address that by including yvals.h, -// but that makes this header non-core. Otherwise, this header can be a core -// header. The macro definition is empty in usage, so the comment has the same -// physical effect (though maybe a different mental effect). +// _CRT_SATELLITE_2 is commented out because it is undefined at the point of this header's inclusion. +// We'd normally address that by including yvals.h, but that makes this header non-core. +// Otherwise, this header can be a core header. The macro definition is empty in usage, +// so the comment has the same physical effect (though maybe a different mental effect). _NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_lgammaf(float) noexcept; _NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_lgamma(double) noexcept; _NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_tgammaf(float) noexcept; @@ -336,9 +326,8 @@ _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, tan) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, tanh) _STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) -// The UCRT defines the following functions on x86 as inline functions that -// forward to their double siblings, so forward-declaring them without defining -// them does not a successful polyfill make. +// The UCRT defines the following functions on x86 as inline functions that forward to their double siblings, +// so forward-declaring them without defining them does not result in a successful polyfill. #pragma function(coshf) _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl coshf(float _Xx) noexcept /* strengthened */ { return __builtin_coshf(_Xx); From b62dc1b416e880e0b68586615138c6b20aa704aa Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:12 -0700 Subject: [PATCH 43/85] __msvc_math.hpp: Reorder definitions to follow the Standard. --- stl/inc/__msvc_math.hpp | 224 +++++++++++++++++++--------------------- 1 file changed, 105 insertions(+), 119 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 714b14405f0..99825641787 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -245,113 +245,73 @@ _NODISCARD _CONSTEXPR_CMATH26 double __cdecl tan(double) noexcept; #pragma function(sqrtf, sqrt) #pragma function(tanf, tan) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, ceil) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, logb) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, fabs) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, round) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, trunc) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, floor) -_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmod) -_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, remainder) -_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, copysign) -_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, nextafter) -_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fdim) -_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmax) -_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmin) -_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, lround, long) -_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, llround, long long) +// The following order matches N5054 [cmath.syn]. _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, acos) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, acosh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, asin) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, asinh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, atan) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, atanh) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, cbrt) +// atan2() is hand-crafted _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, cos) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sin) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, tan) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, acosh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, asinh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, atanh) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, cosh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erf) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erfc) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, sinh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, tanh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, exp) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, exp2) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, expm1) -_STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, hypot) -_STL_DEF_FAMILY1(inline, nearbyint) - -// libc does not yet implement lgamma or tgamma. Polyfilling with the UCRT's implementation -// pulls in the UCRT's fma, which results in linker errors due to our conflicting definition. -// Instead, we prearranged for implementations of lgamma and tgamma to be ready in the satellite lib. -// -// _CRT_SATELLITE_2 is commented out because it is undefined at the point of this header's inclusion. -// We'd normally address that by including yvals.h, but that makes this header non-core. -// Otherwise, this header can be a core header. The macro definition is empty in usage, -// so the comment has the same physical effect (though maybe a different mental effect). -_NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_lgammaf(float) noexcept; -_NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_lgamma(double) noexcept; -_NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_tgammaf(float) noexcept; -_NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_tgamma(double) noexcept; - -_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl lgammaf(float _Xx) noexcept /* strengthened */ { - return __std_smf_lgammaf(_Xx); -} - -_NODISCARD _CONSTEXPR_CMATH26_NYI double __cdecl lgamma(double _Xx) noexcept /* strengthened */ { - return __std_smf_lgamma(_Xx); -} - -_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl lgammal(long double _Xx) noexcept /* strengthened */ { - return __std_smf_lgamma(static_cast(_Xx)); -} - -_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tgammaf(float _Xx) noexcept /* strengthened */ { - return __std_smf_tgammaf(_Xx); -} - -_NODISCARD _CONSTEXPR_CMATH26_NYI double __cdecl tgamma(double _Xx) noexcept /* strengthened */ { - return __std_smf_tgamma(_Xx); -} - -_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl tgammal(long double _Xx) noexcept /* strengthened */ { - return __std_smf_tgamma(static_cast(_Xx)); -} - +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, frexp, int*) +_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, ldexp, int) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log10) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log1p) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log2) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, logb) +// modf() is hand-crafted +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbn, int) +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbln, long) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, cbrt) +// abs() is in <__msvc_stdlib.hpp> +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, fabs) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, hypot) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, pow) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sin) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, sinh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sqrt) -_STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, tan) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, tanh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erf) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erfc) +// lgamma() is hand-crafted +// tgamma() is hand-crafted +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, ceil) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, floor) +_STL_DEF_FAMILY1(inline, nearbyint) +_STL_DEF_FAMILY1(inline, rint) +_STL_DEF_RETURN_FAMILY1(inline, lrint, long) +_STL_DEF_RETURN_FAMILY1(inline, llrint, long long) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, round) +_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, lround, long) +_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, llround, long long) +_STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, trunc) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmod) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, remainder) +_STL_DEF_LASTARG_FAMILY3(_CONSTEXPR_CMATH23, remquo, int*) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, copysign) +// nan() is declared above +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, nextafter) +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, nexttoward, long double) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fdim) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmax) +_STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmin) _STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) -// The UCRT defines the following functions on x86 as inline functions that forward to their double siblings, -// so forward-declaring them without defining them does not result in a successful polyfill. -#pragma function(coshf) -_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl coshf(float _Xx) noexcept /* strengthened */ { - return __builtin_coshf(_Xx); -} - -#pragma function(sinhf) -_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl sinhf(float _Xx) noexcept /* strengthened */ { - return __builtin_sinhf(_Xx); -} - -#pragma function(tanhf) -_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* strengthened */ { - return __builtin_tanhf(_Xx); -} - extern "C++" { _NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(float _Xx) noexcept /* strengthened */ { return __builtin_fpclassifyf(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); } - _NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(double _Xx) noexcept /* strengthened */ { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); } - _NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(long double _Xx) noexcept /* strengthened */ { return __builtin_fpclassifyl(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); } @@ -359,11 +319,9 @@ _NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(long double _Xx) noexcept / _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(float _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) <= 0; } - _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) <= 0; } - _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(long double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) <= 0; } @@ -371,11 +329,9 @@ _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(long double _Xx) noexcept /* _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(float _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_INFINITE; } - _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_INFINITE; } - _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(long double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_INFINITE; } @@ -383,11 +339,9 @@ _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(long double _Xx) noexcept /* st _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(float _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NAN; } - _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NAN; } - _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(long double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NAN; } @@ -395,11 +349,9 @@ _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(long double _Xx) noexcept /* st _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(float _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NORMAL; } - _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NORMAL; } - _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(long double _Xx) noexcept /* strengthened */ { return fpclassify(_Xx) == FP_NORMAL; } @@ -413,31 +365,6 @@ _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, islessgreater) _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isunordered) } // extern "C++" -_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, nexttoward, long double) -_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, frexp, int*) -_STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) -_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, ldexp, int) - -_NODISCARD _CONSTEXPR_CMATH23 float __cdecl modff(float _Xx0, float* _Xx1) noexcept /* strengthened */ { - return __builtin_modff(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 double __cdecl modf(double _Xx0, double* _Xx1) noexcept /* strengthened */ { - return __builtin_modf(_Xx0, _Xx1); -} - -_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl modfl(long double _Xx0, long double* _Xx1) noexcept -/* strengthened */ { - return __builtin_modfl(_Xx0, _Xx1); -} - -_STL_DEF_RETURN_FAMILY1(inline, lrint, long) -_STL_DEF_RETURN_FAMILY1(inline, llrint, long long) -_STL_DEF_FAMILY1(inline, rint) -_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbn, int) -_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbln, long) -_STL_DEF_LASTARG_FAMILY3(_CONSTEXPR_CMATH23, remquo, int*) - // Preserve the sign of zero when atan2 underflows. // __builtin_atan2 can return +0 for tiny negative results. _NODISCARD _CONSTEXPR_CMATH26 float __cdecl atan2f(float _Xx0, float _Xx1) noexcept /* strengthened */ { @@ -447,7 +374,6 @@ _NODISCARD _CONSTEXPR_CMATH26 float __cdecl atan2f(float _Xx0, float _Xx1) noexc } return _Result; } - _NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan2(double _Xx0, double _Xx1) noexcept /* strengthened */ { double _Result = static_cast(__builtin_atan2(_Xx0, _Xx1)); if (_Result == 0.0 && _Xx0 != 0.0) { @@ -455,7 +381,6 @@ _NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan2(double _Xx0, double _Xx1) noe } return _Result; } - _NODISCARD _CONSTEXPR_CMATH26 long double __cdecl atan2l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { long double _Result = static_cast(__builtin_atan2l(_Xx0, _Xx1)); @@ -465,6 +390,67 @@ _NODISCARD _CONSTEXPR_CMATH26 long double __cdecl atan2l(long double _Xx0, long return _Result; } +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl modff(float _Xx0, float* _Xx1) noexcept /* strengthened */ { + return __builtin_modff(_Xx0, _Xx1); +} +_NODISCARD _CONSTEXPR_CMATH23 double __cdecl modf(double _Xx0, double* _Xx1) noexcept /* strengthened */ { + return __builtin_modf(_Xx0, _Xx1); +} +_NODISCARD _CONSTEXPR_CMATH23 long double __cdecl modfl(long double _Xx0, long double* _Xx1) noexcept +/* strengthened */ { + return __builtin_modfl(_Xx0, _Xx1); +} + +// libc does not yet implement lgamma or tgamma. Polyfilling with the UCRT's implementation +// pulls in the UCRT's fma, which results in linker errors due to our conflicting definition. +// Instead, we prearranged for implementations of lgamma and tgamma to be ready in the satellite lib. +// +// _CRT_SATELLITE_2 is commented out because it is undefined at the point of this header's inclusion. +// We'd normally address that by including yvals.h, but that makes this header non-core. +// Otherwise, this header can be a core header. The macro definition is empty in usage, +// so the comment has the same physical effect (though maybe a different mental effect). +_NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_lgammaf(float) noexcept; +_NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_lgamma(double) noexcept; +_NODISCARD /*_CRT_SATELLITE_2*/ float __stdcall __std_smf_tgammaf(float) noexcept; +_NODISCARD /*_CRT_SATELLITE_2*/ double __stdcall __std_smf_tgamma(double) noexcept; + +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl lgammaf(float _Xx) noexcept /* strengthened */ { + return __std_smf_lgammaf(_Xx); +} +_NODISCARD _CONSTEXPR_CMATH26_NYI double __cdecl lgamma(double _Xx) noexcept /* strengthened */ { + return __std_smf_lgamma(_Xx); +} +_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl lgammal(long double _Xx) noexcept /* strengthened */ { + return __std_smf_lgamma(static_cast(_Xx)); +} + +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tgammaf(float _Xx) noexcept /* strengthened */ { + return __std_smf_tgammaf(_Xx); +} +_NODISCARD _CONSTEXPR_CMATH26_NYI double __cdecl tgamma(double _Xx) noexcept /* strengthened */ { + return __std_smf_tgamma(_Xx); +} +_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl tgammal(long double _Xx) noexcept /* strengthened */ { + return __std_smf_tgamma(static_cast(_Xx)); +} + +// The UCRT defines the following functions on x86 as inline functions that forward to their double siblings, +// so forward-declaring them without defining them does not result in a successful polyfill. +#pragma function(coshf) +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl coshf(float _Xx) noexcept /* strengthened */ { + return __builtin_coshf(_Xx); +} + +#pragma function(sinhf) +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl sinhf(float _Xx) noexcept /* strengthened */ { + return __builtin_sinhf(_Xx); +} + +#pragma function(tanhf) +_NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* strengthened */ { + return __builtin_tanhf(_Xx); +} + _NODISCARD double __cdecl _j0(double); _NODISCARD double __cdecl _j1(double); _NODISCARD double __cdecl _jn(int, double); From 0864fddd4cc07cbfffbb92b86c65c327495bee42 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:13 -0700 Subject: [PATCH 44/85] __msvc_math.hpp: We shouldn't need to static_cast the atan2 builtins. --- stl/inc/__msvc_math.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 99825641787..01703f6cd98 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -368,14 +368,14 @@ _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isunordered) // Preserve the sign of zero when atan2 underflows. // __builtin_atan2 can return +0 for tiny negative results. _NODISCARD _CONSTEXPR_CMATH26 float __cdecl atan2f(float _Xx0, float _Xx1) noexcept /* strengthened */ { - float _Result = static_cast(__builtin_atan2f(_Xx0, _Xx1)); + float _Result = __builtin_atan2f(_Xx0, _Xx1); if (_Result == 0.0F && _Xx0 != 0.0F) { return __builtin_copysignf(0.0F, _Xx0); } return _Result; } _NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan2(double _Xx0, double _Xx1) noexcept /* strengthened */ { - double _Result = static_cast(__builtin_atan2(_Xx0, _Xx1)); + double _Result = __builtin_atan2(_Xx0, _Xx1); if (_Result == 0.0 && _Xx0 != 0.0) { return __builtin_copysign(0.0, _Xx0); } @@ -383,7 +383,7 @@ _NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan2(double _Xx0, double _Xx1) noe } _NODISCARD _CONSTEXPR_CMATH26 long double __cdecl atan2l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - long double _Result = static_cast(__builtin_atan2l(_Xx0, _Xx1)); + long double _Result = __builtin_atan2l(_Xx0, _Xx1); if (_Result == 0.0L && _Xx0 != 0.0L) { return __builtin_copysignl(0.0L, _Xx0); } From 63851d0209dfdbd0ebcf95737044a8f4f18566a0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:14 -0700 Subject: [PATCH 45/85] __msvc_math.hpp: Comment that `_NODISCARD` is desirable for frexp/remquo/modf despite out-params. --- stl/inc/__msvc_math.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 01703f6cd98..96840a19091 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -262,7 +262,7 @@ _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, tanh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, exp) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, exp2) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, expm1) -_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, frexp, int*) +_STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, frexp, int*) // _NODISCARD is desirable, despite the out-param _STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, ldexp, int) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log) @@ -295,7 +295,7 @@ _STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, llround, long long) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, trunc) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmod) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, remainder) -_STL_DEF_LASTARG_FAMILY3(_CONSTEXPR_CMATH23, remquo, int*) +_STL_DEF_LASTARG_FAMILY3(_CONSTEXPR_CMATH23, remquo, int*) // _NODISCARD is desirable, despite the out-param _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, copysign) // nan() is declared above _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, nextafter) @@ -390,6 +390,7 @@ _NODISCARD _CONSTEXPR_CMATH26 long double __cdecl atan2l(long double _Xx0, long return _Result; } +// _NODISCARD is desirable, despite the out-param _NODISCARD _CONSTEXPR_CMATH23 float __cdecl modff(float _Xx0, float* _Xx1) noexcept /* strengthened */ { return __builtin_modff(_Xx0, _Xx1); } From 74aa36de5126aff1179b16ff1300047a331852c2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:15 -0700 Subject: [PATCH 46/85] __msvc_math.hpp: [Copilot review] Add `_CONSTEXPR_CMATH26_NYI_DECL` to avoid inline declarations. --- stl/inc/__msvc_math.hpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 96840a19091..389556eb41f 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -120,8 +120,9 @@ extern "C" { // Some functions that are needed for C++26 constexpr cmath are not yet implemented by libc. // We polyfill the library with the UCRT and mark these functions with this macro. -// The resulting declarations are not able to be used during constant-evaluation yet. -#define _CONSTEXPR_CMATH26_NYI inline +// The resulting declarations are not able to be used during constant evaluation yet. +#define _CONSTEXPR_CMATH26_NYI inline +#define _CONSTEXPR_CMATH26_NYI_DECL _EMPTY_ARGUMENT // On x86, when not using /arch:SSE2 or greater, floating-point operations are performed // using the x87 instruction set and FLT_EVAL_METHOD is 2. (When /fp:fast is used, @@ -253,14 +254,14 @@ _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, atan) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, cos) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sin) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, tan) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, acosh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, asinh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, atanh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, cosh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, sinh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, tanh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, acosh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, asinh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, atanh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, cosh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, sinh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, tanh) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, exp) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, exp2) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, exp2) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, expm1) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, frexp, int*) // _NODISCARD is desirable, despite the out-param _STL_DEF_RETURN_FAMILY1(_CONSTEXPR_CMATH23, ilogb, int) @@ -279,8 +280,8 @@ _STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, fabs) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, hypot) _STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, pow) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sqrt) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erf) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI, erfc) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, erf) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, erfc) // lgamma() is hand-crafted // tgamma() is hand-crafted _STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, ceil) From 20fdf6640d0c7ef23c53cc38d0db1658c4bff869 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:15 -0700 Subject: [PATCH 47/85] __msvc_math.hpp: [Copilot review] Comment about the absence of Microsoft-specific stuff. --- stl/inc/__msvc_math.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 389556eb41f..9159b7d86f0 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -17,6 +17,7 @@ // Because this file is intended to supersede the UCRT's math components, we define the _INC_MATH macro // to neutralize the contents of math.h when it is processed after. _INC_MATH is used as the include guard // for the UCRT's math.h and is an intended public API. +// This file intentionally avoids providing most of the Microsoft-specific/non-Standard machinery in math.h. #define _INC_MATH #include From 31024fadc49c7e695fc70ca0aa8800ba2e815440 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:16 -0700 Subject: [PATCH 48/85] __msvc_math.hpp: Drop `_j0`/`j0` etc. Bessel functions, superseded by Special Math. --- stl/inc/__msvc_math.hpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 9159b7d86f0..ad70a1677f8 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -454,25 +454,6 @@ _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* str return __builtin_tanhf(_Xx); } -_NODISCARD double __cdecl _j0(double); -_NODISCARD double __cdecl _j1(double); -_NODISCARD double __cdecl _jn(int, double); -_NODISCARD double __cdecl _y0(double); -_NODISCARD double __cdecl _y1(double); -_NODISCARD double __cdecl _yn(int, double); - -#if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES - -// These functions are included in the Open Group Standard Base Specifications. -_NODISCARD double __cdecl j0(double); -_NODISCARD double __cdecl j1(double); -_NODISCARD double __cdecl jn(int, double); -_NODISCARD double __cdecl y0(double); -_NODISCARD double __cdecl y1(double); -_NODISCARD double __cdecl yn(int, double); - -#endif // defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES - #undef _STL_DEF_FUNC1 #undef _STL_DEF_FUNC2 #undef _STL_DEF_FUNC3 From 77e6e2c3a4ab95995652d2bdb83e9f546a6872e9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:17 -0700 Subject: [PATCH 49/85] __msvc_math.hpp: Drop `_USE_MATH_DEFINES` including ``, superseded by ``. --- stl/inc/__msvc_math.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index ad70a1677f8..c200c2f1abc 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -3,13 +3,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This lies outside of the inclusion guard because the UCRT's math.h allows for repeated inclusion -// with behavioral differences dictated by this macro. math.h can be included once without this macro -// defined and a second time with it defined, resulting in the nonstandard math constants being defined. -#ifdef _USE_MATH_DEFINES -#include -#endif - #ifndef __MSVC_MATH_HPP #define __MSVC_MATH_HPP From f3712452542c545bdf922806e7271cfe9e6a36dc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:18 -0700 Subject: [PATCH 50/85] __msvc_math.hpp: OVERLOADED_PREDICATE => OVERLOADED_COMPARISON --- stl/inc/__msvc_math.hpp | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index c200c2f1abc..2ccb0142a7e 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -79,27 +79,27 @@ extern "C" { _STL_DEF_FUNC3(specs, name##l, long double, long double, long double, lastarg) // N.B. static_cast is used when the builtin returns int. -#define _STL_DEF_OVERLOADED_PREDICATE1(specs, name, builtin, fptype) \ +#define _STL_DEF_OVERLOADED_COMPARISON1(specs, name, builtin, fptype) \ _NODISCARD specs bool __cdecl name(fptype _Xx) noexcept /* strengthened */ { \ return static_cast(builtin(_Xx)); \ } -#define _STL_DEF_OVERLOADED_PREDICATE2(specs, name, builtin, fptype) \ +#define _STL_DEF_OVERLOADED_COMPARISON2(specs, name, builtin, fptype) \ _NODISCARD specs bool __cdecl name(fptype _Xx0, fptype _Xx1) noexcept /* strengthened */ { \ return static_cast(builtin(_Xx0, _Xx1)); \ } // Defines three overloaded functions with signature `bool (fp-type)`. -#define _STL_DEF_OVERLOADED_PREDICATE_FAMILY1(specs, name) \ - _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name##f, float) \ - _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name, double) \ - _STL_DEF_OVERLOADED_PREDICATE1(specs, name, __builtin_##name##l, long double) +#define _STL_DEF_OVERLOADED_COMPARISON_FAMILY1(specs, name) \ + _STL_DEF_OVERLOADED_COMPARISON1(specs, name, __builtin_##name##f, float) \ + _STL_DEF_OVERLOADED_COMPARISON1(specs, name, __builtin_##name, double) \ + _STL_DEF_OVERLOADED_COMPARISON1(specs, name, __builtin_##name##l, long double) // Defines four overloaded functions with signature `bool (fp-type, fp-type)`. -#define _STL_DEF_OVERLOADED_PREDICATE_FAMILY2(specs, name) \ - _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name##f, float) \ - _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name, double) \ - _STL_DEF_OVERLOADED_PREDICATE2(specs, name, __builtin_##name##l, long double) \ +#define _STL_DEF_OVERLOADED_COMPARISON_FAMILY2(specs, name) \ + _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name##f, float) \ + _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name, double) \ + _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name##l, long double) \ template \ _NODISCARD specs bool __cdecl name(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { \ return static_cast(__builtin_##name(static_cast(_Xx0), static_cast(_Xx1))); \ @@ -351,13 +351,13 @@ _NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(long double _Xx) noexcept /* return fpclassify(_Xx) == FP_NORMAL; } -_STL_DEF_OVERLOADED_PREDICATE_FAMILY1(_CONSTEXPR_CMATH23, signbit) -_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isgreater) -_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isgreaterequal) -_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isless) -_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, islessequal) -_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, islessgreater) -_STL_DEF_OVERLOADED_PREDICATE_FAMILY2(_CONSTEXPR_CMATH23, isunordered) +_STL_DEF_OVERLOADED_COMPARISON_FAMILY1(_CONSTEXPR_CMATH23, signbit) +_STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, isgreater) +_STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, isgreaterequal) +_STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, isless) +_STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, islessequal) +_STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, islessgreater) +_STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, isunordered) } // extern "C++" // Preserve the sign of zero when atan2 underflows. @@ -456,10 +456,10 @@ _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* str #undef _STL_DEF_RETURN_FAMILY1 #undef _STL_DEF_LASTARG_FAMILY2 #undef _STL_DEF_LASTARG_FAMILY3 -#undef _STL_DEF_OVERLOADED_PREDICATE1 -#undef _STL_DEF_OVERLOADED_PREDICATE2 -#undef _STL_DEF_OVERLOADED_PREDICATE_FAMILY1 -#undef _STL_DEF_OVERLOADED_PREDICATE_FAMILY2 +#undef _STL_DEF_OVERLOADED_COMPARISON1 +#undef _STL_DEF_OVERLOADED_COMPARISON2 +#undef _STL_DEF_OVERLOADED_COMPARISON_FAMILY1 +#undef _STL_DEF_OVERLOADED_COMPARISON_FAMILY2 #undef _STL_DECLARE_FAMILY1 #undef _CONSTEXPR_CMATH26_NYI From ce57dd54bb3c876e03ede3331448a2a646b23df3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:19 -0700 Subject: [PATCH 51/85] __msvc_math.hpp: Extract `_STL_DEF_OVERLOADED_CLASSIFICATION_FAMILY1`. --- stl/inc/__msvc_math.hpp | 67 +++++++++++------------------------------ 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 2ccb0142a7e..06f3803eb97 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -78,6 +78,17 @@ extern "C" { _STL_DEF_FUNC3(specs, name, double, double, double, lastarg) \ _STL_DEF_FUNC3(specs, name##l, long double, long double, long double, lastarg) +#define _STL_DEF_OVERLOADED_CLASSIFICATION1(specs, ret, name, op_val, builtin, fptype) \ + _NODISCARD specs ret __cdecl name(fptype _Xx) noexcept /* strengthened */ { \ + return builtin(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx) op_val; \ + } + +// Defines three overloaded functions with signature `ret (fp-type)`. +#define _STL_DEF_OVERLOADED_CLASSIFICATION_FAMILY1(specs, ret, name, op_val) \ + _STL_DEF_OVERLOADED_CLASSIFICATION1(specs, ret, name, op_val, __builtin_fpclassifyf, float) \ + _STL_DEF_OVERLOADED_CLASSIFICATION1(specs, ret, name, op_val, __builtin_fpclassify, double) \ + _STL_DEF_OVERLOADED_CLASSIFICATION1(specs, ret, name, op_val, __builtin_fpclassifyl, long double) + // N.B. static_cast is used when the builtin returns int. #define _STL_DEF_OVERLOADED_COMPARISON1(specs, name, builtin, fptype) \ _NODISCARD specs bool __cdecl name(fptype _Xx) noexcept /* strengthened */ { \ @@ -301,55 +312,11 @@ _STL_DEF_FAMILY2(_CONSTEXPR_CMATH23, fmin) _STL_DEF_FAMILY3(_CONSTEXPR_CMATH23, fma) extern "C++" { -_NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(float _Xx) noexcept /* strengthened */ { - return __builtin_fpclassifyf(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); -} -_NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(double _Xx) noexcept /* strengthened */ { - return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); -} -_NODISCARD _CONSTEXPR_CMATH23 int __cdecl fpclassify(long double _Xx) noexcept /* strengthened */ { - return __builtin_fpclassifyl(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, _Xx); -} - -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(float _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) <= 0; -} -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(double _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) <= 0; -} -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isfinite(long double _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) <= 0; -} - -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(float _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_INFINITE; -} -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(double _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_INFINITE; -} -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isinf(long double _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_INFINITE; -} - -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(float _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_NAN; -} -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(double _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_NAN; -} -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnan(long double _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_NAN; -} - -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(float _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_NORMAL; -} -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(double _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_NORMAL; -} -_NODISCARD _CONSTEXPR_CMATH23 bool __cdecl isnormal(long double _Xx) noexcept /* strengthened */ { - return fpclassify(_Xx) == FP_NORMAL; -} +_STL_DEF_OVERLOADED_CLASSIFICATION_FAMILY1(_CONSTEXPR_CMATH23, int, fpclassify, /*unchanged*/) +_STL_DEF_OVERLOADED_CLASSIFICATION_FAMILY1(_CONSTEXPR_CMATH23, bool, isfinite, <= 0) +_STL_DEF_OVERLOADED_CLASSIFICATION_FAMILY1(_CONSTEXPR_CMATH23, bool, isinf, == FP_INFINITE) +_STL_DEF_OVERLOADED_CLASSIFICATION_FAMILY1(_CONSTEXPR_CMATH23, bool, isnan, == FP_NAN) +_STL_DEF_OVERLOADED_CLASSIFICATION_FAMILY1(_CONSTEXPR_CMATH23, bool, isnormal, == FP_NORMAL) _STL_DEF_OVERLOADED_COMPARISON_FAMILY1(_CONSTEXPR_CMATH23, signbit) _STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, isgreater) @@ -456,6 +423,8 @@ _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* str #undef _STL_DEF_RETURN_FAMILY1 #undef _STL_DEF_LASTARG_FAMILY2 #undef _STL_DEF_LASTARG_FAMILY3 +#undef _STL_DEF_OVERLOADED_CLASSIFICATION1 +#undef _STL_DEF_OVERLOADED_CLASSIFICATION_FAMILY1 #undef _STL_DEF_OVERLOADED_COMPARISON1 #undef _STL_DEF_OVERLOADED_COMPARISON2 #undef _STL_DEF_OVERLOADED_COMPARISON_FAMILY1 From b799b2570e7dc3bed58eb95e666f1995c8b809c3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:20 -0700 Subject: [PATCH 52/85] __msvc_math.hpp: Fix ARM64 error C2169: 'fabsf': intrinsic function, cannot be defined --- stl/inc/__msvc_math.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 06f3803eb97..526cabf67c4 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -196,6 +196,7 @@ _NODISCARD _CONSTEXPR_CMATH26 float __cdecl cosf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl cos(double) noexcept; _NODISCARD _CONSTEXPR_CMATH26 float __cdecl expf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH26 double __cdecl exp(double) noexcept; +_NODISCARD _CONSTEXPR_CMATH23 float __cdecl fabsf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH23 double __cdecl fabs(double) noexcept; _NODISCARD _CONSTEXPR_CMATH23 float __cdecl floorf(float) noexcept; _NODISCARD _CONSTEXPR_CMATH23 double __cdecl floor(double) noexcept; @@ -236,7 +237,7 @@ _NODISCARD _CONSTEXPR_CMATH26 double __cdecl tan(double) noexcept; #pragma function(copysignf, copysign) #pragma function(cosf, cos) #pragma function(expf, exp) -#pragma function(fabs) +#pragma function(fabsf, fabs) #pragma function(floorf, floor) #pragma function(fmaf, fma, fmal) #pragma function(fmaxf, fmax, fmaxl) From 7c2a0a75579e32eecedceccec274cf040709f563 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:21 -0700 Subject: [PATCH 53/85] cmath: Cleanup comments. --- stl/inc/cmath | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 33231e32ab2..13685b395da 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -17,14 +17,12 @@ #define _HAS_CMATH_INTRINSICS 0 #endif // ^^^ intrinsics unavailable ^^^ -// MSVC provides builtins for math functions in C++23 and later if the user -// has not specified -Zc:cmath-. The compiler defines the macro below to make -// detection simpler. +// MSVC provides constexpr builtins in C++23 and later, except when /Zc:cmath- opts out of constexpr. #if defined(__clang__) || defined(_MSVC_CONSTEXPR_CMATH) #define _HAS_CMATH_BUILTINS 1 #else // ^^^ builtins available / builtins unavailable vvv #define _HAS_CMATH_BUILTINS 0 -#endif +#endif // ^^^ builtins unavailable ^^^ #if _HAS_CMATH_INTRINSICS #include _STL_INTRIN_HEADER @@ -330,7 +328,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double ceil(_In_ long double _ return __ceil(static_cast(_Xx)); #elif _HAS_CMATH_BUILTINS return __builtin_ceill(_Xx); -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD ceill(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -342,7 +340,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double copysign( return __copysign(static_cast(_Number), static_cast(_Sign)); #elif _HAS_CMATH_BUILTINS return __builtin_copysignl(_Number, _Sign); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv return _CSTD copysignl(_Number, _Sign); #endif // ^^^ intrinsics unavailable ^^^ } From 63e60b370d2e76d219afcb16d7dee09d9c8c369b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:22 -0700 Subject: [PATCH 54/85] cmath: Change `_GENERIC_MATH1I`, `_GENERIC_MATH2I` to directly use the builtins for ceil, floor, round, trunc, copysign. --- stl/inc/cmath | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 13685b395da..66c948ef3e9 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -772,9 +772,9 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #if _HAS_CMATH_INTRINSICS #define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, MSVC_INTRIN) -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS #define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, CLANG_INTRIN) -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv #define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ @@ -801,9 +801,9 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #if _HAS_CMATH_INTRINSICS #define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, MSVC_INTRIN) -#elif defined(__clang__) +#elif _HAS_CMATH_BUILTINS #define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, CLANG_INTRIN) -#else // ^^^ defined(__clang__) / intrinsics unavailable vvv +#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv #define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ From 177ed2ad507b618e7829db7a9e6b920c0479313a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:23 -0700 Subject: [PATCH 55/85] cmath: Define `_HAS_CMATH_BUILTINS` first, as `_HAS_CMATH_INTRINSICS` De Morgans it. --- stl/inc/cmath | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 66c948ef3e9..e7c69193139 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -11,12 +11,6 @@ #include #include -#if !defined(__clang__) && !defined(_M_CEE) && !defined(_MSVC_CONSTEXPR_CMATH) // TRANSITION, VSO-1663104 -#define _HAS_CMATH_INTRINSICS 1 -#else // ^^^ intrinsics available / intrinsics unavailable vvv -#define _HAS_CMATH_INTRINSICS 0 -#endif // ^^^ intrinsics unavailable ^^^ - // MSVC provides constexpr builtins in C++23 and later, except when /Zc:cmath- opts out of constexpr. #if defined(__clang__) || defined(_MSVC_CONSTEXPR_CMATH) #define _HAS_CMATH_BUILTINS 1 @@ -24,6 +18,12 @@ #define _HAS_CMATH_BUILTINS 0 #endif // ^^^ builtins unavailable ^^^ +#if !_HAS_CMATH_BUILTINS && !defined(_M_CEE) // TRANSITION, VSO-1663104 +#define _HAS_CMATH_INTRINSICS 1 +#else // ^^^ intrinsics available / intrinsics unavailable vvv +#define _HAS_CMATH_INTRINSICS 0 +#endif // ^^^ intrinsics unavailable ^^^ + #if _HAS_CMATH_INTRINSICS #include _STL_INTRIN_HEADER #endif // _HAS_CMATH_INTRINSICS From adb92dfc7a39215046854a1c9b8a74705954e9a2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:23 -0700 Subject: [PATCH 56/85] cmath: Restore std::fma overloads for float and long double, now marked `_CONSTEXPR_CMATH23`. --- stl/inc/cmath | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/stl/inc/cmath b/stl/inc/cmath index e7c69193139..68b1c5ef046 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -135,6 +135,11 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float floor(_In_ float _Xx) noexcep #endif // ^^^ intrinsics unavailable ^^^ } +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fma(_In_ float _Xx, _In_ float _Yx, _In_ float _Zx) noexcept +/* strengthened */ { + return _CSTD fmaf(_Xx, _Yx, _Zx); +} + _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fmax(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { return _CSTD fmaxf(_Xx, _Yx); } @@ -392,6 +397,11 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double floor(_In_ long double #endif // ^^^ intrinsics unavailable ^^^ } +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fma( + _In_ long double _Xx, _In_ long double _Yx, _In_ long double _Zx) noexcept /* strengthened */ { + return _CSTD fmal(_Xx, _Yx, _Zx); +} + _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fmax(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD fmaxl(_Xx, _Yx); From c0a103dfa8c644418cadb9ea8069437f2940fb89 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:24 -0700 Subject: [PATCH 57/85] cmath: Add missing `_CONSTEXPR_CMATH23` to std::modf overloads for float, long double. --- stl/inc/cmath | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 68b1c5ef046..99159d65caf 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -208,7 +208,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long lround(_In_ float _Xx) noexcep return _CSTD lroundf(_Xx); } -inline float modf(_In_ float _Xx, _Out_ float* _Yx) noexcept /* strengthened */ { +_CONSTEXPR_CMATH23 float modf(_In_ float _Xx, _Out_ float* _Yx) noexcept /* strengthened */ { return _CSTD modff(_Xx, _Yx); } @@ -475,7 +475,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long lround(_In_ long double _Xx) n return _CSTD lroundl(_Xx); } -inline long double modf(_In_ long double _Xx, _Out_ long double* _Yx) noexcept /* strengthened */ { +_CONSTEXPR_CMATH23 long double modf(_In_ long double _Xx, _Out_ long double* _Yx) noexcept /* strengthened */ { return _CSTD modfl(_Xx, _Yx); } From ac52da3f9eab635fecf0248fcbcfc68bf5e20adb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:25 -0700 Subject: [PATCH 58/85] cmath: Remove `_CONSTEXPR_CMATH26` from acosh; it's NYI in __msvc_math.hpp. --- stl/inc/cmath | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 99159d65caf..98fd4249290 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -40,7 +40,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float acos(_In_ float _Xx) noexcept return _CSTD acosf(_Xx); } -_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float acosh(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ inline float acosh(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD acoshf(_Xx); } @@ -299,7 +299,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double acos(_In_ long double _ return _CSTD acosl(_Xx); } -_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double acosh(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ inline long double acosh(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD acoshl(_Xx); } From 5c1bad6fdfd14af7c57d2b8820848d82e11f570f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:26 -0700 Subject: [PATCH 59/85] cmath: Add `_CONSTEXPR_CMATH26` to match __msvc_math.hpp. --- stl/inc/cmath | 67 ++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 98fd4249290..d73422b95f4 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -44,7 +44,7 @@ _NODISCARD _Check_return_ inline float acosh(_In_ float _Xx) noexcept /* strengt return _CSTD acoshf(_Xx); } -_NODISCARD _Check_return_ inline float asin(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float asin(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD asinf(_Xx); } @@ -52,7 +52,7 @@ _NODISCARD _Check_return_ inline float asinh(_In_ float _Xx) noexcept /* strengt return _CSTD asinhf(_Xx); } -_NODISCARD _Check_return_ inline float atan(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float atan(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD atanf(_Xx); } @@ -60,11 +60,11 @@ _NODISCARD _Check_return_ inline float atanh(_In_ float _Xx) noexcept /* strengt return _CSTD atanhf(_Xx); } -_NODISCARD _Check_return_ inline float atan2(_In_ float _Yx, _In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float atan2(_In_ float _Yx, _In_ float _Xx) noexcept /* strengthened */ { return _CSTD atan2f(_Yx, _Xx); } -_NODISCARD _Check_return_ inline float cbrt(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float cbrt(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD cbrtf(_Xx); } @@ -89,7 +89,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float copysign(_In_ float _Number, #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline float cos(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float cos(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD cosf(_Xx); } @@ -105,7 +105,7 @@ _NODISCARD _Check_return_ inline float erfc(_In_ float _Xx) noexcept /* strength return _CSTD erfcf(_Xx); } -_NODISCARD _Check_return_ inline float exp(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float exp(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD expf(_Xx); } @@ -113,7 +113,7 @@ _NODISCARD _Check_return_ inline float exp2(_In_ float _Xx) noexcept /* strength return _CSTD exp2f(_Xx); } -_NODISCARD _Check_return_ inline float expm1(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float expm1(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD expm1f(_Xx); } @@ -156,7 +156,7 @@ _CONSTEXPR_CMATH23 float frexp(_In_ float _Xx, _Out_ int* _Yx) noexcept /* stren return _CSTD frexpf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float hypot(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float hypot(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { return _CSTD hypotf(_Xx, _Yx); } @@ -180,19 +180,19 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long long llround(_In_ float _Xx) n return _CSTD llroundf(_Xx); } -_NODISCARD _Check_return_ inline float log(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float log(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD logf(_Xx); } -_NODISCARD _Check_return_ inline float log10(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float log10(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD log10f(_Xx); } -_NODISCARD _Check_return_ inline float log1p(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float log1p(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD log1pf(_Xx); } -_NODISCARD _Check_return_ inline float log2(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float log2(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD log2f(_Xx); } @@ -226,7 +226,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float nexttoward(_In_ float _Xx, _I return _CSTD nexttowardf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float pow(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float pow(_In_ float _Xx, _In_ float _Yx) noexcept /* strengthened */ { return _CSTD powf(_Xx, _Yx); } @@ -261,7 +261,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float scalbn(_In_ float _Xx, _In_ i return _CSTD scalbnf(_Xx, _Yx); } -_NODISCARD _Check_return_ inline float sin(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float sin(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD sinf(_Xx); } @@ -269,11 +269,11 @@ _NODISCARD _Check_return_ inline float sinh(_In_ float _Xx) noexcept /* strength return _CSTD sinhf(_Xx); } -_NODISCARD _Check_return_ inline float sqrt(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float sqrt(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD sqrtf(_Xx); } -_NODISCARD _Check_return_ inline float tan(_In_ float _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float tan(_In_ float _Xx) noexcept /* strengthened */ { return _CSTD tanf(_Xx); } @@ -303,7 +303,7 @@ _NODISCARD _Check_return_ inline long double acosh(_In_ long double _Xx) noexcep return _CSTD acoshl(_Xx); } -_NODISCARD _Check_return_ inline long double asin(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double asin(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD asinl(_Xx); } @@ -311,7 +311,7 @@ _NODISCARD _Check_return_ inline long double asinh(_In_ long double _Xx) noexcep return _CSTD asinhl(_Xx); } -_NODISCARD _Check_return_ inline long double atan(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double atan(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD atanl(_Xx); } @@ -319,12 +319,12 @@ _NODISCARD _Check_return_ inline long double atanh(_In_ long double _Xx) noexcep return _CSTD atanhl(_Xx); } -_NODISCARD _Check_return_ inline long double atan2(_In_ long double _Yx, _In_ long double _Xx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double atan2(_In_ long double _Yx, _In_ long double _Xx) noexcept /* strengthened */ { return _CSTD atan2l(_Yx, _Xx); } -_NODISCARD _Check_return_ inline long double cbrt(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double cbrt(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD cbrtl(_Xx); } @@ -350,7 +350,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double copysign( #endif // ^^^ intrinsics unavailable ^^^ } -_NODISCARD _Check_return_ inline long double cos(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double cos(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD cosl(_Xx); } @@ -366,7 +366,7 @@ _NODISCARD _Check_return_ inline long double erfc(_In_ long double _Xx) noexcept return _CSTD erfcl(_Xx); } -_NODISCARD _Check_return_ inline long double exp(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double exp(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD expl(_Xx); } @@ -374,7 +374,7 @@ _NODISCARD _Check_return_ inline long double exp2(_In_ long double _Xx) noexcept return _CSTD exp2l(_Xx); } -_NODISCARD _Check_return_ inline long double expm1(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double expm1(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD expm1l(_Xx); } @@ -421,7 +421,7 @@ _CONSTEXPR_CMATH23 long double frexp(_In_ long double _Xx, _Out_ int* _Yx) noexc return _CSTD frexpl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double hypot(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double hypot(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD hypotl(_Xx, _Yx); } @@ -447,19 +447,19 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long long llround(_In_ long double return _CSTD llroundl(_Xx); } -_NODISCARD _Check_return_ inline long double log(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double log(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD logl(_Xx); } -_NODISCARD _Check_return_ inline long double log10(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double log10(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD log10l(_Xx); } -_NODISCARD _Check_return_ inline long double log1p(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double log1p(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD log1pl(_Xx); } -_NODISCARD _Check_return_ inline long double log2(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double log2(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD log2l(_Xx); } @@ -493,7 +493,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double nexttoward(_In_ long do return _CSTD nexttowardl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double pow(_In_ long double _Xx, _In_ long double _Yx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double pow(_In_ long double _Xx, _In_ long double _Yx) noexcept /* strengthened */ { return _CSTD powl(_Xx, _Yx); } @@ -532,7 +532,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double scalbn(_In_ long double return _CSTD scalbnl(_Xx, _Yx); } -_NODISCARD _Check_return_ inline long double sin(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double sin(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD sinl(_Xx); } @@ -540,11 +540,11 @@ _NODISCARD _Check_return_ inline long double sinh(_In_ long double _Xx) noexcept return _CSTD sinhl(_Xx); } -_NODISCARD _Check_return_ inline long double sqrt(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double sqrt(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD sqrtl(_Xx); } -_NODISCARD _Check_return_ inline long double tan(_In_ long double _Xx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double tan(_In_ long double _Xx) noexcept /* strengthened */ { return _CSTD tanl(_Xx); } @@ -581,7 +581,8 @@ double frexp(_Ty _Value, _Out_ int* const _Exp) noexcept /* strengthened */ { } template && _STD is_arithmetic_v<_Ty2>, int> = 0> -_NODISCARD _STD _Common_float_type_t<_Ty1, _Ty2> pow(_Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26 _STD _Common_float_type_t<_Ty1, _Ty2> pow(_Ty1 _Left, _Ty2 _Right) noexcept +/* strengthened */ { if constexpr (_STD _Is_nonbool_integral<_Ty2>) { if (_Right == 2) { return static_cast(_Left) * static_cast(_Left); // TRANSITION, see GH-5768 From 0cdcc24d3a89a2ff7020165d4852ae252830c9ba Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:27 -0700 Subject: [PATCH 60/85] cmath: Comment how we prefer builtins before intrinsics. --- stl/inc/cmath | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/cmath b/stl/inc/cmath index d73422b95f4..a4497604e42 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -18,6 +18,7 @@ #define _HAS_CMATH_BUILTINS 0 #endif // ^^^ builtins unavailable ^^^ +// When constexpr builtins are unavailable, fall back to intrinsics for better codegen. #if !_HAS_CMATH_BUILTINS && !defined(_M_CEE) // TRANSITION, VSO-1663104 #define _HAS_CMATH_INTRINSICS 1 #else // ^^^ intrinsics available / intrinsics unavailable vvv From be992760b77eaade3d3a7ecfa0c97d5813d71955 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:28 -0700 Subject: [PATCH 61/85] cmath: Reorder preprocessing to check builtins before intrinsics. --- stl/inc/cmath | 96 +++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index a4497604e42..125893f6ace 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -70,22 +70,22 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH26 float cbrt(_In_ float _Xx) noexcept } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float ceil(_In_ float _Xx) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __ceilf(_Xx); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_ceilf(_Xx); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __ceilf(_Xx); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD ceilf(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float copysign(_In_ float _Number, _In_ float _Sign) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __copysignf(_Number, _Sign); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_copysignf(_Number, _Sign); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __copysignf(_Number, _Sign); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD copysignf(_Number, _Sign); #endif // ^^^ intrinsics unavailable ^^^ } @@ -127,11 +127,11 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fdim(_In_ float _Xx, _In_ flo } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float floor(_In_ float _Xx) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __floorf(_Xx); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_floorf(_Xx); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __floorf(_Xx); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD floorf(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -245,11 +245,11 @@ _NODISCARD _Check_return_ inline float rint(_In_ float _Xx) noexcept /* strength } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float round(_In_ float _Xx) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __roundf(_Xx); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_roundf(_Xx); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __roundf(_Xx); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD roundf(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -287,11 +287,11 @@ _NODISCARD _Check_return_ inline float tgamma(_In_ float _Xx) noexcept /* streng } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float trunc(_In_ float _Xx) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __truncf(_Xx); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_truncf(_Xx); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __truncf(_Xx); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD truncf(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -330,11 +330,11 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH26 long double cbrt(_In_ long double _ } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double ceil(_In_ long double _Xx) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __ceil(static_cast(_Xx)); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_ceill(_Xx); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __ceil(static_cast(_Xx)); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD ceill(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -342,11 +342,11 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double ceil(_In_ long double _ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double copysign( _In_ long double _Number, _In_ long double _Sign) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __copysign(static_cast(_Number), static_cast(_Sign)); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_copysignl(_Number, _Sign); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __copysign(static_cast(_Number), static_cast(_Sign)); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD copysignl(_Number, _Sign); #endif // ^^^ intrinsics unavailable ^^^ } @@ -389,11 +389,11 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fdim(_In_ long double _ } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double floor(_In_ long double _Xx) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __floor(static_cast(_Xx)); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_floorl(_Xx); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __floor(static_cast(_Xx)); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD floorl(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -514,11 +514,11 @@ _NODISCARD _Check_return_ inline long double rint(_In_ long double _Xx) noexcept } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double round(_In_ long double _Xx) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __round(static_cast(_Xx)); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_roundl(_Xx); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __round(static_cast(_Xx)); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD roundl(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -558,11 +558,11 @@ _NODISCARD _Check_return_ inline long double tgamma(_In_ long double _Xx) noexce } _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double trunc(_In_ long double _Xx) noexcept /* strengthened */ { -#if _HAS_CMATH_INTRINSICS - return __trunc(static_cast(_Xx)); -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS return __builtin_truncl(_Xx); -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS + return __trunc(static_cast(_Xx)); +#else // ^^^ intrinsics available / intrinsics unavailable vvv return _CSTD truncl(_Xx); #endif // ^^^ intrinsics unavailable ^^^ } @@ -782,11 +782,11 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #define _GENERIC_MATH1R(FUN, RET) _GENERIC_MATH1_BASE(FUN, RET, _CSTD FUN) #define _GENERIC_MATH1(FUN) _GENERIC_MATH1R(FUN, double) -#if _HAS_CMATH_INTRINSICS -#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, MSVC_INTRIN) -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS #define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, CLANG_INTRIN) -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS +#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, MSVC_INTRIN) +#else // ^^^ intrinsics available / intrinsics unavailable vvv #define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ @@ -811,11 +811,11 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #define _GENERIC_MATH2(FUN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) -#if _HAS_CMATH_INTRINSICS -#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, MSVC_INTRIN) -#elif _HAS_CMATH_BUILTINS +#if _HAS_CMATH_BUILTINS #define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, CLANG_INTRIN) -#else // ^^^ _HAS_CMATH_BUILTINS / intrinsics unavailable vvv +#elif _HAS_CMATH_INTRINSICS +#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, MSVC_INTRIN) +#else // ^^^ intrinsics available / intrinsics unavailable vvv #define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ From 55e8e0eba23e29a96453ab2624d7b858bc80af97 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:29 -0700 Subject: [PATCH 62/85] cmath: Rename macro params for clarity, CLANG_INTRIN => BUILTIN and MSVC_INTRIN => INTRINSIC. --- stl/inc/cmath | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 125893f6ace..599e5c5fbf3 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -783,11 +783,11 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #define _GENERIC_MATH1(FUN) _GENERIC_MATH1R(FUN, double) #if _HAS_CMATH_BUILTINS -#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, CLANG_INTRIN) +#define _GENERIC_MATH1I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(FUN, double, BUILTIN) #elif _HAS_CMATH_INTRINSICS -#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, MSVC_INTRIN) +#define _GENERIC_MATH1I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(FUN, double, INTRINSIC) #else // ^^^ intrinsics available / intrinsics unavailable vvv -#define _GENERIC_MATH1I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH1_BASE(FUN, double, _CSTD FUN) +#define _GENERIC_MATH1I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(FUN, double, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ #define _GENERIC_MATH1X(FUN, ARG2) \ @@ -812,11 +812,11 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #define _GENERIC_MATH2(FUN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) #if _HAS_CMATH_BUILTINS -#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, CLANG_INTRIN) +#define _GENERIC_MATH2I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(FUN, BUILTIN) #elif _HAS_CMATH_INTRINSICS -#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, MSVC_INTRIN) +#define _GENERIC_MATH2I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(FUN, INTRINSIC) #else // ^^^ intrinsics available / intrinsics unavailable vvv -#define _GENERIC_MATH2I(FUN, CLANG_INTRIN, MSVC_INTRIN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) +#define _GENERIC_MATH2I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ // TRANSITION, DevCom-10294165, additional overloads are not templated to avoid ambiguity with the overload in UCRT From b37f15dd59f80f010897f0636563d8d08046de48 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:30 -0700 Subject: [PATCH 63/85] cmath: Fix missing `_CONSTEXPR_CMATH23` on `frexp` and `_GENERIC_MATH*` templates --- stl/inc/cmath | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 599e5c5fbf3..edc7f0cdb38 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -577,7 +577,7 @@ _STD_END _EXTERN_CXX_WORKAROUND template , int> = 0> -double frexp(_Ty _Value, _Out_ int* const _Exp) noexcept /* strengthened */ { +_CONSTEXPR_CMATH23 double frexp(_Ty _Value, _Out_ int* const _Exp) noexcept /* strengthened */ { return _CSTD frexp(static_cast(_Value), _Exp); } @@ -773,10 +773,10 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #endif // defined(_NATIVE_WCHAR_T_DEFINED) #undef _GENERIC_MATH_ISNORMAL -#define _GENERIC_MATH1_BASE(NAME, RET, FUN) \ - template , int> = 0> \ - _NODISCARD RET NAME(_Ty _Left) noexcept /* strengthened */ { \ - return FUN(static_cast(_Left)); \ +#define _GENERIC_MATH1_BASE(NAME, RET, FUN) \ + template , int> = 0> \ + _NODISCARD _CONSTEXPR_CMATH23 RET NAME(_Ty _Left) noexcept /* strengthened */ { \ + return FUN(static_cast(_Left)); \ } #define _GENERIC_MATH1R(FUN, RET) _GENERIC_MATH1_BASE(FUN, RET, _CSTD FUN) @@ -790,10 +790,10 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #define _GENERIC_MATH1I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(FUN, double, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ -#define _GENERIC_MATH1X(FUN, ARG2) \ - template , int> = 0> \ - _NODISCARD double FUN(_Ty _Left, ARG2 _Arg2) noexcept /* strengthened */ { \ - return _CSTD FUN(static_cast(_Left), _Arg2); \ +#define _GENERIC_MATH1X(FUN, ARG2) \ + template , int> = 0> \ + _NODISCARD _CONSTEXPR_CMATH23 double FUN(_Ty _Left, ARG2 _Arg2) noexcept /* strengthened */ { \ + return _CSTD FUN(static_cast(_Left), _Arg2); \ } // When the arguments are both floats or both long doubles, overload resolution prefers the @@ -802,11 +802,12 @@ _GENERIC_MATH_ISNORMAL(wchar_t) // when the types of the two arguments differ, in which case _Common_float_type_t is either double // or long double. Note that double and long double have the same underlying representation on our // supported platforms. -#define _GENERIC_MATH2_BASE(NAME, FUN) \ - template && _STD is_arithmetic_v<_Ty2>, int> = 0> \ - _NODISCARD _STD _Common_float_type_t<_Ty1, _Ty2> NAME(_Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { \ - return FUN(static_cast(_Left), static_cast(_Right)); \ +#define _GENERIC_MATH2_BASE(NAME, FUN) \ + template && _STD is_arithmetic_v<_Ty2>, int> = 0> \ + _NODISCARD _CONSTEXPR_CMATH23 _STD _Common_float_type_t<_Ty1, _Ty2> NAME( \ + _Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { \ + return FUN(static_cast(_Left), static_cast(_Right)); \ } #define _GENERIC_MATH2(FUN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) From 471da80e09b8bc9a1657281defcf3422723703b5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:30 -0700 Subject: [PATCH 64/85] cmath: Mark frexp/remquo/modf as _NODISCARD despite their out-params. --- stl/inc/cmath | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index edc7f0cdb38..8714cb3e8bf 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -153,7 +153,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float fmod(_In_ float _Xx, _In_ flo return _CSTD fmodf(_Xx, _Yx); } -_CONSTEXPR_CMATH23 float frexp(_In_ float _Xx, _Out_ int* _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float frexp(_In_ float _Xx, _Out_ int* _Yx) noexcept /* strengthened */ { return _CSTD frexpf(_Xx, _Yx); } @@ -209,7 +209,7 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long lround(_In_ float _Xx) noexcep return _CSTD lroundf(_Xx); } -_CONSTEXPR_CMATH23 float modf(_In_ float _Xx, _Out_ float* _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float modf(_In_ float _Xx, _Out_ float* _Yx) noexcept /* strengthened */ { return _CSTD modff(_Xx, _Yx); } @@ -236,7 +236,8 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float remainder(_In_ float _Xx, _In return _CSTD remainderf(_Xx, _Yx); } -_CONSTEXPR_CMATH23 float remquo(_In_ float _Xx, _In_ float _Yx, _Out_ int* _Zx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 float remquo(_In_ float _Xx, _In_ float _Yx, _Out_ int* _Zx) noexcept +/* strengthened */ { return _CSTD remquof(_Xx, _Yx, _Zx); } @@ -418,7 +419,8 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double fmod(_In_ long double _ return _CSTD fmodl(_Xx, _Yx); } -_CONSTEXPR_CMATH23 long double frexp(_In_ long double _Xx, _Out_ int* _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double frexp(_In_ long double _Xx, _Out_ int* _Yx) noexcept +/* strengthened */ { return _CSTD frexpl(_Xx, _Yx); } @@ -476,7 +478,8 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long lround(_In_ long double _Xx) n return _CSTD lroundl(_Xx); } -_CONSTEXPR_CMATH23 long double modf(_In_ long double _Xx, _Out_ long double* _Yx) noexcept /* strengthened */ { +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double modf(_In_ long double _Xx, _Out_ long double* _Yx) noexcept +/* strengthened */ { return _CSTD modfl(_Xx, _Yx); } @@ -504,7 +507,8 @@ _NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double remainder(_In_ long dou return _CSTD remainderl(_Xx, _Yx); } -_CONSTEXPR_CMATH23 long double remquo(_In_ long double _Xx, _In_ long double _Yx, _Out_ int* _Zx) noexcept +_NODISCARD _Check_return_ _CONSTEXPR_CMATH23 long double remquo( + _In_ long double _Xx, _In_ long double _Yx, _Out_ int* _Zx) noexcept /* strengthened */ { return _CSTD remquol(_Xx, _Yx, _Zx); } @@ -577,7 +581,7 @@ _STD_END _EXTERN_CXX_WORKAROUND template , int> = 0> -_CONSTEXPR_CMATH23 double frexp(_Ty _Value, _Out_ int* const _Exp) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH23 double frexp(_Ty _Value, _Out_ int* const _Exp) noexcept /* strengthened */ { return _CSTD frexp(static_cast(_Value), _Exp); } @@ -608,7 +612,7 @@ _NODISCARD _CONSTEXPR_CMATH23 _STD _Common_float_type_t<_Ty1, _STD _Common_float } template && _STD is_arithmetic_v<_Ty2>, int> = 0> -_CONSTEXPR_CMATH23 _STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo) noexcept +_NODISCARD _CONSTEXPR_CMATH23 _STD _Common_float_type_t<_Ty1, _Ty2> remquo(_Ty1 _Left, _Ty2 _Right, int* _Pquo) noexcept /* strengthened */ { using _Common = _STD _Common_float_type_t<_Ty1, _Ty2>; if constexpr (_STD is_same_v<_Common, float>) { From a67a6a729ca6753f7ad8c65795d981d76a410250 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:31 -0700 Subject: [PATCH 65/85] VSO_0157762_feature_test_macros: Test the feature-test macro. --- tests/std/tests/VSO_0157762_feature_test_macros/env.lst | 2 ++ .../VSO_0157762_feature_test_macros/test.compile.pass.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/env.lst b/tests/std/tests/VSO_0157762_feature_test_macros/env.lst index f498ae71be5..669e4e65de2 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/env.lst +++ b/tests/std/tests/VSO_0157762_feature_test_macros/env.lst @@ -43,3 +43,5 @@ PM_CL="/MT /std:c++14 /permissive- /EHsc /await:strict" PM_CL="/MT /std:c++14 /permissive- /EHsc /Zc:char8_t" PM_CL="/MT /std:c++17 /permissive- /EHsc /Zc:char8_t" PM_CL="/MT /std:c++latest /permissive- /EHsc" +PM_CL="/MT /std:c++latest /permissive- /EHsc /experimental:mathlib" +PM_CL="/MT /std:c++latest /permissive- /EHsc /Zc:cmath-" diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 5bbbbaac6f4..e9228daa967 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -221,6 +221,12 @@ STATIC_ASSERT(__cpp_lib_constexpr_charconv == 202207L); #error __cpp_lib_constexpr_charconv is defined #endif +#if _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) // TRANSITION, Clang and EDG lack support for constexpr . +STATIC_ASSERT(__cpp_lib_constexpr_cmath == 202202L); +#elif defined(__cpp_lib_constexpr_cmath) +#error __cpp_lib_constexpr_cmath is defined +#endif + #if _HAS_CXX20 STATIC_ASSERT(__cpp_lib_constexpr_complex == 201711L); #elif defined(__cpp_lib_constexpr_complex) From 3b86862e9d57a7dbd751b29f1520cce5212402c2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:32 -0700 Subject: [PATCH 66/85] Check `_MSVC_LIBC_MATH` which is properly defined, unlike `_MSVC_CONSTEXPR_CMATH`. --- stl/inc/__msvc_stdlib.hpp | 2 +- stl/inc/cmath | 2 +- stl/inc/yvals_core.h | 14 +++++++------- .../test.compile.pass.cpp | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index ddc503755b0..58232b70298 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -231,7 +231,7 @@ typedef struct _lldiv_t { } lldiv_t; // stdlib functions that became constexpr in C++23 -#if _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) +#if _HAS_CXX23 && defined(_MSVC_LIBC_MATH) #define _CONSTEXPR_CSTDLIB23 constexpr #else // ^^^ constexpr in C++23 and later / inline when /Zc:cmath- opts out of constexpr, and in C++20 and earlier vvv #define _CONSTEXPR_CSTDLIB23 inline diff --git a/stl/inc/cmath b/stl/inc/cmath index 8714cb3e8bf..75a1564599c 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -12,7 +12,7 @@ #include // MSVC provides constexpr builtins in C++23 and later, except when /Zc:cmath- opts out of constexpr. -#if defined(__clang__) || defined(_MSVC_CONSTEXPR_CMATH) +#if defined(__clang__) || defined(__cpp_lib_constexpr_cmath) #define _HAS_CMATH_BUILTINS 1 #else // ^^^ builtins available / builtins unavailable vvv #define _HAS_CMATH_BUILTINS 0 diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 615e2e8f279..65fb0e9c7e4 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -964,14 +964,14 @@ _EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC Compiler 19 #endif // ^^^ inline (not constexpr) in C++20 and earlier ^^^ // Math functions that became constexpr in C++23 -#if _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) +#if _HAS_CXX23 && defined(_MSVC_LIBC_MATH) #define _CONSTEXPR_CMATH23 constexpr #else // ^^^ constexpr in C++23 and later / inline when /Zc:cmath- opts out of constexpr, and in C++20 and earlier vvv #define _CONSTEXPR_CMATH23 inline #endif // ^^^ inline when /Zc:cmath- opts out of constexpr, and in C++20 and earlier ^^^ // Math functions that became constexpr in C++26 -#if _HAS_CXX26 && defined(_MSVC_CONSTEXPR_CMATH) +#if _HAS_CXX26 && defined(_MSVC_LIBC_MATH) #define _CONSTEXPR_CMATH26 constexpr #else // ^^^ constexpr in C++26 and later / inline when /Zc:cmath- opts out of constexpr, and in C++23 and earlier vvv #define _CONSTEXPR_CMATH26 inline @@ -1831,15 +1831,15 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_chrono 201510L // P0092R1 floor(), ceil(), round(), abs() #endif -#if 0 && _HAS_CXX26 && defined(_MSVC_CONSTEXPR_CMATH) // TRANSITION, GH-3789 -#define __cpp_lib_constexpr_cmath 202306L // P1383R2 More constexpr For And -#elif _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) -// _MSVC_CONSTEXPR_CMATH is defined when MSVC supports constexpr , but not when /Zc:cmath- opts out. +// The option /Zc:cmath- disables support for constexpr . // TRANSITION, Clang and EDG lack support for constexpr . +#if 0 && _HAS_CXX26 && defined(_MSVC_LIBC_MATH) // TRANSITION, GH-3789 +#define __cpp_lib_constexpr_cmath 202306L // P1383R2 More constexpr For And +#elif _HAS_CXX23 && defined(_MSVC_LIBC_MATH) #define __cpp_lib_constexpr_cmath 202202L // P0533R9 constexpr For And #endif -#if 0 && _HAS_CXX26 && defined(_MSVC_CONSTEXPR_CMATH) // TRANSITION, GH-3789 +#if 0 && _HAS_CXX26 && defined(_MSVC_LIBC_MATH) // TRANSITION, GH-3789 #define __cpp_lib_constexpr_complex 202306L // P1383R2 More constexpr For And #elif _HAS_CXX20 #define __cpp_lib_constexpr_complex 201711L // P0415R1 constexpr For (Again) diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index e9228daa967..577f4ddd10b 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -221,7 +221,7 @@ STATIC_ASSERT(__cpp_lib_constexpr_charconv == 202207L); #error __cpp_lib_constexpr_charconv is defined #endif -#if _HAS_CXX23 && defined(_MSVC_CONSTEXPR_CMATH) // TRANSITION, Clang and EDG lack support for constexpr . +#if _HAS_CXX23 && defined(_MSVC_LIBC_MATH) // TRANSITION, Clang and EDG lack support for constexpr . STATIC_ASSERT(__cpp_lib_constexpr_cmath == 202202L); #elif defined(__cpp_lib_constexpr_cmath) #error __cpp_lib_constexpr_cmath is defined From 2cc3ed787b20944657edebbd636dbac262d633f8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:33 -0700 Subject: [PATCH 67/85] [STL Vacation] P0533R9_constexpr_for_cmath_and_cstdlib: Add test coverage. --- tests/std/test.lst | 1 + .../env.lst | 22 + .../test.cpp | 385 ++++++++++++++++++ 3 files changed, 408 insertions(+) create mode 100644 tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/env.lst create mode 100644 tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index cce97d793eb..3ead5049d4d 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -397,6 +397,7 @@ tests\P0476R2_bit_cast tests\P0487R1_fixing_operator_shl_basic_istream_char_pointer tests\P0513R0_poisoning_the_hash tests\P0528R3_cmpxchg_pad +tests\P0533R9_constexpr_for_cmath_and_cstdlib tests\P0553R4_bit_rotating_and_counting_functions tests\P0556R3_bit_integral_power_of_two_operations tests\P0586R2_integer_comparison diff --git a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/env.lst b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/env.lst new file mode 100644 index 00000000000..6c5e3a51c84 --- /dev/null +++ b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/env.lst @@ -0,0 +1,22 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst + +# Explicitly enable libc-based math: +PM_CL="/MD /experimental:mathlib" +PM_CL="/MDd /experimental:mathlib" +PM_CL="/MT /experimental:mathlib" +PM_CL="/MTd /experimental:mathlib" + +# /O2 implies /Oi which affects <__msvc_math.hpp>: +PM_CL="/MD /experimental:mathlib /O2" +PM_CL="/MDd /experimental:mathlib /O2" +PM_CL="/MT /experimental:mathlib /O2" +PM_CL="/MTd /experimental:mathlib /O2" + +# Explicitly disable libc-based math: +PM_CL="/MD /Zc:cmath-" +PM_CL="/MDd /Zc:cmath-" +PM_CL="/MT /Zc:cmath-" +PM_CL="/MTd /Zc:cmath-" diff --git a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp new file mode 100644 index 00000000000..d5fc59fb0c1 --- /dev/null +++ b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp @@ -0,0 +1,385 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +using namespace std; + +template +constexpr void test_classification_functions(); + +template +constexpr void test_comparison_functions(); + +constexpr bool test_cmath() { +#ifndef _MSVC_LIBC_MATH // TRANSITION, MSVC-PR-767184 fixing error LNK2005: frexp already defined in test.obj + { + int exponent = 0; + assert(frexp(15.5f, &exponent) == 0.96875f); + assert(exponent == 4); + assert(frexp(17.5, &exponent) == 0.546875); + assert(exponent == 5); + assert(frexp(15.5l, &exponent) == 0.96875l); + assert(exponent == 4); + assert(frexpf(17.5f, &exponent) == 0.546875f); + assert(exponent == 5); + assert(frexpl(15.5l, &exponent) == 0.96875l); + assert(exponent == 4); + assert(frexp(1729, &exponent) == 0.84423828125); + assert(exponent == 11); + } +#endif // ^^^ no workaround ^^^ + + assert(ilogb(0.1729f) == -3); + assert(ilogb(0.1729) == -3); + assert(ilogb(0.1729l) == -3); + assert(ilogbf(0.1729f) == -3); + assert(ilogbl(0.1729l) == -3); + assert(ilogb(2097) == 11); + + assert(ldexp(1.09375f, 3) == 8.75f); + assert(ldexp(1.09375, 3) == 8.75); + assert(ldexp(1.09375l, 3) == 8.75l); + assert(ldexpf(1.09375f, 3) == 8.75f); + assert(ldexpl(1.09375l, 3) == 8.75l); + assert(ldexp(1729, 3) == 13832.0); + + assert(logb(0.1729f) == -3.0f); + assert(logb(0.1729) == -3.0); + assert(logb(0.1729l) == -3.0l); + assert(logbf(0.1729f) == -3.0f); + assert(logbl(0.1729l) == -3.0l); + assert(logb(2097) == 11.0); + + { + float flt = 0.0f; + double dbl = 0.0; + long double lng = 0.0l; + assert(modf(13.1875f, &flt) == 0.1875f); + assert(flt == 13.0f); + assert(modf(14.1875, &dbl) == 0.1875); + assert(dbl == 14.0); + assert(modf(15.1875l, &lng) == 0.1875l); + assert(lng == 15.0l); + assert(modff(16.1875f, &flt) == 0.1875f); + assert(flt == 16.0f); + assert(modfl(17.1875l, &lng) == 0.1875l); + assert(lng == 17.0l); + assert(modf(1729, &dbl) == 0.0); + assert(dbl == 1729.0); + } + + assert(scalbn(1.09375f, 3) == 8.75f); + assert(scalbn(1.09375, 3) == 8.75); + assert(scalbn(1.09375l, 3) == 8.75l); + assert(scalbnf(1.09375f, 3) == 8.75f); + assert(scalbnl(1.09375l, 3) == 8.75l); + assert(scalbn(1729, 3) == 13832.0); + + assert(scalbln(1.09375f, 3L) == 8.75f); + assert(scalbln(1.09375, 3L) == 8.75); + assert(scalbln(1.09375l, 3L) == 8.75l); + assert(scalblnf(1.09375f, 3L) == 8.75f); + assert(scalblnl(1.09375l, 3L) == 8.75l); + assert(scalbln(1729, 3L) == 13832.0); + + assert(fabs(-3.14f) == 3.14f); + assert(fabs(-3.14) == 3.14); + assert(fabs(-3.14l) == 3.14l); + assert(fabsf(-3.14f) == 3.14f); + assert(fabsl(-3.14l) == 3.14l); + assert(fabs(-1729) == 1729.0); + + assert(ceil(3.14f) == 4.0f); + assert(ceil(3.14) == 4.0); + assert(ceil(3.14l) == 4.0l); + assert(ceilf(3.14f) == 4.0f); + assert(ceill(3.14l) == 4.0l); + assert(ceil(1729) == 1729.0); + + assert(floor(7.89f) == 7.0f); + assert(floor(7.89) == 7.0); + assert(floor(7.89l) == 7.0l); + assert(floorf(7.89f) == 7.0f); + assert(floorl(7.89l) == 7.0l); + assert(floor(1729) == 1729.0); + + assert(round(3.14f) == 3.0f); + assert(round(3.14) == 3.0); + assert(round(3.14l) == 3.0l); + assert(roundf(3.14f) == 3.0f); + assert(roundl(3.14l) == 3.0l); + assert(round(1729) == 1729.0); + + assert(lround(3.14f) == 3L); + assert(lround(3.14) == 3L); + assert(lround(3.14l) == 3L); + assert(lroundf(3.14f) == 3L); + assert(lroundl(3.14l) == 3L); + assert(lround(1729) == 1729L); + + assert(llround(0x1p60f) == 0x1000'0000'0000'0000LL); + assert(llround(0x1p60) == 0x1000'0000'0000'0000LL); + assert(llround(0x1p60l) == 0x1000'0000'0000'0000LL); + assert(llroundf(0x1p60f) == 0x1000'0000'0000'0000LL); + assert(llroundl(0x1p60l) == 0x1000'0000'0000'0000LL); + assert(llround(1729) == 1729LL); + + assert(trunc(4.56f) == 4.0f); + assert(trunc(4.56) == 4.0); + assert(trunc(4.56l) == 4.0l); + assert(truncf(4.56f) == 4.0f); + assert(truncl(4.56l) == 4.0l); + assert(trunc(1729) == 1729.0); + + assert(fmod(31.5f, 4.0f) == 3.5f); + assert(fmod(31.5, 4.0) == 3.5); + assert(fmod(31.5l, 4.0l) == 3.5l); + assert(fmodf(31.5f, 4.0f) == 3.5f); + assert(fmodl(31.5l, 4.0l) == 3.5l); + assert(fmod(2097, 100) == 97.0); + + assert(remainder(31.5f, 4.0f) == -0.5f); + assert(remainder(31.5, 4.0) == -0.5); + assert(remainder(31.5l, 4.0l) == -0.5l); + assert(remainderf(31.5f, 4.0f) == -0.5f); + assert(remainderl(31.5l, 4.0l) == -0.5l); + assert(remainder(2097, 100) == -3.0); + + { + int quo = 0; + assert(remquo(17.25f, 5.0f, &quo) == 2.25f); + assert(quo == 3); + assert(remquo(22.25, 5.0, &quo) == 2.25); + assert(quo == 4); + assert(remquo(17.25l, 5.0l, &quo) == 2.25l); + assert(quo == 3); + assert(remquof(22.25f, 5.0f, &quo) == 2.25f); + assert(quo == 4); + assert(remquol(17.25l, 5.0l, &quo) == 2.25l); + assert(quo == 3); + assert(remquo(1729, 400, &quo) == 129.0); + assert(quo == 4); + } + + assert(copysign(3.14f, -7.77f) == -3.14f); + assert(copysign(3.14, -7.77) == -3.14); + assert(copysign(3.14l, -7.77l) == -3.14l); + assert(copysignf(3.14f, -7.77f) == -3.14f); + assert(copysignl(3.14l, -7.77l) == -3.14l); + assert(copysign(1729, -5) == -1729.0); + + assert(nextafter(3.0f, 0.0f) == 0x1.7ffffep+1f); + assert(nextafter(3.0, 0.0) == 0x1.7ffffffffffffp+1); + assert(nextafter(3.0l, 0.0l) == 0x1.7ffffffffffffp+1l); + assert(nextafterf(3.0f, 0.0f) == 0x1.7ffffep+1f); + assert(nextafterl(3.0l, 0.0l) == 0x1.7ffffffffffffp+1l); + assert(nextafter(1729, 0) == 0x1.b03ffffffffffp+10); + + assert(nexttoward(3.0f, 0.0l) == 0x1.7ffffep+1f); + assert(nexttoward(3.0, 0.0l) == 0x1.7ffffffffffffp+1); + assert(nexttoward(3.0l, 0.0l) == 0x1.7ffffffffffffp+1l); + assert(nexttowardf(3.0f, 0.0l) == 0x1.7ffffep+1f); + assert(nexttowardl(3.0l, 0.0l) == 0x1.7ffffffffffffp+1l); + assert(nexttoward(1729, 0.0l) == 0x1.b03ffffffffffp+10); + + assert(fdim(9.75f, 2.5f) == 7.25f); + assert(fdim(9.75, 2.5) == 7.25); + assert(fdim(9.75l, 2.5l) == 7.25l); + assert(fdimf(9.75f, 2.5f) == 7.25f); + assert(fdiml(9.75l, 2.5l) == 7.25l); + assert(fdim(1729, 1700) == 29.0); + + assert(fmax(3.14f, 7.77f) == 7.77f); + assert(fmax(3.14, 7.77) == 7.77); + assert(fmax(3.14l, 7.77l) == 7.77l); + assert(fmaxf(3.14f, 7.77f) == 7.77f); + assert(fmaxl(3.14l, 7.77l) == 7.77l); + assert(fmax(1729, 2097) == 2097.0); + + assert(fmin(3.14f, 7.77f) == 3.14f); + assert(fmin(3.14, 7.77) == 3.14); + assert(fmin(3.14l, 7.77l) == 3.14l); + assert(fminf(3.14f, 7.77f) == 3.14f); + assert(fminl(3.14l, 7.77l) == 3.14l); + assert(fmin(1729, 2097) == 1729.0); + + assert(fma(5.125f, 3.0f, 2.5f) == 17.875f); + assert(fma(5.125, 3.0, 2.5) == 17.875); + assert(fma(5.125l, 3.0l, 2.5l) == 17.875l); + assert(fmaf(5.125f, 3.0f, 2.5f) == 17.875f); + assert(fmal(5.125l, 3.0l, 2.5l) == 17.875l); + assert(fma(17, 100, 29) == 1729.0); + + test_classification_functions(); + test_classification_functions(); + test_classification_functions(); + test_classification_functions(); + + if !consteval { // TRANSITION, the comparison functions "are do-nothing stubs because we don't need them" + // in constant evaluation, OOPSY DOODLE + test_comparison_functions(); + test_comparison_functions(); + test_comparison_functions(); + test_comparison_functions(); + } // ^^^ no workaround ^^^ + + return true; +} + +template +constexpr void test_classification_functions() { + { + constexpr T zro{}; + constexpr T val = static_cast(5); + + assert(fpclassify(zro) == FP_ZERO); + assert(fpclassify(val) == FP_NORMAL); + + assert(isfinite(zro)); + assert(isfinite(val)); + + assert(!isinf(zro)); + assert(!isinf(val)); + + assert(!isnan(zro)); + assert(!isnan(val)); + + assert(!isnormal(zro)); + assert(isnormal(val)); + } + + if constexpr (is_floating_point_v) { + constexpr T sub = numeric_limits::denorm_min(); + constexpr T inf = numeric_limits::infinity(); + constexpr T nan = numeric_limits::quiet_NaN(); + + if constexpr (!is_same_v) { // TRANSITION, MSVC-PR-767404 fixing fpclassify for subnormal floats + assert(fpclassify(sub) == FP_SUBNORMAL); + } // ^^^ no workaround ^^^ + assert(fpclassify(inf) == FP_INFINITE); + assert(fpclassify(nan) == FP_NAN); + + assert(isfinite(sub)); + assert(!isfinite(inf)); + assert(!isfinite(nan)); + + assert(!isinf(sub)); + assert(isinf(inf)); + assert(!isinf(nan)); + + assert(!isnan(sub)); + assert(!isnan(inf)); + assert(isnan(nan)); + + if constexpr (!is_same_v) { // TRANSITION, MSVC-PR-767404 fixing fpclassify for subnormal floats + assert(!isnormal(sub)); + } // ^^^ no workaround ^^^ + assert(!isnormal(inf)); + assert(!isnormal(nan)); + } +} + +template +constexpr void test_comparison_functions() { + constexpr T lo = static_cast(-3); + constexpr T hi = static_cast(4); + + assert(signbit(lo)); + assert(!signbit(hi)); + + assert(!isgreater(lo, hi)); + assert(isgreater(hi, lo)); + assert(!isgreater(hi, hi)); + + assert(!isgreaterequal(lo, hi)); + assert(isgreaterequal(hi, lo)); + assert(isgreaterequal(hi, hi)); + + assert(isless(lo, hi)); + assert(!isless(hi, lo)); + assert(!isless(hi, hi)); + + assert(islessequal(lo, hi)); + assert(!islessequal(hi, lo)); + assert(islessequal(hi, hi)); + + assert(islessgreater(lo, hi)); + assert(islessgreater(hi, lo)); + assert(!islessgreater(hi, hi)); + + assert(!isunordered(lo, hi)); + assert(!isunordered(hi, lo)); + assert(!isunordered(hi, hi)); + + if constexpr (is_floating_point_v) { + constexpr T nan = numeric_limits::quiet_NaN(); + + assert(!isgreater(lo, nan)); + assert(!isgreater(nan, lo)); + assert(!isgreater(nan, nan)); + + assert(!isgreaterequal(lo, nan)); + assert(!isgreaterequal(nan, lo)); + assert(!isgreaterequal(nan, nan)); + + assert(!isless(lo, nan)); + assert(!isless(nan, lo)); + assert(!isless(nan, nan)); + + assert(!islessequal(lo, nan)); + assert(!islessequal(nan, lo)); + assert(!islessequal(nan, nan)); + + assert(!islessgreater(lo, nan)); + assert(!islessgreater(nan, lo)); + assert(!islessgreater(nan, nan)); + + assert(isunordered(lo, nan)); + assert(isunordered(nan, lo)); + assert(isunordered(nan, nan)); + } +} + +constexpr bool test_cstdlib() { + assert(abs(-5) == 5); + assert(abs(-5L) == 5L); + assert(abs(-5LL) == 5LL); + assert(abs(-5.0f) == 5.0f); + assert(abs(-5.0) == 5.0); + assert(abs(-5.0l) == 5.0l); + + assert(labs(-5L) == 5L); + + assert(llabs(-5LL) == 5LL); + + assert(div(1729, 100).quot == 17); + assert(div(1729, 100).rem == 29); + assert(div(1729L, 100L).quot == 17L); + assert(div(1729L, 100L).rem == 29L); + assert(div(1729LL, 100LL).quot == 17LL); + assert(div(1729LL, 100LL).rem == 29LL); + + assert(ldiv(1729L, 100L).quot == 17L); + assert(ldiv(1729L, 100L).rem == 29L); + + assert(lldiv(1729LL, 100LL).quot == 17LL); + assert(lldiv(1729LL, 100LL).rem == 29LL); + + return true; +} + +int main() { +#ifndef _M_ARM64EC // TRANSITION, reported many occurrences of error LNK2019: unresolved external symbol + test_cmath(); + test_cstdlib(); +#endif // ^^^ no workaround ^^^ + +#ifdef __cpp_lib_constexpr_cmath + static_assert(test_cmath()); + static_assert(test_cstdlib()); +#endif // ^^^ defined(__cpp_lib_constexpr_cmath) ^^^ +} From e2575ac6b1a1e3813eb00a122bd54da79042c193 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:34 -0700 Subject: [PATCH 68/85] P0533R9_constexpr_for_cmath_and_cstdlib: Partially remove workarounds after MSVC-PR-767404. --- .../test.cpp | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp index d5fc59fb0c1..d0fd22ec6a7 100644 --- a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp +++ b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp @@ -219,13 +219,15 @@ constexpr bool test_cmath() { test_classification_functions(); test_classification_functions(); - if !consteval { // TRANSITION, the comparison functions "are do-nothing stubs because we don't need them" - // in constant evaluation, OOPSY DOODLE +#ifndef _MSVC_INTERNAL_TESTING // TRANSITION, MSVC-PR-767404 fixed the comparison functions in constant evaluation + if !consteval +#endif // ^^^ workaround ^^^ + { test_comparison_functions(); test_comparison_functions(); test_comparison_functions(); test_comparison_functions(); - } // ^^^ no workaround ^^^ + } return true; } @@ -257,9 +259,12 @@ constexpr void test_classification_functions() { constexpr T inf = numeric_limits::infinity(); constexpr T nan = numeric_limits::quiet_NaN(); - if constexpr (!is_same_v) { // TRANSITION, MSVC-PR-767404 fixing fpclassify for subnormal floats +#ifndef _MSVC_INTERNAL_TESTING // TRANSITION, MSVC-PR-767404 fixed fpclassify for subnormal floats + if constexpr (!is_same_v) +#endif // ^^^ workaround ^^^ + { assert(fpclassify(sub) == FP_SUBNORMAL); - } // ^^^ no workaround ^^^ + } assert(fpclassify(inf) == FP_INFINITE); assert(fpclassify(nan) == FP_NAN); @@ -275,9 +280,12 @@ constexpr void test_classification_functions() { assert(!isnan(inf)); assert(isnan(nan)); - if constexpr (!is_same_v) { // TRANSITION, MSVC-PR-767404 fixing fpclassify for subnormal floats +#ifndef _MSVC_INTERNAL_TESTING // TRANSITION, MSVC-PR-767404 fixed fpclassify for subnormal floats + if constexpr (!is_same_v) +#endif // ^^^ workaround ^^^ + { assert(!isnormal(sub)); - } // ^^^ no workaround ^^^ + } assert(!isnormal(inf)); assert(!isnormal(nan)); } From bc948e4919487972fb6b9b182d44108a9e0bf581 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:35 -0700 Subject: [PATCH 69/85] P0533R9_constexpr_for_cmath_and_cstdlib: Partially remove workaround after MSVC-PR-767414 and MSVC-PR-768260. --- .../std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp index d0fd22ec6a7..e752442ce1b 100644 --- a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp +++ b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp @@ -381,7 +381,7 @@ constexpr bool test_cstdlib() { } int main() { -#ifndef _M_ARM64EC // TRANSITION, reported many occurrences of error LNK2019: unresolved external symbol +#if defined(_MSVC_INTERNAL_TESTING) || !defined(_M_ARM64EC) // TRANSITION, MSVC-PR-767414/MSVC-PR-768260 fixed LNK2019 test_cmath(); test_cstdlib(); #endif // ^^^ no workaround ^^^ From 8e9e205e151a0a6c6111966d3b6d8ba04510372b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:36 -0700 Subject: [PATCH 70/85] tests: MSVC-PR-766982 renamed /experimental:mathlib to /Zc:cmath, pass both until this change ships. --- .../env.lst | 17 +++++++++-------- .../VSO_0157762_feature_test_macros/env.lst | 3 ++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/env.lst b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/env.lst index 6c5e3a51c84..70705eeacf5 100644 --- a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/env.lst +++ b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/env.lst @@ -4,16 +4,17 @@ RUNALL_INCLUDE ..\usual_latest_matrix.lst # Explicitly enable libc-based math: -PM_CL="/MD /experimental:mathlib" -PM_CL="/MDd /experimental:mathlib" -PM_CL="/MT /experimental:mathlib" -PM_CL="/MTd /experimental:mathlib" +# TRANSITION, MSVC-PR-766982 renamed /experimental:mathlib to /Zc:cmath, pass both until this change ships +PM_CL="/MD /Zc:cmath /experimental:mathlib" +PM_CL="/MDd /Zc:cmath /experimental:mathlib" +PM_CL="/MT /Zc:cmath /experimental:mathlib" +PM_CL="/MTd /Zc:cmath /experimental:mathlib" # /O2 implies /Oi which affects <__msvc_math.hpp>: -PM_CL="/MD /experimental:mathlib /O2" -PM_CL="/MDd /experimental:mathlib /O2" -PM_CL="/MT /experimental:mathlib /O2" -PM_CL="/MTd /experimental:mathlib /O2" +PM_CL="/MD /Zc:cmath /experimental:mathlib /O2" +PM_CL="/MDd /Zc:cmath /experimental:mathlib /O2" +PM_CL="/MT /Zc:cmath /experimental:mathlib /O2" +PM_CL="/MTd /Zc:cmath /experimental:mathlib /O2" # Explicitly disable libc-based math: PM_CL="/MD /Zc:cmath-" diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/env.lst b/tests/std/tests/VSO_0157762_feature_test_macros/env.lst index 669e4e65de2..0b32c69f019 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/env.lst +++ b/tests/std/tests/VSO_0157762_feature_test_macros/env.lst @@ -43,5 +43,6 @@ PM_CL="/MT /std:c++14 /permissive- /EHsc /await:strict" PM_CL="/MT /std:c++14 /permissive- /EHsc /Zc:char8_t" PM_CL="/MT /std:c++17 /permissive- /EHsc /Zc:char8_t" PM_CL="/MT /std:c++latest /permissive- /EHsc" -PM_CL="/MT /std:c++latest /permissive- /EHsc /experimental:mathlib" +# TRANSITION, MSVC-PR-766982 renamed /experimental:mathlib to /Zc:cmath, pass both until this change ships +PM_CL="/MT /std:c++latest /permissive- /EHsc /Zc:cmath /experimental:mathlib" PM_CL="/MT /std:c++latest /permissive- /EHsc /Zc:cmath-" From bbf80986edbffe19d4e765036dbc3e0f7261c1b8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:36 -0700 Subject: [PATCH 71/85] __msvc_math.hpp: Cite LLVM-214934 for atan2 underflow. --- stl/inc/__msvc_math.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 526cabf67c4..7ad28ffbe3e 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -328,7 +328,7 @@ _STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, islessgreater) _STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, isunordered) } // extern "C++" -// Preserve the sign of zero when atan2 underflows. +// TRANSITION, LLVM-214934: Preserve the sign of zero when atan2 underflows. // __builtin_atan2 can return +0 for tiny negative results. _NODISCARD _CONSTEXPR_CMATH26 float __cdecl atan2f(float _Xx0, float _Xx1) noexcept /* strengthened */ { float _Result = __builtin_atan2f(_Xx0, _Xx1); From 2f967345ae93e43311ac743faf5387c21b72bd20 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:37 -0700 Subject: [PATCH 72/85] __msvc_math.hpp: [Copilot review] Constrain the comparisons for arithmetic types. --- stl/inc/__msvc_math.hpp | 82 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 7ad28ffbe3e..4fe882711f6 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -25,6 +25,73 @@ _STL_DISABLE_CLANG_WARNINGS #pragma warning(disable : 4163) // 'meow' not available as an intrinsic function +extern "C++" { +namespace _Msvc { // duplicate type traits not provided by + template + constexpr bool _Is_arithmetic_v = false; + + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; +#ifdef _NATIVE_WCHAR_T_DEFINED + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; +#endif // ^^^ defined(_NATIVE_WCHAR_T_DEFINED) ^^^ +#ifdef __cpp_char8_t + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; +#endif // ^^^ defined(__cpp_char8_t) ^^^ + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + template <> + _INLINE_VAR constexpr bool _Is_arithmetic_v = true; + + template + constexpr bool _Is_arithmetic_v = _Is_arithmetic_v<_Ty>; + template + constexpr bool _Is_arithmetic_v = _Is_arithmetic_v<_Ty>; + template + constexpr bool _Is_arithmetic_v = _Is_arithmetic_v<_Ty>; + + template + struct _Enable_if {}; + template + struct _Enable_if { + using type = _Ty; + }; + + template + using _Enable_if_t = typename _Enable_if<_Test, _Ty>::type; +} // namespace _Msvc +} // extern "C++" + extern "C" { #define _STL_DEF_FUNC1(specs, name, ret, arg0) \ @@ -107,13 +174,14 @@ extern "C" { _STL_DEF_OVERLOADED_COMPARISON1(specs, name, __builtin_##name##l, long double) // Defines four overloaded functions with signature `bool (fp-type, fp-type)`. -#define _STL_DEF_OVERLOADED_COMPARISON_FAMILY2(specs, name) \ - _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name##f, float) \ - _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name, double) \ - _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name##l, long double) \ - template \ - _NODISCARD specs bool __cdecl name(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { \ - return static_cast(__builtin_##name(static_cast(_Xx0), static_cast(_Xx1))); \ +#define _STL_DEF_OVERLOADED_COMPARISON_FAMILY2(specs, name) \ + _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name##f, float) \ + _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name, double) \ + _STL_DEF_OVERLOADED_COMPARISON2(specs, name, __builtin_##name##l, long double) \ + template && ::_Msvc::_Is_arithmetic_v<_Ty1>, int> = 0> \ + _NODISCARD specs bool __cdecl name(_Ty0 _Xx0, _Ty1 _Xx1) noexcept /* strengthened */ { \ + return static_cast(__builtin_##name(static_cast(_Xx0), static_cast(_Xx1))); \ } // *Declares* three non-overloaded functions with signature `fp-type (fp-type)`. From a71356bbac5ca7783ae4496860bea31e36adef15 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:38 -0700 Subject: [PATCH 73/85] __msvc_math.hpp: [Copilot review] Undef `_CONSTEXPR_CMATH26_NYI_DECL`. --- stl/inc/__msvc_math.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 4fe882711f6..4e60bd55418 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -500,6 +500,7 @@ _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* str #undef _STL_DEF_OVERLOADED_COMPARISON_FAMILY2 #undef _STL_DECLARE_FAMILY1 #undef _CONSTEXPR_CMATH26_NYI +#undef _CONSTEXPR_CMATH26_NYI_DECL } // extern "C" From 8928c0aaa8988de3a7897a6cbfa6945bae5a6afb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:39 -0700 Subject: [PATCH 74/85] __msvc_stdlib.hpp: [Copilot review] Undef `_CONSTEXPR_CSTDLIB23`. --- stl/inc/__msvc_stdlib.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 58232b70298..098d5e3d79c 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -336,6 +336,8 @@ extern "C++" { } } // extern "C++" +#undef _CONSTEXPR_CSTDLIB23 + // Structs used to fool the compiler into not generating floating point // instructions when copying and pushing [long] double values From 8077b977cbb48678e6791526a968256023f86a76 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:40 -0700 Subject: [PATCH 75/85] __msvc_stdlib.hpp: Remove `_M_CEE_MIXED` checks. --- stl/inc/__msvc_stdlib.hpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 098d5e3d79c..6bb9436b3f6 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -6,6 +6,7 @@ // This file was derived from in the Windows 11 SDK (10.0.28000), with some alterations: // * Formatted with clang-format. // * Removed _M_CEE_PURE checks (never defined here). +// * Removed _M_CEE_MIXED checks (within _M_CEE checks, because /clr:pure is never used here). // * Removed __cplusplus checks (always defined here). // * Changed code to support the MSVC frontend intercepting inclusions of . // * Changed code for C++23's P0533R9 "constexpr For And ". @@ -91,25 +92,12 @@ _Check_return_ int __clrcall _atexit_m_appdomain(_In_opt_ void(__clrcall* _Funct _onexit_m_t __clrcall _onexit_m_appdomain(_onexit_m_t _Function); -#ifdef _M_CEE_MIXED #ifdef __cplusplus [System::Security::SecurityCritical] #endif _Check_return_ int __clrcall _atexit_m(_In_opt_ void(__clrcall* _Function)(void)); _onexit_m_t __clrcall _onexit_m(_onexit_m_t _Function); -#else -#ifdef __cplusplus -[System::Security::SecurityCritical] -#endif - _Check_return_ inline int __clrcall _atexit_m(_In_opt_ void(__clrcall* _Function)(void)) { - return _atexit_m_appdomain(_Function); -} - -inline _onexit_m_t __clrcall _onexit_m(_onexit_t _Function) { - return _onexit_m_appdomain(_Function); -} -#endif #pragma warning(pop) #endif From 26de406112c68e1e708c64e6b9849e549ef0277e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:41 -0700 Subject: [PATCH 76/85] __msvc_stdlib.hpp: Remove `__cplusplus` checks. --- stl/inc/__msvc_stdlib.hpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/stl/inc/__msvc_stdlib.hpp b/stl/inc/__msvc_stdlib.hpp index 6bb9436b3f6..ad45821bcd3 100644 --- a/stl/inc/__msvc_stdlib.hpp +++ b/stl/inc/__msvc_stdlib.hpp @@ -92,10 +92,7 @@ _Check_return_ int __clrcall _atexit_m_appdomain(_In_opt_ void(__clrcall* _Funct _onexit_m_t __clrcall _onexit_m_appdomain(_onexit_m_t _Function); -#ifdef __cplusplus -[System::Security::SecurityCritical] -#endif - _Check_return_ int __clrcall _atexit_m(_In_opt_ void(__clrcall* _Function)(void)); +[System::Security::SecurityCritical] _Check_return_ int __clrcall _atexit_m(_In_opt_ void(__clrcall* _Function)(void)); _onexit_m_t __clrcall _onexit_m(_onexit_m_t _Function); #pragma warning(pop) @@ -809,11 +806,6 @@ _DCRTIMP void __cdecl _sleep(_In_ unsigned long _Duration); //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ #if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES -#ifndef __cplusplus -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) -#endif - #define sys_errlist _sys_errlist #define sys_nerr _sys_nerr From 7f487a3a96ccf96c527ebd41ae930a1b4bd34d9a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:42 -0700 Subject: [PATCH 77/85] P0533R9_constexpr_for_cmath_and_cstdlib: Partially remove workaround after MSVC-PR-767184 and MSVC-PR-772024. --- .../std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp index e752442ce1b..bafb15f463a 100644 --- a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp +++ b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp @@ -15,7 +15,7 @@ template constexpr void test_comparison_functions(); constexpr bool test_cmath() { -#ifndef _MSVC_LIBC_MATH // TRANSITION, MSVC-PR-767184 fixing error LNK2005: frexp already defined in test.obj +#if defined(_MSVC_INTERNAL_TESTING) || !defined(_MSVC_LIBC_MATH) // TRANSITION, MSVC-PR-767184/772024 fixed LNK2005 { int exponent = 0; assert(frexp(15.5f, &exponent) == 0.96875f); From fc6951ac6b29563d0ca52693d9653912786d3158 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:42 -0700 Subject: [PATCH 78/85] __msvc_math.hpp: Fix/refine the cosh/sinh/tanh polyfill workarounds. --- stl/inc/__msvc_math.hpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 4e60bd55418..886f055ea64 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -331,9 +331,9 @@ _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, tan) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, acosh) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, asinh) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, atanh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, cosh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, sinh) -_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, tanh) +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, cosh) // additional workarounds for this polyfill are defined below +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, sinh) // additional workarounds for this polyfill are defined below +_STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, tanh) // additional workarounds for this polyfill are defined below _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, exp) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, exp2) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, expm1) @@ -466,22 +466,31 @@ _NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl tgammal(long double _Xx) n return __std_smf_tgamma(static_cast(_Xx)); } -// The UCRT defines the following functions on x86 as inline functions that forward to their double siblings, -// so forward-declaring them without defining them does not result in a successful polyfill. -#pragma function(coshf) +// The UCRT defines the following functions as inline functions that forward to their double siblings, +// so forward-declaring them without defining them would not result in a successful polyfill. +#if defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64) +#pragma function(coshf, sinhf, tanhf) _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl coshf(float _Xx) noexcept /* strengthened */ { return __builtin_coshf(_Xx); } - -#pragma function(sinhf) _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl sinhf(float _Xx) noexcept /* strengthened */ { return __builtin_sinhf(_Xx); } - -#pragma function(tanhf) _NODISCARD _CONSTEXPR_CMATH26_NYI float __cdecl tanhf(float _Xx) noexcept /* strengthened */ { return __builtin_tanhf(_Xx); } +#endif // ^^^ defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64) ^^^ + +#pragma function(coshl, sinhl, tanhl) +_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl coshl(long double _Xx) noexcept /* strengthened */ { + return _CSTD cosh(static_cast(_Xx)); +} +_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl sinhl(long double _Xx) noexcept /* strengthened */ { + return _CSTD sinh(static_cast(_Xx)); +} +_NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl tanhl(long double _Xx) noexcept /* strengthened */ { + return _CSTD tanh(static_cast(_Xx)); +} #undef _STL_DEF_FUNC1 #undef _STL_DEF_FUNC2 From 344c38a429c53885bd188f77dd1b4e70a84b3bf4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:43 -0700 Subject: [PATCH 79/85] __msvc_math.hpp: Explain why functions are hand-crafted. --- stl/inc/__msvc_math.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 886f055ea64..558b2232ea2 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -324,7 +324,7 @@ _NODISCARD _CONSTEXPR_CMATH26 double __cdecl tan(double) noexcept; _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, acos) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, asin) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, atan) -// atan2() is hand-crafted +// atan2() is hand-crafted because of the workaround for LLVM-214934 _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, cos) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sin) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, tan) @@ -345,7 +345,7 @@ _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log10) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log1p) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, log2) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, logb) -// modf() is hand-crafted +// modf() is hand-crafted because it has a unique signature _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbn, int) _STL_DEF_LASTARG_FAMILY2(_CONSTEXPR_CMATH23, scalbln, long) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, cbrt) @@ -356,8 +356,8 @@ _STL_DEF_FAMILY2(_CONSTEXPR_CMATH26, pow) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH26, sqrt) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, erf) _STL_DECLARE_FAMILY1(_CONSTEXPR_CMATH26_NYI_DECL, erfc) -// lgamma() is hand-crafted -// tgamma() is hand-crafted +// lgamma() is hand-crafted because it is not yet implemented by libc +// tgamma() is hand-crafted because it is not yet implemented by libc _STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, ceil) _STL_DEF_FAMILY1(_CONSTEXPR_CMATH23, floor) _STL_DEF_FAMILY1(inline, nearbyint) From 034c37f39f4b9d871074d128dbd477372306b9a3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 22 Aug 2026 14:19:44 -0700 Subject: [PATCH 80/85] P0533R9_constexpr_for_cmath_and_cstdlib: Add test coverage for C++26-constexpr and always-runtime functions. --- .../test.cpp | 285 ++++++++++++++++-- 1 file changed, 267 insertions(+), 18 deletions(-) diff --git a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp index bafb15f463a..0b51e792793 100644 --- a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp +++ b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp @@ -9,12 +9,12 @@ using namespace std; template -constexpr void test_classification_functions(); +constexpr void test_classification_functions_cxx23(); template -constexpr void test_comparison_functions(); +constexpr void test_comparison_functions_cxx23(); -constexpr bool test_cmath() { +constexpr bool test_cmath_cxx23() { #if defined(_MSVC_INTERNAL_TESTING) || !defined(_MSVC_LIBC_MATH) // TRANSITION, MSVC-PR-767184/772024 fixed LNK2005 { int exponent = 0; @@ -214,26 +214,26 @@ constexpr bool test_cmath() { assert(fmal(5.125l, 3.0l, 2.5l) == 17.875l); assert(fma(17, 100, 29) == 1729.0); - test_classification_functions(); - test_classification_functions(); - test_classification_functions(); - test_classification_functions(); + test_classification_functions_cxx23(); + test_classification_functions_cxx23(); + test_classification_functions_cxx23(); + test_classification_functions_cxx23(); #ifndef _MSVC_INTERNAL_TESTING // TRANSITION, MSVC-PR-767404 fixed the comparison functions in constant evaluation if !consteval #endif // ^^^ workaround ^^^ { - test_comparison_functions(); - test_comparison_functions(); - test_comparison_functions(); - test_comparison_functions(); + test_comparison_functions_cxx23(); + test_comparison_functions_cxx23(); + test_comparison_functions_cxx23(); + test_comparison_functions_cxx23(); } return true; } template -constexpr void test_classification_functions() { +constexpr void test_classification_functions_cxx23() { { constexpr T zro{}; constexpr T val = static_cast(5); @@ -292,7 +292,7 @@ constexpr void test_classification_functions() { } template -constexpr void test_comparison_functions() { +constexpr void test_comparison_functions_cxx23() { constexpr T lo = static_cast(-3); constexpr T hi = static_cast(4); @@ -352,7 +352,7 @@ constexpr void test_comparison_functions() { } } -constexpr bool test_cstdlib() { +constexpr bool test_cstdlib_cxx23() { assert(abs(-5) == 5); assert(abs(-5L) == 5L); assert(abs(-5LL) == 5LL); @@ -380,14 +380,263 @@ constexpr bool test_cstdlib() { return true; } +constexpr bool test_cmath_cxx26() { + // These tests use round() because they're checking for basic functionality, not precision. + + assert(round(acos(0.6f) * 1000.0f) == 927.0f); + assert(round(acos(0.6) * 1000.0) == 927.0); + assert(round(acos(0.6l) * 1000.0l) == 927.0l); + assert(round(acosf(0.6f) * 1000.0f) == 927.0f); + assert(round(acosl(0.6l) * 1000.0l) == 927.0l); + assert(round(acos(-1) * 1000.0) == 3142.0); + + assert(round(asin(0.6f) * 1000.0f) == 644.0f); + assert(round(asin(0.6) * 1000.0) == 644.0); + assert(round(asin(0.6l) * 1000.0l) == 644.0l); + assert(round(asinf(0.6f) * 1000.0f) == 644.0f); + assert(round(asinl(0.6l) * 1000.0l) == 644.0l); + assert(round(asin(1) * 1000.0) == 1571.0); + + assert(round(atan(0.6f) * 1000.0f) == 540.0f); + assert(round(atan(0.6) * 1000.0) == 540.0); + assert(round(atan(0.6l) * 1000.0l) == 540.0l); + assert(round(atanf(0.6f) * 1000.0f) == 540.0f); + assert(round(atanl(0.6l) * 1000.0l) == 540.0l); + assert(round(atan(1) * 1000.0) == 785.0); + + assert(round(atan2(0.06f, 0.1f) * 1000.0f) == 540.0f); + assert(round(atan2(0.06, 0.1) * 1000.0) == 540.0); + assert(round(atan2(0.06l, 0.1l) * 1000.0l) == 540.0l); + assert(round(atan2f(0.06f, 0.1f) * 1000.0f) == 540.0f); + assert(round(atan2l(0.06l, 0.1l) * 1000.0l) == 540.0l); + assert(round(atan2(17, 29) * 1000.0) == 530.0); + + assert(round(cos(0.6f) * 1000.0f) == 825.0f); + assert(round(cos(0.6) * 1000.0) == 825.0); + assert(round(cos(0.6l) * 1000.0l) == 825.0l); + assert(round(cosf(0.6f) * 1000.0f) == 825.0f); + assert(round(cosl(0.6l) * 1000.0l) == 825.0l); + assert(round(cos(1729) * 1000.0) == 432.0); + + assert(round(sin(0.6f) * 1000.0f) == 565.0f); + assert(round(sin(0.6) * 1000.0) == 565.0); + assert(round(sin(0.6l) * 1000.0l) == 565.0l); + assert(round(sinf(0.6f) * 1000.0f) == 565.0f); + assert(round(sinl(0.6l) * 1000.0l) == 565.0l); + assert(round(sin(1729) * 1000.0) == 902.0); + + assert(round(tan(0.6f) * 1000.0f) == 684.0f); + assert(round(tan(0.6) * 1000.0) == 684.0); + assert(round(tan(0.6l) * 1000.0l) == 684.0l); + assert(round(tanf(0.6f) * 1000.0f) == 684.0f); + assert(round(tanl(0.6l) * 1000.0l) == 684.0l); + assert(round(tan(1729) * 1000.0) == 2087.0); + + if !consteval { // TRANSITION, GH-3789 + assert(round(acosh(3.3f) * 1000.0f) == 1863.0f); + assert(round(acosh(3.3) * 1000.0) == 1863.0); + assert(round(acosh(3.3l) * 1000.0l) == 1863.0l); + assert(round(acoshf(3.3f) * 1000.0f) == 1863.0f); + assert(round(acoshl(3.3l) * 1000.0l) == 1863.0l); + assert(round(acosh(7) * 1000.0) == 2634.0); + + assert(round(asinh(3.3f) * 1000.0f) == 1909.0f); + assert(round(asinh(3.3) * 1000.0) == 1909.0); + assert(round(asinh(3.3l) * 1000.0l) == 1909.0l); + assert(round(asinhf(3.3f) * 1000.0f) == 1909.0f); + assert(round(asinhl(3.3l) * 1000.0l) == 1909.0l); + assert(round(asinh(7) * 1000.0) == 2644.0); + + assert(round(atanh(0.6f) * 1000.0f) == 693.0f); + assert(round(atanh(0.6) * 1000.0) == 693.0); + assert(round(atanh(0.6l) * 1000.0l) == 693.0l); + assert(round(atanhf(0.6f) * 1000.0f) == 693.0f); + assert(round(atanhl(0.6l) * 1000.0l) == 693.0l); + assert(round(atanh(0) * 1000.0) == 0.0); + + assert(round(cosh(0.6f) * 1000.0f) == 1185.0f); + assert(round(cosh(0.6) * 1000.0) == 1185.0); + assert(round(cosh(0.6l) * 1000.0l) == 1185.0l); + assert(round(coshf(0.6f) * 1000.0f) == 1185.0f); + assert(round(coshl(0.6l) * 1000.0l) == 1185.0l); + assert(round(cosh(2) * 1000.0) == 3762.0); + + assert(round(sinh(0.6f) * 1000.0f) == 637.0f); + assert(round(sinh(0.6) * 1000.0) == 637.0); + assert(round(sinh(0.6l) * 1000.0l) == 637.0l); + assert(round(sinhf(0.6f) * 1000.0f) == 637.0f); + assert(round(sinhl(0.6l) * 1000.0l) == 637.0l); + assert(round(sinh(2) * 1000.0) == 3627.0); + + assert(round(tanh(0.6f) * 1000.0f) == 537.0f); + assert(round(tanh(0.6) * 1000.0) == 537.0); + assert(round(tanh(0.6l) * 1000.0l) == 537.0l); + assert(round(tanhf(0.6f) * 1000.0f) == 537.0f); + assert(round(tanhl(0.6l) * 1000.0l) == 537.0l); + assert(round(tanh(2) * 1000.0) == 964.0); + } + + assert(round(exp(0.6f) * 1000.0f) == 1822.0f); + assert(round(exp(0.6) * 1000.0) == 1822.0); + assert(round(exp(0.6l) * 1000.0l) == 1822.0l); + assert(round(expf(0.6f) * 1000.0f) == 1822.0f); + assert(round(expl(0.6l) * 1000.0l) == 1822.0l); + assert(round(exp(2) * 1000.0) == 7389.0); + + if !consteval { // TRANSITION, GH-3789 + assert(round(exp2(0.6f) * 1000.0f) == 1516.0f); + assert(round(exp2(0.6) * 1000.0) == 1516.0); + assert(round(exp2(0.6l) * 1000.0l) == 1516.0l); + assert(round(exp2f(0.6f) * 1000.0f) == 1516.0f); + assert(round(exp2l(0.6l) * 1000.0l) == 1516.0l); + assert(round(exp2(-3) * 1000.0) == 125.0); + } + + assert(round(expm1(0.6f) * 1000.0f) == 822.0f); + assert(round(expm1(0.6) * 1000.0) == 822.0); + assert(round(expm1(0.6l) * 1000.0l) == 822.0l); + assert(round(expm1f(0.6f) * 1000.0f) == 822.0f); + assert(round(expm1l(0.6l) * 1000.0l) == 822.0l); + assert(round(expm1(2) * 1000.0) == 6389.0); + + assert(round(log(0.6f) * 1000.0f) == -511.0f); + assert(round(log(0.6) * 1000.0) == -511.0); + assert(round(log(0.6l) * 1000.0l) == -511.0l); + assert(round(logf(0.6f) * 1000.0f) == -511.0f); + assert(round(logl(0.6l) * 1000.0l) == -511.0l); + assert(round(log(7) * 1000.0) == 1946.0); + + assert(round(log10(0.6f) * 1000.0f) == -222.0f); + assert(round(log10(0.6) * 1000.0) == -222.0); + assert(round(log10(0.6l) * 1000.0l) == -222.0l); + assert(round(log10f(0.6f) * 1000.0f) == -222.0f); + assert(round(log10l(0.6l) * 1000.0l) == -222.0l); + assert(round(log10(7) * 1000.0) == 845.0); + + assert(round(log1p(0.6f) * 1000.0f) == 470.0f); + assert(round(log1p(0.6) * 1000.0) == 470.0); + assert(round(log1p(0.6l) * 1000.0l) == 470.0l); + assert(round(log1pf(0.6f) * 1000.0f) == 470.0f); + assert(round(log1pl(0.6l) * 1000.0l) == 470.0l); + assert(round(log1p(7) * 1000.0) == 2079.0); + + assert(round(log2(0.6f) * 1000.0f) == -737.0f); + assert(round(log2(0.6) * 1000.0) == -737.0); + assert(round(log2(0.6l) * 1000.0l) == -737.0l); + assert(round(log2f(0.6f) * 1000.0f) == -737.0f); + assert(round(log2l(0.6l) * 1000.0l) == -737.0l); + assert(round(log2(7) * 1000.0) == 2807.0); + + assert(round(cbrt(0.6f) * 1000.0f) == 843.0f); + assert(round(cbrt(0.6) * 1000.0) == 843.0); + assert(round(cbrt(0.6l) * 1000.0l) == 843.0l); + assert(round(cbrtf(0.6f) * 1000.0f) == 843.0f); + assert(round(cbrtl(0.6l) * 1000.0l) == 843.0l); + assert(round(cbrt(7) * 1000.0) == 1913.0); + + assert(round(hypot(3.3f, 7.7f) * 1000.0f) == 8377.0f); + assert(round(hypot(3.3, 7.7) * 1000.0) == 8377.0); + assert(round(hypot(3.3l, 7.7l) * 1000.0l) == 8377.0l); + assert(round(hypotf(3.3f, 7.7f) * 1000.0f) == 8377.0f); + assert(round(hypotl(3.3l, 7.7l) * 1000.0l) == 8377.0l); + assert(round(hypot(3, 7) * 1000.0) == 7616.0); + + assert(round(pow(3.3f, 0.6f) * 1000.0f) == 2047.0f); + assert(round(pow(3.3, 0.6) * 1000.0) == 2047.0); + assert(round(pow(3.3l, 0.6l) * 1000.0l) == 2047.0l); + assert(round(powf(3.3f, 0.6f) * 1000.0f) == 2047.0f); + assert(round(powl(3.3l, 0.6l) * 1000.0l) == 2047.0l); + assert(round(pow(2, -3) * 1000.0) == 125.0); + + assert(round(sqrt(0.6f) * 1000.0f) == 775.0f); + assert(round(sqrt(0.6) * 1000.0) == 775.0); + assert(round(sqrt(0.6l) * 1000.0l) == 775.0l); + assert(round(sqrtf(0.6f) * 1000.0f) == 775.0f); + assert(round(sqrtl(0.6l) * 1000.0l) == 775.0l); + assert(round(sqrt(7) * 1000.0) == 2646.0); + + if !consteval { // TRANSITION, GH-3789 + assert(round(erf(0.6f) * 1000.0f) == 604.0f); + assert(round(erf(0.6) * 1000.0) == 604.0); + assert(round(erf(0.6l) * 1000.0l) == 604.0l); + assert(round(erff(0.6f) * 1000.0f) == 604.0f); + assert(round(erfl(0.6l) * 1000.0l) == 604.0l); + assert(round(erf(1) * 1000.0) == 843.0); + + assert(round(erfc(0.6f) * 1000.0f) == 396.0f); + assert(round(erfc(0.6) * 1000.0) == 396.0); + assert(round(erfc(0.6l) * 1000.0l) == 396.0l); + assert(round(erfcf(0.6f) * 1000.0f) == 396.0f); + assert(round(erfcl(0.6l) * 1000.0l) == 396.0l); + assert(round(erfc(1) * 1000.0) == 157.0); + + assert(round(lgamma(0.6f) * 1000.0f) == 398.0f); + assert(round(lgamma(0.6) * 1000.0) == 398.0); + assert(round(lgamma(0.6l) * 1000.0l) == 398.0l); + assert(round(lgammaf(0.6f) * 1000.0f) == 398.0f); + assert(round(lgammal(0.6l) * 1000.0l) == 398.0l); + assert(round(lgamma(5) * 1000.0) == 3178.0); + + assert(round(tgamma(0.6f) * 1000.0f) == 1489.0f); + assert(round(tgamma(0.6) * 1000.0) == 1489.0); + assert(round(tgamma(0.6l) * 1000.0l) == 1489.0l); + assert(round(tgammaf(0.6f) * 1000.0f) == 1489.0f); + assert(round(tgammal(0.6l) * 1000.0l) == 1489.0l); + assert(round(tgamma(5) * 1000.0) == 24000.0); + } + + return true; +} + +#if defined(_MSVC_INTERNAL_TESTING) || !defined(_M_ARM64EC) // TRANSITION, MSVC-PR-767414/MSVC-PR-768260 fixed LNK2019 +void test_cmath_runtime() { + assert(nearbyint(3.14f) == 3.0f); + assert(nearbyint(3.14) == 3.0); + assert(nearbyint(3.14l) == 3.0l); + assert(nearbyintf(3.14f) == 3.0f); + assert(nearbyintl(3.14l) == 3.0l); + assert(nearbyint(1729) == 1729.0); + + assert(rint(3.14f) == 3.0f); + assert(rint(3.14) == 3.0); + assert(rint(3.14l) == 3.0l); + assert(rintf(3.14f) == 3.0f); + assert(rintl(3.14l) == 3.0l); + assert(rint(1729) == 1729.0); + + assert(lrint(3.14f) == 3L); + assert(lrint(3.14) == 3L); + assert(lrint(3.14l) == 3L); + assert(lrintf(3.14f) == 3L); + assert(lrintl(3.14l) == 3L); + assert(lrint(1729) == 1729L); + + assert(llrint(0x1p60f) == 0x1000'0000'0000'0000LL); + assert(llrint(0x1p60) == 0x1000'0000'0000'0000LL); + assert(llrint(0x1p60l) == 0x1000'0000'0000'0000LL); + assert(llrintf(0x1p60f) == 0x1000'0000'0000'0000LL); + assert(llrintl(0x1p60l) == 0x1000'0000'0000'0000LL); + assert(llrint(1729) == 1729LL); + + assert(isnan(nan(""))); + assert(isnan(nanf(""))); + assert(isnan(nanl(""))); +} +#endif // ^^^ no workaround ^^^ + int main() { #if defined(_MSVC_INTERNAL_TESTING) || !defined(_M_ARM64EC) // TRANSITION, MSVC-PR-767414/MSVC-PR-768260 fixed LNK2019 - test_cmath(); - test_cstdlib(); + test_cmath_cxx23(); + test_cstdlib_cxx23(); + test_cmath_cxx26(); + test_cmath_runtime(); #endif // ^^^ no workaround ^^^ #ifdef __cpp_lib_constexpr_cmath - static_assert(test_cmath()); - static_assert(test_cstdlib()); + static_assert(test_cmath_cxx23()); + static_assert(test_cstdlib_cxx23()); +#if _HAS_CXX26 && defined(_MSVC_LIBC_MATH) // TRANSITION, GH-3789, should be `__cpp_lib_constexpr_cmath >= 202306L` + static_assert(test_cmath_cxx26()); +#endif // ^^^ _HAS_CXX26 && defined(_MSVC_LIBC_MATH) ^^^ #endif // ^^^ defined(__cpp_lib_constexpr_cmath) ^^^ } From 19aa5f3e1ecda7c66c276d648c635a1a410e835c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 23 Aug 2026 13:24:14 -0700 Subject: [PATCH 81/85] yvals_core.h, VSO_0157762_feature_test_macros: Cite tracking issue for Clang and EDG. --- stl/inc/yvals_core.h | 2 +- .../tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 65fb0e9c7e4..e56292fad59 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1832,7 +1832,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #endif // The option /Zc:cmath- disables support for constexpr . -// TRANSITION, Clang and EDG lack support for constexpr . +// TRANSITION, GH-6412, Clang and EDG lack support for constexpr . #if 0 && _HAS_CXX26 && defined(_MSVC_LIBC_MATH) // TRANSITION, GH-3789 #define __cpp_lib_constexpr_cmath 202306L // P1383R2 More constexpr For And #elif _HAS_CXX23 && defined(_MSVC_LIBC_MATH) diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 577f4ddd10b..c4318d11e41 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -221,7 +221,7 @@ STATIC_ASSERT(__cpp_lib_constexpr_charconv == 202207L); #error __cpp_lib_constexpr_charconv is defined #endif -#if _HAS_CXX23 && defined(_MSVC_LIBC_MATH) // TRANSITION, Clang and EDG lack support for constexpr . +#if _HAS_CXX23 && defined(_MSVC_LIBC_MATH) // TRANSITION, GH-6412, Clang and EDG lack support for constexpr . STATIC_ASSERT(__cpp_lib_constexpr_cmath == 202202L); #elif defined(__cpp_lib_constexpr_cmath) #error __cpp_lib_constexpr_cmath is defined From b2a308f0a7ae115ab8a1547ce270c44cae80eb11 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 23 Aug 2026 12:46:53 -0700 Subject: [PATCH 82/85] __msvc_math.hpp: Refine the atan2() workaround. --- stl/inc/__msvc_math.hpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 558b2232ea2..3a459fbc99b 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -396,29 +396,19 @@ _STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, islessgreater) _STL_DEF_OVERLOADED_COMPARISON_FAMILY2(_CONSTEXPR_CMATH23, isunordered) } // extern "C++" -// TRANSITION, LLVM-214934: Preserve the sign of zero when atan2 underflows. -// __builtin_atan2 can return +0 for tiny negative results. _NODISCARD _CONSTEXPR_CMATH26 float __cdecl atan2f(float _Xx0, float _Xx1) noexcept /* strengthened */ { - float _Result = __builtin_atan2f(_Xx0, _Xx1); - if (_Result == 0.0F && _Xx0 != 0.0F) { - return __builtin_copysignf(0.0F, _Xx0); - } - return _Result; + return __builtin_atan2f(_Xx0, _Xx1); } _NODISCARD _CONSTEXPR_CMATH26 double __cdecl atan2(double _Xx0, double _Xx1) noexcept /* strengthened */ { - double _Result = __builtin_atan2(_Xx0, _Xx1); - if (_Result == 0.0 && _Xx0 != 0.0) { - return __builtin_copysign(0.0, _Xx0); + const double _Result = __builtin_atan2(_Xx0, _Xx1); + if (_Result == 0.0 && _Xx0 != 0.0) { // TRANSITION, LLVM-214934: Preserve the sign of zero when atan2 underflows. + return __builtin_copysign(0.0, _Xx0); // __builtin_atan2 can return +0 for tiny negative results. } return _Result; } _NODISCARD _CONSTEXPR_CMATH26 long double __cdecl atan2l(long double _Xx0, long double _Xx1) noexcept /* strengthened */ { - long double _Result = __builtin_atan2l(_Xx0, _Xx1); - if (_Result == 0.0L && _Xx0 != 0.0L) { - return __builtin_copysignl(0.0L, _Xx0); - } - return _Result; + return _CSTD atan2(static_cast(_Xx0), static_cast(_Xx1)); } // _NODISCARD is desirable, despite the out-param From 829c47aa42d3a9b1565200994abed7b9309cb124 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 23 Aug 2026 13:21:13 -0700 Subject: [PATCH 83/85] __msvc_math.hpp, yvals_core.h: Lift `_CONSTEXPR_CMATH26_NYI`, add TRANSITION comments. --- stl/inc/__msvc_math.hpp | 4 +--- stl/inc/yvals_core.h | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/__msvc_math.hpp b/stl/inc/__msvc_math.hpp index 3a459fbc99b..09622c539f2 100644 --- a/stl/inc/__msvc_math.hpp +++ b/stl/inc/__msvc_math.hpp @@ -194,8 +194,7 @@ extern "C" { // Some functions that are needed for C++26 constexpr cmath are not yet implemented by libc. // We polyfill the library with the UCRT and mark these functions with this macro. // The resulting declarations are not able to be used during constant evaluation yet. -#define _CONSTEXPR_CMATH26_NYI inline -#define _CONSTEXPR_CMATH26_NYI_DECL _EMPTY_ARGUMENT +#define _CONSTEXPR_CMATH26_NYI_DECL _EMPTY_ARGUMENT // TRANSITION, GH-3789 // On x86, when not using /arch:SSE2 or greater, floating-point operations are performed // using the x87 instruction set and FLT_EVAL_METHOD is 2. (When /fp:fast is used, @@ -498,7 +497,6 @@ _NODISCARD _CONSTEXPR_CMATH26_NYI long double __cdecl tanhl(long double _Xx) noe #undef _STL_DEF_OVERLOADED_COMPARISON_FAMILY1 #undef _STL_DEF_OVERLOADED_COMPARISON_FAMILY2 #undef _STL_DECLARE_FAMILY1 -#undef _CONSTEXPR_CMATH26_NYI #undef _CONSTEXPR_CMATH26_NYI_DECL } // extern "C" diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index e56292fad59..b037883504b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -977,6 +977,8 @@ _EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC Compiler 19 #define _CONSTEXPR_CMATH26 inline #endif // ^^^ inline when /Zc:cmath- opts out of constexpr, and in C++23 and earlier ^^^ +#define _CONSTEXPR_CMATH26_NYI inline // TRANSITION, GH-3789 + // P2465R3 Standard Library Modules std And std.compat #ifdef _BUILD_STD_MODULE #if !_HAS_CXX20 From 3da5d5d501ad9ec419091e75c20058752ed78084 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 23 Aug 2026 13:25:41 -0700 Subject: [PATCH 84/85] cmath: Pass `_CONSTEXPR_CMATH23/26/26_NYI` to `_GENERIC_MATH`. --- stl/inc/cmath | 147 +++++++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 75a1564599c..183efe26ca5 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -777,27 +777,27 @@ _GENERIC_MATH_ISNORMAL(wchar_t) #endif // defined(_NATIVE_WCHAR_T_DEFINED) #undef _GENERIC_MATH_ISNORMAL -#define _GENERIC_MATH1_BASE(NAME, RET, FUN) \ - template , int> = 0> \ - _NODISCARD _CONSTEXPR_CMATH23 RET NAME(_Ty _Left) noexcept /* strengthened */ { \ - return FUN(static_cast(_Left)); \ +#define _GENERIC_MATH1_BASE(SPECS, NAME, RET, FUN) \ + template , int> = 0> \ + _NODISCARD SPECS RET NAME(_Ty _Left) noexcept /* strengthened */ { \ + return FUN(static_cast(_Left)); \ } -#define _GENERIC_MATH1R(FUN, RET) _GENERIC_MATH1_BASE(FUN, RET, _CSTD FUN) -#define _GENERIC_MATH1(FUN) _GENERIC_MATH1R(FUN, double) +#define _GENERIC_MATH1R(SPECS, FUN, RET) _GENERIC_MATH1_BASE(SPECS, FUN, RET, _CSTD FUN) +#define _GENERIC_MATH1(SPECS, FUN) _GENERIC_MATH1R(SPECS, FUN, double) #if _HAS_CMATH_BUILTINS -#define _GENERIC_MATH1I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(FUN, double, BUILTIN) +#define _GENERIC_MATH1I(SPECS, FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(SPECS, FUN, double, BUILTIN) #elif _HAS_CMATH_INTRINSICS -#define _GENERIC_MATH1I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(FUN, double, INTRINSIC) +#define _GENERIC_MATH1I(SPECS, FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(SPECS, FUN, double, INTRINSIC) #else // ^^^ intrinsics available / intrinsics unavailable vvv -#define _GENERIC_MATH1I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(FUN, double, _CSTD FUN) +#define _GENERIC_MATH1I(SPECS, FUN, BUILTIN, INTRINSIC) _GENERIC_MATH1_BASE(SPECS, FUN, double, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ -#define _GENERIC_MATH1X(FUN, ARG2) \ - template , int> = 0> \ - _NODISCARD _CONSTEXPR_CMATH23 double FUN(_Ty _Left, ARG2 _Arg2) noexcept /* strengthened */ { \ - return _CSTD FUN(static_cast(_Left), _Arg2); \ +#define _GENERIC_MATH1X(SPECS, FUN, ARG2) \ + template , int> = 0> \ + _NODISCARD SPECS double FUN(_Ty _Left, ARG2 _Arg2) noexcept /* strengthened */ { \ + return _CSTD FUN(static_cast(_Left), _Arg2); \ } // When the arguments are both floats or both long doubles, overload resolution prefers the @@ -806,22 +806,21 @@ _GENERIC_MATH_ISNORMAL(wchar_t) // when the types of the two arguments differ, in which case _Common_float_type_t is either double // or long double. Note that double and long double have the same underlying representation on our // supported platforms. -#define _GENERIC_MATH2_BASE(NAME, FUN) \ - template && _STD is_arithmetic_v<_Ty2>, int> = 0> \ - _NODISCARD _CONSTEXPR_CMATH23 _STD _Common_float_type_t<_Ty1, _Ty2> NAME( \ - _Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { \ - return FUN(static_cast(_Left), static_cast(_Right)); \ +#define _GENERIC_MATH2_BASE(SPECS, NAME, FUN) \ + template && _STD is_arithmetic_v<_Ty2>, int> = 0> \ + _NODISCARD SPECS _STD _Common_float_type_t<_Ty1, _Ty2> NAME(_Ty1 _Left, _Ty2 _Right) noexcept /* strengthened */ { \ + return FUN(static_cast(_Left), static_cast(_Right)); \ } -#define _GENERIC_MATH2(FUN) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) +#define _GENERIC_MATH2(SPECS, FUN) _GENERIC_MATH2_BASE(SPECS, FUN, _CSTD FUN) #if _HAS_CMATH_BUILTINS -#define _GENERIC_MATH2I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(FUN, BUILTIN) +#define _GENERIC_MATH2I(SPECS, FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(SPECS, FUN, BUILTIN) #elif _HAS_CMATH_INTRINSICS -#define _GENERIC_MATH2I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(FUN, INTRINSIC) +#define _GENERIC_MATH2I(SPECS, FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(SPECS, FUN, INTRINSIC) #else // ^^^ intrinsics available / intrinsics unavailable vvv -#define _GENERIC_MATH2I(FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(FUN, _CSTD FUN) +#define _GENERIC_MATH2I(SPECS, FUN, BUILTIN, INTRINSIC) _GENERIC_MATH2_BASE(SPECS, FUN, _CSTD FUN) #endif // ^^^ intrinsics unavailable ^^^ // TRANSITION, DevCom-10294165, additional overloads are not templated to avoid ambiguity with the overload in UCRT @@ -861,64 +860,64 @@ _GENERIC_MATH_ISNORMAL(wchar_t) _GENERIC_MATH_CLASSIFY1_RETV_WCHAR_T(FUN, RETV) // The following order matches N4950 [cmath.syn]. -_GENERIC_MATH1(acos) -_GENERIC_MATH1(asin) -_GENERIC_MATH1(atan) -_GENERIC_MATH2(atan2) -_GENERIC_MATH1(cos) -_GENERIC_MATH1(sin) -_GENERIC_MATH1(tan) -_GENERIC_MATH1(acosh) -_GENERIC_MATH1(asinh) -_GENERIC_MATH1(atanh) -_GENERIC_MATH1(cosh) -_GENERIC_MATH1(sinh) -_GENERIC_MATH1(tanh) -_GENERIC_MATH1(exp) -_GENERIC_MATH1(exp2) -_GENERIC_MATH1(expm1) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, acos) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, asin) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, atan) +_GENERIC_MATH2(_CONSTEXPR_CMATH26, atan2) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, cos) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, sin) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, tan) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, acosh) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, asinh) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, atanh) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, cosh) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, sinh) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, tanh) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, exp) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, exp2) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, expm1) // frexp() is hand-crafted -_GENERIC_MATH1R(ilogb, int) -_GENERIC_MATH1X(ldexp, int) -_GENERIC_MATH1(log) -_GENERIC_MATH1(log10) -_GENERIC_MATH1(log1p) -_GENERIC_MATH1(log2) -_GENERIC_MATH1(logb) +_GENERIC_MATH1R(_CONSTEXPR_CMATH23, ilogb, int) +_GENERIC_MATH1X(_CONSTEXPR_CMATH23, ldexp, int) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, log) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, log10) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, log1p) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, log2) +_GENERIC_MATH1(_CONSTEXPR_CMATH23, logb) // No modf(), types must match -_GENERIC_MATH1X(scalbn, int) -_GENERIC_MATH1X(scalbln, long) -_GENERIC_MATH1(cbrt) +_GENERIC_MATH1X(_CONSTEXPR_CMATH23, scalbn, int) +_GENERIC_MATH1X(_CONSTEXPR_CMATH23, scalbln, long) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, cbrt) // abs() has integer overloads -_GENERIC_MATH1(fabs) -_GENERIC_MATH2(hypot) +_GENERIC_MATH1(_CONSTEXPR_CMATH23, fabs) +_GENERIC_MATH2(_CONSTEXPR_CMATH26, hypot) // 3-arg hypot() is hand-crafted // pow() is hand-crafted -_GENERIC_MATH1(sqrt) -_GENERIC_MATH1(erf) -_GENERIC_MATH1(erfc) -_GENERIC_MATH1(lgamma) -_GENERIC_MATH1(tgamma) -_GENERIC_MATH1I(ceil, __builtin_ceil, __ceil) -_GENERIC_MATH1I(floor, __builtin_floor, __floor) -_GENERIC_MATH1(nearbyint) -_GENERIC_MATH1(rint) -_GENERIC_MATH1R(lrint, long) -_GENERIC_MATH1R(llrint, long long) -_GENERIC_MATH1I(round, __builtin_round, __round) -_GENERIC_MATH1R(lround, long) -_GENERIC_MATH1R(llround, long long) -_GENERIC_MATH1I(trunc, __builtin_trunc, __trunc) -_GENERIC_MATH2(fmod) -_GENERIC_MATH2(remainder) +_GENERIC_MATH1(_CONSTEXPR_CMATH26, sqrt) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, erf) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, erfc) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, lgamma) +_GENERIC_MATH1(_CONSTEXPR_CMATH26_NYI, tgamma) +_GENERIC_MATH1I(_CONSTEXPR_CMATH23, ceil, __builtin_ceil, __ceil) +_GENERIC_MATH1I(_CONSTEXPR_CMATH23, floor, __builtin_floor, __floor) +_GENERIC_MATH1(inline, nearbyint) +_GENERIC_MATH1(inline, rint) +_GENERIC_MATH1R(inline, lrint, long) +_GENERIC_MATH1R(inline, llrint, long long) +_GENERIC_MATH1I(_CONSTEXPR_CMATH23, round, __builtin_round, __round) +_GENERIC_MATH1R(_CONSTEXPR_CMATH23, lround, long) +_GENERIC_MATH1R(_CONSTEXPR_CMATH23, llround, long long) +_GENERIC_MATH1I(_CONSTEXPR_CMATH23, trunc, __builtin_trunc, __trunc) +_GENERIC_MATH2(_CONSTEXPR_CMATH23, fmod) +_GENERIC_MATH2(_CONSTEXPR_CMATH23, remainder) // remquo() is hand-crafted -_GENERIC_MATH2I(copysign, __builtin_copysign, __copysign) +_GENERIC_MATH2I(_CONSTEXPR_CMATH23, copysign, __builtin_copysign, __copysign) // nan(const char*) is exempt -_GENERIC_MATH2(nextafter) -_GENERIC_MATH1X(nexttoward, long double) -_GENERIC_MATH2(fdim) -_GENERIC_MATH2(fmax) -_GENERIC_MATH2(fmin) +_GENERIC_MATH2(_CONSTEXPR_CMATH23, nextafter) +_GENERIC_MATH1X(_CONSTEXPR_CMATH23, nexttoward, long double) +_GENERIC_MATH2(_CONSTEXPR_CMATH23, fdim) +_GENERIC_MATH2(_CONSTEXPR_CMATH23, fmax) +_GENERIC_MATH2(_CONSTEXPR_CMATH23, fmin) // fma() is hand-crafted // lerp() is hand-crafted // fpclassify() is hand-crafted From 42b471a56247408e9dcb93a14f68197383aa3b2b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 23 Aug 2026 13:39:15 -0700 Subject: [PATCH 85/85] cmath, P0533R9_constexpr_for_cmath_and_cstdlib: Mark 3-arg hypot as 26_NYI, add test coverage. --- stl/inc/cmath | 10 ++++++---- .../P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp | 8 ++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/stl/inc/cmath b/stl/inc/cmath index 183efe26ca5..0d16a112505 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -1669,24 +1669,26 @@ _GENERIC_MATH_SPECIAL_UINT1(sph_neumann) #undef _GENERIC_MATH_SPECIAL_UINT1 #undef _GENERIC_MATH_SPECIAL_UINT2 -_EXPORT_STD _NODISCARD inline double hypot(const double _Dx, const double _Dy, const double _Dz) noexcept +_EXPORT_STD _NODISCARD _CONSTEXPR_CMATH26_NYI double hypot( + const double _Dx, const double _Dy, const double _Dz) noexcept /* strengthened */ { return __std_smf_hypot3(_Dx, _Dy, _Dz); } -_EXPORT_STD _NODISCARD inline float hypot(const float _Dx, const float _Dy, const float _Dz) noexcept +_EXPORT_STD _NODISCARD _CONSTEXPR_CMATH26_NYI float hypot(const float _Dx, const float _Dy, const float _Dz) noexcept /* strengthened */ { return __std_smf_hypot3f(_Dx, _Dy, _Dz); } -_EXPORT_STD _NODISCARD inline long double hypot( +_EXPORT_STD _NODISCARD _CONSTEXPR_CMATH26_NYI long double hypot( const long double _Dx, const long double _Dy, const long double _Dz) noexcept /* strengthened */ { return __std_smf_hypot3(static_cast(_Dx), static_cast(_Dy), static_cast(_Dz)); } _EXPORT_STD template && is_arithmetic_v<_Ty2> && is_arithmetic_v<_Ty3>, int> = 0> -_NODISCARD auto hypot(const _Ty1 _Dx, const _Ty2 _Dy, const _Ty3 _Dz) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR_CMATH26_NYI auto hypot(const _Ty1 _Dx, const _Ty2 _Dy, const _Ty3 _Dz) noexcept +/* strengthened */ { // N4950 [cmath.syn]/3 "Sufficient additional overloads" // Note that this template is selected by overload resolution only when at least one // argument is double/long double/integral but not all three are double or long double. diff --git a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp index 0b51e792793..18030a5df98 100644 --- a/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp +++ b/tests/std/tests/P0533R9_constexpr_for_cmath_and_cstdlib/test.cpp @@ -541,6 +541,14 @@ constexpr bool test_cmath_cxx26() { assert(round(hypotl(3.3l, 7.7l) * 1000.0l) == 8377.0l); assert(round(hypot(3, 7) * 1000.0) == 7616.0); + if !consteval { // TRANSITION, GH-3789 + assert(round(hypot(2.2f, 3.3f, 4.4f) * 1000.0f) == 5924.0f); + assert(round(hypot(2.2, 3.3, 4.4) * 1000.0) == 5924.0); + assert(round(hypot(2.2l, 3.3l, 4.4l) * 1000.0l) == 5924.0l); + assert(round(hypot(2, 3, 4) * 1000.0) == 5385.0); + // No 3-arg overloads for hypotf() and hypotl() + } + assert(round(pow(3.3f, 0.6f) * 1000.0f) == 2047.0f); assert(round(pow(3.3, 0.6) * 1000.0) == 2047.0); assert(round(pow(3.3l, 0.6l) * 1000.0l) == 2047.0l);