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