1 //===-- ExtractVariableTests.cpp --------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "TweakTesting.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
17 TWEAK_TEST(ExtractVariable
);
19 TEST_F(ExtractVariableTest
, Test
) {
20 const char *AvailableCases
= R
"cpp(
27 return [[[[t.b[[a]]r]]([[t.z]])]];
30 int a = [[5 +]] [[4 * [[[[xyz]]()]]]];
31 // multivariable initialization
33 int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
48 for(a = [[1]] + 1; a > [[[[3]] + [[4]]]]; a++)
59 EXPECT_AVAILABLE(AvailableCases
);
62 const char *AvailableC
= R
"cpp(
66 EXPECT_AVAILABLE(AvailableC
);
67 ExtraArgs
= {"-xobjective-c"};
68 const char *AvailableObjC
= R
"cpp(
69 __attribute__((objc_root_class))
77 EXPECT_AVAILABLE(AvailableObjC
);
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[[(^]]) {}
88 EXPECT_UNAVAILABLE(NoCrashCases
);
90 const char *UnavailableCases
= R
"cpp(
91 int xyz(int a = [[1]]) {
93 int bar(int a = [[1]]) {
98 return [[t]].bar([[t]].z);
101 // function default argument
102 void f(int b = [[1]]) {
106 auto i = new int, j = new int;
107 [[[[delete i]], delete j]];
111 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
116 for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
119 auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;};
123 // Variable DeclRefExpr
126 // statement expression
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)]]);
144 R
"cpp(void varDecl() {
145 auto placeholder = (3 - 1); int a = 5 * (4 + placeholder);
147 // FIXME: extraction from switch case
148 /*{R"cpp(void f(int a) {
159 R"cpp(void f(int a) {
160 auto placeholder = 1 + 2; if(1)
171 {R
"cpp(#define PLUS(x) x++
173 int y = PLUS([[1+a]]);
175 /*FIXME: It should be extracted like this.
176 R"cpp(#define PLUS(x) x++
178 auto placeholder = 1+a; int y = PLUS(placeholder);
180 R
"cpp(#define PLUS(x) x++
182 auto placeholder = PLUS(1+a); int y = placeholder;
184 // ensure InsertionPoint isn't inside a macro
185 {R
"cpp(#define LOOP(x) while (1) {a = x;}
190 R
"cpp(#define LOOP(x) while (1) {a = x;}
192 auto placeholder = 3; if(1)
193 LOOP(5 + placeholder)
195 {R
"cpp(#define LOOP(x) do {x;} while(1);
200 R
"cpp(#define LOOP(x) do {x;} while(1);
202 auto placeholder = 3; if(1)
203 LOOP(5 + placeholder)
206 {R
"cpp(void f(int a) {
207 [ [gsl::suppress("type
")] ] for (;;) a = [[1]] + 1;
209 R
"cpp(void f(int a) {
210 auto placeholder = 1; [ [gsl::suppress("type
")] ] for (;;) a = placeholder + 1;
215 return [[T().f()]].f();
220 auto placeholder = T().f(); return placeholder.f();
223 // Function DeclRefExpr
228 auto placeholder = f(); return placeholder;
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
236 int x = 1 + [[2 + 3 + 4]] + 5;
239 auto placeholder = 2 + 3 + 4; int x = 1 + placeholder + 5;
242 int x = [[1 + 2 + 3]] + 4 + 5;
245 auto placeholder = 1 + 2 + 3; int x = placeholder + 4 + 5;
248 int x = 1 + 2 + [[3 + 4 + 5]];
251 auto placeholder = 3 + 4 + 5; int x = 1 + 2 + placeholder;
253 // Non-associative operations have no special support
255 int x = 1 - [[2 - 3 - 4]] - 5;
258 auto placeholder = 1 - 2 - 3 - 4; int x = placeholder - 5;
260 // A mix of associative operators isn't associative.
262 int x = 0 + 1 * [[2 + 3]] * 4 + 5;
265 auto placeholder = 1 * 2 + 3 * 4; int x = 0 + placeholder + 5;
267 // Overloaded operators are supported, we assume associativity
268 // as if they were built-in.
275 S x = S(1) + [[S(2) + S(3) + S(4)]] + S(5);
283 auto placeholder = S(2) + S(3) + S(4); S x = S(1) + placeholder + S(5);
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
289 int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
291 R
"cpp(#define ECHO(X) X
293 auto placeholder = 1 + ECHO(2 + 3) + 4; int x = placeholder + 5;
295 {R
"cpp(#define ECHO(X) X
297 int x = 1 + [[ECHO(2) + ECHO(3) + 4]] + 5;
299 R
"cpp(#define ECHO(X) X
301 auto placeholder = 1 + ECHO(2) + ECHO(3) + 4; int x = placeholder + 5;
304 for (const auto &IO
: InputOutputs
) {
305 EXPECT_EQ(IO
.second
, apply(IO
.first
)) << IO
.first
;
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]]);
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);
325 {R
"cpp(int (*foo(char))(int);
329 R
"cpp(int (*foo(char))(int);
331 int (*placeholder)(int) = foo('c'); (void)placeholder;
333 // Arithmetic on typedef types preserves typedef types
334 {R
"cpp(typedef long NSInteger;
337 NSInteger b = [[a * 7]] + 3;
339 R
"cpp(typedef long NSInteger;
342 NSInteger placeholder = a * 7; NSInteger b = placeholder + 3;
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))
353 - (void)setMethod1:(int)a;
359 [[self.method1]] = 1;
360 [[self.method1]] += 1;
366 // Support ObjC property references (explicit property getter).
367 {R
"cpp(__attribute__((objc_root_class))
373 int x = [[self.prop1]] + 1;
376 R
"cpp(__attribute__((objc_root_class))
382 int placeholder = self.prop1; int x = placeholder + 1;
385 // Support ObjC property references (implicit property getter).
386 {R
"cpp(__attribute__((objc_root_class))
392 int x = [[self.method1]] + 1;
395 R
"cpp(__attribute__((objc_root_class))
401 int placeholder = self.method1; int x = placeholder + 1;
405 for (const auto &IO
: InputOutputs
) {
406 EXPECT_EQ(IO
.second
, apply(IO
.first
)) << IO
.first
;
411 } // namespace clangd