Skip to content

Commit e47e69c

Browse files
committed
[libc++] Mark std::expected as nodiscard
Fixes #130656
1 parent f2351d9 commit e47e69c

File tree

8 files changed

+73
-50
lines changed

8 files changed

+73
-50
lines changed

libcxx/include/__expected/expected.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ class __expected_base {
448448
};
449449

450450
template <class _Tp, class _Err>
451-
class expected : private __expected_base<_Tp, _Err> {
451+
class [[nodiscard]] expected : private __expected_base<_Tp, _Err> {
452452
static_assert(!is_reference_v<_Tp> && !is_function_v<_Tp> && !is_same_v<remove_cv_t<_Tp>, in_place_t> &&
453453
!is_same_v<remove_cv_t<_Tp>, unexpect_t> && !__is_std_unexpected<remove_cv_t<_Tp>>::value &&
454454
__valid_std_unexpected<_Err>::value,
@@ -1377,7 +1377,7 @@ class __expected_void_base {
13771377

13781378
template <class _Tp, class _Err>
13791379
requires is_void_v<_Tp>
1380-
class expected<_Tp, _Err> : private __expected_void_base<_Err> {
1380+
class [[nodiscard]] expected<_Tp, _Err> : private __expected_void_base<_Err> {
13811381
static_assert(__valid_std_unexpected<_Err>::value,
13821382
"[expected.void.general] A program that instantiates expected<T, E> with a E that is not a "
13831383
"valid argument for unexpected<E> is ill-formed");

libcxx/test/libcxx/utilities/expected/expected.expected/and_then.mandates.verify.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void test() {
5151
// U is not a specialization of std::expected
5252
{
5353
std::expected<int, int> f1(1);
54-
f1.and_then(lval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(int &)>' requested here}}
54+
(void)f1.and_then(lval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(int &)>' requested here}}
5555
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must be a specialization of std::expected}}
5656
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
5757
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
@@ -60,7 +60,7 @@ void test() {
6060
// !std::is_same_v<U:error_type, E>
6161
{
6262
std::expected<int, int> f1(1);
63-
f1.and_then(lval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(int &)>' requested here}}
63+
(void)f1.and_then(lval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(int &)>' requested here}}
6464
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must have the same error_type as this expected}}
6565
}
6666
}
@@ -70,7 +70,7 @@ void test() {
7070
// U is not a specialization of std::expected
7171
{
7272
const std::expected<int, int> f1(1);
73-
f1.and_then(clval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(const int &)>' requested here}}
73+
(void)f1.and_then(clval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(const int &)>' requested here}}
7474
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must be a specialization of std::expected}}
7575
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
7676
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
@@ -79,7 +79,7 @@ void test() {
7979
// !std::is_same_v<U:error_type, E>
8080
{
8181
const std::expected<int, int> f1(1);
82-
f1.and_then(clval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(const int &)>' requested here}}
82+
(void)f1.and_then(clval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(const int &)>' requested here}}
8383
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must have the same error_type as this expected}}
8484

8585
}
@@ -90,7 +90,7 @@ void test() {
9090
// U is not a specialization of std::expected
9191
{
9292
std::expected<int, int> f1(1);
93-
std::move(f1).and_then(rval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(int &&)>' requested here}}
93+
(void)std::move(f1).and_then(rval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(int &&)>' requested here}}
9494
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(value())) must be a specialization of std::expected}}
9595
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
9696
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
@@ -99,7 +99,7 @@ void test() {
9999
// !std::is_same_v<U:error_type, E>
100100
{
101101
std::expected<int, int> f1(1);
102-
std::move(f1).and_then(rval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(int &&)>' requested here}}
102+
(void)std::move(f1).and_then(rval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(int &&)>' requested here}}
103103
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(value())) must have the same error_type as this expected}}
104104
}
105105
}
@@ -109,7 +109,7 @@ void test() {
109109
// U is not a specialization of std::expected
110110
{
111111
const std::expected<int, int> f1(1);
112-
std::move(f1).and_then(crval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(const int &&)>' requested here}}
112+
(void)std::move(f1).and_then(crval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(const int &&)>' requested here}}
113113
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(value())) must be a specialization of std::expected}}
114114
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
115115
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
@@ -118,7 +118,7 @@ void test() {
118118
// !std::is_same_v<U:error_type, E>
119119
{
120120
const std::expected<int, int> f1(1);
121-
std::move(f1).and_then(crval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(const int &&)>' requested here}}
121+
(void)std::move(f1).and_then(crval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(const int &&)>' requested here}}
122122
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(value())) must have the same error_type as this expected}}
123123
}
124124
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: std-at-least-c++23
10+
11+
// <expected>
12+
13+
// Test that ignoring std::expected generates [[nodiscard]] warnings.
14+
15+
#include <expected>
16+
17+
std::expected<int, int> returns_expected();
18+
std::expected<void, int> returns_expected_void();
19+
20+
void test() {
21+
returns_expected(); // expected-warning {{ignoring return value of type 'expected<int, int>'}}
22+
returns_expected_void(); // expected-warning {{ignoring return value of type 'expected<void, int>'}}
23+
}

libcxx/test/libcxx/utilities/expected/expected.expected/or_else.mandates.verify.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void test() {
5151
// G is not a specialization of std::expected
5252
{
5353
std::expected<int, int> f1(std::unexpected<int>(1));
54-
f1.or_else(lval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<int (&)(int &)>' requested here}}
54+
(void)f1.or_else(lval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<int (&)(int &)>' requested here}}
5555
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(error()) must be a specialization of std::expected}}
5656
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
5757
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
@@ -60,7 +60,7 @@ void test() {
6060
// !std::is_same_v<G:value_type, T>
6161
{
6262
std::expected<int, int> f1(std::unexpected<int>(1));
63-
f1.or_else(lval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<std::expected<NotSameAsInt, int> (&)(int &)>' requested here}}
63+
(void)f1.or_else(lval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<std::expected<NotSameAsInt, int> (&)(int &)>' requested here}}
6464
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(error()) must have the same value_type as this expected}}
6565
}
6666
}
@@ -70,7 +70,7 @@ void test() {
7070
// G is not a specialization of std::expected
7171
{
7272
const std::expected<int, int> f1(std::unexpected<int>(1));
73-
f1.or_else(clval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<int (&)(const int &)>' requested here}}
73+
(void)f1.or_else(clval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<int (&)(const int &)>' requested here}}
7474
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(error()) must be a specialization of std::expected}}
7575
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
7676
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
@@ -79,7 +79,7 @@ void test() {
7979
// !std::is_same_v<G:value_type, T>
8080
{
8181
const std::expected<int, int> f1(std::unexpected<int>(1));
82-
f1.or_else(clval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<std::expected<NotSameAsInt, int> (&)(const int &)>' requested here}}
82+
(void)f1.or_else(clval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<std::expected<NotSameAsInt, int> (&)(const int &)>' requested here}}
8383
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(error()) must have the same value_type as this expected}}
8484
}
8585
}
@@ -89,7 +89,7 @@ void test() {
8989
// G is not a specialization of std::expected
9090
{
9191
std::expected<int, int> f1(std::unexpected<int>(1));
92-
std::move(f1).or_else(rval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<int (&)(int &&)>' requested here}}
92+
(void)std::move(f1).or_else(rval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<int (&)(int &&)>' requested here}}
9393
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(error())) must be a specialization of std::expected}}
9494
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
9595
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
@@ -98,7 +98,7 @@ void test() {
9898
// !std::is_same_v<G:value_type, T>
9999
{
100100
std::expected<int, int> f1(std::unexpected<int>(1));
101-
std::move(f1).or_else(rval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<std::expected<NotSameAsInt, int> (&)(int &&)>' requested here}}
101+
(void)std::move(f1).or_else(rval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<std::expected<NotSameAsInt, int> (&)(int &&)>' requested here}}
102102
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(error())) must have the same value_type as this expected}}
103103
}
104104
}
@@ -108,7 +108,7 @@ void test() {
108108
// G is not a specialization of std::expected
109109
{
110110
const std::expected<int, int> f1(std::unexpected<int>(1));
111-
std::move(f1).or_else(crval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<int (&)(const int &&)>' requested here}}
111+
(void)std::move(f1).or_else(crval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<int (&)(const int &&)>' requested here}}
112112
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(error())) must be a specialization of std::expected}}
113113
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
114114
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
@@ -117,7 +117,7 @@ void test() {
117117
// !std::is_same_v<G:value_type, T>
118118
{
119119
const std::expected<int, int> f1(std::unexpected<int>(1));
120-
std::move(f1).or_else(crval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<std::expected<NotSameAsInt, int> (&)(const int &&)>' requested here}}
120+
(void)std::move(f1).or_else(crval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::or_else<std::expected<NotSameAsInt, int> (&)(const int &&)>' requested here}}
121121
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(error())) must have the same value_type as this expected}}
122122
}
123123
}

libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ void test() {
5858
// Test & overload
5959
{
6060
std::expected<int, int> e;
61-
e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
61+
(void)e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
6262
// expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
6363
// expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
6464
// expected-error-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}}}
6565

66-
e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
66+
(void)e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
6767
// expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
6868
// expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
6969
// expected-warning-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}, which is a Microsoft extension}}
@@ -72,27 +72,27 @@ void test() {
7272
// Test const& overload
7373
{
7474
const std::expected<int, int> e;
75-
e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
75+
(void)e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
7676
// expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
77-
e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
77+
(void)e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
7878
// expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
7979
}
8080

8181
// Test && overload
8282
{
8383
std::expected<int, int> e;
84-
std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
84+
(void)std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
8585
// expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
86-
std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
86+
(void)std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
8787
// expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
8888
}
8989

9090
// Test const&& overload
9191
{
9292
const std::expected<int, int> e;
93-
std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
93+
(void)std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
9494
// expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
95-
std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
95+
(void)std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
9696
// expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
9797
}
9898
}

0 commit comments

Comments
 (0)