clang-tools 24.0.0git
XRefsTests.cpp
Go to the documentation of this file.
1//===-- XRefsTests.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//===----------------------------------------------------------------------===//
8#include "AST.h"
9#include "Annotations.h"
10#include "ParsedAST.h"
11#include "Protocol.h"
12#include "SourceCode.h"
13#include "SyncAPI.h"
14#include "TestFS.h"
15#include "TestTU.h"
16#include "TestWorkspace.h"
17#include "XRefs.h"
18#include "index/MemIndex.h"
19#include "clang/AST/Decl.h"
20#include "clang/Basic/SourceLocation.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/Support/Casting.h"
23#include "llvm/Support/Error.h"
24#include "llvm/Support/Path.h"
25#include "llvm/Support/ScopedPrinter.h"
26#include "gmock/gmock.h"
27#include "gtest/gtest.h"
28#include <optional>
29#include <string>
30#include <vector>
31
32namespace clang {
33namespace clangd {
34namespace {
35
36using ::testing::AllOf;
37using ::testing::ElementsAre;
38using ::testing::Eq;
39using ::testing::IsEmpty;
40using ::testing::Matcher;
41using ::testing::UnorderedElementsAre;
42using ::testing::UnorderedElementsAreArray;
43using ::testing::UnorderedPointwise;
44
45std::string guard(llvm::StringRef Code) {
46 return "#pragma once\n" + Code.str();
47}
48
49MATCHER(declRange, "") {
50 const LocatedSymbol &Sym = ::testing::get<0>(arg);
51 const Range &Range = ::testing::get<1>(arg);
52 return Sym.PreferredDeclaration.range == Range;
53}
54MATCHER(defRange, "") {
55 const LocatedSymbol &Sym = ::testing::get<0>(arg);
56 const Range &Range = ::testing::get<1>(arg);
57 return Sym.Definition.value_or(Sym.PreferredDeclaration).range == Range;
58}
59
60// Extracts ranges from an annotated example, and constructs a matcher for a
61// highlight set. Ranges should be named $read/$write as appropriate.
62Matcher<const std::vector<DocumentHighlight> &>
63highlightsFrom(const Annotations &Test) {
64 std::vector<DocumentHighlight> Expected;
65 auto Add = [&](const Range &R, DocumentHighlightKind K) {
66 Expected.emplace_back();
67 Expected.back().range = R;
68 Expected.back().kind = K;
69 };
70 for (const auto &Range : Test.ranges())
72 for (const auto &Range : Test.ranges("read"))
74 for (const auto &Range : Test.ranges("write"))
76 return UnorderedElementsAreArray(Expected);
77}
78
79TEST(HighlightsTest, All) {
80 const char *Tests[] = {
81 R"cpp(// Local variable
82 int main() {
83 int [[bonjour]];
84 $write[[^bonjour]] = 2;
85 int test1 = $read[[bonjour]];
86 }
87 )cpp",
88
89 R"cpp(// Struct
90 namespace ns1 {
91 struct [[MyClass]] {
92 static void foo([[MyClass]]*) {}
93 };
94 } // namespace ns1
95 int main() {
96 ns1::[[My^Class]]* Params;
97 }
98 )cpp",
99
100 R"cpp(// Function
101 int [[^foo]](int) { return 0; }
102 int main() {
103 [[foo]]([[foo]](42));
104 auto *X = &[[foo]];
105 }
106 )cpp",
107
108 R"cpp(// Function parameter in decl
109 void foo(int [[^bar]]);
110 )cpp",
111 R"cpp(// Not touching any identifiers.
112 struct Foo {
113 [[~]]Foo() {};
114 };
115 void foo() {
116 Foo f;
117 f.[[^~]]Foo();
118 }
119 )cpp",
120 R"cpp(// ObjC methods with split selectors.
121 @interface Foo
122 +(void) [[x]]:(int)a [[y]]:(int)b;
123 @end
124 @implementation Foo
125 +(void) [[x]]:(int)a [[y]]:(int)b {}
126 @end
127 void go() {
128 [Foo [[x]]:2 [[^y]]:4];
129 }
130 )cpp",
131 R"cpp( // Label
132 int main() {
133 goto [[^theLabel]];
134 [[theLabel]]:
135 return 1;
136 }
137 )cpp",
138 R"cpp(// Overloaded operator: the whole name, not just `operator`, is highlighted.
139 using size_t = decltype(sizeof(0));
140 struct S {
141 static void *[[operator]] [[n^ew]](size_t);
142 static void operator delete(void *);
143 };
144 )cpp",
145 R"cpp(// Same, with the cursor on the operator keyword itself.
146 using size_t = decltype(sizeof(0));
147 struct S {
148 static void *[[^operator]] [[new]](size_t);
149 static void operator delete(void *);
150 };
151 )cpp",
152 R"cpp(// Same, for operator delete.
153 using size_t = decltype(sizeof(0));
154 struct S {
155 static void *operator new(size_t);
156 static void [[operator]] [[del^ete]](void *);
157 };
158 )cpp",
159 R"cpp(// Overloaded operator spanning multiple tokens.
160 struct S {
161 void [[operator]] [[^(]][[)]](int);
162 };
163 )cpp",
164 R"cpp(// Explicit operator-call syntax also highlights the whole name.
165 struct S {
166 S [[operator]] [[+]](S);
167 };
168 void f(S a) {
169 a.[[operator]] [[^+]](a);
170 }
171 )cpp",
172 R"cpp(// Literal operator: the suffix is lexed together with the preceding
173 // `""` as a single token, so the whole thing is highlighted.
174 long double [[operator]] [[""_te^st]](long double);
175 )cpp",
176 R"cpp(// Conversion operator: the target type name is highlighted too.
177 // (Clicking on `int` itself doesn't resolve to the declaration at
178 // all, a separate limitation.)
179 struct S {
180 [[^operator]] [[int]]();
181 };
182 )cpp",
183 R"cpp(// Regression: an operator name coming from a macro expansion must not
184 // crash. Since a macro location isn't something we can safely treat
185 // as spelled tokens, we fall back to highlighting just `operator`.
186 #define PLUS +
187 struct S { void [[operator]] PLU^S(int); };
188 )cpp",
189 R"cpp(// Regression: an overloaded operator called with dependent arguments
190 // (so overload resolution is deferred, producing an
191 // UnresolvedMemberExpr with several candidates at one location)
192 // should still have its whole name highlighted, not just `operator`.
193 struct S {
194 void operator+(int);
195 void [[operat^or]] [[+]](double);
196 };
197 template <typename T>
198 void foo(S s, T t) {
199 s.[[operator]] [[+]](t);
200 }
201 )cpp",
202 };
203 for (const char *Test : Tests) {
204 Annotations T(Test);
205 auto TU = TestTU::withCode(T.code());
206 TU.ExtraArgs.push_back("-xobjective-c++");
207 auto AST = TU.build();
208 EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T))
209 << Test;
210 }
211}
212
213TEST(HighlightsTest, ControlFlow) {
214 const char *Tests[] = {
215 R"cpp(
216 // Highlight same-function returns.
217 int fib(unsigned n) {
218 if (n <= 1) [[ret^urn]] 1;
219 [[return]] fib(n - 1) + fib(n - 2);
220
221 // Returns from other functions not highlighted.
222 auto Lambda = [] { return; };
223 class LocalClass { void x() { return; } };
224 }
225 )cpp",
226
227 R"cpp(
228 #define FAIL() return false
229 #define DO(x) { x; }
230 bool foo(int n) {
231 if (n < 0) [[FAIL]]();
232 DO([[re^turn]] true)
233 }
234 )cpp",
235
236 R"cpp(
237 // Highlight loop control flow
238 int magic() {
239 int counter = 0;
240 [[^for]] (char c : "fruit loops!") {
241 if (c == ' ') [[continue]];
242 counter += c;
243 if (c == '!') [[break]];
244 if (c == '?') [[return]] -1;
245 }
246 return counter;
247 }
248 )cpp",
249
250 R"cpp(
251 // Highlight loop and same-loop control flow
252 void nonsense() {
253 [[while]] (true) {
254 if (false) [[bre^ak]];
255 switch (1) break;
256 [[continue]];
257 }
258 }
259 )cpp",
260
261 R"cpp(
262 // Highlight switch for break (but not other breaks).
263 void describe(unsigned n) {
264 [[switch]](n) {
265 case 0:
266 break;
267 [[default]]:
268 [[^break]];
269 }
270 }
271 )cpp",
272
273 R"cpp(
274 // Highlight case and exits for switch-break (but not other cases).
275 void describe(unsigned n) {
276 [[switch]](n) {
277 case 0:
278 break;
279 [[case]] 1:
280 [[default]]:
281 [[return]];
282 [[^break]];
283 }
284 }
285 )cpp",
286
287 R"cpp(
288 // Highlight exits and switch for case
289 void describe(unsigned n) {
290 [[switch]](n) {
291 case 0:
292 break;
293 [[case]] 1:
294 [[d^efault]]:
295 [[return]];
296 [[break]];
297 }
298 }
299 )cpp",
300
301 R"cpp(
302 // Highlight nothing for switch.
303 void describe(unsigned n) {
304 s^witch(n) {
305 case 0:
306 break;
307 case 1:
308 default:
309 return;
310 break;
311 }
312 }
313 )cpp",
314
315 R"cpp(
316 // FIXME: match exception type against catch blocks
317 int catchy() {
318 try { // wrong: highlight try with matching catch
319 try { // correct: has no matching catch
320 [[thr^ow]] "oh no!";
321 } catch (int) { } // correct: catch doesn't match type
322 [[return]] -1; // correct: exits the matching catch
323 } catch (const char*) { } // wrong: highlight matching catch
324 [[return]] 42; // wrong: throw doesn't exit function
325 }
326 )cpp",
327
328 R"cpp(
329 // Loop highlights goto exiting the loop, but not jumping within it.
330 void jumpy() {
331 [[wh^ile]](1) {
332 up:
333 if (0) [[goto]] out;
334 goto up;
335 }
336 out: return;
337 }
338 )cpp",
339 };
340 for (const char *Test : Tests) {
341 Annotations T(Test);
342 auto TU = TestTU::withCode(T.code());
343 TU.ExtraArgs.push_back("-fexceptions"); // FIXME: stop testing on PS4.
344 auto AST = TU.build();
345 EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T))
346 << Test;
347 }
348}
349
350MATCHER_P3(sym, Name, Decl, DefOrNone, "") {
351 std::optional<Range> Def = DefOrNone;
352 if (Name != arg.Name) {
353 *result_listener << "Name is " << arg.Name;
354 return false;
355 }
356 if (Decl != arg.PreferredDeclaration.range) {
357 *result_listener << "Declaration is "
358 << llvm::to_string(arg.PreferredDeclaration);
359 return false;
360 }
361 if (!Def && !arg.Definition)
362 return true;
363 if (Def && !arg.Definition) {
364 *result_listener << "Has no definition";
365 return false;
366 }
367 if (!Def && arg.Definition) {
368 *result_listener << "Definition is " << llvm::to_string(*arg.Definition);
369 return false;
370 }
371 if (arg.Definition->range != *Def) {
372 *result_listener << "Definition is " << llvm::to_string(*arg.Definition);
373 return false;
374 }
375 return true;
376}
377
378MATCHER_P(sym, Name, "") { return arg.Name == Name; }
379
380MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; }
381MATCHER_P(fileIs, F, "") { return arg.Loc.uri.file() == F; }
382MATCHER_P(containerIs, C, "") {
383 return arg.Loc.containerName.value_or("") == C;
384}
385MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; }
386MATCHER_P(hasID, ID, "") { return arg.ID == ID; }
387
388TEST(LocateSymbol, WithIndex) {
389 Annotations SymbolHeader(R"cpp(
390 class $forward[[Forward]];
391 class $foo[[Foo]] {};
392
393 void $f1[[f1]]();
394
395 inline void $f2[[f2]]() {}
396 )cpp");
397 Annotations SymbolCpp(R"cpp(
398 class $forward[[forward]] {};
399 void $f1[[f1]]() {}
400 )cpp");
401
402 TestTU TU;
403 TU.Code = std::string(SymbolCpp.code());
404 TU.HeaderCode = std::string(SymbolHeader.code());
405 auto Index = TU.index();
406 auto LocateWithIndex = [&Index](const Annotations &Main) {
407 auto AST = TestTU::withCode(Main.code()).build();
408 return clangd::locateSymbolAt(AST, Main.point(), Index.get());
409 };
410
411 Annotations Test(R"cpp(// only declaration in AST.
412 void [[f1]]();
413 int main() {
414 ^f1();
415 }
416 )cpp");
417 EXPECT_THAT(LocateWithIndex(Test),
418 ElementsAre(sym("f1", Test.range(), SymbolCpp.range("f1"))));
419
420 Test = Annotations(R"cpp(// definition in AST.
421 void [[f1]]() {}
422 int main() {
423 ^f1();
424 }
425 )cpp");
426 EXPECT_THAT(LocateWithIndex(Test),
427 ElementsAre(sym("f1", SymbolHeader.range("f1"), Test.range())));
428
429 Test = Annotations(R"cpp(// forward declaration in AST.
430 class [[Foo]];
431 F^oo* create();
432 )cpp");
433 EXPECT_THAT(LocateWithIndex(Test),
434 ElementsAre(sym("Foo", Test.range(), SymbolHeader.range("foo"))));
435
436 Test = Annotations(R"cpp(// definition in AST.
437 class [[Forward]] {};
438 F^orward create();
439 )cpp");
440 EXPECT_THAT(
441 LocateWithIndex(Test),
442 ElementsAre(sym("Forward", SymbolHeader.range("forward"), Test.range())));
443}
444
445TEST(LocateSymbol, AnonymousStructFields) {
446 auto Code = Annotations(R"cpp(
447 struct $2[[Foo]] {
448 struct { int $1[[x]]; };
449 void foo() {
450 // Make sure the implicit base is skipped.
451 $1^x = 42;
452 }
453 };
454 // Check that we don't skip explicit bases.
455 int a = $2^Foo{}.x;
456 )cpp");
457 TestTU TU = TestTU::withCode(Code.code());
458 auto AST = TU.build();
459 EXPECT_THAT(locateSymbolAt(AST, Code.point("1"), TU.index().get()),
460 UnorderedElementsAre(sym("x", Code.range("1"), Code.range("1"))));
461 EXPECT_THAT(
462 locateSymbolAt(AST, Code.point("2"), TU.index().get()),
463 UnorderedElementsAre(sym("Foo", Code.range("2"), Code.range("2"))));
464}
465
466TEST(LocateSymbol, FindOverrides) {
467 auto Code = Annotations(R"cpp(
468 class Foo {
469 virtual void $1[[fo^o]]() = 0;
470 };
471 class Bar : public Foo {
472 void $2[[foo]]() override;
473 };
474 )cpp");
475 TestTU TU = TestTU::withCode(Code.code());
476 auto AST = TU.build();
477 EXPECT_THAT(locateSymbolAt(AST, Code.point(), TU.index().get()),
478 UnorderedElementsAre(sym("foo", Code.range("1"), std::nullopt),
479 sym("foo", Code.range("2"), std::nullopt)));
480}
481
482TEST(LocateSymbol, FindOverridesFromDefObjC) {
483 auto Code = Annotations(R"objc(
484 @protocol Fooey
485 - (void)foo;
486 @end
487 @interface Base
488 - (void)foo;
489 @end
490 @interface Foo : Base<Fooey>
491 - (void)$1[[foo]];
492 @end
493
494 @interface Bar : Foo
495 - (void)$2[[foo]];
496 @end
497 @implementation Bar
498 - (void)$3[[fo^o]] {}
499 @end
500 )objc");
501 TestTU TU = TestTU::withCode(Code.code());
502 TU.ExtraArgs.push_back("-xobjective-c++");
503 auto AST = TU.build();
504 EXPECT_THAT(
505 locateSymbolAt(AST, Code.point(), TU.index().get()),
506 UnorderedElementsAre(sym("foo", Code.range("1"), std::nullopt),
507 sym("foo", Code.range("2"), Code.range("3"))));
508}
509
510TEST(LocateSymbol, NoOverridesFromDeclObjC) {
511 auto Code = Annotations(R"objc(
512 @protocol Fooey
513 - (void)foo;
514 @end
515 @interface Base
516 - (void)foo;
517 @end
518 @interface Foo : Base<Fooey>
519 - (void)foo;
520 @end
521
522 @interface Bar : Foo
523 - (void)$2[[fo^o]];
524 @end
525 @implementation Bar
526 - (void)$3[[foo]] {}
527 @end
528 )objc");
529 TestTU TU = TestTU::withCode(Code.code());
530 TU.ExtraArgs.push_back("-xobjective-c++");
531 auto AST = TU.build();
532 EXPECT_THAT(
533 locateSymbolAt(AST, Code.point(), TU.index().get()),
534 UnorderedElementsAre(sym("foo", Code.range("2"), Code.range("3"))));
535}
536
537TEST(LocateSymbol, ObjCNoOverridesOnUsage) {
538 auto Code = Annotations(R"objc(
539 @interface Foo
540 - (void)foo;
541 @end
542
543 @interface Bar : Foo
544 - (void)$1[[foo]];
545 @end
546 @implementation Bar
547 - (void)$2[[foo]] {}
548 @end
549 void doSomething(Bar *bar) {
550 [bar fo^o];
551 }
552 )objc");
553 TestTU TU = TestTU::withCode(Code.code());
554 TU.ExtraArgs.push_back("-xobjective-c++");
555 auto AST = TU.build();
556 EXPECT_THAT(
557 locateSymbolAt(AST, Code.point(), TU.index().get()),
558 UnorderedElementsAre(sym("foo", Code.range("1"), Code.range("2"))));
559}
560
561TEST(LocateSymbol, WithIndexPreferredLocation) {
562 Annotations SymbolHeader(R"cpp(
563 class $p[[Proto]] {};
564 void $f[[func]]() {};
565 )cpp");
566 TestTU TU;
567 TU.HeaderCode = std::string(SymbolHeader.code());
568 TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.
569 auto Index = TU.index();
570
571 Annotations Test(R"cpp(// only declaration in AST.
572 // Shift to make range different.
573 class Proto;
574 void func() {}
575 P$p^roto* create() {
576 fu$f^nc();
577 return nullptr;
578 }
579 )cpp");
580
581 auto AST = TestTU::withCode(Test.code()).build();
582 {
583 auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());
584 auto CodeGenLoc = SymbolHeader.range("p");
585 EXPECT_THAT(Locs, ElementsAre(sym("Proto", CodeGenLoc, CodeGenLoc)));
586 }
587 {
588 auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());
589 auto CodeGenLoc = SymbolHeader.range("f");
590 EXPECT_THAT(Locs, ElementsAre(sym("func", CodeGenLoc, CodeGenLoc)));
591 }
592}
593
594TEST(LocateSymbol, All) {
595 // Ranges in tests:
596 // $decl is the declaration location (if absent, no symbol is located)
597 // $def is the definition location (if absent, symbol has no definition)
598 // unnamed range becomes both $decl and $def.
599 const char *Tests[] = {
600 R"cpp(
601 struct X {
602 union {
603 int [[a]];
604 float b;
605 };
606 };
607 int test(X &x) {
608 return x.^a;
609 }
610 )cpp",
611
612 R"cpp(// Local variable
613 int main() {
614 int [[bonjour]];
615 ^bonjour = 2;
616 int test1 = bonjour;
617 }
618 )cpp",
619
620 R"cpp(// Struct
621 namespace ns1 {
622 struct [[MyClass]] {};
623 } // namespace ns1
624 int main() {
625 ns1::My^Class* Params;
626 }
627 )cpp",
628
629 R"cpp(// Function definition via pointer
630 void [[foo]](int) {}
631 int main() {
632 auto *X = &^foo;
633 }
634 )cpp",
635
636 R"cpp(// Function declaration via call
637 int $decl[[foo]](int);
638 int main() {
639 return ^foo(42);
640 }
641 )cpp",
642
643 R"cpp(// Field
644 struct Foo { int [[x]]; };
645 int main() {
646 Foo bar;
647 (void)bar.^x;
648 }
649 )cpp",
650
651 R"cpp(// Field, member initializer
652 struct Foo {
653 int [[x]];
654 Foo() : ^x(0) {}
655 };
656 )cpp",
657
658 R"cpp(// Field, field designator
659 struct Foo { int [[x]]; };
660 int main() {
661 Foo bar = { .^x = 2 };
662 }
663 )cpp",
664
665 R"cpp(// Field in offsetof
666 struct Foo { int [[x]]; };
667 int y = __builtin_offsetof(Foo, ^x);
668 )cpp",
669
670 R"cpp(// Outer field in nested offsetof designator
671 struct Inner { int c; };
672 struct A { Inner [[B]]; };
673 int y = __builtin_offsetof(A, ^B.c);
674 )cpp",
675
676 R"cpp(// Inner field in nested offsetof designator
677 struct Inner { int [[c]]; };
678 struct A { Inner B; };
679 int y = __builtin_offsetof(A, B.^c);
680 )cpp",
681
682 R"cpp(// Field in offsetof macro form
683 #define offsetof(t, m) __builtin_offsetof(t, m)
684 struct Foo { int [[x]]; };
685 int y = offsetof(Foo, ^x);
686 )cpp",
687
688 R"cpp(// Inherited field in offsetof
689 struct B { int [[x]]; };
690 struct D : B {};
691 int y = __builtin_offsetof(D, ^x);
692 )cpp",
693
694 R"cpp(// Builtin offsetof name is not a field reference.
695 struct Foo { int x; };
696 int y = __builtin_o^ffsetof(Foo, x);
697 )cpp",
698
699 R"cpp(// Method call
700 struct Foo { int $decl[[x]](); };
701 int main() {
702 Foo bar;
703 bar.^x();
704 }
705 )cpp",
706
707 R"cpp(// Typedef
708 typedef int $decl[[Foo]];
709 int main() {
710 ^Foo bar;
711 }
712 )cpp",
713
714 R"cpp(// Template type parameter
715 template <typename [[T]]>
716 void foo() { ^T t; }
717 )cpp",
718
719 R"cpp(// Template template type parameter
720 template <template<typename> class [[T]]>
721 void foo() { ^T<int> t; }
722 )cpp",
723
724 R"cpp(// Namespace
725 namespace $decl[[ns]] {
726 struct Foo { static void bar(); };
727 } // namespace ns
728 int main() { ^ns::Foo::bar(); }
729 )cpp",
730
731 R"cpp(// Macro
732 class TTT { public: int a; };
733 #define [[FF]](S) if (int b = S.a) {}
734 void f() {
735 TTT t;
736 F^F(t);
737 }
738 )cpp",
739
740 R"cpp(// Macro argument
741 int [[i]];
742 #define ADDRESSOF(X) &X;
743 int *j = ADDRESSOF(^i);
744 )cpp",
745 R"cpp(// Macro argument appearing multiple times in expansion
746 #define VALIDATE_TYPE(x) (void)x;
747 #define ASSERT(expr) \
748 do { \
749 VALIDATE_TYPE(expr); \
750 if (!expr); \
751 } while (false)
752 bool [[waldo]]() { return true; }
753 void foo() {
754 ASSERT(wa^ldo());
755 }
756 )cpp",
757 R"cpp(// Symbol concatenated inside macro (not supported)
758 int *pi;
759 #define POINTER(X) p ## X;
760 int x = *POINTER(^i);
761 )cpp",
762
763 R"cpp(// Forward class declaration
764 class $decl[[Foo]];
765 class $def[[Foo]] {};
766 F^oo* foo();
767 )cpp",
768
769 R"cpp(// Function declaration
770 void $decl[[foo]]();
771 void g() { f^oo(); }
772 void $def[[foo]]() {}
773 )cpp",
774
775 R"cpp(
776 #define FF(name) class name##_Test {};
777 [[FF]](my);
778 void f() { my^_Test a; }
779 )cpp",
780
781 R"cpp(
782 #define FF() class [[Test]] {};
783 FF();
784 void f() { T^est a; }
785 )cpp",
786
787 R"cpp(// explicit template specialization
788 template <typename T>
789 struct Foo { void bar() {} };
790
791 template <>
792 struct [[Foo]]<int> { void bar() {} };
793
794 void foo() {
795 Foo<char> abc;
796 Fo^o<int> b;
797 }
798 )cpp",
799
800 R"cpp(// implicit template specialization
801 template <typename T>
802 struct [[Foo]] { void bar() {} };
803 template <>
804 struct Foo<int> { void bar() {} };
805 void foo() {
806 Fo^o<char> abc;
807 Foo<int> b;
808 }
809 )cpp",
810
811 R"cpp(// partial template specialization
812 template <typename T>
813 struct Foo { void bar() {} };
814 template <typename T>
815 struct [[Foo]]<T*> { void bar() {} };
816 ^Foo<int*> x;
817 )cpp",
818
819 R"cpp(// function template specializations
820 template <class T>
821 void foo(T) {}
822 template <>
823 void [[foo]](int) {}
824 void bar() {
825 fo^o(10);
826 }
827 )cpp",
828
829 R"cpp(// variable template decls
830 template <class T>
831 T var = T();
832
833 template <>
834 double [[var]]<int> = 10;
835
836 double y = va^r<int>;
837 )cpp",
838
839 R"cpp(// No implicit constructors
840 struct X {
841 X(X&& x) = default;
842 };
843 X $decl[[makeX]]();
844 void foo() {
845 auto x = m^akeX();
846 }
847 )cpp",
848
849 R"cpp(
850 struct X {
851 X& $decl[[operator]]++();
852 };
853 void foo(X& x) {
854 +^+x;
855 }
856 )cpp",
857
858 R"cpp(
859 struct S1 { void f(); };
860 struct S2 { S1 * $decl[[operator]]->(); };
861 void test(S2 s2) {
862 s2-^>f();
863 }
864 )cpp",
865
866 R"cpp(// Declaration of explicit template specialization
867 template <typename T>
868 struct $decl[[$def[[Foo]]]] {};
869
870 template <>
871 struct Fo^o<int> {};
872 )cpp",
873
874 R"cpp(// Declaration of partial template specialization
875 template <typename T>
876 struct $decl[[$def[[Foo]]]] {};
877
878 template <typename T>
879 struct Fo^o<T*> {};
880 )cpp",
881
882 R"cpp(// Definition on ClassTemplateDecl
883 namespace ns {
884 // Forward declaration.
885 template<typename T>
886 struct $decl[[Foo]];
887
888 template <typename T>
889 struct $def[[Foo]] {};
890 }
891
892 using ::ns::Fo^o;
893 )cpp",
894
895 R"cpp(// auto builtin type (not supported)
896 ^auto x = 42;
897 )cpp",
898
899 R"cpp(// auto on lambda
900 auto x = [[[]]]{};
901 ^auto y = x;
902 )cpp",
903
904 R"cpp(// auto on struct
905 namespace ns1 {
906 struct [[S1]] {};
907 } // namespace ns1
908
909 ^auto x = ns1::S1{};
910 )cpp",
911
912 R"cpp(// decltype on struct
913 namespace ns1 {
914 struct [[S1]] {};
915 } // namespace ns1
916
917 ns1::S1 i;
918 ^decltype(i) j;
919 )cpp",
920
921 R"cpp(// decltype(auto) on struct
922 namespace ns1 {
923 struct [[S1]] {};
924 } // namespace ns1
925
926 ns1::S1 i;
927 ns1::S1& j = i;
928 ^decltype(auto) k = j;
929 )cpp",
930
931 R"cpp(// auto on template class
932 template<typename T> class [[Foo]] {};
933
934 ^auto x = Foo<int>();
935 )cpp",
936
937 R"cpp(// auto on template class with forward declared class
938 template<typename T> class [[Foo]] {};
939 class X;
940
941 ^auto x = Foo<X>();
942 )cpp",
943
944 R"cpp(// auto on specialized template class
945 template<typename T> class Foo {};
946 template<> class [[Foo]]<int> {};
947
948 ^auto x = Foo<int>();
949 )cpp",
950
951 R"cpp(// auto on initializer list.
952 namespace std
953 {
954 template<class _E>
955 class [[initializer_list]] { const _E *a, *b; };
956 }
957
958 ^auto i = {1,2};
959 )cpp",
960
961 R"cpp(// auto function return with trailing type
962 struct [[Bar]] {};
963 ^auto test() -> decltype(Bar()) {
964 return Bar();
965 }
966 )cpp",
967
968 R"cpp(// decltype in trailing return type
969 struct [[Bar]] {};
970 auto test() -> ^decltype(Bar()) {
971 return Bar();
972 }
973 )cpp",
974
975 R"cpp(// auto in function return
976 struct [[Bar]] {};
977 ^auto test() {
978 return Bar();
979 }
980 )cpp",
981
982 R"cpp(// auto& in function return
983 struct [[Bar]] {};
984 ^auto& test() {
985 static Bar x;
986 return x;
987 }
988 )cpp",
989
990 R"cpp(// auto* in function return
991 struct [[Bar]] {};
992 ^auto* test() {
993 Bar* x;
994 return x;
995 }
996 )cpp",
997
998 R"cpp(// const auto& in function return
999 struct [[Bar]] {};
1000 const ^auto& test() {
1001 static Bar x;
1002 return x;
1003 }
1004 )cpp",
1005
1006 R"cpp(// auto lambda param where there's a single instantiation
1007 struct [[Bar]] {};
1008 auto Lambda = [](^auto){ return 0; };
1009 int x = Lambda(Bar{});
1010 )cpp",
1011
1012 R"cpp(// decltype(auto) in function return
1013 struct [[Bar]] {};
1014 ^decltype(auto) test() {
1015 return Bar();
1016 }
1017 )cpp",
1018
1019 R"cpp(// decltype of function with trailing return type.
1020 struct [[Bar]] {};
1021 auto test() -> decltype(Bar()) {
1022 return Bar();
1023 }
1024 void foo() {
1025 ^decltype(test()) i = test();
1026 }
1027 )cpp",
1028
1029 R"cpp(// auto with dependent type
1030 template <typename>
1031 struct [[A]] {};
1032 template <typename T>
1033 void foo(A<T> a) {
1034 ^auto copy = a;
1035 }
1036 )cpp",
1037
1038 R"cpp(// Override specifier jumps to overridden method
1039 class Y { virtual void $decl[[a]]() = 0; };
1040 class X : Y { void a() ^override {} };
1041 )cpp",
1042 R"cpp(// Final specifier jumps to overridden method
1043 class Y { virtual void $decl[[a]]() = 0; };
1044 class X : Y { void a() ^final {} };
1045 )cpp",
1046
1047 R"cpp(// Heuristic resolution of dependent method
1048 template <typename T>
1049 struct S {
1050 void [[bar]]() {}
1051 };
1052
1053 template <typename T>
1054 void foo(S<T> arg) {
1055 arg.ba^r();
1056 }
1057 )cpp",
1058
1059 R"cpp(// Heuristic resolution of dependent method via this->
1060 template <typename T>
1061 struct S {
1062 void [[foo]]() {
1063 this->fo^o();
1064 }
1065 };
1066 )cpp",
1067
1068 R"cpp(// Heuristic resolution of dependent static method
1069 template <typename T>
1070 struct S {
1071 static void [[bar]]() {}
1072 };
1073
1074 template <typename T>
1075 void foo() {
1076 S<T>::ba^r();
1077 }
1078 )cpp",
1079
1080 R"cpp(// Heuristic resolution of dependent method
1081 // invoked via smart pointer
1082 template <typename> struct S { void [[foo]]() {} };
1083 template <typename T> struct unique_ptr {
1084 T* operator->();
1085 };
1086 template <typename T>
1087 void test(unique_ptr<S<T>>& V) {
1088 V->fo^o();
1089 }
1090 )cpp",
1091
1092 R"cpp(// Heuristic resolution of dependent enumerator
1093 template <typename T>
1094 struct Foo {
1095 enum class E { [[A]], B };
1096 E e = E::A^;
1097 };
1098 )cpp",
1099
1100 R"cpp(// Enum base
1101 typedef int $decl[[MyTypeDef]];
1102 enum Foo : My^TypeDef {};
1103 )cpp",
1104 R"cpp(// Enum base
1105 typedef int $decl[[MyTypeDef]];
1106 enum Foo : My^TypeDef;
1107 )cpp",
1108 R"cpp(// Enum base
1109 using $decl[[MyTypeDef]] = int;
1110 enum Foo : My^TypeDef {};
1111 )cpp",
1112
1113 R"objc(
1114 @protocol Dog;
1115 @protocol $decl[[Dog]]
1116 - (void)bark;
1117 @end
1118 id<Do^g> getDoggo() {
1119 return 0;
1120 }
1121 )objc",
1122
1123 R"objc(
1124 @interface Cat
1125 @end
1126 @implementation Cat
1127 @end
1128 @interface $decl[[Cat]] (Exte^nsion)
1129 - (void)meow;
1130 @end
1131 @implementation $def[[Cat]] (Extension)
1132 - (void)meow {}
1133 @end
1134 )objc",
1135
1136 R"objc(
1137 @class $decl[[Foo]];
1138 Fo^o * getFoo() {
1139 return 0;
1140 }
1141 )objc",
1142
1143 R"objc(// Prefer interface definition over forward declaration
1144 @class Foo;
1145 @interface $decl[[Foo]]
1146 @end
1147 Fo^o * getFoo() {
1148 return 0;
1149 }
1150 )objc",
1151
1152 R"objc(
1153 @class Foo;
1154 @interface $decl[[Foo]]
1155 @end
1156 @implementation $def[[Foo]]
1157 @end
1158 Fo^o * getFoo() {
1159 return 0;
1160 }
1161 )objc",
1162
1163 R"objc(// Method decl and definition for ObjC class.
1164 @interface Cat
1165 - (void)$decl[[meow]];
1166 @end
1167 @implementation Cat
1168 - (void)$def[[meow]] {}
1169 @end
1170 void makeNoise(Cat *kitty) {
1171 [kitty me^ow];
1172 }
1173 )objc",
1174
1175 R"objc(// Method decl and definition for ObjC category.
1176 @interface Dog
1177 @end
1178 @interface Dog (Play)
1179 - (void)$decl[[runAround]];
1180 @end
1181 @implementation Dog (Play)
1182 - (void)$def[[runAround]] {}
1183 @end
1184 void play(Dog *dog) {
1185 [dog run^Around];
1186 }
1187 )objc",
1188
1189 R"objc(// Method decl and definition for ObjC class extension.
1190 @interface Dog
1191 @end
1192 @interface Dog ()
1193 - (void)$decl[[howl]];
1194 @end
1195 @implementation Dog
1196 - (void)$def[[howl]] {}
1197 @end
1198 void play(Dog *dog) {
1199 [dog ho^wl];
1200 }
1201 )objc",
1202 R"cpp(
1203 struct PointerIntPairInfo {
1204 static void *$decl[[getPointer]](void *Value);
1205 };
1206
1207 template <typename Info = PointerIntPairInfo> struct PointerIntPair {
1208 void *Value;
1209 void *getPointer() const { return Info::get^Pointer(Value); }
1210 };
1211 )cpp",
1212 R"cpp(// Deducing this
1213 struct S {
1214 int bar(this S&);
1215 };
1216 void foo() {
1217 S [[waldo]];
1218 int x = wa^ldo.bar();
1219 }
1220 )cpp"};
1221 for (const char *Test : Tests) {
1222 Annotations T(Test);
1223 std::optional<Range> WantDecl;
1224 std::optional<Range> WantDef;
1225 if (!T.ranges().empty())
1226 WantDecl = WantDef = T.range();
1227 if (!T.ranges("decl").empty())
1228 WantDecl = T.range("decl");
1229 if (!T.ranges("def").empty())
1230 WantDef = T.range("def");
1231
1232 TestTU TU;
1233 TU.Code = std::string(T.code());
1234
1235 TU.ExtraArgs.push_back("-xobjective-c++");
1236 TU.ExtraArgs.push_back("-std=c++23");
1237
1238 auto AST = TU.build();
1239 auto Results = locateSymbolAt(AST, T.point());
1240
1241 if (!WantDecl) {
1242 EXPECT_THAT(Results, IsEmpty()) << Test;
1243 } else {
1244 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1245 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1246 EXPECT_TRUE(Results[0].ID) << Test;
1247 std::optional<Range> GotDef;
1248 if (Results[0].Definition)
1249 GotDef = Results[0].Definition->range;
1250 EXPECT_EQ(WantDef, GotDef) << Test;
1251 }
1252 }
1253}
1254TEST(LocateSymbol, ValidSymbolID) {
1255 auto T = Annotations(R"cpp(
1256 #define MACRO(x, y) ((x) + (y))
1257 int add(int x, int y) { return $MACRO^MACRO(x, y); }
1258 int sum = $add^add(1, 2);
1259 )cpp");
1260
1261 TestTU TU = TestTU::withCode(T.code());
1262 auto AST = TU.build();
1263 auto Index = TU.index();
1264 EXPECT_THAT(locateSymbolAt(AST, T.point("add"), Index.get()),
1265 ElementsAre(AllOf(sym("add"),
1266 hasID(getSymbolID(&findDecl(AST, "add"))))));
1267 EXPECT_THAT(
1268 locateSymbolAt(AST, T.point("MACRO"), Index.get()),
1269 ElementsAre(AllOf(sym("MACRO"),
1270 hasID(findSymbol(TU.headerSymbols(), "MACRO").ID))));
1271}
1272
1273TEST(LocateSymbol, AllMulti) {
1274 // Ranges in tests:
1275 // $declN is the declaration location
1276 // $defN is the definition location (if absent, symbol has no definition)
1277 //
1278 // NOTE:
1279 // N starts at 0.
1280 struct ExpectedRanges {
1281 Range WantDecl;
1282 std::optional<Range> WantDef;
1283 };
1284 const char *Tests[] = {
1285 R"objc(
1286 @interface $decl0[[Cat]]
1287 @end
1288 @implementation $def0[[Cat]]
1289 @end
1290 @interface $decl1[[Ca^t]] (Extension)
1291 - (void)meow;
1292 @end
1293 @implementation $def1[[Cat]] (Extension)
1294 - (void)meow {}
1295 @end
1296 )objc",
1297
1298 R"objc(
1299 @interface $decl0[[Cat]]
1300 @end
1301 @implementation $def0[[Cat]]
1302 @end
1303 @interface $decl1[[Cat]] (Extension)
1304 - (void)meow;
1305 @end
1306 @implementation $def1[[Ca^t]] (Extension)
1307 - (void)meow {}
1308 @end
1309 )objc",
1310
1311 R"objc(
1312 @interface $decl0[[Cat]]
1313 @end
1314 @interface $decl1[[Ca^t]] ()
1315 - (void)meow;
1316 @end
1317 @implementation $def0[[$def1[[Cat]]]]
1318 - (void)meow {}
1319 @end
1320 )objc",
1321 };
1322 for (const char *Test : Tests) {
1323 Annotations T(Test);
1324 std::vector<ExpectedRanges> Ranges;
1325 for (int Idx = 0; true; Idx++) {
1326 bool HasDecl = !T.ranges("decl" + std::to_string(Idx)).empty();
1327 bool HasDef = !T.ranges("def" + std::to_string(Idx)).empty();
1328 if (!HasDecl && !HasDef)
1329 break;
1330 ExpectedRanges Range;
1331 if (HasDecl)
1332 Range.WantDecl = T.range("decl" + std::to_string(Idx));
1333 if (HasDef)
1334 Range.WantDef = T.range("def" + std::to_string(Idx));
1335 Ranges.push_back(Range);
1336 }
1337
1338 TestTU TU;
1339 TU.Code = std::string(T.code());
1340 TU.ExtraArgs.push_back("-xobjective-c++");
1341
1342 auto AST = TU.build();
1343 auto Results = locateSymbolAt(AST, T.point());
1344
1345 ASSERT_THAT(Results, ::testing::SizeIs(Ranges.size())) << Test;
1346 for (size_t Idx = 0; Idx < Ranges.size(); Idx++) {
1347 EXPECT_EQ(Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl)
1348 << "($decl" << Idx << ")" << Test;
1349 std::optional<Range> GotDef;
1350 if (Results[Idx].Definition)
1351 GotDef = Results[Idx].Definition->range;
1352 EXPECT_EQ(GotDef, Ranges[Idx].WantDef) << "($def" << Idx << ")" << Test;
1353 }
1354 }
1355}
1356
1357// LocateSymbol test cases that produce warnings.
1358// These are separated out from All so that in All we can assert
1359// that there are no diagnostics.
1360TEST(LocateSymbol, Warnings) {
1361 const char *Tests[] = {
1362 R"cpp(// Field, GNU old-style field designator
1363 struct Foo { int [[x]]; };
1364 int main() {
1365 Foo bar = { ^x : 1 };
1366 }
1367 )cpp",
1368
1369 R"cpp(// Macro
1370 #define MACRO 0
1371 #define [[MACRO]] 1
1372 int main() { return ^MACRO; }
1373 #define MACRO 2
1374 #undef macro
1375 )cpp",
1376 };
1377
1378 for (const char *Test : Tests) {
1379 Annotations T(Test);
1380 std::optional<Range> WantDecl;
1381 std::optional<Range> WantDef;
1382 if (!T.ranges().empty())
1383 WantDecl = WantDef = T.range();
1384 if (!T.ranges("decl").empty())
1385 WantDecl = T.range("decl");
1386 if (!T.ranges("def").empty())
1387 WantDef = T.range("def");
1388
1389 TestTU TU;
1390 TU.Code = std::string(T.code());
1391
1392 auto AST = TU.build();
1393 auto Results = locateSymbolAt(AST, T.point());
1394
1395 if (!WantDecl) {
1396 EXPECT_THAT(Results, IsEmpty()) << Test;
1397 } else {
1398 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1399 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1400 std::optional<Range> GotDef;
1401 if (Results[0].Definition)
1402 GotDef = Results[0].Definition->range;
1403 EXPECT_EQ(WantDef, GotDef) << Test;
1404 }
1405 }
1406}
1407
1408TEST(LocateSymbol, TextualSmoke) {
1409 auto T = Annotations(
1410 R"cpp(
1411 struct [[MyClass]] {};
1412 // Comment mentioning M^yClass
1413 )cpp");
1414
1415 auto TU = TestTU::withCode(T.code());
1416 auto AST = TU.build();
1417 auto Index = TU.index();
1418 EXPECT_THAT(
1419 locateSymbolAt(AST, T.point(), Index.get()),
1420 ElementsAre(AllOf(sym("MyClass", T.range(), T.range()),
1421 hasID(getSymbolID(&findDecl(AST, "MyClass"))))));
1422}
1423
1424TEST(LocateSymbol, Textual) {
1425 const char *Tests[] = {
1426 R"cpp(// Comment
1427 struct [[MyClass]] {};
1428 // Comment mentioning M^yClass
1429 )cpp",
1430 R"cpp(// String
1431 struct MyClass {};
1432 // Not triggered for string literal tokens.
1433 const char* s = "String literal mentioning M^yClass";
1434 )cpp",
1435 R"cpp(// Ifdef'ed out code
1436 struct [[MyClass]] {};
1437 #ifdef WALDO
1438 M^yClass var;
1439 #endif
1440 )cpp",
1441 R"cpp(// Macro definition
1442 struct [[MyClass]] {};
1443 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
1444 )cpp",
1445 R"cpp(// Invalid code
1446 /*error-ok*/
1447 int myFunction(int);
1448 // Not triggered for token which survived preprocessing.
1449 int var = m^yFunction();
1450 )cpp"};
1451
1452 for (const char *Test : Tests) {
1453 Annotations T(Test);
1454 std::optional<Range> WantDecl;
1455 if (!T.ranges().empty())
1456 WantDecl = T.range();
1457
1458 auto TU = TestTU::withCode(T.code());
1459
1460 auto AST = TU.build();
1461 auto Index = TU.index();
1462 auto Word = SpelledWord::touching(
1463 cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),
1464 AST.getTokens(), AST.getLangOpts());
1465 if (!Word) {
1466 ADD_FAILURE() << "No word touching point!" << Test;
1467 continue;
1468 }
1469 auto Results = locateSymbolTextually(*Word, AST, Index.get(),
1470 testPath(TU.Filename), ASTNodeKind());
1471
1472 if (!WantDecl) {
1473 EXPECT_THAT(Results, IsEmpty()) << Test;
1474 } else {
1475 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1476 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1477 }
1478 }
1479} // namespace
1480
1481TEST(LocateSymbol, Ambiguous) {
1482 auto T = Annotations(R"cpp(
1483 struct Foo {
1484 Foo();
1485 Foo(Foo&&);
1486 $ConstructorLoc[[Foo]](const char*);
1487 };
1488
1489 Foo f();
1490
1491 void g(Foo foo);
1492
1493 void call() {
1494 const char* str = "123";
1495 Foo a = $1^str;
1496 Foo b = Foo($2^str);
1497 Foo c = $3^f();
1498 $4^g($5^f());
1499 g($6^str);
1500 Foo ab$7^c;
1501 Foo ab$8^cd("asdf");
1502 Foo foox = Fo$9^o("asdf");
1503 Foo abcde$10^("asdf");
1504 Foo foox2 = Foo$11^("asdf");
1505 }
1506
1507 template <typename T>
1508 struct S {
1509 void $NonstaticOverload1[[bar]](int);
1510 void $NonstaticOverload2[[bar]](float);
1511
1512 static void $StaticOverload1[[baz]](int);
1513 static void $StaticOverload2[[baz]](float);
1514 };
1515
1516 template <typename T, typename U>
1517 void dependent_call(S<T> s, U u) {
1518 s.ba$12^r(u);
1519 S<T>::ba$13^z(u);
1520 }
1521 )cpp");
1522 auto TU = TestTU::withCode(T.code());
1523 // FIXME: Go-to-definition in a template requires disabling delayed template
1524 // parsing.
1525 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
1526 auto AST = TU.build();
1527 // Ordered assertions are deliberate: we expect a predictable order.
1528 EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(sym("str")));
1529 EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(sym("str")));
1530 EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(sym("f")));
1531 EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(sym("g")));
1532 EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(sym("f")));
1533 EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(sym("str")));
1534 // FIXME: Target the constructor as well.
1535 EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(sym("abc")));
1536 // FIXME: Target the constructor as well.
1537 EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(sym("abcd")));
1538 // FIXME: Target the constructor as well.
1539 EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(sym("Foo")));
1540 EXPECT_THAT(locateSymbolAt(AST, T.point("10")),
1541 ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt)));
1542 EXPECT_THAT(locateSymbolAt(AST, T.point("11")),
1543 ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt)));
1544 // These assertions are unordered because the order comes from
1545 // CXXRecordDecl::lookupDependentName() which doesn't appear to provide
1546 // an order guarantee.
1547 EXPECT_THAT(locateSymbolAt(AST, T.point("12")),
1548 UnorderedElementsAre(
1549 sym("bar", T.range("NonstaticOverload1"), std::nullopt),
1550 sym("bar", T.range("NonstaticOverload2"), std::nullopt)));
1551 EXPECT_THAT(locateSymbolAt(AST, T.point("13")),
1552 UnorderedElementsAre(
1553 sym("baz", T.range("StaticOverload1"), std::nullopt),
1554 sym("baz", T.range("StaticOverload2"), std::nullopt)));
1555}
1556
1557TEST(LocateSymbol, TextualDependent) {
1558 // Put the declarations in the header to make sure we are
1559 // finding them via the index heuristic and not the
1560 // nearby-ident heuristic.
1561 Annotations Header(R"cpp(
1562 struct Foo {
1563 void $FooLoc[[uniqueMethodName]]();
1564 };
1565 struct Bar {
1566 void $BarLoc[[uniqueMethodName]]();
1567 };
1568 )cpp");
1569 Annotations Source(R"cpp(
1570 template <typename T>
1571 void f(T t) {
1572 t.u^niqueMethodName();
1573 }
1574 )cpp");
1575 TestTU TU;
1576 TU.Code = std::string(Source.code());
1577 TU.HeaderCode = std::string(Header.code());
1578 auto AST = TU.build();
1579 auto Index = TU.index();
1580 // Need to use locateSymbolAt() since we are testing an
1581 // interaction between locateASTReferent() and
1582 // locateSymbolNamedTextuallyAt().
1583 auto Results = locateSymbolAt(AST, Source.point(), Index.get());
1584 EXPECT_THAT(
1585 Results,
1586 UnorderedElementsAre(
1587 sym("uniqueMethodName", Header.range("FooLoc"), std::nullopt),
1588 sym("uniqueMethodName", Header.range("BarLoc"), std::nullopt)));
1589}
1590
1591TEST(LocateSymbol, Alias) {
1592 const char *Tests[] = {
1593 R"cpp(
1594 template <class T> struct function {};
1595 template <class T> using [[callback]] = function<T()>;
1596
1597 c^allback<int> foo;
1598 )cpp",
1599
1600 // triggered on non-definition of a renaming alias: should not give any
1601 // underlying decls.
1602 R"cpp(
1603 class Foo {};
1604 typedef Foo [[Bar]];
1605
1606 B^ar b;
1607 )cpp",
1608 R"cpp(
1609 class Foo {};
1610 using [[Bar]] = Foo; // definition
1611 Ba^r b;
1612 )cpp",
1613
1614 // triggered on the underlying decl of a renaming alias.
1615 R"cpp(
1616 class [[Foo]];
1617 using Bar = Fo^o;
1618 )cpp",
1619
1620 // triggered on definition of a non-renaming alias: should give underlying
1621 // decls.
1622 R"cpp(
1623 namespace ns { class [[Foo]] {}; }
1624 using ns::F^oo;
1625 )cpp",
1626
1627 R"cpp(
1628 namespace ns { int [[x]](char); int [[x]](double); }
1629 using ns::^x;
1630 )cpp",
1631
1632 R"cpp(
1633 namespace ns { int [[x]](char); int x(double); }
1634 using ns::[[x]];
1635 int y = ^x('a');
1636 )cpp",
1637
1638 R"cpp(
1639 namespace ns { class [[Foo]] {}; }
1640 using ns::[[Foo]];
1641 F^oo f;
1642 )cpp",
1643
1644 // other cases that don't matter much.
1645 R"cpp(
1646 class Foo {};
1647 typedef Foo [[Ba^r]];
1648 )cpp",
1649 R"cpp(
1650 class Foo {};
1651 using [[B^ar]] = Foo;
1652 )cpp",
1653
1654 // Member of dependent base
1655 R"cpp(
1656 template <typename T>
1657 struct Base {
1658 void [[waldo]]() {}
1659 };
1660 template <typename T>
1661 struct Derived : Base<T> {
1662 using Base<T>::w^aldo;
1663 };
1664 )cpp",
1665 };
1666
1667 for (const auto *Case : Tests) {
1668 SCOPED_TRACE(Case);
1669 auto T = Annotations(Case);
1670 auto AST = TestTU::withCode(T.code()).build();
1671 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1672 UnorderedPointwise(declRange(), T.ranges()));
1673 }
1674}
1675
1676TEST(LocateSymbol, RelPathsInCompileCommand) {
1677 // The source is in "/clangd-test/src".
1678 // We build in "/clangd-test/build".
1679
1680 Annotations SourceAnnotations(R"cpp(
1681#include "header_in_preamble.h"
1682int [[foo]];
1683#include "header_not_in_preamble.h"
1684int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
1685)cpp");
1686
1687 Annotations HeaderInPreambleAnnotations(R"cpp(
1688int [[bar_preamble]];
1689)cpp");
1690
1691 Annotations HeaderNotInPreambleAnnotations(R"cpp(
1692int [[bar_not_preamble]];
1693)cpp");
1694
1695 // Make the compilation paths appear as ../src/foo.cpp in the compile
1696 // commands.
1697 SmallString<32> RelPathPrefix("..");
1698 llvm::sys::path::append(RelPathPrefix, "src");
1699 std::string BuildDir = testPath("build");
1700 MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
1701
1702 MockFS FS;
1703 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1704
1705 // Fill the filesystem.
1706 auto FooCpp = testPath("src/foo.cpp");
1707 FS.Files[FooCpp] = "";
1708 auto HeaderInPreambleH = testPath("src/header_in_preamble.h");
1709 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
1710 auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h");
1711 FS.Files[HeaderNotInPreambleH] =
1712 std::string(HeaderNotInPreambleAnnotations.code());
1713
1714 runAddDocument(Server, FooCpp, SourceAnnotations.code());
1715
1716 // Go to a definition in main source file.
1717 auto Locations =
1718 runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));
1719 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1720 EXPECT_THAT(*Locations, ElementsAre(sym("foo", SourceAnnotations.range(),
1721 SourceAnnotations.range())));
1722
1723 // Go to a definition in header_in_preamble.h.
1724 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));
1725 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1726 EXPECT_THAT(
1727 *Locations,
1728 ElementsAre(sym("bar_preamble", HeaderInPreambleAnnotations.range(),
1729 HeaderInPreambleAnnotations.range())));
1730
1731 // Go to a definition in header_not_in_preamble.h.
1732 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));
1733 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1734 EXPECT_THAT(*Locations,
1735 ElementsAre(sym("bar_not_preamble",
1736 HeaderNotInPreambleAnnotations.range(),
1737 HeaderNotInPreambleAnnotations.range())));
1738}
1739
1740TEST(GoToInclude, All) {
1741 MockFS FS;
1743 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1744
1745 auto FooCpp = testPath("foo.cpp");
1746 const char *SourceContents = R"cpp(
1747 #include ^"$2^foo.h$3^"
1748 #include "$4^invalid.h"
1749 int b = a;
1750 // test
1751 int foo;
1752 #in$5^clude "$6^foo.h"$7^
1753 )cpp";
1754 Annotations SourceAnnotations(SourceContents);
1755 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1756 auto FooH = testPath("foo.h");
1757
1758 const char *HeaderContents = R"cpp([[]]#pragma once
1759 int a;
1760 )cpp";
1761 Annotations HeaderAnnotations(HeaderContents);
1762 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1763
1764 runAddDocument(Server, FooH, HeaderAnnotations.code());
1765 runAddDocument(Server, FooCpp, SourceAnnotations.code());
1766
1767 // Test include in preamble.
1768 auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());
1769 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1770 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1771 HeaderAnnotations.range())));
1772
1773 // Test include in preamble, last char.
1774 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));
1775 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1776 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1777 HeaderAnnotations.range())));
1778
1779 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));
1780 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1781 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1782 HeaderAnnotations.range())));
1783
1784 // Test include outside of preamble.
1785 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));
1786 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1787 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1788 HeaderAnnotations.range())));
1789
1790 // Test a few positions that do not result in Locations.
1791 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));
1792 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1793 EXPECT_THAT(*Locations, IsEmpty());
1794
1795 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
1796 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1797 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1798 HeaderAnnotations.range())));
1799
1800 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));
1801 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1802 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1803 HeaderAnnotations.range())));
1804
1805 // Objective C #import directive.
1806 Annotations ObjC(R"objc(
1807 #import "^foo.h"
1808 )objc");
1809 auto FooM = testPath("foo.m");
1810 FS.Files[FooM] = std::string(ObjC.code());
1811
1812 runAddDocument(Server, FooM, ObjC.code());
1813 Locations = runLocateSymbolAt(Server, FooM, ObjC.point());
1814 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1815 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1816 HeaderAnnotations.range())));
1817}
1818
1819TEST(LocateSymbol, WithPreamble) {
1820 // Test stragety: AST should always use the latest preamble instead of last
1821 // good preamble.
1822 MockFS FS;
1824 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1825
1826 auto FooCpp = testPath("foo.cpp");
1827 // The trigger locations must be the same.
1828 Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");
1829 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1830
1831 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1832
1833 auto FooH = testPath("foo.h");
1834 Annotations FooHeader(R"cpp([[]])cpp");
1835 FS.Files[FooH] = std::string(FooHeader.code());
1836
1837 runAddDocument(Server, FooCpp, FooWithHeader.code());
1838 // LocateSymbol goes to a #include file: the result comes from the preamble.
1839 EXPECT_THAT(
1840 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),
1841 ElementsAre(sym("foo.h", FooHeader.range(), FooHeader.range())));
1842
1843 // Only preamble is built, and no AST is built in this request.
1844 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1846 // We build AST here, and it should use the latest preamble rather than the
1847 // stale one.
1848 EXPECT_THAT(
1849 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1850 ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt)));
1851
1852 // Reset test environment.
1853 runAddDocument(Server, FooCpp, FooWithHeader.code());
1854 // Both preamble and AST are built in this request.
1855 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1857 // Use the AST being built in above request.
1858 EXPECT_THAT(
1859 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1860 ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt)));
1861}
1862
1863TEST(LocateSymbol, NearbyTokenSmoke) {
1864 auto T = Annotations(R"cpp(
1865 // prints e^rr and crashes
1866 void die(const char* [[err]]);
1867 )cpp");
1868 auto AST = TestTU::withCode(T.code()).build();
1869 // We don't pass an index, so can't hit index-based fallback.
1870 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1871 ElementsAre(sym("err", T.range(), T.range())));
1872}
1873
1874TEST(LocateSymbol, NearbyIdentifier) {
1875 const char *Tests[] = {
1876 R"cpp(
1877 // regular identifiers (won't trigger)
1878 int hello;
1879 int y = he^llo;
1880 )cpp",
1881 R"cpp(
1882 // disabled preprocessor sections
1883 int [[hello]];
1884 #if 0
1885 int y = ^hello;
1886 #endif
1887 )cpp",
1888 R"cpp(
1889 // comments
1890 // he^llo, world
1891 int [[hello]];
1892 )cpp",
1893 R"cpp(
1894 // not triggered by string literals
1895 int hello;
1896 const char* greeting = "h^ello, world";
1897 )cpp",
1898
1899 R"cpp(
1900 // can refer to macro invocations
1901 #define INT int
1902 [[INT]] x;
1903 // I^NT
1904 )cpp",
1905
1906 R"cpp(
1907 // can refer to macro invocations (even if they expand to nothing)
1908 #define EMPTY
1909 [[EMPTY]] int x;
1910 // E^MPTY
1911 )cpp",
1912
1913 R"cpp(
1914 // prefer nearest occurrence, backwards is worse than forwards
1915 int hello;
1916 int x = hello;
1917 // h^ello
1918 int y = [[hello]];
1919 int z = hello;
1920 )cpp",
1921
1922 R"cpp(
1923 // short identifiers find near results
1924 int [[hi]];
1925 // h^i
1926 )cpp",
1927 R"cpp(
1928 // short identifiers don't find far results
1929 int hi;
1930
1931
1932
1933 // h^i
1934
1935
1936
1937
1938 int x = hi;
1939 )cpp",
1940 R"cpp(
1941 // prefer nearest occurrence even if several matched tokens
1942 // have the same value of `floor(log2(<token line> - <word line>))`.
1943 int hello;
1944 int x = hello, y = hello;
1945 int z = [[hello]];
1946 // h^ello
1947 )cpp"};
1948 for (const char *Test : Tests) {
1949 Annotations T(Test);
1950 auto AST = TestTU::withCode(T.code()).build();
1951 const auto &SM = AST.getSourceManager();
1952 std::optional<Range> Nearby;
1953 auto Word =
1954 SpelledWord::touching(cantFail(sourceLocationInMainFile(SM, T.point())),
1955 AST.getTokens(), AST.getLangOpts());
1956 if (!Word) {
1957 ADD_FAILURE() << "No word at point! " << Test;
1958 continue;
1959 }
1960 if (const auto *Tok = findNearbyIdentifier(*Word, AST.getTokens()))
1961 Nearby = halfOpenToRange(SM, CharSourceRange::getCharRange(
1962 Tok->location(), Tok->endLocation()));
1963 if (T.ranges().empty())
1964 EXPECT_THAT(Nearby, Eq(std::nullopt)) << Test;
1965 else
1966 EXPECT_EQ(Nearby, T.range()) << Test;
1967 }
1968}
1969
1970TEST(FindImplementations, Inheritance) {
1971 llvm::StringRef Test = R"cpp(
1972 struct $0^Base {
1973 virtual void F$1^oo();
1974 void C$4^oncrete();
1975 };
1976 struct $0[[Child1]] : Base {
1977 void $1[[Fo$3^o]]() override;
1978 virtual void B$2^ar();
1979 void Concrete(); // No implementations for concrete methods.
1980 };
1981 struct $0[[Child2]] : Child1 {
1982 void $1[[$3[[Foo]]]]() override;
1983 void $2[[Bar]]() override;
1984 };
1985 void FromReference() {
1986 $0^Base* B;
1987 B->Fo$1^o();
1988 B->C$4^oncrete();
1989 &Base::Fo$1^o;
1990 Child1 * C1;
1991 C1->B$2^ar();
1992 C1->Fo$3^o();
1993 }
1994 // CRTP should work.
1995 template<typename T>
1996 struct $5^TemplateBase {};
1997 struct $5[[Child3]] : public TemplateBase<Child3> {};
1998
1999 // Local classes.
2000 void LocationFunction() {
2001 struct $0[[LocalClass1]] : Base {
2002 void $1[[Foo]]() override;
2003 };
2004 struct $6^LocalBase {
2005 virtual void $7^Bar();
2006 };
2007 struct $6[[LocalClass2]]: LocalBase {
2008 void $7[[Bar]]() override;
2009 };
2010 }
2011 )cpp";
2012
2013 Annotations Code(Test);
2014 auto TU = TestTU::withCode(Code.code());
2015 auto AST = TU.build();
2016 auto Index = TU.index();
2017 for (StringRef Label : {"0", "1", "2", "3", "4", "5", "6", "7"}) {
2018 for (const auto &Point : Code.points(Label)) {
2019 EXPECT_THAT(findImplementations(AST, Point, Index.get()),
2020 UnorderedPointwise(declRange(), Code.ranges(Label)))
2021 << Code.code() << " at " << Point << " for Label " << Label;
2022 }
2023 }
2024}
2025
2026TEST(FindImplementations, InheritanceRecursion) {
2027 // Make sure inheritance is followed, but does not diverge.
2028 llvm::StringRef Test = R"cpp(
2029 template <int>
2030 struct Ev^en;
2031
2032 template <int>
2033 struct Odd;
2034
2035 template <>
2036 struct Even<0> {
2037 static const bool value = true;
2038 };
2039
2040 template <>
2041 struct Odd<0> {
2042 static const bool value = false;
2043 };
2044
2045 template <int I>
2046 struct [[Even]] : Odd<I - 1> {};
2047
2048 template <int I>
2049 struct [[Odd]] : Even<I - 1> {};
2050
2051 constexpr bool Answer = Even<42>::value;
2052 )cpp";
2053
2054 Annotations Code(Test);
2055 auto TU = TestTU::withCode(Code.code());
2056 auto AST = TU.build();
2057 auto Index = TU.index();
2058 EXPECT_THAT(findImplementations(AST, Code.point(), Index.get()),
2059 UnorderedPointwise(defRange(), Code.ranges()));
2060}
2061
2062TEST(FindImplementations, InheritanceObjC) {
2063 llvm::StringRef Test = R"objc(
2064 @interface $base^Base
2065 - (void)fo$foo^o;
2066 @end
2067 @protocol Protocol
2068 - (void)$protocol^protocol;
2069 @end
2070 @interface $ChildDecl[[Child]] : Base <Protocol>
2071 - (void)concrete;
2072 - (void)$fooDecl[[foo]];
2073 @end
2074 @implementation $ChildDef[[Child]]
2075 - (void)concrete {}
2076 - (void)$fooDef[[foo]] {}
2077 - (void)$protocolDef[[protocol]] {}
2078 @end
2079 )objc";
2080
2081 Annotations Code(Test);
2082 auto TU = TestTU::withCode(Code.code());
2083 TU.ExtraArgs.push_back("-xobjective-c++");
2084 auto AST = TU.build();
2085 auto Index = TU.index();
2086 EXPECT_THAT(findImplementations(AST, Code.point("base"), Index.get()),
2087 UnorderedElementsAre(sym("Child", Code.range("ChildDecl"),
2088 Code.range("ChildDef"))));
2089 EXPECT_THAT(findImplementations(AST, Code.point("foo"), Index.get()),
2090 UnorderedElementsAre(
2091 sym("foo", Code.range("fooDecl"), Code.range("fooDef"))));
2092 EXPECT_THAT(findImplementations(AST, Code.point("protocol"), Index.get()),
2093 UnorderedElementsAre(sym("protocol", Code.range("protocolDef"),
2094 Code.range("protocolDef"))));
2095}
2096
2097TEST(FindImplementations, CaptureDefinition) {
2098 llvm::StringRef Test = R"cpp(
2099 struct Base {
2100 virtual void F^oo();
2101 };
2102 struct Child1 : Base {
2103 void $Decl[[Foo]]() override;
2104 };
2105 struct Child2 : Base {
2106 void $Child2[[Foo]]() override;
2107 };
2108 void Child1::$Def[[Foo]]() { /* Definition */ }
2109 )cpp";
2110 Annotations Code(Test);
2111 auto TU = TestTU::withCode(Code.code());
2112 auto AST = TU.build();
2113 EXPECT_THAT(
2114 findImplementations(AST, Code.point(), TU.index().get()),
2115 UnorderedElementsAre(sym("Foo", Code.range("Decl"), Code.range("Def")),
2116 sym("Foo", Code.range("Child2"), std::nullopt)))
2117 << Test;
2118}
2119
2120TEST(FindType, All) {
2121 Annotations HeaderA(R"cpp(
2122 struct $Target[[Target]] { operator int() const; };
2123 struct Aggregate { Target a, b; };
2124 Target t;
2125 Target make();
2126
2127 template <typename T> struct $smart_ptr[[smart_ptr]] {
2128 T& operator*();
2129 T* operator->();
2130 T* get();
2131 };
2132 )cpp");
2133 auto TU = TestTU::withHeaderCode(HeaderA.code());
2134 for (const llvm::StringRef Case : {
2135 "str^uct Target;",
2136 "T^arget x;",
2137 "Target ^x;",
2138 "a^uto x = Target{};",
2139 "namespace m { Target tgt; } auto x = m^::tgt;",
2140 "Target funcCall(); auto x = ^funcCall();",
2141 "Aggregate a = { {}, ^{} };",
2142 "Aggregate a = { ^.a=t, };",
2143 "struct X { Target a; X() : ^a() {} };",
2144 "^using T = Target; ^T foo();",
2145 "^template <int> Target foo();",
2146 "void x() { try {} ^catch(Target e) {} }",
2147 "void x() { ^throw t; }",
2148 "int x() { ^return t; }",
2149 "void x() { ^switch(t) {} }",
2150 "void x() { ^delete (Target*)nullptr; }",
2151 "Target& ^tref = t;",
2152 "void x() { ^if (t) {} }",
2153 "void x() { ^while (t) {} }",
2154 "void x() { ^do { } while (t); }",
2155 "void x() { ^make(); }",
2156 "void x(smart_ptr<Target> &t) { t.^get(); }",
2157 "^auto x = []() { return t; };",
2158 "Target* ^tptr = &t;",
2159 "Target ^tarray[3];",
2160 }) {
2161 Annotations A(Case);
2162 TU.Code = A.code().str();
2163 ParsedAST AST = TU.build();
2164
2165 ASSERT_GT(A.points().size(), 0u) << Case;
2166 for (auto Pos : A.points())
2167 EXPECT_THAT(findType(AST, Pos, nullptr),
2168 ElementsAre(
2169 sym("Target", HeaderA.range("Target"), HeaderA.range("Target"))))
2170 << Case;
2171 }
2172
2173 for (const llvm::StringRef Case : {
2174 "smart_ptr<Target> ^tsmart;",
2175 }) {
2176 Annotations A(Case);
2177 TU.Code = A.code().str();
2178 ParsedAST AST = TU.build();
2179
2180 EXPECT_THAT(findType(AST, A.point(), nullptr),
2181 UnorderedElementsAre(
2182 sym("Target", HeaderA.range("Target"), HeaderA.range("Target")),
2183 sym("smart_ptr", HeaderA.range("smart_ptr"), HeaderA.range("smart_ptr"))
2184 ))
2185 << Case;
2186 }
2187}
2188
2189TEST(FindType, Definition) {
2190 Annotations A(R"cpp(
2191 class $decl[[X]];
2192 X *$x^x;
2193 class $def[[X]] {};
2194
2195 template <class T>
2196 concept $Concept^True = true;
2197 )cpp");
2198 auto TU = TestTU::withCode(A.code().str());
2199 TU.ExtraArgs.push_back("-std=c++20");
2200 ParsedAST AST = TU.build();
2201
2202 EXPECT_THAT(findType(AST, A.point("x"), nullptr),
2203 ElementsAre(sym("X", A.range("decl"), A.range("def"))));
2204 EXPECT_THAT(findType(AST, A.point("Concept"), nullptr), IsEmpty());
2205}
2206
2207TEST(FindType, Index) {
2208 Annotations Def(R"cpp(
2209 // This definition is only available through the index.
2210 class [[X]] {};
2211 )cpp");
2212 TestTU DefTU = TestTU::withHeaderCode(Def.code());
2213 DefTU.HeaderFilename = "def.h";
2214 auto DefIdx = DefTU.index();
2215
2216 Annotations A(R"cpp(
2217 class [[X]];
2218 X *^x;
2219 )cpp");
2220 auto TU = TestTU::withCode(A.code().str());
2221 ParsedAST AST = TU.build();
2222
2223 EXPECT_THAT(findType(AST, A.point(), DefIdx.get()),
2224 ElementsAre(sym("X", A.range(), Def.range())));
2225}
2226
2227void checkFindRefs(llvm::StringRef Test, bool UseIndex = false) {
2228 Annotations T(Test);
2229 auto TU = TestTU::withCode(T.code());
2230 TU.ExtraArgs.push_back("-std=c++20");
2231 TU.ExtraArgs.push_back("-xobjective-c++");
2232
2233 auto AST = TU.build();
2234 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2235 for (const auto &[R, Context] : T.rangesWithPayload())
2236 ExpectedLocations.push_back(
2237 AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));
2238 // $def is actually shorthand for both definition and declaration.
2239 // If we have cases that are definition-only, we should change this.
2240 for (const auto &[R, Context] : T.rangesWithPayload("def"))
2241 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
2244 for (const auto &[R, Context] : T.rangesWithPayload("decl"))
2245 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
2247 for (const auto &[R, Context] : T.rangesWithPayload("overridedecl"))
2248 ExpectedLocations.push_back(AllOf(
2249 rangeIs(R), containerIs(Context),
2251 for (const auto &[R, Context] : T.rangesWithPayload("overridedef"))
2252 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
2256 for (const auto &P : T.points()) {
2257 EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr,
2258 /*AddContext*/ true)
2259 .References,
2260 UnorderedElementsAreArray(ExpectedLocations))
2261 << "Failed for Refs at " << P << "\n"
2262 << Test;
2263 }
2264}
2265
2266TEST(FindReferences, WithinAST) {
2267 const char *Tests[] = {
2268 R"cpp(// Local variable
2269 int main() {
2270 int $def(main)[[foo]];
2271 $(main)[[^foo]] = 2;
2272 int test1 = $(main)[[foo]];
2273 }
2274 )cpp",
2275
2276 R"cpp(// Struct
2277 namespace ns1 {
2278 struct $def(ns1)[[Foo]] {};
2279 } // namespace ns1
2280 int main() {
2281 ns1::$(main)[[Fo^o]]* Params;
2282 }
2283 )cpp",
2284
2285 R"cpp(// Forward declaration
2286 class $decl[[Foo]];
2287 class $def[[Foo]] {};
2288 int main() {
2289 $(main)[[Fo^o]] foo;
2290 }
2291 )cpp",
2292
2293 R"cpp(// Function
2294 int $def[[foo]](int) { return 0; }
2295 int main() {
2296 auto *X = &$(main)[[^foo]];
2297 $(main)[[foo]](42);
2298 }
2299 )cpp",
2300
2301 R"cpp(// Field
2302 struct Foo {
2303 int $def(Foo)[[foo]];
2304 Foo() : $(Foo::Foo)[[foo]](0) {}
2305 };
2306 int main() {
2307 Foo f;
2308 f.$(main)[[f^oo]] = 1;
2309 }
2310 )cpp",
2311
2312 R"cpp(// Method call
2313 struct Foo { int $decl(Foo)[[foo]](); };
2314 int Foo::$def(Foo)[[foo]]() { return 0; }
2315 int main() {
2316 Foo f;
2317 f.$(main)[[^foo]]();
2318 }
2319 )cpp",
2320
2321 R"cpp(// Constructor
2322 struct Foo {
2323 $decl(Foo)[[F^oo]](int);
2324 };
2325 void foo() {
2326 Foo f = $(foo)[[Foo]](42);
2327 }
2328 )cpp",
2329
2330 R"cpp(// Typedef
2331 typedef int $def[[Foo]];
2332 int main() {
2333 $(main)[[^Foo]] bar;
2334 }
2335 )cpp",
2336
2337 R"cpp(// Namespace
2338 namespace $decl[[ns]] { // FIXME: def?
2339 struct Foo {};
2340 } // namespace ns
2341 int main() { $(main)[[^ns]]::Foo foo; }
2342 )cpp",
2343
2344 R"cpp(// Macros
2345 #define TYPE(X) X
2346 #define FOO Foo
2347 #define CAT(X, Y) X##Y
2348 class $def[[Fo^o]] {};
2349 void test() {
2350 TYPE($(test)[[Foo]]) foo;
2351 $(test)[[FOO]] foo2;
2352 TYPE(TYPE($(test)[[Foo]])) foo3;
2353 $(test)[[CAT]](Fo, o) foo4;
2354 }
2355 )cpp",
2356
2357 R"cpp(// Macros
2358 #define $def[[MA^CRO]](X) (X+1)
2359 void test() {
2360 int x = $[[MACRO]]($[[MACRO]](1));
2361 }
2362 )cpp",
2363
2364 R"cpp(// Macro outside preamble
2365 int breakPreamble;
2366 #define $def[[MA^CRO]](X) (X+1)
2367 void test() {
2368 int x = $[[MACRO]]($[[MACRO]](1));
2369 }
2370 )cpp",
2371
2372 R"cpp(
2373 int $def[[v^ar]] = 0;
2374 void foo(int s = $(foo)[[var]]);
2375 )cpp",
2376
2377 R"cpp(
2378 template <typename T>
2379 class $def[[Fo^o]] {};
2380 void func($(func)[[Foo]]<int>);
2381 )cpp",
2382
2383 R"cpp(
2384 template <typename T>
2385 class $def[[Foo]] {};
2386 void func($(func)[[Fo^o]]<int>);
2387 )cpp",
2388 R"cpp(// Not touching any identifiers.
2389 struct Foo {
2390 $def(Foo)[[~]]Foo() {};
2391 };
2392 void foo() {
2393 Foo f;
2394 f.$(foo)[[^~]]Foo();
2395 }
2396 )cpp",
2397 R"cpp(// Lambda capture initializer
2398 void foo() {
2399 int $def(foo)[[w^aldo]] = 42;
2400 auto lambda = [x = $(foo)[[waldo]]](){};
2401 }
2402 )cpp",
2403 R"cpp(// Renaming alias
2404 template <typename> class Vector {};
2405 using $def[[^X]] = Vector<int>;
2406 $(x1)[[X]] x1;
2407 Vector<int> x2;
2408 Vector<double> y;
2409 )cpp",
2410 R"cpp(// Dependent code
2411 template <typename T> void $decl[[foo]](T t);
2412 template <typename T> void bar(T t) { $(bar)[[foo]](t); } // foo in bar is uninstantiated.
2413 void baz(int x) { $(baz)[[f^oo]](x); }
2414 )cpp",
2415 R"cpp(
2416 namespace ns {
2417 struct S{};
2418 void $decl(ns)[[foo]](S s);
2419 } // namespace ns
2420 template <typename T> void foo(T t);
2421 // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL)
2422 // when bar<ns::S> is instantiated?
2423 template <typename T> void bar(T t) { foo(t); }
2424 void baz(int x) {
2425 ns::S s;
2426 bar<ns::S>(s);
2427 $(baz)[[f^oo]](s);
2428 }
2429 )cpp",
2430 R"cpp(// unresolved member expression
2431 struct Foo {
2432 template <typename T> void $decl(Foo)[[b^ar]](T t);
2433 };
2434 template <typename T> void test(Foo F, T t) {
2435 F.$(test)[[bar]](t);
2436 }
2437 )cpp",
2438
2439 // Enum base
2440 R"cpp(
2441 typedef int $def[[MyTypeD^ef]];
2442 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2443 )cpp",
2444 R"cpp(
2445 typedef int $def[[MyType^Def]];
2446 enum MyEnum : $(MyEnum)[[MyTypeD^ef]];
2447 )cpp",
2448 R"cpp(
2449 using $def[[MyTypeD^ef]] = int;
2450 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2451 )cpp",
2452 // UDL
2453 R"cpp(
2454 bool $decl[[operator]]"" _u^dl(unsigned long long value);
2455 bool x = $(x)[[1_udl]];
2456 )cpp",
2457 R"cpp(
2458 struct S {
2459 public:
2460 static void $decl(S)[[operator]] delete(void *);
2461 static void deleteObject(S *S) {
2462 $(S::deleteObject)[[de^lete]] S;
2463 }
2464 };
2465 )cpp",
2466 // Array designators
2467 R"cpp(
2468 const int $def[[F^oo]] = 0;
2469 int Bar[] = {
2470 [$(Bar)[[F^oo]]...$(Bar)[[Fo^o]] + 1] = 0,
2471 [$(Bar)[[^Foo]] + 2] = 1
2472 };
2473 )cpp",
2474 // Field of pointer-to-member type
2475 R"cpp(
2476 struct S { void foo(); };
2477 struct A {
2478 void (S::*$def(A)[[fi^eld]])();
2479 };
2480 void bar(A& a, S& s) {
2481 (s.*(a.$(bar)[[field]]))();
2482 }
2483 )cpp"};
2484 for (const char *Test : Tests)
2485 checkFindRefs(Test);
2486}
2487
2488TEST(FindReferences, ConceptsWithinAST) {
2489 constexpr llvm::StringLiteral Code = R"cpp(
2490 template <class T>
2491 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2492
2493 template <class T>
2494 concept IsSmallPtr = requires(T x) {
2495 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2496 };
2497
2498 $(i)[[IsSmall]] auto i = 'c';
2499 template<$(foo)[[IsSmal^l]] U> void foo();
2500 template<class U> void bar() requires $(bar)[[IsSmal^l]]<U>;
2501 template<class U> requires $(baz)[[IsSmal^l]]<U> void baz();
2502 static_assert([[IsSma^ll]]<char>);
2503 )cpp";
2504 checkFindRefs(Code);
2505}
2506
2507TEST(FindReferences, ConceptReq) {
2508 constexpr llvm::StringLiteral Code = R"cpp(
2509 template <class T>
2510 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2511
2512 template <class T>
2513 concept IsSmallPtr = requires(T x) {
2514 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2515 };
2516 )cpp";
2517 checkFindRefs(Code);
2518}
2519
2520TEST(FindReferences, RequiresExprParameters) {
2521 constexpr llvm::StringLiteral Code = R"cpp(
2522 template <class T>
2523 concept IsSmall = sizeof(T) <= 8;
2524
2525 template <class T>
2526 concept IsSmallPtr = requires(T $def[[^x]]) {
2527 { *$(IsSmallPtr)[[^x]] } -> IsSmall;
2528 };
2529 )cpp";
2530 checkFindRefs(Code);
2531}
2532
2533TEST(FindReferences, IncludeOverrides) {
2534 llvm::StringRef Test =
2535 R"cpp(
2536 class Base {
2537 public:
2538 virtu^al void $decl(Base)[[f^unc]]() ^= ^0;
2539 };
2540 class Derived : public Base {
2541 public:
2542 void $overridedecl(Derived::func)[[func]]() override;
2543 };
2544 void Derived::$overridedef[[func]]() {}
2545 class Derived2 : public Base {
2546 void $overridedef(Derived2::func)[[func]]() override {}
2547 };
2548 void test(Derived* D, Base* B) {
2549 D->func(); // No references to the overrides.
2550 B->$(test)[[func]]();
2551 })cpp";
2552 checkFindRefs(Test, /*UseIndex=*/true);
2553}
2554
2555TEST(FindReferences, IncludeOverridesObjC) {
2556 llvm::StringRef Test =
2557 R"objc(
2558 @interface Base
2559 - (void)$decl(Base)[[f^unc]];
2560 @end
2561 @interface Derived : Base
2562 - (void)$overridedecl(Derived::func)[[func]];
2563 @end
2564 @implementation Derived
2565 - (void)$overridedef[[func]] {}
2566 @end
2567 void test(Derived *derived, Base *base) {
2568 [derived func]; // No references to the overrides.
2569 [base $(test)[[func]]];
2570 })objc";
2571 checkFindRefs(Test, /*UseIndex=*/true);
2572}
2573
2574TEST(FindReferences, RefsToBaseMethod) {
2575 llvm::StringRef Test =
2576 R"cpp(
2577 class BaseBase {
2578 public:
2579 virtual void $(BaseBase)[[func]]();
2580 };
2581 class Base : public BaseBase {
2582 public:
2583 void $(Base)[[func]]() override;
2584 };
2585 class Derived : public Base {
2586 public:
2587 void $decl(Derived)[[fu^nc]]() over^ride;
2588 };
2589 void test(BaseBase* BB, Base* B, Derived* D) {
2590 // refs to overridden methods in complete type hierarchy are reported.
2591 BB->$(test)[[func]]();
2592 B->$(test)[[func]]();
2593 D->$(test)[[fu^nc]]();
2594 })cpp";
2595 checkFindRefs(Test, /*UseIndex=*/true);
2596}
2597
2598TEST(FindReferences, RefsToBaseMethodObjC) {
2599 llvm::StringRef Test =
2600 R"objc(
2601 @interface BaseBase
2602 - (void)$(BaseBase)[[func]];
2603 @end
2604 @interface Base : BaseBase
2605 - (void)$(Base)[[func]];
2606 @end
2607 @interface Derived : Base
2608 - (void)$decl(Derived)[[fu^nc]];
2609 @end
2610 void test(BaseBase *bb, Base *b, Derived *d) {
2611 // refs to overridden methods in complete type hierarchy are reported.
2612 [bb $(test)[[func]]];
2613 [b $(test)[[func]]];
2614 [d $(test)[[fu^nc]]];
2615 })objc";
2616 checkFindRefs(Test, /*UseIndex=*/true);
2617}
2618
2619TEST(FindReferences, MainFileReferencesOnly) {
2620 llvm::StringRef Test =
2621 R"cpp(
2622 void test() {
2623 int [[fo^o]] = 1;
2624 // refs not from main file should not be included.
2625 #include "foo.inc"
2626 })cpp";
2627
2628 Annotations Code(Test);
2629 auto TU = TestTU::withCode(Code.code());
2630 TU.AdditionalFiles["foo.inc"] = R"cpp(
2631 foo = 3;
2632 )cpp";
2633 auto AST = TU.build();
2634
2635 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2636 for (const auto &R : Code.ranges())
2637 ExpectedLocations.push_back(rangeIs(R));
2638 EXPECT_THAT(findReferences(AST, Code.point(), 0).References,
2639 ElementsAreArray(ExpectedLocations))
2640 << Test;
2641}
2642
2643TEST(FindReferences, ExplicitSymbols) {
2644 const char *Tests[] = {
2645 R"cpp(
2646 struct Foo { Foo* $decl(Foo)[[self]]() const; };
2647 void f() {
2648 Foo foo;
2649 if (Foo* T = foo.$(f)[[^self]]()) {} // Foo member call expr.
2650 }
2651 )cpp",
2652
2653 R"cpp(
2654 struct Foo { Foo(int); };
2655 Foo f() {
2656 int $def(f)[[b]];
2657 return $(f)[[^b]]; // Foo constructor expr.
2658 }
2659 )cpp",
2660
2661 R"cpp(
2662 struct Foo {};
2663 void g(Foo);
2664 Foo $decl[[f]]();
2665 void call() {
2666 g($(call)[[^f]]()); // Foo constructor expr.
2667 }
2668 )cpp",
2669
2670 R"cpp(
2671 void $decl[[foo]](int);
2672 void $decl[[foo]](double);
2673
2674 namespace ns {
2675 using ::$decl(ns)[[fo^o]];
2676 }
2677 )cpp",
2678
2679 R"cpp(
2680 struct X {
2681 operator bool();
2682 };
2683
2684 int test() {
2685 X $def(test)[[a]];
2686 $(test)[[a]].operator bool();
2687 if ($(test)[[a^]]) {} // ignore implicit conversion-operator AST node
2688 return 0;
2689 }
2690 )cpp",
2691 };
2692 for (const char *Test : Tests)
2693 checkFindRefs(Test);
2694}
2695
2696TEST(FindReferences, UsedSymbolsFromInclude) {
2697 const char *Tests[] = {
2698 R"cpp( [[#include ^"bar.h"]]
2699 #include <vector>
2700 int fstBar = [[bar1]]();
2701 int sndBar = [[bar2]]();
2702 [[Bar]] bar;
2703 int macroBar = [[BAR]];
2704 std::vector<int> vec;
2705 )cpp",
2706
2707 R"cpp([[#in^clude <vector>]]
2708 std::[[vector]]<int> vec;
2709 )cpp",
2710
2711 R"cpp(
2712 [[#include ^"udl_header.h"]]
2713 auto x = [[1_b]];
2714 )cpp",
2715 };
2716 for (const char *Test : Tests) {
2717 Annotations T(Test);
2718 auto TU = TestTU::withCode(T.code());
2719 TU.ExtraArgs.push_back("-std=c++20");
2720 TU.AdditionalFiles["bar.h"] = guard(R"cpp(
2721 #define BAR 5
2722 int bar1();
2723 int bar2();
2724 class Bar {};
2725 )cpp");
2726 TU.AdditionalFiles["system/vector"] = guard(R"cpp(
2727 namespace std {
2728 template<typename>
2729 class vector{};
2730 }
2731 )cpp");
2732 TU.AdditionalFiles["udl_header.h"] = guard(R"cpp(
2733 bool operator"" _b(unsigned long long value);
2734 )cpp");
2735 TU.ExtraArgs.push_back("-isystem" + testPath("system"));
2736
2737 auto AST = TU.build();
2738 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2739 for (const auto &R : T.ranges())
2740 ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
2741 for (const auto &P : T.points())
2742 EXPECT_THAT(findReferences(AST, P, 0).References,
2743 UnorderedElementsAreArray(ExpectedLocations))
2744 << "Failed for Refs at " << P << "\n"
2745 << Test;
2746 }
2747}
2748
2749TEST(FindReferences, NeedsIndexForSymbols) {
2750 const char *Header = "int foo();";
2751 Annotations Main("int main() { [[f^oo]](); }");
2752 TestTU TU;
2753 TU.Code = std::string(Main.code());
2754 TU.HeaderCode = Header;
2755 auto AST = TU.build();
2756
2757 // References in main file are returned without index.
2758 EXPECT_THAT(
2759 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
2760 ElementsAre(rangeIs(Main.range())));
2761 Annotations IndexedMain(R"cpp(
2762 int $decl[[foo]]() { return 42; }
2763 void bar() { $bar(bar)[[foo]](); }
2764 struct S { void bar() { $S(S::bar)[[foo]](); } };
2765 namespace N { void bar() { $N(N::bar)[[foo]](); } }
2766 )cpp");
2767
2768 // References from indexed files are included.
2769 TestTU IndexedTU;
2770 IndexedTU.Code = std::string(IndexedMain.code());
2771 IndexedTU.Filename = "Indexed.cpp";
2772 IndexedTU.HeaderCode = Header;
2773 EXPECT_THAT(
2774 findReferences(AST, Main.point(), 0, IndexedTU.index().get(),
2775 /*AddContext*/ true)
2776 .References,
2777 ElementsAre(
2778 rangeIs(Main.range()),
2779 AllOf(rangeIs(IndexedMain.range("decl")),
2782 AllOf(rangeIs(IndexedMain.range("bar")), containerIs("bar")),
2783 AllOf(rangeIs(IndexedMain.range("S")), containerIs("S::bar")),
2784 AllOf(rangeIs(IndexedMain.range("N")), containerIs("N::bar"))));
2785 auto LimitRefs =
2786 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
2787 EXPECT_EQ(1u, LimitRefs.References.size());
2788 EXPECT_TRUE(LimitRefs.HasMore);
2789
2790 // Avoid indexed results for the main file. Use AST for the mainfile.
2791 TU.Code = ("\n\n" + Main.code()).str();
2792 EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,
2793 ElementsAre(rangeIs(Main.range())));
2794}
2795
2796TEST(FindReferences, NeedsIndexForMacro) {
2797 const char *Header = "#define MACRO(X) (X+1)";
2798 Annotations Main(R"cpp(
2799 int main() {
2800 int a = [[MA^CRO]](1);
2801 }
2802 )cpp");
2803 TestTU TU;
2804 TU.Code = std::string(Main.code());
2805 TU.HeaderCode = Header;
2806 auto AST = TU.build();
2807
2808 // References in main file are returned without index.
2809 EXPECT_THAT(
2810 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
2811 ElementsAre(rangeIs(Main.range())));
2812
2813 Annotations IndexedMain(R"cpp(
2814 int indexed_main() {
2815 int a = [[MACRO]](1);
2816 return 0;
2817 }
2818 )cpp");
2819
2820 // References from indexed files are included.
2821 TestTU IndexedTU;
2822 IndexedTU.Code = std::string(IndexedMain.code());
2823 IndexedTU.Filename = "Indexed.cpp";
2824 IndexedTU.HeaderCode = Header;
2825 EXPECT_THAT(
2826 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
2827 ElementsAre(rangeIs(Main.range()), rangeIs(IndexedMain.range())));
2828 auto LimitRefs =
2829 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
2830 EXPECT_EQ(1u, LimitRefs.References.size());
2831 EXPECT_TRUE(LimitRefs.HasMore);
2832}
2833
2834TEST(FindReferences, NoQueryForLocalSymbols) {
2835 struct RecordingIndex : public MemIndex {
2836 mutable std::optional<llvm::DenseSet<SymbolID>> RefIDs;
2837 bool refs(const RefsRequest &Req,
2838 llvm::function_ref<void(const Ref &)>) const override {
2839 RefIDs = Req.IDs;
2840 return false;
2841 }
2842 };
2843
2844 struct Test {
2845 StringRef AnnotatedCode;
2846 bool WantQuery;
2847 } Tests[] = {
2848 {"int ^x;", true},
2849 // For now we don't assume header structure which would allow skipping.
2850 {"namespace { int ^x; }", true},
2851 {"static int ^x;", true},
2852 // Anything in a function certainly can't be referenced though.
2853 {"void foo() { int ^x; }", false},
2854 {"void foo() { struct ^x{}; }", false},
2855 {"auto lambda = []{ int ^x; };", false},
2856 };
2857 for (Test T : Tests) {
2858 Annotations File(T.AnnotatedCode);
2859 RecordingIndex Rec;
2860 auto AST = TestTU::withCode(File.code()).build();
2861 findReferences(AST, File.point(), 0, &Rec);
2862 if (T.WantQuery)
2863 EXPECT_NE(Rec.RefIDs, std::nullopt) << T.AnnotatedCode;
2864 else
2865 EXPECT_EQ(Rec.RefIDs, std::nullopt) << T.AnnotatedCode;
2866 }
2867}
2868
2869TEST(FindReferences, ConstructorForwardingInAST) {
2870 Annotations Main(R"cpp(
2871 namespace std {
2872 template <class T> T &&forward(T &t);
2873 template <class T, class... Args> T *make_unique(Args &&...args) {
2874 return new T(std::forward<Args>(args)...);
2875 }
2876 }
2877
2878 struct Test {
2879 $Constructor[[T^est]](){}
2880 };
2881
2882 int main() {
2883 auto a = std::$Caller[[make_unique]]<Test>();
2884 }
2885 )cpp");
2886 TestTU TU;
2887 TU.Code = std::string(Main.code());
2888 auto AST = TU.build();
2889
2890 EXPECT_THAT(findReferences(AST, Main.point(), 0).References,
2891 ElementsAre(rangeIs(Main.range("Constructor")),
2892 rangeIs(Main.range("Caller"))));
2893}
2894
2895TEST(FindReferences, ConstructorForwardingInASTChained) {
2896 Annotations Main(R"cpp(
2897 namespace std {
2898 template <class T> T &&forward(T &t);
2899 template <class T, class... Args> T *make_unique(Args &&...args) {
2900 return new T(forward<Args>(args)...);
2901 }
2902 template <class T, class... Args> T *make_unique2(Args &&...args) {
2903 return make_unique<T>(forward<Args>(args)...);
2904 }
2905 template <class T, class... Args> T *make_unique3(Args &&...args) {
2906 return make_unique2<T>(forward<Args>(args)...);
2907 }
2908 }
2909
2910 struct Test {
2911 $Constructor[[T^est]](){}
2912 };
2913
2914 int main() {
2915 auto a = std::$Caller[[make_unique3]]<Test>();
2916 }
2917 )cpp");
2918 TestTU TU;
2919 TU.Code = std::string(Main.code());
2920 auto AST = TU.build();
2921
2922 EXPECT_THAT(findReferences(AST, Main.point(), 0).References,
2923 ElementsAre(rangeIs(Main.range("Constructor")),
2924 rangeIs(Main.range("Caller"))));
2925}
2926
2927TEST(FindReferences, ConstructorForwardingInIndex) {
2928 Annotations Header(R"cpp(
2929 namespace std {
2930 template <class T> T &&forward(T &t);
2931 template <class T, class... Args> T *make_unique(Args &&...args) {
2932 return new T(std::forward<Args>(args)...);
2933 }
2934 }
2935 struct Test {
2936 [[T^est]](){}
2937 };
2938 )cpp");
2939 Annotations Main(R"cpp(
2940 #include "header.hpp"
2941 int main() {
2942 auto a = std::[[make_unique]]<Test>();
2943 }
2944 )cpp");
2945 TestWorkspace TW;
2946 TW.addSource("header.hpp", Header.code());
2947 TW.addMainFile("main.cpp", Main.code());
2948 auto AST = TW.openFile("header.hpp").value();
2949 auto Index = TW.index();
2950
2951 EXPECT_THAT(
2952 findReferences(AST, Header.point(), 0, Index.get(),
2953 /*AddContext*/ true)
2954 .References,
2955 ElementsAre(
2956 AllOf(rangeIs(Header.range()), fileIs(testPath("header.hpp"))),
2957 AllOf(rangeIs(Main.range()), fileIs(testPath("main.cpp")))));
2958}
2959
2960TEST(FindReferences, TemplatedConstructorForwarding) {
2961 Annotations Main(R"cpp(
2962 namespace std {
2963 template <class T> T &&forward(T &t);
2964 template <class T, class... Args> T *make_unique(Args &&...args) {
2965 return new T(std::forward<Args>(args)...);
2966 }
2967 }
2968
2969 struct Waldo {
2970 template <typename T>
2971 $Constructor[[W$Waldo^aldo]](T);
2972 };
2973 template <typename T>
2974 struct Waldo2 {
2975 $Constructor2[[W$Waldo2^aldo2]](int);
2976 };
2977 struct S {};
2978
2979 int main() {
2980 S s;
2981 Waldo $Caller[[w]](s);
2982 std::$ForwardedCaller[[make_unique]]<Waldo>(s);
2983
2984 Waldo2<int> $Caller2[[w2]](42);
2985 std::$ForwardedCaller2[[make_unique]]<Waldo2<int>>(42);
2986 }
2987 )cpp");
2988 TestTU TU;
2989 TU.Code = std::string(Main.code());
2990 auto AST = TU.build();
2991
2992 EXPECT_THAT(findReferences(AST, Main.point("Waldo"), 0).References,
2993 ElementsAre(rangeIs(Main.range("Constructor")),
2994 rangeIs(Main.range("Caller")),
2995 rangeIs(Main.range("ForwardedCaller"))));
2996
2997 EXPECT_THAT(findReferences(AST, Main.point("Waldo2"), 0).References,
2998 ElementsAre(rangeIs(Main.range("Constructor2")),
2999 rangeIs(Main.range("Caller2")),
3000 rangeIs(Main.range("ForwardedCaller2"))));
3001}
3002
3003TEST(LocateSymbol, ConstructorForwarding) {
3004 // Caret-on-paren of a forwarding wrapper navigates to the constructor it
3005 // ultimately invokes; caret-on-identifier still navigates to the wrapper.
3006 // This mirrors the existing direct-ctor behaviour (`Abc^()` -> ctor,
3007 // `A^bc()` -> type).
3008 Annotations Code(R"cpp(
3009 namespace std {
3010 template <class T> T &&forward(T &t);
3011 template <class T, class... Args>
3012 T *$MakeUnique[[make_unique]](Args &&...args) {
3013 return new T(std::forward<Args>(args)...);
3014 }
3015 template <class T, class... Args> T *make_unique2(Args &&...args) {
3016 return make_unique<T>(forward<Args>(args)...);
3017 }
3018 template <class T, class... Args> T *make_unique3(Args &&...args) {
3019 return make_unique2<T>(forward<Args>(args)...);
3020 }
3021 template <class T> struct shared_ptr {
3022 shared_ptr(T *) {}
3023 };
3024 template <class T, class... Args>
3025 shared_ptr<T> make_shared(Args &&...args) {
3026 return shared_ptr<T>(new T(std::forward<Args>(args)...));
3027 }
3028 }
3029
3030 // Non-forwarding template: a call to it should fall through to itself.
3031 template <class T> T *$Make[[make]]() { return nullptr; }
3032
3033 struct Test {
3034 $DefaultCtor[[Test]]() {}
3035 $IntCtor[[Test]](int) {}
3036 Test(const char *) {}
3037 };
3038
3039 int main() {
3040 // Caret on parens -> Test default ctor.
3041 auto a = std::make_unique<Test>$ParenMU^();
3042 // Caret on the wrapper identifier -> make_unique itself.
3043 auto b = std::ma$IdentMU^ke_unique<Test>();
3044 // make_shared works the same way; overload resolution picks Test(int).
3045 auto c = std::make_shared<Test>$MakeShared^(1);
3046 // Chained forwarding (three wrappers deep).
3047 auto d = std::make_unique3<Test>$Chained^();
3048 // Overload resolution inside the instantiated body picks Test(int).
3049 auto e = std::make_unique<Test>$Overload^(42);
3050 // Non-forwarding template call: no constructor target.
3051 auto f = make<Test>$NonFwd^();
3052 }
3053 )cpp");
3054 TestTU TU = TestTU::withCode(Code.code());
3055 auto AST = TU.build();
3056
3057 EXPECT_THAT(locateSymbolAt(AST, Code.point("ParenMU")),
3058 ElementsAre(sym("Test", Code.range("DefaultCtor"),
3059 Code.range("DefaultCtor"))));
3060 EXPECT_THAT(locateSymbolAt(AST, Code.point("IdentMU")),
3061 ElementsAre(sym("make_unique", Code.range("MakeUnique"),
3062 Code.range("MakeUnique"))));
3063 EXPECT_THAT(
3064 locateSymbolAt(AST, Code.point("MakeShared")),
3065 ElementsAre(sym("Test", Code.range("IntCtor"), Code.range("IntCtor"))));
3066 EXPECT_THAT(locateSymbolAt(AST, Code.point("Chained")),
3067 ElementsAre(sym("Test", Code.range("DefaultCtor"),
3068 Code.range("DefaultCtor"))));
3069 EXPECT_THAT(
3070 locateSymbolAt(AST, Code.point("Overload")),
3071 ElementsAre(sym("Test", Code.range("IntCtor"), Code.range("IntCtor"))));
3072 EXPECT_THAT(locateSymbolAt(AST, Code.point("NonFwd")),
3073 ElementsAre(sym("make", Code.range("Make"), Code.range("Make"))));
3074}
3075
3076TEST(GetNonLocalDeclRefs, All) {
3077 struct Case {
3078 llvm::StringRef AnnotatedCode;
3079 std::vector<std::string> ExpectedDecls;
3080 } Cases[] = {
3081 {
3082 // VarDecl and ParamVarDecl
3083 R"cpp(
3084 void bar();
3085 void ^foo(int baz) {
3086 int x = 10;
3087 bar();
3088 })cpp",
3089 {"bar"},
3090 },
3091 {
3092 // Method from class
3093 R"cpp(
3094 class Foo { public: void foo(); };
3095 class Bar {
3096 void foo();
3097 void bar();
3098 };
3099 void Bar::^foo() {
3100 Foo f;
3101 bar();
3102 f.foo();
3103 })cpp",
3104 {"Bar", "Bar::bar", "Foo", "Foo::foo"},
3105 },
3106 {
3107 // Local types
3108 R"cpp(
3109 void ^foo() {
3110 class Foo { public: void foo() {} };
3111 class Bar { public: void bar() {} };
3112 Foo f;
3113 Bar b;
3114 b.bar();
3115 f.foo();
3116 })cpp",
3117 {},
3118 },
3119 {
3120 // Template params
3121 R"cpp(
3122 template <typename T, template<typename> class Q>
3123 void ^foo() {
3124 T x;
3125 Q<T> y;
3126 })cpp",
3127 {},
3128 },
3129 };
3130 for (const Case &C : Cases) {
3131 Annotations File(C.AnnotatedCode);
3132 auto AST = TestTU::withCode(File.code()).build();
3133 SourceLocation SL = llvm::cantFail(
3134 sourceLocationInMainFile(AST.getSourceManager(), File.point()));
3135
3136 const FunctionDecl *FD =
3137 llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) {
3138 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
3139 }));
3140 ASSERT_NE(FD, nullptr);
3141
3142 auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD);
3143 std::vector<std::string> Names;
3144 for (const Decl *D : NonLocalDeclRefs) {
3145 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
3146 Names.push_back(ND->getQualifiedNameAsString());
3147 }
3148 EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
3149 << File.code();
3150 }
3151}
3152
3153TEST(DocumentLinks, All) {
3154 Annotations MainCpp(R"cpp(
3155 #define HEADER_AA "faa.h"
3156 #define HEADER_BB "fbb.h"
3157 #define GET_HEADER(X) HEADER_ ## X
3158
3159 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
3160 int end_of_preamble = 0;
3161 #include $bar[[<bar.h>]]
3162 #include $AA[[GET_HEADER]](AA) // Some comment !
3163 # /* What about */ \
3164 include /* multiple line */ \
3165 $BB[[GET_HEADER]]( /* statements ? */ \
3166 BB /* :) */ )
3167 )cpp");
3168
3169 TestTU TU;
3170 TU.Code = std::string(MainCpp.code());
3171 TU.AdditionalFiles = {
3172 {"faa.h", ""}, {"fbb.h", ""}, {"foo.h", ""}, {"bar.h", ""}};
3173 TU.ExtraArgs = {"-isystem."};
3174 auto AST = TU.build();
3175
3176 EXPECT_THAT(
3178 ElementsAre(
3179 DocumentLink({MainCpp.range("foo"),
3180 URIForFile::canonicalize(testPath("foo.h"), "")}),
3181 DocumentLink({MainCpp.range("bar"),
3182 URIForFile::canonicalize(testPath("bar.h"), "")}),
3183 DocumentLink({MainCpp.range("AA"),
3184 URIForFile::canonicalize(testPath("faa.h"), "")}),
3185 DocumentLink({MainCpp.range("BB"),
3186 URIForFile::canonicalize(testPath("fbb.h"), "")})));
3187}
3188
3189} // namespace
3190} // namespace clangd
3191} // namespace clang
std::vector< HeaderEntry > HeaderContents
Same as llvm::Annotations, but adjusts functions to LSP-specific types for positions and ranges.
Definition Annotations.h:23
Manages a collection of source files and derived data (ASTs, indexes), and provides language-aware fe...
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition Context.h:69
MemIndex is a naive in-memory index suitable for a small set of symbols.
Definition MemIndex.h:21
Stores and provides access to parsed AST.
Definition ParsedAST.h:47
void addSource(llvm::StringRef Filename, llvm::StringRef Code)
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:44
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
Definition AST.cpp:354
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition TestTU.cpp:220
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition XRefs.cpp:1511
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat, llvm::StringRef Signature)
Definition TestIndex.cpp:40
std::vector< LocatedSymbol > locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST, const SymbolIndex *Index, llvm::StringRef MainFilePath, ASTNodeKind NodeKind)
Definition XRefs.cpp:672
std::vector< DocumentLink > getDocumentLinks(ParsedAST &AST)
Get all document links.
Definition XRefs.cpp:959
std::vector< LocatedSymbol > findType(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Returns symbols for types referenced at Pos.
Definition XRefs.cpp:2382
MATCHER_P(named, N, "")
ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index, bool AddContext)
Returns references of the symbol at a specified Pos.
Definition XRefs.cpp:1677
std::string testPath(PathRef File, llvm::sys::path::Style Style)
Definition TestFS.cpp:94
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition XRefs.cpp:873
TEST(BackgroundQueueTest, Priority)
const syntax::Token * findNearbyIdentifier(const SpelledWord &Word, const syntax::TokenBuffer &TB)
Definition XRefs.cpp:782
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, llvm::StringRef Version, WantDiagnostics WantDiags, bool ForceRebuild)
Definition SyncAPI.cpp:17
llvm::Expected< std::vector< LocatedSymbol > > runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos)
Definition SyncAPI.cpp:88
const Symbol & findSymbol(const SymbolSlab &Slab, llvm::StringRef QName)
Definition TestTU.cpp:186
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
@ No
Diagnostics must be generated for this snapshot.
Definition TUScheduler.h:55
std::vector< LocatedSymbol > findImplementations(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Returns implementations at a specified Pos:
Definition XRefs.cpp:1552
llvm::DenseSet< const Decl * > getNonLocalDeclRefs(ParsedAST &AST, const FunctionDecl *FD)
Returns all decls that are referenced in the FD except local symbols.
Definition XRefs.cpp:2726
@ Alias
This declaration is an alias that was referred to.
Definition FindTarget.h:112
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccessCheck P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::vector< Reference > References
Definition XRefs.h:94
static std::optional< SpelledWord > touching(SourceLocation SpelledLoc, const syntax::TokenBuffer &TB, const LangOptions &LangOpts)
SymbolID ID
The ID of the symbol.
Definition Symbol.h:51
std::string Code
Definition TestTU.h:49
ParsedAST build() const
Definition TestTU.cpp:115
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
Definition TestTU.h:42
static TestTU withCode(llvm::StringRef Code)
Definition TestTU.h:36
std::string HeaderCode
Definition TestTU.h:53
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition Protocol.cpp:46