Skip to content

Commit ddd770d

Browse files
authored
[libc++] Applied [[nodiscard]] to <exception>, <stdexcept> and <system_error> (#170837)
[[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html
1 parent 6bb7863 commit ddd770d

File tree

10 files changed

+178
-29
lines changed

10 files changed

+178
-29
lines changed

libcxx/include/__exception/exception.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ class exception { // base of all library exceptions
5454

5555
virtual ~exception() _NOEXCEPT {}
5656

57-
virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; }
57+
[[__nodiscard__]] virtual char const* what() const _NOEXCEPT {
58+
return __data_._What ? __data_._What : "Unknown exception";
59+
}
5860

5961
private:
6062
__std_exception_data __data_;
@@ -76,7 +78,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception {
7678
_LIBCPP_HIDE_FROM_ABI exception& operator=(const exception&) _NOEXCEPT = default;
7779

7880
virtual ~exception() _NOEXCEPT;
79-
virtual const char* what() const _NOEXCEPT;
81+
[[__nodiscard__]] virtual const char* what() const _NOEXCEPT;
8082
};
8183

8284
class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception {
@@ -85,7 +87,7 @@ class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception {
8587
_LIBCPP_HIDE_FROM_ABI bad_exception(const bad_exception&) _NOEXCEPT = default;
8688
_LIBCPP_HIDE_FROM_ABI bad_exception& operator=(const bad_exception&) _NOEXCEPT = default;
8789
~bad_exception() _NOEXCEPT override;
88-
const char* what() const _NOEXCEPT override;
90+
[[__nodiscard__]] const char* what() const _NOEXCEPT override;
8991
};
9092
#endif // !_LIBCPP_ABI_VCRUNTIME
9193

libcxx/include/__exception/nested_exception.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class _LIBCPP_EXPORTED_FROM_ABI nested_exception {
4040

4141
// access functions
4242
[[__noreturn__]] void rethrow_nested() const;
43-
_LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; }
43+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; }
4444
};
4545

4646
template <class _Tp>

libcxx/include/__exception/operations.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,22 @@ _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
2020
defined(_LIBCPP_BUILDING_LIBRARY)
2121
using unexpected_handler = void (*)();
2222
_LIBCPP_EXPORTED_FROM_ABI unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;
23-
_LIBCPP_EXPORTED_FROM_ABI unexpected_handler get_unexpected() _NOEXCEPT;
23+
[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI unexpected_handler get_unexpected() _NOEXCEPT;
2424
[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void unexpected();
2525
#endif
2626

2727
using terminate_handler = void (*)();
2828
_LIBCPP_EXPORTED_FROM_ABI terminate_handler set_terminate(terminate_handler) _NOEXCEPT;
29-
_LIBCPP_EXPORTED_FROM_ABI terminate_handler get_terminate() _NOEXCEPT;
29+
[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI terminate_handler get_terminate() _NOEXCEPT;
3030

3131
#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION)
32-
_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 bool uncaught_exception() _NOEXCEPT;
32+
[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 bool uncaught_exception() _NOEXCEPT;
3333
#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION)
34-
_LIBCPP_EXPORTED_FROM_ABI int uncaught_exceptions() _NOEXCEPT;
34+
[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI int uncaught_exceptions() _NOEXCEPT;
3535

3636
class _LIBCPP_EXPORTED_FROM_ABI exception_ptr;
3737

38-
_LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
38+
[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
3939
[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr);
4040
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
4141

libcxx/include/__system_error/error_category.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ class _LIBCPP_EXPORTED_FROM_ABI error_category {
3737
error_category(const error_category&) = delete;
3838
error_category& operator=(const error_category&) = delete;
3939

40-
virtual const char* name() const _NOEXCEPT = 0;
41-
virtual error_condition default_error_condition(int __ev) const _NOEXCEPT;
42-
virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT;
43-
virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT;
44-
virtual string message(int __ev) const = 0;
40+
[[__nodiscard__]] virtual const char* name() const _NOEXCEPT = 0;
41+
[[__nodiscard__]] virtual error_condition default_error_condition(int __ev) const _NOEXCEPT;
42+
[[__nodiscard__]] virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT;
43+
[[__nodiscard__]] virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT;
44+
[[__nodiscard__]] virtual string message(int __ev) const = 0;
4545

4646
_LIBCPP_HIDE_FROM_ABI bool operator==(const error_category& __rhs) const _NOEXCEPT { return this == &__rhs; }
4747

@@ -67,8 +67,8 @@ class _LIBCPP_HIDDEN __do_message : public error_category {
6767
string message(int __ev) const override;
6868
};
6969

70-
[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& generic_category() _NOEXCEPT;
71-
[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& system_category() _NOEXCEPT;
70+
[[__gnu__::__const__]] [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& generic_category() _NOEXCEPT;
71+
[[__gnu__::__const__]] [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& system_category() _NOEXCEPT;
7272

7373
_LIBCPP_END_NAMESPACE_STD
7474

libcxx/include/__system_error/error_code.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,20 @@ class _LIBCPP_EXPORTED_FROM_ABI error_code {
7171
__cat_ = &system_category();
7272
}
7373

74-
_LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; }
74+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; }
7575

76-
_LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; }
76+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; }
7777

78-
_LIBCPP_HIDE_FROM_ABI error_condition default_error_condition() const _NOEXCEPT {
78+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI error_condition default_error_condition() const _NOEXCEPT {
7979
return __cat_->default_error_condition(__val_);
8080
}
8181

82-
string message() const;
82+
[[__nodiscard__]] string message() const;
8383

8484
_LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __val_ != 0; }
8585
};
8686

87-
inline _LIBCPP_HIDE_FROM_ABI error_code make_error_code(errc __e) _NOEXCEPT {
87+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI error_code make_error_code(errc __e) _NOEXCEPT {
8888
return error_code(static_cast<int>(__e), generic_category());
8989
}
9090

libcxx/include/__system_error/error_condition.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ class _LIBCPP_EXPORTED_FROM_ABI error_condition {
8080
__cat_ = &generic_category();
8181
}
8282

83-
_LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; }
83+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; }
8484

85-
_LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; }
86-
string message() const;
85+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; }
86+
[[__nodiscard__]] string message() const;
8787

8888
_LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __val_ != 0; }
8989
};
9090

91-
inline _LIBCPP_HIDE_FROM_ABI error_condition make_error_condition(errc __e) _NOEXCEPT {
91+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI error_condition make_error_condition(errc __e) _NOEXCEPT {
9292
return error_condition(static_cast<int>(__e), generic_category());
9393
}
9494

libcxx/include/__system_error/system_error.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class _LIBCPP_EXPORTED_FROM_ABI system_error : public runtime_error {
3636
_LIBCPP_HIDE_FROM_ABI system_error(const system_error&) _NOEXCEPT = default;
3737
~system_error() _NOEXCEPT override;
3838

39-
_LIBCPP_HIDE_FROM_ABI const error_code& code() const _NOEXCEPT { return __ec_; }
39+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const error_code& code() const _NOEXCEPT { return __ec_; }
4040
};
4141

4242
// __ev is expected to be an error in the generic_category domain (e.g. from

libcxx/include/stdexcept

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public:
9191

9292
~logic_error() _NOEXCEPT override;
9393

94-
const char* what() const _NOEXCEPT override;
94+
[[__nodiscard__]] const char* what() const _NOEXCEPT override;
9595
# else
9696

9797
public:
@@ -115,7 +115,7 @@ public:
115115

116116
~runtime_error() _NOEXCEPT override;
117117

118-
const char* what() const _NOEXCEPT override;
118+
[[__nodiscard__]] const char* what() const _NOEXCEPT override;
119119
# else
120120

121121
public:
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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+
// Check that functions are marked [[nodiscard]]
10+
11+
#include <stdexcept>
12+
#include <system_error>
13+
14+
void test() {
15+
{ // <stdexcept>
16+
std::logic_error le("logic error");
17+
le.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
18+
19+
std::runtime_error re("runtime error");
20+
re.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
21+
22+
std::domain_error de("domain error");
23+
de.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
24+
25+
std::invalid_argument ia("invalid argument");
26+
ia.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
27+
28+
std::length_error lerr("length error");
29+
lerr.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
30+
31+
std::out_of_range oor("out of range");
32+
oor.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
33+
34+
std::range_error rerr("range error");
35+
rerr.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
36+
37+
std::overflow_error oferr("overflow error");
38+
oferr.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
39+
40+
std::underflow_error uferr("underflow error");
41+
uferr.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
42+
}
43+
{ // <system_error>
44+
{
45+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
46+
std::generic_category();
47+
48+
const std::error_category& ec = std::generic_category();
49+
50+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
51+
ec.name();
52+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
53+
ec.default_error_condition(94);
54+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
55+
ec.equivalent(94, ec.default_error_condition(82));
56+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
57+
ec.equivalent(std::error_code(49, ec), 94);
58+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
59+
ec.message(82);
60+
}
61+
{
62+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
63+
std::system_category();
64+
65+
const std::error_category& ec = std::system_category();
66+
67+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
68+
ec.name();
69+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
70+
ec.default_error_condition(94);
71+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
72+
ec.equivalent(94, ec.default_error_condition(82));
73+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
74+
ec.equivalent(std::error_code(49, ec), 94);
75+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
76+
ec.message(82);
77+
}
78+
{
79+
std::error_code ec;
80+
81+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
82+
ec.value();
83+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
84+
ec.category();
85+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
86+
ec.default_error_condition();
87+
88+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
89+
ec.message();
90+
91+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
92+
std::make_error_code(std::errc::invalid_argument);
93+
}
94+
{
95+
std::error_condition ec;
96+
97+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
98+
ec.value();
99+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
100+
ec.category();
101+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
102+
ec.message();
103+
104+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
105+
std::make_error_condition(std::errc::invalid_argument);
106+
}
107+
}
108+
}

libcxx/test/libcxx/language.support/nodiscard.verify.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03
9+
// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated
10+
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS
11+
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION
1012

1113
// Check that functions are marked [[nodiscard]]
1214

1315
#include <compare>
1416
#include <coroutine>
17+
#include <exception>
1518
#include <functional>
1619
#include <initializer_list>
1720

@@ -81,11 +84,47 @@ void test() {
8184
}
8285
#endif
8386

87+
{ // <exception>
88+
{
89+
std::bad_exception bex;
90+
91+
bex.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
92+
}
93+
{
94+
std::exception ex;
95+
96+
ex.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
97+
}
98+
{
99+
std::nested_exception nex;
100+
101+
nex.nested_ptr(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
102+
}
103+
104+
#if TEST_STD_VER <= 14
105+
std::get_unexpected(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
106+
#endif
107+
108+
std::get_terminate(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
109+
110+
#if _LIBCPP_STD_VER <= 17
111+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
112+
std::uncaught_exception();
113+
#endif
114+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
115+
std::uncaught_exceptions();
116+
117+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
118+
std::current_exception();
119+
}
120+
121+
#if TEST_STD_VER >= 11
84122
{ // <initializer_list>
85123
std::initializer_list<int> il{94, 82, 49};
86124

87125
il.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
88126
il.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
89127
il.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
90128
}
129+
#endif
91130
}

0 commit comments

Comments
 (0)