1 // RUN: %check_clang_tidy -std=c++17-or-later %s modernize-use-nodiscard %t -- \
2 // RUN:   -config="{CheckOptions: [{key: modernize-use-nodiscard.ReplacementString, value: '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
f18() const104     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.
__anond8745c7d0102null170 const auto nonConstReferenceType = [] {
171   return true;
172 };
173 
__anond8745c7d0202(int a, int b) 174 auto lambda1 = [](int a, int b) { return a < b; };
__anond8745c7d0302(int a) 175 auto lambda1a = [](int a) { return a; };
__anond8745c7d0402() 176 auto lambda1b = []()  { return true;};
177 
__anond8745c7d0502(bool check) 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.
f19() const188 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.
operator bool() const200     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>
empty() const255 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