-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[libc++] Add test coverage for our implementation of LWG4031 #87508
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
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-libcxx Author: Louis Dionne (ldionne) ChangesThis was actually already implemented in the initial version of std::expected, but this patch adds test coverage and makes it more explicit that we intend to make these functions noexcept. Full diff: https://github.com/llvm/llvm-project/pull/87508.diff 5 Files Affected:
diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index f471c430b19c18..54ea374c5bdd17 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -52,7 +52,7 @@
"`4023 <https://wg21.link/LWG4023>`__","Preconditions of ``std::basic_streambuf::setg/setp``","Tokyo March 2024","","",""
"`4025 <https://wg21.link/LWG4025>`__","Move assignment operator of ``std::expected<cv void, E>`` should not be conditionally deleted","Tokyo March 2024","","",""
"`4030 <https://wg21.link/LWG4030>`__","Clarify whether arithmetic expressions in ``[numeric.sat.func]`` are mathematical or C++","Tokyo March 2024","","",""
-"`4031 <https://wg21.link/LWG4031>`__","``bad_expected_access<void>`` member functions should be ``noexcept``","Tokyo March 2024","","",""
+"`4031 <https://wg21.link/LWG4031>`__","``bad_expected_access<void>`` member functions should be ``noexcept``","Tokyo March 2024","|Complete|","16.0",""
"`4035 <https://wg21.link/LWG4035>`__","``single_view`` should provide ``empty``","Tokyo March 2024","","","|ranges|"
"`4036 <https://wg21.link/LWG4036>`__","``__alignof_is_defined`` is only implicitly specified in C++ and not yet deprecated","Tokyo March 2024","","",""
"`4037 <https://wg21.link/LWG4037>`__","Static data members of ``ctype_base`` are not yet required to be usable in constant expressions","Tokyo March 2024","","",""
diff --git a/libcxx/include/__expected/bad_expected_access.h b/libcxx/include/__expected/bad_expected_access.h
index 27f01d9350eea6..4341e94be0f2c2 100644
--- a/libcxx/include/__expected/bad_expected_access.h
+++ b/libcxx/include/__expected/bad_expected_access.h
@@ -30,12 +30,12 @@ class bad_expected_access;
template <>
class bad_expected_access<void> : public exception {
protected:
- _LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default;
- _LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) = default;
- _LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default;
- _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default;
- _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default;
- _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default;
+ _LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default;
+ _LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) noexcept = default;
+ _LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) noexcept = default;
+ _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) noexcept = default;
+ _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) noexcept = default;
+ _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default;
public:
// The way this has been designed (by using a class template below) means that we'll already
diff --git a/libcxx/test/std/utilities/expected/expected.bad/what.noexcept.compile.pass.cpp b/libcxx/test/std/utilities/expected/expected.bad/base.compile.pass.cpp
similarity index 56%
rename from libcxx/test/std/utilities/expected/expected.bad/what.noexcept.compile.pass.cpp
rename to libcxx/test/std/utilities/expected/expected.bad/base.compile.pass.cpp
index e6d050b2129d62..545215a3b16130 100644
--- a/libcxx/test/std/utilities/expected/expected.bad/what.noexcept.compile.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.bad/base.compile.pass.cpp
@@ -7,19 +7,12 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-// const char* what() const noexcept override;
+// Make sure std::bad_expected_access<E> inherits from std::bad_expected_access<void>.
#include <expected>
-#include <utility>
+#include <type_traits>
-template <class T>
-concept WhatNoexcept =
- requires(const T& t) {
- { t.what() } noexcept;
- };
+struct Foo {};
-struct foo{};
-
-static_assert(!WhatNoexcept<foo>);
-static_assert(WhatNoexcept<std::bad_expected_access<int>>);
-static_assert(WhatNoexcept<std::bad_expected_access<foo>>);
+static_assert(std::is_base_of_v<std::bad_expected_access<void>, std::bad_expected_access<int>>);
+static_assert(std::is_base_of_v<std::bad_expected_access<void>, std::bad_expected_access<Foo>>);
diff --git a/libcxx/test/std/utilities/expected/expected.bad/void-specialization.pass.cpp b/libcxx/test/std/utilities/expected/expected.bad/void-specialization.pass.cpp
new file mode 100644
index 00000000000000..ce0609acdb5abd
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.bad/void-specialization.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// template<>
+// class bad_expected_access<void> : public exception {
+// protected:
+// bad_expected_access() noexcept;
+// bad_expected_access(const bad_expected_access&) noexcept;
+// bad_expected_access(bad_expected_access&&) noexcept;
+// bad_expected_access& operator=(const bad_expected_access&) noexcept;
+// bad_expected_access& operator=(bad_expected_access&&) noexcept;
+// ~bad_expected_access();
+//
+// public:
+// const char* what() const noexcept override;
+// };
+
+#include <expected>
+#include <cassert>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+struct Inherit : std::bad_expected_access<void> {};
+
+int main(int, char**) {
+ // base class
+ static_assert(std::is_base_of_v<std::exception, std::bad_expected_access<void>>);
+
+ // default constructor
+ {
+ Inherit exc;
+ ASSERT_NOEXCEPT(Inherit());
+ }
+
+ // copy constructor
+ {
+ Inherit exc;
+ Inherit copy(exc);
+ ASSERT_NOEXCEPT(Inherit(exc));
+ }
+
+ // move constructor
+ {
+ Inherit exc;
+ Inherit copy(std::move(exc));
+ ASSERT_NOEXCEPT(Inherit(std::move(exc)));
+ }
+
+ // copy assignment
+ {
+ Inherit exc;
+ Inherit copy;
+ [[maybe_unused]] Inherit& result = (copy = exc);
+ ASSERT_NOEXCEPT(copy = exc);
+ }
+
+ // move assignment
+ {
+ Inherit exc;
+ Inherit copy;
+ [[maybe_unused]] Inherit& result = (copy = std::move(exc));
+ ASSERT_NOEXCEPT(copy = std::move(exc));
+ }
+
+ // what()
+ {
+ Inherit exc;
+ char const* what = exc.what();
+ assert(what != nullptr);
+ ASSERT_NOEXCEPT(exc.what());
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/expected/expected.bad/what.pass.cpp b/libcxx/test/std/utilities/expected/expected.bad/what.pass.cpp
new file mode 100644
index 00000000000000..bc5e356161a740
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.bad/what.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// const char* what() const noexcept override;
+
+#include <expected>
+#include <cassert>
+#include <utility>
+
+#include "test_macros.h"
+
+struct Foo {};
+
+int main(int, char**) {
+ {
+ std::bad_expected_access<int> const exc(99);
+ char const* what = exc.what();
+ assert(what != nullptr);
+ ASSERT_NOEXCEPT(exc.what());
+ }
+ {
+ std::bad_expected_access<Foo> const exc(Foo{});
+ char const* what = exc.what();
+ assert(what != nullptr);
+ ASSERT_NOEXCEPT(exc.what());
+ }
+
+ return 0;
+}
|
This was actually already implemented in the initial version of std::expected, but this patch adds test coverage and makes it more explicit that we intend to make these functions noexcept.
c66a826
to
27fec94
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This was actually already implemented in the initial version of std::expected, but this patch adds test coverage and makes it more explicit that we intend to make these functions noexcept.