-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[libc++][char_traits] Applied [[nodiscard]]
#172244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++][char_traits] Applied [[nodiscard]]
#172244
Conversation
|
@llvm/pr-subscribers-libcxx Author: A. Jiang (frederick-vs-ja) Changes
Full diff: https://github.com/llvm/llvm-project/pull/172244.diff 2 Files Affected:
diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h
index 8292750919427..4bf5b34e75894 100644
--- a/libcxx/include/__string/char_traits.h
+++ b/libcxx/include/__string/char_traits.h
@@ -94,16 +94,17 @@ struct char_traits<char> {
}
// TODO: Make this _LIBCPP_HIDE_FROM_ABI
- static inline _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {
+ [[__nodiscard__]] static inline _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {
return __c1 == __c2;
}
- static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {
+ [[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
+ lt(char_type __c1, char_type __c2) _NOEXCEPT {
return (unsigned char)__c1 < (unsigned char)__c2;
}
// __constexpr_memcmp requires a trivially lexicographically comparable type, but char is not when char is a signed
// type
- static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
+ [[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __lhs, const char_type* __rhs, size_t __count) _NOEXCEPT {
if (__libcpp_is_constant_evaluated()) {
#ifdef _LIBCPP_COMPILER_CLANG_BASED
@@ -126,11 +127,12 @@ struct char_traits<char> {
}
}
- static inline _LIBCPP_HIDE_FROM_ABI size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT {
+ [[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI size_t _LIBCPP_CONSTEXPR_SINCE_CXX17
+ length(const char_type* __s) _NOEXCEPT {
return std::__constexpr_strlen(__s);
}
- static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
+ [[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
return std::__constexpr_memchr(__s, __a, __n);
}
@@ -154,19 +156,24 @@ struct char_traits<char> {
return __s;
}
- static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
+ [[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
return eq_int_type(__c, eof()) ? ~eof() : __c;
}
- static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
+ [[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type
+ to_char_type(int_type __c) _NOEXCEPT {
return char_type(__c);
}
- static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {
+ [[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
+ to_int_type(char_type __c) _NOEXCEPT {
return int_type((unsigned char)__c);
}
- static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {
+ [[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
+ eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {
return __c1 == __c2;
}
- static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(EOF); }
+ [[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT {
+ return int_type(EOF);
+ }
};
template <class _CharT, class _IntT, _IntT _EOFVal>
@@ -187,11 +194,11 @@ struct __char_traits_base {
__lhs = __rhs;
}
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq(char_type __lhs, char_type __rhs) _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq(char_type __lhs, char_type __rhs) _NOEXCEPT {
return __lhs == __rhs;
}
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool lt(char_type __lhs, char_type __rhs) _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool lt(char_type __lhs, char_type __rhs) _NOEXCEPT {
return __lhs < __rhs;
}
@@ -213,19 +220,22 @@ struct __char_traits_base {
return __str;
}
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
return char_type(__c);
}
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT { return int_type(__c); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {
+ return int_type(__c);
+ }
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq_int_type(int_type __lhs, int_type __rhs) _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool
+ eq_int_type(int_type __lhs, int_type __rhs) _NOEXCEPT {
return __lhs == __rhs;
}
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return _EOFVal; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return _EOFVal; }
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
return eq_int_type(__c, eof()) ? static_cast<int_type>(~eof()) : __c;
}
};
@@ -235,18 +245,19 @@ struct __char_traits_base {
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
struct char_traits<wchar_t> : __char_traits_base<wchar_t, wint_t, static_cast<wint_t>(WEOF)> {
- static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
+ [[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
if (__n == 0)
return 0;
return std::__constexpr_wmemcmp(__s1, __s2, __n);
}
- static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT {
+ [[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
+ length(const char_type* __s) _NOEXCEPT {
return std::__constexpr_wcslen(__s);
}
- static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
+ [[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
return std::__constexpr_wmemchr(__s, __a, __n);
}
@@ -258,15 +269,15 @@ struct char_traits<wchar_t> : __char_traits_base<wchar_t, wint_t, static_cast<wi
template <>
struct char_traits<char8_t> : __char_traits_base<char8_t, unsigned int, static_cast<unsigned int>(EOF)> {
static _LIBCPP_HIDE_FROM_ABI constexpr int
- compare(const char_type* __s1, const char_type* __s2, size_t __n) noexcept {
+ [[__nodiscard__]] compare(const char_type* __s1, const char_type* __s2, size_t __n) noexcept {
return std::__constexpr_memcmp(__s1, __s2, __element_count(__n));
}
- static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __str) noexcept {
+ [[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __str) noexcept {
return std::__constexpr_strlen(__str);
}
- _LIBCPP_HIDE_FROM_ABI static constexpr const char_type*
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static constexpr const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) noexcept {
return std::__constexpr_memchr(__s, __a, __n);
}
@@ -276,11 +287,11 @@ struct char_traits<char8_t> : __char_traits_base<char8_t, unsigned int, static_c
template <>
struct char_traits<char16_t> : __char_traits_base<char16_t, uint_least16_t, static_cast<uint_least16_t>(0xFFFF)> {
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
__identity __proj;
const char_type* __match = std::__find(__s, __s + __n, __a, __proj);
@@ -290,7 +301,7 @@ struct char_traits<char16_t> : __char_traits_base<char16_t, uint_least16_t, stat
}
};
-inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
for (; __n; --__n, ++__s1, ++__s2) {
if (lt(*__s1, *__s2))
@@ -301,7 +312,8 @@ char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, siz
return 0;
}
-inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
+char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT {
size_t __len = 0;
for (; !eq(*__s, char_type(0)); ++__s)
++__len;
@@ -310,11 +322,11 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char16_t>::length(const
template <>
struct char_traits<char32_t> : __char_traits_base<char32_t, uint_least32_t, static_cast<uint_least32_t>(0xFFFFFFFF)> {
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
__identity __proj;
const char_type* __match = std::__find(__s, __s + __n, __a, __proj);
@@ -324,7 +336,7 @@ struct char_traits<char32_t> : __char_traits_base<char32_t, uint_least32_t, stat
}
};
-inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
for (; __n; --__n, ++__s1, ++__s2) {
if (lt(*__s1, *__s2))
@@ -335,7 +347,8 @@ char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, siz
return 0;
}
-inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
+char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT {
size_t __len = 0;
for (; !eq(*__s, char_type(0)); ++__s)
++__len;
diff --git a/libcxx/test/libcxx/strings/char.traits/nodiscard.verify.cpp b/libcxx/test/libcxx/strings/char.traits/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..b443b105bb464
--- /dev/null
+++ b/libcxx/test/libcxx/strings/char.traits/nodiscard.verify.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Check that functions are marked [[nodiscard]]
+
+#include <string>
+
+#include "test_macros.h"
+
+template <class CharT>
+void test() {
+ typedef std::char_traits<CharT> traits;
+ typedef typename traits::int_type int_t;
+
+ const CharT buf[1] = {};
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ traits::eq(CharT(), CharT());
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ traits::lt(CharT(), CharT());
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ traits::compare(buf, buf, 0);
+ traits::length(buf); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ traits::find(buf, 0, CharT());
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ traits::not_eof(CharT());
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ traits::to_char_type(int_t());
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ traits::to_int_type(CharT());
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ traits::eq_int_type(int_t(), int_t());
+ traits::eof(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+}
+
+void test() {
+ test<char>();
+#ifndef TEST_HAS_NO_CHAR8_T
+ test<char8_t>();
+#endif
+ test<char16_t>();
+ test<char32_t>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ test<wchar_t>();
+#endif
+}
|
6d621ea to
27749ba
Compare
`[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html - https://wg21.link/char.traits
27749ba to
8c730d2
Compare
| template <> | ||
| struct char_traits<char8_t> : __char_traits_base<char8_t, unsigned int, static_cast<unsigned int>(EOF)> { | ||
| static _LIBCPP_HIDE_FROM_ABI constexpr int | ||
| [[nodiscard]] static _LIBCPP_HIDE_FROM_ABI constexpr int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for review: Non-uglified nodiscard occurrences can only appear since C++20 currently, while other uglified __nodiscard__ occurrences can appear in C++03.
| #ifndef TEST_HAS_NO_CHAR8_T | ||
| void test_char8_t() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for review: I attempted to use a function template to handle five character types. However, the count of expected warnings varies in different modes, and it's infeasible to write the different counts in comments. As a result, I chose to repeat the function body 5 times.
Zingam
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks for catching this omission!
[[nodiscard]]should be applied to functions where discarding the return value is most likely a correctness issue.