llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.33k stars 11.7k forks source link

clang++, libstdc++14, std=c++23 : lots of library code in mainstream libraries fails to build #97842

Closed jcelerier closed 2 months ago

jcelerier commented 3 months ago

Some repros ; easily reproducible on an archlinux container.

Ex. 1: https://github.com/boostorg/container/issues/282

Repro:

$ docker run -v $PWD:/src -it archlinux:latest
$ pacman -Sy
$ pacman -S clang 
$ echo '#include <boost/container/flat_map.hpp>

int main() {
  boost::container::flat_map<int, int> f;
  f[0];
}' > foo.cpp

$  clang++ foo.cpp -std=c++23 -I /src/boost_1_85_0

Ex. 2: https://github.com/martinus/unordered_dense/issues/119 Ex. 3:

#include <nlohmann/json.hpp>

void x(const char* s, int n)
{
  nlohmann::json::parse(s, s + n);
}

cause errors such as :

/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/tuple:956:36: error: no matching function for call to 'get'
  956 |             return __convertible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
      |                                           ^~~~~~~~~~~~~
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/tuple:955:11: note: in instantiation of function template specialization 'std::tuple<const std::basic_string<char> &>::__convertible_from_tuple_like()::(anonymous class)::operator()<0UL>' requested here
  955 |           return []<size_t... _Is>(index_sequence<_Is...>) {
      |                  ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/tuple:1136:22: note: in instantiation of function template specialization 'std::tuple<const std::basic_string<char> &>::__convertible_from_tuple_like<const std::basic_string<char> &>' requested here
 1136 |         constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
      |                             ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_map.h:514:38: note: while substituting deduced template arguments into function template 'tuple' [with _UTuple = const key_type &]
  514 |                                             std::tuple<const key_type&>(__k),
      |                                                                         ^
/usr/include/nlohmann/detail/input/json_sax.hpp:442:66: note: in instantiation of member function 'std::map<std::basic_string<char>, nlohmann::basic_json<>, std::less<void>>::operator[]' requested here
  442 |             object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
      |                                                                  ^
/usr/include/nlohmann/detail/input/parser.hpp:219:56: note: in instantiation of member function 'nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<>>::key' requested here
  219 |                         if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
      |                                                        ^
/usr/include/nlohmann/detail/input/parser.hpp:98:13: note: in instantiation of function template specialization 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char *>>::sax_parse_internal<nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<>>>' requested here
   98 |             sax_parse_internal(&sdp);
      |             ^
/usr/include/nlohmann/json.hpp:4029:113: note: in instantiation of member function 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char *>>::parse' requested here
 4029 |         parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
      |                                                                                                                 ^
/usr/include/nlohmann/json.hpp:5138:28: note: in instantiation of function template specialization 'nlohmann::basic_json<>::parse<const char *>' requested here
 5138 |     return nlohmann::json::parse(s, s + n);
      |                            ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:122:5: note: candidate template ignored: could not match 'tuple' against 'basic_string'
  122 |     get(tuple<_Elements...>& __t) noexcept;
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:126:5: note: candidate template ignored: could not match 'tuple' against 'basic_string'
  126 |     get(const tuple<_Elements...>& __t) noexcept;
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:130:5: note: candidate template ignored: could not match 'tuple' against 'basic_string'
  130 |     get(tuple<_Elements...>&& __t) noexcept;
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:134:5: note: candidate template ignored: could not match 'tuple' against 'basic_string'
  134 |     get(const tuple<_Elements...>&& __t) noexcept;
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:138:5: note: candidate template ignored: could not match 'array' against 'basic_string'
  138 |     get(array<_Tp, _Nm>&) noexcept;
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:142:5: note: candidate template ignored: could not match 'array' against 'basic_string'
  142 |     get(array<_Tp, _Nm>&&) noexcept;
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:146:5: note: candidate template ignored: could not match 'array' against 'basic_string'
  146 |     get(const array<_Tp, _Nm>&) noexcept;
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:150:5: note: candidate template ignored: could not match 'array' against 'basic_string'
  150 |     get(const array<_Tp, _Nm>&&) noexcept;
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1250:5: note: candidate template ignored: could not match 'pair' against 'basic_string'
 1250 |     get(pair<_Tp1, _Tp2>& __in) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1255:5: note: candidate template ignored: could not match 'pair' against 'basic_string'
 1255 |     get(pair<_Tp1, _Tp2>&& __in) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1260:5: note: candidate template ignored: could not match 'pair' against 'basic_string'
 1260 |     get(const pair<_Tp1, _Tp2>& __in) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1265:5: note: candidate template ignored: could not match 'pair' against 'basic_string'
 1265 |     get(const pair<_Tp1, _Tp2>&& __in) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/ranges_util.h:444:5: note: candidate template ignored: could not match 'subrange' against 'basic_string'
  444 |     get(const subrange<_It, _Sent, _Kind>& __r)
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/ranges_util.h:455:5: note: candidate template ignored: could not match 'subrange' against 'basic_string'
  455 |     get(subrange<_It, _Sent, _Kind>&& __r)
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1272:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp'
 1272 |     get(pair<_Tp, _Up>& __p) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1277:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp'
 1277 |     get(const pair<_Tp, _Up>& __p) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1282:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp'
 1282 |     get(pair<_Tp, _Up>&& __p) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1287:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp'
 1287 |     get(const pair<_Tp, _Up>&& __p) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1292:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp'
 1292 |     get(pair<_Up, _Tp>& __p) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1297:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp'
 1297 |     get(const pair<_Up, _Tp>& __p) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1302:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp'
 1302 |     get(pair<_Up, _Tp>&& __p) noexcept
      |     ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1307:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp'
 1307 |     get(const pair<_Up, _Tp>&& __p) noexcept
      |     ^
1 warning and 1 error generated.
BertalanD commented 3 months ago

Ran across the same thing in one of my projects; updating to Clang 18 fixed the compilation errors.

Clang 17 won't be getting any updates (19 is just around the corner), maybe it would be worth asking libstdc++ developers to add a workaround on their side?

llvmbot commented 3 months ago

@llvm/issue-subscribers-clang-frontend

Author: Jean-Michaël Celerier (jcelerier)

Some repros ; easily reproducible on an archlinux container. Ex. 1: https://github.com/boostorg/container/issues/282 Repro: ```bash $ docker run -v $PWD:/src -it archlinux:latest $ pacman -Sy $ pacman -S clang $ echo '#include <boost/container/flat_map.hpp> int main() { boost::container::flat_map<int, int> f; f[0]; }' > foo.cpp $ clang++ foo.cpp -std=c++23 -I /src/boost_1_85_0 ``` Ex. 2: https://github.com/martinus/unordered_dense/issues/119 Ex. 3: ```c++ #include <nlohmann/json.hpp> void x(const char* s, int n) { nlohmann::json::parse(s, s + n); } ``` cause errors such as : ``` /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/tuple:956:36: error: no matching function for call to 'get' 956 | return __convertible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>(); | ^~~~~~~~~~~~~ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/tuple:955:11: note: in instantiation of function template specialization 'std::tuple<const std::basic_string<char> &>::__convertible_from_tuple_like()::(anonymous class)::operator()<0UL>' requested here 955 | return []<size_t... _Is>(index_sequence<_Is...>) { | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/tuple:1136:22: note: in instantiation of function template specialization 'std::tuple<const std::basic_string<char> &>::__convertible_from_tuple_like<const std::basic_string<char> &>' requested here 1136 | constexpr explicit(!__convertible_from_tuple_like<_UTuple>()) | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_map.h:514:38: note: while substituting deduced template arguments into function template 'tuple' [with _UTuple = const key_type &] 514 | std::tuple<const key_type&>(__k), | ^ /usr/include/nlohmann/detail/input/json_sax.hpp:442:66: note: in instantiation of member function 'std::map<std::basic_string<char>, nlohmann::basic_json<>, std::less<void>>::operator[]' requested here 442 | object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); | ^ /usr/include/nlohmann/detail/input/parser.hpp:219:56: note: in instantiation of member function 'nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<>>::key' requested here 219 | if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) | ^ /usr/include/nlohmann/detail/input/parser.hpp:98:13: note: in instantiation of function template specialization 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char *>>::sax_parse_internal<nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<>>>' requested here 98 | sax_parse_internal(&sdp); | ^ /usr/include/nlohmann/json.hpp:4029:113: note: in instantiation of member function 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char *>>::parse' requested here 4029 | parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); | ^ /usr/include/nlohmann/json.hpp:5138:28: note: in instantiation of function template specialization 'nlohmann::basic_json<>::parse<const char *>' requested here 5138 | return nlohmann::json::parse(s, s + n); | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:122:5: note: candidate template ignored: could not match 'tuple' against 'basic_string' 122 | get(tuple<_Elements...>& __t) noexcept; | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:126:5: note: candidate template ignored: could not match 'tuple' against 'basic_string' 126 | get(const tuple<_Elements...>& __t) noexcept; | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:130:5: note: candidate template ignored: could not match 'tuple' against 'basic_string' 130 | get(tuple<_Elements...>&& __t) noexcept; | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:134:5: note: candidate template ignored: could not match 'tuple' against 'basic_string' 134 | get(const tuple<_Elements...>&& __t) noexcept; | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:138:5: note: candidate template ignored: could not match 'array' against 'basic_string' 138 | get(array<_Tp, _Nm>&) noexcept; | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:142:5: note: candidate template ignored: could not match 'array' against 'basic_string' 142 | get(array<_Tp, _Nm>&&) noexcept; | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:146:5: note: candidate template ignored: could not match 'array' against 'basic_string' 146 | get(const array<_Tp, _Nm>&) noexcept; | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:150:5: note: candidate template ignored: could not match 'array' against 'basic_string' 150 | get(const array<_Tp, _Nm>&&) noexcept; | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1250:5: note: candidate template ignored: could not match 'pair' against 'basic_string' 1250 | get(pair<_Tp1, _Tp2>& __in) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1255:5: note: candidate template ignored: could not match 'pair' against 'basic_string' 1255 | get(pair<_Tp1, _Tp2>&& __in) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1260:5: note: candidate template ignored: could not match 'pair' against 'basic_string' 1260 | get(const pair<_Tp1, _Tp2>& __in) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1265:5: note: candidate template ignored: could not match 'pair' against 'basic_string' 1265 | get(const pair<_Tp1, _Tp2>&& __in) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/ranges_util.h:444:5: note: candidate template ignored: could not match 'subrange' against 'basic_string' 444 | get(const subrange<_It, _Sent, _Kind>& __r) | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/ranges_util.h:455:5: note: candidate template ignored: could not match 'subrange' against 'basic_string' 455 | get(subrange<_It, _Sent, _Kind>&& __r) | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1272:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 1272 | get(pair<_Tp, _Up>& __p) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1277:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 1277 | get(const pair<_Tp, _Up>& __p) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1282:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 1282 | get(pair<_Tp, _Up>&& __p) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1287:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 1287 | get(const pair<_Tp, _Up>&& __p) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1292:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 1292 | get(pair<_Up, _Tp>& __p) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1297:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 1297 | get(const pair<_Up, _Tp>& __p) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1302:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 1302 | get(pair<_Up, _Tp>&& __p) noexcept | ^ /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/stl_pair.h:1307:5: note: candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 1307 | get(const pair<_Up, _Tp>&& __p) noexcept | ^ 1 warning and 1 error generated. ```
jwakely commented 2 months ago

Clang 17 won't be getting any updates (19 is just around the corner), maybe it would be worth asking libstdc++ developers to add a workaround on their side?

I'll consider patches to do so, but I'm not going to spend my own time working around bugs in "old" versions of Clang (I know 17 isn't very old, but if you want to use -std=c++23 then you can also use a version of Clang where that works better).

BertalanD commented 2 months ago

Sounds reasonable to me, sorry if my comment sounded demanding. Let me take a stab at it.

jwakely commented 2 months ago

No, don't worry - it's a reasonable request, and we do try to support clang. I just don't know what the problem is here, and so don't know how to solve it.

If somebody knows (or can bisect to find out) which Clang change fixed this, then that might help to come up with a workaround.

BertalanD commented 2 months ago

Bisect part 1 done: this is the commit where it broke: https://github.com/llvm/llvm-project/commit/bba6ea8c2d56faad49936b95a57c7499095b920b

BertalanD commented 2 months ago

@jwakely https://github.com/llvm/llvm-project/commit/128b3b61fe6768c724975fd1df2be0abec848cf6 is the commit that fixed this

jwakely commented 2 months ago

So is this just a dup of #59827?

I think what changed is that libstdc++ now uses explicit(bool) more widely in C++23 mode.

jwakely commented 2 months ago

I suggested a possible workaround in GCC bugzilla, but I can't test it right now

BertalanD commented 2 months ago

Duplicate of #59827

BertalanD commented 2 months ago

I tried searching in Bugzilla, but I didn't find the workaround you mentioned. Was I looking in the wrong place?

Anyway, this issue is even less vital now that Arch Linux is finally shipping Clang 18 in their repos.

jwakely commented 2 months ago

Weird, I can't find it now either, so I wonder where I added that comment!

The suggestion I apparently never made was:

diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 0604bc2c520..fc2fa0c195f 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1766,6 +1766,7 @@ ftms = {
   values = {
     v = 202207;
     cxxmin = 23;
+    extra_cond = "! defined __clang__ || __clang > 17";
   };
 };

diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index e9ccc116f9f..e83e79596e1 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1939,7 +1939,7 @@
 #undef __glibcxx_want_to_underlying

 #if !defined(__cpp_lib_tuple_like)
-# if (__cplusplus >= 202100L)
+# if (__cplusplus >= 202100L) && (! defined __clang__ || __clang > 17)
 #  define __glibcxx_tuple_like 202207L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_tuple_like)
 #   define __cpp_lib_tuple_like 202207L