1#include "../clang-tidy/utils/FixItHintUtils.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"
8#include <optional>
9
10namespace clang {
11namespace tidy {
12
13namespace {
14using namespace clang::ast_matchers;
15using namespace utils::fixit;
16
17template <QualifierTarget CT, QualifierPolicy CP>
18class ConstTransform : public ClangTidyCheck {
19public:
20 ConstTransform(StringRef CheckName, ClangTidyContext *Context)
21 : ClangTidyCheck(CheckName, Context) {}
22
23 void registerMatchers(MatchFinder *Finder) override {
24 Finder->addMatcher(varDecl(hasName(Name: "target")).bind(ID: "var"), this);
25 }
26
27 void check(const MatchFinder::MatchResult &Result) override {
28 const auto *D = Result.Nodes.getNodeAs<VarDecl>(ID: "var");
29 using utils::fixit::addQualifierToVarDecl;
30 std::optional<FixItHint> Fix = addQualifierToVarDecl(
31 *D, *Result.Context, DeclSpec::TQ::TQ_const, CT, CP);
32 auto Diag = diag(D->getBeginLoc(), "doing const transformation");
33 if (Fix)
34 Diag << *Fix;
35 }
36};
37} // namespace
38
39namespace test {
40using PointeeLTransform =
41 ConstTransform<QualifierTarget::Pointee, QualifierPolicy::Left>;
42using PointeeRTransform =
43 ConstTransform<QualifierTarget::Pointee, QualifierPolicy::Right>;
44
45using ValueLTransform =
46 ConstTransform<QualifierTarget::Value, QualifierPolicy::Left>;
47using ValueRTransform =
48 ConstTransform<QualifierTarget::Value, QualifierPolicy::Right>;
49
50// ----------------------------------------------------------------------------
51// Test Value-like types. Everything with indirection is done later.
52// ----------------------------------------------------------------------------
53
54TEST(Values, Builtin) {
55 StringRef Snippet = "int target = 0;";
56
57 EXPECT_EQ("const int target = 0;", runCheckOnCode<ValueLTransform>(Snippet));
58 EXPECT_EQ("const int target = 0;",
59 runCheckOnCode<PointeeLTransform>(Snippet));
60
61 EXPECT_EQ("int const target = 0;", runCheckOnCode<ValueRTransform>(Snippet));
62 EXPECT_EQ("int const target = 0;",
63 runCheckOnCode<PointeeRTransform>(Snippet));
64}
65TEST(Values, TypedefBuiltin) {
66 StringRef T = "typedef int MyInt;";
67 StringRef S = "MyInt target = 0;";
68 auto Cat = [&T](StringRef S) { return (T + S).str(); };
69
70 EXPECT_EQ(Cat("const MyInt target = 0;"),
71 runCheckOnCode<ValueLTransform>(Cat(S)));
72 EXPECT_EQ(Cat("const MyInt target = 0;"),
73 runCheckOnCode<PointeeLTransform>(Cat(S)));
74
75 EXPECT_EQ(Cat("MyInt const target = 0;"),
76 runCheckOnCode<ValueRTransform>(Cat(S)));
77 EXPECT_EQ(Cat("MyInt const target = 0;"),
78 runCheckOnCode<PointeeRTransform>(Cat(S)));
79}
80TEST(Values, TypedefBuiltinPointer) {
81 StringRef T = "typedef int* MyInt;";
82 StringRef S = "MyInt target = nullptr;";
83 auto Cat = [&T](StringRef S) { return (T + S).str(); };
84
85 EXPECT_EQ(Cat("const MyInt target = nullptr;"),
86 runCheckOnCode<ValueLTransform>(Cat(S)));
87 EXPECT_EQ(Cat("const MyInt target = nullptr;"),
88 runCheckOnCode<PointeeLTransform>(Cat(S)));
89
90 EXPECT_EQ(Cat("MyInt const target = nullptr;"),
91 runCheckOnCode<ValueRTransform>(Cat(S)));
92 EXPECT_EQ(Cat("MyInt const target = nullptr;"),
93 runCheckOnCode<PointeeRTransform>(Cat(S)));
94}
95TEST(Values, UsingBuiltin) {
96 StringRef T = "using MyInt = int;";
97 StringRef S = "MyInt target = 0;";
98 auto Cat = [&T](StringRef S) { return (T + S).str(); };
99
100 EXPECT_EQ(Cat("const MyInt target = 0;"),
101 runCheckOnCode<ValueLTransform>(Cat(S)));
102 EXPECT_EQ(Cat("const MyInt target = 0;"),
103 runCheckOnCode<PointeeLTransform>(Cat(S)));
104
105 EXPECT_EQ(Cat("MyInt const target = 0;"),
106 runCheckOnCode<ValueRTransform>(Cat(S)));
107 EXPECT_EQ(Cat("MyInt const target = 0;"),
108 runCheckOnCode<PointeeRTransform>(Cat(S)));
109}
110TEST(Values, UsingBuiltinPointer) {
111 StringRef T = "using MyInt = int*;";
112 StringRef S = "MyInt target = nullptr;";
113 auto Cat = [&T](StringRef S) { return (T + S).str(); };
114
115 EXPECT_EQ(Cat("const MyInt target = nullptr;"),
116 runCheckOnCode<ValueLTransform>(Cat(S)));
117 EXPECT_EQ(Cat("const MyInt target = nullptr;"),
118 runCheckOnCode<PointeeLTransform>(Cat(S)));
119
120 EXPECT_EQ(Cat("MyInt const target = nullptr;"),
121 runCheckOnCode<ValueRTransform>(Cat(S)));
122 EXPECT_EQ(Cat("MyInt const target = nullptr;"),
123 runCheckOnCode<PointeeRTransform>(Cat(S)));
124}
125TEST(Values, AutoValue) {
126 StringRef T = "int f() { return 42; }\n";
127 StringRef S = "auto target = f();";
128 auto Cat = [&T](StringRef S) { return (T + S).str(); };
129
130 EXPECT_EQ(Cat("const auto target = f();"),
131 runCheckOnCode<ValueLTransform>(Cat(S)));
132 EXPECT_EQ(Cat("const auto target = f();"),
133 runCheckOnCode<PointeeLTransform>(Cat(S)));
134
135 EXPECT_EQ(Cat("auto const target = f();"),
136 runCheckOnCode<ValueRTransform>(Cat(S)));
137 EXPECT_EQ(Cat("auto const target = f();"),
138 runCheckOnCode<PointeeRTransform>(Cat(S)));
139}
140TEST(Values, AutoPointer) {
141 StringRef T = "int* f() { return nullptr; }\n";
142 StringRef S = "auto target = f();";
143 auto Cat = [&T](StringRef S) { return (T + S).str(); };
144
145 EXPECT_EQ(Cat("const auto target = f();"),
146 runCheckOnCode<ValueLTransform>(Cat(S)));
147 EXPECT_EQ(Cat("const auto target = f();"),
148 runCheckOnCode<PointeeLTransform>(Cat(S)));
149
150 EXPECT_EQ(Cat("auto const target = f();"),
151 runCheckOnCode<ValueRTransform>(Cat(S)));
152 EXPECT_EQ(Cat("auto const target = f();"),
153 runCheckOnCode<PointeeRTransform>(Cat(S)));
154}
155TEST(Values, AutoReference) {
156 StringRef T = "static int global = 42; int& f() { return global; }\n";
157 StringRef S = "auto target = f();";
158 auto Cat = [&T](StringRef S) { return (T + S).str(); };
159
160 EXPECT_EQ(Cat("const auto target = f();"),
161 runCheckOnCode<ValueLTransform>(Cat(S)));
162 EXPECT_EQ(Cat("const auto target = f();"),
163 runCheckOnCode<PointeeLTransform>(Cat(S)));
164
165 EXPECT_EQ(Cat("auto const target = f();"),
166 runCheckOnCode<ValueRTransform>(Cat(S)));
167 EXPECT_EQ(Cat("auto const target = f();"),
168 runCheckOnCode<PointeeRTransform>(Cat(S)));
169}
170TEST(Values, DeclTypeValue) {
171 StringRef T = "int f() { return 42; }\n";
172 StringRef S = "decltype(f()) target = f();";
173 auto Cat = [&T](StringRef S) { return (T + S).str(); };
174
175 EXPECT_EQ(Cat("const decltype(f()) target = f();"),
176 runCheckOnCode<ValueLTransform>(Cat(S)));
177 EXPECT_EQ(Cat("const decltype(f()) target = f();"),
178 runCheckOnCode<PointeeLTransform>(Cat(S)));
179
180 EXPECT_EQ(Cat("decltype(f()) const target = f();"),
181 runCheckOnCode<ValueRTransform>(Cat(S)));
182 EXPECT_EQ(Cat("decltype(f()) const target = f();"),
183 runCheckOnCode<PointeeRTransform>(Cat(S)));
184}
185TEST(Values, DeclTypePointer) {
186 // The pointer itself will be changed to 'const'. There is no
187 // way to make the pointee 'const' with this syntax.
188 StringRef T = "int* f() { return nullptr; }\n";
189 StringRef S = "decltype(f()) target = f();";
190 auto Cat = [&T](StringRef S) { return (T + S).str(); };
191
192 EXPECT_EQ(Cat("const decltype(f()) target = f();"),
193 runCheckOnCode<ValueLTransform>(Cat(S)));
194 EXPECT_EQ(Cat("const decltype(f()) target = f();"),
195 runCheckOnCode<PointeeLTransform>(Cat(S)));
196
197 EXPECT_EQ(Cat("decltype(f()) const target = f();"),
198 runCheckOnCode<ValueRTransform>(Cat(S)));
199 EXPECT_EQ(Cat("decltype(f()) const target = f();"),
200 runCheckOnCode<PointeeRTransform>(Cat(S)));
201}
202TEST(Values, DeclTypeReference) {
203 // Same as pointer, but the reference itself will be marked 'const'.
204 // This has no effect and will result in a warning afterwards. The
205 // transformation itself is still correct.
206 StringRef T = "static int global = 42; int& f() { return global; }\n";
207 StringRef S = "decltype(f()) target = f();";
208 auto Cat = [&T](StringRef S) { return (T + S).str(); };
209
210 EXPECT_EQ(Cat("const decltype(f()) target = f();"),
211 runCheckOnCode<ValueLTransform>(Cat(S)));
212 EXPECT_EQ(Cat("const decltype(f()) target = f();"),
213 runCheckOnCode<PointeeLTransform>(Cat(S)));
214
215 EXPECT_EQ(Cat("decltype(f()) const target = f();"),
216 runCheckOnCode<ValueRTransform>(Cat(S)));
217 EXPECT_EQ(Cat("decltype(f()) const target = f();"),
218 runCheckOnCode<PointeeRTransform>(Cat(S)));
219}
220TEST(Values, Parens) {
221 StringRef Snippet = "int ((target)) = 0;";
222
223 EXPECT_EQ("const int ((target)) = 0;",
224 runCheckOnCode<ValueLTransform>(Snippet));
225 EXPECT_EQ("const int ((target)) = 0;",
226 runCheckOnCode<PointeeLTransform>(Snippet));
227
228 EXPECT_EQ("int const ((target)) = 0;",
229 runCheckOnCode<ValueRTransform>(Snippet));
230 EXPECT_EQ("int const ((target)) = 0;",
231 runCheckOnCode<PointeeRTransform>(Snippet));
232}
233
234// ----------------------------------------------------------------------------
235// Test builtin-arrays
236// ----------------------------------------------------------------------------
237
238TEST(Arrays, Builtin) {
239 StringRef Snippet = "int target[][1] = {{1}, {2}, {3}};";
240
241 EXPECT_EQ("const int target[][1] = {{1}, {2}, {3}};",
242 runCheckOnCode<PointeeLTransform>(Snippet));
243 EXPECT_EQ("const int target[][1] = {{1}, {2}, {3}};",
244 runCheckOnCode<ValueLTransform>(Snippet));
245
246 EXPECT_EQ("int const target[][1] = {{1}, {2}, {3}};",
247 runCheckOnCode<PointeeRTransform>(Snippet));
248 EXPECT_EQ("int const target[][1] = {{1}, {2}, {3}};",
249 runCheckOnCode<ValueRTransform>(Snippet));
250}
251TEST(Arrays, BuiltinParens) {
252 StringRef Snippet = "int ((target))[][1] = {{1}, {2}, {3}};";
253
254 EXPECT_EQ("const int ((target))[][1] = {{1}, {2}, {3}};",
255 runCheckOnCode<PointeeLTransform>(Snippet));
256 EXPECT_EQ("const int ((target))[][1] = {{1}, {2}, {3}};",
257 runCheckOnCode<ValueLTransform>(Snippet));
258
259 EXPECT_EQ("int const ((target))[][1] = {{1}, {2}, {3}};",
260 runCheckOnCode<PointeeRTransform>(Snippet));
261 EXPECT_EQ("int const ((target))[][1] = {{1}, {2}, {3}};",
262 runCheckOnCode<ValueRTransform>(Snippet));
263}
264TEST(Arrays, Pointers) {
265 StringRef Snippet = "int x; int* target[] = {&x, &x, &x};";
266
267 EXPECT_EQ("int x; const int* target[] = {&x, &x, &x};",
268 runCheckOnCode<PointeeLTransform>(Snippet));
269 EXPECT_EQ("int x; int const* target[] = {&x, &x, &x};",
270 runCheckOnCode<PointeeRTransform>(Snippet));
271
272 EXPECT_EQ("int x; int* const target[] = {&x, &x, &x};",
273 runCheckOnCode<ValueLTransform>(Snippet));
274 EXPECT_EQ("int x; int* const target[] = {&x, &x, &x};",
275 runCheckOnCode<ValueRTransform>(Snippet));
276}
277TEST(Arrays, PointerPointers) {
278 StringRef Snippet = "int* x = nullptr; int** target[] = {&x, &x, &x};";
279
280 EXPECT_EQ("int* x = nullptr; int* const* target[] = {&x, &x, &x};",
281 runCheckOnCode<PointeeLTransform>(Snippet));
282 EXPECT_EQ("int* x = nullptr; int** const target[] = {&x, &x, &x};",
283 runCheckOnCode<ValueLTransform>(Snippet));
284
285 EXPECT_EQ("int* x = nullptr; int* const* target[] = {&x, &x, &x};",
286 runCheckOnCode<PointeeRTransform>(Snippet));
287 EXPECT_EQ("int* x = nullptr; int** const target[] = {&x, &x, &x};",
288 runCheckOnCode<ValueRTransform>(Snippet));
289}
290TEST(Arrays, PointersParens) {
291 StringRef Snippet = "int x; int* (target)[] = {&x, &x, &x};";
292
293 EXPECT_EQ("int x; const int* (target)[] = {&x, &x, &x};",
294 runCheckOnCode<PointeeLTransform>(Snippet));
295 EXPECT_EQ("int x; int const* (target)[] = {&x, &x, &x};",
296 runCheckOnCode<PointeeRTransform>(Snippet));
297
298 EXPECT_EQ("int x; int* const (target)[] = {&x, &x, &x};",
299 runCheckOnCode<ValueLTransform>(Snippet));
300 EXPECT_EQ("int x; int* const (target)[] = {&x, &x, &x};",
301 runCheckOnCode<ValueRTransform>(Snippet));
302}
303
304// ----------------------------------------------------------------------------
305// Test reference types. This does not include pointers and arrays.
306// ----------------------------------------------------------------------------
307
308TEST(Reference, LValueBuiltin) {
309 StringRef Snippet = "int x = 42; int& target = x;";
310
311 EXPECT_EQ("int x = 42; const int& target = x;",
312 runCheckOnCode<ValueLTransform>(Snippet));
313 EXPECT_EQ("int x = 42; const int& target = x;",
314 runCheckOnCode<PointeeLTransform>(Snippet));
315
316 EXPECT_EQ("int x = 42; int const& target = x;",
317 runCheckOnCode<ValueRTransform>(Snippet));
318 EXPECT_EQ("int x = 42; int const& target = x;",
319 runCheckOnCode<PointeeRTransform>(Snippet));
320}
321TEST(Reference, RValueBuiltin) {
322 StringRef Snippet = "int&& target = 42;";
323 EXPECT_EQ("const int&& target = 42;",
324 runCheckOnCode<ValueLTransform>(Snippet));
325 EXPECT_EQ("const int&& target = 42;",
326 runCheckOnCode<PointeeLTransform>(Snippet));
327
328 EXPECT_EQ("int const&& target = 42;",
329 runCheckOnCode<ValueRTransform>(Snippet));
330 EXPECT_EQ("int const&& target = 42;",
331 runCheckOnCode<PointeeRTransform>(Snippet));
332}
333TEST(Reference, LValueToPointer) {
334 StringRef Snippet = "int* p; int *& target = p;";
335 EXPECT_EQ("int* p; int * const& target = p;",
336 runCheckOnCode<ValueLTransform>(Snippet));
337 EXPECT_EQ("int* p; int * const& target = p;",
338 runCheckOnCode<PointeeLTransform>(Snippet));
339
340 EXPECT_EQ("int* p; int * const& target = p;",
341 runCheckOnCode<ValueRTransform>(Snippet));
342 EXPECT_EQ("int* p; int * const& target = p;",
343 runCheckOnCode<PointeeRTransform>(Snippet));
344}
345TEST(Reference, LValueParens) {
346 StringRef Snippet = "int x = 42; int ((& target)) = x;";
347
348 EXPECT_EQ("int x = 42; const int ((& target)) = x;",
349 runCheckOnCode<ValueLTransform>(Snippet));
350 EXPECT_EQ("int x = 42; const int ((& target)) = x;",
351 runCheckOnCode<PointeeLTransform>(Snippet));
352
353 EXPECT_EQ("int x = 42; int const((& target)) = x;",
354 runCheckOnCode<ValueRTransform>(Snippet));
355 EXPECT_EQ("int x = 42; int const((& target)) = x;",
356 runCheckOnCode<PointeeRTransform>(Snippet));
357}
358TEST(Reference, ToArray) {
359 StringRef ArraySnippet = "int a[4] = {1, 2, 3, 4};";
360 StringRef Snippet = "int (&target)[4] = a;";
361 auto Cat = [&ArraySnippet](StringRef S) { return (ArraySnippet + S).str(); };
362
363 EXPECT_EQ(Cat("const int (&target)[4] = a;"),
364 runCheckOnCode<ValueLTransform>(Cat(Snippet)));
365 EXPECT_EQ(Cat("const int (&target)[4] = a;"),
366 runCheckOnCode<PointeeLTransform>(Cat(Snippet)));
367
368 EXPECT_EQ(Cat("int const(&target)[4] = a;"),
369 runCheckOnCode<ValueRTransform>(Cat(Snippet)));
370 EXPECT_EQ(Cat("int const(&target)[4] = a;"),
371 runCheckOnCode<PointeeRTransform>(Cat(Snippet)));
372}
373TEST(Reference, Auto) {
374 StringRef T = "static int global = 42; int& f() { return global; }\n";
375 StringRef S = "auto& target = f();";
376 auto Cat = [&T](StringRef S) { return (T + S).str(); };
377
378 EXPECT_EQ(Cat("const auto& target = f();"),
379 runCheckOnCode<ValueLTransform>(Cat(S)));
380 EXPECT_EQ(Cat("auto const& target = f();"),
381 runCheckOnCode<ValueRTransform>(Cat(S)));
382
383 EXPECT_EQ(Cat("const auto& target = f();"),
384 runCheckOnCode<PointeeLTransform>(Cat(S)));
385 EXPECT_EQ(Cat("auto const& target = f();"),
386 runCheckOnCode<PointeeRTransform>(Cat(S)));
387}
388
389// ----------------------------------------------------------------------------
390// Test pointers types.
391// ----------------------------------------------------------------------------
392
393TEST(Pointers, SingleBuiltin) {
394 StringRef Snippet = "int* target = nullptr;";
395
396 EXPECT_EQ("int* const target = nullptr;",
397 runCheckOnCode<ValueLTransform>(Snippet));
398 EXPECT_EQ("int* const target = nullptr;",
399 runCheckOnCode<ValueRTransform>(Snippet));
400
401 EXPECT_EQ("const int* target = nullptr;",
402 runCheckOnCode<PointeeLTransform>(Snippet));
403 EXPECT_EQ("int const* target = nullptr;",
404 runCheckOnCode<PointeeRTransform>(Snippet));
405}
406TEST(Pointers, MultiBuiltin) {
407 StringRef Snippet = "int** target = nullptr;";
408
409 EXPECT_EQ("int** const target = nullptr;",
410 runCheckOnCode<ValueLTransform>(Snippet));
411 EXPECT_EQ("int** const target = nullptr;",
412 runCheckOnCode<ValueRTransform>(Snippet));
413
414 EXPECT_EQ("int* const* target = nullptr;",
415 runCheckOnCode<PointeeLTransform>(Snippet));
416 EXPECT_EQ("int* const* target = nullptr;",
417 runCheckOnCode<PointeeRTransform>(Snippet));
418}
419TEST(Pointers, ToArray) {
420 StringRef ArraySnippet = "int a[4] = {1, 2, 3, 4};";
421 StringRef Snippet = "int (*target)[4] = &a;";
422 auto Cat = [&ArraySnippet](StringRef S) { return (ArraySnippet + S).str(); };
423
424 EXPECT_EQ(Cat("int (*const target)[4] = &a;"),
425 runCheckOnCode<ValueLTransform>(Cat(Snippet)));
426 EXPECT_EQ(Cat("const int (*target)[4] = &a;"),
427 runCheckOnCode<PointeeLTransform>(Cat(Snippet)));
428
429 EXPECT_EQ(Cat("int (*const target)[4] = &a;"),
430 runCheckOnCode<ValueRTransform>(Cat(Snippet)));
431 EXPECT_EQ(Cat("int const(*target)[4] = &a;"),
432 runCheckOnCode<PointeeRTransform>(Cat(Snippet)));
433}
434TEST(Pointers, Parens) {
435 StringRef Snippet = "int ((**target)) = nullptr;";
436
437 EXPECT_EQ("int ((**const target)) = nullptr;",
438 runCheckOnCode<ValueLTransform>(Snippet));
439 EXPECT_EQ("int ((**const target)) = nullptr;",
440 runCheckOnCode<ValueRTransform>(Snippet));
441
442 EXPECT_EQ("int ((* const*target)) = nullptr;",
443 runCheckOnCode<PointeeLTransform>(Snippet));
444 EXPECT_EQ("int ((* const*target)) = nullptr;",
445 runCheckOnCode<PointeeRTransform>(Snippet));
446}
447TEST(Pointers, Auto) {
448 StringRef T = "int* f() { return nullptr; }\n";
449 StringRef S = "auto* target = f();";
450 auto Cat = [&T](StringRef S) { return (T + S).str(); };
451
452 EXPECT_EQ(Cat("auto* const target = f();"),
453 runCheckOnCode<ValueLTransform>(Cat(S)));
454 EXPECT_EQ(Cat("auto* const target = f();"),
455 runCheckOnCode<ValueRTransform>(Cat(S)));
456
457 EXPECT_EQ(Cat("const auto* target = f();"),
458 runCheckOnCode<PointeeLTransform>(Cat(S)));
459 EXPECT_EQ(Cat("auto const* target = f();"),
460 runCheckOnCode<PointeeRTransform>(Cat(S)));
461}
462TEST(Pointers, AutoParens) {
463 StringRef T = "int* f() { return nullptr; }\n";
464 StringRef S = "auto (((* target))) = f();";
465 auto Cat = [&T](StringRef S) { return (T + S).str(); };
466
467 EXPECT_EQ(Cat("auto (((* const target))) = f();"),
468 runCheckOnCode<ValueLTransform>(Cat(S)));
469 EXPECT_EQ(Cat("auto (((* const target))) = f();"),
470 runCheckOnCode<ValueRTransform>(Cat(S)));
471
472 EXPECT_EQ(Cat("const auto (((* target))) = f();"),
473 runCheckOnCode<PointeeLTransform>(Cat(S)));
474 EXPECT_EQ(Cat("auto const(((* target))) = f();"),
475 runCheckOnCode<PointeeRTransform>(Cat(S)));
476}
477TEST(Pointers, FunctionPointer) {
478 StringRef S = "int (*target)(float, int, double) = nullptr;";
479
480 EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",
481 runCheckOnCode<ValueLTransform>(S));
482 EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",
483 runCheckOnCode<ValueRTransform>(S));
484
485 EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",
486 runCheckOnCode<PointeeLTransform>(S));
487 EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",
488 runCheckOnCode<PointeeRTransform>(S));
489
490 S = "int (((*target)))(float, int, double) = nullptr;";
491 EXPECT_EQ("int (((*const target)))(float, int, double) = nullptr;",
492 runCheckOnCode<PointeeRTransform>(S));
493}
494TEST(Pointers, MemberFunctionPointer) {
495 StringRef T = "struct A { int f() { return 1; } };";
496 StringRef S = "int (A::*target)() = &A::f;";
497 auto Cat = [&T](StringRef S) { return (T + S).str(); };
498
499 EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),
500 runCheckOnCode<ValueLTransform>(Cat(S)));
501 EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),
502 runCheckOnCode<ValueRTransform>(Cat(S)));
503
504 EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),
505 runCheckOnCode<PointeeLTransform>(Cat(S)));
506 EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),
507 runCheckOnCode<PointeeRTransform>(Cat(S)));
508
509 S = "int (A::*((target)))() = &A::f;";
510 EXPECT_EQ(Cat("int (A::*const ((target)))() = &A::f;"),
511 runCheckOnCode<ValueLTransform>(Cat(S)));
512}
513TEST(Pointers, MemberDataPointer) {
514 StringRef T = "struct A { int member = 0; };";
515 StringRef S = "int A::*target = &A::member;";
516 auto Cat = [&T](StringRef S) { return (T + S).str(); };
517
518 EXPECT_EQ(Cat("int A::*const target = &A::member;"),
519 runCheckOnCode<ValueLTransform>(Cat(S)));
520 EXPECT_EQ(Cat("int A::*const target = &A::member;"),
521 runCheckOnCode<ValueRTransform>(Cat(S)));
522
523 EXPECT_EQ(Cat("int A::*const target = &A::member;"),
524 runCheckOnCode<PointeeLTransform>(Cat(S)));
525 EXPECT_EQ(Cat("int A::*const target = &A::member;"),
526 runCheckOnCode<PointeeRTransform>(Cat(S)));
527
528 S = "int A::*((target)) = &A::member;";
529 EXPECT_EQ(Cat("int A::*const ((target)) = &A::member;"),
530 runCheckOnCode<PointeeRTransform>(Cat(S)));
531}
532
533// ----------------------------------------------------------------------------
534// Test TagTypes (struct, class, unions, enums)
535// ----------------------------------------------------------------------------
536
537TEST(TagTypes, Struct) {
538 StringRef T = "struct Foo { int data; int method(); };\n";
539 StringRef S = "struct Foo target{0};";
540 auto Cat = [&T](StringRef S) { return (T + S).str(); };
541
542 EXPECT_EQ(Cat("const struct Foo target{0};"),
543 runCheckOnCode<ValueLTransform>(Cat(S)));
544 EXPECT_EQ(Cat("const struct Foo target{0};"),
545 runCheckOnCode<PointeeLTransform>(Cat(S)));
546
547 EXPECT_EQ(Cat("struct Foo const target{0};"),
548 runCheckOnCode<ValueRTransform>(Cat(S)));
549 EXPECT_EQ(Cat("struct Foo const target{0};"),
550 runCheckOnCode<PointeeRTransform>(Cat(S)));
551
552 S = "Foo target{0};";
553 EXPECT_EQ(Cat("const Foo target{0};"),
554 runCheckOnCode<ValueLTransform>(Cat(S)));
555 EXPECT_EQ(Cat("const Foo target{0};"),
556 runCheckOnCode<PointeeLTransform>(Cat(S)));
557
558 EXPECT_EQ(Cat("Foo const target{0};"),
559 runCheckOnCode<ValueRTransform>(Cat(S)));
560 EXPECT_EQ(Cat("Foo const target{0};"),
561 runCheckOnCode<PointeeRTransform>(Cat(S)));
562
563 S = "Foo (target){0};";
564 EXPECT_EQ(Cat("const Foo (target){0};"),
565 runCheckOnCode<ValueLTransform>(Cat(S)));
566 EXPECT_EQ(Cat("const Foo (target){0};"),
567 runCheckOnCode<PointeeLTransform>(Cat(S)));
568
569 EXPECT_EQ(Cat("Foo const (target){0};"),
570 runCheckOnCode<ValueRTransform>(Cat(S)));
571 EXPECT_EQ(Cat("Foo const (target){0};"),
572 runCheckOnCode<PointeeRTransform>(Cat(S)));
573
574 S = "struct S { int i; } target = { 0 };";
575 EXPECT_EQ("const struct S { int i; } target = { 0 };",
576 runCheckOnCode<ValueLTransform>(S));
577 EXPECT_EQ("const struct S { int i; } target = { 0 };",
578 runCheckOnCode<PointeeLTransform>(S));
579
580 EXPECT_EQ("struct S { int i; } const target = { 0 };",
581 runCheckOnCode<PointeeRTransform>(S));
582 EXPECT_EQ("struct S { int i; } const target = { 0 };",
583 runCheckOnCode<PointeeRTransform>(S));
584
585 S = "struct { int i; } target = { 0 };";
586 EXPECT_EQ("const struct { int i; } target = { 0 };",
587 runCheckOnCode<ValueLTransform>(S));
588 EXPECT_EQ("const struct { int i; } target = { 0 };",
589 runCheckOnCode<PointeeLTransform>(S));
590
591 EXPECT_EQ("struct { int i; } const target = { 0 };",
592 runCheckOnCode<PointeeRTransform>(S));
593 EXPECT_EQ("struct { int i; } const target = { 0 };",
594 runCheckOnCode<PointeeRTransform>(S));
595}
596TEST(TagTypes, Class) {
597 StringRef T = "class Foo { int data; int method(); };\n";
598 StringRef S = "class Foo target;";
599 auto Cat = [&T](StringRef S) { return (T + S).str(); };
600
601 EXPECT_EQ(Cat("const class Foo target;"),
602 runCheckOnCode<ValueLTransform>(Cat(S)));
603 EXPECT_EQ(Cat("const class Foo target;"),
604 runCheckOnCode<PointeeLTransform>(Cat(S)));
605
606 EXPECT_EQ(Cat("class Foo const target;"),
607 runCheckOnCode<ValueRTransform>(Cat(S)));
608 EXPECT_EQ(Cat("class Foo const target;"),
609 runCheckOnCode<PointeeRTransform>(Cat(S)));
610
611 S = "Foo target;";
612 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));
613 EXPECT_EQ(Cat("const Foo target;"),
614 runCheckOnCode<PointeeLTransform>(Cat(S)));
615
616 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));
617 EXPECT_EQ(Cat("Foo const target;"),
618 runCheckOnCode<PointeeRTransform>(Cat(S)));
619
620 S = "Foo (target);";
621 EXPECT_EQ(Cat("const Foo (target);"),
622 runCheckOnCode<ValueLTransform>(Cat(S)));
623 EXPECT_EQ(Cat("const Foo (target);"),
624 runCheckOnCode<PointeeLTransform>(Cat(S)));
625
626 EXPECT_EQ(Cat("Foo const (target);"),
627 runCheckOnCode<ValueRTransform>(Cat(S)));
628 EXPECT_EQ(Cat("Foo const (target);"),
629 runCheckOnCode<PointeeRTransform>(Cat(S)));
630}
631TEST(TagTypes, Enum) {
632 StringRef T = "enum Foo { N_ONE, N_TWO, N_THREE };\n";
633 StringRef S = "enum Foo target;";
634 auto Cat = [&T](StringRef S) { return (T + S).str(); };
635
636 EXPECT_EQ(Cat("const enum Foo target;"),
637 runCheckOnCode<ValueLTransform>(Cat(S)));
638 EXPECT_EQ(Cat("const enum Foo target;"),
639 runCheckOnCode<PointeeLTransform>(Cat(S)));
640
641 EXPECT_EQ(Cat("enum Foo const target;"),
642 runCheckOnCode<ValueRTransform>(Cat(S)));
643 EXPECT_EQ(Cat("enum Foo const target;"),
644 runCheckOnCode<PointeeRTransform>(Cat(S)));
645
646 S = "Foo target;";
647 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));
648 EXPECT_EQ(Cat("const Foo target;"),
649 runCheckOnCode<PointeeLTransform>(Cat(S)));
650
651 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));
652 EXPECT_EQ(Cat("Foo const target;"),
653 runCheckOnCode<PointeeRTransform>(Cat(S)));
654
655 S = "Foo (target);";
656 EXPECT_EQ(Cat("const Foo (target);"),
657 runCheckOnCode<ValueLTransform>(Cat(S)));
658 EXPECT_EQ(Cat("const Foo (target);"),
659 runCheckOnCode<PointeeLTransform>(Cat(S)));
660
661 EXPECT_EQ(Cat("Foo const (target);"),
662 runCheckOnCode<ValueRTransform>(Cat(S)));
663 EXPECT_EQ(Cat("Foo const (target);"),
664 runCheckOnCode<PointeeRTransform>(Cat(S)));
665}
666TEST(TagTypes, Union) {
667 StringRef T = "union Foo { int yay; float nej; };\n";
668 StringRef S = "union Foo target;";
669 auto Cat = [&T](StringRef S) { return (T + S).str(); };
670
671 EXPECT_EQ(Cat("const union Foo target;"),
672 runCheckOnCode<ValueLTransform>(Cat(S)));
673 EXPECT_EQ(Cat("const union Foo target;"),
674 runCheckOnCode<PointeeLTransform>(Cat(S)));
675
676 EXPECT_EQ(Cat("union Foo const target;"),
677 runCheckOnCode<ValueRTransform>(Cat(S)));
678 EXPECT_EQ(Cat("union Foo const target;"),
679 runCheckOnCode<PointeeRTransform>(Cat(S)));
680
681 S = "Foo target;";
682 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));
683 EXPECT_EQ(Cat("const Foo target;"),
684 runCheckOnCode<PointeeLTransform>(Cat(S)));
685
686 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));
687 EXPECT_EQ(Cat("Foo const target;"),
688 runCheckOnCode<PointeeRTransform>(Cat(S)));
689
690 S = "Foo (target);";
691 EXPECT_EQ(Cat("const Foo (target);"),
692 runCheckOnCode<ValueLTransform>(Cat(S)));
693 EXPECT_EQ(Cat("const Foo (target);"),
694 runCheckOnCode<PointeeLTransform>(Cat(S)));
695
696 EXPECT_EQ(Cat("Foo const (target);"),
697 runCheckOnCode<ValueRTransform>(Cat(S)));
698 EXPECT_EQ(Cat("Foo const (target);"),
699 runCheckOnCode<PointeeRTransform>(Cat(S)));
700}
701
702// ----------------------------------------------------------------------------
703// Test Macro expansions.
704// ----------------------------------------------------------------------------
705
706TEST(Macro, AllInMacro) {
707 StringRef T = "#define DEFINE_VARIABLE int target = 42\n";
708 StringRef S = "DEFINE_VARIABLE;";
709 auto Cat = [&T](StringRef S) { return (T + S).str(); };
710
711 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<ValueLTransform>(Cat(S)));
712 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<ValueRTransform>(Cat(S)));
713
714 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<PointeeLTransform>(Cat(S)));
715 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<PointeeRTransform>(Cat(S)));
716}
717TEST(Macro, MacroParameter) {
718 StringRef T = "#define DEFINE_VARIABLE(X) int X = 42\n";
719 StringRef S = "DEFINE_VARIABLE(target);";
720 auto Cat = [&T](StringRef S) { return (T + S).str(); };
721
722 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
723 runCheckOnCode<ValueLTransform>(Cat(S)));
724 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
725 runCheckOnCode<ValueRTransform>(Cat(S)));
726
727 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
728 runCheckOnCode<PointeeLTransform>(Cat(S)));
729 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
730 runCheckOnCode<PointeeRTransform>(Cat(S)));
731}
732TEST(Macro, MacroTypeValue) {
733 StringRef T = "#define BAD_TYPEDEF int\n";
734 StringRef S = "BAD_TYPEDEF target = 42;";
735 auto Cat = [&T](StringRef S) { return (T + S).str(); };
736
737 EXPECT_EQ(Cat("BAD_TYPEDEF target = 42;"),
738 runCheckOnCode<ValueLTransform>(Cat(S)));
739 EXPECT_EQ(Cat("BAD_TYPEDEF target = 42;"),
740 runCheckOnCode<PointeeLTransform>(Cat(S)));
741
742 EXPECT_EQ(Cat("BAD_TYPEDEF const target = 42;"),
743 runCheckOnCode<PointeeRTransform>(Cat(S)));
744 EXPECT_EQ(Cat("BAD_TYPEDEF const target = 42;"),
745 runCheckOnCode<ValueRTransform>(Cat(S)));
746}
747TEST(Macro, MacroTypePointer) {
748 StringRef T = "#define BAD_TYPEDEF int *\n";
749 StringRef S = "BAD_TYPEDEF target = nullptr;";
750 auto Cat = [&T](StringRef S) { return (T + S).str(); };
751
752 EXPECT_EQ(Cat("BAD_TYPEDEF const target = nullptr;"),
753 runCheckOnCode<ValueLTransform>(Cat(S)));
754 EXPECT_EQ(Cat("BAD_TYPEDEF const target = nullptr;"),
755 runCheckOnCode<ValueRTransform>(Cat(S)));
756
757 // FIXME: Failing even all parts seem to bail-out in for isMacroID()
758 // The macro itself is changed here and below which is not intended.
759 EXPECT_NE(Cat("BAD_TYPEDEF target = nullptr;"),
760 runCheckOnCode<PointeeRTransform>(Cat(S)));
761 EXPECT_EQ(Cat("BAD_TYPEDEF target = nullptr;"),
762 runCheckOnCode<PointeeLTransform>(Cat(S)));
763}
764TEST(Macro, MacroTypeReference) {
765 StringRef T = "static int g = 42;\n#define BAD_TYPEDEF int&\n";
766 StringRef S = "BAD_TYPEDEF target = g;";
767 auto Cat = [&T](StringRef S) { return (T + S).str(); };
768
769 EXPECT_EQ(Cat("BAD_TYPEDEF target = g;"),
770 runCheckOnCode<ValueLTransform>(Cat(S)));
771 // FIXME: Failing even all parts seem to bail-out in for isMacroID()
772 EXPECT_NE(Cat("BAD_TYPEDEF target = g;"),
773 runCheckOnCode<ValueRTransform>(Cat(S)));
774
775 EXPECT_EQ(Cat("BAD_TYPEDEF target = g;"),
776 runCheckOnCode<PointeeLTransform>(Cat(S)));
777 // FIXME: Failing even all parts seem to bail-out in for isMacroID()
778 EXPECT_NE(Cat("BAD_TYPEDEF target = g;"),
779 runCheckOnCode<PointeeRTransform>(Cat(S)));
780}
781// This failed in LLVM.
782TEST(Macro, Variable) {
783 StringRef M = "#define DEBUG(X) do { if (1) { X; } } while (0)\n";
784 StringRef F = "void foo() ";
785 StringRef V = "{ DEBUG(int target = 42;); }";
786
787 auto Cat = [&](StringRef S) { return (M + F + V).str(); };
788
789 EXPECT_EQ(Cat("{ DEBUG(const int target = 42;); }"),
790 runCheckOnCode<ValueLTransform>(Cat(V)));
791 EXPECT_EQ(Cat("{ DEBUG(int const target = 42;); }"),
792 runCheckOnCode<ValueRTransform>(Cat(V)));
793}
794TEST(Macro, RangeLoop) {
795 StringRef M = "#define DEBUG(X) do { if (1) { X; }} while (false)\n";
796 StringRef F = "void foo() { char array[] = {'a', 'b', 'c'}; ";
797 StringRef V = "DEBUG( for(auto& target: array) 10 + target; );";
798 StringRef E = "}";
799
800 auto Cat = [&](StringRef S) { return (M + F + V + E).str(); };
801
802 EXPECT_EQ(Cat("DEBUG( for(const auto& target: array); );"),
803 runCheckOnCode<ValueLTransform>(Cat(V)));
804 EXPECT_EQ(Cat("DEBUG( for(auto const& target: array); );"),
805 runCheckOnCode<ValueRTransform>(Cat(V)));
806}
807
808// ----------------------------------------------------------------------------
809// Test template code.
810// ----------------------------------------------------------------------------
811
812TEST(Template, TemplateVariable) {
813 StringRef T = "template <typename T> T target = 3.1415;";
814
815 EXPECT_EQ("template <typename T> const T target = 3.1415;",
816 runCheckOnCode<ValueLTransform>(T));
817 EXPECT_EQ("template <typename T> T const target = 3.1415;",
818 runCheckOnCode<ValueRTransform>(T));
819
820 EXPECT_EQ("template <typename T> const T target = 3.1415;",
821 runCheckOnCode<PointeeLTransform>(T));
822 EXPECT_EQ("template <typename T> T const target = 3.1415;",
823 runCheckOnCode<PointeeRTransform>(T));
824}
825TEST(Template, FunctionValue) {
826 StringRef T = "template <typename T> void f(T v) \n";
827 StringRef S = "{ T target = v; }";
828 auto Cat = [&T](StringRef S) { return (T + S).str(); };
829
830 EXPECT_EQ(Cat("{ const T target = v; }"),
831 runCheckOnCode<ValueLTransform>(Cat(S)));
832 EXPECT_EQ(Cat("{ T const target = v; }"),
833 runCheckOnCode<ValueRTransform>(Cat(S)));
834
835 EXPECT_EQ(Cat("{ const T target = v; }"),
836 runCheckOnCode<PointeeLTransform>(Cat(S)));
837 EXPECT_EQ(Cat("{ T const target = v; }"),
838 runCheckOnCode<PointeeRTransform>(Cat(S)));
839}
840TEST(Template, FunctionPointer) {
841 StringRef T = "template <typename T> void f(T* v) \n";
842 StringRef S = "{ T* target = v; }";
843 auto Cat = [&T](StringRef S) { return (T + S).str(); };
844
845 EXPECT_EQ(Cat("{ T* const target = v; }"),
846 runCheckOnCode<ValueLTransform>(Cat(S)));
847 EXPECT_EQ(Cat("{ T* const target = v; }"),
848 runCheckOnCode<ValueRTransform>(Cat(S)));
849
850 EXPECT_EQ(Cat("{ const T* target = v; }"),
851 runCheckOnCode<PointeeLTransform>(Cat(S)));
852 EXPECT_EQ(Cat("{ T const* target = v; }"),
853 runCheckOnCode<PointeeRTransform>(Cat(S)));
854}
855TEST(Template, FunctionReference) {
856 StringRef T = "template <typename T> void f(T& v) \n";
857 StringRef S = "{ T& target = v; }";
858 auto Cat = [&T](StringRef S) { return (T + S).str(); };
859
860 EXPECT_EQ(Cat("{ const T& target = v; }"),
861 runCheckOnCode<ValueLTransform>(Cat(S)));
862 EXPECT_EQ(Cat("{ T const& target = v; }"),
863 runCheckOnCode<ValueRTransform>(Cat(S)));
864
865 EXPECT_EQ(Cat("{ const T& target = v; }"),
866 runCheckOnCode<PointeeLTransform>(Cat(S)));
867 EXPECT_EQ(Cat("{ T const& target = v; }"),
868 runCheckOnCode<PointeeRTransform>(Cat(S)));
869}
870TEST(Template, MultiInstantiationsFunction) {
871 StringRef T = "template <typename T> void f(T v) \n";
872 StringRef S = "{ T target = v; }";
873 StringRef InstantStart = "void calls() {\n";
874 StringRef InstValue = "f<int>(42);\n";
875 StringRef InstConstValue = "f<const int>(42);\n";
876 StringRef InstPointer = "f<int*>(nullptr);\n";
877 StringRef InstPointerConst = "f<int* const>(nullptr);\n";
878 StringRef InstConstPointer = "f<const int*>(nullptr);\n";
879 StringRef InstConstPointerConst = "f<const int* const>(nullptr);\n";
880 StringRef InstRef = "int i = 42;\nf<int&>(i);\n";
881 StringRef InstConstRef = "f<const int&>(i);\n";
882 StringRef InstantEnd = "}";
883 auto Cat = [&](StringRef Target) {
884 return (T + Target + InstantStart + InstValue + InstConstValue +
885 InstPointer + InstPointerConst + InstConstPointer +
886 InstConstPointerConst + InstRef + InstConstRef + InstantEnd)
887 .str();
888 };
889
890 EXPECT_EQ(Cat("{ const T target = v; }"),
891 runCheckOnCode<ValueLTransform>(Cat(S)));
892 EXPECT_EQ(Cat("{ T const target = v; }"),
893 runCheckOnCode<ValueRTransform>(Cat(S)));
894
895 EXPECT_EQ(Cat("{ const T target = v; }"),
896 runCheckOnCode<PointeeLTransform>(Cat(S)));
897 EXPECT_EQ(Cat("{ T const target = v; }"),
898 runCheckOnCode<PointeeRTransform>(Cat(S)));
899}
900
901TEST(Template, StructValue) {
902 StringRef T = "template <typename T> struct S { void f(T& v) \n";
903 StringRef S = "{ T target = v; }";
904 StringRef End = "\n};";
905 auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };
906
907 EXPECT_EQ(Cat("{ const T target = v; }"),
908 runCheckOnCode<ValueLTransform>(Cat(S)));
909 EXPECT_EQ(Cat("{ T const target = v; }"),
910 runCheckOnCode<ValueRTransform>(Cat(S)));
911
912 EXPECT_EQ(Cat("{ const T target = v; }"),
913 runCheckOnCode<PointeeLTransform>(Cat(S)));
914 EXPECT_EQ(Cat("{ T const target = v; }"),
915 runCheckOnCode<PointeeRTransform>(Cat(S)));
916}
917TEST(Template, StructPointer) {
918 StringRef T = "template <typename T> struct S { void f(T* v) \n";
919 StringRef S = "{ T* target = v; }";
920 StringRef End = "\n};";
921 auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };
922
923 EXPECT_EQ(Cat("{ T* const target = v; }"),
924 runCheckOnCode<ValueLTransform>(Cat(S)));
925 EXPECT_EQ(Cat("{ T* const target = v; }"),
926 runCheckOnCode<ValueRTransform>(Cat(S)));
927
928 EXPECT_EQ(Cat("{ const T* target = v; }"),
929 runCheckOnCode<PointeeLTransform>(Cat(S)));
930 EXPECT_EQ(Cat("{ T const* target = v; }"),
931 runCheckOnCode<PointeeRTransform>(Cat(S)));
932}
933TEST(Template, StructReference) {
934 StringRef T = "template <typename T> struct S { void f(T& v) \n";
935 StringRef S = "{ T& target = v; }";
936 StringRef End = "\n};";
937 auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };
938
939 EXPECT_EQ(Cat("{ const T& target = v; }"),
940 runCheckOnCode<ValueLTransform>(Cat(S)));
941 EXPECT_EQ(Cat("{ T const& target = v; }"),
942 runCheckOnCode<ValueRTransform>(Cat(S)));
943
944 EXPECT_EQ(Cat("{ const T& target = v; }"),
945 runCheckOnCode<PointeeLTransform>(Cat(S)));
946 EXPECT_EQ(Cat("{ T const& target = v; }"),
947 runCheckOnCode<PointeeRTransform>(Cat(S)));
948}
949TEST(Template, DependentReturnFunction) {
950 StringRef TS = "template <typename T> struct TS { using value_type = T; };";
951 StringRef T = "template <typename T> void foo() ";
952 StringRef S = "{ typename T::value_type target; }";
953 auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };
954
955 EXPECT_EQ(Cat("{ const typename T::value_type target; }"),
956 runCheckOnCode<ValueLTransform>(Cat(S)));
957 EXPECT_EQ(Cat("{ typename T::value_type const target; }"),
958 runCheckOnCode<ValueRTransform>(Cat(S)));
959
960 EXPECT_EQ(Cat("{ const typename T::value_type target; }"),
961 runCheckOnCode<PointeeLTransform>(Cat(S)));
962 EXPECT_EQ(Cat("{ typename T::value_type const target; }"),
963 runCheckOnCode<PointeeRTransform>(Cat(S)));
964}
965TEST(Template, DependentReturnPointerFunction) {
966 StringRef TS = "template <typename T> struct TS { using value_type = T; };";
967 StringRef T = "template <typename T> void foo() ";
968 StringRef S = "{ typename T::value_type *target; }";
969 auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };
970
971 EXPECT_EQ(Cat("{ typename T::value_type *const target; }"),
972 runCheckOnCode<ValueLTransform>(Cat(S)));
973 EXPECT_EQ(Cat("{ typename T::value_type *const target; }"),
974 runCheckOnCode<ValueRTransform>(Cat(S)));
975
976 EXPECT_EQ(Cat("{ const typename T::value_type *target; }"),
977 runCheckOnCode<PointeeLTransform>(Cat(S)));
978 EXPECT_EQ(Cat("{ typename T::value_type const*target; }"),
979 runCheckOnCode<PointeeRTransform>(Cat(S)));
980}
981TEST(Template, DependentReturnReferenceFunction) {
982 StringRef TS = "template <typename T> struct TS { using value_type = T; };";
983 StringRef T = "template <typename T> void foo(T& f) ";
984 StringRef S = "{ typename T::value_type &target = f; }";
985 auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };
986
987 EXPECT_EQ(Cat("{ const typename T::value_type &target = f; }"),
988 runCheckOnCode<ValueLTransform>(Cat(S)));
989 EXPECT_EQ(Cat("{ typename T::value_type const&target = f; }"),
990 runCheckOnCode<ValueRTransform>(Cat(S)));
991
992 EXPECT_EQ(Cat("{ const typename T::value_type &target = f; }"),
993 runCheckOnCode<PointeeLTransform>(Cat(S)));
994 EXPECT_EQ(Cat("{ typename T::value_type const&target = f; }"),
995 runCheckOnCode<PointeeRTransform>(Cat(S)));
996}
997TEST(Template, VectorLikeType) {
998 StringRef TS = "template <typename T> struct TS { TS(const T&) {} }; ";
999 StringRef T = "void foo() ";
1000 StringRef S = "{ TS<int> target(42); }";
1001 auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };
1002
1003 EXPECT_EQ(Cat("{ const TS<int> target(42); }"),
1004 runCheckOnCode<ValueLTransform>(Cat(S)));
1005 EXPECT_EQ(Cat("{ TS<int> const target(42); }"),
1006 runCheckOnCode<ValueRTransform>(Cat(S)));
1007
1008 EXPECT_EQ(Cat("{ const TS<int> target(42); }"),
1009 runCheckOnCode<PointeeLTransform>(Cat(S)));
1010 EXPECT_EQ(Cat("{ TS<int> const target(42); }"),
1011 runCheckOnCode<PointeeRTransform>(Cat(S)));
1012}
1013TEST(Template, SpecializedTemplate) {
1014 StringRef TS = "template <typename T = int> struct TS { TS(const T&) {} }; ";
1015 StringRef TS2 = "template <> struct TS<double> { TS(const double&) {} }; ";
1016 StringRef T = "void foo() ";
1017 StringRef S = "{ TS<double> target(42.42); }";
1018 auto Cat = [&](StringRef S) { return (TS + TS2 + T + S).str(); };
1019
1020 EXPECT_EQ(Cat("{ const TS<double> target(42.42); }"),
1021 runCheckOnCode<ValueLTransform>(Cat(S)));
1022 EXPECT_EQ(Cat("{ TS<double> const target(42.42); }"),
1023 runCheckOnCode<ValueRTransform>(Cat(S)));
1024
1025 EXPECT_EQ(Cat("{ const TS<double> target(42.42); }"),
1026 runCheckOnCode<PointeeLTransform>(Cat(S)));
1027 EXPECT_EQ(Cat("{ TS<double> const target(42.42); }"),
1028 runCheckOnCode<PointeeRTransform>(Cat(S)));
1029}
1030
1031// -----------------------------------------------------------------------------
1032// ObjC Pointers
1033// -----------------------------------------------------------------------------
1034
1035TEST(ObjC, SimplePointers) {
1036 StringRef S = "int * target = 0;";
1037 EXPECT_EQ(runCheckOnCode<PointeeLTransform>(S, nullptr, "input.m"),
1038 "const int * target = 0;");
1039 EXPECT_EQ(runCheckOnCode<PointeeRTransform>(S, nullptr, "input.m"),
1040 "int const* target = 0;");
1041 EXPECT_EQ(runCheckOnCode<ValueLTransform>(S, nullptr, "input.m"),
1042 "int * const target = 0;");
1043 EXPECT_EQ(runCheckOnCode<ValueRTransform>(S, nullptr, "input.m"),
1044 "int * const target = 0;");
1045}
1046TEST(ObjC, ClassPointer) {
1047 StringRef TB = "@class Object;\nint main() {\n";
1048 StringRef S = "Object *target;";
1049 StringRef TE = "\n}";
1050 auto Cat = [&](StringRef S) { return (TB + S + TE).str(); };
1051
1052 // FIXME: Not done properly for some reason.
1053 EXPECT_NE(runCheckOnCode<PointeeLTransform>(Cat(S), nullptr, "input.m"),
1054 Cat("const Object *target;"));
1055 EXPECT_NE(runCheckOnCode<PointeeRTransform>(Cat(S), nullptr, "input.m"),
1056 Cat("Object const*target;"));
1057 EXPECT_NE(runCheckOnCode<ValueLTransform>(Cat(S), nullptr, "input.m"),
1058 Cat("Object *const target;"));
1059 EXPECT_NE(runCheckOnCode<ValueRTransform>(Cat(S), nullptr, "input.m"),
1060 Cat("Object *const target;"));
1061}
1062TEST(ObjC, InterfacePointer) {
1063 StringRef TB = "@interface I\n";
1064 StringRef S = "- (void) foo: (int *) target;";
1065 StringRef TE = "\n@end";
1066 auto Cat = [&](StringRef S) { return (TB + S + TE).str(); };
1067
1068 EXPECT_EQ(runCheckOnCode<PointeeLTransform>(Cat(S), nullptr, "input.m"),
1069 Cat("- (void) foo: (const int *) target;"));
1070 EXPECT_EQ(runCheckOnCode<PointeeRTransform>(Cat(S), nullptr, "input.m"),
1071 Cat("- (void) foo: (int const*) target;"));
1072 // FIXME: These transformations are incorrect. ObjC seems to need
1073 // RParenSkipping which is not implemented.
1074 EXPECT_NE(runCheckOnCode<ValueLTransform>(Cat(S), nullptr, "input.m"),
1075 Cat("- (void) foo: (int * const) target;"));
1076 EXPECT_NE(runCheckOnCode<ValueRTransform>(Cat(S), nullptr, "input.m"),
1077 Cat("- (void) foo: (int * const) target;"));
1078}
1079
1080} // namespace test
1081} // namespace tidy
1082} // namespace clang
1083

source code of clang-tools-extra/unittests/clang-tidy/AddConstTest.cpp