1 | // RUN: %check_clang_tidy -std=c++17-or-later %s modernize-use-nodiscard %t -- \ |
2 | // RUN: -config="{CheckOptions: {modernize-use-nodiscard.ReplacementString: 'NO_DISCARD'}}" |
3 | |
4 | namespace std { |
5 | template <class> |
6 | class function; |
7 | class string {}; |
8 | } |
9 | |
10 | namespace boost { |
11 | template <class> |
12 | class function; |
13 | } |
14 | |
15 | #define MUST_USE_RESULT __attribute__((warn_unused_result)) |
16 | #define NO_DISCARD [[nodiscard]] |
17 | #define NO_RETURN [[noreturn]] |
18 | |
19 | #define BOOLEAN_FUNC bool f23() const |
20 | |
21 | typedef unsigned my_unsigned; |
22 | typedef unsigned &my_unsigned_reference; |
23 | typedef const unsigned &my_unsigned_const_reference; |
24 | |
25 | struct NO_DISCARD NoDiscardStruct{}; |
26 | |
27 | class Foo { |
28 | public: |
29 | using size_type = unsigned; |
30 | |
31 | bool f1() const; |
32 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f1' should be marked NO_DISCARD [modernize-use-nodiscard] |
33 | // CHECK-FIXES: NO_DISCARD bool f1() const; |
34 | |
35 | bool f2(int) const; |
36 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f2' should be marked NO_DISCARD [modernize-use-nodiscard] |
37 | // CHECK-FIXES: NO_DISCARD bool f2(int) const; |
38 | |
39 | bool f3(const int &) const; |
40 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' should be marked NO_DISCARD [modernize-use-nodiscard] |
41 | // CHECK-FIXES: NO_DISCARD bool f3(const int &) const; |
42 | |
43 | bool f4(void) const; |
44 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f4' should be marked NO_DISCARD [modernize-use-nodiscard] |
45 | // CHECK-FIXES: NO_DISCARD bool f4(void) const; |
46 | |
47 | // negative tests |
48 | |
49 | void f5() const; |
50 | |
51 | bool f6(); |
52 | |
53 | bool f7(int &); |
54 | |
55 | bool f8(int &) const; |
56 | |
57 | bool f9(int *) const; |
58 | |
59 | bool f10(const int &, int &) const; |
60 | |
61 | NO_DISCARD bool f12() const; |
62 | |
63 | MUST_USE_RESULT bool f13() const; |
64 | |
65 | [[nodiscard]] bool f11() const; |
66 | |
67 | [[clang::warn_unused_result]] bool f11a() const; |
68 | |
69 | [[gnu::warn_unused_result]] bool f11b() const; |
70 | |
71 | bool _f20() const; |
72 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function '_f20' should be marked NO_DISCARD [modernize-use-nodiscard] |
73 | // CHECK-FIXES: NO_DISCARD bool _f20() const; |
74 | |
75 | NO_RETURN bool f21() const; |
76 | |
77 | ~Foo(); |
78 | |
79 | bool operator+=(int) const; |
80 | |
81 | // extra keywords (virtual,inline,const) on return type |
82 | |
83 | virtual bool f14() const; |
84 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f14' should be marked NO_DISCARD [modernize-use-nodiscard] |
85 | // CHECK-FIXES: NO_DISCARD virtual bool f14() const; |
86 | |
87 | const bool f15() const; |
88 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f15' should be marked NO_DISCARD [modernize-use-nodiscard] |
89 | // CHECK-FIXES: NO_DISCARD const bool f15() const; |
90 | |
91 | inline const bool f16() const; |
92 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f16' should be marked NO_DISCARD [modernize-use-nodiscard] |
93 | // CHECK-FIXES: NO_DISCARD inline const bool f16() const; |
94 | |
95 | inline const std::string &f45() const; |
96 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f45' should be marked NO_DISCARD [modernize-use-nodiscard] |
97 | // CHECK-FIXES: NO_DISCARD inline const std::string &f45() const; |
98 | |
99 | inline virtual const bool f17() const; |
100 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f17' should be marked NO_DISCARD [modernize-use-nodiscard] |
101 | // CHECK-FIXES: NO_DISCARD inline virtual const bool f17() const; |
102 | |
103 | // inline with body |
104 | bool f18() const |
105 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f18' should be marked NO_DISCARD [modernize-use-nodiscard] |
106 | // CHECK-FIXES: NO_DISCARD bool f18() const |
107 | { |
108 | return true; |
109 | } |
110 | |
111 | bool f19() const; |
112 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f19' should be marked NO_DISCARD [modernize-use-nodiscard] |
113 | // CHECK-FIXES: NO_DISCARD bool f19() const; |
114 | |
115 | BOOLEAN_FUNC; |
116 | |
117 | bool f24(size_type) const; |
118 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f24' should be marked NO_DISCARD [modernize-use-nodiscard] |
119 | // CHECK-FIXES: NO_DISCARD bool f24(size_type) const; |
120 | |
121 | bool f28(my_unsigned) const; |
122 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f28' should be marked NO_DISCARD [modernize-use-nodiscard] |
123 | // CHECK-FIXES: NO_DISCARD bool f28(my_unsigned) const; |
124 | |
125 | bool f29(my_unsigned_reference) const; |
126 | |
127 | bool f30(my_unsigned_const_reference) const; |
128 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f30' should be marked NO_DISCARD [modernize-use-nodiscard] |
129 | // CHECK-FIXES: NO_DISCARD bool f30(my_unsigned_const_reference) const; |
130 | |
131 | template <class F> |
132 | F f37(F a, F b) const; |
133 | |
134 | template <class F> |
135 | bool f38(F a) const; |
136 | |
137 | bool f39(const std::function<bool()> &predicate) const; |
138 | |
139 | bool f39a(std::function<bool()> predicate) const; |
140 | |
141 | bool f39b(const std::function<bool()> predicate) const; |
142 | |
143 | bool f45(const boost::function<bool()> &predicate) const; |
144 | |
145 | bool f45a(boost::function<bool()> predicate) const; |
146 | |
147 | bool f45b(const boost::function<bool()> predicate) const; |
148 | |
149 | // Do not add ``[[nodiscard]]`` to parameter packs. |
150 | template <class... Args> |
151 | bool ParameterPack(Args... args) const; |
152 | |
153 | template <typename... Targs> |
154 | bool ParameterPack2(Targs... Fargs) const; |
155 | |
156 | // Do not add ``[[nodiscard]]`` to variadic functions. |
157 | bool VariadicFunctionTest(const int &, ...) const; |
158 | |
159 | // Do not add ``[[nodiscard]]`` to non constant static functions. |
160 | static bool not_empty(); |
161 | |
162 | // Do not add ``[[nodiscard]]`` to conversion functions. |
163 | // explicit operator bool() const { return true; } |
164 | |
165 | // Do not add ``[[nodiscard]]`` to functions returning types marked [[nodiscard]]. |
166 | NoDiscardStruct f50() const; |
167 | }; |
168 | |
169 | // Do not add ``[[nodiscard]]`` to Lambda. |
170 | const auto nonConstReferenceType = [] { |
171 | return true; |
172 | }; |
173 | |
174 | auto lambda1 = [](int a, int b) { return a < b; }; |
175 | auto lambda1a = [](int a) { return a; }; |
176 | auto lambda1b = []() { return true;}; |
177 | |
178 | auto get_functor = [](bool check) { |
179 | return [&](const std::string& sr)->std::string { |
180 | if(check){ |
181 | return std::string(); |
182 | } |
183 | return std::string(); |
184 | }; |
185 | }; |
186 | |
187 | // Do not add ``[[nodiscard]]`` to function definition. |
188 | bool Foo::f19() const { |
189 | return true; |
190 | } |
191 | |
192 | template <class T> |
193 | class Bar { |
194 | public: |
195 | using value_type = T; |
196 | using reference = value_type &; |
197 | using const_reference = const value_type &; |
198 | |
199 | // Do not add ``[[nodiscard]]`` to non explicit conversion functions. |
200 | operator bool() const { return true; } |
201 | |
202 | bool empty() const; |
203 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'empty' should be marked NO_DISCARD [modernize-use-nodiscard] |
204 | // CHECK-FIXES: NO_DISCARD bool empty() const; |
205 | |
206 | // we cannot assume that the template parameter isn't a pointer |
207 | bool f25(value_type) const; |
208 | |
209 | bool f27(reference) const; |
210 | |
211 | typename T::value_type f35() const; |
212 | |
213 | T f34() const; |
214 | |
215 | bool f31(T) const; |
216 | |
217 | bool f33(T &) const; |
218 | |
219 | bool f26(const_reference) const; |
220 | |
221 | bool f32(const T &) const; |
222 | }; |
223 | |
224 | template <typename _Tp, int cn> |
225 | class Vec { |
226 | public: |
227 | Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor |
228 | |
229 | Vec cross(const Vec &v) const; |
230 | |
231 | template <typename T2> |
232 | operator Vec<T2, cn>() const; |
233 | }; |
234 | |
235 | template <class T> |
236 | class Bar2 { |
237 | public: |
238 | typedef T value_type; |
239 | typedef value_type &reference; |
240 | typedef const value_type &const_reference; |
241 | |
242 | // we cannot assume that the template parameter isn't a pointer |
243 | bool f40(value_type) const; |
244 | |
245 | bool f41(reference) const; |
246 | |
247 | value_type f42() const; |
248 | |
249 | typename T::value_type f43() const; |
250 | |
251 | bool f44(const_reference) const; |
252 | }; |
253 | |
254 | template <class T> |
255 | bool Bar<T>::empty() const { |
256 | return true; |
257 | } |
258 | |
259 | // don't mark typical ``[[nodiscard]]`` candidates if the class |
260 | // has mutable member variables |
261 | class MutableExample { |
262 | mutable bool m_isempty; |
263 | |
264 | public: |
265 | bool empty() const; |
266 | }; |
267 | |