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