10#include "gmock/gmock.h"
11#include "gtest/gtest.h"
19TEST_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++)
62 const char *AvailableC = R
"cpp(
69 const char *NoCrashCasesC = R
"cpp(
70 // error-ok: broken code, but shouldn't crash
75 ExtraArgs = {"-xobjective-c"};
76 const char *AvailableObjC = R
"cpp(
77 __attribute__((objc_root_class))
88 const char *NoCrashCases = R
"cpp(
89 // error-ok: broken code, but shouldn't crash
90 template<typename T, typename ...Args>
91 struct Test<T, Args...> {
92 Test(const T &v) :val[[(^]]) {}
98 const char *UnavailableCases = R
"cpp(
99 int xyz(int a = [[1]]) {
101 int bar(int a = [[1]]) {
106 return [[t]].bar([[t]].z);
110 // function default argument
111 void f(int b = [[1]]) {
115 auto i = new int, j = new int;
116 [[[[delete i]], delete j]];
120 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
125 for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
128 auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;};
132 // Variable DeclRefExpr
135 // statement expression
153 // lambdas: default args, cannot extract into function-local scope
154 [](int x = [[10]]){};
155 [](auto h = [[ [i = [](){}](){} ]]) {};
157 // lambdas: default args
158 // Extracting from capture initializers is usually fine,
159 // but not if the capture itself is nested inside a default argument
160 [](auto h = [i = [[ [](){} ]]](){}) {};
161 [](auto h = [i = [[ 42 ]]](){}) {};
165 if ([[ [&](){ return a + 1; } ]]() == 4)
168 for (int c = 0; [[ [&]() { return c < b; } ]](); ++c) {
170 for (int c = 0; [[ [&]() { return c < b; } () ]]; ++c) {
173 // lambdas: scope with structured binding
179 if (const auto [x, y] = c; x > y)
180 auto f = [[ [&]() { return x + y; } ]];
182 // lambdas: referencing outside variables that block extraction
183 // in trailing return type or in a decltype used
186 if ([[ []() -> decltype(a) { return 1; } ]] () == 4)
189 if ([[ [](int x = decltype(a){}) { return 1; } ]] () == 4)
192 if ([[ [](decltype(a) x) { return 1; } ]] (42) == 4)
198 ExtraArgs = {"-std=c++20"};
199 const char *UnavailableCasesCXX20 = R
"cpp(
200 template <typename T>
201 concept Constraint = requires (T t) { true; };
203 // lambdas: referencing outside variables that block extraction
204 // in requires clause or defaulted explicit template parameters
206 if ([[ [](auto b) requires (Constraint<decltype(a)> && Constraint<decltype(b)>) { return true; } ]] (a))
210 if ([[ []<typename T = decltype(a)>(T b) { return true; } ]] (a))
218 std::vector<std::pair<std::string, std::string>> InputOutputs = {
220 {R
"cpp(void varDecl() {
221 int a = 5 * (4 + (3 [[- 1)]]);
223 R"cpp(void varDecl() {
224 auto placeholder = (3 - 1); int a = 5 * (4 + placeholder);
250 {R
"cpp(#define PLUS(x) x++
252 int y = PLUS([[1+a]]);
259 R
"cpp(#define PLUS(x) x++
261 auto placeholder = PLUS(1+a); int y = placeholder;
264 {R
"cpp(#define LOOP(x) while (1) {a = x;}
269 R"cpp(#define LOOP(x) while (1) {a = x;}
271 auto placeholder = 3; if(1)
272 LOOP(5 + placeholder)
274 {R"cpp(#define LOOP(x) do {x;} while(1);
279 R"cpp(#define LOOP(x) do {x;} while(1);
281 auto placeholder = 3; if(1)
282 LOOP(5 + placeholder)
285 {R
"cpp(void f(int a) {
286 [ [gsl::suppress("type")] ] for (;;) a = [[1]] + 1;
288 R"cpp(void f(int a) {
289 auto placeholder = 1; [ [gsl::suppress("type")] ] for (;;) a = placeholder + 1;
294 return [[T().f()]].f();
299 auto placeholder = T().f(); return placeholder.f();
307 auto placeholder = f(); return placeholder;
315 int x = 1 + [[2 + 3 + 4]] + 5;
318 auto placeholder = 2 + 3 + 4; int x = 1 + placeholder + 5;
321 int x = [[1 + 2 + 3]] + 4 + 5;
324 auto placeholder = 1 + 2 + 3; int x = placeholder + 4 + 5;
327 int x = 1 + 2 + [[3 + 4 + 5]];
330 auto placeholder = 3 + 4 + 5; int x = 1 + 2 + placeholder;
334 int x = 1 - [[2 - 3 - 4]] - 5;
337 auto placeholder = 1 - 2 - 3 - 4; int x = placeholder - 5;
341 int x = 0 + 1 * [[2 + 3]] * 4 + 5;
344 auto placeholder = 1 * 2 + 3 * 4; int x = 0 + placeholder + 5;
354 S x = S(1) + [[S(2) + S(3) + S(4)]] + S(5);
362 auto placeholder = S(2) + S(3) + S(4); S x = S(1) + placeholder + S(5);
365 {R
"cpp(template <typename T> void f(T) {}
367 f([[ [](){ return 42; }]]);
370 R"cpp(template <typename T> void f(T) {}
372 auto placeholder = [](){ return 42; }; f( placeholder);
375 {R"cpp(template <typename T> void f(T) {}
377 f([x = [[40 + 2]] ](){ return 42; });
380 R"cpp(template <typename T> void f(T) {}
382 auto placeholder = 40 + 2; f([x = placeholder ](){ return 42; });
385 {R"cpp(auto foo(int VarA) {
387 return [[ [VarA, VarC = 42 + VarA](int VarB) { return VarA + VarB + VarC; }]];
391 R"cpp(auto foo(int VarA) {
393 auto placeholder = [VarA, VarC = 42 + VarA](int VarB) { return VarA + VarB + VarC; }; return placeholder;
397 {R"cpp(template <typename T> void f(T) {}
399 f([[ [&var](){ auto internal_val = 42; return var + internal_val; }]]);
402 R"cpp(template <typename T> void f(T) {}
404 auto placeholder = [&var](){ auto internal_val = 42; return var + internal_val; }; f( placeholder);
407 {R"cpp(template <typename T> void f(T) { }
411 f([[ [&var, &local_var, this]() {
412 auto internal_val = 42;
413 return var + local_var + internal_val + member;
420 R"cpp(template <typename T> void f(T) { }
424 auto placeholder = [&var, &local_var, this]() {
425 auto internal_val = 42;
426 return var + local_var + internal_val + member;
433 {R"cpp(void f() { auto x = [[ [](){ return 42; }]]; })cpp",
434 R"cpp(void f() { auto placeholder = [](){ return 42; }; auto x = placeholder; })cpp"},
436 template <typename T>
437 auto sink(T f) { return f(); }
439 return sink([[ []() { return 42; }]]);
443 template <typename T>
444 auto sink(T f) { return f(); }
446 auto placeholder = []() { return 42; }; return sink( placeholder);
452 if ([[ [&](){ return a + 1; } ]]() == 4)
459 auto placeholder = [&](){ return a + 1; }; if ( placeholder () == 4)
466 if ([[ [&](){ return a + 1; }() ]] == 4)
473 auto placeholder = [&](){ return a + 1; }(); if ( placeholder == 4)
478 template <typename T>
479 auto call(T t) { return t(); }
482 return [[ call([](){ int a = 1; return a + 1; }) ]] + 5;
485 template <typename T>
486 auto call(T t) { return t(); }
489 auto placeholder = call([](){ int a = 1; return a + 1; }); return placeholder + 5;
494 return [f = [[ [this](int g) { return g + x; } ]] ]() { return 42; }();
502 auto placeholder = [this](int g) { return g + x; }; return [f = placeholder ]() { return 42; }();
509 return [[ []() { return 42; }() ]];
513 auto placeholder = []() { return 42; }(); return placeholder ;
516 template <typename ...Ts>
517 void foo(Ts ...args) {
518 auto x = [[ [&args...]() {} ]];
522 template <typename ...Ts>
523 void foo(Ts ...args) {
524 auto placeholder = [&args...]() {}; auto x = placeholder ;
535 const auto [x, y] = c;
536 auto f = [[ [&]() { return x + y; } ]];
547 const auto [x, y] = c;
548 auto placeholder = [&]() { return x + y; }; auto f = placeholder ;
559 if (const auto [x, y] = c; x > y) {
560 auto f = [[ [&]() { return x + y; } ]];
572 if (const auto [x, y] = c; x > y) {
573 auto placeholder = [&]() { return x + y; }; auto f = placeholder ;
579 {R
"cpp(#define ECHO(X) X
581 int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
583 R"cpp(#define ECHO(X) X
585 auto placeholder = 1 + ECHO(2 + 3) + 4; int x = placeholder + 5;
587 {R"cpp(#define ECHO(X) X
589 int x = 1 + [[ECHO(2) + ECHO(3) + 4]] + 5;
591 R"cpp(#define ECHO(X) X
593 auto placeholder = 1 + ECHO(2) + ECHO(3) + 4; int x = placeholder + 5;
596 for (
const auto &IO : InputOutputs) {
597 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
603 {R
"cpp(struct Handlers {
604 void (*handlerFunc)(int);
606 void runFunction(void (*func)(int)) {}
607 void f(struct Handlers *handler) {
608 runFunction([[handler->handlerFunc]]);
610 R"cpp(struct Handlers {
611 void (*handlerFunc)(int);
613 void runFunction(void (*func)(int)) {}
614 void f(struct Handlers *handler) {
615 void (*placeholder)(int) = handler->handlerFunc; runFunction(placeholder);
617 {R"cpp(int (*foo(char))(int);
621 R"cpp(int (*foo(char))(int);
623 int (*placeholder)(int) = foo('c'); (void)placeholder;
626 {R
"cpp(typedef long NSInteger;
629 NSInteger b = [[a * 7]] + 3;
631 R"cpp(typedef long NSInteger;
634 NSInteger placeholder = a * 7; NSInteger b = placeholder + 3;
637 for (
const auto &IO : InputOutputs) {
638 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
641 ExtraArgs = {
"-xobjective-c"};
643 __attribute__((objc_root_class))
645 - (void)setMethod1:(int)a;
651 [[self.method1]] = 1;
652 [[self.method1]] += 1;
659 {R
"cpp(__attribute__((objc_root_class))
665 int x = [[self.prop1]] + 1;
668 R"cpp(__attribute__((objc_root_class))
674 int placeholder = self.prop1; int x = placeholder + 1;
678 {R
"cpp(__attribute__((objc_root_class))
684 int x = [[self.method1]] + 1;
687 R"cpp(__attribute__((objc_root_class))
693 int placeholder = self.method1; int x = placeholder + 1;
697 for (
const auto &IO : InputOutputs) {
698 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
#define TWEAK_TEST(TweakID)
#define EXPECT_AVAILABLE(MarkedCode)
#define EXPECT_UNAVAILABLE(MarkedCode)
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//