[libcxx-commits] [libcxx] [libc++] Fix ABI tag mismatches during C++20 module deserialization (PR #213495)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Aug 1 17:28:47 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Damian Höster (damster101)

<details>
<summary>Changes</summary>

After updating my clang with tools and libc++ to latest git, I got a lot of `cannot add 'abi_tag' attribute in a redeclaration` compilation errors when compiling a private project. I used an LLM agent (Gemini 3.6 Flash) to fix those errors. While the changes look good and safe to me, they do not appear to exhaustively fix this general issue, but only the parts that affected compilation of my own project, which now compiles again. Maybe this patch is still useful as a baseline?
I assume it was #<!-- -->208348 that exposed all these `_LIBCPP_HIDE_FROM_ABI` attribute mismatches by making module deserialization strictly call `Sema::mergeDeclAttributes()`.

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


8 Files Affected:

- (modified) libcxx/include/__iterator/bounded_iter.h (+3-3) 
- (modified) libcxx/include/__iterator/static_bounded_iter.h (+2-2) 
- (modified) libcxx/include/__memory/pointer_traits.h (+3-1) 
- (modified) libcxx/include/__ostream/basic_ostream.h (+1-1) 
- (modified) libcxx/include/__ostream/print.h (+6-3) 
- (modified) libcxx/include/__string/char_traits.h (+6-6) 
- (modified) libcxx/include/string (+25-21) 
- (modified) libcxx/include/tuple (+9-8) 


``````````diff
diff --git a/libcxx/include/__iterator/bounded_iter.h b/libcxx/include/__iterator/bounded_iter.h
index 9e5d929c8f191..7e9b0a540558f 100644
--- a/libcxx/include/__iterator/bounded_iter.h
+++ b/libcxx/include/__iterator/bounded_iter.h
@@ -105,7 +105,7 @@ struct __bounded_iter {
   }
 
   template <class _It>
-  friend _LIBCPP_CONSTEXPR __bounded_iter<_It> __make_bounded_iter(_It, _It, _It);
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __bounded_iter<_It> __make_bounded_iter(_It, _It, _It);
 
 public:
   // Dereference and indexing operations.
@@ -214,8 +214,8 @@ struct __bounded_iter {
   }
 
 #if _LIBCPP_STD_VER <= 17
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
-  operator!=(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR friend bool operator!=(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT {
     return __x.__current_ != __y.__current_;
   }
 
diff --git a/libcxx/include/__iterator/static_bounded_iter.h b/libcxx/include/__iterator/static_bounded_iter.h
index a048073b5a897..da2ab8e2c3c60 100644
--- a/libcxx/include/__iterator/static_bounded_iter.h
+++ b/libcxx/include/__iterator/static_bounded_iter.h
@@ -123,8 +123,8 @@ struct __static_bounded_iter {
         __current <= __end(), "__static_bounded_iter(current, begin): current and (begin + Size) are inconsistent");
   }
 
-  template <size_t _Sz, class _It>
-  friend _LIBCPP_CONSTEXPR __static_bounded_iter<_It, _Sz> __make_static_bounded_iter(_It, _It);
+  template <class _It, size_t _Sz>
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __static_bounded_iter<_It, _Sz> __make_static_bounded_iter(_It, _It);
 
 public:
   // Dereference and indexing operations.
diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h
index 44567839ed91d..0828b560e2ddc 100644
--- a/libcxx/include/__memory/pointer_traits.h
+++ b/libcxx/include/__memory/pointer_traits.h
@@ -158,6 +158,7 @@ template <class _Pointer>
 inline const bool __has_arrow_v<_Pointer, decltype((void)std::declval<const _Pointer&>().operator->()) > = true;
 
 template <class _Pointer, __enable_if_t<__has_to_address_v<_Pointer>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI
 _LIBCPP_CONSTEXPR __decay_t<decltype(pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))>
 __to_address(const _Pointer& __p) _NOEXCEPT {
   return pointer_traits<_Pointer>::to_address(__p);
@@ -167,7 +168,8 @@ template <class _Pointer>
 struct __to_address_arrow_result;
 
 template <class _Pointer, __enable_if_t<!__has_to_address_v<_Pointer> && __has_arrow_v<_Pointer>, int> = 0>
-_LIBCPP_CONSTEXPR typename __to_address_arrow_result<_Pointer>::type __to_address(const _Pointer& __p) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename __to_address_arrow_result<_Pointer>::type
+__to_address(const _Pointer& __p) _NOEXCEPT {
   return std::__to_address(__p.operator->());
 }
 
diff --git a/libcxx/include/__ostream/basic_ostream.h b/libcxx/include/__ostream/basic_ostream.h
index 43c9399758bf1..b32e26e255043 100644
--- a/libcxx/include/__ostream/basic_ostream.h
+++ b/libcxx/include/__ostream/basic_ostream.h
@@ -573,7 +573,7 @@ _LIBCPP_HIDE_FROM_ABI _Stream&& operator<<(_Stream&& __os, const _Tp& __x) {
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-basic_ostream<_CharT, _Traits>&
+_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
 operator<<(basic_ostream<_CharT, _Traits>& __os, const basic_string<_CharT, _Traits, _Allocator>& __str) {
   return std::__put_character_sequence(__os, __str.data(), __str.size());
 }
diff --git a/libcxx/include/__ostream/print.h b/libcxx/include/__ostream/print.h
index 4a519c177b990..db9abbd775633 100644
--- a/libcxx/include/__ostream/print.h
+++ b/libcxx/include/__ostream/print.h
@@ -88,7 +88,8 @@ _LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
 
 #    if _LIBCPP_HAS_UNICODE
 template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
-_LIBCPP_HIDE_FROM_ABI void __vprint_unicode(ostream& __os, string_view __fmt, format_args __args, bool __write_nl) {
+_LIBCPP_HIDE_FROM_ABI inline void
+__vprint_unicode(ostream& __os, string_view __fmt, format_args __args, bool __write_nl) {
 #      ifndef _WIN32
   return std::__vprint_nonunicode(__os, __fmt, __args, __write_nl);
 #      else
@@ -133,7 +134,8 @@ _LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(ostream& __os, string_view __fm
 #    endif // _LIBCPP_HAS_UNICODE
 
 template <class... _Args>
-_LIBCPP_HIDE_FROM_ABI void print(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) {
+_LIBCPP_HIDE_FROM_ABI
+_LIBCPP_ALWAYS_INLINE void print(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) {
 #    if _LIBCPP_HAS_UNICODE
   if constexpr (__print::__use_unicode_execution_charset)
     std::__vprint_unicode(__os, __fmt.get(), std::make_format_args(__args...), false);
@@ -145,7 +147,8 @@ _LIBCPP_HIDE_FROM_ABI void print(ostream& __os, format_string<_Args...> __fmt, _
 }
 
 template <class... _Args>
-_LIBCPP_HIDE_FROM_ABI void println(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE void
+println(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) {
 #    if _LIBCPP_HAS_UNICODE
   // Note the wording in the Standard is inefficient. The output of
   // std::format is a std::string which is then copied. This solution
diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h
index d98595030e6a5..59a7c948dcac5 100644
--- a/libcxx/include/__string/char_traits.h
+++ b/libcxx/include/__string/char_traits.h
@@ -88,8 +88,8 @@ struct char_traits<char> {
   using comparison_category = strong_ordering;
 #endif
 
-  static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void
-  assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {
+  static inline _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX17 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {
     __c1 = __c2;
   }
 
@@ -301,7 +301,7 @@ struct char_traits<char16_t> : __char_traits_base<char16_t, uint_least16_t, stat
   }
 };
 
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
 char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
   for (; __n; --__n, ++__s1, ++__s2) {
     if (lt(*__s1, *__s2))
@@ -312,7 +312,7 @@ char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, siz
   return 0;
 }
 
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
 char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT {
   size_t __len = 0;
   for (; !eq(*__s, char_type(0)); ++__s)
@@ -336,7 +336,7 @@ struct char_traits<char32_t> : __char_traits_base<char32_t, uint_least32_t, stat
   }
 };
 
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
 char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
   for (; __n; --__n, ++__s1, ++__s2) {
     if (lt(*__s1, *__s2))
@@ -347,7 +347,7 @@ char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, siz
   return 0;
 }
 
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
 char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT {
   size_t __len = 0;
   for (; !eq(*__s, char_type(0)); ++__s)
diff --git a/libcxx/include/string b/libcxx/include/string
index 39de836dbcf85..a4d7c10e7fb18 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -802,7 +802,7 @@ private:
 
     pointer __data_;
     size_type __size_;
-    size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
+    size_type __cap_     : sizeof(size_type) * CHAR_BIT - 1;
     size_type __is_long_ : 1;
   };
 
@@ -856,7 +856,7 @@ private:
 
     struct _LIBCPP_PACKED {
       size_type __is_long_ : 1;
-      size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
+      size_type __cap_     : sizeof(size_type) * CHAR_BIT - 1;
     };
     size_type __size_;
     pointer __data_;
@@ -934,7 +934,7 @@ private:
     return std::__make_bounded_iter(__p, __get_pointer(), __get_pointer() + size());
 #  else
     return const_iterator(__p);
-#  endif                    // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING
+#  endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING
   }
 
 public:
@@ -1153,8 +1153,8 @@ public:
     return assign(__il.begin(), __il.size());
   }
 #  endif
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
-  operator=(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) {
     return assign(__s);
   }
 #  if _LIBCPP_STD_VER >= 23
@@ -1518,8 +1518,8 @@ public:
   }
 #  endif // _LIBCPP_CXX03_LANG
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
-  insert(size_type __pos1, const basic_string& __str) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const basic_string& __str) {
     return insert(__pos1, __str.data(), __str.size());
   }
 
@@ -1564,8 +1564,8 @@ public:
   }
 #  endif
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
-  insert(const_iterator __pos, size_type __n, value_type __c) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, size_type __n, value_type __c) {
     difference_type __p = __pos - begin();
     insert(static_cast<size_type>(__p), __n, __c);
     return begin() + __p;
@@ -1586,8 +1586,8 @@ public:
   }
 
 #  ifndef _LIBCPP_CXX03_LANG
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
-  insert(const_iterator __pos, initializer_list<value_type> __il) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, initializer_list<value_type> __il) {
     return insert(__pos, __il.begin(), __il.end());
   }
 #  endif // _LIBCPP_CXX03_LANG
@@ -2483,7 +2483,7 @@ private:
     std::__throw_out_of_range("basic_string");
   }
 
-  friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string
   __concatenate_strings<>(const _Allocator&, __type_identity_t<__self_view>, __type_identity_t<__self_view>);
 
   template <class _CharT2, class _Traits2, class _Allocator2>
@@ -2839,8 +2839,9 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
 #  ifndef _LIBCPP_CXX03_LANG
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__move_assign(
-    basic_string& __str, false_type) noexcept(__alloc_traits::is_always_equal::value) {
+_LIBCPP_HIDE_FROM_ABI inline
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__move_assign(
+        basic_string& __str, false_type) noexcept(__alloc_traits::is_always_equal::value) {
   if (__alloc_ != __str.__alloc_)
     assign(__str);
   else
@@ -2848,7 +2849,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void
 basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type)
 #    if _LIBCPP_STD_VER >= 17
     noexcept
@@ -3296,7 +3297,7 @@ basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n)
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
 basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) {
   _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
       __pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator");
@@ -3307,7 +3308,7 @@ basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) {
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
 basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) {
   _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "string::erase(first, last) called with invalid range");
   iterator __b  = begin();
@@ -3317,13 +3318,14 @@ basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_i
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() {
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() {
   _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty");
   __erase_to_end(size() - 1);
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void
+basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT {
   size_type __old_size;
   if (__is_long()) {
     __old_size = __get_long_size();
@@ -3435,7 +3437,8 @@ basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n,
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void
+basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
 #  if _LIBCPP_STD_VER >= 14
     _NOEXCEPT
 #  else
@@ -3481,7 +3484,8 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocato
 // __invariants
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX20 bool basic_string<_CharT, _Traits, _Allocator>::__invariants() const {
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
+basic_string<_CharT, _Traits, _Allocator>::__invariants() const {
   if (size() > capacity())
     return false;
   if (capacity() < __min_cap - 1)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 158729969288d..db012d8e682c8 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -558,15 +558,16 @@ class _LIBCPP_NO_SPECIALIZATIONS tuple {
   _BaseT __base_;
 
   template <size_t _Jp, class... _Up>
-  friend _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Jp, tuple<_Up...> >::type& get(tuple<_Up...>&) _NOEXCEPT;
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Jp, tuple<_Up...> >::type&
+  get(tuple<_Up...>&) _NOEXCEPT;
   template <size_t _Jp, class... _Up>
-  friend _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Jp, tuple<_Up...> >::type&
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Jp, tuple<_Up...> >::type&
   get(const tuple<_Up...>&) _NOEXCEPT;
   template <size_t _Jp, class... _Up>
-  friend _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Jp, tuple<_Up...> >::type&&
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Jp, tuple<_Up...> >::type&&
   get(tuple<_Up...>&&) _NOEXCEPT;
   template <size_t _Jp, class... _Up>
-  friend _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Jp, tuple<_Up...> >::type&&
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Jp, tuple<_Up...> >::type&&
   get(const tuple<_Up...>&&) _NOEXCEPT;
 
 public:
@@ -1165,8 +1166,8 @@ template <class... _Tp, class... _Up>
              { __t == __u } -> __boolean_testable;
            }...>::value && (sizeof...(_Tp) == sizeof...(_Up)))
 #    endif
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
-operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) {
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) {
   static_assert(sizeof...(_Tp) == sizeof...(_Up), "Can't compare tuples of different sizes");
   return std::__tuple_compare_equal<sizeof...(_Tp)>(__x, __y);
 }
@@ -1186,8 +1187,8 @@ operator<=>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) {
 #    else // _LIBCPP_STD_VER >= 20
 
 template <class... _Tp, class... _Up>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
-operator!=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) {
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator!=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) {
   return !(__x == __y);
 }
 

``````````

</details>


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


More information about the libcxx-commits mailing list