clang-tools  10.0.0svn
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 Decl *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 
119 TEST_F(TargetDeclTest, UsingDecl) {
120  Code = R"cpp(
121  namespace foo {
122  int f(int);
123  int f(char);
124  }
125  using foo::f;
126  int x = [[f]](42);
127  )cpp";
128  // f(char) is not referenced!
129  EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias},
130  {"int f(int)", Rel::Underlying});
131 
132  Code = R"cpp(
133  namespace foo {
134  int f(int);
135  int f(char);
136  }
137  [[using foo::f]];
138  )cpp";
139  // All overloads are referenced.
140  EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias},
141  {"int f(int)", Rel::Underlying},
142  {"int f(char)", Rel::Underlying});
143 
144  Code = R"cpp(
145  struct X {
146  int foo();
147  };
148  struct Y : X {
149  using X::foo;
150  };
151  int x = Y().[[foo]]();
152  )cpp";
153  EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias},
154  {"int foo()", Rel::Underlying});
155 }
156 
157 TEST_F(TargetDeclTest, ConstructorInitList) {
158  Code = R"cpp(
159  struct X {
160  int a;
161  X() : [[a]](42) {}
162  };
163  )cpp";
164  EXPECT_DECLS("CXXCtorInitializer", "int a");
165 
166  Code = R"cpp(
167  struct X {
168  X() : [[X]](1) {}
169  X(int);
170  };
171  )cpp";
172  EXPECT_DECLS("RecordTypeLoc", "struct X");
173 }
174 
175 TEST_F(TargetDeclTest, DesignatedInit) {
176  Flags = {"-xc"}; // array designators are a C99 extension.
177  Code = R"c(
178  struct X { int a; };
179  struct Y { int b; struct X c[2]; };
180  struct Y y = { .c[0].[[a]] = 1 };
181  )c";
182  EXPECT_DECLS("DesignatedInitExpr", "int a");
183 }
184 
185 TEST_F(TargetDeclTest, NestedNameSpecifier) {
186  Code = R"cpp(
187  namespace a { namespace b { int c; } }
188  int x = a::[[b::]]c;
189  )cpp";
190  EXPECT_DECLS("NestedNameSpecifierLoc", "namespace b");
191 
192  Code = R"cpp(
193  namespace a { struct X { enum { y }; }; }
194  int x = a::[[X::]]y;
195  )cpp";
196  EXPECT_DECLS("NestedNameSpecifierLoc", "struct X");
197 
198  Code = R"cpp(
199  template <typename T>
200  int x = [[T::]]y;
201  )cpp";
202  // FIXME: We don't do a good job printing TemplateTypeParmDecls, apparently!
203  EXPECT_DECLS("NestedNameSpecifierLoc", "");
204 
205  Code = R"cpp(
206  namespace a { int x; }
207  namespace b = a;
208  int y = [[b]]::x;
209  )cpp";
210  EXPECT_DECLS("NestedNameSpecifierLoc", {"namespace b = a", Rel::Alias},
211  {"namespace a", Rel::Underlying});
212 }
213 
214 TEST_F(TargetDeclTest, Types) {
215  Code = R"cpp(
216  struct X{};
217  [[X]] x;
218  )cpp";
219  EXPECT_DECLS("RecordTypeLoc", "struct X");
220 
221  Code = R"cpp(
222  struct S{};
223  typedef S X;
224  [[X]] x;
225  )cpp";
226  EXPECT_DECLS("TypedefTypeLoc", {"typedef S X", Rel::Alias},
227  {"struct S", Rel::Underlying});
228 
229  // FIXME: Auto-completion in a template requires disabling delayed template
230  // parsing.
231  Flags = {"-fno-delayed-template-parsing"};
232  Code = R"cpp(
233  template<class T>
234  void foo() { [[T]] x; }
235  )cpp";
236  // FIXME: We don't do a good job printing TemplateTypeParmDecls, apparently!
237  EXPECT_DECLS("TemplateTypeParmTypeLoc", "");
238  Flags.clear();
239 
240  // FIXME: Auto-completion in a template requires disabling delayed template
241  // parsing.
242  Flags = {"-fno-delayed-template-parsing"};
243  Code = R"cpp(
244  template<template<typename> class T>
245  void foo() { [[T<int>]] x; }
246  )cpp";
247  EXPECT_DECLS("TemplateSpecializationTypeLoc", "template <typename> class T");
248  Flags.clear();
249 
250  Code = R"cpp(
251  struct S{};
252  S X;
253  [[decltype]](X) Y;
254  )cpp";
255  EXPECT_DECLS("DecltypeTypeLoc", {"struct S", Rel::Underlying});
256 
257  Code = R"cpp(
258  struct S{};
259  [[auto]] X = S{};
260  )cpp";
261  // FIXME: deduced type missing in AST. https://llvm.org/PR42914
262  EXPECT_DECLS("AutoTypeLoc");
263 }
264 
265 TEST_F(TargetDeclTest, ClassTemplate) {
266  Code = R"cpp(
267  // Implicit specialization.
268  template<int x> class Foo{};
269  [[Foo<42>]] B;
270  )cpp";
271  EXPECT_DECLS("TemplateSpecializationTypeLoc",
272  {"template<> class Foo<42>", Rel::TemplateInstantiation},
273  {"class Foo", Rel::TemplatePattern});
274 
275  Code = R"cpp(
276  // Explicit specialization.
277  template<int x> class Foo{};
278  template<> class Foo<42>{};
279  [[Foo<42>]] B;
280  )cpp";
281  EXPECT_DECLS("TemplateSpecializationTypeLoc", "template<> class Foo<42>");
282 
283  Code = R"cpp(
284  // Partial specialization.
285  template<typename T> class Foo{};
286  template<typename T> class Foo<T*>{};
287  [[Foo<int*>]] B;
288  )cpp";
289  EXPECT_DECLS("TemplateSpecializationTypeLoc",
290  {"template<> class Foo<int *>", Rel::TemplateInstantiation},
291  {"template <typename T> class Foo<type-parameter-0-0 *>",
293 }
294 
295 TEST_F(TargetDeclTest, FunctionTemplate) {
296  Code = R"cpp(
297  // Implicit specialization.
298  template<typename T> bool foo(T) { return false; };
299  bool x = [[foo]](42);
300  )cpp";
301  EXPECT_DECLS("DeclRefExpr",
302  {"template<> bool foo<int>(int)", Rel::TemplateInstantiation},
303  {"bool foo(T)", Rel::TemplatePattern});
304 
305  Code = R"cpp(
306  // Explicit specialization.
307  template<typename T> bool foo(T) { return false; };
308  template<> bool foo<int>(int) { return false; };
309  bool x = [[foo]](42);
310  )cpp";
311  EXPECT_DECLS("DeclRefExpr", "template<> bool foo<int>(int)");
312 }
313 
314 TEST_F(TargetDeclTest, VariableTemplate) {
315  // Pretty-printer doesn't do a very good job of variable templates :-(
316  Code = R"cpp(
317  // Implicit specialization.
318  template<typename T> int foo;
319  int x = [[foo]]<char>;
320  )cpp";
321  EXPECT_DECLS("DeclRefExpr", {"int foo", Rel::TemplateInstantiation},
322  {"int foo", Rel::TemplatePattern});
323 
324  Code = R"cpp(
325  // Explicit specialization.
326  template<typename T> int foo;
327  template <> bool foo<char>;
328  int x = [[foo]]<char>;
329  )cpp";
330  EXPECT_DECLS("DeclRefExpr", "bool foo");
331 
332  Code = R"cpp(
333  // Partial specialization.
334  template<typename T> int foo;
335  template<typename T> bool foo<T*>;
336  bool x = [[foo]]<char*>;
337  )cpp";
338  EXPECT_DECLS("DeclRefExpr", {"bool foo", Rel::TemplateInstantiation},
339  {"bool foo", Rel::TemplatePattern});
340 }
341 
342 TEST_F(TargetDeclTest, TypeAliasTemplate) {
343  Code = R"cpp(
344  template<typename T, int X> class SmallVector {};
345  template<typename U> using TinyVector = SmallVector<U, 1>;
346  [[TinyVector<int>]] X;
347  )cpp";
348  EXPECT_DECLS("TemplateSpecializationTypeLoc",
349  {"template<> class SmallVector<int, 1>",
351  {"class SmallVector", Rel::TemplatePattern | Rel::Underlying},
352  {"using TinyVector = SmallVector<U, 1>",
354 }
355 
356 TEST_F(TargetDeclTest, MemberOfTemplate) {
357  Code = R"cpp(
358  template <typename T> struct Foo {
359  int x(T);
360  };
361  int y = Foo<int>().[[x]](42);
362  )cpp";
363  EXPECT_DECLS("MemberExpr", {"int x(int)", Rel::TemplateInstantiation},
364  {"int x(T)", Rel::TemplatePattern});
365 
366  Code = R"cpp(
367  template <typename T> struct Foo {
368  template <typename U>
369  int x(T, U);
370  };
371  int y = Foo<char>().[[x]]('c', 42);
372  )cpp";
373  EXPECT_DECLS("MemberExpr",
374  {"template<> int x<int>(char, int)", Rel::TemplateInstantiation},
375  {"int x(T, U)", Rel::TemplatePattern});
376 }
377 
378 TEST_F(TargetDeclTest, Lambda) {
379  Code = R"cpp(
380  void foo(int x = 42) {
381  auto l = [ [[x]] ]{ return x + 1; };
382  };
383  )cpp";
384  EXPECT_DECLS("DeclRefExpr", "int x = 42");
385 
386  // It seems like this should refer to another var, with the outer param being
387  // an underlying decl. But it doesn't seem to exist.
388  Code = R"cpp(
389  void foo(int x = 42) {
390  auto l = [x]{ return [[x]] + 1; };
391  };
392  )cpp";
393  EXPECT_DECLS("DeclRefExpr", "int x = 42");
394 
395  Code = R"cpp(
396  void foo() {
397  auto l = [x = 1]{ return [[x]] + 1; };
398  };
399  )cpp";
400  // FIXME: why both auto and int?
401  EXPECT_DECLS("DeclRefExpr", "auto int x = 1");
402 }
403 
404 TEST_F(TargetDeclTest, OverloadExpr) {
405  // FIXME: Auto-completion in a template requires disabling delayed template
406  // parsing.
407  Flags = {"-fno-delayed-template-parsing"};
408 
409  Code = R"cpp(
410  void func(int*);
411  void func(char*);
412 
413  template <class T>
414  void foo(T t) {
415  [[func]](t);
416  };
417  )cpp";
418  EXPECT_DECLS("UnresolvedLookupExpr", "void func(int *)", "void func(char *)");
419 
420  Code = R"cpp(
421  struct X {
422  void func(int*);
423  void func(char*);
424  };
425 
426  template <class T>
427  void foo(X x, T t) {
428  x.[[func]](t);
429  };
430  )cpp";
431  EXPECT_DECLS("UnresolvedMemberExpr", "void func(int *)", "void func(char *)");
432 }
433 
434 TEST_F(TargetDeclTest, ObjC) {
435  Flags = {"-xobjective-c"};
436  Code = R"cpp(
437  @interface Foo {}
438  -(void)bar;
439  @end
440  void test(Foo *f) {
441  [f [[bar]] ];
442  }
443  )cpp";
444  EXPECT_DECLS("ObjCMessageExpr", "- (void)bar");
445 
446  Code = R"cpp(
447  @interface Foo { @public int bar; }
448  @end
449  int test(Foo *f) {
450  return [[f->bar]];
451  }
452  )cpp";
453  EXPECT_DECLS("ObjCIvarRefExpr", "int bar");
454 
455  Code = R"cpp(
456  @interface Foo {}
457  -(int) x;
458  -(void) setX:(int)x;
459  @end
460  void test(Foo *f) {
461  [[f.x]] = 42;
462  }
463  )cpp";
464  EXPECT_DECLS("ObjCPropertyRefExpr", "- (void)setX:(int)x");
465 
466  Code = R"cpp(
467  @interface Foo {}
468  @property int x;
469  @end
470  void test(Foo *f) {
471  [[f.x]] = 42;
472  }
473  )cpp";
474  EXPECT_DECLS("ObjCPropertyRefExpr",
475  "@property(atomic, assign, unsafe_unretained, readwrite) int x");
476 
477  Code = R"cpp(
478  @protocol Foo
479  @end
480  id test() {
481  return [[@protocol(Foo)]];
482  }
483  )cpp";
484  EXPECT_DECLS("ObjCProtocolExpr", "@protocol Foo");
485 
486  Code = R"cpp(
487  @interface Foo
488  @end
489  void test([[Foo]] *p);
490  )cpp";
491  EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo");
492 
493  Code = R"cpp(
494  @protocol Foo
495  @end
496  void test([[id<Foo>]] p);
497  )cpp";
498  EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo");
499 
500  Code = R"cpp(
501  @class C;
502  @protocol Foo
503  @end
504  void test(C<[[Foo]]> *p);
505  )cpp";
506  // FIXME: there's no AST node corresponding to 'Foo', so we're stuck.
507  EXPECT_DECLS("ObjCObjectTypeLoc");
508 }
509 
510 class FindExplicitReferencesTest : public ::testing::Test {
511 protected:
512  struct AllRefs {
513  std::string AnnotatedCode;
514  std::string DumpedReferences;
515  };
516 
517  /// Parses \p Code, finds function '::foo' and annotates its body with results
518  /// of findExplicitReferecnces.
519  /// See actual tests for examples of annotation format.
520  AllRefs annotateReferencesInFoo(llvm::StringRef Code) {
521  TestTU TU;
522  TU.Code = Code;
523 
524  // FIXME: Auto-completion in a template requires disabling delayed template
525  // parsing.
526  TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
527 
528  auto AST = TU.build();
529 
530  auto *TestDecl = &findDecl(AST, "foo");
531  if (auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl))
532  TestDecl = T->getTemplatedDecl();
533  auto &Func = llvm::cast<FunctionDecl>(*TestDecl);
534 
535  std::vector<ReferenceLoc> Refs;
536  findExplicitReferences(Func.getBody(), [&Refs](ReferenceLoc R) {
537  Refs.push_back(std::move(R));
538  });
539 
540  auto &SM = AST.getSourceManager();
541  llvm::sort(Refs, [&](const ReferenceLoc &L, const ReferenceLoc &R) {
542  return SM.isBeforeInTranslationUnit(L.NameLoc, R.NameLoc);
543  });
544 
545  std::string AnnotatedCode;
546  unsigned NextCodeChar = 0;
547  for (unsigned I = 0; I < Refs.size(); ++I) {
548  auto &R = Refs[I];
549 
550  SourceLocation Pos = R.NameLoc;
551  assert(Pos.isValid());
552  if (Pos.isMacroID()) // FIXME: figure out how to show macro locations.
553  Pos = SM.getExpansionLoc(Pos);
554  assert(Pos.isFileID());
555 
556  FileID File;
557  unsigned Offset;
558  std::tie(File, Offset) = SM.getDecomposedLoc(Pos);
559  if (File == SM.getMainFileID()) {
560  // Print the reference in a source code.
561  assert(NextCodeChar <= Offset);
562  AnnotatedCode += Code.substr(NextCodeChar, Offset - NextCodeChar);
563  AnnotatedCode += "$" + std::to_string(I) + "^";
564 
565  NextCodeChar = Offset;
566  }
567  }
568  AnnotatedCode += Code.substr(NextCodeChar);
569 
570  std::string DumpedReferences;
571  for (unsigned I = 0; I < Refs.size(); ++I)
572  DumpedReferences += llvm::formatv("{0}: {1}\n", I, Refs[I]);
573 
574  return AllRefs{std::move(AnnotatedCode), std::move(DumpedReferences)};
575  }
576 };
577 
578 TEST_F(FindExplicitReferencesTest, All) {
579  std::pair</*Code*/ llvm::StringRef, /*References*/ llvm::StringRef> Cases[] =
580  {
581  // Simple expressions.
582  {R"cpp(
583  int global;
584  int func();
585  void foo(int param) {
586  $0^global = $1^param + $2^func();
587  }
588  )cpp",
589  "0: targets = {global}\n"
590  "1: targets = {param}\n"
591  "2: targets = {func}\n"},
592  {R"cpp(
593  struct X { int a; };
594  void foo(X x) {
595  $0^x.$1^a = 10;
596  }
597  )cpp",
598  "0: targets = {x}\n"
599  "1: targets = {X::a}\n"},
600  // Namespaces and aliases.
601  {R"cpp(
602  namespace ns {}
603  namespace alias = ns;
604  void foo() {
605  using namespace $0^ns;
606  using namespace $1^alias;
607  }
608  )cpp",
609  "0: targets = {ns}\n"
610  "1: targets = {alias}\n"},
611  // Using declarations.
612  {R"cpp(
613  namespace ns { int global; }
614  void foo() {
615  using $0^ns::$1^global;
616  }
617  )cpp",
618  "0: targets = {ns}\n"
619  "1: targets = {ns::global}, qualifier = 'ns::'\n"},
620  // Simple types.
621  {R"cpp(
622  struct Struct { int a; };
623  using Typedef = int;
624  void foo() {
625  $0^Struct $1^x;
626  $2^Typedef $3^y;
627  static_cast<$4^Struct*>(0);
628  }
629  )cpp",
630  "0: targets = {Struct}\n"
631  "1: targets = {x}, decl\n"
632  "2: targets = {Typedef}\n"
633  "3: targets = {y}, decl\n"
634  "4: targets = {Struct}\n"},
635  // Name qualifiers.
636  {R"cpp(
637  namespace a { namespace b { struct S { typedef int type; }; } }
638  void foo() {
639  $0^a::$1^b::$2^S $3^x;
640  using namespace $4^a::$5^b;
641  $6^S::$7^type $8^y;
642  }
643  )cpp",
644  "0: targets = {a}\n"
645  "1: targets = {a::b}, qualifier = 'a::'\n"
646  "2: targets = {a::b::S}, qualifier = 'a::b::'\n"
647  "3: targets = {x}, decl\n"
648  "4: targets = {a}\n"
649  "5: targets = {a::b}, qualifier = 'a::'\n"
650  "6: targets = {a::b::S}\n"
651  "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
652  "8: targets = {y}, decl\n"},
653  // Simple templates.
654  {R"cpp(
655  template <class T> struct vector { using value_type = T; };
656  template <> struct vector<bool> { using value_type = bool; };
657  void foo() {
658  $0^vector<int> $1^vi;
659  $2^vector<bool> $3^vb;
660  }
661  )cpp",
662  "0: targets = {vector<int>}\n"
663  "1: targets = {vi}, decl\n"
664  "2: targets = {vector<bool>}\n"
665  "3: targets = {vb}, decl\n"},
666  // Template type aliases.
667  {R"cpp(
668  template <class T> struct vector { using value_type = T; };
669  template <> struct vector<bool> { using value_type = bool; };
670  template <class T> using valias = vector<T>;
671  void foo() {
672  $0^valias<int> $1^vi;
673  $2^valias<bool> $3^vb;
674  }
675  )cpp",
676  "0: targets = {valias}\n"
677  "1: targets = {vi}, decl\n"
678  "2: targets = {valias}\n"
679  "3: targets = {vb}, decl\n"},
680  // MemberExpr should know their using declaration.
681  {R"cpp(
682  struct X { void func(int); }
683  struct Y : X {
684  using X::func;
685  };
686  void foo(Y y) {
687  $0^y.$1^func(1);
688  }
689  )cpp",
690  "0: targets = {y}\n"
691  "1: targets = {Y::func}\n"},
692  // DeclRefExpr should know their using declaration.
693  {R"cpp(
694  namespace ns { void bar(int); }
695  using ns::bar;
696 
697  void foo() {
698  $0^bar(10);
699  }
700  )cpp",
701  "0: targets = {bar}\n"},
702  // References from a macro.
703  {R"cpp(
704  #define FOO a
705  #define BAR b
706 
707  void foo(int a, int b) {
708  $0^FOO+$1^BAR;
709  }
710  )cpp",
711  "0: targets = {a}\n"
712  "1: targets = {b}\n"},
713  // No references from implicit nodes.
714  {R"cpp(
715  struct vector {
716  int *begin();
717  int *end();
718  };
719 
720  void foo() {
721  for (int $0^x : $1^vector()) {
722  $2^x = 10;
723  }
724  }
725  )cpp",
726  "0: targets = {x}, decl\n"
727  "1: targets = {vector}\n"
728  "2: targets = {x}\n"},
729  // Handle UnresolvedLookupExpr.
730  {R"cpp(
731  namespace ns1 { void func(char*); }
732  namespace ns2 { void func(int*); }
733  using namespace ns1;
734  using namespace ns2;
735 
736  template <class T>
737  void foo(T t) {
738  $0^func($1^t);
739  }
740  )cpp",
741  "0: targets = {ns1::func, ns2::func}\n"
742  "1: targets = {t}\n"},
743  // Handle UnresolvedMemberExpr.
744  {R"cpp(
745  struct X {
746  void func(char*);
747  void func(int*);
748  };
749 
750  template <class T>
751  void foo(X x, T t) {
752  $0^x.$1^func($2^t);
753  }
754  )cpp",
755  "0: targets = {x}\n"
756  "1: targets = {X::func, X::func}\n"
757  "2: targets = {t}\n"},
758  // Type template parameters.
759  {R"cpp(
760  template <class T>
761  void foo() {
762  static_cast<$0^T>(0);
763  $1^T();
764  $2^T $3^t;
765  }
766  )cpp",
767  "0: targets = {T}\n"
768  "1: targets = {T}\n"
769  "2: targets = {T}\n"
770  "3: targets = {t}, decl\n"},
771  // Non-type template parameters.
772  {R"cpp(
773  template <int I>
774  void foo() {
775  int $0^x = $1^I;
776  }
777  )cpp",
778  "0: targets = {x}, decl\n"
779  "1: targets = {I}\n"},
780  // Template template parameters.
781  {R"cpp(
782  template <class T> struct vector {};
783 
784  template <template<class> class TT, template<class> class ...TP>
785  void foo() {
786  $0^TT<int> $1^x;
787  $2^foo<$3^TT>();
788  $4^foo<$5^vector>()
789  $6^foo<$7^TP...>();
790  }
791  )cpp",
792  "0: targets = {TT}\n"
793  "1: targets = {x}, decl\n"
794  "2: targets = {foo}\n"
795  "3: targets = {TT}\n"
796  "4: targets = {foo}\n"
797  "5: targets = {vector}\n"
798  "6: targets = {foo}\n"
799  "7: targets = {TP}\n"},
800  // Non-type template parameters with declarations.
801  {R"cpp(
802  int func();
803  template <int(*)()> struct wrapper {};
804 
805  template <int(*FuncParam)()>
806  void foo() {
807  $0^wrapper<$1^func> $2^w;
808  $3^FuncParam();
809  }
810  )cpp",
811  "0: targets = {wrapper<&func>}\n"
812  "1: targets = {func}\n"
813  "2: targets = {w}, decl\n"
814  "3: targets = {FuncParam}\n"},
815  {R"cpp(
816  namespace ns {}
817  class S {};
818  void foo() {
819  class $0^Foo { $1^Foo(); ~$2^Foo(); int $3^field; };
820  int $4^Var;
821  enum $5^E { $6^ABC };
822  typedef int $7^INT;
823  using $8^INT2 = int;
824  namespace $9^NS = $10^ns;
825  }
826  )cpp",
827  "0: targets = {Foo}, decl\n"
828  "1: targets = {foo()::Foo::Foo}, decl\n"
829  "2: targets = {Foo}\n"
830  "3: targets = {foo()::Foo::field}, decl\n"
831  "4: targets = {Var}, decl\n"
832  "5: targets = {E}, decl\n"
833  "6: targets = {foo()::ABC}, decl\n"
834  "7: targets = {INT}, decl\n"
835  "8: targets = {INT2}, decl\n"
836  "9: targets = {NS}, decl\n"
837  "10: targets = {ns}\n"},
838  };
839 
840  for (const auto &C : Cases) {
841  llvm::StringRef ExpectedCode = C.first;
842  llvm::StringRef ExpectedRefs = C.second;
843 
844  auto Actual =
845  annotateReferencesInFoo(llvm::Annotations(ExpectedCode).code());
846  EXPECT_EQ(ExpectedCode, Actual.AnnotatedCode);
847  EXPECT_EQ(ExpectedRefs, Actual.DumpedReferences) << ExpectedCode;
848  }
849 }
850 
851 } // namespace
852 } // namespace clangd
853 } // namespace clang
std::string Code
std::string Name
std::string DumpedReferences
This is the pattern the template specialization was instantiated from.
std::vector< const char * > Flags
#define EXPECT_DECLS(NodeType,...)
This declaration is an alias that was referred to.
std::vector< const char * > ExtraArgs
Definition: TestTU.h:57
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
bool operator==(const Ref &L, const Ref &R)
Definition: Ref.h:61
This is the template instantiation that was referred to.
const Decl * D
Definition: XRefs.cpp:849
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:33
size_t Offset
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::SmallVector< std::pair< const Decl *, 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:343
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:708
This is the underlying declaration for an alias, decltype etc.
DeclRelationSet Relations
CharSourceRange Range
SourceRange for the file name.
RefSlab Refs
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
std::string AnnotatedCode
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:118