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"
14 using namespace clang::ast_matchers
;
15 using namespace utils::fixit
;
17 template <QualifierTarget CT
, QualifierPolicy CP
>
18 class ConstTransform
: public ClangTidyCheck
{
20 ConstTransform(StringRef CheckName
, ClangTidyContext
*Context
)
21 : ClangTidyCheck(CheckName
, Context
) {}
23 void registerMatchers(MatchFinder
*Finder
) override
{
24 Finder
->addMatcher(varDecl(hasName("target")).bind("var"), this);
27 void check(const MatchFinder::MatchResult
&Result
) override
{
28 const auto *D
= Result
.Nodes
.getNodeAs
<VarDecl
>("var");
29 using utils::fixit::addQualifierToVarDecl
;
30 std::optional
<FixItHint
> Fix
=
31 addQualifierToVarDecl(*D
, *Result
.Context
, Qualifiers::Const
, CT
, CP
);
32 auto Diag
= diag(D
->getBeginLoc(), "doing const transformation");
40 using PointeeLTransform
=
41 ConstTransform
<QualifierTarget::Pointee
, QualifierPolicy::Left
>;
42 using PointeeRTransform
=
43 ConstTransform
<QualifierTarget::Pointee
, QualifierPolicy::Right
>;
45 using ValueLTransform
=
46 ConstTransform
<QualifierTarget::Value
, QualifierPolicy::Left
>;
47 using ValueRTransform
=
48 ConstTransform
<QualifierTarget::Value
, QualifierPolicy::Right
>;
50 // ----------------------------------------------------------------------------
51 // Test Value-like types. Everything with indirection is done later.
52 // ----------------------------------------------------------------------------
54 TEST(Values
, Builtin
) {
55 StringRef Snippet
= "int target = 0;";
57 EXPECT_EQ("const int target = 0;", runCheckOnCode
<ValueLTransform
>(Snippet
));
58 EXPECT_EQ("const int target = 0;",
59 runCheckOnCode
<PointeeLTransform
>(Snippet
));
61 EXPECT_EQ("int const target = 0;", runCheckOnCode
<ValueRTransform
>(Snippet
));
62 EXPECT_EQ("int const target = 0;",
63 runCheckOnCode
<PointeeRTransform
>(Snippet
));
65 TEST(Values
, TypedefBuiltin
) {
66 StringRef T
= "typedef int MyInt;";
67 StringRef S
= "MyInt target = 0;";
68 auto Cat
= [&T
](StringRef S
) { return (T
+ S
).str(); };
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
)));
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
)));
80 TEST(Values
, TypedefBuiltinPointer
) {
81 StringRef T
= "typedef int* MyInt;";
82 StringRef S
= "MyInt target = nullptr;";
83 auto Cat
= [&T
](StringRef S
) { return (T
+ S
).str(); };
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
)));
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
)));
95 TEST(Values
, UsingBuiltin
) {
96 StringRef T
= "using MyInt = int;";
97 StringRef S
= "MyInt target = 0;";
98 auto Cat
= [&T
](StringRef S
) { return (T
+ S
).str(); };
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
)));
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
)));
110 TEST(Values
, UsingBuiltinPointer
) {
111 StringRef T
= "using MyInt = int*;";
112 StringRef S
= "MyInt target = nullptr;";
113 auto Cat
= [&T
](StringRef S
) { return (T
+ S
).str(); };
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
)));
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
)));
125 TEST(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(); };
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
)));
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
)));
140 TEST(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(); };
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
)));
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
)));
155 TEST(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(); };
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
)));
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
)));
170 TEST(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(); };
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
)));
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
)));
185 TEST(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(); };
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
)));
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
)));
202 TEST(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(); };
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
)));
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
)));
220 TEST(Values
, Parens
) {
221 StringRef Snippet
= "int ((target)) = 0;";
223 EXPECT_EQ("const int ((target)) = 0;",
224 runCheckOnCode
<ValueLTransform
>(Snippet
));
225 EXPECT_EQ("const int ((target)) = 0;",
226 runCheckOnCode
<PointeeLTransform
>(Snippet
));
228 EXPECT_EQ("int const ((target)) = 0;",
229 runCheckOnCode
<ValueRTransform
>(Snippet
));
230 EXPECT_EQ("int const ((target)) = 0;",
231 runCheckOnCode
<PointeeRTransform
>(Snippet
));
234 // ----------------------------------------------------------------------------
235 // Test builtin-arrays
236 // ----------------------------------------------------------------------------
238 TEST(Arrays
, Builtin
) {
239 StringRef Snippet
= "int target[][1] = {{1}, {2}, {3}};";
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
));
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
));
251 TEST(Arrays
, BuiltinParens
) {
252 StringRef Snippet
= "int ((target))[][1] = {{1}, {2}, {3}};";
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
));
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
));
264 TEST(Arrays
, Pointers
) {
265 StringRef Snippet
= "int x; int* target[] = {&x, &x, &x};";
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
));
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
));
277 TEST(Arrays
, PointerPointers
) {
278 StringRef Snippet
= "int* x = nullptr; int** target[] = {&x, &x, &x};";
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
));
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
));
290 TEST(Arrays
, PointersParens
) {
291 StringRef Snippet
= "int x; int* (target)[] = {&x, &x, &x};";
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
));
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
));
304 // ----------------------------------------------------------------------------
305 // Test reference types. This does not include pointers and arrays.
306 // ----------------------------------------------------------------------------
308 TEST(Reference
, LValueBuiltin
) {
309 StringRef Snippet
= "int x = 42; int& target = x;";
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
));
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
));
321 TEST(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
));
328 EXPECT_EQ("int const&& target = 42;",
329 runCheckOnCode
<ValueRTransform
>(Snippet
));
330 EXPECT_EQ("int const&& target = 42;",
331 runCheckOnCode
<PointeeRTransform
>(Snippet
));
333 TEST(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
));
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
));
345 TEST(Reference
, LValueParens
) {
346 StringRef Snippet
= "int x = 42; int ((& target)) = x;";
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
));
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
));
358 TEST(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(); };
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
)));
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
)));
373 TEST(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(); };
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
)));
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
)));
389 // ----------------------------------------------------------------------------
390 // Test pointers types.
391 // ----------------------------------------------------------------------------
393 TEST(Pointers
, SingleBuiltin
) {
394 StringRef Snippet
= "int* target = nullptr;";
396 EXPECT_EQ("int* const target = nullptr;",
397 runCheckOnCode
<ValueLTransform
>(Snippet
));
398 EXPECT_EQ("int* const target = nullptr;",
399 runCheckOnCode
<ValueRTransform
>(Snippet
));
401 EXPECT_EQ("const int* target = nullptr;",
402 runCheckOnCode
<PointeeLTransform
>(Snippet
));
403 EXPECT_EQ("int const* target = nullptr;",
404 runCheckOnCode
<PointeeRTransform
>(Snippet
));
406 TEST(Pointers
, MultiBuiltin
) {
407 StringRef Snippet
= "int** target = nullptr;";
409 EXPECT_EQ("int** const target = nullptr;",
410 runCheckOnCode
<ValueLTransform
>(Snippet
));
411 EXPECT_EQ("int** const target = nullptr;",
412 runCheckOnCode
<ValueRTransform
>(Snippet
));
414 EXPECT_EQ("int* const* target = nullptr;",
415 runCheckOnCode
<PointeeLTransform
>(Snippet
));
416 EXPECT_EQ("int* const* target = nullptr;",
417 runCheckOnCode
<PointeeRTransform
>(Snippet
));
419 TEST(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(); };
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
)));
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
)));
434 TEST(Pointers
, Parens
) {
435 StringRef Snippet
= "int ((**target)) = nullptr;";
437 EXPECT_EQ("int ((**const target)) = nullptr;",
438 runCheckOnCode
<ValueLTransform
>(Snippet
));
439 EXPECT_EQ("int ((**const target)) = nullptr;",
440 runCheckOnCode
<ValueRTransform
>(Snippet
));
442 EXPECT_EQ("int ((* const*target)) = nullptr;",
443 runCheckOnCode
<PointeeLTransform
>(Snippet
));
444 EXPECT_EQ("int ((* const*target)) = nullptr;",
445 runCheckOnCode
<PointeeRTransform
>(Snippet
));
447 TEST(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(); };
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
)));
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
)));
462 TEST(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(); };
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
)));
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
)));
477 TEST(Pointers
, FunctionPointer
) {
478 StringRef S
= "int (*target)(float, int, double) = nullptr;";
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
));
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
));
490 S
= "int (((*target)))(float, int, double) = nullptr;";
491 EXPECT_EQ("int (((*const target)))(float, int, double) = nullptr;",
492 runCheckOnCode
<PointeeRTransform
>(S
));
494 TEST(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(); };
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
)));
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
)));
509 S
= "int (A::*((target)))() = &A::f;";
510 EXPECT_EQ(Cat("int (A::*const ((target)))() = &A::f;"),
511 runCheckOnCode
<ValueLTransform
>(Cat(S
)));
513 TEST(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(); };
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
)));
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
)));
528 S
= "int A::*((target)) = &A::member;";
529 EXPECT_EQ(Cat("int A::*const ((target)) = &A::member;"),
530 runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
533 // ----------------------------------------------------------------------------
534 // Test TagTypes (struct, class, unions, enums)
535 // ----------------------------------------------------------------------------
537 TEST(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(); };
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
)));
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
)));
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
)));
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
)));
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
)));
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
)));
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
));
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
));
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
));
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
));
596 TEST(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(); };
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
)));
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
)));
612 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode
<ValueLTransform
>(Cat(S
)));
613 EXPECT_EQ(Cat("const Foo target;"),
614 runCheckOnCode
<PointeeLTransform
>(Cat(S
)));
616 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode
<ValueRTransform
>(Cat(S
)));
617 EXPECT_EQ(Cat("Foo const target;"),
618 runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
621 EXPECT_EQ(Cat("const Foo (target);"),
622 runCheckOnCode
<ValueLTransform
>(Cat(S
)));
623 EXPECT_EQ(Cat("const Foo (target);"),
624 runCheckOnCode
<PointeeLTransform
>(Cat(S
)));
626 EXPECT_EQ(Cat("Foo const (target);"),
627 runCheckOnCode
<ValueRTransform
>(Cat(S
)));
628 EXPECT_EQ(Cat("Foo const (target);"),
629 runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
631 TEST(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(); };
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
)));
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
)));
647 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode
<ValueLTransform
>(Cat(S
)));
648 EXPECT_EQ(Cat("const Foo target;"),
649 runCheckOnCode
<PointeeLTransform
>(Cat(S
)));
651 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode
<ValueRTransform
>(Cat(S
)));
652 EXPECT_EQ(Cat("Foo const target;"),
653 runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
656 EXPECT_EQ(Cat("const Foo (target);"),
657 runCheckOnCode
<ValueLTransform
>(Cat(S
)));
658 EXPECT_EQ(Cat("const Foo (target);"),
659 runCheckOnCode
<PointeeLTransform
>(Cat(S
)));
661 EXPECT_EQ(Cat("Foo const (target);"),
662 runCheckOnCode
<ValueRTransform
>(Cat(S
)));
663 EXPECT_EQ(Cat("Foo const (target);"),
664 runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
666 TEST(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(); };
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
)));
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
)));
682 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode
<ValueLTransform
>(Cat(S
)));
683 EXPECT_EQ(Cat("const Foo target;"),
684 runCheckOnCode
<PointeeLTransform
>(Cat(S
)));
686 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode
<ValueRTransform
>(Cat(S
)));
687 EXPECT_EQ(Cat("Foo const target;"),
688 runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
691 EXPECT_EQ(Cat("const Foo (target);"),
692 runCheckOnCode
<ValueLTransform
>(Cat(S
)));
693 EXPECT_EQ(Cat("const Foo (target);"),
694 runCheckOnCode
<PointeeLTransform
>(Cat(S
)));
696 EXPECT_EQ(Cat("Foo const (target);"),
697 runCheckOnCode
<ValueRTransform
>(Cat(S
)));
698 EXPECT_EQ(Cat("Foo const (target);"),
699 runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
702 // ----------------------------------------------------------------------------
703 // Test Macro expansions.
704 // ----------------------------------------------------------------------------
706 TEST(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(); };
711 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode
<ValueLTransform
>(Cat(S
)));
712 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode
<ValueRTransform
>(Cat(S
)));
714 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode
<PointeeLTransform
>(Cat(S
)));
715 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
717 TEST(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(); };
722 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
723 runCheckOnCode
<ValueLTransform
>(Cat(S
)));
724 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
725 runCheckOnCode
<ValueRTransform
>(Cat(S
)));
727 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
728 runCheckOnCode
<PointeeLTransform
>(Cat(S
)));
729 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
730 runCheckOnCode
<PointeeRTransform
>(Cat(S
)));
732 TEST(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(); };
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
)));
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
)));
747 TEST(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(); };
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
)));
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
)));
764 TEST(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(); };
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
)));
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
)));
781 // This failed in LLVM.
782 TEST(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;); }";
787 auto Cat
= [&](StringRef S
) { return (M
+ F
+ V
).str(); };
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
)));
794 TEST(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; );";
800 auto Cat
= [&](StringRef S
) { return (M
+ F
+ V
+ E
).str(); };
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
)));
808 // ----------------------------------------------------------------------------
809 // Test template code.
810 // ----------------------------------------------------------------------------
812 TEST(Template
, TemplateVariable
) {
813 StringRef T
= "template <typename T> T target = 3.1415;";
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
));
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
));
825 TEST(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(); };
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
)));
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
)));
840 TEST(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(); };
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
)));
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
)));
855 TEST(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(); };
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
)));
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
)));
870 TEST(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
)
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
)));
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
)));
901 TEST(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(); };
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
)));
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
)));
917 TEST(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(); };
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
)));
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
)));
933 TEST(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(); };
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
)));
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
)));
949 TEST(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(); };
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
)));
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
)));
965 TEST(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(); };
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
)));
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
)));
981 TEST(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(); };
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
)));
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
)));
997 TEST(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(); };
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
)));
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
)));
1013 TEST(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(); };
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
)));
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
)));
1031 // -----------------------------------------------------------------------------
1033 // -----------------------------------------------------------------------------
1035 TEST(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;");
1046 TEST(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(); };
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;"));
1062 TEST(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(); };
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;"));
1082 } // namespace clang