[libcxx-commits] [libcxx] 5d73c7d - [libc++] Re-introduce special support for narrowing conversions to bool in variant (#73121)
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Nov 22 11:41:16 PST 2023
Author: bgra8
Date: 2023-11-22T20:41:12+01:00
New Revision: 5d73c7d1af78379827759dfb57887246e47a503e
URL: https://github.com/llvm/llvm-project/commit/5d73c7d1af78379827759dfb57887246e47a503e
DIFF: https://github.com/llvm/llvm-project/commit/5d73c7d1af78379827759dfb57887246e47a503e.diff
LOG: [libc++] Re-introduce special support for narrowing conversions to bool in variant (#73121)
This patch re-introduces special support for narrowing conversions to
bool
in std::variant, which was removed in 170810fca6ee in order to make
libc++
Standards-conforming.
The special support is gated by the
`_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT`
macro and will be supported for LLVM 18 only as a courtesy to help large
code bases migrate over to the Standard behavior.
---------
Co-authored-by: Bogdan Graur <bgraur at google.com>
Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>
Added:
Modified:
libcxx/docs/ReleaseNotes/18.rst
libcxx/include/variant
libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp
libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp
libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp
libcxx/test/support/variant_test_helpers.h
Removed:
################################################################################
diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst
index c28a5b73f7ec68b..f9e0bdee3176a1a 100644
--- a/libcxx/docs/ReleaseNotes/18.rst
+++ b/libcxx/docs/ReleaseNotes/18.rst
@@ -81,6 +81,12 @@ Deprecations and Removals
- The non-conforming constructor ``std::future_error(std::error_code)`` has been removed. Please use the
``std::future_error(std::future_errc)`` constructor provided in C++17 instead.
+- `P1957 <https://wg21.link/P1957>` has been implemented in Clang and libc++ removed a code path that led to
+ narrowing conversions in ``std::variant`` behaving in a non-standard way. This may change how some uses of
+ ``std::variant``'s constructor behave in user code. The ``_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT``
+ macro is provided to restore the previous behavior, and it will be supported in the LLVM 18 release only.
+ In LLVM 19 and beyond, ``_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT`` will not be honored anymore.
+
Upcoming Deprecations and Removals
----------------------------------
diff --git a/libcxx/include/variant b/libcxx/include/variant
index d89c0596b1db0de..8f31de6da01ac6c 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -1252,6 +1252,25 @@ struct __overload {
auto operator()(_Tp, _Up&&) const -> __check_for_narrowing<_Tp, _Up>;
};
+// TODO(LLVM-19): Remove all occurrences of this macro.
+#ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
+template <class _Tp, size_t>
+struct __overload_bool {
+ template <class _Up, class _Ap = __remove_cvref_t<_Up>>
+ auto operator()(bool, _Up&&) const
+ -> enable_if_t<is_same_v<_Ap, bool>, __type_identity<_Tp>>;
+};
+
+template <size_t _Idx>
+struct __overload<bool, _Idx> : __overload_bool<bool, _Idx> {};
+template <size_t _Idx>
+struct __overload<bool const, _Idx> : __overload_bool<bool const, _Idx> {};
+template <size_t _Idx>
+struct __overload<bool volatile, _Idx> : __overload_bool<bool volatile, _Idx> {};
+template <size_t _Idx>
+struct __overload<bool const volatile, _Idx> : __overload_bool<bool const volatile, _Idx> {};
+#endif
+
template <class ..._Bases>
struct __all_overloads : _Bases... {
void operator()() const;
diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp
index c63626090c2fe9a..b3fc2021a6b2237 100644
--- a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp
@@ -146,8 +146,10 @@ void test_T_assignment_sfinae() {
};
static_assert(!std::is_assignable<V, X>::value,
"no boolean conversion in operator=");
+#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
static_assert(std::is_assignable<V, std::false_type>::value,
"converted to bool in operator=");
+#endif
}
{
struct X {};
@@ -297,11 +299,13 @@ void test_T_assignment_performs_assignment() {
}
void test_T_assignment_vector_bool() {
+#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
std::vector<bool> vec = {true};
std::variant<bool, int> v;
v = vec[0];
assert(v.index() == 0);
assert(std::get<0>(v) == true);
+#endif
}
int main(int, char**) {
diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp
index d93d429e262c05b..246309c01b4d76b 100644
--- a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp
@@ -34,7 +34,9 @@ int main(int, char**)
static_assert(!std::is_assignable<std::variant<int, bool>, decltype("meow")>::value, "");
static_assert(!std::is_assignable<std::variant<int, const bool>, decltype("meow")>::value, "");
+#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
static_assert(std::is_assignable<std::variant<bool>, std::true_type>::value, "");
+#endif
static_assert(!std::is_assignable<std::variant<bool>, std::unique_ptr<char> >::value, "");
static_assert(!std::is_assignable<std::variant<bool>, decltype(nullptr)>::value, "");
diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
index 04329f4f412b06a..89fd646878eeca5 100644
--- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
@@ -80,8 +80,10 @@ void test_T_ctor_sfinae() {
};
static_assert(!std::is_constructible<V, X>::value,
"no boolean conversion in constructor");
+#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
static_assert(std::is_constructible<V, std::false_type>::value,
"converted to bool in constructor");
+#endif
}
{
struct X {};
@@ -200,10 +202,12 @@ void test_construction_with_repeated_types() {
}
void test_vector_bool() {
+#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
std::vector<bool> vec = {true};
std::variant<bool, int> v = vec[0];
assert(v.index() == 0);
assert(std::get<0>(v) == true);
+#endif
}
int main(int, char**) {
diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp
index 7a4c68b5dacca7f..7fb44ff407653ba 100644
--- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp
@@ -33,7 +33,9 @@ int main(int, char**)
static_assert(!std::is_constructible<std::variant<int, bool>, decltype("meow")>::value, "");
static_assert(!std::is_constructible<std::variant<int, const bool>, decltype("meow")>::value, "");
+#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
static_assert(std::is_constructible<std::variant<bool>, std::true_type>::value, "");
+#endif
static_assert(!std::is_constructible<std::variant<bool>, std::unique_ptr<char> >::value, "");
static_assert(!std::is_constructible<std::variant<bool>, decltype(nullptr)>::value, "");
diff --git a/libcxx/test/support/variant_test_helpers.h b/libcxx/test/support/variant_test_helpers.h
index 78b3978dde484bc..c174cba3284019b 100644
--- a/libcxx/test/support/variant_test_helpers.h
+++ b/libcxx/test/support/variant_test_helpers.h
@@ -23,10 +23,11 @@
// FIXME: Currently the variant<T&> tests are disabled using this macro.
#define TEST_VARIANT_HAS_NO_REFERENCES
+
+// TODO(LLVM-19): Remove TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
#ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
# define TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
#endif
-
#ifdef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
constexpr bool VariantAllowsNarrowingConversions = true;
#else
More information about the libcxx-commits
mailing list