[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clangd / unittests / tweaks / ExtractVariableTests.cpp
blob6e38ea77ad68d153d85d2edbf6290bd3e339df42
1 //===-- ExtractVariableTests.cpp --------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "TweakTesting.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
13 namespace clang {
14 namespace clangd {
15 namespace {
17 TWEAK_TEST(ExtractVariable);
19 TEST_F(ExtractVariableTest, Test) {
20 const char *AvailableCases = R"cpp(
21 int xyz(int a = 1) {
22 struct T {
23 int bar(int a = 1);
24 int z;
25 } t;
26 // return statement
27 return [[[[t.b[[a]]r]]([[t.z]])]];
29 void f() {
30 int a = [[5 +]] [[4 * [[[[xyz]]()]]]];
31 // multivariable initialization
32 if(1)
33 int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
34 // if without else
35 if([[1]])
36 a = [[1]] + 1;
37 // if with else
38 if(a < [[3]])
39 if(a == [[4]])
40 a = [[5]] + 1;
41 else
42 a = [[5]] + 1;
43 else if (a < [[4]])
44 a = [[4]] + 1;
45 else
46 a = [[5]] + 1;
47 // for loop
48 for(a = [[1]] + 1; a > [[[[3]] + [[4]]]]; a++)
49 a = [[2]] + 1;
50 // while
51 while(a < [[1]])
52 a = [[1]] + 1;
53 // do while
55 a = [[1]] + 1;
56 while(a < [[3]]);
58 )cpp";
59 EXPECT_AVAILABLE(AvailableCases);
61 ExtraArgs = {"-xc"};
62 const char *AvailableC = R"cpp(
63 void foo() {
64 int x = [[1]];
65 })cpp";
66 EXPECT_AVAILABLE(AvailableC);
67 ExtraArgs = {"-xobjective-c"};
68 const char *AvailableObjC = R"cpp(
69 __attribute__((objc_root_class))
70 @interface Foo
71 @end
72 @implementation Foo
73 - (void)method {
74 int x = [[1 + 2]];
76 @end)cpp";
77 EXPECT_AVAILABLE(AvailableObjC);
78 ExtraArgs = {};
80 const char *NoCrashCases = R"cpp(
81 // error-ok: broken code, but shouldn't crash
82 template<typename T, typename ...Args>
83 struct Test<T, Args...> {
84 Test(const T &v) :val[[(^]]) {}
85 T val;
87 )cpp";
88 EXPECT_UNAVAILABLE(NoCrashCases);
90 const char *UnavailableCases = R"cpp(
91 int xyz(int a = [[1]]) {
92 struct T {
93 int bar(int a = [[1]]) {
94 int b = [[z]];
96 int z = [[1]];
97 } t;
98 return [[t]].bar([[t]].z);
100 void v() { return; }
101 // function default argument
102 void f(int b = [[1]]) {
103 // empty selection
104 int a = ^1 ^+ ^2;
105 // void expressions
106 auto i = new int, j = new int;
107 [[[[delete i]], delete j]];
108 [[v]]();
109 // if
110 if(1)
111 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
112 if(int a = 1)
113 if([[a + 1]] == 4)
114 a = [[[[a]] +]] 1;
115 // for loop
116 for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
117 a = [[a + 1]];
118 // lambda
119 auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;};
120 // assignment
121 xyz([[a = 5]]);
122 xyz([[a *= 5]]);
123 // Variable DeclRefExpr
124 a = [[b]];
125 a = [[xyz()]];
126 // statement expression
127 [[xyz()]];
128 while (a)
129 [[++a]];
130 // label statement
131 goto label;
132 label:
133 a = [[1]];
135 )cpp";
136 EXPECT_UNAVAILABLE(UnavailableCases);
138 // vector of pairs of input and output strings
139 std::vector<std::pair<std::string, std::string>> InputOutputs = {
140 // extraction from variable declaration/assignment
141 {R"cpp(void varDecl() {
142 int a = 5 * (4 + (3 [[- 1)]]);
143 })cpp",
144 R"cpp(void varDecl() {
145 auto placeholder = (3 - 1); int a = 5 * (4 + placeholder);
146 })cpp"},
147 // FIXME: extraction from switch case
148 /*{R"cpp(void f(int a) {
149 if(1)
150 while(a < 1)
151 switch (1) {
152 case 1:
153 a = [[1 + 2]];
154 break;
155 default:
156 break;
158 })cpp",
159 R"cpp(void f(int a) {
160 auto placeholder = 1 + 2; if(1)
161 while(a < 1)
162 switch (1) {
163 case 1:
164 a = placeholder;
165 break;
166 default:
167 break;
169 })cpp"},*/
170 // Macros
171 {R"cpp(#define PLUS(x) x++
172 void f(int a) {
173 int y = PLUS([[1+a]]);
174 })cpp",
175 /*FIXME: It should be extracted like this.
176 R"cpp(#define PLUS(x) x++
177 void f(int a) {
178 auto placeholder = 1+a; int y = PLUS(placeholder);
179 })cpp"},*/
180 R"cpp(#define PLUS(x) x++
181 void f(int a) {
182 auto placeholder = PLUS(1+a); int y = placeholder;
183 })cpp"},
184 // ensure InsertionPoint isn't inside a macro
185 {R"cpp(#define LOOP(x) while (1) {a = x;}
186 void f(int a) {
187 if(1)
188 LOOP(5 + [[3]])
189 })cpp",
190 R"cpp(#define LOOP(x) while (1) {a = x;}
191 void f(int a) {
192 auto placeholder = 3; if(1)
193 LOOP(5 + placeholder)
194 })cpp"},
195 {R"cpp(#define LOOP(x) do {x;} while(1);
196 void f(int a) {
197 if(1)
198 LOOP(5 + [[3]])
199 })cpp",
200 R"cpp(#define LOOP(x) do {x;} while(1);
201 void f(int a) {
202 auto placeholder = 3; if(1)
203 LOOP(5 + placeholder)
204 })cpp"},
205 // attribute testing
206 {R"cpp(void f(int a) {
207 [ [gsl::suppress("type")] ] for (;;) a = [[1]] + 1;
208 })cpp",
209 R"cpp(void f(int a) {
210 auto placeholder = 1; [ [gsl::suppress("type")] ] for (;;) a = placeholder + 1;
211 })cpp"},
212 // MemberExpr
213 {R"cpp(class T {
214 T f() {
215 return [[T().f()]].f();
217 };)cpp",
218 R"cpp(class T {
219 T f() {
220 auto placeholder = T().f(); return placeholder.f();
222 };)cpp"},
223 // Function DeclRefExpr
224 {R"cpp(int f() {
225 return [[f]]();
226 })cpp",
227 R"cpp(int f() {
228 auto placeholder = f(); return placeholder;
229 })cpp"},
230 // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = [[1]];
231 // since the attr is inside the DeclStmt and the bounds of
232 // DeclStmt don't cover the attribute.
234 // Binary subexpressions
235 {R"cpp(void f() {
236 int x = 1 + [[2 + 3 + 4]] + 5;
237 })cpp",
238 R"cpp(void f() {
239 auto placeholder = 2 + 3 + 4; int x = 1 + placeholder + 5;
240 })cpp"},
241 {R"cpp(void f() {
242 int x = [[1 + 2 + 3]] + 4 + 5;
243 })cpp",
244 R"cpp(void f() {
245 auto placeholder = 1 + 2 + 3; int x = placeholder + 4 + 5;
246 })cpp"},
247 {R"cpp(void f() {
248 int x = 1 + 2 + [[3 + 4 + 5]];
249 })cpp",
250 R"cpp(void f() {
251 auto placeholder = 3 + 4 + 5; int x = 1 + 2 + placeholder;
252 })cpp"},
253 // Non-associative operations have no special support
254 {R"cpp(void f() {
255 int x = 1 - [[2 - 3 - 4]] - 5;
256 })cpp",
257 R"cpp(void f() {
258 auto placeholder = 1 - 2 - 3 - 4; int x = placeholder - 5;
259 })cpp"},
260 // A mix of associative operators isn't associative.
261 {R"cpp(void f() {
262 int x = 0 + 1 * [[2 + 3]] * 4 + 5;
263 })cpp",
264 R"cpp(void f() {
265 auto placeholder = 1 * 2 + 3 * 4; int x = 0 + placeholder + 5;
266 })cpp"},
267 // Overloaded operators are supported, we assume associativity
268 // as if they were built-in.
269 {R"cpp(struct S {
270 S(int);
272 S operator+(S, S);
274 void f() {
275 S x = S(1) + [[S(2) + S(3) + S(4)]] + S(5);
276 })cpp",
277 R"cpp(struct S {
278 S(int);
280 S operator+(S, S);
282 void f() {
283 auto placeholder = S(2) + S(3) + S(4); S x = S(1) + placeholder + S(5);
284 })cpp"},
285 // Don't try to analyze across macro boundaries
286 // FIXME: it'd be nice to do this someday (in a safe way)
287 {R"cpp(#define ECHO(X) X
288 void f() {
289 int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
290 })cpp",
291 R"cpp(#define ECHO(X) X
292 void f() {
293 auto placeholder = 1 + ECHO(2 + 3) + 4; int x = placeholder + 5;
294 })cpp"},
295 {R"cpp(#define ECHO(X) X
296 void f() {
297 int x = 1 + [[ECHO(2) + ECHO(3) + 4]] + 5;
298 })cpp",
299 R"cpp(#define ECHO(X) X
300 void f() {
301 auto placeholder = 1 + ECHO(2) + ECHO(3) + 4; int x = placeholder + 5;
302 })cpp"},
304 for (const auto &IO : InputOutputs) {
305 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
308 ExtraArgs = {"-xc"};
309 InputOutputs = {
310 // Function Pointers
311 {R"cpp(struct Handlers {
312 void (*handlerFunc)(int);
314 void runFunction(void (*func)(int)) {}
315 void f(struct Handlers *handler) {
316 runFunction([[handler->handlerFunc]]);
317 })cpp",
318 R"cpp(struct Handlers {
319 void (*handlerFunc)(int);
321 void runFunction(void (*func)(int)) {}
322 void f(struct Handlers *handler) {
323 void (*placeholder)(int) = handler->handlerFunc; runFunction(placeholder);
324 })cpp"},
325 {R"cpp(int (*foo(char))(int);
326 void bar() {
327 (void)[[foo('c')]];
328 })cpp",
329 R"cpp(int (*foo(char))(int);
330 void bar() {
331 int (*placeholder)(int) = foo('c'); (void)placeholder;
332 })cpp"},
333 // Arithmetic on typedef types preserves typedef types
334 {R"cpp(typedef long NSInteger;
335 void varDecl() {
336 NSInteger a = 2 * 5;
337 NSInteger b = [[a * 7]] + 3;
338 })cpp",
339 R"cpp(typedef long NSInteger;
340 void varDecl() {
341 NSInteger a = 2 * 5;
342 NSInteger placeholder = a * 7; NSInteger b = placeholder + 3;
343 })cpp"},
345 for (const auto &IO : InputOutputs) {
346 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
349 ExtraArgs = {"-xobjective-c"};
350 EXPECT_UNAVAILABLE(R"cpp(
351 __attribute__((objc_root_class))
352 @interface Foo
353 - (void)setMethod1:(int)a;
354 - (int)method1;
355 @property int prop1;
356 @end
357 @implementation Foo
358 - (void)method {
359 [[self.method1]] = 1;
360 [[self.method1]] += 1;
361 [[self.prop1]] = 1;
362 [[self.prop1]] += 1;
364 @end)cpp");
365 InputOutputs = {
366 // Support ObjC property references (explicit property getter).
367 {R"cpp(__attribute__((objc_root_class))
368 @interface Foo
369 @property int prop1;
370 @end
371 @implementation Foo
372 - (void)method {
373 int x = [[self.prop1]] + 1;
375 @end)cpp",
376 R"cpp(__attribute__((objc_root_class))
377 @interface Foo
378 @property int prop1;
379 @end
380 @implementation Foo
381 - (void)method {
382 int placeholder = self.prop1; int x = placeholder + 1;
384 @end)cpp"},
385 // Support ObjC property references (implicit property getter).
386 {R"cpp(__attribute__((objc_root_class))
387 @interface Foo
388 - (int)method1;
389 @end
390 @implementation Foo
391 - (void)method {
392 int x = [[self.method1]] + 1;
394 @end)cpp",
395 R"cpp(__attribute__((objc_root_class))
396 @interface Foo
397 - (int)method1;
398 @end
399 @implementation Foo
400 - (void)method {
401 int placeholder = self.method1; int x = placeholder + 1;
403 @end)cpp"},
405 for (const auto &IO : InputOutputs) {
406 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
410 } // namespace
411 } // namespace clangd
412 } // namespace clang