diff --git a/libcxx/include/regex b/libcxx/include/regex index b6c19518be301..89370583c9a04 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -986,7 +986,7 @@ public: explicit regex_error(regex_constants::error_type __ecode); _LIBCPP_HIDE_FROM_ABI regex_error(const regex_error&) _NOEXCEPT = default; ~regex_error() _NOEXCEPT override; - _LIBCPP_HIDE_FROM_ABI regex_constants::error_type code() const { return __code_; } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI regex_constants::error_type code() const { return __code_; } }; template @@ -2412,16 +2412,16 @@ public: # endif // _LIBCPP_CXX03_LANG // const operations: - _LIBCPP_HIDE_FROM_ABI unsigned mark_count() const { return __marked_count_; } - _LIBCPP_HIDE_FROM_ABI flag_type flags() const { return __flags_; } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unsigned mark_count() const { return __marked_count_; } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI flag_type flags() const { return __flags_; } // locale: - _LIBCPP_HIDE_FROM_ABI locale_type imbue(locale_type __loc) { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI locale_type imbue(locale_type __loc) { __member_init(ECMAScript); __start_.reset(); return __traits_.imbue(__loc); } - _LIBCPP_HIDE_FROM_ABI locale_type getloc() const { return __traits_.getloc(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI locale_type getloc() const { return __traits_.getloc(); } // swap: void swap(basic_regex& __r); @@ -4206,17 +4206,17 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR sub_match() : matched() {} - _LIBCPP_HIDE_FROM_ABI difference_type length() const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI difference_type length() const { return matched ? std::distance(this->first, this->second) : 0; } - _LIBCPP_HIDE_FROM_ABI string_type str() const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI string_type str() const { return matched ? string_type(this->first, this->second) : string_type(); } _LIBCPP_HIDE_FROM_ABI operator string_type() const { return str(); } - _LIBCPP_HIDE_FROM_ABI int compare(const sub_match& __s) const { return str().compare(__s.str()); } - _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return str().compare(__s); } - _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return str().compare(__s); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int compare(const sub_match& __s) const { return str().compare(__s.str()); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int compare(const string_type& __s) const { return str().compare(__s); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int compare(const value_type* __s) const { return str().compare(__s); } _LIBCPP_HIDE_FROM_ABI void swap(sub_match& __s) _NOEXCEPT_(__is_nothrow_swappable_v<_BidirectionalIterator>) { this->pair<_BidirectionalIterator, _BidirectionalIterator>::swap(__s); @@ -4581,49 +4581,53 @@ public: _LIBCPP_HIDE_FROM_ABI bool ready() const { return __ready_; } // size: - _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __matches_.size(); } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __matches_.max_size(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __matches_.size(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __matches_.max_size(); } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return size() == 0; } // element access: - _LIBCPP_HIDE_FROM_ABI difference_type length(size_type __sub = 0) const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI difference_type length(size_type __sub = 0) const { // If the match results are not ready, this will return `0`. _LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::length() called when not ready"); return (*this)[__sub].length(); } - _LIBCPP_HIDE_FROM_ABI difference_type position(size_type __sub = 0) const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI difference_type position(size_type __sub = 0) const { // If the match results are not ready, this will return the result of subtracting two default-constructed iterators // (which is typically a well-defined operation). _LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::position() called when not ready"); return std::distance(__position_start_, (*this)[__sub].first); } - _LIBCPP_HIDE_FROM_ABI string_type str(size_type __sub = 0) const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI string_type str(size_type __sub = 0) const { // If the match results are not ready, this will return an empty string. _LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::str() called when not ready"); return (*this)[__sub].str(); } - _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const { // If the match results are not ready, this call will be equivalent to calling this function with `__n >= size()`, // returning an empty subrange. _LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::operator[]() called when not ready"); return __n < __matches_.size() ? __matches_[__n] : __unmatched_; } - _LIBCPP_HIDE_FROM_ABI const_reference prefix() const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reference prefix() const { // If the match results are not ready, this will return a default-constructed empty `__suffix_`. _LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::prefix() called when not ready"); return __prefix_; } - _LIBCPP_HIDE_FROM_ABI const_reference suffix() const { + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reference suffix() const { // If the match results are not ready, this will return a default-constructed empty `__suffix_`. _LIBCPP_ASSERT_PEDANTIC(ready(), "match_results::suffix() called when not ready"); return __suffix_; } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const { return empty() ? __matches_.end() : __matches_.begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __matches_.end(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const { return empty() ? __matches_.end() : __matches_.begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const { return __matches_.end(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const { + return empty() ? __matches_.end() : __matches_.begin(); + } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __matches_.end(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const { + return empty() ? __matches_.end() : __matches_.begin(); + } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const { return __matches_.end(); } // format: template @@ -4639,14 +4643,14 @@ public: return format(__output_iter, __fmt.data(), __fmt.data() + __fmt.size(), __flags); } template - _LIBCPP_HIDE_FROM_ABI basic_string + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_string format(const basic_string& __fmt, regex_constants::match_flag_type __flags = regex_constants::format_default) const { basic_string __r; format(std::back_inserter(__r), __fmt.data(), __fmt.data() + __fmt.size(), __flags); return __r; } - _LIBCPP_HIDE_FROM_ABI string_type + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI string_type format(const char_type* __fmt, regex_constants::match_flag_type __flags = regex_constants::format_default) const { string_type __r; format(std::back_inserter(__r), __fmt, __fmt + char_traits::length(__fmt), __flags); @@ -4654,7 +4658,7 @@ public: } // allocator: - _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return __matches_.get_allocator(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return __matches_.get_allocator(); } // swap: void swap(match_results& __m); @@ -5375,7 +5379,7 @@ public: _LIBCPP_HIDE_FROM_ABI bool operator!=(const regex_iterator& __x) const { return !(*this == __x); } # endif - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __match_; } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __match_; } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return std::addressof(__match_); } regex_iterator& operator++(); @@ -5556,7 +5560,7 @@ public: _LIBCPP_HIDE_FROM_ABI bool operator!=(const regex_token_iterator& __x) const { return !(*this == __x); } # endif - _LIBCPP_HIDE_FROM_ABI const value_type& operator*() const { return *__result_; } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const value_type& operator*() const { return *__result_; } _LIBCPP_HIDE_FROM_ABI const value_type* operator->() const { return __result_; } regex_token_iterator& operator++(); diff --git a/libcxx/test/libcxx/diagnostics/regex.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/regex.nodiscard.verify.cpp index 0959ec5e26bd6..1d989fe14b1f9 100644 --- a/libcxx/test/libcxx/diagnostics/regex.nodiscard.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/regex.nodiscard.verify.cpp @@ -6,15 +6,77 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++03 +// REQUIRES: std-at-least-c++11 // UNSUPPORTED: no-localization // check that functions are marked [[nodiscard]] #include +#include void test() { - std::cmatch match_result; - match_result.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + { + std::basic_regex re; + + re.mark_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + re.flags(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + re.imbue({}); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + re.getloc(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + } + { + std::sub_match sm; + + sm.length(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + sm.str(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + sm.compare(sm); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + sm.compare(std::string{}); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + sm.compare(""); + } + { + std::match_results m; + + m.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + m.length(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m.position(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m.str(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + m.prefix(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m.suffix(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + m.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + m.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + m.format(std::string{}); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + m.format(""); + } + { + std::regex_iterator ri; + + *ri; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + } + { + std::regex_token_iterator rti; + + *rti; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + } + { + std::regex_error err{std::regex_constants::error_backref}; + + err.code(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + } }