[libcxx-commits] [libcxx] [libc++] Fix hypotf linker error with Clang modules on Windows UCRT (PR #209403)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jul 14 02:05:25 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Junji Watanabe (Jwata)

<details>
<summary>Changes</summary>

This commit resolves an undefined symbol `hypotf` linking error that occurs when compiling standard C++ headers with Clang modules enabled targeting Windows with MSVC C-Runtime (UCRT).

You can find the minimal repro at Chromium here: https://crrev.com/c/8085003

### Context & Cause
Under Windows UCRT, the import libraries (`ucrt.lib`/`ucrtd.lib`) do not export the symbol `hypotf` directly. Instead, they export `_hypotf`. The UCRT header `corecrt_math.h` declares `hypotf` as an inline wrapper function:

```cpp
_Check_return_ __inline float __CRTDECL hypotf(_In_ float _X, _In_ float _Y) {
  return _hypotf(_X, _Y);
}
```

When building libc++ with Clang modules enabled at Chromium, the `std_core.math.hypot` submodule (mapping to `__math/hypot.h`) is precompiled into a binary module file in isolation.

Because `__math/hypot.h` does not include `<math.h>` or `<cmath>`, Clang's front-end parses the submodule without visibility of the UCRT inline declaration of `hypotf`.
1. During AST resolution of `std::hypot` (defined using `__builtin_hypotf`), the front-end fails to bind the builtin to the inline wrapper `hypotf` since it is not present in the symbol table.
2. Clang passes `__builtin_hypotf` down to the LLVM backend.
3. The LLVM backend's `TargetLibraryInfo` config for MSVC expects the standard `hypotf` symbol to be available, and thus lowers it to a direct external call to the symbol `hypotf`.
4. This results in the object file containing a direct external reference to `hypotf` rather than an imported call to `__imp__hypotf`.
5. The link phase fails because no `hypotf` symbol exists in `ucrt.lib`.

### Solution
We bypass `__builtin_hypotf` and `__builtin_hypotl` on Windows targeting UCRT (when `_LIBCPP_MSVCRT` is defined):
1. **For `float`**: We explicitly declare the imported UCRT `_hypotf` function (using the `_LIBCPP_CRT_FUNC` macro to dynamically support both static `/MT` and DLL `/MD` runtime linking) and route `std::hypot(float, float)` to it.
2. **For `long double`**: Since `long double` is represented as a 64-bit float (identical to `double`) on MSVC, and `_hypotl` is also inline-only in UCRT, we promote the arguments to `double` and forward to the `double` implementation (which maps to the exported `hypot` symbol).

Assisted-by: Gemini

---
Full diff: https://github.com/llvm/llvm-project/pull/209403.diff


1 Files Affected:

- (modified) libcxx/include/__math/hypot.h (+17-1) 


``````````diff
diff --git a/libcxx/include/__math/hypot.h b/libcxx/include/__math/hypot.h
index 2b12d7be21072..37788e542fa66 100644
--- a/libcxx/include/__math/hypot.h
+++ b/libcxx/include/__math/hypot.h
@@ -27,11 +27,23 @@
 _LIBCPP_PUSH_MACROS
 #include <__undef_macros>
 
+#if defined(_LIBCPP_MSVCRT)
+extern "C" {
+_LIBCPP_CRT_FUNC float __cdecl _hypotf(float, float);
+}
+#endif
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 namespace __math {
 
-inline _LIBCPP_HIDE_FROM_ABI float hypot(float __x, float __y) _NOEXCEPT { return __builtin_hypotf(__x, __y); }
+inline _LIBCPP_HIDE_FROM_ABI float hypot(float __x, float __y) _NOEXCEPT {
+#if defined(_LIBCPP_MSVCRT)
+  return ::_hypotf(__x, __y);
+#else
+  return __builtin_hypotf(__x, __y);
+#endif
+}
 
 template <class = int>
 _LIBCPP_HIDE_FROM_ABI double hypot(double __x, double __y) _NOEXCEPT {
@@ -39,7 +51,11 @@ _LIBCPP_HIDE_FROM_ABI double hypot(double __x, double __y) _NOEXCEPT {
 }
 
 inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y) _NOEXCEPT {
+#if defined(_LIBCPP_MSVCRT)
+  return (long double)__math::hypot((double)__x, (double)__y);
+#else
   return __builtin_hypotl(__x, __y);
+#endif
 }
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>

``````````

</details>


https://github.com/llvm/llvm-project/pull/209403


More information about the libcxx-commits mailing list