clang-tools 10.0.0

FindTargetTests.cpp
Go to the documentation of this file.
1 //===-- FindSymbolsTests.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 "FindTarget.h"
9
10 #include "Selection.h"
11 #include "TestTU.h"
12 #include "clang/AST/Decl.h"
13 #include "clang/AST/DeclTemplate.h"
14 #include "clang/Basic/SourceLocation.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/Casting.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/Testing/Support/Annotations.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include <initializer_list>
22
23 namespace clang {
24 namespace clangd {
25 namespace {
26
27 // A referenced Decl together with its DeclRelationSet, for assertions.
28 //
29 // There's no great way to assert on the "content" of a Decl in the general case
30 // that's both expressive and unambiguous (e.g. clearly distinguishes between
31 // templated decls and their specializations).
32 //
33 // We use the result of pretty-printing the decl, with the {body} truncated.
34 struct PrintedDecl {
35 PrintedDecl(const char *Name, DeclRelationSet Relations = {})
36 : Name(Name), Relations(Relations) {}
37 PrintedDecl(const NamedDecl *D, DeclRelationSet Relations = {})
38 : Relations(Relations) {
39 std::string S;
40 llvm::raw_string_ostream OS(S);
41 D->print(OS);
42 llvm::StringRef FirstLine =
43 llvm::StringRef(OS.str()).take_until([](char C) { return C == '\n'; });
44 FirstLine = FirstLine.rtrim(" {");
45 Name = FirstLine.rtrim(" {");
46 }
47
48 std::string Name;
49 DeclRelationSet Relations;
50 };
51 bool operator==(const PrintedDecl &L, const PrintedDecl &R) {
52 return std::tie(L.Name, L.Relations) == std::tie(R.Name, R.Relations);
53 }
54 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const PrintedDecl &D) {
55 return OS << D.Name << " Rel=" << D.Relations;
56 }
57
58 // The test cases in for targetDecl() take the form
59 // - a piece of code (Code = "...")
60 // - Code should have a single AST node marked as a [[range]]
61 // - an EXPECT_DECLS() assertion that verify the type of node selected, and
62 // all the decls that targetDecl() considers it to reference
63 // Despite the name, these cases actually test allTargetDecls() for brevity.
64 class TargetDeclTest : public ::testing::Test {
65 protected:
66 using Rel = DeclRelation;
67 std::string Code;
68 std::vector<const char *> Flags;
69
70 // Asserts that `Code` has a marked selection of a node `NodeType`,
71 // and returns allTargetDecls() as PrintedDecl structs.
72 // Use via EXPECT_DECLS().
73 std::vector<PrintedDecl> assertNodeAndPrintDecls(const char *NodeType) {
74 llvm::Annotations A(Code);
75 auto TU = TestTU::withCode(A.code());
76 TU.ExtraArgs = Flags;
77 auto AST = TU.build();
78 EXPECT_THAT(AST.getDiagnostics(), ::testing::IsEmpty()) << Code;
79 llvm::Annotations::Range R = A.range();
80 SelectionTree Selection(AST.getASTContext(), AST.getTokens(), R.Begin,
81 R.End);
82 const SelectionTree::Node *N = Selection.commonAncestor();
83 if (!N) {
84 ADD_FAILURE() << "No node selected!\n" << Code;
85 return {};
86 }
87 EXPECT_EQ(N->kind(), NodeType) << Selection;
88
89 std::vector<PrintedDecl> ActualDecls;
90 for (const auto &Entry : allTargetDecls(N->ASTNode))
91 ActualDecls.emplace_back(Entry.first, Entry.second);
92 return ActualDecls;
93 }
94 };
95
96 // This is a macro to preserve line numbers in assertion failures.
97 // It takes the expected decls as varargs to work around comma-in-macro issues.
98 #define EXPECT_DECLS(NodeType, ...) \
99 EXPECT_THAT(assertNodeAndPrintDecls(NodeType), \
100 ::testing::UnorderedElementsAreArray( \
101 std::vector<PrintedDecl>({__VA_ARGS__}))) \
102 << Code
103 using ExpectedDecls = std::vector<PrintedDecl>;
104
105 TEST_F(TargetDeclTest, Exprs) {
106 Code = R"cpp(
107 int f();
108 int x = [[f]]();
109 )cpp";
110 EXPECT_DECLS("DeclRefExpr", "int f()");
111
112 Code = R"cpp(
113 struct S { S operator+(S) const; };
114 auto X = S() [[+]] S();
115 )cpp";
116 EXPECT_DECLS("DeclRefExpr", "S operator+(S) const");
117
118 Code = R"cpp(
119 int foo();
120 int s = foo[[()]];
121 )cpp";
122 EXPECT_DECLS("CallExpr", "int foo()");
123
124 Code = R"cpp(
125 struct X {
126 void operator()(int n);
127 };
128 void test() {
129 X x;
130 x[[(123)]];
131 }
132 )cpp";
133 EXPECT_DECLS("CXXOperatorCallExpr", "void operator()(int n)");
134 }
135
136 TEST_F(TargetDeclTest, UsingDecl) {
137 Code = R"cpp(
138 namespace foo {
139 int f(int);
140 int f(char);
141 }
142 using foo::f;
143 int x = [[f]](42);
144 )cpp";
145 // f(char) is not referenced!
146 EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias},
147 {"int f(int)", Rel::Underlying});
148
149 Code = R"cpp(
150 namespace foo {
151 int f(int);
152 int f(char);
153 }
154 [[using foo::f]];
155 )cpp";
156 // All overloads are referenced.
157 EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias},
158 {"int f(int)", Rel::Underlying},
159 {"int f(char)", Rel::Underlying});
160
161 Code = R"cpp(
162 struct X {
163 int foo();
164 };
165 struct Y : X {
166 using X::foo;
167 };
168 int x = Y().[[foo]]();
169 )cpp";
170 EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias},
171 {"int foo()", Rel::Underlying});
172 }
173
174 TEST_F(TargetDeclTest, ConstructorInitList) {
175 Code = R"cpp(
176 struct X {
177 int a;
178 X() : [[a]](42) {}
179 };
180 )cpp";
181 EXPECT_DECLS("CXXCtorInitializer", "int a");
182
183 Code = R"cpp(
184 struct X {
185 X() : [[X]](1) {}
186 X(int);
187 };
188 )cpp";
189 EXPECT_DECLS("RecordTypeLoc", "struct X");
190 }
191
192 TEST_F(TargetDeclTest, DesignatedInit) {
193 Flags = {"-xc"}; // array designators are a C99 extension.
194 Code = R"c(
195 struct X { int a; };
196 struct Y { int b; struct X c[2]; };
197 struct Y y = { .c[0].[[a]] = 1 };
198 )c";
199 EXPECT_DECLS("DesignatedInitExpr", "int a");
200 }
201
202 TEST_F(TargetDeclTest, NestedNameSpecifier) {
203 Code = R"cpp(
204 namespace a { namespace b { int c; } }
205 int x = a::[[b::]]c;
206 )cpp";
207 EXPECT_DECLS("NestedNameSpecifierLoc", "namespace b");
208
209 Code = R"cpp(
210 namespace a { struct X { enum { y }; }; }
211 int x = a::[[X::]]y;
212 )cpp";
213 EXPECT_DECLS("NestedNameSpecifierLoc", "struct X");
214
215 Code = R"cpp(
216 template <typename T>
217 int x = [[T::]]y;
218 )cpp";
219 // FIXME: We don't do a good job printing TemplateTypeParmDecls, apparently!
220 EXPECT_DECLS("NestedNameSpecifierLoc", "");
221
222 Code = R"cpp(
223 namespace a { int x; }
224 namespace b = a;
225 int y = [[b]]::x;
226 )cpp";
227 EXPECT_DECLS("NestedNameSpecifierLoc", {"namespace b = a", Rel::Alias},
228 {"namespace a", Rel::Underlying});
229 }
230
231 TEST_F(TargetDeclTest, Types) {
232 Code = R"cpp(
233 struct X{};
234 [[X]] x;
235 )cpp";
236 EXPECT_DECLS("RecordTypeLoc", "struct X");
237
238 Code = R"cpp(
239 struct S{};
240 typedef S X;
241 [[X]] x;
242 )cpp";
243 EXPECT_DECLS("TypedefTypeLoc", {"typedef S X", Rel::Alias},
244 {"struct S", Rel::Underlying});
245
246 // FIXME: Auto-completion in a template requires disabling delayed template
247 // parsing.
248 Flags = {"-fno-delayed-template-parsing"};
249 Code = R"cpp(
250 template<class T>
251 void foo() { [[T]] x; }
252 )cpp";
253 // FIXME: We don't do a good job printing TemplateTypeParmDecls, apparently!
254 EXPECT_DECLS("TemplateTypeParmTypeLoc", "");
255 Flags.clear();
256
257 // FIXME: Auto-completion in a template requires disabling delayed template
258 // parsing.
259 Flags = {"-fno-delayed-template-parsing"};
260 Code = R"cpp(
261 template<template<typename> class T>
262 void foo() { [[T<int>]] x; }
263 )cpp";
264 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template <typename> class T");
265 Flags.clear();
266
267 Code = R"cpp(
268 struct S{};
269 S X;
270 [[decltype]](X) Y;
271 )cpp";
272 EXPECT_DECLS("DecltypeTypeLoc", {"struct S", Rel::Underlying});
273
274 Code = R"cpp(
275 struct S{};
276 [[auto]] X = S{};
277 )cpp";
278 // FIXME: deduced type missing in AST. https://llvm.org/PR42914
279 EXPECT_DECLS("AutoTypeLoc");
280
281 Code = R"cpp(
282 template <typename... E>
283 struct S {
284 static const int size = sizeof...([[E]]);
285 };
286 )cpp";
287 // FIXME: We don't do a good job printing TemplateTypeParmDecls, apparently!
288 EXPECT_DECLS("SizeOfPackExpr", "");
289 }
290
291 TEST_F(TargetDeclTest, ClassTemplate) {
292 Code = R"cpp(
293 // Implicit specialization.
294 template<int x> class Foo{};
295 [[Foo<42>]] B;
296 )cpp";
297 EXPECT_DECLS("TemplateSpecializationTypeLoc",
298 {"template<> class Foo<42>", Rel::TemplateInstantiation},
299 {"class Foo", Rel::TemplatePattern});
300
301 Code = R"cpp(
302 // Explicit specialization.
303 template<int x> class Foo{};
304 template<> class Foo<42>{};
305 [[Foo<42>]] B;
306 )cpp";
307 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template<> class Foo<42>");
308
309 Code = R"cpp(
310 // Partial specialization.
311 template<typename T> class Foo{};
312 template<typename T> class Foo<T*>{};
313 [[Foo<int*>]] B;
314 )cpp";
315 EXPECT_DECLS("TemplateSpecializationTypeLoc",
316 {"template<> class Foo<int *>", Rel::TemplateInstantiation},
317 {"template <typename T> class Foo<T *>", Rel::TemplatePattern});
318
319 Code = R"cpp(
320 // Class template argument deduction
321 template <typename T>
322 struct Test {
323 Test(T);
324 };
325 void foo() {
326 [[Test]] a(5);
327 }
328 )cpp";
329 Flags.push_back("-std=c++17");
330 EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",
331 {"struct Test", Rel::TemplatePattern});
332 }
333
334 TEST_F(TargetDeclTest, FunctionTemplate) {
335 Code = R"cpp(
336 // Implicit specialization.
337 template<typename T> bool foo(T) { return false; };
338 bool x = [[foo]](42);
339 )cpp";
340 EXPECT_DECLS("DeclRefExpr",
341 {"template<> bool foo<int>(int)", Rel::TemplateInstantiation},
342 {"bool foo(T)", Rel::TemplatePattern});
343
344 Code = R"cpp(
345 // Explicit specialization.
346 template<typename T> bool foo(T) { return false; };
347 template<> bool foo<int>(int) { return false; };
348 bool x = [[foo]](42);
349 )cpp";
350 EXPECT_DECLS("DeclRefExpr", "template<> bool foo<int>(int)");
351 }
352
353 TEST_F(TargetDeclTest, VariableTemplate) {
354 // Pretty-printer doesn't do a very good job of variable templates :-(
355 Code = R"cpp(
356 // Implicit specialization.
357 template<typename T> int foo;
358 int x = [[foo]]<char>;
359 )cpp";
360 EXPECT_DECLS("DeclRefExpr", {"int foo", Rel::TemplateInstantiation},
361 {"int foo", Rel::TemplatePattern});
362
363 Code = R"cpp(
364 // Explicit specialization.
365 template<typename T> int foo;
366 template <> bool foo<char>;
367 int x = [[foo]]<char>;
368 )cpp";
369 EXPECT_DECLS("DeclRefExpr", "bool foo");
370
371 Code = R"cpp(
372 // Partial specialization.
373 template<typename T> int foo;
374 template<typename T> bool foo<T*>;
375 bool x = [[foo]]<char*>;
376 )cpp";
377 EXPECT_DECLS("DeclRefExpr", {"bool foo", Rel::TemplateInstantiation},
378 {"bool foo", Rel::TemplatePattern});
379 }
380
381 TEST_F(TargetDeclTest, TypeAliasTemplate) {
382 Code = R"cpp(
383 template<typename T, int X> class SmallVector {};
384 template<typename U> using TinyVector = SmallVector<U, 1>;
385 [[TinyVector<int>]] X;
386 )cpp";
387 EXPECT_DECLS("TemplateSpecializationTypeLoc",
388 {"template<> class SmallVector<int, 1>",
389 Rel::TemplateInstantiation | Rel::Underlying},
390 {"class SmallVector", Rel::TemplatePattern | Rel::Underlying},
391 {"using TinyVector = SmallVector<U, 1>",
392 Rel::Alias | Rel::TemplatePattern});
393 }
394
395 TEST_F(TargetDeclTest, MemberOfTemplate) {
396 Code = R"cpp(
397 template <typename T> struct Foo {
398 int x(T);
399 };
400 int y = Foo<int>().[[x]](42);
401 )cpp";
402 EXPECT_DECLS("MemberExpr", {"int x(int)", Rel::TemplateInstantiation},
403 {"int x(T)", Rel::TemplatePattern});
404
405 Code = R"cpp(
406 template <typename T> struct Foo {
407 template <typename U>
408 int x(T, U);
409 };
410 int y = Foo<char>().[[x]]('c', 42);
411 )cpp";
412 EXPECT_DECLS("MemberExpr",
413 {"template<> int x<int>(char, int)", Rel::TemplateInstantiation},
414 {"int x(T, U)", Rel::TemplatePattern});
415 }
416
417 TEST_F(TargetDeclTest, Lambda) {
418 Code = R"cpp(
419 void foo(int x = 42) {
420 auto l = [ [[x]] ]{ return x + 1; };
421 };
422 )cpp";
423 EXPECT_DECLS("DeclRefExpr", "int x = 42");
424
425 // It seems like this should refer to another var, with the outer param being
426 // an underlying decl. But it doesn't seem to exist.
427 Code = R"cpp(
428 void foo(int x = 42) {
429 auto l = [x]{ return [[x]] + 1; };
430 };
431 )cpp";
432 EXPECT_DECLS("DeclRefExpr", "int x = 42");
433
434 Code = R"cpp(
435 void foo() {
436 auto l = [x = 1]{ return [[x]] + 1; };
437 };
438 )cpp";
439 // FIXME: why both auto and int?
440 EXPECT_DECLS("DeclRefExpr", "auto int x = 1");
441 }
442
443 TEST_F(TargetDeclTest, OverloadExpr) {
444 // FIXME: Auto-completion in a template requires disabling delayed template
445 // parsing.
446 Flags = {"-fno-delayed-template-parsing"};
447
448 Code = R"cpp(
449 void func(int*);
450 void func(char*);
451
452 template <class T>
453 void foo(T t) {
454 [[func]](t);
455 };
456 )cpp";
457 EXPECT_DECLS("UnresolvedLookupExpr", "void func(int *)", "void func(char *)");
458
459 Code = R"cpp(
460 struct X {
461 void func(int*);
462 void func(char*);
463 };
464
465 template <class T>
466 void foo(X x, T t) {
467 x.[[func]](t);
468 };
469 )cpp";
470 EXPECT_DECLS("UnresolvedMemberExpr", "void func(int *)", "void func(char *)");
471 }
472
473 TEST_F(TargetDeclTest, ObjC) {
474 Flags = {"-xobjective-c"};
475 Code = R"cpp(
476 @interface Foo {}
477 -(void)bar;
478 @end
479 void test(Foo *f) {
480 [f [[bar]] ];
481 }
482 )cpp";
483 EXPECT_DECLS("ObjCMessageExpr", "- (void)bar");
484
485 Code = R"cpp(
486 @interface Foo { @public int bar; }
487 @end
488 int test(Foo *f) {
489 return [[f->bar]];
490 }
491 )cpp";
492 EXPECT_DECLS("ObjCIvarRefExpr", "int bar");
493
494 Code = R"cpp(
495 @interface Foo {}
496 -(int) x;
497 -(void) setX:(int)x;
498 @end
499 void test(Foo *f) {
500 [[f.x]] = 42;
501 }
502 )cpp";
503 EXPECT_DECLS("ObjCPropertyRefExpr", "- (void)setX:(int)x");
504
505 Code = R"cpp(
506 @interface I {}
507 @property(retain) I* x;
508 @property(retain) I* y;
509 @end
510 void test(I *f) {
511 [[f.x]].y = 0;
512 }
513 )cpp";
514 EXPECT_DECLS("OpaqueValueExpr", "@property(atomic, retain, readwrite) I *x");
515
516 Code = R"cpp(
517 @protocol Foo
518 @end
519 id test() {
520 return [[@protocol(Foo)]];
521 }
522 )cpp";
523 EXPECT_DECLS("ObjCProtocolExpr", "@protocol Foo");
524
525 Code = R"cpp(
526 @interface Foo
527 @end
528 void test([[Foo]] *p);
529 )cpp";
530 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo");
531
532 Code = R"cpp(
533 @protocol Foo
534 @end
535 void test([[id<Foo>]] p);
536 )cpp";
537 EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo");
538
539 Code = R"cpp(
540 @class C;
541 @protocol Foo
542 @end
543 void test(C<[[Foo]]> *p);
544 )cpp";
545 // FIXME: there's no AST node corresponding to 'Foo', so we're stuck.
546 EXPECT_DECLS("ObjCObjectTypeLoc");
547 }
548
549 class FindExplicitReferencesTest : public ::testing::Test {
550 protected:
551 struct AllRefs {
552 std::string AnnotatedCode;
553 std::string DumpedReferences;
554 };
555
556 /// Parses \p Code, finds function '::foo' and annotates its body with results
557 /// of findExplicitReferecnces.
558 /// See actual tests for examples of annotation format.
559 AllRefs annotateReferencesInFoo(llvm::StringRef Code) {
560 TestTU TU;
561 TU.Code = Code;
562
563 // FIXME: Auto-completion in a template requires disabling delayed template
564 // parsing.
565 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
566 TU.ExtraArgs.push_back("-std=c++17");
567
568 auto AST = TU.build();
569 for (auto &D : AST.getDiagnostics()) {
570 if (D.Severity > DiagnosticsEngine::Warning)
571 ADD_FAILURE() << D << Code;
572 }
573
574 auto *TestDecl = &findDecl(AST, "foo");
575 if (auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl))
576 TestDecl = T->getTemplatedDecl();
577 auto &Func = llvm::cast<FunctionDecl>(*TestDecl);
578
579 std::vector<ReferenceLoc> Refs;
580 findExplicitReferences(Func.getBody(), [&Refs](ReferenceLoc R) {
581 Refs.push_back(std::move(R));
582 });
583
584 auto &SM = AST.getSourceManager();
585 llvm::sort(Refs, [&](const ReferenceLoc &L, const ReferenceLoc &R) {
586 return SM.isBeforeInTranslationUnit(L.NameLoc, R.NameLoc);
587 });
588
589 std::string AnnotatedCode;
590 unsigned NextCodeChar = 0;
591 for (unsigned I = 0; I < Refs.size(); ++I) {
592 auto &R = Refs[I];
593
594 SourceLocation Pos = R.NameLoc;
595 assert(Pos.isValid());
596 if (Pos.isMacroID()) // FIXME: figure out how to show macro locations.
597 Pos = SM.getExpansionLoc(Pos);
598 assert(Pos.isFileID());
599
600 FileID File;
601 unsigned Offset;
602 std::tie(File, Offset) = SM.getDecomposedLoc(Pos);
603 if (File == SM.getMainFileID()) {
604 // Print the reference in a source code.
605 assert(NextCodeChar <= Offset);
606 AnnotatedCode += Code.substr(NextCodeChar, Offset - NextCodeChar);
607 AnnotatedCode += "$" + std::to_string(I) + "^";
608
609 NextCodeChar = Offset;
610 }
611 }
612 AnnotatedCode += Code.substr(NextCodeChar);
613
614 std::string DumpedReferences;
615 for (unsigned I = 0; I < Refs.size(); ++I)
616 DumpedReferences += llvm::formatv("{0}: {1}\n", I, Refs[I]);
617
618 return AllRefs{std::move(AnnotatedCode), std::move(DumpedReferences)};
619 }
620 };
621
622 TEST_F(FindExplicitReferencesTest, All) {
623 std::pair</*Code*/ llvm::StringRef, /*References*/ llvm::StringRef> Cases[] =
624 {// Simple expressions.
625 {R"cpp(
626 int global;
627 int func();
628 void foo(int param) {
629 $0^global = $1^param + $2^func();
630 }
631 )cpp",
632 "0: targets = {global}\n"
633 "1: targets = {param}\n"
634 "2: targets = {func}\n"},
635 {R"cpp(
636 struct X { int a; };
637 void foo(X x) {
638 $0^x.$1^a = 10;
639 }
640 )cpp",
641 "0: targets = {x}\n"
642 "1: targets = {X::a}\n"},
643 // Namespaces and aliases.
644 {R"cpp(
645 namespace ns {}
646 namespace alias = ns;
647 void foo() {
648 using namespace $0^ns;
649 using namespace $1^alias;
650 }
651 )cpp",
652 "0: targets = {ns}\n"
653 "1: targets = {alias}\n"},
654 // Using declarations.
655 {R"cpp(
656 namespace ns { int global; }
657 void foo() {
658 using $0^ns::$1^global;
659 }
660 )cpp",
661 "0: targets = {ns}\n"
662 "1: targets = {ns::global}, qualifier = 'ns::'\n"},
663 // Simple types.
664 {R"cpp(
665 struct Struct { int a; };
666 using Typedef = int;
667 void foo() {
668 $0^Struct $1^x;
669 $2^Typedef $3^y;
670 static_cast<$4^Struct*>(0);
671 }
672 )cpp",
673 "0: targets = {Struct}\n"
674 "1: targets = {x}, decl\n"
675 "2: targets = {Typedef}\n"
676 "3: targets = {y}, decl\n"
677 "4: targets = {Struct}\n"},
678 // Name qualifiers.
679 {R"cpp(
680 namespace a { namespace b { struct S { typedef int type; }; } }
681 void foo() {
682 $0^a::$1^b::$2^S $3^x;
683 using namespace $4^a::$5^b;
684 $6^S::$7^type $8^y;
685 }
686 )cpp",
687 "0: targets = {a}\n"
688 "1: targets = {a::b}, qualifier = 'a::'\n"
689 "2: targets = {a::b::S}, qualifier = 'a::b::'\n"
690 "3: targets = {x}, decl\n"
691 "4: targets = {a}\n"
692 "5: targets = {a::b}, qualifier = 'a::'\n"
693 "6: targets = {a::b::S}\n"
694 "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
695 "8: targets = {y}, decl\n"},
696 // Simple templates.
697 {R"cpp(
698 template <class T> struct vector { using value_type = T; };
699 template <> struct vector<bool> { using value_type = bool; };
700 void foo() {
701 $0^vector<int> $1^vi;
702 $2^vector<bool> $3^vb;
703 }
704 )cpp",
705 "0: targets = {vector<int>}\n"
706 "1: targets = {vi}, decl\n"
707 "2: targets = {vector<bool>}\n"
708 "3: targets = {vb}, decl\n"},
709 // Template type aliases.
710 {R"cpp(
711 template <class T> struct vector { using value_type = T; };
712 template <> struct vector<bool> { using value_type = bool; };
713 template <class T> using valias = vector<T>;
714 void foo() {
715 $0^valias<int> $1^vi;
716 $2^valias<bool> $3^vb;
717 }
718 )cpp",
719 "0: targets = {valias}\n"
720 "1: targets = {vi}, decl\n"
721 "2: targets = {valias}\n"
722 "3: targets = {vb}, decl\n"},
723 // MemberExpr should know their using declaration.
724 {R"cpp(
725 struct X { void func(int); };
726 struct Y : X {
727 using X::func;
728 };
729 void foo(Y y) {
730 $0^y.$1^func(1);
731 }
732 )cpp",
733 "0: targets = {y}\n"
734 "1: targets = {Y::func}\n"},
735 // DeclRefExpr should know their using declaration.
736 {R"cpp(
737 namespace ns { void bar(int); }
738 using ns::bar;
739
740 void foo() {
741 $0^bar(10);
742 }
743 )cpp",
744 "0: targets = {bar}\n"},
745 // References from a macro.
746 {R"cpp(
747 #define FOO a
748 #define BAR b
749
750 void foo(int a, int b) {
751 $0^FOO+$1^BAR;
752 }
753 )cpp",
754 "0: targets = {a}\n"
755 "1: targets = {b}\n"},
756 // No references from implicit nodes.
757 {R"cpp(
758 struct vector {
759 int *begin();
760 int *end();
761 };
762
763 void foo() {
764 for (int $0^x : $1^vector()) {
765 $2^x = 10;
766 }
767 }
768 )cpp",
769 "0: targets = {x}, decl\n"
770 "1: targets = {vector}\n"
771 "2: targets = {x}\n"},
772 // Handle UnresolvedLookupExpr.
773 {R"cpp(
774 namespace ns1 { void func(char*); }
775 namespace ns2 { void func(int*); }
776 using namespace ns1;
777 using namespace ns2;
778
779 template <class T>
780 void foo(T t) {
781 $0^func($1^t);
782 }
783 )cpp",
784 "0: targets = {ns1::func, ns2::func}\n"
785 "1: targets = {t}\n"},
786 // Handle UnresolvedMemberExpr.
787 {R"cpp(
788 struct X {
789 void func(char*);
790 void func(int*);
791 };
792
793 template <class T>
794 void foo(X x, T t) {
795 $0^x.$1^func($2^t);
796 }
797 )cpp",
798 "0: targets = {x}\n"
799 "1: targets = {X::func, X::func}\n"
800 "2: targets = {t}\n"},
801 // Type template parameters.
802 {R"cpp(
803 template <class T>
804 void foo() {
805 static_cast<$0^T>(0);
806 $1^T();
807 $2^T $3^t;
808 }
809 )cpp",
810 "0: targets = {T}\n"
811 "1: targets = {T}\n"
812 "2: targets = {T}\n"
813 "3: targets = {t}, decl\n"},
814 // Non-type template parameters.
815 {R"cpp(
816 template <int I>
817 void foo() {
818 int $0^x = $1^I;
819 }
820 )cpp",
821 "0: targets = {x}, decl\n"
822 "1: targets = {I}\n"},
823 // Template template parameters.
824 {R"cpp(
825 template <class T> struct vector {};
826
827 template <template<class> class TT, template<class> class ...TP>
828 void foo() {
829 $0^TT<int> $1^x;
830 $2^foo<$3^TT>();
831 $4^foo<$5^vector>();
832 $6^foo<$7^TP...>();
833 }
834 )cpp",
835 "0: targets = {TT}\n"
836 "1: targets = {x}, decl\n"
837 "2: targets = {foo}\n"
838 "3: targets = {TT}\n"
839 "4: targets = {foo}\n"
840 "5: targets = {vector}\n"
841 "6: targets = {foo}\n"
842 "7: targets = {TP}\n"},
843 // Non-type template parameters with declarations.
844 {R"cpp(
845 int func();
846 template <int(*)()> struct wrapper {};
847
848 template <int(*FuncParam)()>
849 void foo() {
850 $0^wrapper<$1^func> $2^w;
851 $3^FuncParam();
852 }
853 )cpp",
854 "0: targets = {wrapper<&func>}\n"
855 "1: targets = {func}\n"
856 "2: targets = {w}, decl\n"
857 "3: targets = {FuncParam}\n"},
858 // declaration references.
859 {R"cpp(
860 namespace ns {}
861 class S {};
862 void foo() {
863 class $0^Foo { $1^Foo(); ~$2^Foo(); int $3^field; };
864 int $4^Var;
865 enum $5^E { $6^ABC };
866 typedef int $7^INT;
867 using $8^INT2 = int;
868 namespace $9^NS = $10^ns;
869 }
870 )cpp",
871 "0: targets = {Foo}, decl\n"
872 "1: targets = {foo()::Foo::Foo}, decl\n"
873 "2: targets = {Foo}\n"
874 "3: targets = {foo()::Foo::field}, decl\n"
875 "4: targets = {Var}, decl\n"
876 "5: targets = {E}, decl\n"
877 "6: targets = {foo()::ABC}, decl\n"
878 "7: targets = {INT}, decl\n"
879 "8: targets = {INT2}, decl\n"
880 "9: targets = {NS}, decl\n"
881 "10: targets = {ns}\n"},
882 // cxx constructor initializer.
883 {R"cpp(
884 class Base {};
885 void foo() {
886 // member initializer
887 class $0^X {
888 int $1^abc;
889 $2^X(): $3^abc() {}
890 };
891 // base initializer
892 class $4^Derived : public $5^Base {
893 $6^Base $7^B;
894 $8^Derived() : $9^Base() {}
895 };
896 // delegating initializer
897 class $10^Foo {
898 $11^Foo(int);
899 $12^Foo(): $13^Foo(111) {}
900 };
901 }
902 )cpp",
903 "0: targets = {X}, decl\n"
904 "1: targets = {foo()::X::abc}, decl\n"
905 "2: targets = {foo()::X::X}, decl\n"
906 "3: targets = {foo()::X::abc}\n"
907 "4: targets = {Derived}, decl\n"
908 "5: targets = {Base}\n"
909 "6: targets = {Base}\n"
910 "7: targets = {foo()::Derived::B}, decl\n"
911 "8: targets = {foo()::Derived::Derived}, decl\n"
912 "9: targets = {Base}\n"
913 "10: targets = {Foo}, decl\n"
914 "11: targets = {foo()::Foo::Foo}, decl\n"
915 "12: targets = {foo()::Foo::Foo}, decl\n"
916 "13: targets = {Foo}\n"},
917 // Anonymous entities should not be reported.
918 {
919 R"cpp(
920 void foo() {
921 class {} $0^x;
922 int (*$1^fptr)(int $2^a, int) = nullptr;
923 }
924 )cpp",
925 "0: targets = {x}, decl\n"
926 "1: targets = {fptr}, decl\n"
927 "2: targets = {a}, decl\n"},
928 // Namespace aliases should be handled properly.
929 {
930 R"cpp(
931 namespace ns { struct Type {}; }
932 namespace alias = ns;
933 namespace rec_alias = alias;
934
935 void foo() {
936 $0^ns::$1^Type $2^a;
937 $3^alias::$4^Type $5^b;
938 $6^rec_alias::$7^Type $8^c;
939 }
940 )cpp",
941 "0: targets = {ns}\n"
942 "1: targets = {ns::Type}, qualifier = 'ns::'\n"
943 "2: targets = {a}, decl\n"
944 "3: targets = {alias}\n"
945 "4: targets = {ns::Type}, qualifier = 'alias::'\n"
946 "5: targets = {b}, decl\n"
947 "6: targets = {rec_alias}\n"
948 "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"
949 "8: targets = {c}, decl\n"},
950 // Handle SizeOfPackExpr.
951 {
952 R"cpp(
953 template <typename... E>
954 void foo() {
955 constexpr int $0^size = sizeof...($1^E);
956 };
957 )cpp",
958 "0: targets = {size}, decl\n"
959 "1: targets = {E}\n"},
960 // Class template argument deduction
961 {
962 R"cpp(
963 template <typename T>
964 struct Test {
965 Test(T);
966 };
967 void foo() {
968 $0^Test $1^a(5);
969 }
970 )cpp",
971 "0: targets = {Test}\n"
972 "1: targets = {a}, decl\n"}};
973
974 for (const auto &C : Cases) {
975 llvm::StringRef ExpectedCode = C.first;
976 llvm::StringRef ExpectedRefs = C.second;
977
978 auto Actual =
979 annotateReferencesInFoo(llvm::Annotations(ExpectedCode).code());
980 EXPECT_EQ(ExpectedCode, Actual.AnnotatedCode);
981 EXPECT_EQ(ExpectedRefs, Actual.DumpedReferences) << ExpectedCode;
982 }
983 }
984
985 } // namespace
986 } // namespace clangd
987 } // namespace clang
Code
std::string Code
Definition: FindTargetTests.cpp:67
clang::clangd::MessageType::Warning
A warning message.
clang::clangd::operator==
bool operator==(const HoverInfo::Param &LHS, const HoverInfo::Param &RHS)
Definition: Hover.h:78
clang::clangd::allTargetDecls
llvm::SmallVector< std::pair< const NamedDecl *, DeclRelationSet >, 1 > allTargetDecls(const ast_type_traits::DynTypedNode &N)
Similar to targetDecl(), however instead of applying a filter, all possible decls are returned along ...
Definition: FindTarget.cpp:486
Name
std::string Name
Definition: FindTargetTests.cpp:48
DumpedReferences
std::string DumpedReferences
Definition: FindTargetTests.cpp:553
clang::clangd::DeclRelation::TemplatePattern
This is the pattern the template specialization was instantiated from.
Flags
std::vector< const char * > Flags
Definition: FindTargetTests.cpp:68
clang::clangd::RefKind::All
TestTU.h
EXPECT_DECLS
#define EXPECT_DECLS(NodeType,...)
Definition: FindTargetTests.cpp:98
clang::clangd::DeclRelation::Alias
This declaration is an alias that was referred to.
clang::clangd::TestTU::ExtraArgs
std::vector< const char * > ExtraArgs
Definition: TestTU.h:57
clang::clangd::TEST_F
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
Definition: BackgroundIndexTests.cpp:88
clang::clangd::SymbolOrigin::AST
clang::clangd::DeclRelation::TemplateInstantiation
This is the template instantiation that was referred to.
Pos
Position Pos
Definition: SourceCode.cpp:772
clang::clangd::DeclRelation
DeclRelation
Definition: FindTarget.h:93
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:33
Offset
size_t Offset
Definition: CodeComplete.cpp:1022
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::findExplicitReferences
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out)
Recursively traverse S and report all references explicitly written in the code.
Definition: FindTarget.cpp:867
FindTarget.h
clang::clangd::DeclRelation::Underlying
This is the underlying declaration for an alias, decltype etc.
Relations
DeclRelationSet Relations
Definition: FindTargetTests.cpp:49
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
Refs
RefSlab Refs
Definition: SymbolCollectorTests.cpp:296
clang::clangd::operator<<
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Definition: CodeComplete.cpp:1850
AnnotatedCode
std::string AnnotatedCode
Definition: FindTargetTests.cpp:552
clang::clangd::CompletionItemKind::File
Selection.h
Entry
Definition: Modularize.cpp:429
clang::clangd::findDecl
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:118