Skip to content

Commit 6d621ea

Browse files
[libc++][char_traits] 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 - https://wg21.link/char.traits
1 parent 00b92e3 commit 6d621ea

File tree

2 files changed

+98
-31
lines changed

2 files changed

+98
-31
lines changed

libcxx/include/__string/char_traits.h

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,17 @@ struct char_traits<char> {
9494
}
9595

9696
// TODO: Make this _LIBCPP_HIDE_FROM_ABI
97-
static inline _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {
97+
[[__nodiscard__]] static inline _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {
9898
return __c1 == __c2;
9999
}
100-
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {
100+
[[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
101+
lt(char_type __c1, char_type __c2) _NOEXCEPT {
101102
return (unsigned char)__c1 < (unsigned char)__c2;
102103
}
103104

104105
// __constexpr_memcmp requires a trivially lexicographically comparable type, but char is not when char is a signed
105106
// type
106-
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
107+
[[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
107108
compare(const char_type* __lhs, const char_type* __rhs, size_t __count) _NOEXCEPT {
108109
if (__libcpp_is_constant_evaluated()) {
109110
#ifdef _LIBCPP_COMPILER_CLANG_BASED
@@ -126,11 +127,12 @@ struct char_traits<char> {
126127
}
127128
}
128129

129-
static inline _LIBCPP_HIDE_FROM_ABI size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT {
130+
[[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI size_t _LIBCPP_CONSTEXPR_SINCE_CXX17
131+
length(const char_type* __s) _NOEXCEPT {
130132
return std::__constexpr_strlen(__s);
131133
}
132134

133-
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
135+
[[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
134136
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
135137
return std::__constexpr_memchr(__s, __a, __n);
136138
}
@@ -154,19 +156,24 @@ struct char_traits<char> {
154156
return __s;
155157
}
156158

157-
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
159+
[[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
158160
return eq_int_type(__c, eof()) ? ~eof() : __c;
159161
}
160-
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
162+
[[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type
163+
to_char_type(int_type __c) _NOEXCEPT {
161164
return char_type(__c);
162165
}
163-
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {
166+
[[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
167+
to_int_type(char_type __c) _NOEXCEPT {
164168
return int_type((unsigned char)__c);
165169
}
166-
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {
170+
[[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
171+
eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {
167172
return __c1 == __c2;
168173
}
169-
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(EOF); }
174+
[[__nodiscard__]] static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT {
175+
return int_type(EOF);
176+
}
170177
};
171178

172179
template <class _CharT, class _IntT, _IntT _EOFVal>
@@ -187,11 +194,11 @@ struct __char_traits_base {
187194
__lhs = __rhs;
188195
}
189196

190-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq(char_type __lhs, char_type __rhs) _NOEXCEPT {
197+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq(char_type __lhs, char_type __rhs) _NOEXCEPT {
191198
return __lhs == __rhs;
192199
}
193200

194-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool lt(char_type __lhs, char_type __rhs) _NOEXCEPT {
201+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool lt(char_type __lhs, char_type __rhs) _NOEXCEPT {
195202
return __lhs < __rhs;
196203
}
197204

@@ -213,19 +220,22 @@ struct __char_traits_base {
213220
return __str;
214221
}
215222

216-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
223+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
217224
return char_type(__c);
218225
}
219226

220-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT { return int_type(__c); }
227+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {
228+
return int_type(__c);
229+
}
221230

222-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq_int_type(int_type __lhs, int_type __rhs) _NOEXCEPT {
231+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool
232+
eq_int_type(int_type __lhs, int_type __rhs) _NOEXCEPT {
223233
return __lhs == __rhs;
224234
}
225235

226-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return _EOFVal; }
236+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return _EOFVal; }
227237

228-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
238+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
229239
return eq_int_type(__c, eof()) ? static_cast<int_type>(~eof()) : __c;
230240
}
231241
};
@@ -235,18 +245,19 @@ struct __char_traits_base {
235245
#if _LIBCPP_HAS_WIDE_CHARACTERS
236246
template <>
237247
struct char_traits<wchar_t> : __char_traits_base<wchar_t, wint_t, static_cast<wint_t>(WEOF)> {
238-
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
248+
[[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
239249
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
240250
if (__n == 0)
241251
return 0;
242252
return std::__constexpr_wmemcmp(__s1, __s2, __n);
243253
}
244254

245-
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT {
255+
[[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
256+
length(const char_type* __s) _NOEXCEPT {
246257
return std::__constexpr_wcslen(__s);
247258
}
248259

249-
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
260+
[[__nodiscard__]] static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
250261
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
251262
return std::__constexpr_wmemchr(__s, __a, __n);
252263
}
@@ -257,16 +268,16 @@ struct char_traits<wchar_t> : __char_traits_base<wchar_t, wint_t, static_cast<wi
257268

258269
template <>
259270
struct char_traits<char8_t> : __char_traits_base<char8_t, unsigned int, static_cast<unsigned int>(EOF)> {
260-
static _LIBCPP_HIDE_FROM_ABI constexpr int
271+
[[nodiscard]] static _LIBCPP_HIDE_FROM_ABI constexpr int
261272
compare(const char_type* __s1, const char_type* __s2, size_t __n) noexcept {
262273
return std::__constexpr_memcmp(__s1, __s2, __element_count(__n));
263274
}
264275

265-
static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __str) noexcept {
276+
[[nodiscard]] static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __str) noexcept {
266277
return std::__constexpr_strlen(__str);
267278
}
268279

269-
_LIBCPP_HIDE_FROM_ABI static constexpr const char_type*
280+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr const char_type*
270281
find(const char_type* __s, size_t __n, const char_type& __a) noexcept {
271282
return std::__constexpr_memchr(__s, __a, __n);
272283
}
@@ -276,11 +287,11 @@ struct char_traits<char8_t> : __char_traits_base<char8_t, unsigned int, static_c
276287

277288
template <>
278289
struct char_traits<char16_t> : __char_traits_base<char16_t, uint_least16_t, static_cast<uint_least16_t>(0xFFFF)> {
279-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
290+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
280291
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
281292
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
282293

283-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
294+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
284295
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
285296
__identity __proj;
286297
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
290301
}
291302
};
292303

293-
inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
304+
[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
294305
char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
295306
for (; __n; --__n, ++__s1, ++__s2) {
296307
if (lt(*__s1, *__s2))
@@ -301,7 +312,8 @@ char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, siz
301312
return 0;
302313
}
303314

304-
inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT {
315+
[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
316+
char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT {
305317
size_t __len = 0;
306318
for (; !eq(*__s, char_type(0)); ++__s)
307319
++__len;
@@ -310,11 +322,11 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char16_t>::length(const
310322

311323
template <>
312324
struct char_traits<char32_t> : __char_traits_base<char32_t, uint_least32_t, static_cast<uint_least32_t>(0xFFFFFFFF)> {
313-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
325+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
314326
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
315327
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
316328

317-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
329+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
318330
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
319331
__identity __proj;
320332
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
324336
}
325337
};
326338

327-
inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
339+
[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
328340
char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
329341
for (; __n; --__n, ++__s1, ++__s2) {
330342
if (lt(*__s1, *__s2))
@@ -335,7 +347,8 @@ char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, siz
335347
return 0;
336348
}
337349

338-
inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT {
350+
[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
351+
char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT {
339352
size_t __len = 0;
340353
for (; !eq(*__s, char_type(0)); ++__s)
341354
++__len;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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 <string>
12+
13+
#include "test_macros.h"
14+
15+
template <class CharT>
16+
void test() {
17+
typedef std::char_traits<CharT> traits;
18+
typedef typename traits::int_type int_t;
19+
20+
const CharT buf[1] = {};
21+
22+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
23+
traits::eq(CharT(), CharT());
24+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
25+
traits::lt(CharT(), CharT());
26+
27+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
28+
traits::compare(buf, buf, 0);
29+
traits::length(buf); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
30+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
31+
traits::find(buf, 0, CharT());
32+
33+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
34+
traits::not_eof(CharT());
35+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
36+
traits::to_char_type(int_t());
37+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
38+
traits::to_int_type(CharT());
39+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
40+
traits::eq_int_type(int_t(), int_t());
41+
traits::eof(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
42+
}
43+
44+
void test() {
45+
test<char>();
46+
#ifndef TEST_HAS_NO_CHAR8_T
47+
test<char8_t>();
48+
#endif
49+
test<char16_t>();
50+
test<char32_t>();
51+
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
52+
test<wchar_t>();
53+
#endif
54+
}

0 commit comments

Comments
 (0)