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 | |
10 | namespace clang { |
11 | namespace tidy { |
12 | |
13 | namespace { |
14 | using namespace clang::ast_matchers; |
15 | using namespace utils::fixit; |
16 | |
17 | template <QualifierTarget CT, QualifierPolicy CP> |
18 | class ConstTransform : public ClangTidyCheck { |
19 | public: |
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 | |
39 | namespace test { |
40 | using PointeeLTransform = |
41 | ConstTransform<QualifierTarget::Pointee, QualifierPolicy::Left>; |
42 | using PointeeRTransform = |
43 | ConstTransform<QualifierTarget::Pointee, QualifierPolicy::Right>; |
44 | |
45 | using ValueLTransform = |
46 | ConstTransform<QualifierTarget::Value, QualifierPolicy::Left>; |
47 | using ValueRTransform = |
48 | ConstTransform<QualifierTarget::Value, QualifierPolicy::Right>; |
49 | |
50 | // ---------------------------------------------------------------------------- |
51 | // Test Value-like types. Everything with indirection is done later. |
52 | // ---------------------------------------------------------------------------- |
53 | |
54 | TEST(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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
220 | TEST(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 | |
238 | TEST(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 | } |
251 | TEST(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 | } |
264 | TEST(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 | } |
277 | TEST(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 | } |
290 | TEST(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 | |
308 | TEST(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 | } |
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)); |
327 | |
328 | EXPECT_EQ("int const&& target = 42;" , |
329 | runCheckOnCode<ValueRTransform>(Snippet)); |
330 | EXPECT_EQ("int const&& target = 42;" , |
331 | runCheckOnCode<PointeeRTransform>(Snippet)); |
332 | } |
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)); |
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 | } |
345 | TEST(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 | } |
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(); }; |
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 | } |
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(); }; |
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 | |
393 | TEST(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 | } |
406 | TEST(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 | } |
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(); }; |
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 | } |
434 | TEST(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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
477 | TEST(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 | } |
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(); }; |
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 | } |
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(); }; |
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 | |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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. |
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;); }" ; |
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 | } |
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; );" ; |
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 | |
812 | TEST(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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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) |
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 | |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | } |
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(); }; |
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 | |
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;" ); |
1045 | } |
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(); }; |
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 | } |
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(); }; |
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 | |