[libc-commits] [libc] [libc][memory_utils] Rename shadowed load/store to avoid ADL ambiguity (PR #211714)

via libc-commits libc-commits at lists.llvm.org
Thu Jul 23 22:48:34 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Jackson Stogel (jtstogel)

<details>
<summary>Changes</summary>

When compiling with MSVC for non-x86 architectures, `op_generic.h` picks a non-builtin type for generic_v128 and friends: https://github.com/llvm/llvm-project/blob/cad3c95a89c48d714a71f6e8b4af6f3e3ab100ea/libc/src/string/memory_utils/op_generic.h#L54-L57

This causes calls to `load` and `store` to trigger ADL, which is ambiguous with `load` definition in `memory_utils/utils.h`.

```
C:\Users\jtstogel\Github\llvm-project\libc\src/string/memory_utils/op_generic.h(348): error C2668: '__llvm_libc_24_0_0_git::generic::store': ambiguous call to overloaded function
C:\Users\jtstogel\Github\llvm-project\libc\src/string/memory_utils/op_generic.h(138): note: could be 'void __llvm_libc_24_0_0_git::generic::store<T>(__llvm_libc_24_0_0_git::Ptr,T)'
        with
        [
            T=__llvm_libc_24_0_0_git::inline_memmove_aarch64::uint512_t
        ]
C:\Users\jtstogel\Github\llvm-project\libc\src/string/memory_utils/utils.h(221): note: or       'void __llvm_libc_24_0_0_git::store<T>(__llvm_libc_24_0_0_git::Ptr,T)' [found using argument-dependent lookup]
        with
        [
            T=__llvm_libc_24_0_0_git::inline_memmove_aarch64::uint512_t
        ]
C:\Users\jtstogel\Github\llvm-project\libc\src/string/memory_utils/op_generic.h(348): note: while trying to match the argument list '(__llvm_libc_24_0_0_git::Ptr, const T)'
        with
        [
            T=__llvm_libc_24_0_0_git::inline_memmove_aarch64::uint512_t
        ]
```

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


2 Files Affected:

- (modified) libc/src/string/memory_utils/op_generic.h (+3-3) 
- (modified) libc/src/string/memory_utils/utils.h (+5-5) 


``````````diff
diff --git a/libc/src/string/memory_utils/op_generic.h b/libc/src/string/memory_utils/op_generic.h
index a86cbd8bcfc72..670ef085f9dee 100644
--- a/libc/src/string/memory_utils/op_generic.h
+++ b/libc/src/string/memory_utils/op_generic.h
@@ -125,7 +125,7 @@ template <typename T> constexpr size_t array_size_v = array_size<T>::value;
 template <typename T> T load(CPtr src) {
   static_assert(is_element_type_v<T>);
   if constexpr (is_scalar_v<T> || is_vector_v<T>) {
-    return ::LIBC_NAMESPACE::load<T>(src);
+    return load_unaligned<T>(src);
   } else if constexpr (is_array_v<T>) {
     using value_type = typename T::value_type;
     T value;
@@ -138,7 +138,7 @@ template <typename T> T load(CPtr src) {
 template <typename T> void store(Ptr dst, T value) {
   static_assert(is_element_type_v<T>);
   if constexpr (is_scalar_v<T> || is_vector_v<T>) {
-    ::LIBC_NAMESPACE::store<T>(dst, value);
+    store_unaligned<T>(dst, value);
   } else if constexpr (is_array_v<T>) {
     using value_type = typename T::value_type;
     for (size_t i = 0; i < array_size_v<T>; ++i)
@@ -357,7 +357,7 @@ template <typename T> struct Memmove {
 // Making the offset explicit hints the compiler to use relevant addressing mode
 // consistently.
 template <typename T> LIBC_INLINE T load(CPtr ptr, size_t offset) {
-  return ::LIBC_NAMESPACE::load<T>(ptr + offset);
+  return load_unaligned<T>(ptr + offset);
 }
 
 // Same as above but also makes sure the loaded value is in big endian format.
diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h
index 9824c4b058b3a..b1a4885cb8c1f 100644
--- a/libc/src/string/memory_utils/utils.h
+++ b/libc/src/string/memory_utils/utils.h
@@ -211,14 +211,14 @@ LIBC_INLINE MemcmpReturnType cmp_neq_uint64_t(uint64_t a, uint64_t b) {
 
 // Loads bytes from memory (possibly unaligned) and materializes them as
 // type.
-template <typename T> LIBC_INLINE T load(CPtr ptr) {
+template <typename T> LIBC_INLINE T load_unaligned(CPtr ptr) {
   T out;
   memcpy_inline<sizeof(T)>(&out, ptr);
   return out;
 }
 
 // Stores a value of type T in memory (possibly unaligned).
-template <typename T> LIBC_INLINE void store(Ptr ptr, T value) {
+template <typename T> LIBC_INLINE void store_unaligned(Ptr ptr, T value) {
   memcpy_inline<sizeof(T)>(ptr, &value);
 }
 
@@ -234,7 +234,7 @@ template <typename ValueType, typename T, typename... TS>
 LIBC_INLINE ValueType load_aligned(CPtr src) {
   static_assert(sizeof(ValueType) >= (sizeof(T) + ... + sizeof(TS)));
   static_assert(Endian::IS_LITTLE || Endian::IS_BIG, "Invalid endianness");
-  const ValueType value = load<T>(assume_aligned<sizeof(T)>(src));
+  const ValueType value = load_unaligned<T>(assume_aligned<sizeof(T)>(src));
 
   if constexpr (sizeof...(TS) > 0) {
     const ValueType next = load_aligned<ValueType, TS...>(src + sizeof(T));
@@ -274,12 +274,12 @@ LIBC_INLINE void store_aligned(ValueType value, Ptr dst) {
   static_assert(sizeof(ValueType) >= (sizeof(T) + ... + sizeof(TS)));
   constexpr size_t SHIFT = sizeof(T) * 8;
   if constexpr (Endian::IS_LITTLE) {
-    store<T>(assume_aligned<sizeof(T)>(dst), T(value & T(~0)));
+    store_unaligned<T>(assume_aligned<sizeof(T)>(dst), T(value & T(~0)));
     if constexpr (sizeof...(TS) > 0)
       store_aligned<ValueType, TS...>(value >> SHIFT, dst + sizeof(T));
   } else if constexpr (Endian::IS_BIG) {
     constexpr size_t OFFSET = (0 + ... + sizeof(TS));
-    store<T>(assume_aligned<sizeof(T)>(dst + OFFSET), value & ~T(0));
+    store_unaligned<T>(assume_aligned<sizeof(T)>(dst + OFFSET), value & ~T(0));
     if constexpr (sizeof...(TS) > 0)
       store_aligned<ValueType, TS...>(value >> SHIFT, dst);
   } else {

``````````

</details>


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


More information about the libc-commits mailing list