[libcxx-commits] [libcxx] 03c2862 - [libc++][ranges] Reject non-class types in ranges::to (#135802)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Apr 24 01:30:02 PDT 2025
Author: Yuzhiy
Date: 2025-04-24T10:29:59+02:00
New Revision: 03c2862404a9ab19940f87f8fb2dbe01818ab439
URL: https://github.com/llvm/llvm-project/commit/03c2862404a9ab19940f87f8fb2dbe01818ab439
DIFF: https://github.com/llvm/llvm-project/commit/03c2862404a9ab19940f87f8fb2dbe01818ab439.diff
LOG: [libc++][ranges] Reject non-class types in ranges::to (#135802)
This patch adds `static_assert` using `is_class_v` and `is_union_v` to
reject no-class type template parameters.
Fixes #132133
---------
Co-authored-by: A. Jiang <de34 at live.cn>
Added:
Modified:
libcxx/include/__ranges/to.h
libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.static_assert.verify.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h
index c937b0656de87..3a2bc42969f7b 100644
--- a/libcxx/include/__ranges/to.h
+++ b/libcxx/include/__ranges/to.h
@@ -26,7 +26,9 @@
#include <__ranges/size.h>
#include <__ranges/transform_view.h>
#include <__type_traits/add_pointer.h>
+#include <__type_traits/is_class.h>
#include <__type_traits/is_const.h>
+#include <__type_traits/is_union.h>
#include <__type_traits/is_volatile.h>
#include <__type_traits/type_identity.h>
#include <__utility/declval.h>
@@ -81,7 +83,7 @@ template <class _Container, input_range _Range, class... _Args>
static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const");
static_assert(
!is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile");
-
+ static_assert(is_class_v<_Container> || is_union_v<_Container>, "The target must be a class type or union type");
// First see if the non-recursive case applies -- the conversion target is either:
// - a range with a convertible value type;
// - a non-range type which might support being created from the input argument(s) (e.g. an `optional`).
@@ -208,7 +210,7 @@ template <class _Container, class... _Args>
static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const");
static_assert(
!is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile");
-
+ static_assert(is_class_v<_Container> || is_union_v<_Container>, "The target must be a class type or union type");
auto __to_func = []<input_range _Range, class... _Tail>(_Range&& __range, _Tail&&... __tail) static
requires requires { //
/**/ ranges::to<_Container>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...);
diff --git a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.static_assert.verify.cpp b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.static_assert.verify.cpp
index c3ab002558a03..0800ee8cf7bae 100644
--- a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.static_assert.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.static_assert.verify.cpp
@@ -14,12 +14,79 @@
#include <ranges>
#include <vector>
-void test() {
+void test_cv_qualifications() {
using R = std::vector<int>;
- R in = {1, 2, 3};
+ R in = {1, 2, 3};
- (void)std::ranges::to<const R>(in); //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be const-qualified, please remove the const}}
- (void)(in | std::ranges::to<const R>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be const-qualified, please remove the const}}
- (void)std::ranges::to<volatile R>(in); //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be volatile-qualified, please remove the volatile}}
- (void)(in | std::ranges::to<volatile R>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be volatile-qualified, please remove the volatile}}
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be const-qualified, please remove the const}}
+ (void)std::ranges::to<const R>(in);
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be const-qualified, please remove the const}}
+ (void)(in | std::ranges::to<const R>());
+
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be volatile-qualified, please remove the volatile}}
+ (void)std::ranges::to<volatile R>(in);
+
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be volatile-qualified, please remove the volatile}}
+ (void)(in | std::ranges::to<volatile R>());
+}
+//unexpected_types
+void ff();
+void test_unexpected_types() {
+ struct C {
+ int member;
+ int f();
+ };
+
+ enum color { red, green, blue };
+ using member_func_ptr = decltype(&C::f);
+ using member_ptr = decltype(&C::member);
+ using func_ptr = decltype(&ff);
+ using func_t = decltype(ff);
+
+ struct R {
+ int* begin() const { return nullptr; };
+ int* end() const { return nullptr; };
+
+ operator int() const;
+ operator int*() const;
+ operator func_ptr() const;
+ operator member_func_ptr() const;
+ operator member_ptr() const;
+ operator color() const;
+ };
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<int>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<int>());
+
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<int*>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<int*>());
+
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<func_ptr>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<func_ptr>());
+
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<member_ptr>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<member_ptr>());
+
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<func_t>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<func_t>());
+
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<void>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type.}}
+ (void)(R{} | std::ranges::to<void>());
+
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<color>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<color>());
}
More information about the libcxx-commits
mailing list