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]] + 1, y = a + [[1]], a = [[1]] + 2, 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
76 const char *NoCrashDesignator = R
"cpp(
85 void foo(struct B *b) {
86 struct A a = {.x=b[[->]]y};
91 ExtraArgs = {"-xobjective-c"};
92 const char *AvailableObjC = R
"cpp(
93 __attribute__((objc_root_class))
104 const char *NoCrashCases = R
"cpp(
105 // error-ok: broken code, but shouldn't crash
106 template<typename T, typename ...Args>
107 struct Test<T, Args...> {
108 Test(const T &v) :val[[(^]]) {}
114 const char *UnavailableCases = R
"cpp(
115 int xyz(int a = [[1]]) {
117 int bar(int a = [[1]]) {
126 return [[t]].bar([[t]].z);
130 // function default argument
131 void f(int b = [[1]]) {
135 auto i = new int, j = new int;
136 [[[[delete i]], delete j]];
140 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
145 for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
148 auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;};
152 // Variable DeclRefExpr
155 // expression statement of type void
173 // lambdas: default args, cannot extract into function-local scope
174 [](int x = [[10]]){};
175 [](auto h = [[ [i = [](){}](){} ]]) {};
177 // lambdas: default args
178 // Extracting from capture initializers is usually fine,
179 // but not if the capture itself is nested inside a default argument
180 [](auto h = [i = [[ [](){} ]]](){}) {};
181 [](auto h = [i = [[ 42 ]]](){}) {};
185 if ([[ [&](){ return a + 1; } ]]() == 4)
188 for (int c = 0; [[ [&]() { return c < b; } ]](); ++c) {
190 for (int c = 0; [[ [&]() { return c < b; } () ]]; ++c) {
193 // lambdas: scope with structured binding
199 if (const auto [x, y] = c; x > y)
200 auto f = [[ [&]() { return x + y; } ]];
202 // lambdas: referencing outside variables that block extraction
203 // in trailing return type or in a decltype used
206 if ([[ []() -> decltype(a) { return 1; } ]] () == 4)
209 if ([[ [](int x = decltype(a){}) { return 1; } ]] () == 4)
212 if ([[ [](decltype(a) x) { return 1; } ]] (42) == 4)
218 ExtraArgs = {"-std=c++20"};
219 const char *UnavailableCasesCXX20 = R
"cpp(
220 template <typename T>
221 concept Constraint = requires (T t) { true; };
223 // lambdas: referencing outside variables that block extraction
224 // in requires clause or defaulted explicit template parameters
226 if ([[ [](auto b) requires (Constraint<decltype(a)> && Constraint<decltype(b)>) { return true; } ]] (a))
230 if ([[ []<typename T = decltype(a)>(T b) { return true; } ]] (a))
238 std::vector<std::pair<std::string, std::string>> InputOutputs = {
240 {R
"cpp(void varDecl() {
241 int a = 5 * (4 + (3 [[- 1)]]);
243 R"cpp(void varDecl() {
244 auto placeholder = (3 - 1); int a = 5 * (4 + placeholder);
270 {R
"cpp(#define PLUS(x) x++
272 int y = PLUS([[1+a]]);
279 R
"cpp(#define PLUS(x) x++
281 auto placeholder = PLUS(1+a); int y = placeholder;
284 {R
"cpp(#define LOOP(x) while (1) {a = x;}
289 R"cpp(#define LOOP(x) while (1) {a = x;}
291 auto placeholder = 3; if(1)
292 LOOP(5 + placeholder)
294 {R"cpp(#define LOOP(x) do {x;} while(1);
299 R"cpp(#define LOOP(x) do {x;} while(1);
301 auto placeholder = 3; if(1)
302 LOOP(5 + placeholder)
305 {R
"cpp(void f(int a) {
306 [ [gsl::suppress("type")] ] for (;;) a = [[1]] + 1;
308 R"cpp(void f(int a) {
309 auto placeholder = 1; [ [gsl::suppress("type")] ] for (;;) a = placeholder + 1;
314 return [[T().f()]].f();
319 auto placeholder = T().f(); return placeholder.f();
327 auto placeholder = f(); return placeholder;
335 int x = 1 + [[2 + 3 + 4]] + 5;
338 auto placeholder = 2 + 3 + 4; int x = 1 + placeholder + 5;
341 int x = [[1 + 2 + 3]] + 4 + 5;
344 auto placeholder = 1 + 2 + 3; int x = placeholder + 4 + 5;
347 int x = 1 + 2 + [[3 + 4 + 5]];
350 auto placeholder = 3 + 4 + 5; int x = 1 + 2 + placeholder;
354 int x = 1 - [[2 - 3 - 4]] - 5;
357 auto placeholder = 1 - 2 - 3 - 4; int x = placeholder - 5;
361 int x = 0 + 1 * [[2 + 3]] * 4 + 5;
364 auto placeholder = 1 * 2 + 3 * 4; int x = 0 + placeholder + 5;
374 S x = S(1) + [[S(2) + S(3) + S(4)]] + S(5);
382 auto placeholder = S(2) + S(3) + S(4); S x = S(1) + placeholder + S(5);
385 {R
"cpp(template <typename T> void f(T) {}
387 f([[ [](){ return 42; }]]);
390 R"cpp(template <typename T> void f(T) {}
392 auto placeholder = [](){ return 42; }; f( placeholder);
395 {R"cpp(template <typename T> void f(T) {}
397 f([x = [[40 + 2]] ](){ return 42; });
400 R"cpp(template <typename T> void f(T) {}
402 auto placeholder = 40 + 2; f([x = placeholder ](){ return 42; });
405 {R"cpp(auto foo(int VarA) {
407 return [[ [VarA, VarC = 42 + VarA](int VarB) { return VarA + VarB + VarC; }]];
411 R"cpp(auto foo(int VarA) {
413 auto placeholder = [VarA, VarC = 42 + VarA](int VarB) { return VarA + VarB + VarC; }; return placeholder;
417 {R"cpp(template <typename T> void f(T) {}
419 f([[ [&var](){ auto internal_val = 42; return var + internal_val; }]]);
422 R"cpp(template <typename T> void f(T) {}
424 auto placeholder = [&var](){ auto internal_val = 42; return var + internal_val; }; f( placeholder);
427 {R"cpp(template <typename T> void f(T) { }
431 f([[ [&var, &local_var, this]() {
432 auto internal_val = 42;
433 return var + local_var + internal_val + member;
440 R"cpp(template <typename T> void f(T) { }
444 auto placeholder = [&var, &local_var, this]() {
445 auto internal_val = 42;
446 return var + local_var + internal_val + member;
453 {R"cpp(void f() { auto x = +[[ [](){ return 42; }]]; })cpp",
454 R"cpp(void f() { auto placeholder = [](){ return 42; }; auto x = + placeholder; })cpp"},
456 template <typename T>
457 auto sink(T f) { return f(); }
459 return sink([[ []() { return 42; }]]);
463 template <typename T>
464 auto sink(T f) { return f(); }
466 auto placeholder = []() { return 42; }; return sink( placeholder);
472 if ([[ [&](){ return a + 1; } ]]() == 4)
479 auto placeholder = [&](){ return a + 1; }; if ( placeholder () == 4)
486 if ([[ [&](){ return a + 1; }() ]] == 4)
493 auto placeholder = [&](){ return a + 1; }(); if ( placeholder == 4)
498 int func() { return 0; }
503 int func() { return 0; }
505 auto placeholder = func();
508 template <typename T>
509 auto call(T t) { return t(); }
512 return [[ call([](){ int a = 1; return a + 1; }) ]] + 5;
515 template <typename T>
516 auto call(T t) { return t(); }
519 auto placeholder = call([](){ int a = 1; return a + 1; }); return placeholder + 5;
524 return [f = [[ [this](int g) { return g + x; } ]] ]() { return 42; }();
532 auto placeholder = [this](int g) { return g + x; }; return [f = placeholder ]() { return 42; }();
539 return [[ []() { return 42; }() ]];
543 auto placeholder = []() { return 42; }(); return placeholder ;
546 template <typename ...Ts>
547 void foo(Ts ...args) {
548 auto x = +[[ [&args...]() {} ]];
552 template <typename ...Ts>
553 void foo(Ts ...args) {
554 auto placeholder = [&args...]() {}; auto x = + placeholder ;
565 const auto [x, y] = c;
566 auto f = [[ [&]() { return x + y; } ]]();
577 const auto [x, y] = c;
578 auto placeholder = [&]() { return x + y; }; auto f = placeholder ();
589 if (const auto [x, y] = c; x > y) {
590 auto f = [[ [&]() { return x + y; } ]]();
602 if (const auto [x, y] = c; x > y) {
603 auto placeholder = [&]() { return x + y; }; auto f = placeholder ();
609 {R
"cpp(#define ECHO(X) X
611 int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
613 R"cpp(#define ECHO(X) X
615 auto placeholder = 1 + ECHO(2 + 3) + 4; int x = placeholder + 5;
617 {R"cpp(#define ECHO(X) X
619 int x = 1 + [[ECHO(2) + ECHO(3) + 4]] + 5;
621 R"cpp(#define ECHO(X) X
623 auto placeholder = 1 + ECHO(2) + ECHO(3) + 4; int x = placeholder + 5;
626 for (
const auto &IO : InputOutputs) {
627 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
633 {R
"cpp(struct Handlers {
634 void (*handlerFunc)(int);
636 void runFunction(void (*func)(int)) {}
637 void f(struct Handlers *handler) {
638 runFunction([[handler->handlerFunc]]);
640 R"cpp(struct Handlers {
641 void (*handlerFunc)(int);
643 void runFunction(void (*func)(int)) {}
644 void f(struct Handlers *handler) {
645 void (*placeholder)(int) = handler->handlerFunc; runFunction(placeholder);
647 {R"cpp(int (*foo(char))(int);
651 R"cpp(int (*foo(char))(int);
653 int (*placeholder)(int) = foo('c'); (void)placeholder;
656 {R
"cpp(typedef long NSInteger;
659 NSInteger b = [[a * 7]] + 3;
661 R"cpp(typedef long NSInteger;
664 NSInteger placeholder = a * 7; NSInteger b = placeholder + 3;
667 for (
const auto &IO : InputOutputs) {
668 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
671 ExtraArgs = {
"-xobjective-c"};
673 __attribute__((objc_root_class))
675 - (void)setMethod1:(int)a;
681 [[self.method1]] = 1;
682 [[self.method1]] += 1;
689 {R
"cpp(__attribute__((objc_root_class))
695 int x = [[self.prop1]] + 1;
698 R"cpp(__attribute__((objc_root_class))
704 int placeholder = self.prop1; int x = placeholder + 1;
708 {R
"cpp(__attribute__((objc_root_class))
714 int x = [[self.method1]] + 1;
717 R"cpp(__attribute__((objc_root_class))
723 int placeholder = self.method1; int x = placeholder + 1;
727 for (
const auto &IO : InputOutputs) {
728 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
#define TWEAK_TEST(TweakID)
#define EXPECT_AVAILABLE(MarkedCode)
#define EXPECT_UNAVAILABLE(MarkedCode)
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//