1 //===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "clang/AST/ASTConsumer.h"
11 #include "clang/AST/DeclCXX.h"
12 #include "clang/AST/DeclGroup.h"
13 #include "clang/Frontend/ASTUnit.h"
14 #include "clang/Frontend/CompilerInstance.h"
15 #include "clang/Frontend/FrontendAction.h"
16 #include "clang/Frontend/FrontendActions.h"
17 #include "clang/Tooling/CompilationDatabase.h"
18 #include "clang/Tooling/Tooling.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/Config/llvm-config.h"
21 #include "llvm/Support/Path.h"
22 #include "llvm/Support/TargetRegistry.h"
23 #include "llvm/Support/TargetSelect.h"
24 #include "gtest/gtest.h"
25 #include <algorithm>
26 #include <string>
27 
28 namespace clang {
29 namespace tooling {
30 
31 namespace {
32 /// Takes an ast consumer and returns it from CreateASTConsumer. This only
33 /// works with single translation unit compilations.
34 class TestAction : public clang::ASTFrontendAction {
35 public:
36   /// Takes ownership of TestConsumer.
37   explicit TestAction(std::unique_ptr<clang::ASTConsumer> TestConsumer)
38       : TestConsumer(std::move(TestConsumer)) {}
39 
40 protected:
41   std::unique_ptr<clang::ASTConsumer>
42   CreateASTConsumer(clang::CompilerInstance &compiler,
43                     StringRef dummy) override {
44     /// TestConsumer will be deleted by the framework calling us.
45     return std::move(TestConsumer);
46   }
47 
48 private:
49   std::unique_ptr<clang::ASTConsumer> TestConsumer;
50 };
51 
52 class FindTopLevelDeclConsumer : public clang::ASTConsumer {
53  public:
54   explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
55       : FoundTopLevelDecl(FoundTopLevelDecl) {}
56   bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) override {
57     *FoundTopLevelDecl = true;
58     return true;
59   }
60  private:
61   bool * const FoundTopLevelDecl;
62 };
63 } // end namespace
64 
65 TEST(runToolOnCode, FindsNoTopLevelDeclOnEmptyCode) {
66   bool FoundTopLevelDecl = false;
67   EXPECT_TRUE(
68       runToolOnCode(new TestAction(llvm::make_unique<FindTopLevelDeclConsumer>(
69                         &FoundTopLevelDecl)),
70                     ""));
71   EXPECT_FALSE(FoundTopLevelDecl);
72 }
73 
74 namespace {
75 class FindClassDeclXConsumer : public clang::ASTConsumer {
76  public:
77   FindClassDeclXConsumer(bool *FoundClassDeclX)
78       : FoundClassDeclX(FoundClassDeclX) {}
79   bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) override {
80     if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
81             *GroupRef.begin())) {
82       if (Record->getName() == "X") {
83         *FoundClassDeclX = true;
84       }
85     }
86     return true;
87   }
88  private:
89   bool *FoundClassDeclX;
90 };
91 bool FindClassDeclX(ASTUnit *AST) {
92   for (std::vector<Decl *>::iterator i = AST->top_level_begin(),
93                                      e = AST->top_level_end();
94        i != e; ++i) {
95     if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(*i)) {
96       if (Record->getName() == "X") {
97         return true;
98       }
99     }
100   }
101   return false;
102 }
103 } // end namespace
104 
105 TEST(runToolOnCode, FindsClassDecl) {
106   bool FoundClassDeclX = false;
107   EXPECT_TRUE(
108       runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>(
109                         &FoundClassDeclX)),
110                     "class X;"));
111   EXPECT_TRUE(FoundClassDeclX);
112 
113   FoundClassDeclX = false;
114   EXPECT_TRUE(
115       runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>(
116                         &FoundClassDeclX)),
117                     "class Y;"));
118   EXPECT_FALSE(FoundClassDeclX);
119 }
120 
121 TEST(buildASTFromCode, FindsClassDecl) {
122   std::unique_ptr<ASTUnit> AST = buildASTFromCode("class X;");
123   ASSERT_TRUE(AST.get());
124   EXPECT_TRUE(FindClassDeclX(AST.get()));
125 
126   AST = buildASTFromCode("class Y;");
127   ASSERT_TRUE(AST.get());
128   EXPECT_FALSE(FindClassDeclX(AST.get()));
129 }
130 
131 TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
132   std::unique_ptr<FrontendActionFactory> Factory(
133       newFrontendActionFactory<SyntaxOnlyAction>());
134   std::unique_ptr<FrontendAction> Action(Factory->create());
135   EXPECT_TRUE(Action.get() != nullptr);
136 }
137 
138 struct IndependentFrontendActionCreator {
139   std::unique_ptr<ASTConsumer> newASTConsumer() {
140     return llvm::make_unique<FindTopLevelDeclConsumer>(nullptr);
141   }
142 };
143 
144 TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
145   IndependentFrontendActionCreator Creator;
146   std::unique_ptr<FrontendActionFactory> Factory(
147       newFrontendActionFactory(&Creator));
148   std::unique_ptr<FrontendAction> Action(Factory->create());
149   EXPECT_TRUE(Action.get() != nullptr);
150 }
151 
152 TEST(ToolInvocation, TestMapVirtualFile) {
153   llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
154       new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
155   llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
156       new vfs::InMemoryFileSystem);
157   OverlayFileSystem->pushOverlay(InMemoryFileSystem);
158   llvm::IntrusiveRefCntPtr<FileManager> Files(
159       new FileManager(FileSystemOptions(), OverlayFileSystem));
160   std::vector<std::string> Args;
161   Args.push_back("tool-executable");
162   Args.push_back("-Idef");
163   Args.push_back("-fsyntax-only");
164   Args.push_back("test.cpp");
165   clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
166                                             Files.get());
167   InMemoryFileSystem->addFile(
168       "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include <abc>\n"));
169   InMemoryFileSystem->addFile("def/abc", 0,
170                               llvm::MemoryBuffer::getMemBuffer("\n"));
171   EXPECT_TRUE(Invocation.run());
172 }
173 
174 TEST(ToolInvocation, TestVirtualModulesCompilation) {
175   // FIXME: Currently, this only tests that we don't exit with an error if a
176   // mapped module.map is found on the include path. In the future, expand this
177   // test to run a full modules enabled compilation, so we make sure we can
178   // rerun modules compilations with a virtual file system.
179   llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
180       new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
181   llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
182       new vfs::InMemoryFileSystem);
183   OverlayFileSystem->pushOverlay(InMemoryFileSystem);
184   llvm::IntrusiveRefCntPtr<FileManager> Files(
185       new FileManager(FileSystemOptions(), OverlayFileSystem));
186   std::vector<std::string> Args;
187   Args.push_back("tool-executable");
188   Args.push_back("-Idef");
189   Args.push_back("-fsyntax-only");
190   Args.push_back("test.cpp");
191   clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
192                                             Files.get());
193   InMemoryFileSystem->addFile(
194       "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include <abc>\n"));
195   InMemoryFileSystem->addFile("def/abc", 0,
196                               llvm::MemoryBuffer::getMemBuffer("\n"));
197   // Add a module.map file in the include directory of our header, so we trigger
198   // the module.map header search logic.
199   InMemoryFileSystem->addFile("def/module.map", 0,
200                               llvm::MemoryBuffer::getMemBuffer("\n"));
201   EXPECT_TRUE(Invocation.run());
202 }
203 
204 struct VerifyEndCallback : public SourceFileCallbacks {
205   VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {}
206   bool handleBeginSource(CompilerInstance &CI, StringRef Filename) override {
207     ++BeginCalled;
208     return true;
209   }
210   void handleEndSource() override { ++EndCalled; }
211   std::unique_ptr<ASTConsumer> newASTConsumer() {
212     return llvm::make_unique<FindTopLevelDeclConsumer>(&Matched);
213   }
214   unsigned BeginCalled;
215   unsigned EndCalled;
216   bool Matched;
217 };
218 
219 #if !defined(LLVM_ON_WIN32)
220 TEST(newFrontendActionFactory, InjectsSourceFileCallbacks) {
221   VerifyEndCallback EndCallback;
222 
223   FixedCompilationDatabase Compilations("/", std::vector<std::string>());
224   std::vector<std::string> Sources;
225   Sources.push_back("/a.cc");
226   Sources.push_back("/b.cc");
227   ClangTool Tool(Compilations, Sources);
228 
229   Tool.mapVirtualFile("/a.cc", "void a() {}");
230   Tool.mapVirtualFile("/b.cc", "void b() {}");
231 
232   std::unique_ptr<FrontendActionFactory> Action(
233       newFrontendActionFactory(&EndCallback, &EndCallback));
234   Tool.run(Action.get());
235 
236   EXPECT_TRUE(EndCallback.Matched);
237   EXPECT_EQ(2u, EndCallback.BeginCalled);
238   EXPECT_EQ(2u, EndCallback.EndCalled);
239 }
240 #endif
241 
242 struct SkipBodyConsumer : public clang::ASTConsumer {
243   /// Skip the 'skipMe' function.
244   bool shouldSkipFunctionBody(Decl *D) override {
245     NamedDecl *F = dyn_cast<NamedDecl>(D);
246     return F && F->getNameAsString() == "skipMe";
247   }
248 };
249 
250 struct SkipBodyAction : public clang::ASTFrontendAction {
251   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
252                                                  StringRef) override {
253     Compiler.getFrontendOpts().SkipFunctionBodies = true;
254     return llvm::make_unique<SkipBodyConsumer>();
255   }
256 };
257 
258 TEST(runToolOnCode, TestSkipFunctionBody) {
259   std::vector<std::string> Args = {"-std=c++11"};
260   std::vector<std::string> Args2 = {"-fno-delayed-template-parsing"};
261 
262   EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
263                             "int skipMe() { an_error_here }"));
264   EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
265                              "int skipMeNot() { an_error_here }"));
266 
267   // Test constructors with initializers
268   EXPECT_TRUE(runToolOnCodeWithArgs(
269       new SkipBodyAction,
270       "struct skipMe { skipMe() : an_error() { more error } };", Args));
271   EXPECT_TRUE(runToolOnCodeWithArgs(
272       new SkipBodyAction, "struct skipMe { skipMe(); };"
273                           "skipMe::skipMe() : an_error([](){;}) { more error }",
274       Args));
275   EXPECT_TRUE(runToolOnCodeWithArgs(
276       new SkipBodyAction, "struct skipMe { skipMe(); };"
277                           "skipMe::skipMe() : an_error{[](){;}} { more error }",
278       Args));
279   EXPECT_TRUE(runToolOnCodeWithArgs(
280       new SkipBodyAction,
281       "struct skipMe { skipMe(); };"
282       "skipMe::skipMe() : a<b<c>(e)>>(), f{}, g() { error }",
283       Args));
284   EXPECT_TRUE(runToolOnCodeWithArgs(
285       new SkipBodyAction, "struct skipMe { skipMe() : bases()... { error } };",
286       Args));
287 
288   EXPECT_FALSE(runToolOnCodeWithArgs(
289       new SkipBodyAction, "struct skipMeNot { skipMeNot() : an_error() { } };",
290       Args));
291   EXPECT_FALSE(runToolOnCodeWithArgs(new SkipBodyAction,
292                                      "struct skipMeNot { skipMeNot(); };"
293                                      "skipMeNot::skipMeNot() : an_error() { }",
294                                      Args));
295 
296   // Try/catch
297   EXPECT_TRUE(runToolOnCode(
298       new SkipBodyAction,
299       "void skipMe() try { an_error() } catch(error) { error };"));
300   EXPECT_TRUE(runToolOnCode(
301       new SkipBodyAction,
302       "struct S { void skipMe() try { an_error() } catch(error) { error } };"));
303   EXPECT_TRUE(
304       runToolOnCode(new SkipBodyAction,
305                     "void skipMe() try { an_error() } catch(error) { error; }"
306                     "catch(error) { error } catch (error) { }"));
307   EXPECT_FALSE(runToolOnCode(
308       new SkipBodyAction,
309       "void skipMe() try something;")); // don't crash while parsing
310 
311   // Template
312   EXPECT_TRUE(runToolOnCode(
313       new SkipBodyAction, "template<typename T> int skipMe() { an_error_here }"
314                           "int x = skipMe<int>();"));
315   EXPECT_FALSE(runToolOnCodeWithArgs(
316       new SkipBodyAction,
317       "template<typename T> int skipMeNot() { an_error_here }", Args2));
318 }
319 
320 TEST(runToolOnCodeWithArgs, TestNoDepFile) {
321   llvm::SmallString<32> DepFilePath;
322   ASSERT_FALSE(
323       llvm::sys::fs::createTemporaryFile("depfile", "d", DepFilePath));
324   std::vector<std::string> Args;
325   Args.push_back("-MMD");
326   Args.push_back("-MT");
327   Args.push_back(DepFilePath.str());
328   Args.push_back("-MF");
329   Args.push_back(DepFilePath.str());
330   EXPECT_TRUE(runToolOnCodeWithArgs(new SkipBodyAction, "", Args));
331   EXPECT_FALSE(llvm::sys::fs::exists(DepFilePath.str()));
332   EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
333 }
334 
335 struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
336   CheckColoredDiagnosticsAction(bool ShouldShowColor)
337       : ShouldShowColor(ShouldShowColor) {}
338   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
339                                                  StringRef) override {
340     if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
341       Compiler.getDiagnostics().Report(
342           Compiler.getDiagnostics().getCustomDiagID(
343               DiagnosticsEngine::Fatal,
344               "getDiagnosticOpts().ShowColors != ShouldShowColor"));
345     return llvm::make_unique<ASTConsumer>();
346   }
347 
348 private:
349   bool ShouldShowColor = true;
350 };
351 
352 TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
353 
354   EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
355                                     {"-fcolor-diagnostics"}));
356   EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
357                                     "", {"-fno-color-diagnostics"}));
358   EXPECT_TRUE(
359       runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
360                             {"-fno-color-diagnostics", "-fcolor-diagnostics"}));
361   EXPECT_TRUE(
362       runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "",
363                             {"-fcolor-diagnostics", "-fno-color-diagnostics"}));
364   EXPECT_TRUE(runToolOnCodeWithArgs(
365       new CheckColoredDiagnosticsAction(true), "",
366       {"-fno-color-diagnostics", "-fdiagnostics-color=always"}));
367 
368   // Check that this test would fail if ShowColors is not what it should.
369   EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
370                                      "", {"-fcolor-diagnostics"}));
371 }
372 
373 TEST(ClangToolTest, ArgumentAdjusters) {
374   FixedCompilationDatabase Compilations("/", std::vector<std::string>());
375 
376   ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
377   Tool.mapVirtualFile("/a.cc", "void a() {}");
378 
379   std::unique_ptr<FrontendActionFactory> Action(
380       newFrontendActionFactory<SyntaxOnlyAction>());
381 
382   bool Found = false;
383   bool Ran = false;
384   ArgumentsAdjuster CheckSyntaxOnlyAdjuster =
385       [&Found, &Ran](const CommandLineArguments &Args, StringRef /*unused*/) {
386     Ran = true;
387     if (std::find(Args.begin(), Args.end(), "-fsyntax-only") != Args.end())
388       Found = true;
389     return Args;
390   };
391   Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
392   Tool.run(Action.get());
393   EXPECT_TRUE(Ran);
394   EXPECT_TRUE(Found);
395 
396   Ran = Found = false;
397   Tool.clearArgumentsAdjusters();
398   Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
399   Tool.appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
400   Tool.run(Action.get());
401   EXPECT_TRUE(Ran);
402   EXPECT_FALSE(Found);
403 }
404 
405 namespace {
406 /// Find a target name such that looking for it in TargetRegistry by that name
407 /// returns the same target. We expect that there is at least one target
408 /// configured with this property.
409 std::string getAnyTarget() {
410   llvm::InitializeAllTargets();
411   for (const auto &Target : llvm::TargetRegistry::targets()) {
412     std::string Error;
413     StringRef TargetName(Target.getName());
414     if (TargetName == "x86-64")
415       TargetName = "x86_64";
416     if (llvm::TargetRegistry::lookupTarget(TargetName, Error) == &Target) {
417       return TargetName;
418     }
419   }
420   return "";
421 }
422 }
423 
424 TEST(addTargetAndModeForProgramName, AddsTargetAndMode) {
425   std::string Target = getAnyTarget();
426   ASSERT_FALSE(Target.empty());
427 
428   std::vector<std::string> Args = {"clang", "-foo"};
429   addTargetAndModeForProgramName(Args, "");
430   EXPECT_EQ((std::vector<std::string>{"clang", "-foo"}), Args);
431   addTargetAndModeForProgramName(Args, Target + "-g++");
432   EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target,
433                                       "--driver-mode=g++", "-foo"}),
434             Args);
435 }
436 
437 TEST(addTargetAndModeForProgramName, PathIgnored) {
438   std::string Target = getAnyTarget();
439   ASSERT_FALSE(Target.empty());
440 
441   SmallString<32> ToolPath;
442   llvm::sys::path::append(ToolPath, "foo", "bar", Target + "-g++");
443 
444   std::vector<std::string> Args = {"clang", "-foo"};
445   addTargetAndModeForProgramName(Args, ToolPath);
446   EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target,
447                                       "--driver-mode=g++", "-foo"}),
448             Args);
449 }
450 
451 TEST(addTargetAndModeForProgramName, IgnoresExistingTarget) {
452   std::string Target = getAnyTarget();
453   ASSERT_FALSE(Target.empty());
454 
455   std::vector<std::string> Args = {"clang", "-foo", "-target", "something"};
456   addTargetAndModeForProgramName(Args, Target + "-g++");
457   EXPECT_EQ((std::vector<std::string>{"clang", "--driver-mode=g++", "-foo",
458                                       "-target", "something"}),
459             Args);
460 
461   std::vector<std::string> ArgsAlt = {"clang", "-foo", "-target=something"};
462   addTargetAndModeForProgramName(ArgsAlt, Target + "-g++");
463   EXPECT_EQ((std::vector<std::string>{"clang", "--driver-mode=g++", "-foo",
464                                       "-target=something"}),
465             ArgsAlt);
466 }
467 
468 TEST(addTargetAndModeForProgramName, IgnoresExistingMode) {
469   std::string Target = getAnyTarget();
470   ASSERT_FALSE(Target.empty());
471 
472   std::vector<std::string> Args = {"clang", "-foo", "--driver-mode=abc"};
473   addTargetAndModeForProgramName(Args, Target + "-g++");
474   EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target, "-foo",
475                                       "--driver-mode=abc"}),
476             Args);
477 
478   std::vector<std::string> ArgsAlt = {"clang", "-foo", "--driver-mode", "abc"};
479   addTargetAndModeForProgramName(ArgsAlt, Target + "-g++");
480   EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target, "-foo",
481                                       "--driver-mode", "abc"}),
482             ArgsAlt);
483 }
484 
485 #ifndef LLVM_ON_WIN32
486 TEST(ClangToolTest, BuildASTs) {
487   FixedCompilationDatabase Compilations("/", std::vector<std::string>());
488 
489   std::vector<std::string> Sources;
490   Sources.push_back("/a.cc");
491   Sources.push_back("/b.cc");
492   ClangTool Tool(Compilations, Sources);
493 
494   Tool.mapVirtualFile("/a.cc", "void a() {}");
495   Tool.mapVirtualFile("/b.cc", "void b() {}");
496 
497   std::vector<std::unique_ptr<ASTUnit>> ASTs;
498   EXPECT_EQ(0, Tool.buildASTs(ASTs));
499   EXPECT_EQ(2u, ASTs.size());
500 }
501 
502 struct TestDiagnosticConsumer : public DiagnosticConsumer {
503   TestDiagnosticConsumer() : NumDiagnosticsSeen(0) {}
504   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
505                         const Diagnostic &Info) override {
506     ++NumDiagnosticsSeen;
507   }
508   unsigned NumDiagnosticsSeen;
509 };
510 
511 TEST(ClangToolTest, InjectDiagnosticConsumer) {
512   FixedCompilationDatabase Compilations("/", std::vector<std::string>());
513   ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
514   Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
515   TestDiagnosticConsumer Consumer;
516   Tool.setDiagnosticConsumer(&Consumer);
517   std::unique_ptr<FrontendActionFactory> Action(
518       newFrontendActionFactory<SyntaxOnlyAction>());
519   Tool.run(Action.get());
520   EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
521 }
522 
523 TEST(ClangToolTest, InjectDiagnosticConsumerInBuildASTs) {
524   FixedCompilationDatabase Compilations("/", std::vector<std::string>());
525   ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
526   Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
527   TestDiagnosticConsumer Consumer;
528   Tool.setDiagnosticConsumer(&Consumer);
529   std::vector<std::unique_ptr<ASTUnit>> ASTs;
530   Tool.buildASTs(ASTs);
531   EXPECT_EQ(1u, ASTs.size());
532   EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
533 }
534 #endif
535 
536 } // end namespace tooling
537 } // end namespace clang
538