Bump version to 19.1.0 (final)
[llvm-project.git] / clang-tools-extra / unittests / clang-tidy / DeclRefExprUtilsTest.cpp
blob064e04c932de83e212a035be7da8bf7c88a4f493
1 #include "../clang-tidy/utils/DeclRefExprUtils.h"
2 #include "ClangTidyDiagnosticConsumer.h"
3 #include "ClangTidyTest.h"
4 #include "clang/ASTMatchers/ASTMatchFinder.h"
5 #include "clang/ASTMatchers/ASTMatchers.h"
6 #include "clang/Tooling/Tooling.h"
7 #include "gtest/gtest.h"
9 namespace clang {
10 namespace tidy {
12 namespace {
13 using namespace clang::ast_matchers;
15 template <int Indirections>
16 class ConstReferenceDeclRefExprsTransform : public ClangTidyCheck {
17 public:
18 ConstReferenceDeclRefExprsTransform(StringRef CheckName,
19 ClangTidyContext *Context)
20 : ClangTidyCheck(CheckName, Context) {}
22 void registerMatchers(MatchFinder *Finder) override {
23 Finder->addMatcher(varDecl(hasName("target")).bind("var"), this);
26 void check(const MatchFinder::MatchResult &Result) override {
27 const auto *D = Result.Nodes.getNodeAs<VarDecl>("var");
28 using utils::decl_ref_expr::constReferenceDeclRefExprs;
29 const auto const_decrefexprs = constReferenceDeclRefExprs(
30 *D, *cast<FunctionDecl>(D->getDeclContext())->getBody(),
31 *Result.Context, Indirections);
33 for (const DeclRefExpr *const Expr : const_decrefexprs) {
34 assert(Expr);
35 diag(Expr->getBeginLoc(), "const usage")
36 << FixItHint::CreateInsertion(Expr->getBeginLoc(), "/*const*/");
40 } // namespace
42 namespace test {
44 template <int Indirections> void RunTest(StringRef Snippet) {
46 StringRef CommonCode = R"(
47 struct ConstTag{};
48 struct NonConstTag{};
49 struct Tag1{};
51 struct S {
52 void constMethod() const;
53 void nonConstMethod();
55 static void staticMethod();
57 void operator()(ConstTag) const;
58 void operator()(NonConstTag);
60 void operator[](int);
61 void operator[](int) const;
63 int& at(int);
64 const int& at(int) const;
65 const int& at(Tag1);
67 int& weird_overload();
68 const double& weird_overload() const;
70 bool operator==(const S&) const;
72 int int_member;
73 // We consider a mutation of the `*ptr_member` to be a const use of
74 // `*this`. This is consistent with the semantics of `const`-qualified
75 // methods, which prevent modifying `ptr_member` but not `*ptr_member`.
76 int* ptr_member;
80 struct Derived : public S {
84 void useVal(S);
85 void useRef(S&);
86 void usePtr(S*);
87 void usePtrPtr(S**);
88 void usePtrConstPtr(S* const*);
89 void useConstRef(const S&);
90 void useConstPtr(const S*);
91 void useConstPtrRef(const S*&);
92 void useConstPtrPtr(const S**);
93 void useConstPtrConstRef(const S* const&);
94 void useConstPtrConstPtr(const S* const*);
96 void useInt(int);
97 void useIntRef(int&);
98 void useIntConstRef(const int&);
99 void useIntPtr(int*);
100 void useIntConstPtr(const int*);
104 std::string Code = (CommonCode + Snippet).str();
106 llvm::SmallVector<StringRef, 1> Parts;
107 StringRef(Code).split(Parts, "/*const*/");
109 EXPECT_EQ(Code,
110 runCheckOnCode<ConstReferenceDeclRefExprsTransform<Indirections>>(
111 join(Parts, "")));
114 TEST(ConstReferenceDeclRefExprsTest, ConstValueVar) {
115 RunTest<0>(R"(
116 void f(const S target) {
117 useVal(/*const*/target);
118 useConstRef(/*const*/target);
119 useConstPtr(&/*const*/target);
120 useConstPtrConstRef(&/*const*/target);
121 /*const*/target.constMethod();
122 /*const*/target.staticMethod();
123 /*const*/target(ConstTag{});
124 /*const*/target[42];
125 useConstRef((/*const*/target));
126 (/*const*/target).constMethod();
127 /*const*/target.staticMethod();
128 (void)(/*const*/target == /*const*/target);
129 (void)/*const*/target;
130 (void)&/*const*/target;
131 (void)*&/*const*/target;
132 /*const*/target;
133 S copy1 = /*const*/target;
134 S copy2(/*const*/target);
135 /*const*/target.int_member;
136 useInt(/*const*/target.int_member);
137 useIntConstRef(/*const*/target.int_member);
138 useIntPtr(/*const*/target.ptr_member);
139 useIntConstPtr(&/*const*/target.int_member);
141 const S& const_target_ref = /*const*/target;
142 const S* const_target_ptr = &/*const*/target;
144 )");
147 TEST(ConstReferenceDeclRefExprsTest, ConstRefVar) {
148 RunTest<0>(R"(
149 void f(const S& target) {
150 useVal(/*const*/target);
151 useConstRef(/*const*/target);
152 useConstPtr(&/*const*/target);
153 useConstPtrConstRef(&/*const*/target);
154 /*const*/target.constMethod();
155 /*const*/target.staticMethod();
156 /*const*/target(ConstTag{});
157 /*const*/target[42];
158 useConstRef((/*const*/target));
159 (/*const*/target).constMethod();
160 (void)(/*const*/target == /*const*/target);
161 (void)/*const*/target;
162 (void)&/*const*/target;
163 (void)*&/*const*/target;
164 /*const*/target;
165 S copy1 = /*const*/target;
166 S copy2(/*const*/target);
167 /*const*/target.int_member;
168 useInt(/*const*/target.int_member);
169 useIntConstRef(/*const*/target.int_member);
170 useIntPtr(/*const*/target.ptr_member);
171 useIntConstPtr(&/*const*/target.int_member);
172 (void)/*const*/target.at(3);
174 const S& const_target_ref = /*const*/target;
175 const S* const_target_ptr = &/*const*/target;
176 (void)/*const*/target.at(3);
178 )");
181 TEST(ConstReferenceDeclRefExprsTest, DEBUGREMOVEME) {
182 RunTest<0>(R"(
183 void f(S target, const S& other) {
184 S* target_ptr = &target;
186 )");
189 TEST(ConstReferenceDeclRefExprsTest, ValueVar) {
190 RunTest<0>(R"(
191 void f(S target, const S& other) {
192 useConstRef(/*const*/target);
193 useVal(/*const*/target);
194 useConstPtr(&/*const*/target);
195 useConstPtrConstRef(&/*const*/target);
196 /*const*/target.constMethod();
197 /*const*/target.staticMethod();
198 target.nonConstMethod();
199 /*const*/target(ConstTag{});
200 /*const*/target[42];
201 /*const*/target(ConstTag{});
202 target(NonConstTag{});
203 useRef(target);
204 usePtr(&target);
205 useConstRef((/*const*/target));
206 (/*const*/target).constMethod();
207 (void)(/*const*/target == /*const*/target);
208 (void)(/*const*/target == other);
209 (void)/*const*/target;
210 (void)&/*const*/target;
211 (void)*&/*const*/target;
212 /*const*/target;
213 S copy1 = /*const*/target;
214 S copy2(/*const*/target);
215 /*const*/target.int_member;
216 useInt(/*const*/target.int_member);
217 useIntConstRef(/*const*/target.int_member);
218 useIntPtr(/*const*/target.ptr_member);
219 useIntConstPtr(&/*const*/target.int_member);
221 const S& const_target_ref = /*const*/target;
222 const S* const_target_ptr = &/*const*/target;
223 S* target_ptr = &target;
225 (void)/*const*/target.at(3);
226 ++target.at(3);
227 const int civ = /*const*/target.at(3);
228 const int& cir = /*const*/target.at(3);
229 int& ir = target.at(3);
230 target.at(Tag1{});
231 target.weird_overload();
233 )");
236 TEST(ConstReferenceDeclRefExprsTest, RefVar) {
237 RunTest<0>(R"(
238 void f(S& target) {
239 useVal(/*const*/target);
240 usePtr(&target);
241 useConstRef(/*const*/target);
242 useConstPtr(&/*const*/target);
243 useConstPtrConstRef(&/*const*/target);
244 /*const*/target.constMethod();
245 /*const*/target.staticMethod();
246 target.nonConstMethod();
247 /*const*/target(ConstTag{});
248 /*const*/target[42];
249 useConstRef((/*const*/target));
250 (/*const*/target).constMethod();
251 (void)(/*const*/target == /*const*/target);
252 (void)/*const*/target;
253 (void)&/*const*/target;
254 (void)*&/*const*/target;
255 /*const*/target;
256 S copy1 = /*const*/target;
257 S copy2(/*const*/target);
258 /*const*/target.int_member;
259 useInt(/*const*/target.int_member);
260 useIntConstRef(/*const*/target.int_member);
261 useIntPtr(/*const*/target.ptr_member);
262 useIntConstPtr(&/*const*/target.int_member);
264 (void)(&/*const*/target)->int_member;
265 useIntRef((&target)->int_member);
267 const S& const_target_ref = /*const*/target;
268 const S* const_target_ptr = &/*const*/target;
269 S* target_ptr = &target;
271 (void)/*const*/target.at(3);
272 ++target.at(3);
273 const int civ = /*const*/target.at(3);
274 const int& cir = /*const*/target.at(3);
275 int& ir = target.at(3);
276 target.at(Tag1{});
277 target.weird_overload();
279 )");
282 TEST(ConstReferenceDeclRefExprsTest, PtrVar) {
283 RunTest<1>(R"(
284 void f(S* target) {
285 useVal(*/*const*/target);
286 usePtr(target);
287 useConstRef(*/*const*/target);
288 useConstPtr(/*const*/target);
289 useConstPtrConstRef(/*const*/target);
290 usePtrConstPtr(&target);
291 /*const*/target->constMethod();
292 /*const*/target->staticMethod();
293 target->nonConstMethod();
294 (*/*const*/target)(ConstTag{});
295 (*/*const*/target)[42];
296 /*const*/target->operator[](42);
297 useConstRef((*/*const*/target));
298 (/*const*/target)->constMethod();
299 (void)(*/*const*/target == */*const*/target);
300 (void)*/*const*/target;
301 (void)/*const*/target;
302 /*const*/target;
303 S copy1 = */*const*/target;
304 S copy2(*/*const*/target);
305 /*const*/target->int_member;
306 useInt(/*const*/target->int_member);
307 useIntConstRef(/*const*/target->int_member);
308 useIntPtr(/*const*/target->ptr_member);
309 useIntConstPtr(&/*const*/target->int_member);
311 const S& const_target_ref = */*const*/target;
312 const S* const_target_ptr = /*const*/target;
313 S* target_ptr = target; // FIXME: we could chect const usage of `target_ptr`
315 (void)/*const*/target->at(3);
316 ++target->at(3);
317 const int civ = /*const*/target->at(3);
318 const int& cir = /*const*/target->at(3);
319 int& ir = target->at(3);
320 target->at(Tag1{});
321 target->weird_overload();
323 )");
326 TEST(ConstReferenceDeclRefExprsTest, ConstPtrVar) {
327 RunTest<1>(R"(
328 void f(const S* target) {
329 useVal(*/*const*/target);
330 useConstRef(*/*const*/target);
331 useConstPtr(/*const*/target);
332 useConstPtrRef(/*const*/target);
333 useConstPtrPtr(&/*const*/target);
334 useConstPtrConstPtr(&/*const*/target);
335 useConstPtrConstRef(/*const*/target);
336 /*const*/target->constMethod();
337 /*const*/target->staticMethod();
338 (*/*const*/target)(ConstTag{});
339 (*/*const*/target)[42];
340 /*const*/target->operator[](42);
341 (void)(*/*const*/target == */*const*/target);
342 (void)/*const*/target;
343 (void)*/*const*/target;
344 /*const*/target;
345 if(/*const*/target) {}
346 S copy1 = */*const*/target;
347 S copy2(*/*const*/target);
348 /*const*/target->int_member;
349 useInt(/*const*/target->int_member);
350 useIntConstRef(/*const*/target->int_member);
351 useIntPtr(/*const*/target->ptr_member);
352 useIntConstPtr(&/*const*/target->int_member);
354 const S& const_target_ref = */*const*/target;
355 const S* const_target_ptr = /*const*/target;
357 (void)/*const*/target->at(3);
358 const int civ = /*const*/target->at(3);
359 const int& cir = /*const*/target->at(3);
361 )");
364 TEST(ConstReferenceDeclRefExprsTest, ConstPtrPtrVar) {
365 RunTest<2>(R"(
366 void f(const S** target) {
367 useVal(**/*const*/target);
368 useConstRef(**/*const*/target);
369 useConstPtr(*/*const*/target);
370 useConstPtrRef(*/*const*/target);
371 useConstPtrPtr(/*const*/target);
372 useConstPtrConstPtr(/*const*/target);
373 useConstPtrConstRef(*/*const*/target);
374 (void)/*const*/target;
375 (void)*/*const*/target;
376 (void)**/*const*/target;
377 /*const*/target;
378 if(/*const*/target) {}
379 if(*/*const*/target) {}
380 S copy1 = **/*const*/target;
381 S copy2(**/*const*/target);
382 (*/*const*/target)->int_member;
383 useInt((*/*const*/target)->int_member);
384 useIntConstRef((*/*const*/target)->int_member);
385 useIntPtr((*/*const*/target)->ptr_member);
386 useIntConstPtr(&(*/*const*/target)->int_member);
388 const S& const_target_ref = **/*const*/target;
389 const S* const_target_ptr = */*const*/target;
391 )");
394 TEST(ConstReferenceDeclRefExprsTest, ConstPtrConstPtrVar) {
395 RunTest<2>(R"(
396 void f(const S* const* target) {
397 useVal(**/*const*/target);
398 useConstRef(**/*const*/target);
399 useConstPtr(*/*const*/target);
400 useConstPtrConstPtr(/*const*/target);
401 useConstPtrConstRef(*/*const*/target);
402 (void)/*const*/target;
403 (void)*/*const*/target;
404 (void)**/*const*/target;
405 /*const*/target;
406 if(/*const*/target) {}
407 if(*/*const*/target) {}
408 S copy1 = **/*const*/target;
409 S copy2(**/*const*/target);
410 (*/*const*/target)->int_member;
411 useInt((*/*const*/target)->int_member);
412 useIntConstRef((*/*const*/target)->int_member);
413 useIntPtr((*/*const*/target)->ptr_member);
414 useIntConstPtr(&(*/*const*/target)->int_member);
416 const S& const_target_ref = **/*const*/target;
417 const S* const_target_ptr = */*const*/target;
419 )");
422 } // namespace test
423 } // namespace tidy
424 } // namespace clang