Skip to content

Commit b739452

Browse files
committed
[libc++][regex] Applied [[nodiscard]]
`[[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 979462c commit b739452

File tree

2 files changed

+96
-30
lines changed

2 files changed

+96
-30
lines changed

libcxx/include/regex

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,7 @@ public:
986986
explicit regex_error(regex_constants::error_type __ecode);
987987
_LIBCPP_HIDE_FROM_ABI regex_error(const regex_error&) _NOEXCEPT = default;
988988
~regex_error() _NOEXCEPT override;
989-
_LIBCPP_HIDE_FROM_ABI regex_constants::error_type code() const { return __code_; }
989+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI regex_constants::error_type code() const { return __code_; }
990990
};
991991

992992
template <regex_constants::error_type _Ev>
@@ -2412,16 +2412,16 @@ public:
24122412
# endif // _LIBCPP_CXX03_LANG
24132413

24142414
// const operations:
2415-
_LIBCPP_HIDE_FROM_ABI unsigned mark_count() const { return __marked_count_; }
2416-
_LIBCPP_HIDE_FROM_ABI flag_type flags() const { return __flags_; }
2415+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unsigned mark_count() const { return __marked_count_; }
2416+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI flag_type flags() const { return __flags_; }
24172417

24182418
// locale:
2419-
_LIBCPP_HIDE_FROM_ABI locale_type imbue(locale_type __loc) {
2419+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI locale_type imbue(locale_type __loc) {
24202420
__member_init(ECMAScript);
24212421
__start_.reset();
24222422
return __traits_.imbue(__loc);
24232423
}
2424-
_LIBCPP_HIDE_FROM_ABI locale_type getloc() const { return __traits_.getloc(); }
2424+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI locale_type getloc() const { return __traits_.getloc(); }
24252425

24262426
// swap:
24272427
void swap(basic_regex& __r);
@@ -4206,17 +4206,17 @@ public:
42064206

42074207
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR sub_match() : matched() {}
42084208

4209-
_LIBCPP_HIDE_FROM_ABI difference_type length() const {
4209+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI difference_type length() const {
42104210
return matched ? std::distance(this->first, this->second) : 0;
42114211
}
4212-
_LIBCPP_HIDE_FROM_ABI string_type str() const {
4212+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI string_type str() const {
42134213
return matched ? string_type(this->first, this->second) : string_type();
42144214
}
42154215
_LIBCPP_HIDE_FROM_ABI operator string_type() const { return str(); }
42164216

4217-
_LIBCPP_HIDE_FROM_ABI int compare(const sub_match& __s) const { return str().compare(__s.str()); }
4218-
_LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return str().compare(__s); }
4219-
_LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return str().compare(__s); }
4217+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int compare(const sub_match& __s) const { return str().compare(__s.str()); }
4218+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return str().compare(__s); }
4219+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return str().compare(__s); }
42204220

42214221
_LIBCPP_HIDE_FROM_ABI void swap(sub_match& __s) _NOEXCEPT_(__is_nothrow_swappable_v<_BidirectionalIterator>) {
42224222
this->pair<_BidirectionalIterator, _BidirectionalIterator>::swap(__s);
@@ -4581,49 +4581,53 @@ public:
45814581
_LIBCPP_HIDE_FROM_ABI bool ready() const { return __ready_; }
45824582

45834583
// size:
4584-
_LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __matches_.size(); }
4585-
_LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __matches_.max_size(); }
4584+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __matches_.size(); }
4585+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __matches_.max_size(); }
45864586
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return size() == 0; }
45874587

45884588
// element access:
4589-
_LIBCPP_HIDE_FROM_ABI difference_type length(size_type __sub = 0) const {
4589+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI difference_type length(size_type __sub = 0) const {
45904590
// If the match results are not ready, this will return `0`.
45914591
_LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::length() called when not ready");
45924592
return (*this)[__sub].length();
45934593
}
4594-
_LIBCPP_HIDE_FROM_ABI difference_type position(size_type __sub = 0) const {
4594+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI difference_type position(size_type __sub = 0) const {
45954595
// If the match results are not ready, this will return the result of subtracting two default-constructed iterators
45964596
// (which is typically a well-defined operation).
45974597
_LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::position() called when not ready");
45984598
return std::distance(__position_start_, (*this)[__sub].first);
45994599
}
4600-
_LIBCPP_HIDE_FROM_ABI string_type str(size_type __sub = 0) const {
4600+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI string_type str(size_type __sub = 0) const {
46014601
// If the match results are not ready, this will return an empty string.
46024602
_LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::str() called when not ready");
46034603
return (*this)[__sub].str();
46044604
}
4605-
_LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const {
4605+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const {
46064606
// If the match results are not ready, this call will be equivalent to calling this function with `__n >= size()`,
46074607
// returning an empty subrange.
46084608
_LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::operator[]() called when not ready");
46094609
return __n < __matches_.size() ? __matches_[__n] : __unmatched_;
46104610
}
46114611

4612-
_LIBCPP_HIDE_FROM_ABI const_reference prefix() const {
4612+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reference prefix() const {
46134613
// If the match results are not ready, this will return a default-constructed empty `__suffix_`.
46144614
_LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::prefix() called when not ready");
46154615
return __prefix_;
46164616
}
4617-
_LIBCPP_HIDE_FROM_ABI const_reference suffix() const {
4617+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reference suffix() const {
46184618
// If the match results are not ready, this will return a default-constructed empty `__suffix_`.
46194619
_LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::suffix() called when not ready");
46204620
return __suffix_;
46214621
}
46224622

4623-
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const { return empty() ? __matches_.end() : __matches_.begin(); }
4624-
_LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __matches_.end(); }
4625-
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const { return empty() ? __matches_.end() : __matches_.begin(); }
4626-
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const { return __matches_.end(); }
4623+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const {
4624+
return empty() ? __matches_.end() : __matches_.begin();
4625+
}
4626+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __matches_.end(); }
4627+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const {
4628+
return empty() ? __matches_.end() : __matches_.begin();
4629+
}
4630+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const { return __matches_.end(); }
46274631

46284632
// format:
46294633
template <class _OutputIter>
@@ -4639,22 +4643,22 @@ public:
46394643
return format(__output_iter, __fmt.data(), __fmt.data() + __fmt.size(), __flags);
46404644
}
46414645
template <class _ST, class _SA>
4642-
_LIBCPP_HIDE_FROM_ABI basic_string<char_type, _ST, _SA>
4646+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_string<char_type, _ST, _SA>
46434647
format(const basic_string<char_type, _ST, _SA>& __fmt,
46444648
regex_constants::match_flag_type __flags = regex_constants::format_default) const {
46454649
basic_string<char_type, _ST, _SA> __r;
46464650
format(std::back_inserter(__r), __fmt.data(), __fmt.data() + __fmt.size(), __flags);
46474651
return __r;
46484652
}
4649-
_LIBCPP_HIDE_FROM_ABI string_type
4653+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI string_type
46504654
format(const char_type* __fmt, regex_constants::match_flag_type __flags = regex_constants::format_default) const {
46514655
string_type __r;
46524656
format(std::back_inserter(__r), __fmt, __fmt + char_traits<char_type>::length(__fmt), __flags);
46534657
return __r;
46544658
}
46554659

46564660
// allocator:
4657-
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return __matches_.get_allocator(); }
4661+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return __matches_.get_allocator(); }
46584662

46594663
// swap:
46604664
void swap(match_results& __m);
@@ -5375,7 +5379,7 @@ public:
53755379
_LIBCPP_HIDE_FROM_ABI bool operator!=(const regex_iterator& __x) const { return !(*this == __x); }
53765380
# endif
53775381

5378-
_LIBCPP_HIDE_FROM_ABI reference operator*() const { return __match_; }
5382+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __match_; }
53795383
_LIBCPP_HIDE_FROM_ABI pointer operator->() const { return std::addressof(__match_); }
53805384

53815385
regex_iterator& operator++();
@@ -5556,7 +5560,7 @@ public:
55565560
_LIBCPP_HIDE_FROM_ABI bool operator!=(const regex_token_iterator& __x) const { return !(*this == __x); }
55575561
# endif
55585562

5559-
_LIBCPP_HIDE_FROM_ABI const value_type& operator*() const { return *__result_; }
5563+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const value_type& operator*() const { return *__result_; }
55605564
_LIBCPP_HIDE_FROM_ABI const value_type* operator->() const { return __result_; }
55615565

55625566
regex_token_iterator& operator++();

libcxx/test/libcxx/diagnostics/regex.nodiscard.verify.cpp

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,77 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03
9+
// REQUIRES: std-at-least-c++11
1010

1111
// UNSUPPORTED: no-localization
1212

1313
// check that <regex> functions are marked [[nodiscard]]
1414

1515
#include <regex>
16+
#include <string>
1617

1718
void test() {
18-
std::cmatch match_result;
19-
match_result.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
19+
{
20+
std::basic_regex<char> re;
21+
22+
re.mark_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
23+
re.flags(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
24+
25+
re.imbue({}); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
26+
27+
re.getloc(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
28+
}
29+
{
30+
std::sub_match<const char*> sm;
31+
32+
sm.length(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
33+
sm.str(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
34+
35+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
36+
sm.compare(sm);
37+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
38+
sm.compare(std::string{});
39+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
40+
sm.compare("");
41+
}
42+
{
43+
std::match_results<const char*> m;
44+
45+
m.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
46+
m.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
47+
m.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
48+
49+
m.length(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
50+
m.position(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
51+
m.str(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
52+
m[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
53+
54+
m.prefix(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
55+
m.suffix(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
56+
57+
m.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
58+
m.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
59+
m.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
60+
m.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
61+
62+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
63+
m.format(std::string{});
64+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
65+
m.format("");
66+
}
67+
{
68+
std::regex_iterator<const char*> ri;
69+
70+
*ri; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
71+
}
72+
{
73+
std::regex_token_iterator<const char*> rti;
74+
75+
*rti; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
76+
}
77+
{
78+
std::regex_error err{std::regex_constants::error_backref};
79+
80+
err.code(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
81+
}
2082
}

0 commit comments

Comments
 (0)