Skip to content

Commit c66a826

Browse files
committed
[libc++] Add test coverage for our implementation of LWG4031
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.
1 parent 0f5f931 commit c66a826

File tree

5 files changed

+129
-19
lines changed

5 files changed

+129
-19
lines changed

libcxx/docs/Status/Cxx2cIssues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"`4023 <https://wg21.link/LWG4023>`__","Preconditions of ``std::basic_streambuf::setg/setp``","Tokyo March 2024","","",""
5353
"`4025 <https://wg21.link/LWG4025>`__","Move assignment operator of ``std::expected<cv void, E>`` should not be conditionally deleted","Tokyo March 2024","","",""
5454
"`4030 <https://wg21.link/LWG4030>`__","Clarify whether arithmetic expressions in ``[numeric.sat.func]`` are mathematical or C++","Tokyo March 2024","","",""
55-
"`4031 <https://wg21.link/LWG4031>`__","``bad_expected_access<void>`` member functions should be ``noexcept``","Tokyo March 2024","","",""
55+
"`4031 <https://wg21.link/LWG4031>`__","``bad_expected_access<void>`` member functions should be ``noexcept``","Tokyo March 2024","|Complete|","16.0",""
5656
"`4035 <https://wg21.link/LWG4035>`__","``single_view`` should provide ``empty``","Tokyo March 2024","","","|ranges|"
5757
"`4036 <https://wg21.link/LWG4036>`__","``__alignof_is_defined`` is only implicitly specified in C++ and not yet deprecated","Tokyo March 2024","","",""
5858
"`4037 <https://wg21.link/LWG4037>`__","Static data members of ``ctype_base`` are not yet required to be usable in constant expressions","Tokyo March 2024","","",""

libcxx/include/__expected/bad_expected_access.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ class bad_expected_access;
3030
template <>
3131
class bad_expected_access<void> : public exception {
3232
protected:
33-
_LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default;
34-
_LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) = default;
35-
_LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default;
36-
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default;
37-
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default;
38-
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default;
33+
_LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default;
34+
_LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) noexcept = default;
35+
_LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) noexcept = default;
36+
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) noexcept = default;
37+
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) noexcept = default;
38+
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default;
3939

4040
public:
4141
// The way this has been designed (by using a class template below) means that we'll already

libcxx/test/std/utilities/expected/expected.bad/what.noexcept.compile.pass.cpp renamed to libcxx/test/std/utilities/expected/expected.bad/base.compile.pass.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,12 @@
77

88
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
99

10-
// const char* what() const noexcept override;
10+
// Make sure std::bad_expected_access<E> inherits from std::bad_expected_access<void>.
1111

1212
#include <expected>
13-
#include <utility>
13+
#include <type_traits>
1414

15-
template <class T>
16-
concept WhatNoexcept =
17-
requires(const T& t) {
18-
{ t.what() } noexcept;
19-
};
15+
struct Foo {};
2016

21-
struct foo{};
22-
23-
static_assert(!WhatNoexcept<foo>);
24-
static_assert(WhatNoexcept<std::bad_expected_access<int>>);
25-
static_assert(WhatNoexcept<std::bad_expected_access<foo>>);
17+
static_assert(std::is_base_of_v<std::bad_expected_access<void>, std::bad_expected_access<int>>);
18+
static_assert(std::is_base_of_v<std::bad_expected_access<void>, std::bad_expected_access<Foo>>);
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===----------------------------------------------------------------------===//
2+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
//===----------------------------------------------------------------------===//
7+
8+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9+
10+
// template<>
11+
// class bad_expected_access<void> : public exception {
12+
// protected:
13+
// bad_expected_access() noexcept;
14+
// bad_expected_access(const bad_expected_access&) noexcept;
15+
// bad_expected_access(bad_expected_access&&) noexcept;
16+
// bad_expected_access& operator=(const bad_expected_access&) noexcept;
17+
// bad_expected_access& operator=(bad_expected_access&&) noexcept;
18+
// ~bad_expected_access();
19+
//
20+
// public:
21+
// const char* what() const noexcept override;
22+
// };
23+
24+
#include <expected>
25+
#include <cassert>
26+
#include <type_traits>
27+
#include <utility>
28+
29+
#include "test_macros.h"
30+
31+
struct Inherit : std::bad_expected_access<void> {};
32+
33+
int main(int, char**) {
34+
// base class
35+
static_assert(std::is_base_of_v<std::exception, std::bad_expected_access<void>>);
36+
37+
// default constructor
38+
{
39+
Inherit exc;
40+
ASSERT_NOEXCEPT(Inherit());
41+
}
42+
43+
// copy constructor
44+
{
45+
Inherit exc;
46+
Inherit copy(exc);
47+
ASSERT_NOEXCEPT(Inherit(exc));
48+
}
49+
50+
// move constructor
51+
{
52+
Inherit exc;
53+
Inherit copy(std::move(exc));
54+
ASSERT_NOEXCEPT(Inherit(std::move(exc)));
55+
}
56+
57+
// copy assignment
58+
{
59+
Inherit exc;
60+
Inherit copy;
61+
[[maybe_unused]] Inherit& result = (copy = exc);
62+
ASSERT_NOEXCEPT(copy = exc);
63+
}
64+
65+
// move assignment
66+
{
67+
Inherit exc;
68+
Inherit copy;
69+
[[maybe_unused]] Inherit& result = (copy = std::move(exc));
70+
ASSERT_NOEXCEPT(copy = std::move(exc));
71+
}
72+
73+
// what()
74+
{
75+
Inherit exc;
76+
char const* what = exc.what();
77+
assert(what != nullptr);
78+
ASSERT_NOEXCEPT(exc.what());
79+
}
80+
81+
return 0;
82+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
//===----------------------------------------------------------------------===//
7+
8+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9+
10+
// const char* what() const noexcept override;
11+
12+
#include <expected>
13+
#include <cassert>
14+
#include <utility>
15+
16+
#include "test_macros.h"
17+
18+
struct Foo {};
19+
20+
int main(int, char**) {
21+
{
22+
std::bad_expected_access<int> const exc(99);
23+
char const* what = exc.what();
24+
assert(what != nullptr);
25+
ASSERT_NOEXCEPT(exc.what());
26+
}
27+
{
28+
std::bad_expected_access<Foo> const exc(Foo{});
29+
char const* what = exc.what();
30+
assert(what != nullptr);
31+
ASSERT_NOEXCEPT(exc.what());
32+
}
33+
34+
return 0;
35+
}

0 commit comments

Comments
 (0)