Skip to content

Commit d038525

Browse files
committed
[libc++] Applied [[nodiscard] to <exception>, <stdexcept> and <system_error>
[[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 38678a9 commit d038525

File tree

10 files changed

+170
-28
lines changed

10 files changed

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

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88

99
// UNSUPPORTED: c++03
1010

11+
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS
12+
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION
13+
1114
// Check that functions are marked [[nodiscard]]
1215

1316
#include <compare>
1417
#include <coroutine>
18+
#include <exception>
1519
#include <functional>
1620
#include <initializer_list>
1721

@@ -81,6 +85,32 @@ void test() {
8185
}
8286
#endif
8387

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

0 commit comments

Comments
 (0)