Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reland: [libc++][format] P2637R3: Member visit (std::basic_format_arg) #76449 #79032

Merged
merged 13 commits into from
Jan 29, 2024

Conversation

H-G-Hristov
Copy link
Contributor

@H-G-Hristov H-G-Hristov commented Jan 22, 2024

Deleted the offending test case.

libcxx/test/std/utilities/format/format.arguments/format.arg/visit.return_type.pass.cpp
lines: 134-135:

test<Context, bool, long>(true, 192812079084L);
test<Context, bool, long>(false, 192812079084L);

Relands: #76449
Reverted in: 02f95b7

@H-G-Hristov H-G-Hristov requested a review from a team as a code owner January 22, 2024 18:44
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jan 22, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 22, 2024

@llvm/pr-subscribers-libcxx

Author: Hristo Hristov (H-G-Hristov)

Changes

Patch is 51.26 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/79032.diff

15 Files Affected:

  • (modified) libcxx/docs/ReleaseNotes/18.rst (+1)
  • (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1)
  • (modified) libcxx/docs/Status/FormatIssues.csv (+1-1)
  • (modified) libcxx/include/__config (+6)
  • (modified) libcxx/include/__format/format_arg.h (+106-3)
  • (modified) libcxx/include/__format/format_context.h (+19-14)
  • (modified) libcxx/include/format (+1-1)
  • (added) libcxx/test/std/utilities/format/format.arguments/format.arg/visit.pass.cpp (+333)
  • (added) libcxx/test/std/utilities/format/format.arguments/format.arg/visit.return_type.pass.cpp (+366)
  • (added) libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.deprecated.verify.cpp (+38)
  • (modified) libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.pass.cpp (+5-1)
  • (modified) libcxx/test/std/utilities/format/format.arguments/format.args/get.pass.cpp (+29-19)
  • (modified) libcxx/test/support/test_basic_format_arg.h (+12-8)
  • (modified) libcxx/test/support/test_macros.h (+5)
  • (modified) libcxx/utils/generate_feature_test_macro_components.py (+1)
diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst
index fd882bafe19a517..237a63022d55ff5 100644
--- a/libcxx/docs/ReleaseNotes/18.rst
+++ b/libcxx/docs/ReleaseNotes/18.rst
@@ -79,6 +79,7 @@ Implemented Papers
 - P1759R6 - Native handles and file streams
 - P2868R3 - Remove Deprecated ``std::allocator`` Typedef From C++26
 - P2517R1 - Add a conditional ``noexcept`` specification to ``std::apply``
+- P2637R3 - Member ``visit``
 - P2447R6 - ``span`` over initializer list
 
 
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index f80b1f6b663f045..c45aa3c510072e4 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -17,7 +17,7 @@
 "`P0792R14 <https://wg21.link/P0792R14>`__","LWG","``function_ref``: a type-erased callable reference","Varna June 2023","","",""
 "`P2874R2 <https://wg21.link/P2874R2>`__","LWG","Mandating Annex D Require No More","Varna June 2023","","",""
 "`P2757R3 <https://wg21.link/P2757R3>`__","LWG","Type-checking format args","Varna June 2023","","","|format|"
-"`P2637R3 <https://wg21.link/P2637R3>`__","LWG","Member ``visit``","Varna June 2023","|Partial|","18.0",""
+"`P2637R3 <https://wg21.link/P2637R3>`__","LWG","Member ``visit``","Varna June 2023","|Complete|","18.0",""
 "`P2641R4 <https://wg21.link/P2641R4>`__","CWG, LWG","Checking if a ``union`` alternative is active","Varna June 2023","","",""
 "`P1759R6 <https://wg21.link/P1759R6>`__","LWG","Native handles and file streams","Varna June 2023","|Complete|","18.0",""
 "`P2697R1 <https://wg21.link/P2697R1>`__","LWG","Interfacing ``bitset`` with ``string_view``","Varna June 2023","|Complete|","18.0",""
diff --git a/libcxx/docs/Status/FormatIssues.csv b/libcxx/docs/Status/FormatIssues.csv
index 513988d08036ca6..6e58e752191ea5d 100644
--- a/libcxx/docs/Status/FormatIssues.csv
+++ b/libcxx/docs/Status/FormatIssues.csv
@@ -16,7 +16,7 @@ Number,Name,Standard,Assignee,Status,First released version
 "`P2693R1 <https://wg21.link/P2693R1>`__","Formatting ``thread::id`` and ``stacktrace``","C++23","Mark de Wever","|In Progress|"
 "`P2510R3 <https://wg21.link/P2510R3>`__","Formatting pointers","C++26","Mark de Wever","|Complete|",17.0
 "`P2757R3 <https://wg21.link/P2757R3>`__","Type-checking format args","C++26","","",
-"`P2637R3 <https://wg21.link/P2637R3>`__","Member ``visit``","C++26","","",
+"`P2637R3 <https://wg21.link/P2637R3>`__","Member ``visit``","C++26","Hristo Hristov","|Complete|",18.0
 "`P2905R2 <https://wg21.link/P2905R2>`__","Runtime format strings","C++26 DR","Mark de Wever","|Complete|",18.0
 "`P2918R2 <https://wg21.link/P2918R2>`__","Runtime format strings II","C++26","Mark de Wever","|Complete|",18.0
 "`P2909R4 <https://wg21.link/P2909R4>`__","Fix formatting of code units as integers (Dude, where’s my ``char``?)","C++26 DR","Mark de Wever","|Complete|",18.0
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 9a64cdb489119d9..00489d971c296c2 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -995,6 +995,12 @@ typedef __char32_t char32_t;
 #    define _LIBCPP_DEPRECATED_IN_CXX23
 #  endif
 
+#  if _LIBCPP_STD_VER >= 26
+#    define _LIBCPP_DEPRECATED_IN_CXX26 _LIBCPP_DEPRECATED
+#  else
+#    define _LIBCPP_DEPRECATED_IN_CXX26
+#  endif
+
 #  if !defined(_LIBCPP_HAS_NO_CHAR8_T)
 #    define _LIBCPP_DEPRECATED_WITH_CHAR8_T _LIBCPP_DEPRECATED
 #  else
diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h
index 10fca15d5a7a94e..02ee3cef7d402b7 100644
--- a/libcxx/include/__format/format_arg.h
+++ b/libcxx/include/__format/format_arg.h
@@ -93,7 +93,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __arg_t __get_packed_type(uint64_t __types, size
 
 } // namespace __format
 
-// This function is not user obervable, so it can directly use the non-standard
+// This function is not user observable, so it can directly use the non-standard
 // types of the "variant". See __arg_t for more details.
 template <class _Visitor, class _Context>
 _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
@@ -144,6 +144,59 @@ _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_
   __libcpp_unreachable();
 }
 
+#  if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
+
+template <class _Rp, class _Visitor, class _Context>
+_LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
+  switch (__arg.__type_) {
+  case __format::__arg_t::__none:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__monostate_);
+  case __format::__arg_t::__boolean:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__boolean_);
+  case __format::__arg_t::__char_type:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__char_type_);
+  case __format::__arg_t::__int:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__int_);
+  case __format::__arg_t::__long_long:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_);
+  case __format::__arg_t::__i128:
+#    ifndef _LIBCPP_HAS_NO_INT128
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__i128_);
+#    else
+    __libcpp_unreachable();
+#    endif
+  case __format::__arg_t::__unsigned:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_);
+  case __format::__arg_t::__unsigned_long_long:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_);
+  case __format::__arg_t::__u128:
+#    ifndef _LIBCPP_HAS_NO_INT128
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__u128_);
+#    else
+    __libcpp_unreachable();
+#    endif
+  case __format::__arg_t::__float:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__float_);
+  case __format::__arg_t::__double:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__double_);
+  case __format::__arg_t::__long_double:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_double_);
+  case __format::__arg_t::__const_char_type_ptr:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_);
+  case __format::__arg_t::__string_view:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__string_view_);
+  case __format::__arg_t::__ptr:
+    return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__ptr_);
+  case __format::__arg_t::__handle:
+    return std::invoke_r<_Rp>(
+        std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_});
+  }
+
+  __libcpp_unreachable();
+}
+
+#  endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
+
 /// Contains the values used in basic_format_arg.
 ///
 /// This is a separate type so it's possible to store the values and types in
@@ -227,6 +280,52 @@ class _LIBCPP_TEMPLATE_VIS basic_format_arg {
 
   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __type_ != __format::__arg_t::__none; }
 
+#  if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
+
+  // This function is user facing, so it must wrap the non-standard types of
+  // the "variant" in a handle to stay conforming. See __arg_t for more details.
+  template <class _Visitor>
+  _LIBCPP_HIDE_FROM_ABI decltype(auto) visit(this basic_format_arg __arg, _Visitor&& __vis) {
+    switch (__arg.__type_) {
+#    ifndef _LIBCPP_HAS_NO_INT128
+    case __format::__arg_t::__i128: {
+      typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_};
+      return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
+    }
+
+    case __format::__arg_t::__u128: {
+      typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_};
+      return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
+    }
+#    endif
+    default:
+      return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg);
+    }
+  }
+
+  // This function is user facing, so it must wrap the non-standard types of
+  // the "variant" in a handle to stay conforming. See __arg_t for more details.
+  template <class _Rp, class _Visitor>
+  _LIBCPP_HIDE_FROM_ABI _Rp visit(this basic_format_arg __arg, _Visitor&& __vis) {
+    switch (__arg.__type_) {
+#    ifndef _LIBCPP_HAS_NO_INT128
+    case __format::__arg_t::__i128: {
+      typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_};
+      return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
+    }
+
+    case __format::__arg_t::__u128: {
+      typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_};
+      return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
+    }
+#    endif
+    default:
+      return std::__visit_format_arg<_Rp>(std::forward<_Visitor>(__vis), __arg);
+    }
+  }
+
+#  endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
+
 private:
   using char_type = typename _Context::char_type;
 
@@ -267,7 +366,11 @@ class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle {
 // This function is user facing, so it must wrap the non-standard types of
 // the "variant" in a handle to stay conforming. See __arg_t for more details.
 template <class _Visitor, class _Context>
-_LIBCPP_HIDE_FROM_ABI decltype(auto) visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
+#  if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
+_LIBCPP_DEPRECATED_IN_CXX26
+#  endif
+    _LIBCPP_HIDE_FROM_ABI decltype(auto)
+    visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
   switch (__arg.__type_) {
 #  ifndef _LIBCPP_HAS_NO_INT128
   case __format::__arg_t::__i128: {
@@ -279,7 +382,7 @@ _LIBCPP_HIDE_FROM_ABI decltype(auto) visit_format_arg(_Visitor&& __vis, basic_fo
     typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_};
     return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
   }
-#  endif
+#  endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
   default:
     return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg);
   }
diff --git a/libcxx/include/__format/format_context.h b/libcxx/include/__format/format_context.h
index 5b252b81f691bc1..0beaa84b028beb7 100644
--- a/libcxx/include/__format/format_context.h
+++ b/libcxx/include/__format/format_context.h
@@ -163,20 +163,25 @@ class _LIBCPP_TEMPLATE_VIS basic_format_context<typename __format::__retarget_bu
 #  endif
         __ctx_(std::addressof(__ctx)),
         __arg_([](void* __c, size_t __id) {
-          return std::visit_format_arg(
-              [&](auto __arg) -> basic_format_arg<basic_format_context> {
-                if constexpr (same_as<decltype(__arg), monostate>)
-                  return {};
-                else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Context>::handle>)
-                  // At the moment it's not possible for formatting to use a re-targeted handle.
-                  // TODO FMT add this when support is needed.
-                  std::__throw_format_error("Re-targeting handle not supported");
-                else
-                  return basic_format_arg<basic_format_context>{
-                      __format::__determine_arg_t<basic_format_context, decltype(__arg)>(),
-                      __basic_format_arg_value<basic_format_context>(__arg)};
-              },
-              static_cast<_Context*>(__c)->arg(__id));
+          auto __visitor = [&](auto __arg) -> basic_format_arg<basic_format_context> {
+            if constexpr (same_as<decltype(__arg), monostate>)
+              return {};
+            else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Context>::handle>)
+              // At the moment it's not possible for formatting to use a re-targeted handle.
+              // TODO FMT add this when support is needed.
+              std::__throw_format_error("Re-targeting handle not supported");
+            else
+              return basic_format_arg<basic_format_context>{
+                  __format::__determine_arg_t<basic_format_context, decltype(__arg)>(),
+                  __basic_format_arg_value<basic_format_context>(__arg)};
+          };
+#  if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
+          return static_cast<_Context*>(__c)->arg(__id).visit(std::move(__visitor));
+#  else
+          _LIBCPP_SUPPRESS_DEPRECATED_PUSH
+          return std::visit_format_arg(std::move(__visitor), static_cast<_Context*>(__c)->arg(__id));
+          _LIBCPP_SUPPRESS_DEPRECATED_POP
+#  endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
         }) {
   }
 
diff --git a/libcxx/include/format b/libcxx/include/format
index ab9b336d0cdabee..64f6ba1d25284aa 100644
--- a/libcxx/include/format
+++ b/libcxx/include/format
@@ -170,7 +170,7 @@ namespace std {
   template<class Context> class basic_format_arg;
 
   template<class Visitor, class Context>
-    see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
+    see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); // Deprecated in C++26
 
   // [format.arg.store], class template format-arg-store
   template<class Context, class... Args> struct format-arg-store;      // exposition only
diff --git a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.pass.cpp b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.pass.cpp
new file mode 100644
index 000000000000000..994ccc70a38daae
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.pass.cpp
@@ -0,0 +1,333 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
+// The tested functionality needs deducing this.
+// UNSUPPORTED: clang-16 || clang-17
+// XFAIL: apple-clang
+
+// <format>
+
+// class basic_format_arg;
+
+// template<class Visitor>
+//   decltype(auto) visit(this basic_format_arg arg, Visitor&& vis);  // since C++26
+
+#include <algorithm>
+#include <cassert>
+#include <format>
+#include <type_traits>
+
+#include "constexpr_char_traits.h"
+#include "make_string.h"
+#include "min_allocator.h"
+#include "test_macros.h"
+
+template <class Context, class To, class From>
+void test(From value) {
+  auto store = std::make_format_args<Context>(value);
+  std::basic_format_args<Context> format_args{store};
+
+  LIBCPP_ASSERT(format_args.__size() == 1);
+  assert(format_args.get(0));
+
+  auto result = format_args.get(0).visit([v = To(value)](auto a) -> To {
+    if constexpr (std::is_same_v<To, decltype(a)>) {
+      assert(v == a);
+      return a;
+    } else {
+      assert(false);
+      return {};
+    }
+  });
+
+  using ct = std::common_type_t<From, To>;
+  assert(static_cast<ct>(result) == static_cast<ct>(value));
+}
+
+// Some types, as an extension, are stored in the variant. The Standard
+// requires them to be observed as a handle.
+template <class Context, class T>
+void test_handle(T value) {
+  auto store = std::make_format_args<Context>(value);
+  std::basic_format_args<Context> format_args{store};
+
+  LIBCPP_ASSERT(format_args.__size() == 1);
+  assert(format_args.get(0));
+
+  format_args.get(0).visit([](auto a) {
+    assert((std::is_same_v<decltype(a), typename std::basic_format_arg<Context>::handle>));
+  });
+}
+
+// Test specific for string and string_view.
+//
+// Since both result in a string_view there's no need to pass this as a
+// template argument.
+template <class Context, class From>
+void test_string_view(From value) {
+  auto store = std::make_format_args<Context>(value);
+  std::basic_format_args<Context> format_args{store};
+
+  LIBCPP_ASSERT(format_args.__size() == 1);
+  assert(format_args.get(0));
+
+  using CharT = typename Context::char_type;
+  using To    = std::basic_string_view<CharT>;
+  using V     = std::basic_string<CharT>;
+
+  auto result = format_args.get(0).visit([v = V(value.begin(), value.end())](auto a) -> To {
+    if constexpr (std::is_same_v<To, decltype(a)>) {
+      assert(v == a);
+      return a;
+    } else {
+      assert(false);
+      return {};
+    }
+  });
+
+  assert(std::equal(value.begin(), value.end(), result.begin(), result.end()));
+}
+
+template <class CharT>
+void test() {
+  using Context = std::basic_format_context<CharT*, CharT>;
+  std::basic_string<CharT> empty;
+  std::basic_string<CharT> str = MAKE_STRING(CharT, "abc");
+
+  // Test boolean types.
+
+  test<Context, bool>(true);
+  test<Context, bool>(false);
+
+  // Test CharT types.
+
+  test<Context, CharT, CharT>('a');
+  test<Context, CharT, CharT>('z');
+  test<Context, CharT, CharT>('0');
+  test<Context, CharT, CharT>('9');
+
+  // Test char types.
+
+  if (std::is_same_v<CharT, char>) {
+    // char to char -> char
+    test<Context, CharT, char>('a');
+    test<Context, CharT, char>('z');
+    test<Context, CharT, char>('0');
+    test<Context, CharT, char>('9');
+  } else {
+    if (std::is_same_v<CharT, wchar_t>) {
+      // char to wchar_t -> wchar_t
+      test<Context, wchar_t, char>('a');
+      test<Context, wchar_t, char>('z');
+      test<Context, wchar_t, char>('0');
+      test<Context, wchar_t, char>('9');
+    } else if (std::is_signed_v<char>) {
+      // char to CharT -> int
+      // This happens when CharT is a char8_t, char16_t, or char32_t and char
+      // is a signed type.
+      // Note if sizeof(CharT) > sizeof(int) this test fails. If there are
+      // platforms where that occurs extra tests need to be added for char32_t
+      // testing it against a long long.
+      test<Context, int, char>('a');
+      test<Context, int, char>('z');
+      test<Context, int, char>('0');
+      test<Context, int, char>('9');
+    } else {
+      // char to CharT -> unsigned
+      // This happens when CharT is a char8_t, char16_t, or char32_t and char
+      // is an unsigned type.
+      // Note if sizeof(CharT) > sizeof(unsigned) this test fails. If there are
+      // platforms where that occurs extra tests need to be added for char32_t
+      // testing it against an unsigned long long.
+      test<Context, unsigned, char>('a');
+      test<Context, unsigned, char>('z');
+      test<Context, unsigned, char>('0');
+      test<Context, unsigned, char>('9');
+    }
+  }
+
+  // Test signed integer types.
+
+  test<Context, int, signed char>(std::numeric_limits<signed char>::min());
+  test<Context, int, signed char>(0);
+  test<Context, int, signed char>(std::numeric_limits<signed char>::max());
+
+  test<Context, int, short>(std::numeric_limits<short>::min());
+  test<Context, int, short>(std::numeric_limits<signed char>::min());
+  test<Context, int, short>(0);
+  test<Context, int, short>(std::numeric_limits<signed char>::max());
+  test<Context, int, short>(std::numeric_limits<short>::max());
+
+  test<Context, int, int>(std::numeric_limits<int>::min());
+  test<Context, int, int>(std::numeric_limits<short>::min());
+  test<Context, int, int>(std::numeric_limits<signed char>::min());
+  test<Context, int, int>(0);
+  test<Context, int, int>(std::numeric_limits<signed char>::max());
+  test<Context, int, int>(std::numeric_limits<short>::max());
+  test<Context, int, int>(std::numeric_limits<int>::max());
+
+  using LongToType = std::conditional_t<sizeof(long) == sizeof(int), int, long long>;
+
+  test<Context, LongToType, long>(std::numeric_limits<long>::min());
+  test<Context, LongToType, long>(std::numeric_limits<int>::min());
+  test<Context, LongToType, long>(std::numeric_limits<short...
[truncated]

@mordante mordante self-assigned this Jan 22, 2024
Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@petrhosek the original patches worked in our Windows pre-commit CI. Can you verify this patch works for you.

I'm still happy with the patch. Please wait for @petrhosek's confirmation before landing.

@H-G-Hristov
Copy link
Contributor Author

@petrhosek Thank you for reacting. I'm sorry I didn't see your message earlier: #76449 (comment)

@mstorsjo
Copy link
Member

@petrhosek the original patches worked in our Windows pre-commit CI.

FWIW, the reason for this is that the test has UNSUPPORTED: clang-16 || clang-17, and the Windows pre-commit CI only uses release versions of clang.

Copy link
Contributor Author

@H-G-Hristov H-G-Hristov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@petrhosek the original patches worked in our Windows pre-commit CI.

FWIW, the reason for this is that the test has UNSUPPORTED: clang-16 || clang-17, and the Windows pre-commit CI only uses release versions of clang.

Hmm, now that this #78991 has landed we could probably replace the guards with: __has_extension(cxx_explicit_this_parameter)

@petrhosek
Copy link
Member

@H-G-Hristov Would it be possible to update your branch? I sent it to our Windows builders but Clang is segfaulting while building runtimes.

@H-G-Hristov
Copy link
Contributor Author

H-G-Hristov commented Jan 24, 2024

@H-G-Hristov Would it be possible to update your branch? I sent it to our Windows builders but Clang is segfaulting while building runtimes.

@petrhosek Thank you for taking a look. I updated the branch. Please note that pre-release Clang 18 used to have a bug related to "deducing this", which is used by this feature. It has been rectified since then:
#75913
#75732
The other patch related to this paper P2637R3 (memberv visit variant) seems to have passed the CI:
#76449

Could the crash be related to the above?

@H-G-Hristov
Copy link
Contributor Author

H-G-Hristov commented Jan 25, 2024

I noticed some of clang-cl test crashed (cmake + python errors). I rebased again.

Copy link
Contributor Author

@H-G-Hristov H-G-Hristov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mordante I guess the PR missed LLVM18 release. I'll update the release notes accordingly. Is that OK?

libcxx/docs/Status/Cxx2cPapers.csv Outdated Show resolved Hide resolved
libcxx/docs/Status/FormatIssues.csv Outdated Show resolved Hide resolved
libcxx/docs/ReleaseNotes/18.rst Outdated Show resolved Hide resolved
@petrhosek
Copy link
Member

I tried this branch on our Windows builders although I'm not sure if it's related or not to this patch:

# COMPILED WITH
C:/b/s/w/ir/x/w/llvm_build/./bin/clang-cl.exe C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp --driver-mode=g++ --target=x86_64-pc-windows-msvc -fms-runtime-lib=static -nostdinc++ -I C:/b/s/w/ir/x/w/llvm_build/include/c++/v1 -I C:/b/s/w/ir/x/w/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -I C:/b/s/w/ir/x/w/github-H-G-Hristov-llvm-project/libcxx/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety -Wuser-defined-warnings  -llibc++experimental -nostdlib -L C:/b/s/w/ir/x/w/llvm_build/./lib/x86_64-pc-windows-msvc -llibc++ -llibcpmt -o C:\b\s\w\ir\x\w\llvm_build\runtimes\runtimes-x86_64-pc-windows-msvc-bins\test\libcxx\fuzzing\Output\random.pass.cpp.dir\t.tmp.exe
# executed command: C:/b/s/w/ir/x/w/llvm_build/./bin/clang-cl.exe 'C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp' --driver-mode=g++ --target=x86_64-pc-windows-msvc -fms-runtime-lib=static -nostdinc++ -I C:/b/s/w/ir/x/w/llvm_build/include/c++/v1 -I C:/b/s/w/ir/x/w/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -I C:/b/s/w/ir/x/w/github-H-G-Hristov-llvm-project/libcxx/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety -Wuser-defined-warnings -llibc++experimental -nostdlib -L C:/b/s/w/ir/x/w/llvm_build/./lib/x86_64-pc-windows-msvc -llibc++ -llibcpmt -o 'C:\b\s\w\ir\x\w\llvm_build\runtimes\runtimes-x86_64-pc-windows-msvc-bins\test\libcxx\fuzzing\Output\random.pass.cpp.dir\t.tmp.exe'
# .---command stderr------------
# | In file included from C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:16:
# | In file included from C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\cmath:319:
# | In file included from C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\math.h:301:
# | In file included from C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\math.h:11:
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:413:16: error: call to 'fpclassify' is ambiguous
# |   413 |         return fpclassify(_X) == FP_NAN;
# |       |                ^~~~~~~~~~
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:166:12: note: in instantiation of function template specialization 'isnan<short>' requested here
# |   166 |   if (std::isnan(res)) {
# |       |            ^
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:178:10: note: in instantiation of function template specialization 'helper<std::uniform_int_distribution<short>>' requested here
# |   178 |   return helper<std::uniform_int_distribution<std::int16_t>>(data, size)       ||
# |       |          ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:288:31: note: candidate function
# |   288 |     _Check_return_ inline int fpclassify(_In_ float _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:293:31: note: candidate function
# |   293 |     _Check_return_ inline int fpclassify(_In_ double _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:298:31: note: candidate function
# |   298 |     _Check_return_ inline int fpclassify(_In_ long double _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:413:16: error: call to 'fpclassify' is ambiguous
# |   413 |         return fpclassify(_X) == FP_NAN;
# |       |                ^~~~~~~~~~
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:166:12: note: in instantiation of function template specialization 'isnan<bool>' requested here
# |   166 |   if (std::isnan(res)) {
# |       |            ^
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:180:10: note: in instantiation of function template specialization 'helper<std::bernoulli_distribution>' requested here
# |   180 |          helper<std::bernoulli_distribution>(data, size)                       ||
# |       |          ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:288:31: note: candidate function
# |   288 |     _Check_return_ inline int fpclassify(_In_ float _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:293:31: note: candidate function
# |   293 |     _Check_return_ inline int fpclassify(_In_ double _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:298:31: note: candidate function
# |   298 |     _Check_return_ inline int fpclassify(_In_ long double _X) throw()
# |       |                               ^
# | In file included from C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:20:
# | In file included from C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\random:1686:
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/clamp_to_integral.h:36:86: error: shift count is negative [-Werror,-Wshift-count-negative]
# |    36 |   return _FloatBigger ? numeric_limits<_IntT>::max() : (numeric_limits<_IntT>::max() >> _Bits << _Bits);
# |       |                                                                                      ^  ~~~~~
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/clamp_to_integral.h:46:27: note: in instantiation of function template specialization 'std::__max_representable_int_for_float<short, double, true, -38>' requested here
# |    46 |   const _IntT __max_val = __max_representable_int_for_float<_IntT, _RealT>();
# |       |                           ^
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/poisson_distribution.h:153:21: note: in instantiation of function template specialization 'std::__clamp_to_integral<short, double>' requested here
# |   153 |         return std::__clamp_to_integral<result_type>(__tx);
# |       |                     ^
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/poisson_distribution.h:83:12: note: in instantiation of function template specialization 'std::poisson_distribution<short>::operator()<std::mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 2567483615, 11, 4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>>' requested here
# |    83 |     return (*this)(__g, __p_);
# |       |            ^
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:165:23: note: in instantiation of function template specialization 'std::poisson_distribution<short>::operator()<std::mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 2567483615, 11, 4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>>' requested here
# |   165 |   volatile auto res = d(engine);
# |       |                       ^
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:181:10: note: in instantiation of function template specialization 'helper<std::poisson_distribution<short>>' requested here
# |   181 |          helper<std::poisson_distribution<std::int16_t>>(data, size)           ||
# |       |          ^
# | In file included from C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:20:
# | In file included from C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\random:1686:
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/clamp_to_integral.h:36:95: error: shift count is negative [-Werror,-Wshift-count-negative]
# |    36 |   return _FloatBigger ? numeric_limits<_IntT>::max() : (numeric_limits<_IntT>::max() >> _Bits << _Bits);
# |       |                                                                                               ^  ~~~~~
# | 4 errors generated.
# `-----------------------------
# error: command failed with exit status: 1

--

https://logs.chromium.org/logs/fuchsia/led/phosek_google.com/62644843c966785c9dedf065a79d80df8734b4df5ff7703ea3c2a2b5643cec05/+/u/clang/test/stdout is the full log.

@Zingam
Copy link
Contributor

Zingam commented Jan 26, 2024

@petrhosek It is not related. It was supposedly fixed by this: #79619
I've been observing the chromium Windows CI failing for a while. Let's see if the above patch fixes it. I'll rebase now this one now.

@Zingam
Copy link
Contributor

Zingam commented Jan 26, 2024

@petrhosek According to the log, the tests in this patch pass. Could you please try again. I'll wait a while and if there is no negative feedback I'll reland the patch.

https://logs.chromium.org/logs/fuchsia/led/phosek_google.com/62644843c966785c9dedf065a79d80df8734b4df5ff7703ea3c2a2b5643cec05/+/u/clang/test/stdout is the full log.

 PASS: llvm-libc++-static-clangcl.cfg.in :: std/utilities/format/format.arguments/format.arg/visit.pass.cpp (8505 of 9639)
 PASS: llvm-libc++-static-clangcl.cfg.in :: std/utilities/format/format.arguments/format.arg/visit_format_arg.pass.cpp (8506 of 9639)
 PASS: llvm-libc++-static-clangcl.cfg.in :: std/utilities/format/format.arguments/format.arg/visit.return_type.pass.cpp (8537 of 9639)
 PASS: llvm-libc++-static-clangcl.cfg.in :: std/utilities/format/format.arguments/format.arg/visit_format_arg.deprecated.verify.cpp (8439 of 9639)

@H-G-Hristov
Copy link
Contributor Author

H-G-Hristov commented Jan 27, 2024

I tried this branch on our Windows builders although I'm not sure if it's related or not to this patch:

# COMPILED WITH
C:/b/s/w/ir/x/w/llvm_build/./bin/clang-cl.exe C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp --driver-mode=g++ --target=x86_64-pc-windows-msvc -fms-runtime-lib=static -nostdinc++ -I C:/b/s/w/ir/x/w/llvm_build/include/c++/v1 -I C:/b/s/w/ir/x/w/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -I C:/b/s/w/ir/x/w/github-H-G-Hristov-llvm-project/libcxx/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety -Wuser-defined-warnings  -llibc++experimental -nostdlib -L C:/b/s/w/ir/x/w/llvm_build/./lib/x86_64-pc-windows-msvc -llibc++ -llibcpmt -o C:\b\s\w\ir\x\w\llvm_build\runtimes\runtimes-x86_64-pc-windows-msvc-bins\test\libcxx\fuzzing\Output\random.pass.cpp.dir\t.tmp.exe
# executed command: C:/b/s/w/ir/x/w/llvm_build/./bin/clang-cl.exe 'C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp' --driver-mode=g++ --target=x86_64-pc-windows-msvc -fms-runtime-lib=static -nostdinc++ -I C:/b/s/w/ir/x/w/llvm_build/include/c++/v1 -I C:/b/s/w/ir/x/w/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -I C:/b/s/w/ir/x/w/github-H-G-Hristov-llvm-project/libcxx/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety -Wuser-defined-warnings -llibc++experimental -nostdlib -L C:/b/s/w/ir/x/w/llvm_build/./lib/x86_64-pc-windows-msvc -llibc++ -llibcpmt -o 'C:\b\s\w\ir\x\w\llvm_build\runtimes\runtimes-x86_64-pc-windows-msvc-bins\test\libcxx\fuzzing\Output\random.pass.cpp.dir\t.tmp.exe'
# .---command stderr------------
# | In file included from C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:16:
# | In file included from C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\cmath:319:
# | In file included from C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\math.h:301:
# | In file included from C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\math.h:11:
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:413:16: error: call to 'fpclassify' is ambiguous
# |   413 |         return fpclassify(_X) == FP_NAN;
# |       |                ^~~~~~~~~~
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:166:12: note: in instantiation of function template specialization 'isnan<short>' requested here
# |   166 |   if (std::isnan(res)) {
# |       |            ^
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:178:10: note: in instantiation of function template specialization 'helper<std::uniform_int_distribution<short>>' requested here
# |   178 |   return helper<std::uniform_int_distribution<std::int16_t>>(data, size)       ||
# |       |          ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:288:31: note: candidate function
# |   288 |     _Check_return_ inline int fpclassify(_In_ float _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:293:31: note: candidate function
# |   293 |     _Check_return_ inline int fpclassify(_In_ double _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:298:31: note: candidate function
# |   298 |     _Check_return_ inline int fpclassify(_In_ long double _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:413:16: error: call to 'fpclassify' is ambiguous
# |   413 |         return fpclassify(_X) == FP_NAN;
# |       |                ^~~~~~~~~~
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:166:12: note: in instantiation of function template specialization 'isnan<bool>' requested here
# |   166 |   if (std::isnan(res)) {
# |       |            ^
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:180:10: note: in instantiation of function template specialization 'helper<std::bernoulli_distribution>' requested here
# |   180 |          helper<std::bernoulli_distribution>(data, size)                       ||
# |       |          ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:288:31: note: candidate function
# |   288 |     _Check_return_ inline int fpclassify(_In_ float _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:293:31: note: candidate function
# |   293 |     _Check_return_ inline int fpclassify(_In_ double _X) throw()
# |       |                               ^
# | C:\b\s\w\ir\cache\windows_sdk\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_math.h:298:31: note: candidate function
# |   298 |     _Check_return_ inline int fpclassify(_In_ long double _X) throw()
# |       |                               ^
# | In file included from C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:20:
# | In file included from C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\random:1686:
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/clamp_to_integral.h:36:86: error: shift count is negative [-Werror,-Wshift-count-negative]
# |    36 |   return _FloatBigger ? numeric_limits<_IntT>::max() : (numeric_limits<_IntT>::max() >> _Bits << _Bits);
# |       |                                                                                      ^  ~~~~~
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/clamp_to_integral.h:46:27: note: in instantiation of function template specialization 'std::__max_representable_int_for_float<short, double, true, -38>' requested here
# |    46 |   const _IntT __max_val = __max_representable_int_for_float<_IntT, _RealT>();
# |       |                           ^
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/poisson_distribution.h:153:21: note: in instantiation of function template specialization 'std::__clamp_to_integral<short, double>' requested here
# |   153 |         return std::__clamp_to_integral<result_type>(__tx);
# |       |                     ^
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/poisson_distribution.h:83:12: note: in instantiation of function template specialization 'std::poisson_distribution<short>::operator()<std::mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 2567483615, 11, 4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>>' requested here
# |    83 |     return (*this)(__g, __p_);
# |       |            ^
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:165:23: note: in instantiation of function template specialization 'std::poisson_distribution<short>::operator()<std::mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 2567483615, 11, 4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>>' requested here
# |   165 |   volatile auto res = d(engine);
# |       |                       ^
# | C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:181:10: note: in instantiation of function template specialization 'helper<std::poisson_distribution<short>>' requested here
# |   181 |          helper<std::poisson_distribution<std::int16_t>>(data, size)           ||
# |       |          ^
# | In file included from C:\b\s\w\ir\x\w\github-H-G-Hristov-llvm-project\libcxx\test\libcxx\fuzzing\random.pass.cpp:20:
# | In file included from C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\random:1686:
# | C:/b/s/w/ir/x/w/llvm_build/include/c++/v1\__random/clamp_to_integral.h:36:95: error: shift count is negative [-Werror,-Wshift-count-negative]
# |    36 |   return _FloatBigger ? numeric_limits<_IntT>::max() : (numeric_limits<_IntT>::max() >> _Bits << _Bits);
# |       |                                                                                               ^  ~~~~~
# | 4 errors generated.
# `-----------------------------
# error: command failed with exit status: 1

--

https://logs.chromium.org/logs/fuchsia/led/phosek_google.com/62644843c966785c9dedf065a79d80df8734b4df5ff7703ea3c2a2b5643cec05/+/u/clang/test/stdout is the full log.

This issue was already reported a while back here: #70225
Mitigated by XFAIL here: #79619
The Chromium Windows build is happy currently: https://ci.chromium.org/p/fuchsia/g/llvm/console

@mordante
Copy link
Member

@mordante I guess the PR missed LLVM18 release. I'll update the release notes accordingly. Is that OK?

Yes. It would have been nice to get this in LLVM 18, but I don't feel it's critical to backport it. (Especially since it's a C++26 only feature and I expect very few people are already using it.)

@Zingam Zingam merged commit 27e67cd into llvm:main Jan 29, 2024
52 checks passed
@H-G-Hristov H-G-Hristov deleted the hgh/libcxx/revert-revert_member_visit branch January 29, 2024 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants