1//===-- FindAllSymbolsTests.cpp - find all symbols unit tests ---*- 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
9#include "FindAllSymbolsAction.h"
10#include "HeaderMapCollector.h"
11#include "SymbolInfo.h"
12#include "SymbolReporter.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14#include "clang/Basic/FileManager.h"
15#include "clang/Basic/FileSystemOptions.h"
16#include "clang/Frontend/CompilerInstance.h"
17#include "clang/Frontend/PCHContainerOperations.h"
18#include "clang/Tooling/Tooling.h"
19#include "llvm/ADT/IntrusiveRefCntPtr.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/Support/MemoryBuffer.h"
23#include "llvm/Support/VirtualFileSystem.h"
24#include "gtest/gtest.h"
25#include <memory>
26#include <string>
27#include <vector>
28
29namespace clang {
30namespace find_all_symbols {
31
32static const char HeaderName[] = "symbols.h";
33
34class TestSymbolReporter : public SymbolReporter {
35public:
36 ~TestSymbolReporter() override {}
37
38 void reportSymbols(llvm::StringRef FileName,
39 const SymbolInfo::SignalMap &NewSymbols) override {
40 for (const auto &Entry : NewSymbols)
41 Symbols[Entry.first] += Entry.second;
42 }
43
44 int seen(const SymbolInfo &Symbol) const {
45 auto it = Symbols.find(x: Symbol);
46 return it == Symbols.end() ? 0 : it->second.Seen;
47 }
48
49 int used(const SymbolInfo &Symbol) const {
50 auto it = Symbols.find(x: Symbol);
51 return it == Symbols.end() ? 0 : it->second.Used;
52 }
53
54private:
55 SymbolInfo::SignalMap Symbols;
56};
57
58class FindAllSymbolsTest : public ::testing::Test {
59public:
60 int seen(const SymbolInfo &Symbol) { return Reporter.seen(Symbol); }
61
62 int used(const SymbolInfo &Symbol) { return Reporter.used(Symbol); }
63
64 bool runFindAllSymbols(StringRef HeaderCode, StringRef MainCode) {
65 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
66 new llvm::vfs::InMemoryFileSystem);
67 llvm::IntrusiveRefCntPtr<FileManager> Files(
68 new FileManager(FileSystemOptions(), InMemoryFileSystem));
69
70 std::string FileName = "symbol.cc";
71
72 const std::string InternalHeader = "internal/internal_header.h";
73 const std::string TopHeader = "<top>";
74 // Test .inc header path. The header for `IncHeaderClass` should be
75 // internal.h, which will eventually be mapped to <top>.
76 std::string IncHeader = "internal/private.inc";
77 std::string IncHeaderCode = "class IncHeaderClass {};";
78
79 HeaderMapCollector::RegexHeaderMap RegexMap = {
80 {R"(internal_.*\.h$)", TopHeader.c_str()},
81 };
82
83 std::string InternalCode =
84 "#include \"private.inc\"\nclass Internal {};";
85 SymbolInfo InternalSymbol("Internal", SymbolInfo::SymbolKind::Class,
86 TopHeader, {});
87 SymbolInfo IncSymbol("IncHeaderClass", SymbolInfo::SymbolKind::Class,
88 TopHeader, {});
89 InMemoryFileSystem->addFile(
90 Path: IncHeader, ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: IncHeaderCode));
91 InMemoryFileSystem->addFile(Path: InternalHeader, ModificationTime: 0,
92 Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: InternalCode));
93
94 std::unique_ptr<tooling::FrontendActionFactory> Factory(
95 new FindAllSymbolsActionFactory(&Reporter, &RegexMap));
96
97 tooling::ToolInvocation Invocation(
98 {std::string("find_all_symbols"), std::string("-fsyntax-only"),
99 std::string("-std=c++11"), FileName},
100 Factory->create(), Files.get(),
101 std::make_shared<PCHContainerOperations>());
102
103 InMemoryFileSystem->addFile(Path: HeaderName, ModificationTime: 0,
104 Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: HeaderCode));
105
106 std::string Content = "#include\"" + std::string(HeaderName) +
107 "\"\n"
108 "#include \"" +
109 InternalHeader + "\"";
110#if !defined(_MSC_VER) && !defined(__MINGW32__)
111 // Test path cleaning for both decls and macros.
112 const std::string DirtyHeader = "./internal/./a/b.h";
113 Content += "\n#include \"" + DirtyHeader + "\"";
114 const std::string CleanHeader = "internal/a/b.h";
115 const std::string DirtyHeaderContent =
116 "#define INTERNAL 1\nclass ExtraInternal {};";
117 InMemoryFileSystem->addFile(
118 Path: DirtyHeader, ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: DirtyHeaderContent));
119 SymbolInfo DirtyMacro("INTERNAL", SymbolInfo::SymbolKind::Macro,
120 CleanHeader, {});
121 SymbolInfo DirtySymbol("ExtraInternal", SymbolInfo::SymbolKind::Class,
122 CleanHeader, {});
123#endif // _MSC_VER && __MINGW32__
124 Content += "\n" + MainCode.str();
125 InMemoryFileSystem->addFile(Path: FileName, ModificationTime: 0,
126 Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: Content));
127 Invocation.run();
128 EXPECT_EQ(1, seen(InternalSymbol));
129 EXPECT_EQ(1, seen(IncSymbol));
130#if !defined(_MSC_VER) && !defined(__MINGW32__)
131 EXPECT_EQ(1, seen(DirtySymbol));
132 EXPECT_EQ(1, seen(DirtyMacro));
133#endif // _MSC_VER && __MINGW32__
134 return true;
135 }
136
137protected:
138 TestSymbolReporter Reporter;
139};
140
141TEST_F(FindAllSymbolsTest, VariableSymbols) {
142 static const char Header[] = R"(
143 extern int xargc;
144 namespace na {
145 static bool SSSS = false;
146 namespace nb { const long long *XXXX; }
147 })";
148 static const char Main[] = R"(
149 auto y = &na::nb::XXXX;
150 int main() { if (na::SSSS) return xargc; }
151 )";
152 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
153
154 SymbolInfo Symbol =
155 SymbolInfo("xargc", SymbolInfo::SymbolKind::Variable, HeaderName, {});
156 EXPECT_EQ(1, seen(Symbol));
157 EXPECT_EQ(1, used(Symbol));
158
159 Symbol = SymbolInfo("SSSS", SymbolInfo::SymbolKind::Variable, HeaderName,
160 {{SymbolInfo::ContextType::Namespace, "na"}});
161 EXPECT_EQ(1, seen(Symbol));
162 EXPECT_EQ(1, used(Symbol));
163
164 Symbol = SymbolInfo("XXXX", SymbolInfo::SymbolKind::Variable, HeaderName,
165 {{SymbolInfo::ContextType::Namespace, "nb"},
166 {SymbolInfo::ContextType::Namespace, "na"}});
167 EXPECT_EQ(1, seen(Symbol));
168 EXPECT_EQ(1, used(Symbol));
169}
170
171TEST_F(FindAllSymbolsTest, ExternCSymbols) {
172 static const char Header[] = R"(
173 extern "C" {
174 int C_Func() { return 0; }
175 struct C_struct {
176 int Member;
177 };
178 })";
179 static const char Main[] = R"(
180 C_struct q() {
181 int(*ptr)() = C_Func;
182 return {0};
183 }
184 )";
185 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
186
187 SymbolInfo Symbol =
188 SymbolInfo("C_Func", SymbolInfo::SymbolKind::Function, HeaderName, {});
189 EXPECT_EQ(1, seen(Symbol));
190 EXPECT_EQ(1, used(Symbol));
191
192 Symbol =
193 SymbolInfo("C_struct", SymbolInfo::SymbolKind::Class, HeaderName, {});
194 EXPECT_EQ(1, seen(Symbol));
195 EXPECT_EQ(1, used(Symbol));
196}
197
198TEST_F(FindAllSymbolsTest, CXXRecordSymbols) {
199 static const char Header[] = R"(
200 struct Glob {};
201 struct A; // Not a definition, ignored.
202 class NOP; // Not a definition, ignored
203 namespace na {
204 struct A {
205 struct AAAA {};
206 int x;
207 int y;
208 void f() {}
209 };
210 }; //
211 )";
212 static const char Main[] = R"(
213 static Glob glob;
214 static na::A::AAAA* a;
215 )";
216 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
217
218 SymbolInfo Symbol =
219 SymbolInfo("Glob", SymbolInfo::SymbolKind::Class, HeaderName, {});
220 EXPECT_EQ(1, seen(Symbol));
221 EXPECT_EQ(1, used(Symbol));
222
223 Symbol = SymbolInfo("A", SymbolInfo::SymbolKind::Class, HeaderName,
224 {{SymbolInfo::ContextType::Namespace, "na"}});
225 EXPECT_EQ(1, seen(Symbol));
226 EXPECT_EQ(1, used(Symbol));
227
228 Symbol = SymbolInfo("AAA", SymbolInfo::SymbolKind::Class, HeaderName,
229 {{SymbolInfo::ContextType::Record, "A"},
230 {SymbolInfo::ContextType::Namespace, "na"}});
231 EXPECT_EQ(0, seen(Symbol));
232 EXPECT_EQ(0, used(Symbol));
233}
234
235TEST_F(FindAllSymbolsTest, CXXRecordSymbolsTemplate) {
236 static const char Header[] = R"(
237 template <typename T>
238 struct T_TEMP {
239 template <typename _Tp1>
240 struct rebind { typedef T_TEMP<_Tp1> other; };
241 };
242 // Ignore specialization.
243 template class T_TEMP<char>;
244
245 template <typename T>
246 class Observer {
247 };
248 // Ignore specialization.
249 template <> class Observer<int> {};
250 )";
251 static const char Main[] = R"(
252 extern T_TEMP<int>::rebind<char> weirdo;
253 )";
254 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
255
256 SymbolInfo Symbol =
257 SymbolInfo("T_TEMP", SymbolInfo::SymbolKind::Class, HeaderName, {});
258 EXPECT_EQ(1, seen(Symbol));
259 EXPECT_EQ(1, used(Symbol));
260}
261
262TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
263 static const char Code[] = R"(
264 template<class> class Class; // undefined
265 template<class R, class... ArgTypes>
266 class Class<R(ArgTypes...)> {
267 };
268
269 template<class T> void f() {};
270 template<> void f<int>() {};
271 )";
272 runFindAllSymbols(HeaderCode: Code, MainCode: "");
273 SymbolInfo Symbol =
274 SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, {});
275 EXPECT_EQ(1, seen(Symbol));
276 Symbol = SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, {});
277 EXPECT_EQ(1, seen(Symbol));
278}
279
280TEST_F(FindAllSymbolsTest, FunctionSymbols) {
281 static const char Header[] = R"(
282 namespace na {
283 int gg(int);
284 int f(const int &a) { int Local; static int StaticLocal; return 0; }
285 static void SSSFFF() {}
286 } // namespace na
287 namespace na {
288 namespace nb {
289 template<typename T>
290 void fun(T t) {};
291 } // namespace nb
292 } // namespace na";
293 )";
294 static const char Main[] = R"(
295 int(*gg)(int) = &na::gg;
296 int main() {
297 (void)na::SSSFFF;
298 na::nb::fun(0);
299 return na::f(gg(0));
300 }
301 )";
302 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
303
304 SymbolInfo Symbol =
305 SymbolInfo("gg", SymbolInfo::SymbolKind::Function, HeaderName,
306 {{SymbolInfo::ContextType::Namespace, "na"}});
307 EXPECT_EQ(1, seen(Symbol));
308 EXPECT_EQ(1, used(Symbol));
309
310 Symbol = SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName,
311 {{SymbolInfo::ContextType::Namespace, "na"}});
312 EXPECT_EQ(1, seen(Symbol));
313 EXPECT_EQ(1, used(Symbol));
314
315 Symbol = SymbolInfo("SSSFFF", SymbolInfo::SymbolKind::Function, HeaderName,
316 {{SymbolInfo::ContextType::Namespace, "na"}});
317 EXPECT_EQ(1, seen(Symbol));
318 EXPECT_EQ(1, used(Symbol));
319
320 Symbol = SymbolInfo("fun", SymbolInfo::SymbolKind::Function, HeaderName,
321 {{SymbolInfo::ContextType::Namespace, "nb"},
322 {SymbolInfo::ContextType::Namespace, "na"}});
323 EXPECT_EQ(1, seen(Symbol));
324 EXPECT_EQ(1, used(Symbol));
325}
326
327TEST_F(FindAllSymbolsTest, NamespaceTest) {
328 static const char Header[] = R"(
329 int X1;
330 namespace { int X2; }
331 namespace { namespace { int X3; } }
332 namespace { namespace nb { int X4; } }
333 namespace na { inline namespace __1 { int X5; } }
334 )";
335 static const char Main[] = R"(
336 using namespace nb;
337 int main() {
338 X1 = X2;
339 X3 = X4;
340 (void)na::X5;
341 }
342 )";
343 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
344
345 SymbolInfo Symbol =
346 SymbolInfo("X1", SymbolInfo::SymbolKind::Variable, HeaderName, {});
347 EXPECT_EQ(1, seen(Symbol));
348 EXPECT_EQ(1, used(Symbol));
349
350 Symbol = SymbolInfo("X2", SymbolInfo::SymbolKind::Variable, HeaderName,
351 {{SymbolInfo::ContextType::Namespace, ""}});
352 EXPECT_EQ(1, seen(Symbol));
353 EXPECT_EQ(1, used(Symbol));
354
355 Symbol = SymbolInfo("X3", SymbolInfo::SymbolKind::Variable, HeaderName,
356 {{SymbolInfo::ContextType::Namespace, ""},
357 {SymbolInfo::ContextType::Namespace, ""}});
358 EXPECT_EQ(1, seen(Symbol));
359 EXPECT_EQ(1, used(Symbol));
360
361 Symbol = SymbolInfo("X4", SymbolInfo::SymbolKind::Variable, HeaderName,
362 {{SymbolInfo::ContextType::Namespace, "nb"},
363 {SymbolInfo::ContextType::Namespace, ""}});
364 EXPECT_EQ(1, seen(Symbol));
365 EXPECT_EQ(1, used(Symbol));
366
367 Symbol = SymbolInfo("X5", SymbolInfo::SymbolKind::Variable, HeaderName,
368 {{SymbolInfo::ContextType::Namespace, "na"}});
369 EXPECT_EQ(1, seen(Symbol));
370 EXPECT_EQ(1, used(Symbol));
371}
372
373TEST_F(FindAllSymbolsTest, DecayedTypeTest) {
374 static const char Header[] = "void DecayedFunc(int x[], int y[10]) {}";
375 static const char Main[] = R"(int main() { DecayedFunc(nullptr, nullptr); })";
376 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
377 SymbolInfo Symbol = SymbolInfo(
378 "DecayedFunc", SymbolInfo::SymbolKind::Function, HeaderName, {});
379 EXPECT_EQ(1, seen(Symbol));
380 EXPECT_EQ(1, used(Symbol));
381}
382
383TEST_F(FindAllSymbolsTest, CTypedefTest) {
384 static const char Header[] = R"(
385 typedef unsigned size_t_;
386 typedef struct { int x; } X;
387 using XX = X;
388 )";
389 static const char Main[] = R"(
390 size_t_ f;
391 template<typename T> struct vector{};
392 vector<X> list;
393 void foo(const XX&){}
394 )";
395 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
396
397 SymbolInfo Symbol = SymbolInfo("size_t_", SymbolInfo::SymbolKind::TypedefName,
398 HeaderName, {});
399 EXPECT_EQ(1, seen(Symbol));
400 EXPECT_EQ(1, used(Symbol));
401
402 Symbol = SymbolInfo("X", SymbolInfo::SymbolKind::TypedefName, HeaderName, {});
403 EXPECT_EQ(1, seen(Symbol));
404 EXPECT_EQ(1, used(Symbol));
405
406 Symbol =
407 SymbolInfo("XX", SymbolInfo::SymbolKind::TypedefName, HeaderName, {});
408 EXPECT_EQ(1, seen(Symbol));
409 EXPECT_EQ(1, used(Symbol));
410}
411
412TEST_F(FindAllSymbolsTest, EnumTest) {
413 static const char Header[] = R"(
414 enum Glob_E { G1, G2 };
415 enum class Altitude { high='h', low='l'};
416 enum { A1, A2 };
417 class A {
418 public:
419 enum A_ENUM { X1, X2 };
420 };
421 enum DECL : int;
422 )";
423 static const char Main[] = R"(
424 static auto flags = G1 | G2;
425 static auto alt = Altitude::high;
426 static auto nested = A::X1;
427 extern DECL whatever;
428 static auto flags2 = A1 | A2;
429 )";
430 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
431
432 SymbolInfo Symbol =
433 SymbolInfo("Glob_E", SymbolInfo::SymbolKind::EnumDecl, HeaderName, {});
434 EXPECT_EQ(1, seen(Symbol));
435 EXPECT_EQ(0, used(Symbol));
436
437 Symbol =
438 SymbolInfo("G1", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName,
439 {{SymbolInfo::ContextType::EnumDecl, "Glob_E"}});
440 EXPECT_EQ(1, seen(Symbol));
441 EXPECT_EQ(1, used(Symbol));
442
443 Symbol =
444 SymbolInfo("G2", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName,
445 {{SymbolInfo::ContextType::EnumDecl, "Glob_E"}});
446 EXPECT_EQ(1, seen(Symbol));
447 EXPECT_EQ(1, used(Symbol));
448
449 Symbol =
450 SymbolInfo("Altitude", SymbolInfo::SymbolKind::EnumDecl, HeaderName, {});
451 EXPECT_EQ(1, seen(Symbol));
452 EXPECT_EQ(1, used(Symbol));
453 Symbol =
454 SymbolInfo("high", SymbolInfo::SymbolKind::EnumConstantDecl, HeaderName,
455 {{SymbolInfo::ContextType::EnumDecl, "Altitude"}});
456 EXPECT_EQ(0, seen(Symbol));
457 EXPECT_EQ(0, used(Symbol));
458
459 Symbol = SymbolInfo("A1", SymbolInfo::SymbolKind::EnumConstantDecl,
460 HeaderName, {{SymbolInfo::ContextType::EnumDecl, ""}});
461 EXPECT_EQ(1, seen(Symbol));
462 EXPECT_EQ(1, used(Symbol));
463 Symbol = SymbolInfo("A2", SymbolInfo::SymbolKind::EnumConstantDecl,
464 HeaderName, {{SymbolInfo::ContextType::EnumDecl, ""}});
465 EXPECT_EQ(1, seen(Symbol));
466 EXPECT_EQ(1, used(Symbol));
467 Symbol = SymbolInfo("", SymbolInfo::SymbolKind::EnumDecl, HeaderName, {});
468 EXPECT_EQ(0, seen(Symbol));
469 EXPECT_EQ(0, used(Symbol));
470
471 Symbol = SymbolInfo("A_ENUM", SymbolInfo::SymbolKind::EnumDecl, HeaderName,
472 {{SymbolInfo::ContextType::Record, "A"}});
473 EXPECT_EQ(0, seen(Symbol));
474 EXPECT_EQ(0, used(Symbol));
475
476 Symbol = SymbolInfo("X1", SymbolInfo::SymbolKind::EnumDecl, HeaderName,
477 {{SymbolInfo::ContextType::EnumDecl, "A_ENUM"},
478 {SymbolInfo::ContextType::Record, "A"}});
479 EXPECT_EQ(0, seen(Symbol));
480
481 Symbol = SymbolInfo("DECL", SymbolInfo::SymbolKind::EnumDecl, HeaderName, {});
482 EXPECT_EQ(0, seen(Symbol));
483}
484
485TEST_F(FindAllSymbolsTest, IWYUPrivatePragmaTest) {
486 static const char Header[] = R"(
487 // IWYU pragma: private, include "bar.h"
488 struct Bar {
489 };
490 )";
491 static const char Main[] = R"(
492 Bar bar;
493 )";
494 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
495
496 SymbolInfo Symbol =
497 SymbolInfo("Bar", SymbolInfo::SymbolKind::Class, "bar.h", {});
498 EXPECT_EQ(1, seen(Symbol));
499 EXPECT_EQ(1, used(Symbol));
500}
501
502TEST_F(FindAllSymbolsTest, MacroTest) {
503 static const char Header[] = R"(
504 #define X
505 #define Y 1
506 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
507 )";
508 static const char Main[] = R"(
509 #ifdef X
510 int main() { return MAX(0,Y); }
511 #endif
512 )";
513 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
514 SymbolInfo Symbol =
515 SymbolInfo("X", SymbolInfo::SymbolKind::Macro, HeaderName, {});
516 EXPECT_EQ(1, seen(Symbol));
517 EXPECT_EQ(1, used(Symbol));
518
519 Symbol = SymbolInfo("Y", SymbolInfo::SymbolKind::Macro, HeaderName, {});
520 EXPECT_EQ(1, seen(Symbol));
521 EXPECT_EQ(1, used(Symbol));
522
523 Symbol = SymbolInfo("MAX", SymbolInfo::SymbolKind::Macro, HeaderName, {});
524 EXPECT_EQ(1, seen(Symbol));
525 EXPECT_EQ(1, used(Symbol));
526}
527
528TEST_F(FindAllSymbolsTest, MacroTestWithIWYU) {
529 static const char Header[] = R"(
530 // IWYU pragma: private, include "bar.h"
531 #define X 1
532 #define Y 1
533 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
534 )";
535 static const char Main[] = R"(
536 #ifdef X
537 int main() { return MAX(0,Y); }
538 #endif
539 )";
540 runFindAllSymbols(HeaderCode: Header, MainCode: Main);
541 SymbolInfo Symbol =
542 SymbolInfo("X", SymbolInfo::SymbolKind::Macro, "bar.h", {});
543 EXPECT_EQ(1, seen(Symbol));
544 EXPECT_EQ(1, used(Symbol));
545
546 Symbol = SymbolInfo("Y", SymbolInfo::SymbolKind::Macro, "bar.h", {});
547 EXPECT_EQ(1, seen(Symbol));
548 EXPECT_EQ(1, used(Symbol));
549
550 Symbol = SymbolInfo("MAX", SymbolInfo::SymbolKind::Macro, "bar.h", {});
551 EXPECT_EQ(1, seen(Symbol));
552 EXPECT_EQ(1, used(Symbol));
553}
554
555TEST_F(FindAllSymbolsTest, NoFriendTest) {
556 static const char Header[] = R"(
557 class WorstFriend {
558 friend void Friend();
559 friend class BestFriend;
560 };
561 )";
562 runFindAllSymbols(HeaderCode: Header, MainCode: "");
563 SymbolInfo Symbol =
564 SymbolInfo("WorstFriend", SymbolInfo::SymbolKind::Class, HeaderName, {});
565 EXPECT_EQ(1, seen(Symbol));
566
567 Symbol =
568 SymbolInfo("Friend", SymbolInfo::SymbolKind::Function, HeaderName, {});
569 EXPECT_EQ(0, seen(Symbol));
570
571 Symbol =
572 SymbolInfo("BestFriend", SymbolInfo::SymbolKind::Class, HeaderName, {});
573 EXPECT_EQ(0, seen(Symbol));
574}
575
576} // namespace find_all_symbols
577} // namespace clang
578

source code of clang-tools-extra/unittests/clang-include-fixer/find-all-symbols/FindAllSymbolsTests.cpp