[libcxx-commits] [libcxx] [libc++] Refactor `optional` constructor tests (PR #169203)
William Tran-Viet via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Nov 27 10:36:35 PST 2025
https://github.com/smallp-o-p updated https://github.com/llvm/llvm-project/pull/169203
>From aad59c30ff774e54c6d94dde37ce61bff0baf37a Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sat, 22 Nov 2025 22:22:39 -0500
Subject: [PATCH 01/17] Default
---
.../optional.object.ctor/default.pass.cpp | 82 ++++++++++---------
1 file changed, 45 insertions(+), 37 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
index 71d4d052da3b7..540863b2b19c4 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// constexpr optional() noexcept;
@@ -18,56 +18,64 @@
#include "test_macros.h"
#include "archetypes.h"
-using std::optional;
+template <class T>
+constexpr void test() {
+ static_assert(std::is_nothrow_default_constructible_v<std::optional<T>>);
+ static_assert(std::is_trivially_destructible_v<T> == std::is_trivially_destructible_v<std::optional<T>>);
-template <class Opt>
-void test_constexpr() {
- static_assert(std::is_nothrow_default_constructible<Opt>::value, "");
- static_assert(std::is_trivially_destructible<Opt>::value, "");
- static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, "");
-
- constexpr Opt opt;
- static_assert(static_cast<bool>(opt) == false, "");
-
- struct test_constexpr_ctor : public Opt {
- constexpr test_constexpr_ctor() {}
- };
-}
+ if constexpr (!std::is_lvalue_reference_v<T>) {
+ static_assert(
+ std::is_trivially_destructible_v<T> == std::is_trivially_destructible_v<typename std::optional<T>::value_type>);
+ }
-template <class Opt>
-void test() {
- static_assert(std::is_nothrow_default_constructible<Opt>::value, "");
- static_assert(!std::is_trivially_destructible<Opt>::value, "");
- static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, "");
{
- Opt opt;
+ std::optional<T> opt;
assert(static_cast<bool>(opt) == false);
}
{
- const Opt opt;
+ const std::optional<T> opt;
assert(static_cast<bool>(opt) == false);
}
- struct test_constexpr_ctor : public Opt {
+ struct test_constexpr_ctor : public std::optional<T> {
constexpr test_constexpr_ctor() {}
};
}
-int main(int, char**) {
- test_constexpr<optional<int>>();
- test_constexpr<optional<int*>>();
- test_constexpr<optional<ImplicitTypes::NoCtors>>();
- test_constexpr<optional<NonTrivialTypes::NoCtors>>();
- test_constexpr<optional<NonConstexprTypes::NoCtors>>();
- test<optional<NonLiteralTypes::NoCtors>>();
- // EXTENSIONS
-#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
- test_constexpr<optional<int&>>();
- test_constexpr<optional<const int&>>();
- test_constexpr<optional<int&>>();
- test_constexpr<optional<NonLiteralTypes::NoCtors&>>();
- test_constexpr<optional<NonLiteralTypes::NoCtors&&>>();
+TEST_CONSTEXPR_CXX23 void non_literal_test() {
+ test<NonLiteralTypes::NoCtors>();
+ test<NonLiteralTypes::NoCtors>();
+}
+
+constexpr bool test() {
+ test<int>();
+ test<int*>();
+ test<ImplicitTypes::NoCtors>();
+ test<NonTrivialTypes::NoCtors>();
+ test<NonConstexprTypes::NoCtors>();
+#if TEST_STD_VER >= 23
+ non_literal_test();
+#endif
+#if TEST_STD_VER >= 26
+ test<int&>();
+ test<const int&>();
+ test<int&>();
+ test<NonLiteralTypes::NoCtors&>();
+// TODO: optional<T&&> is not allowed.
+# if 0
+ test<NonLiteralTypes::NoCtors&&>();
+# endif
#endif
+ return true;
+}
+
+int main(int, char**) {
+ assert(test());
+ static_assert(test());
+
+ {
+ non_literal_test();
+ }
return 0;
}
>From fc5d81154c79218f34c9c082413f9344af185c89 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sat, 22 Nov 2025 23:11:39 -0500
Subject: [PATCH 02/17] optional<U> and friends
---
.../const_optional_U.pass.cpp | 33 ++++++++++++----
.../explicit_const_optional_U.pass.cpp | 39 +++++++++++++------
.../explicit_optional_U.pass.cpp | 35 ++++++++++++-----
3 files changed, 78 insertions(+), 29 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
index 70fd76ec6ed0b..ab424a6509183 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class U>
@@ -68,7 +68,7 @@ class Z {
int i_;
public:
- Z(int i) : i_(i) { TEST_THROW(6); }
+ constexpr Z(int i) : i_(i) { TEST_THROW(6); }
friend bool operator==(const Z& x, const Z& y) { return x.i_ == y.i_; }
};
@@ -86,15 +86,20 @@ constexpr bool test_all() {
return true;
}
-int main(int, char**) {
+constexpr bool test() {
test_all<int, short>();
test_all<X, int>();
test_all<Y, int>();
-#if TEST_STD_VER > 17
- static_assert(test_all<int, short>());
- static_assert(test_all<X, int>());
- static_assert(test_all<Y, int>());
+
+// TODO: Enable once P3068R6 is implemented
+#if TEST_STD_VER >= 26 && 0
+ test_throwing();
#endif
+
+ return true;
+}
+
+TEST_CONSTEXPR_CXX26 bool test_throwing() {
{
typedef Z T;
typedef int U;
@@ -108,7 +113,19 @@ int main(int, char**) {
test<T>(rhs, true);
}
- static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value), "");
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 20
+ static_assert(test());
+#endif
+
+ {
+ test_throwing();
+ }
+ static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value));
return 0;
}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
index 1b9882fb25633..fa9a96c39b8fa 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRED: std-at-least-c++17
// <optional>
// template <class U>
@@ -22,7 +22,7 @@ using std::optional;
template <class T, class U>
TEST_CONSTEXPR_CXX20 void test(const optional<U>& rhs, bool is_going_to_throw = false) {
- static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value), "");
+ static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value));
bool rhs_engaged = static_cast<bool>(rhs);
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
@@ -69,9 +69,9 @@ class Z {
int i_;
public:
- explicit Z(int i) : i_(i) { TEST_THROW(6); }
+ constexpr explicit Z(int i) : i_(i) { TEST_THROW(6); }
- friend bool operator==(const Z& x, const Z& y) { return x.i_ == y.i_; }
+ friend constexpr bool operator==(const Z& x, const Z& y) { return x.i_ == y.i_; }
};
template <class T, class U>
@@ -87,13 +87,7 @@ constexpr bool test_all() {
return true;
}
-int main(int, char**) {
- test_all<X, int>();
- test_all<Y, int>();
-#if TEST_STD_VER > 17
- static_assert(test_all<X, int>());
- static_assert(test_all<Y, int>());
-#endif
+TEST_CONSTEXPR_CXX26 bool test_throwing() {
{
typedef Z T;
typedef int U;
@@ -107,5 +101,28 @@ int main(int, char**) {
test<T>(rhs, true);
}
+ return true;
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ test_all<X, int>();
+ test_all<Y, int>();
+
+// TODO: Enable once P3068R6 is implemented
+#if TEST_STD_VER >= 26 && 0
+ test_throwing();
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 20
+ static_assert(test());
+#endif
+ {
+ test_throwing();
+ }
return 0;
}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
index bddbd4ba93d5a..f89ba1319a9ed 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class U>
@@ -22,7 +22,7 @@ using std::optional;
template <class T, class U>
TEST_CONSTEXPR_CXX20 void test(optional<U>&& rhs, bool is_going_to_throw = false) {
- static_assert(!(std::is_convertible<optional<U>&&, optional<T>>::value), "");
+ static_assert(!(std::is_convertible<optional<U>&&, optional<T>>::value));
bool rhs_engaged = static_cast<bool>(rhs);
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
@@ -57,6 +57,19 @@ class Z {
explicit Z(int) { TEST_THROW(6); }
};
+TEST_CONSTEXPR_CXX26 bool test_throwing() {
+ {
+ optional<int> rhs;
+ test<Z>(std::move(rhs));
+ }
+ {
+ optional<int> rhs(3);
+ test<Z>(std::move(rhs), true);
+ }
+
+ return true;
+}
+
TEST_CONSTEXPR_CXX20 bool test() {
{
optional<int> rhs;
@@ -67,21 +80,23 @@ TEST_CONSTEXPR_CXX20 bool test() {
test<X>(std::move(rhs));
}
+ {
+// TODO: Enable once P3068R6 is implemented
+#if TEST_STD_VER >= 26 && 0
+ test_throwing();
+#endif
+ }
+
return true;
}
int main(int, char**) {
-#if TEST_STD_VER > 17
+ test();
+#if TEST_STD_VER >= 20
static_assert(test());
#endif
- test();
{
- optional<int> rhs;
- test<Z>(std::move(rhs));
- }
- {
- optional<int> rhs(3);
- test<Z>(std::move(rhs), true);
+ test_throwing();
}
return 0;
>From d4eaafc80925a7d67385939eb110065fddf119bf Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sat, 22 Nov 2025 23:21:48 -0500
Subject: [PATCH 03/17] nullopt_t
---
.../optional.object.ctor/nullopt_t.pass.cpp | 77 ++++++++++---------
1 file changed, 42 insertions(+), 35 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
index c1bdd81e5ed47..9e06b9b609a0a 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// constexpr optional(nullopt_t) noexcept;
@@ -19,49 +19,56 @@
#include "test_macros.h"
-using std::nullopt;
-using std::nullopt_t;
-using std::optional;
+template <class T>
+constexpr void test() {
+ static_assert(std::is_nothrow_constructible_v<std::optional<T>, std::nullopt_t&>);
+ static_assert(std::is_trivially_destructible_v<T> == std::is_trivially_destructible_v<std::optional<T>>);
+ static_assert(
+ std::is_trivially_destructible_v<T> == std::is_trivially_destructible_v<typename std::optional<T>::value_type>);
-template <class Opt>
-void test_constexpr() {
- static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, "");
- static_assert(std::is_trivially_destructible<Opt>::value, "");
- static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, "");
+ constexpr std::optional<T> opt(std::nullopt);
+ assert(!static_cast<bool>(opt));
- constexpr Opt opt(nullopt);
- static_assert(static_cast<bool>(opt) == false, "");
-
- struct test_constexpr_ctor : public Opt {
+ struct test_constexpr_ctor : public std::optional<T> {
constexpr test_constexpr_ctor() {}
};
}
-template <class Opt>
-void test() {
- static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, "");
- static_assert(!std::is_trivially_destructible<Opt>::value, "");
- static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, "");
- {
- Opt opt(nullopt);
- assert(static_cast<bool>(opt) == false);
- }
- {
- const Opt opt(nullopt);
- assert(static_cast<bool>(opt) == false);
- }
- struct test_constexpr_ctor : public Opt {
- constexpr test_constexpr_ctor() {}
- };
+template <class T>
+TEST_CONSTEXPR_CXX23 void rt_test() {
+ static_assert(std::is_nothrow_constructible_v<std::optional<T>, std::nullopt_t&>);
+ static_assert(std::is_trivially_destructible_v<T> == std::is_trivially_destructible_v<std::optional<T>>);
+ static_assert(
+ std::is_trivially_destructible_v<T> == std::is_trivially_destructible_v<typename std::optional<T>::value_type>);
+
+ const std::optional<T> opt(std::nullopt);
+ assert(!static_cast<bool>(opt));
+}
+
+TEST_CONSTEXPR_CXX23 bool test_non_literal() {
+ rt_test<NonLiteralTypes::NoCtors>();
+ return true;
+}
+
+constexpr bool test() {
+ test<int>();
+ test<int*>();
+ test<ImplicitTypes::NoCtors>();
+ test<NonTrivialTypes::NoCtors>();
+ test<NonConstexprTypes::NoCtors>();
+#if TEST_STD_VER >= 23
+ test_non_literal();
+#endif
+ return true;
}
int main(int, char**) {
- test_constexpr<optional<int>>();
- test_constexpr<optional<int*>>();
- test_constexpr<optional<ImplicitTypes::NoCtors>>();
- test_constexpr<optional<NonTrivialTypes::NoCtors>>();
- test_constexpr<optional<NonConstexprTypes::NoCtors>>();
- test<optional<NonLiteralTypes::NoCtors>>();
+ assert(test());
+ static_assert(test());
+
+ {
+ test_non_literal();
+ }
return 0;
}
>From 5edaf25ba8bf9c95803f44012d62e431cac13757 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sat, 22 Nov 2025 23:49:47 -0500
Subject: [PATCH 04/17] Copy
---
.../optional.object.ctor/copy.pass.cpp | 129 ++++++++++--------
1 file changed, 74 insertions(+), 55 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
index f61a22c23a04d..bd4741154e6d8 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// constexpr optional(const optional<T>& rhs);
@@ -21,24 +21,18 @@
using std::optional;
template <class T, class... InitArgs>
-void test(InitArgs&&... args) {
- const optional<T> rhs(std::forward<InitArgs>(args)...);
- bool rhs_engaged = static_cast<bool>(rhs);
- optional<T> lhs = rhs;
- assert(static_cast<bool>(lhs) == rhs_engaged);
- if (rhs_engaged)
- assert(*lhs == *rhs);
-}
+constexpr bool test(InitArgs&&... args) {
+ static_assert(std::is_trivially_copy_constructible_v<T> ==
+ std::is_trivially_copy_constructible_v<std::optional<T>>); // requirement
+ const optional<T> lhs(std::forward<InitArgs>(args)...);
+ optional<T> rhs(lhs);
+ assert(lhs.has_value() == rhs.has_value());
+ assert(lhs.has_value() ? *lhs == *rhs : true);
-template <class T, class... InitArgs>
-constexpr bool constexpr_test(InitArgs&&... args) {
- static_assert(std::is_trivially_copy_constructible_v<T>, ""); // requirement
- const optional<T> rhs(std::forward<InitArgs>(args)...);
- optional<T> lhs = rhs;
- return (lhs.has_value() == rhs.has_value()) && (lhs.has_value() ? *lhs == *rhs : true);
+ return true;
}
-void test_throwing_ctor() {
+TEST_CONSTEXPR_CXX26 bool test_throwing_ctor() {
#ifndef TEST_HAS_NO_EXCEPTIONS
struct Z {
Z() : count(0) {}
@@ -57,6 +51,8 @@ void test_throwing_ctor() {
assert(i == 6);
}
#endif
+
+ return true;
}
template <class T, class... InitArgs>
@@ -69,8 +65,9 @@ void test_ref(InitArgs&&... args) {
assert(&(*lhs) == &(*rhs));
}
+// TODO: Add constexpr tests
void test_reference_extension() {
-#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
+#if TEST_STD_VER >= 26
using T = TestTypes::TestType;
T::reset();
{
@@ -99,24 +96,73 @@ void test_reference_extension() {
}
assert(T::alive == 0);
assert(T::destroyed == 1);
+
+# if 0 // FIXME: optional<T&&> is not allowed.
{
- static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
- static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
+ static_assert(!std::is_copy_constructible<std::optional<T&&>>::value);
+ static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value);
}
+# endif
#endif
}
-int main(int, char**) {
+constexpr bool test() {
test<int>();
test<int>(3);
- static_assert(constexpr_test<int>(), "");
- static_assert(constexpr_test<int>(3), "");
+ test<const int>(42);
+
+ // FIXME: Why is this in ctor copy.pass.cpp?
+ {
+ constexpr std::optional<int> o1{4};
+ constexpr std::optional<int> o2 = o1;
+ static_assert(*o2 == 4, "");
+ }
+
+ {
+ // LWG3836 https://wg21.link/LWG3836
+ // std::optional<bool> conversion constructor optional(const optional<U>&)
+ // should take precedence over optional(U&&) with operator bool
+ {
+ std::optional<bool> o1(false);
+ std::optional<bool> o2(o1);
+ assert(!o2.value());
+ }
+ }
+
+ {
+ using T = TrivialTestTypes::TestType;
+ test<T>();
+ test<T>(42);
+ }
+
+ // TODO: Enable once P3068R6 is implemented
+#if TEST_STD_VER >= 26 && 0
+ test_throwing_ctor();
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
{
- const optional<const int> o(42);
- optional<const int> o2(o);
- assert(*o2 == 42);
+ test_throwing_ctor();
}
+
+#if TEST_STD_VER >= 26
+ {
+ test_reference_extension();
+ }
+#endif
+
+ { // FIXME: Shouldn't this be able to pass in a constexpr context since C++17?
+ using T = ConstexprTestTypes::TestType;
+ test<T>();
+ test<T>(42);
+ }
+
{
using T = TestTypes::TestType;
T::reset();
@@ -126,7 +172,9 @@ int main(int, char**) {
assert(lhs.has_value() == false);
assert(T::alive == 0);
}
+
TestTypes::TestType::reset();
+
{
using T = TestTypes::TestType;
T::reset();
@@ -139,37 +187,8 @@ int main(int, char**) {
assert(T::copy_constructed == 1);
assert(T::alive == 2);
}
- TestTypes::TestType::reset();
- {
- using namespace ConstexprTestTypes;
- test<TestType>();
- test<TestType>(42);
- }
- {
- using namespace TrivialTestTypes;
- test<TestType>();
- test<TestType>(42);
- }
- {
- test_throwing_ctor();
- }
- {
- test_reference_extension();
- }
- {
- constexpr std::optional<int> o1{4};
- constexpr std::optional<int> o2 = o1;
- static_assert(*o2 == 4, "");
- }
- // LWG3836 https://wg21.link/LWG3836
- // std::optional<bool> conversion constructor optional(const optional<U>&)
- // should take precedence over optional(U&&) with operator bool
- {
- std::optional<bool> o1(false);
- std::optional<bool> o2(o1);
- assert(!o2.value());
- }
+ TestTypes::TestType::reset();
return 0;
}
>From e3e454eb14952114686677bc3fecdb84dde92919 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 00:23:17 -0500
Subject: [PATCH 05/17] Move
---
.../optional.object.ctor/move.pass.cpp | 83 +++++++++++--------
1 file changed, 48 insertions(+), 35 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
index 583debcaac650..ba37fad3f1e2c 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
@@ -22,26 +22,20 @@
using std::optional;
template <class T, class... InitArgs>
-void test(InitArgs&&... args) {
+constexpr bool test(InitArgs&&... args) {
+ static_assert(std::is_trivially_move_constructible_v<T> == std::is_trivially_move_constructible_v<std::optional<T>>);
const optional<T> orig(std::forward<InitArgs>(args)...);
- optional<T> rhs(orig);
- bool rhs_engaged = static_cast<bool>(rhs);
- optional<T> lhs = std::move(rhs);
- assert(static_cast<bool>(lhs) == rhs_engaged);
- if (rhs_engaged)
- assert(*lhs == *orig);
-}
-template <class T, class... InitArgs>
-constexpr bool constexpr_test(InitArgs&&... args) {
- static_assert(std::is_trivially_copy_constructible_v<T>, ""); // requirement
- const optional<T> orig(std::forward<InitArgs>(args)...);
- optional<T> rhs(orig);
- optional<T> lhs = std::move(rhs);
- return (lhs.has_value() == orig.has_value()) && (lhs.has_value() ? *lhs == *orig : true);
+ optional<T> lhs(orig);
+ optional<T> rhs(std::move(lhs));
+
+ assert(lhs.has_value() == rhs.has_value());
+ assert(lhs.has_value() ? *rhs == *orig : true);
+
+ return true;
}
-void test_throwing_ctor() {
+TEST_CONSTEXPR_CXX26 void test_throwing_ctor() {
#ifndef TEST_HAS_NO_EXCEPTIONS
struct Z {
Z() : count(0) {}
@@ -72,6 +66,7 @@ void test_ref(InitArgs&&... args) {
assert(&(*lhs) == &(*rhs));
}
+// TODO: Add constexpr tests
void test_reference_extension() {
#if TEST_STD_VER >= 26
using T = TestTypes::TestType;
@@ -137,17 +132,27 @@ void test_reference_extension() {
#endif
}
-int main(int, char**) {
+constexpr bool test() {
test<int>();
test<int>(3);
- static_assert(constexpr_test<int>(), "");
- static_assert(constexpr_test<int>(3), "");
+ test<const int>(42);
+
+ {
+ using T = TrivialTestTypes::TestType;
+ test<T>();
+ test<T>(42);
+ }
+#if TEST_STD_VER >= 26 && 0
{
- optional<const int> o(42);
- optional<const int> o2(std::move(o));
- assert(*o2 == 42);
+ test_throwing_ctor();
}
+#endif
+
+ return true;
+}
+
+bool rt_test() {
{
using T = TestTypes::TestType;
T::reset();
@@ -158,7 +163,9 @@ int main(int, char**) {
assert(rhs.has_value() == false);
assert(T::alive == 0);
}
+
TestTypes::TestType::reset();
+
{
using T = TestTypes::TestType;
T::reset();
@@ -174,20 +181,15 @@ int main(int, char**) {
assert(T::move_constructed == 1);
assert(T::alive == 2);
}
+
TestTypes::TestType::reset();
- {
+
+ { // TODO: Why doesn't this pass in a C++17 constexpr context?
using namespace ConstexprTestTypes;
test<TestType>();
test<TestType>(42);
}
- {
- using namespace TrivialTestTypes;
- test<TestType>();
- test<TestType>(42);
- }
- {
- test_throwing_ctor();
- }
+
{
struct ThrowsMove {
ThrowsMove() noexcept(false) {}
@@ -202,13 +204,24 @@ int main(int, char**) {
};
static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, "");
}
+
+ return true;
+}
+
+int main(int, char**) {
+ assert(test());
+ static_assert(test());
+
{
- test_reference_extension();
+ rt_test();
+ }
+
+ {
+ test_throwing_ctor();
}
+
{
- constexpr std::optional<int> o1{4};
- constexpr std::optional<int> o2 = std::move(o1);
- static_assert(*o2 == 4, "");
+ test_reference_extension();
}
return 0;
>From c8ee1c4e0d8ac04fd9de9fabe21e943bba9ae14d Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 00:33:49 -0500
Subject: [PATCH 06/17] const_T
---
.../optional.object.ctor/const_T.pass.cpp | 74 +++++++------------
1 file changed, 28 insertions(+), 46 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
index 67d0fcfc18b86..61cfc056dadd6 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
@@ -20,35 +20,38 @@
#include "archetypes.h"
using std::optional;
+template <typename T, typename... Args>
+constexpr void test_ctor(Args... args) {
+ const T t(args...);
+ const std::optional<T> opt(t);
-int main(int, char**) {
- {
- typedef int T;
- constexpr T t(5);
- constexpr optional<T> opt(t);
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(*opt == 5, "");
+ assert(static_cast<bool>(opt));
+ assert(*opt == t);
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(const T&) {}
- };
- }
- {
- typedef double T;
- constexpr T t(3);
- constexpr optional<T> opt(t);
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(*opt == 3, "");
+ struct test_constexpr_ctor : public optional<T> {
+ constexpr test_constexpr_ctor(const T&) {}
+ };
+}
+
+constexpr bool test() {
+ test_ctor<int>(5);
+ test_ctor<double>(3.0);
+ test_ctor<const int>(42);
+ test_ctor<ConstexprTestTypes::TestType>(3);
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(const T&) {}
- };
- }
{
- const int x = 42;
- optional<const int> o(x);
- assert(*o == x);
+ using T = ExplicitConstexprTestTypes::TestType;
+ static_assert(!std::is_convertible_v<const T&, optional<T>>);
+ test_ctor<T>(3);
}
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
{
typedef TestTypes::TestType T;
T::reset();
@@ -59,6 +62,7 @@ int main(int, char**) {
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
+
{
typedef ExplicitTestTypes::TestType T;
static_assert(!std::is_convertible<T const&, optional<T>>::value, "");
@@ -70,29 +74,7 @@ int main(int, char**) {
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
- {
- typedef ConstexprTestTypes::TestType T;
- constexpr T t(3);
- constexpr optional<T> opt = {t};
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(opt.value().value == 3, "");
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(const T&) {}
- };
- }
- {
- typedef ExplicitConstexprTestTypes::TestType T;
- static_assert(!std::is_convertible<const T&, optional<T>>::value, "");
- constexpr T t(3);
- constexpr optional<T> opt(t);
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(opt.value().value == 3, "");
-
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(const T&) {}
- };
- }
#ifndef TEST_HAS_NO_EXCEPTIONS
{
struct Z {
>From 0b8f6ee78b2382869798413d86edb4c1c35a8626 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 00:43:59 -0500
Subject: [PATCH 07/17] optional_U
---
.../optional.object.ctor/optional_U.pass.cpp | 29 ++++++++++++++-----
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
index 709b106c800a6..ff315de570a4d 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
@@ -68,13 +68,7 @@ TEST_CONSTEXPR_CXX20 bool test_all() {
return true;
}
-int main(int, char**) {
- test_all<short, int>();
- test_all<int, X>();
-#if TEST_STD_VER > 17
- static_assert(test_all<short, int>());
- static_assert(test_all<int, X>());
-#endif
+TEST_CONSTEXPR_CXX26 void test_throw() {
{
optional<int> rhs;
test<Z>(std::move(rhs));
@@ -85,6 +79,27 @@ int main(int, char**) {
}
static_assert(!(std::is_constructible<optional<X>, optional<Z>>::value), "");
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ test_all<short, int>();
+ test_all<int, X>();
+
+#if TEST_STD_VER >= 26 && 0
+ test_throw();
+#endif
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 20
+ static_assert(test());
+#endif
+
+ {
+ test_throw();
+ }
return 0;
}
>From b626e1d8a80acf3c40e5b23ece6730b39031723c Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 00:58:27 -0500
Subject: [PATCH 08/17] Deduct
---
.../optional.object.ctor/deduct.pass.cpp | 53 ++++++++++---------
1 file changed, 28 insertions(+), 25 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp
index bc1d26aa8bd18..1d7707a6d3f05 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp
@@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
+// REQUIRES: std-at-least-c++17
+
// <optional>
-// UNSUPPORTED: c++03, c++11, c++14
// template<class T>
// optional(T) -> optional<T>;
@@ -17,47 +18,41 @@
#include "test_macros.h"
-struct A {};
+struct A {
+ friend constexpr bool operator==(const A&, const A&) { return true; }
+};
-int main(int, char**) {
- // Test the explicit deduction guides
- {
- // optional(T)
- std::optional opt(5);
- ASSERT_SAME_TYPE(decltype(opt), std::optional<int>);
- assert(static_cast<bool>(opt));
- assert(*opt == 5);
- }
+template <typename T>
+constexpr void test_deduct(T arg) {
+ std::optional opt(arg);
- {
- // optional(T)
- std::optional opt(A{});
- ASSERT_SAME_TYPE(decltype(opt), std::optional<A>);
- assert(static_cast<bool>(opt));
- }
+ ASSERT_SAME_TYPE(decltype(opt), std::optional<T>);
+ assert(static_cast<bool>(opt));
+ assert(*opt == arg);
+}
+
+constexpr bool test() {
+ // optional(T)
+ test_deduct<int>(5);
+ test_deduct<A>(A{});
{
// optional(const T&);
const int& source = 5;
- std::optional opt(source);
- ASSERT_SAME_TYPE(decltype(opt), std::optional<int>);
- assert(static_cast<bool>(opt));
- assert(*opt == 5);
+ test_deduct<int>(source);
}
{
// optional(T*);
const int* source = nullptr;
- std::optional opt(source);
- ASSERT_SAME_TYPE(decltype(opt), std::optional<const int*>);
- assert(static_cast<bool>(opt));
- assert(*opt == nullptr);
+ test_deduct<const int*>(source);
}
{
// optional(T[]);
int source[] = {1, 2, 3};
std::optional opt(source);
+
ASSERT_SAME_TYPE(decltype(opt), std::optional<int*>);
assert(static_cast<bool>(opt));
assert((*opt)[0] == 1);
@@ -68,10 +63,18 @@ int main(int, char**) {
// optional(optional);
std::optional<char> source('A');
std::optional opt(source);
+
ASSERT_SAME_TYPE(decltype(opt), std::optional<char>);
assert(static_cast<bool>(opt) == static_cast<bool>(source));
assert(*opt == *source);
}
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
return 0;
}
>From cee7738080504e4f7ec5582ae9b0652c84fbe52e Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 01:23:35 -0500
Subject: [PATCH 09/17] in_place_t
---
.../optional.object.ctor/in_place_t.pass.cpp | 109 ++++++------------
1 file changed, 37 insertions(+), 72 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
index 902754418fbde..ae3d76eff4a42 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRED: std-at-least-c++17
// <optional>
@@ -16,6 +16,7 @@
#include <cassert>
#include <optional>
#include <type_traits>
+#include <utility>
#include "test_macros.h"
@@ -28,25 +29,13 @@ class X {
int j_ = 0;
public:
- X() : i_(0) {}
- X(int i) : i_(i) {}
- X(int i, int j) : i_(i), j_(j) {}
+ constexpr X() : i_(0) {}
+ constexpr X(int i) : i_(i) {}
+ constexpr X(int i, int j) : i_(i), j_(j) {}
- ~X() {}
+ ~X() = default;
- friend bool operator==(const X& x, const X& y) { return x.i_ == y.i_ && x.j_ == y.j_; }
-};
-
-class Y {
- int i_;
- int j_ = 0;
-
-public:
- constexpr Y() : i_(0) {}
- constexpr Y(int i) : i_(i) {}
- constexpr Y(int i, int j) : i_(i), j_(j) {}
-
- friend constexpr bool operator==(const Y& x, const Y& y) { return x.i_ == y.i_ && x.j_ == y.j_; }
+ friend constexpr bool operator==(const X& x, const X& y) { return x.i_ == y.i_ && x.j_ == y.j_; }
};
class Z {
@@ -54,62 +43,18 @@ class Z {
Z(int) { TEST_THROW(6); }
};
-int main(int, char**) {
- {
- constexpr optional<int> opt(in_place, 5);
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(*opt == 5, "");
+template <typename T, typename... Args>
+constexpr void test_inplace(Args... args) {
+ optional<T> opt(in_place, args...);
+ assert(bool(opt));
+ assert(*opt == T(args...));
- struct test_constexpr_ctor : public optional<int> {
- constexpr test_constexpr_ctor(in_place_t, int i) : optional<int>(in_place, i) {}
- };
- }
- {
- optional<const int> opt(in_place, 5);
- assert(*opt == 5);
- }
- {
- const optional<X> opt(in_place);
- assert(static_cast<bool>(opt) == true);
- assert(*opt == X());
- }
- {
- const optional<X> opt(in_place, 5);
- assert(static_cast<bool>(opt) == true);
- assert(*opt == X(5));
- }
- {
- const optional<X> opt(in_place, 5, 4);
- assert(static_cast<bool>(opt) == true);
- assert(*opt == X(5, 4));
- }
- {
- constexpr optional<Y> opt(in_place);
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(*opt == Y(), "");
-
- struct test_constexpr_ctor : public optional<Y> {
- constexpr test_constexpr_ctor(in_place_t) : optional<Y>(in_place) {}
- };
- }
- {
- constexpr optional<Y> opt(in_place, 5);
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(*opt == Y(5), "");
-
- struct test_constexpr_ctor : public optional<Y> {
- constexpr test_constexpr_ctor(in_place_t, int i) : optional<Y>(in_place, i) {}
- };
- }
- {
- constexpr optional<Y> opt(in_place, 5, 4);
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(*opt == Y(5, 4), "");
+ struct test_constexpr_ctor : public optional<int> {
+ constexpr test_constexpr_ctor(in_place_t, int i) : optional<int>(in_place, i) {}
+ };
+}
- struct test_constexpr_ctor : public optional<Y> {
- constexpr test_constexpr_ctor(in_place_t, int i, int j) : optional<Y>(in_place, i, j) {}
- };
- }
+TEST_CONSTEXPR_CXX26 void test_throwing() {
#ifndef TEST_HAS_NO_EXCEPTIONS
{
try {
@@ -120,6 +65,26 @@ int main(int, char**) {
}
}
#endif
+}
+
+constexpr bool test() {
+ test_inplace<int>(5);
+ test_inplace<const int>(5);
+ test_inplace<X>();
+ test_inplace<X>(5);
+ test_inplace<X>(5, 4);
+#if TEST_STD_VER >= 26 && 0
+ test_throwing();
+#endif
+ return true;
+}
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ {
+ test_throwing();
+ }
return 0;
}
>From 5f575023551d7d2bcdb86f7ddb190e81208d7889 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 01:59:54 -0500
Subject: [PATCH 10/17] rvalue_T
---
.../optional.object.ctor/rvalue_T.pass.cpp | 114 ++++++++++--------
1 file changed, 62 insertions(+), 52 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
index e73eef4592256..05af88af13916 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
@@ -27,32 +27,27 @@ class Z {
Z(Z&&) { TEST_THROW(6); }
};
-int main(int, char**) {
- {
- typedef int T;
- constexpr optional<T> opt(T(5));
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(*opt == 5, "");
-
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(T&&) {}
- };
- }
+template <typename T, typename U>
+constexpr void test_rvalueT(U arg) {
{
- typedef double T;
- constexpr optional<T> opt(T(3));
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(*opt == 3, "");
-
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(T&&) {}
- };
+ const optional<T> opt(arg);
+ assert(bool(opt));
+ assert(*opt == T(arg));
}
+
{
- const int x = 42;
- optional<const int> o(std::move(x));
- assert(*o == 42);
+ T t(arg);
+ optional<T> opt(std::move(t));
+ assert(*opt == T(arg));
}
+
+ struct test_constexpr_ctor : public optional<T> {
+ constexpr test_constexpr_ctor(T&&) {}
+ constexpr test_constexpr_ctor(const T&) {}
+ };
+}
+
+void test_rt() {
{
typedef TestTypes::TestType T;
T::reset();
@@ -83,37 +78,9 @@ int main(int, char**) {
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
- {
- typedef ConstexprTestTypes::TestType T;
- constexpr optional<T> opt = {T(3)};
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(opt.value().value == 3, "");
-
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(const T&) {}
- };
- }
- {
- typedef ConstexprTestTypes::TestType T;
- constexpr optional<T> opt = {3};
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(opt.value().value == 3, "");
-
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(const T&) {}
- };
- }
- {
- typedef ExplicitConstexprTestTypes::TestType T;
- static_assert(!std::is_convertible<T&&, optional<T>>::value, "");
- constexpr optional<T> opt(T{3});
- static_assert(static_cast<bool>(opt) == true, "");
- static_assert(opt.value().value == 3, "");
+}
- struct test_constexpr_ctor : public optional<T> {
- constexpr test_constexpr_ctor(T&&) {}
- };
- }
+TEST_CONSTEXPR_CXX26 void test_throwing() {
#ifndef TEST_HAS_NO_EXCEPTIONS
{
try {
@@ -125,6 +92,49 @@ int main(int, char**) {
}
}
#endif
+}
+
+constexpr bool test() {
+ test_rvalueT<int>(5);
+ test_rvalueT<double>(3.0);
+ test_rvalueT<const int>(42);
+
+ {
+ using T = ConstexprTestTypes::TestType;
+ test_rvalueT<T>(T(3));
+ }
+
+ {
+ using T = ConstexprTestTypes::TestType;
+ test_rvalueT<T>(3);
+ }
+
+ {
+ using T = ExplicitConstexprTestTypes::TestType;
+ static_assert(!std::is_convertible<T&&, optional<T>>::value);
+ test_rvalueT<T>(T(3));
+ }
+#if TEST_STD_VER >= 26 && 0
+ {
+ test_throwing();
+ }
+
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ {
+ test_rt();
+ }
+
+ {
+ test_throwing();
+ }
return 0;
}
>From ade226065d355f5214e33e0de36a5172652c58ec Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 02:05:46 -0500
Subject: [PATCH 11/17] Format U.pass
---
.../optional.object/optional.object.ctor/U.pass.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
index 1e951ebdf1d74..d09e5a2ef5466 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
@@ -5,19 +5,18 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: c++03, c++11, c++14
+
+// REQUIRED: std-at-least-c++17
// <optional>
// template <class U>
-// constexpr EXPLICIT optional(U&& u);
+// constexpr explicit optional(U&& u);
#include <cassert>
#include <optional>
#include <type_traits>
-#include "test_macros.h"
#include "archetypes.h"
#include "test_convertible.h"
>From 04066ceccd98288e85077f214f1e83661fe23ded Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 02:19:27 -0500
Subject: [PATCH 12/17] U.pass
---
.../optional.object.ctor/U.pass.cpp | 151 +++++++++++-------
1 file changed, 95 insertions(+), 56 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
index d09e5a2ef5466..965085846bc4c 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
@@ -44,80 +44,47 @@ struct ImplicitAny {
template <class To, class From>
constexpr bool implicit_conversion(optional<To>&& opt, const From& v) {
using O = optional<To>;
- static_assert(test_convertible<O, From>(), "");
- static_assert(!test_convertible<O, void*>(), "");
- static_assert(!test_convertible<O, From, int>(), "");
- return opt && *opt == static_cast<To>(v);
+ assert((test_convertible<O, From>()));
+ assert(!(test_convertible<O, void*>()));
+ assert(!(test_convertible<O, From, int>()));
+ assert(opt);
+ assert(*opt == static_cast<To>(v));
+
+ return true;
}
template <class To, class Input, class Expect>
constexpr bool explicit_conversion(Input&& in, const Expect& v) {
using O = optional<To>;
- static_assert(std::is_constructible<O, Input>::value, "");
- static_assert(!std::is_convertible<Input, O>::value, "");
- static_assert(!std::is_constructible<O, void*>::value, "");
- static_assert(!std::is_constructible<O, Input, int>::value, "");
+ assert((std::is_constructible<O, Input>::value));
+ assert(!(std::is_convertible<Input, O>::value));
+ assert(!(std::is_constructible<O, void*>::value));
+ assert(!(std::is_constructible<O, Input, int>::value));
+
optional<To> opt(std::forward<Input>(in));
optional<To> opt2{std::forward<Input>(in)};
- return opt && *opt == static_cast<To>(v) && (opt2 && *opt2 == static_cast<To>(v));
+ assert(opt);
+ assert(opt2);
+ assert(*opt == static_cast<To>(v));
+ assert(*opt2 == static_cast<To>(v));
+
+ return true;
}
void test_implicit() {
- {
- static_assert(implicit_conversion<long long>(42, 42), "");
- }
- {
- static_assert(implicit_conversion<long double>(3.14, 3.14), "");
- }
- {
- int x = 42;
- optional<void* const> o(&x);
- assert(*o == &x);
- }
- {
- using T = TrivialTestTypes::TestType;
- static_assert(implicit_conversion<T>(42, 42), "");
- }
- {
- using T = TestTypes::TestType;
- assert(implicit_conversion<T>(3, T(3)));
- }
{
using T = TestTypes::TestType;
optional<T> opt({3});
assert(opt && *opt == static_cast<T>(3));
}
+
{
- using O = optional<ImplicitAny>;
- static_assert(!test_convertible<O, std::in_place_t>(), "");
- static_assert(!test_convertible<O, std::in_place_t&>(), "");
- static_assert(!test_convertible<O, const std::in_place_t&>(), "");
- static_assert(!test_convertible<O, std::in_place_t&&>(), "");
- static_assert(!test_convertible<O, const std::in_place_t&&>(), "");
- }
-#ifndef TEST_HAS_NO_EXCEPTIONS
- {
- try {
- using T = ImplicitThrow;
- optional<T> t = 42;
- assert(false);
- ((void)t);
- } catch (int) {
- }
+ using T = TestTypes::TestType;
+ assert((implicit_conversion<T>(3, T(3))));
}
-#endif
}
void test_explicit() {
- {
- using T = ExplicitTrivialTestTypes::TestType;
- static_assert(explicit_conversion<T>(42, 42), "");
- }
- {
- using T = ExplicitConstexprTestTypes::TestType;
- static_assert(explicit_conversion<T>(42, 42), "");
- static_assert(!std::is_convertible<int, T>::value, "");
- }
{
using T = ExplicitTestTypes::TestType;
T::reset();
@@ -136,7 +103,20 @@ void test_explicit() {
}
assert(T::alive == 0);
}
+}
+
+TEST_CONSTEXPR_CXX26 void test_throwing() {
#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ try {
+ using T = ImplicitThrow;
+ optional<T> t = 42;
+ assert(false);
+ ((void)t);
+ } catch (int) {
+ }
+ }
+
{
try {
using T = ExplicitThrow;
@@ -148,9 +128,68 @@ void test_explicit() {
#endif
}
+constexpr bool test() {
+ {
+ assert((implicit_conversion<long long>(42, 42)));
+ }
+
+ {
+ assert((implicit_conversion<long double>(3.14, 3.14)));
+ }
+
+ {
+ int x = 42;
+ optional<void* const> o(&x);
+ assert(*o == &x);
+ }
+
+ {
+ using T = TrivialTestTypes::TestType;
+ assert((implicit_conversion<T>(42, 42)));
+ }
+
+ {
+ using O = optional<ImplicitAny>;
+ assert(!(test_convertible<O, std::in_place_t>()));
+ assert(!(test_convertible<O, std::in_place_t&>()));
+ assert(!(test_convertible<O, const std::in_place_t&>()));
+ assert(!(test_convertible<O, std::in_place_t&&>()));
+ assert(!(test_convertible<O, const std::in_place_t&&>()));
+ }
+
+ {
+ using T = ExplicitTrivialTestTypes::TestType;
+ assert((explicit_conversion<T>(42, 42)));
+ }
+
+ {
+ using T = ExplicitConstexprTestTypes::TestType;
+ assert(explicit_conversion<T>(42, 42));
+ assert(!(std::is_convertible<int, T>::value));
+ }
+
+#if TEST_STD_VER >= 26 && 0
+ test_throwing();
+#endif
+
+ return true;
+}
+
int main(int, char**) {
- test_implicit();
- test_explicit();
+ test();
+ static_assert(test());
+
+ {
+ test_implicit();
+ }
+
+ {
+ test_explicit();
+ }
+
+ {
+ test_throwing();
+ }
return 0;
}
>From 242e5eb671af3f0ec94cc22393da705f5d3cf4a7 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 23 Nov 2025 13:51:24 -0500
Subject: [PATCH 13/17] Typo'd some REQUIRES directives
---
.../optional/optional.object/optional.object.ctor/U.pass.cpp | 2 +-
.../optional.object.ctor/explicit_const_optional_U.pass.cpp | 2 +-
.../optional.object/optional.object.ctor/in_place_t.pass.cpp | 2 +-
.../optional.object/optional.object.ctor/rvalue_T.pass.cpp | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
index 965085846bc4c..8701cb6dabed8 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRED: std-at-least-c++17
+// REQUIRES: std-at-least-c++17
// <optional>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
index fa9a96c39b8fa..da51b6a3c4350 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRED: std-at-least-c++17
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class U>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
index ae3d76eff4a42..f69f189acfdfd 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
-// REQUIRED: std-at-least-c++17
+// REQUIRES: std-at-least-c++17
// <optional>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
index 05af88af13916..5988159832fe9 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
@@ -5,7 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-//
+
// UNSUPPORTED: c++03, c++11, c++14
// <optional>
>From 91bb309bd314d55071e53e4f56fe3ae6272a0bab Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 25 Nov 2025 21:34:48 -0500
Subject: [PATCH 14/17] Add a optional<T&> copy and move test
---
.../const_optional_U.pass.cpp | 2 +-
.../optional.object.ctor/copy.pass.cpp | 69 ++++++++++++-------
.../optional.object.ctor/move.pass.cpp | 41 ++++++++---
3 files changed, 78 insertions(+), 34 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
index ab424a6509183..95aa7b33c3a96 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
@@ -87,6 +87,7 @@ constexpr bool test_all() {
}
constexpr bool test() {
+ static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value));
test_all<int, short>();
test_all<X, int>();
test_all<Y, int>();
@@ -126,6 +127,5 @@ int main(int, char**) {
test_throwing();
}
- static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value));
return 0;
}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
index bd4741154e6d8..9d711d7fb91f2 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
@@ -65,9 +65,26 @@ void test_ref(InitArgs&&... args) {
assert(&(*lhs) == &(*rhs));
}
-// TODO: Add constexpr tests
-void test_reference_extension() {
#if TEST_STD_VER >= 26
+struct X {
+ int copy_count = 0;
+
+ constexpr X() {}
+ constexpr X(const X&) { copy_count++; }
+};
+
+constexpr void test_ref() {
+ {
+ X x{};
+ std::optional<X&> o1(x);
+ std::optional<X&> o2(o1);
+ assert(o1.has_value() && o2.has_value());
+ assert(x.copy_count == 0);
+ assert(&*o1 == &*o2);
+ }
+}
+
+void test_reference_extension() {
using T = TestTypes::TestType;
T::reset();
{
@@ -103,13 +120,15 @@ void test_reference_extension() {
static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value);
}
# endif
-#endif
}
+#endif
constexpr bool test() {
test<int>();
test<int>(3);
test<const int>(42);
+ test<TrivialTestTypes::TestType>();
+ test<TrivialTestTypes::TestType>(42);
// FIXME: Why is this in ctor copy.pass.cpp?
{
@@ -129,34 +148,19 @@ constexpr bool test() {
}
}
- {
- using T = TrivialTestTypes::TestType;
- test<T>();
- test<T>(42);
- }
+#if TEST_STD_VER >= 26
+ test_ref();
// TODO: Enable once P3068R6 is implemented
-#if TEST_STD_VER >= 26 && 0
+# if 0
test_throwing_ctor();
+# endif
#endif
return true;
}
-int main(int, char**) {
- test();
- static_assert(test());
-
- {
- test_throwing_ctor();
- }
-
-#if TEST_STD_VER >= 26
- {
- test_reference_extension();
- }
-#endif
-
+void test_rt() {
{ // FIXME: Shouldn't this be able to pass in a constexpr context since C++17?
using T = ConstexprTestTypes::TestType;
test<T>();
@@ -189,6 +193,25 @@ int main(int, char**) {
}
TestTypes::TestType::reset();
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ {
+ test_rt();
+ }
+
+ {
+ test_throwing_ctor();
+ }
+
+#if TEST_STD_VER >= 26
+ {
+ test_reference_extension();
+ }
+#endif
return 0;
}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
index ba37fad3f1e2c..5bb8146f08338 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
@@ -59,16 +59,33 @@ TEST_CONSTEXPR_CXX26 void test_throwing_ctor() {
template <class T, class... InitArgs>
void test_ref(InitArgs&&... args) {
optional<T> rhs(std::forward<InitArgs>(args)...);
- bool rhs_engaged = static_cast<bool>(rhs);
- optional<T> lhs = std::move(rhs);
- assert(static_cast<bool>(lhs) == rhs_engaged);
- if (rhs_engaged)
- assert(&(*lhs) == &(*rhs));
+ optional<T> lhs(std::move(rhs));
+
+ assert(lhs.has_value() == rhs.has_value());
+ assert(rhs.has_value() ? &*lhs == &*rhs : true);
}
-// TODO: Add constexpr tests
-void test_reference_extension() {
+struct F {
+ int move_count = 0;
+
+ constexpr F() {}
+ constexpr F(F&&) { move_count++; }
+};
+
#if TEST_STD_VER >= 26
+
+constexpr void test_ref() {
+ { // Test that moving from an optional<T&> doesn't also move the object it's referencing
+ F f{};
+ std::optional<F&> o1(f);
+ std::optional<F&> o2(std::move(o1));
+ assert(f.move_count == 0);
+ assert(o1.has_value() && o2.has_value());
+ assert(&*o1 == &*o2);
+ }
+}
+
+void test_reference_extension() {
using T = TestTypes::TestType;
T::reset();
{
@@ -129,8 +146,8 @@ void test_reference_extension() {
static_assert(!std::is_copy_constructible_v<std::optional<T const&&>>);
}
# endif
-#endif
}
+#endif
constexpr bool test() {
test<int>();
@@ -143,6 +160,10 @@ constexpr bool test() {
test<T>(42);
}
+#if TEST_STD_VER >= 26
+ test_ref();
+#endif
+
#if TEST_STD_VER >= 26 && 0
{
test_throwing_ctor();
@@ -152,7 +173,7 @@ constexpr bool test() {
return true;
}
-bool rt_test() {
+bool test_rt() {
{
using T = TestTypes::TestType;
T::reset();
@@ -213,7 +234,7 @@ int main(int, char**) {
static_assert(test());
{
- rt_test();
+ test_rt();
}
{
>From ea768b4a85aa17154222a48434dae16bbb3b759a Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 27 Nov 2025 13:19:50 -0500
Subject: [PATCH 15/17] REQUIRES -> unsupported for the C++17
---
.../optional/optional.object/optional.object.ctor/U.pass.cpp | 2 +-
.../optional.object/optional.object.ctor/const_T.pass.cpp | 2 +-
.../optional.object.ctor/const_optional_U.pass.cpp | 3 ++-
.../optional.object/optional.object.ctor/copy.pass.cpp | 3 ++-
.../optional.object/optional.object.ctor/ctor.verify.cpp | 1 +
.../optional.object/optional.object.ctor/default.pass.cpp | 3 ++-
.../empty_in_place_t_does_not_clobber.pass.cpp | 1 +
.../optional.object.ctor/explicit_const_optional_U.pass.cpp | 3 ++-
.../optional.object.ctor/explicit_optional_U.pass.cpp | 3 ++-
.../optional.object/optional.object.ctor/in_place_t.pass.cpp | 4 ++--
.../optional.object.ctor/initializer_list.pass.cpp | 1 +
.../optional.object/optional.object.ctor/nullopt_t.pass.cpp | 3 ++-
.../optional.object/optional.object.ctor/optional_U.pass.cpp | 1 +
13 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
index 8701cb6dabed8..61dfe1166a980 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++17
+// UNSUPPORTED: c++03, c++11, c++14
// <optional>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
index 61cfc056dadd6..2f045bd19be77 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
@@ -5,7 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-//
+
// UNSUPPORTED: c++03, c++11, c++14
// <optional>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
index 95aa7b33c3a96..8f2105e409a8f 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
@@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++17
+// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// template <class U>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
index 9d711d7fb91f2..722eb95b5bef7 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
@@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++17
+// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// constexpr optional(const optional<T>& rhs);
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp
index 00ca941668eb2..08b2b43faacd4 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// T shall be an object type other than cv in_place_t or cv nullopt_t
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
index 540863b2b19c4..6fdf8d8898e38 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
@@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++17
+// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// constexpr optional() noexcept;
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/empty_in_place_t_does_not_clobber.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/empty_in_place_t_does_not_clobber.pass.cpp
index f19174841813c..c624911cb8c25 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/empty_in_place_t_does_not_clobber.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/empty_in_place_t_does_not_clobber.pass.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// constexpr optional(in_place_t);
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
index da51b6a3c4350..3f8bfb3a60e5e 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
@@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++17
+// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// template <class U>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
index f89ba1319a9ed..07e36a54872c4 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
@@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++17
+// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// template <class U>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
index f69f189acfdfd..2b78968ae521c 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-//
-// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: c++03, c++11, c++14
// <optional>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp
index 1993476792878..be1edc8f6c190 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// template <class U, class... Args>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
index 9e06b9b609a0a..60db025c3ffaa 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
@@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++17
+// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// constexpr optional(nullopt_t) noexcept;
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
index ff315de570a4d..f03ccaa0a0257 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
+
// <optional>
// template <class U>
>From 03fd8796ab0054908cc1f297d4a2890fb4e6db47 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 27 Nov 2025 13:22:51 -0500
Subject: [PATCH 16/17] Break verify test comments into their own lines and
re-format
---
.../optional.object.ctor/ctor.verify.cpp | 38 ++++++++++++-------
.../optional.object.ctor/deduct.verify.cpp | 4 --
2 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp
index 08b2b43faacd4..10f3defbd6f44 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp
@@ -24,30 +24,40 @@ struct NonDestructible {
};
int main(int, char**) {
- // clang-format off
{
#if TEST_STD_VER >= 26
- std::optional<int&&> opt2; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with an rvalue reference type is ill-formed}}
+ std::optional<int&&> opt2;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with an rvalue reference type is ill-formed}}
#else
- std::optional<char&> o1; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with a reference type is ill-formed}}
+ std::optional<char&> o1;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with a reference type is ill-formed}}
#endif
- std::optional<NonDestructible> o2; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with a non-destructible type is ill-formed}}
- std::optional<char[20]> o3; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with an array type is ill-formed}}
+ std::optional<NonDestructible> o2;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with a non-destructible type is ill-formed}}
+ std::optional<char[20]> o3;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with an array type is ill-formed}}
}
{
- std::optional< std::in_place_t> o1; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with in_place_t is ill-formed}}
- std::optional<const std::in_place_t> o2; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with in_place_t is ill-formed}}
- std::optional< volatile std::in_place_t> o3; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with in_place_t is ill-formed}}
- std::optional<const volatile std::in_place_t> o4; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with in_place_t is ill-formed}}
+ std::optional< std::in_place_t> o1;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with in_place_t is ill-formed}}
+ std::optional<const std::in_place_t> o2;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with in_place_t is ill-formed}}
+ std::optional< volatile std::in_place_t> o3;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with in_place_t is ill-formed}}
+ std::optional<const volatile std::in_place_t> o4;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with in_place_t is ill-formed}}
}
{
- std::optional< std::nullopt_t> o1; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with nullopt_t is ill-formed}}
- std::optional<const std::nullopt_t> o2; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with nullopt_t is ill-formed}}
- std::optional< volatile std::nullopt_t> o3; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with nullopt_t is ill-formed}}
- std::optional<const volatile std::nullopt_t> o4; // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with nullopt_t is ill-formed}}
+ std::optional< std::nullopt_t> o1;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with nullopt_t is ill-formed}}
+ std::optional<const std::nullopt_t> o2;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with nullopt_t is ill-formed}}
+ std::optional< volatile std::nullopt_t> o3;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with nullopt_t is ill-formed}}
+ std::optional<const volatile std::nullopt_t> o4;
+ // expected-error-re at optional:* {{static assertion failed{{.*}}instantiation of optional with nullopt_t is ill-formed}}
}
- // clang-format on
return 0;
}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.verify.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.verify.cpp
index 7ab842bf68c51..5616b2e0676e3 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.verify.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.verify.cpp
@@ -19,10 +19,6 @@
struct A {};
int main(int, char**) {
- // Test the explicit deduction guides
-
- // Test the implicit deduction guides
-
// clang-format off
{
// optional()
>From bcf9f55b72a6e24d9e22bbb7308d1a05cb4e2645 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 27 Nov 2025 13:36:10 -0500
Subject: [PATCH 17/17] Fold some tests into the runtime tests
---
.../optional.object.ctor/copy.pass.cpp | 18 +++++------
.../optional.object.ctor/move.pass.cpp | 18 ++++++-----
.../optional.object.ctor/rvalue_T.pass.cpp | 32 ++++++++++---------
3 files changed, 36 insertions(+), 32 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
index 722eb95b5bef7..0237cfd1ca596 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
@@ -194,15 +194,6 @@ void test_rt() {
}
TestTypes::TestType::reset();
-}
-
-int main(int, char**) {
- test();
- static_assert(test());
-
- {
- test_rt();
- }
{
test_throwing_ctor();
@@ -213,6 +204,15 @@ int main(int, char**) {
test_reference_extension();
}
#endif
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ {
+ test_rt();
+ }
return 0;
}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
index 5bb8146f08338..b4df9c4e43bbb 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
@@ -226,6 +226,16 @@ bool test_rt() {
static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, "");
}
+ {
+ test_throwing_ctor();
+ }
+
+#if TEST_STD_VER >= 26
+ {
+ test_reference_extension();
+ }
+#endif
+
return true;
}
@@ -237,13 +247,5 @@ int main(int, char**) {
test_rt();
}
- {
- test_throwing_ctor();
- }
-
- {
- test_reference_extension();
- }
-
return 0;
}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
index 5988159832fe9..e851cc82d60fb 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
@@ -47,6 +47,20 @@ constexpr void test_rvalueT(U arg) {
};
}
+TEST_CONSTEXPR_CXX26 void test_throwing() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ try {
+ Z z(3);
+ optional<Z> opt(std::move(z));
+ assert(false);
+ } catch (int i) {
+ assert(i == 6);
+ }
+ }
+#endif
+}
+
void test_rt() {
{
typedef TestTypes::TestType T;
@@ -57,6 +71,7 @@ void test_rt() {
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
+
{
typedef ExplicitTestTypes::TestType T;
static_assert(!std::is_convertible<T&&, optional<T>>::value, "");
@@ -67,6 +82,7 @@ void test_rt() {
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
+
{
typedef TestTypes::TestType T;
T::reset();
@@ -78,20 +94,10 @@ void test_rt() {
assert(static_cast<bool>(opt) == true);
assert(opt.value().value == 3);
}
-}
-TEST_CONSTEXPR_CXX26 void test_throwing() {
-#ifndef TEST_HAS_NO_EXCEPTIONS
{
- try {
- Z z(3);
- optional<Z> opt(std::move(z));
- assert(false);
- } catch (int i) {
- assert(i == 6);
- }
+ test_throwing();
}
-#endif
}
constexpr bool test() {
@@ -132,9 +138,5 @@ int main(int, char**) {
test_rt();
}
- {
- test_throwing();
- }
-
return 0;
}
More information about the libcxx-commits
mailing list