1 //===- TreeTest.cpp -------------------------------------------------------===// 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 "clang/Tooling/Syntax/Tree.h" 10 #include "clang/AST/ASTConsumer.h" 11 #include "clang/AST/Decl.h" 12 #include "clang/AST/Stmt.h" 13 #include "clang/Basic/LLVM.h" 14 #include "clang/Basic/TokenKinds.h" 15 #include "clang/Frontend/CompilerInstance.h" 16 #include "clang/Frontend/CompilerInvocation.h" 17 #include "clang/Frontend/FrontendAction.h" 18 #include "clang/Frontend/TextDiagnosticPrinter.h" 19 #include "clang/Lex/PreprocessorOptions.h" 20 #include "clang/Testing/CommandLineArgs.h" 21 #include "clang/Tooling/Core/Replacement.h" 22 #include "clang/Tooling/Syntax/BuildTree.h" 23 #include "clang/Tooling/Syntax/Mutations.h" 24 #include "clang/Tooling/Syntax/Nodes.h" 25 #include "clang/Tooling/Syntax/Tokens.h" 26 #include "clang/Tooling/Tooling.h" 27 #include "llvm/ADT/ArrayRef.h" 28 #include "llvm/ADT/STLExtras.h" 29 #include "llvm/ADT/StringExtras.h" 30 #include "llvm/ADT/StringRef.h" 31 #include "llvm/Support/Casting.h" 32 #include "llvm/Support/Error.h" 33 #include "llvm/Testing/Support/Annotations.h" 34 #include "gmock/gmock.h" 35 #include "gtest/gtest.h" 36 #include <cstdlib> 37 38 using namespace clang; 39 40 namespace { 41 static llvm::ArrayRef<syntax::Token> tokens(syntax::Node *N) { 42 assert(N->isOriginal() && "tokens of modified nodes are not well-defined"); 43 if (auto *L = dyn_cast<syntax::Leaf>(N)) 44 return llvm::makeArrayRef(L->token(), 1); 45 auto *T = cast<syntax::Tree>(N); 46 return llvm::makeArrayRef(T->firstLeaf()->token(), 47 T->lastLeaf()->token() + 1); 48 } 49 50 struct TestClangConfig { 51 TestLanguage Language; 52 std::string Target; 53 54 bool isC99OrLater() const { return Language == Lang_C99; } 55 56 bool isCXX() const { 57 return Language == Lang_CXX03 || Language == Lang_CXX11 || 58 Language == Lang_CXX14 || Language == Lang_CXX17 || 59 Language == Lang_CXX20; 60 } 61 62 bool isCXX11OrLater() const { 63 return Language == Lang_CXX11 || Language == Lang_CXX14 || 64 Language == Lang_CXX17 || Language == Lang_CXX20; 65 } 66 67 bool hasDelayedTemplateParsing() const { 68 return Target == "x86_64-pc-win32-msvc"; 69 } 70 71 std::vector<std::string> getCommandLineArgs() const { 72 std::vector<std::string> Result = getCommandLineArgsForTesting(Language); 73 Result.push_back("-target"); 74 Result.push_back(Target); 75 return Result; 76 } 77 78 std::string toString() const { 79 std::string Result; 80 llvm::raw_string_ostream OS(Result); 81 OS << "{ Language=" << Language << ", Target=" << Target << " }"; 82 return OS.str(); 83 } 84 85 friend std::ostream &operator<<(std::ostream &OS, 86 const TestClangConfig &ClangConfig) { 87 return OS << ClangConfig.toString(); 88 } 89 90 static std::vector<TestClangConfig> &allConfigs() { 91 static std::vector<TestClangConfig> all_configs = []() { 92 std::vector<TestClangConfig> all_configs; 93 for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11, 94 Lang_CXX14, Lang_CXX17, Lang_CXX20}) { 95 TestClangConfig config; 96 config.Language = lang; 97 config.Target = "x86_64-pc-linux-gnu"; 98 all_configs.push_back(config); 99 100 // Windows target is interesting to test because it enables 101 // `-fdelayed-template-parsing`. 102 config.Target = "x86_64-pc-win32-msvc"; 103 all_configs.push_back(config); 104 } 105 return all_configs; 106 }(); 107 return all_configs; 108 } 109 }; 110 111 class SyntaxTreeTest : public ::testing::Test, 112 public ::testing::WithParamInterface<TestClangConfig> { 113 protected: 114 // Build a syntax tree for the code. 115 syntax::TranslationUnit *buildTree(llvm::StringRef Code, 116 const TestClangConfig &ClangConfig) { 117 // FIXME: this code is almost the identical to the one in TokensTest. Share 118 // it. 119 class BuildSyntaxTree : public ASTConsumer { 120 public: 121 BuildSyntaxTree(syntax::TranslationUnit *&Root, 122 std::unique_ptr<syntax::Arena> &Arena, 123 std::unique_ptr<syntax::TokenCollector> Tokens) 124 : Root(Root), Arena(Arena), Tokens(std::move(Tokens)) { 125 assert(this->Tokens); 126 } 127 128 void HandleTranslationUnit(ASTContext &Ctx) override { 129 Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(), 130 Ctx.getLangOpts(), 131 std::move(*Tokens).consume()); 132 Tokens = nullptr; // make sure we fail if this gets called twice. 133 Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl()); 134 } 135 136 private: 137 syntax::TranslationUnit *&Root; 138 std::unique_ptr<syntax::Arena> &Arena; 139 std::unique_ptr<syntax::TokenCollector> Tokens; 140 }; 141 142 class BuildSyntaxTreeAction : public ASTFrontendAction { 143 public: 144 BuildSyntaxTreeAction(syntax::TranslationUnit *&Root, 145 std::unique_ptr<syntax::Arena> &Arena) 146 : Root(Root), Arena(Arena) {} 147 148 std::unique_ptr<ASTConsumer> 149 CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { 150 // We start recording the tokens, ast consumer will take on the result. 151 auto Tokens = 152 std::make_unique<syntax::TokenCollector>(CI.getPreprocessor()); 153 return std::make_unique<BuildSyntaxTree>(Root, Arena, 154 std::move(Tokens)); 155 } 156 157 private: 158 syntax::TranslationUnit *&Root; 159 std::unique_ptr<syntax::Arena> &Arena; 160 }; 161 162 constexpr const char *FileName = "./input.cpp"; 163 FS->addFile(FileName, time_t(), llvm::MemoryBuffer::getMemBufferCopy("")); 164 165 if (!Diags->getClient()) 166 Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), DiagOpts.get())); 167 Diags->setSeverityForGroup(diag::Flavor::WarningOrError, "unused-value", 168 diag::Severity::Ignored, SourceLocation()); 169 170 // Prepare to run a compiler. 171 std::vector<std::string> Args = { 172 "syntax-test", 173 "-fsyntax-only", 174 }; 175 llvm::copy(ClangConfig.getCommandLineArgs(), std::back_inserter(Args)); 176 Args.push_back(FileName); 177 178 std::vector<const char *> ArgsCStr; 179 for (const std::string &arg : Args) { 180 ArgsCStr.push_back(arg.c_str()); 181 } 182 183 Invocation = createInvocationFromCommandLine(ArgsCStr, Diags, FS); 184 assert(Invocation); 185 Invocation->getFrontendOpts().DisableFree = false; 186 Invocation->getPreprocessorOpts().addRemappedFile( 187 FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release()); 188 CompilerInstance Compiler; 189 Compiler.setInvocation(Invocation); 190 Compiler.setDiagnostics(Diags.get()); 191 Compiler.setFileManager(FileMgr.get()); 192 Compiler.setSourceManager(SourceMgr.get()); 193 194 syntax::TranslationUnit *Root = nullptr; 195 BuildSyntaxTreeAction Recorder(Root, this->Arena); 196 197 // Action could not be executed but the frontend didn't identify any errors 198 // in the code ==> problem in setting up the action. 199 if (!Compiler.ExecuteAction(Recorder) && 200 Diags->getClient()->getNumErrors() == 0) { 201 ADD_FAILURE() << "failed to run the frontend"; 202 std::abort(); 203 } 204 return Root; 205 } 206 207 void expectTreeDumpEqual(StringRef Code, StringRef Tree) { 208 SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " ")); 209 SCOPED_TRACE(Code); 210 211 auto *Root = buildTree(Code, GetParam()); 212 EXPECT_EQ(Diags->getClient()->getNumErrors(), 0u) 213 << "Source file has syntax errors, they were printed to the test log"; 214 std::string Actual = std::string(StringRef(Root->dump(*Arena)).trim()); 215 EXPECT_EQ(Tree.trim().str(), Actual); 216 } 217 218 // Adds a file to the test VFS. 219 void addFile(llvm::StringRef Path, llvm::StringRef Contents) { 220 if (!FS->addFile(Path, time_t(), 221 llvm::MemoryBuffer::getMemBufferCopy(Contents))) { 222 ADD_FAILURE() << "could not add a file to VFS: " << Path; 223 } 224 } 225 226 /// Finds the deepest node in the tree that covers exactly \p R. 227 /// FIXME: implement this efficiently and move to public syntax tree API. 228 syntax::Node *nodeByRange(llvm::Annotations::Range R, syntax::Node *Root) { 229 llvm::ArrayRef<syntax::Token> Toks = tokens(Root); 230 231 if (Toks.front().location().isFileID() && 232 Toks.back().location().isFileID() && 233 syntax::Token::range(*SourceMgr, Toks.front(), Toks.back()) == 234 syntax::FileRange(SourceMgr->getMainFileID(), R.Begin, R.End)) 235 return Root; 236 237 auto *T = dyn_cast<syntax::Tree>(Root); 238 if (!T) 239 return nullptr; 240 for (auto *C = T->firstChild(); C != nullptr; C = C->nextSibling()) { 241 if (auto *Result = nodeByRange(R, C)) 242 return Result; 243 } 244 return nullptr; 245 } 246 247 // Data fields. 248 llvm::IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = 249 new DiagnosticOptions(); 250 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags = 251 new DiagnosticsEngine(new DiagnosticIDs, DiagOpts.get()); 252 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS = 253 new llvm::vfs::InMemoryFileSystem; 254 llvm::IntrusiveRefCntPtr<FileManager> FileMgr = 255 new FileManager(FileSystemOptions(), FS); 256 llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr = 257 new SourceManager(*Diags, *FileMgr); 258 std::shared_ptr<CompilerInvocation> Invocation; 259 // Set after calling buildTree(). 260 std::unique_ptr<syntax::Arena> Arena; 261 }; 262 263 TEST_P(SyntaxTreeTest, Simple) { 264 expectTreeDumpEqual( 265 R"cpp( 266 int main() {} 267 void foo() {} 268 )cpp", 269 R"txt( 270 *: TranslationUnit 271 |-SimpleDeclaration 272 | |-int 273 | |-SimpleDeclarator 274 | | |-main 275 | | `-ParametersAndQualifiers 276 | | |-( 277 | | `-) 278 | `-CompoundStatement 279 | |-{ 280 | `-} 281 `-SimpleDeclaration 282 |-void 283 |-SimpleDeclarator 284 | |-foo 285 | `-ParametersAndQualifiers 286 | |-( 287 | `-) 288 `-CompoundStatement 289 |-{ 290 `-} 291 )txt"); 292 } 293 294 TEST_P(SyntaxTreeTest, SimpleVariable) { 295 expectTreeDumpEqual( 296 R"cpp( 297 int a; 298 int b = 42; 299 )cpp", 300 R"txt( 301 *: TranslationUnit 302 |-SimpleDeclaration 303 | |-int 304 | |-SimpleDeclarator 305 | | `-a 306 | `-; 307 `-SimpleDeclaration 308 |-int 309 |-SimpleDeclarator 310 | |-b 311 | |-= 312 | `-UnknownExpression 313 | `-42 314 `-; 315 )txt"); 316 } 317 318 TEST_P(SyntaxTreeTest, SimpleFunction) { 319 expectTreeDumpEqual( 320 R"cpp( 321 void foo(int a, int b) {} 322 )cpp", 323 R"txt( 324 *: TranslationUnit 325 `-SimpleDeclaration 326 |-void 327 |-SimpleDeclarator 328 | |-foo 329 | `-ParametersAndQualifiers 330 | |-( 331 | |-SimpleDeclaration 332 | | |-int 333 | | `-SimpleDeclarator 334 | | `-a 335 | |-, 336 | |-SimpleDeclaration 337 | | |-int 338 | | `-SimpleDeclarator 339 | | `-b 340 | `-) 341 `-CompoundStatement 342 |-{ 343 `-} 344 )txt"); 345 } 346 347 TEST_P(SyntaxTreeTest, If) { 348 expectTreeDumpEqual( 349 R"cpp( 350 int main() { 351 if (1) {} 352 if (1) {} else if (0) {} 353 } 354 )cpp", 355 R"txt( 356 *: TranslationUnit 357 `-SimpleDeclaration 358 |-int 359 |-SimpleDeclarator 360 | |-main 361 | `-ParametersAndQualifiers 362 | |-( 363 | `-) 364 `-CompoundStatement 365 |-{ 366 |-IfStatement 367 | |-if 368 | |-( 369 | |-UnknownExpression 370 | | `-1 371 | |-) 372 | `-CompoundStatement 373 | |-{ 374 | `-} 375 |-IfStatement 376 | |-if 377 | |-( 378 | |-UnknownExpression 379 | | `-1 380 | |-) 381 | |-CompoundStatement 382 | | |-{ 383 | | `-} 384 | |-else 385 | `-IfStatement 386 | |-if 387 | |-( 388 | |-UnknownExpression 389 | | `-0 390 | |-) 391 | `-CompoundStatement 392 | |-{ 393 | `-} 394 `-} 395 )txt"); 396 } 397 398 TEST_P(SyntaxTreeTest, For) { 399 expectTreeDumpEqual( 400 R"cpp( 401 void test() { 402 for (;;) {} 403 } 404 )cpp", 405 R"txt( 406 *: TranslationUnit 407 `-SimpleDeclaration 408 |-void 409 |-SimpleDeclarator 410 | |-test 411 | `-ParametersAndQualifiers 412 | |-( 413 | `-) 414 `-CompoundStatement 415 |-{ 416 |-ForStatement 417 | |-for 418 | |-( 419 | |-; 420 | |-; 421 | |-) 422 | `-CompoundStatement 423 | |-{ 424 | `-} 425 `-} 426 )txt"); 427 } 428 429 TEST_P(SyntaxTreeTest, RangeBasedFor) { 430 if (!GetParam().isCXX11OrLater()) { 431 return; 432 } 433 expectTreeDumpEqual( 434 R"cpp( 435 void test() { 436 int a[3]; 437 for (int x : a) 438 ; 439 } 440 )cpp", 441 R"txt( 442 *: TranslationUnit 443 `-SimpleDeclaration 444 |-void 445 |-SimpleDeclarator 446 | |-test 447 | `-ParametersAndQualifiers 448 | |-( 449 | `-) 450 `-CompoundStatement 451 |-{ 452 |-DeclarationStatement 453 | |-SimpleDeclaration 454 | | |-int 455 | | `-SimpleDeclarator 456 | | |-a 457 | | `-ArraySubscript 458 | | |-[ 459 | | |-UnknownExpression 460 | | | `-3 461 | | `-] 462 | `-; 463 |-RangeBasedForStatement 464 | |-for 465 | |-( 466 | |-SimpleDeclaration 467 | | |-int 468 | | |-SimpleDeclarator 469 | | | `-x 470 | | `-: 471 | |-UnknownExpression 472 | | `-a 473 | |-) 474 | `-EmptyStatement 475 | `-; 476 `-} 477 )txt"); 478 } 479 480 TEST_P(SyntaxTreeTest, DeclarationStatement) { 481 expectTreeDumpEqual("void test() { int a = 10; }", 482 R"txt( 483 *: TranslationUnit 484 `-SimpleDeclaration 485 |-void 486 |-SimpleDeclarator 487 | |-test 488 | `-ParametersAndQualifiers 489 | |-( 490 | `-) 491 `-CompoundStatement 492 |-{ 493 |-DeclarationStatement 494 | |-SimpleDeclaration 495 | | |-int 496 | | `-SimpleDeclarator 497 | | |-a 498 | | |-= 499 | | `-UnknownExpression 500 | | `-10 501 | `-; 502 `-} 503 )txt"); 504 } 505 506 TEST_P(SyntaxTreeTest, Switch) { 507 expectTreeDumpEqual( 508 R"cpp( 509 void test() { 510 switch (1) { 511 case 0: 512 default:; 513 } 514 } 515 )cpp", 516 R"txt( 517 *: TranslationUnit 518 `-SimpleDeclaration 519 |-void 520 |-SimpleDeclarator 521 | |-test 522 | `-ParametersAndQualifiers 523 | |-( 524 | `-) 525 `-CompoundStatement 526 |-{ 527 |-SwitchStatement 528 | |-switch 529 | |-( 530 | |-UnknownExpression 531 | | `-1 532 | |-) 533 | `-CompoundStatement 534 | |-{ 535 | |-CaseStatement 536 | | |-case 537 | | |-UnknownExpression 538 | | | `-0 539 | | |-: 540 | | `-DefaultStatement 541 | | |-default 542 | | |-: 543 | | `-EmptyStatement 544 | | `-; 545 | `-} 546 `-} 547 )txt"); 548 } 549 550 TEST_P(SyntaxTreeTest, While) { 551 expectTreeDumpEqual( 552 R"cpp( 553 void test() { 554 while (1) { continue; break; } 555 } 556 )cpp", 557 R"txt( 558 *: TranslationUnit 559 `-SimpleDeclaration 560 |-void 561 |-SimpleDeclarator 562 | |-test 563 | `-ParametersAndQualifiers 564 | |-( 565 | `-) 566 `-CompoundStatement 567 |-{ 568 |-WhileStatement 569 | |-while 570 | |-( 571 | |-UnknownExpression 572 | | `-1 573 | |-) 574 | `-CompoundStatement 575 | |-{ 576 | |-ContinueStatement 577 | | |-continue 578 | | `-; 579 | |-BreakStatement 580 | | |-break 581 | | `-; 582 | `-} 583 `-} 584 )txt"); 585 } 586 587 TEST_P(SyntaxTreeTest, UnhandledStatement) { 588 // Unhandled statements should end up as 'unknown statement'. 589 // This example uses a 'label statement', which does not yet have a syntax 590 // counterpart. 591 expectTreeDumpEqual("int main() { foo: return 100; }", 592 R"txt( 593 *: TranslationUnit 594 `-SimpleDeclaration 595 |-int 596 |-SimpleDeclarator 597 | |-main 598 | `-ParametersAndQualifiers 599 | |-( 600 | `-) 601 `-CompoundStatement 602 |-{ 603 |-UnknownStatement 604 | |-foo 605 | |-: 606 | `-ReturnStatement 607 | |-return 608 | |-UnknownExpression 609 | | `-100 610 | `-; 611 `-} 612 )txt"); 613 } 614 615 TEST_P(SyntaxTreeTest, Expressions) { 616 // expressions should be wrapped in 'ExpressionStatement' when they appear 617 // in a statement position. 618 expectTreeDumpEqual( 619 R"cpp( 620 void test() { 621 test(); 622 if (1) test(); else test(); 623 } 624 )cpp", 625 R"txt( 626 *: TranslationUnit 627 `-SimpleDeclaration 628 |-void 629 |-SimpleDeclarator 630 | |-test 631 | `-ParametersAndQualifiers 632 | |-( 633 | `-) 634 `-CompoundStatement 635 |-{ 636 |-ExpressionStatement 637 | |-UnknownExpression 638 | | |-UnknownExpression 639 | | | `-test 640 | | |-( 641 | | `-) 642 | `-; 643 |-IfStatement 644 | |-if 645 | |-( 646 | |-UnknownExpression 647 | | `-1 648 | |-) 649 | |-ExpressionStatement 650 | | |-UnknownExpression 651 | | | |-UnknownExpression 652 | | | | `-test 653 | | | |-( 654 | | | `-) 655 | | `-; 656 | |-else 657 | `-ExpressionStatement 658 | |-UnknownExpression 659 | | |-UnknownExpression 660 | | | `-test 661 | | |-( 662 | | `-) 663 | `-; 664 `-} 665 )txt"); 666 } 667 668 TEST_P(SyntaxTreeTest, PostfixUnaryOperator) { 669 expectTreeDumpEqual( 670 R"cpp( 671 void test(int a) { 672 a++; 673 a--; 674 } 675 )cpp", 676 R"txt( 677 *: TranslationUnit 678 `-SimpleDeclaration 679 |-void 680 |-SimpleDeclarator 681 | |-test 682 | `-ParametersAndQualifiers 683 | |-( 684 | |-SimpleDeclaration 685 | | |-int 686 | | `-SimpleDeclarator 687 | | `-a 688 | `-) 689 `-CompoundStatement 690 |-{ 691 |-ExpressionStatement 692 | |-PostfixUnaryOperatorExpression 693 | | |-UnknownExpression 694 | | | `-a 695 | | `-++ 696 | `-; 697 |-ExpressionStatement 698 | |-PostfixUnaryOperatorExpression 699 | | |-UnknownExpression 700 | | | `-a 701 | | `--- 702 | `-; 703 `-} 704 )txt"); 705 } 706 707 TEST_P(SyntaxTreeTest, PrefixUnaryOperator) { 708 if (!GetParam().isCXX()) { 709 // TODO: Split parts that depend on C++ into a separate test. 710 return; 711 } 712 expectTreeDumpEqual( 713 R"cpp( 714 void test(int a, int *ap, bool b) { 715 --a; ++a; 716 ~a; compl a; 717 -a; 718 +a; 719 &a; 720 *ap; 721 !b; not b; 722 __real a; __imag a; 723 } 724 )cpp", 725 R"txt( 726 *: TranslationUnit 727 `-SimpleDeclaration 728 |-void 729 |-SimpleDeclarator 730 | |-test 731 | `-ParametersAndQualifiers 732 | |-( 733 | |-SimpleDeclaration 734 | | |-int 735 | | `-SimpleDeclarator 736 | | `-a 737 | |-, 738 | |-SimpleDeclaration 739 | | |-int 740 | | `-SimpleDeclarator 741 | | |-* 742 | | `-ap 743 | |-, 744 | |-SimpleDeclaration 745 | | |-bool 746 | | `-SimpleDeclarator 747 | | `-b 748 | `-) 749 `-CompoundStatement 750 |-{ 751 |-ExpressionStatement 752 | |-PrefixUnaryOperatorExpression 753 | | |--- 754 | | `-UnknownExpression 755 | | `-a 756 | `-; 757 |-ExpressionStatement 758 | |-PrefixUnaryOperatorExpression 759 | | |-++ 760 | | `-UnknownExpression 761 | | `-a 762 | `-; 763 |-ExpressionStatement 764 | |-PrefixUnaryOperatorExpression 765 | | |-~ 766 | | `-UnknownExpression 767 | | `-a 768 | `-; 769 |-ExpressionStatement 770 | |-PrefixUnaryOperatorExpression 771 | | |-compl 772 | | `-UnknownExpression 773 | | `-a 774 | `-; 775 |-ExpressionStatement 776 | |-PrefixUnaryOperatorExpression 777 | | |-- 778 | | `-UnknownExpression 779 | | `-a 780 | `-; 781 |-ExpressionStatement 782 | |-PrefixUnaryOperatorExpression 783 | | |-+ 784 | | `-UnknownExpression 785 | | `-a 786 | `-; 787 |-ExpressionStatement 788 | |-PrefixUnaryOperatorExpression 789 | | |-& 790 | | `-UnknownExpression 791 | | `-a 792 | `-; 793 |-ExpressionStatement 794 | |-PrefixUnaryOperatorExpression 795 | | |-* 796 | | `-UnknownExpression 797 | | `-ap 798 | `-; 799 |-ExpressionStatement 800 | |-PrefixUnaryOperatorExpression 801 | | |-! 802 | | `-UnknownExpression 803 | | `-b 804 | `-; 805 |-ExpressionStatement 806 | |-PrefixUnaryOperatorExpression 807 | | |-not 808 | | `-UnknownExpression 809 | | `-b 810 | `-; 811 |-ExpressionStatement 812 | |-PrefixUnaryOperatorExpression 813 | | |-__real 814 | | `-UnknownExpression 815 | | `-a 816 | `-; 817 |-ExpressionStatement 818 | |-PrefixUnaryOperatorExpression 819 | | |-__imag 820 | | `-UnknownExpression 821 | | `-a 822 | `-; 823 `-} 824 )txt"); 825 } 826 827 TEST_P(SyntaxTreeTest, BinaryOperator) { 828 if (!GetParam().isCXX()) { 829 // TODO: Split parts that depend on C++ into a separate test. 830 return; 831 } 832 expectTreeDumpEqual( 833 R"cpp( 834 void test(int a) { 835 1 - 2; 836 1 == 2; 837 a = 1; 838 a <<= 1; 839 840 true || false; 841 true or false; 842 843 1 & 2; 844 1 bitand 2; 845 846 a ^= 3; 847 a xor_eq 3; 848 } 849 )cpp", 850 R"txt( 851 *: TranslationUnit 852 `-SimpleDeclaration 853 |-void 854 |-SimpleDeclarator 855 | |-test 856 | `-ParametersAndQualifiers 857 | |-( 858 | |-SimpleDeclaration 859 | | |-int 860 | | `-SimpleDeclarator 861 | | `-a 862 | `-) 863 `-CompoundStatement 864 |-{ 865 |-ExpressionStatement 866 | |-BinaryOperatorExpression 867 | | |-UnknownExpression 868 | | | `-1 869 | | |-- 870 | | `-UnknownExpression 871 | | `-2 872 | `-; 873 |-ExpressionStatement 874 | |-BinaryOperatorExpression 875 | | |-UnknownExpression 876 | | | `-1 877 | | |-== 878 | | `-UnknownExpression 879 | | `-2 880 | `-; 881 |-ExpressionStatement 882 | |-BinaryOperatorExpression 883 | | |-UnknownExpression 884 | | | `-a 885 | | |-= 886 | | `-UnknownExpression 887 | | `-1 888 | `-; 889 |-ExpressionStatement 890 | |-BinaryOperatorExpression 891 | | |-UnknownExpression 892 | | | `-a 893 | | |-<<= 894 | | `-UnknownExpression 895 | | `-1 896 | `-; 897 |-ExpressionStatement 898 | |-BinaryOperatorExpression 899 | | |-UnknownExpression 900 | | | `-true 901 | | |-|| 902 | | `-UnknownExpression 903 | | `-false 904 | `-; 905 |-ExpressionStatement 906 | |-BinaryOperatorExpression 907 | | |-UnknownExpression 908 | | | `-true 909 | | |-or 910 | | `-UnknownExpression 911 | | `-false 912 | `-; 913 |-ExpressionStatement 914 | |-BinaryOperatorExpression 915 | | |-UnknownExpression 916 | | | `-1 917 | | |-& 918 | | `-UnknownExpression 919 | | `-2 920 | `-; 921 |-ExpressionStatement 922 | |-BinaryOperatorExpression 923 | | |-UnknownExpression 924 | | | `-1 925 | | |-bitand 926 | | `-UnknownExpression 927 | | `-2 928 | `-; 929 |-ExpressionStatement 930 | |-BinaryOperatorExpression 931 | | |-UnknownExpression 932 | | | `-a 933 | | |-^= 934 | | `-UnknownExpression 935 | | `-3 936 | `-; 937 |-ExpressionStatement 938 | |-BinaryOperatorExpression 939 | | |-UnknownExpression 940 | | | `-a 941 | | |-xor_eq 942 | | `-UnknownExpression 943 | | `-3 944 | `-; 945 `-} 946 )txt"); 947 } 948 949 TEST_P(SyntaxTreeTest, NestedBinaryOperator) { 950 expectTreeDumpEqual( 951 R"cpp( 952 void test(int a, int b) { 953 (1 + 2) * (4 / 2); 954 a + b + 42; 955 a = b = 42; 956 a + b * 4 + 2; 957 a % 2 + b * 42; 958 } 959 )cpp", 960 R"txt( 961 *: TranslationUnit 962 `-SimpleDeclaration 963 |-void 964 |-SimpleDeclarator 965 | |-test 966 | `-ParametersAndQualifiers 967 | |-( 968 | |-SimpleDeclaration 969 | | |-int 970 | | `-SimpleDeclarator 971 | | `-a 972 | |-, 973 | |-SimpleDeclaration 974 | | |-int 975 | | `-SimpleDeclarator 976 | | `-b 977 | `-) 978 `-CompoundStatement 979 |-{ 980 |-ExpressionStatement 981 | |-BinaryOperatorExpression 982 | | |-UnknownExpression 983 | | | |-( 984 | | | |-BinaryOperatorExpression 985 | | | | |-UnknownExpression 986 | | | | | `-1 987 | | | | |-+ 988 | | | | `-UnknownExpression 989 | | | | `-2 990 | | | `-) 991 | | |-* 992 | | `-UnknownExpression 993 | | |-( 994 | | |-BinaryOperatorExpression 995 | | | |-UnknownExpression 996 | | | | `-4 997 | | | |-/ 998 | | | `-UnknownExpression 999 | | | `-2 1000 | | `-) 1001 | `-; 1002 |-ExpressionStatement 1003 | |-BinaryOperatorExpression 1004 | | |-BinaryOperatorExpression 1005 | | | |-UnknownExpression 1006 | | | | `-a 1007 | | | |-+ 1008 | | | `-UnknownExpression 1009 | | | `-b 1010 | | |-+ 1011 | | `-UnknownExpression 1012 | | `-42 1013 | `-; 1014 |-ExpressionStatement 1015 | |-BinaryOperatorExpression 1016 | | |-UnknownExpression 1017 | | | `-a 1018 | | |-= 1019 | | `-BinaryOperatorExpression 1020 | | |-UnknownExpression 1021 | | | `-b 1022 | | |-= 1023 | | `-UnknownExpression 1024 | | `-42 1025 | `-; 1026 |-ExpressionStatement 1027 | |-BinaryOperatorExpression 1028 | | |-BinaryOperatorExpression 1029 | | | |-UnknownExpression 1030 | | | | `-a 1031 | | | |-+ 1032 | | | `-BinaryOperatorExpression 1033 | | | |-UnknownExpression 1034 | | | | `-b 1035 | | | |-* 1036 | | | `-UnknownExpression 1037 | | | `-4 1038 | | |-+ 1039 | | `-UnknownExpression 1040 | | `-2 1041 | `-; 1042 |-ExpressionStatement 1043 | |-BinaryOperatorExpression 1044 | | |-BinaryOperatorExpression 1045 | | | |-UnknownExpression 1046 | | | | `-a 1047 | | | |-% 1048 | | | `-UnknownExpression 1049 | | | `-2 1050 | | |-+ 1051 | | `-BinaryOperatorExpression 1052 | | |-UnknownExpression 1053 | | | `-b 1054 | | |-* 1055 | | `-UnknownExpression 1056 | | `-42 1057 | `-; 1058 `-} 1059 )txt"); 1060 } 1061 1062 TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) { 1063 if (!GetParam().isCXX()) { 1064 return; 1065 } 1066 expectTreeDumpEqual( 1067 R"cpp( 1068 struct X { 1069 X& operator=(const X&); 1070 friend X operator+(X, const X&); 1071 friend bool operator<(const X&, const X&); 1072 }; 1073 void test(X x, X y) { 1074 x = y; 1075 x + y; 1076 x < y; 1077 } 1078 )cpp", 1079 R"txt( 1080 *: TranslationUnit 1081 |-SimpleDeclaration 1082 | |-struct 1083 | |-X 1084 | |-{ 1085 | |-SimpleDeclaration 1086 | | |-X 1087 | | |-SimpleDeclarator 1088 | | | |-& 1089 | | | |-operator 1090 | | | |-= 1091 | | | `-ParametersAndQualifiers 1092 | | | |-( 1093 | | | |-SimpleDeclaration 1094 | | | | |-const 1095 | | | | |-X 1096 | | | | `-SimpleDeclarator 1097 | | | | `-& 1098 | | | `-) 1099 | | `-; 1100 | |-UnknownDeclaration 1101 | | `-SimpleDeclaration 1102 | | |-friend 1103 | | |-X 1104 | | |-SimpleDeclarator 1105 | | | |-operator 1106 | | | |-+ 1107 | | | `-ParametersAndQualifiers 1108 | | | |-( 1109 | | | |-SimpleDeclaration 1110 | | | | `-X 1111 | | | |-, 1112 | | | |-SimpleDeclaration 1113 | | | | |-const 1114 | | | | |-X 1115 | | | | `-SimpleDeclarator 1116 | | | | `-& 1117 | | | `-) 1118 | | `-; 1119 | |-UnknownDeclaration 1120 | | `-SimpleDeclaration 1121 | | |-friend 1122 | | |-bool 1123 | | |-SimpleDeclarator 1124 | | | |-operator 1125 | | | |-< 1126 | | | `-ParametersAndQualifiers 1127 | | | |-( 1128 | | | |-SimpleDeclaration 1129 | | | | |-const 1130 | | | | |-X 1131 | | | | `-SimpleDeclarator 1132 | | | | `-& 1133 | | | |-, 1134 | | | |-SimpleDeclaration 1135 | | | | |-const 1136 | | | | |-X 1137 | | | | `-SimpleDeclarator 1138 | | | | `-& 1139 | | | `-) 1140 | | `-; 1141 | |-} 1142 | `-; 1143 `-SimpleDeclaration 1144 |-void 1145 |-SimpleDeclarator 1146 | |-test 1147 | `-ParametersAndQualifiers 1148 | |-( 1149 | |-SimpleDeclaration 1150 | | |-X 1151 | | `-SimpleDeclarator 1152 | | `-x 1153 | |-, 1154 | |-SimpleDeclaration 1155 | | |-X 1156 | | `-SimpleDeclarator 1157 | | `-y 1158 | `-) 1159 `-CompoundStatement 1160 |-{ 1161 |-ExpressionStatement 1162 | |-BinaryOperatorExpression 1163 | | |-UnknownExpression 1164 | | | `-x 1165 | | |-UnknownExpression 1166 | | | `-= 1167 | | `-UnknownExpression 1168 | | `-y 1169 | `-; 1170 |-ExpressionStatement 1171 | |-BinaryOperatorExpression 1172 | | |-UnknownExpression 1173 | | | `-UnknownExpression 1174 | | | `-x 1175 | | |-UnknownExpression 1176 | | | `-+ 1177 | | `-UnknownExpression 1178 | | `-y 1179 | `-; 1180 |-ExpressionStatement 1181 | |-BinaryOperatorExpression 1182 | | |-UnknownExpression 1183 | | | `-x 1184 | | |-UnknownExpression 1185 | | | `-< 1186 | | `-UnknownExpression 1187 | | `-y 1188 | `-; 1189 `-} 1190 )txt"); 1191 } 1192 1193 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) { 1194 expectTreeDumpEqual( 1195 R"cpp( 1196 int *a, b; int *c, d; 1197 )cpp", 1198 R"txt( 1199 *: TranslationUnit 1200 |-SimpleDeclaration 1201 | |-int 1202 | |-SimpleDeclarator 1203 | | |-* 1204 | | `-a 1205 | |-, 1206 | |-SimpleDeclarator 1207 | | `-b 1208 | `-; 1209 `-SimpleDeclaration 1210 |-int 1211 |-SimpleDeclarator 1212 | |-* 1213 | `-c 1214 |-, 1215 |-SimpleDeclarator 1216 | `-d 1217 `-; 1218 )txt"); 1219 } 1220 1221 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) { 1222 expectTreeDumpEqual( 1223 R"cpp( 1224 typedef int *a, b; 1225 )cpp", 1226 R"txt( 1227 *: TranslationUnit 1228 `-SimpleDeclaration 1229 |-typedef 1230 |-int 1231 |-SimpleDeclarator 1232 | |-* 1233 | `-a 1234 |-, 1235 |-SimpleDeclarator 1236 | `-b 1237 `-; 1238 )txt"); 1239 } 1240 1241 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) { 1242 expectTreeDumpEqual( 1243 R"cpp( 1244 void foo() { 1245 int *a, b; 1246 typedef int *ta, tb; 1247 } 1248 )cpp", 1249 R"txt( 1250 *: TranslationUnit 1251 `-SimpleDeclaration 1252 |-void 1253 |-SimpleDeclarator 1254 | |-foo 1255 | `-ParametersAndQualifiers 1256 | |-( 1257 | `-) 1258 `-CompoundStatement 1259 |-{ 1260 |-DeclarationStatement 1261 | |-SimpleDeclaration 1262 | | |-int 1263 | | |-SimpleDeclarator 1264 | | | |-* 1265 | | | `-a 1266 | | |-, 1267 | | `-SimpleDeclarator 1268 | | `-b 1269 | `-; 1270 |-DeclarationStatement 1271 | |-SimpleDeclaration 1272 | | |-typedef 1273 | | |-int 1274 | | |-SimpleDeclarator 1275 | | | |-* 1276 | | | `-ta 1277 | | |-, 1278 | | `-SimpleDeclarator 1279 | | `-tb 1280 | `-; 1281 `-} 1282 )txt"); 1283 } 1284 1285 TEST_P(SyntaxTreeTest, Namespaces) { 1286 if (!GetParam().isCXX()) { 1287 return; 1288 } 1289 expectTreeDumpEqual( 1290 R"cpp( 1291 namespace a { namespace b {} } 1292 namespace a::b {} 1293 namespace {} 1294 1295 namespace foo = a; 1296 )cpp", 1297 R"txt( 1298 *: TranslationUnit 1299 |-NamespaceDefinition 1300 | |-namespace 1301 | |-a 1302 | |-{ 1303 | |-NamespaceDefinition 1304 | | |-namespace 1305 | | |-b 1306 | | |-{ 1307 | | `-} 1308 | `-} 1309 |-NamespaceDefinition 1310 | |-namespace 1311 | |-a 1312 | |-:: 1313 | |-b 1314 | |-{ 1315 | `-} 1316 |-NamespaceDefinition 1317 | |-namespace 1318 | |-{ 1319 | `-} 1320 `-NamespaceAliasDefinition 1321 |-namespace 1322 |-foo 1323 |-= 1324 |-a 1325 `-; 1326 )txt"); 1327 } 1328 1329 TEST_P(SyntaxTreeTest, UsingDirective) { 1330 if (!GetParam().isCXX()) { 1331 return; 1332 } 1333 expectTreeDumpEqual( 1334 R"cpp( 1335 namespace ns {} 1336 using namespace ::ns; 1337 )cpp", 1338 R"txt( 1339 *: TranslationUnit 1340 |-NamespaceDefinition 1341 | |-namespace 1342 | |-ns 1343 | |-{ 1344 | `-} 1345 `-UsingNamespaceDirective 1346 |-using 1347 |-namespace 1348 |-:: 1349 |-ns 1350 `-; 1351 )txt"); 1352 } 1353 1354 TEST_P(SyntaxTreeTest, UsingDeclaration) { 1355 if (!GetParam().isCXX()) { 1356 return; 1357 } 1358 expectTreeDumpEqual( 1359 R"cpp( 1360 namespace ns { int a; } 1361 using ns::a; 1362 )cpp", 1363 R"txt( 1364 *: TranslationUnit 1365 |-NamespaceDefinition 1366 | |-namespace 1367 | |-ns 1368 | |-{ 1369 | |-SimpleDeclaration 1370 | | |-int 1371 | | |-SimpleDeclarator 1372 | | | `-a 1373 | | `-; 1374 | `-} 1375 `-UsingDeclaration 1376 |-using 1377 |-ns 1378 |-:: 1379 |-a 1380 `-; 1381 )txt"); 1382 } 1383 1384 TEST_P(SyntaxTreeTest, FreeStandingClasses) { 1385 // Free-standing classes, must live inside a SimpleDeclaration. 1386 expectTreeDumpEqual( 1387 R"cpp( 1388 struct X; 1389 struct X {}; 1390 1391 struct Y *y1; 1392 struct Y {} *y2; 1393 1394 struct {} *a1; 1395 )cpp", 1396 R"txt( 1397 *: TranslationUnit 1398 |-SimpleDeclaration 1399 | |-struct 1400 | |-X 1401 | `-; 1402 |-SimpleDeclaration 1403 | |-struct 1404 | |-X 1405 | |-{ 1406 | |-} 1407 | `-; 1408 |-SimpleDeclaration 1409 | |-struct 1410 | |-Y 1411 | |-SimpleDeclarator 1412 | | |-* 1413 | | `-y1 1414 | `-; 1415 |-SimpleDeclaration 1416 | |-struct 1417 | |-Y 1418 | |-{ 1419 | |-} 1420 | |-SimpleDeclarator 1421 | | |-* 1422 | | `-y2 1423 | `-; 1424 `-SimpleDeclaration 1425 |-struct 1426 |-{ 1427 |-} 1428 |-SimpleDeclarator 1429 | |-* 1430 | `-a1 1431 `-; 1432 )txt"); 1433 } 1434 1435 TEST_P(SyntaxTreeTest, Templates) { 1436 if (!GetParam().isCXX()) { 1437 return; 1438 } 1439 if (GetParam().hasDelayedTemplateParsing()) { 1440 // FIXME: Make this test work on Windows by generating the expected syntax 1441 // tree when `-fdelayed-template-parsing` is active. 1442 return; 1443 } 1444 expectTreeDumpEqual( 1445 R"cpp( 1446 template <class T> struct cls {}; 1447 template <class T> int var = 10; 1448 template <class T> int fun() {} 1449 )cpp", 1450 R"txt( 1451 *: TranslationUnit 1452 |-TemplateDeclaration 1453 | |-template 1454 | |-< 1455 | |-UnknownDeclaration 1456 | | |-class 1457 | | `-T 1458 | |-> 1459 | `-SimpleDeclaration 1460 | |-struct 1461 | |-cls 1462 | |-{ 1463 | |-} 1464 | `-; 1465 |-TemplateDeclaration 1466 | |-template 1467 | |-< 1468 | |-UnknownDeclaration 1469 | | |-class 1470 | | `-T 1471 | |-> 1472 | `-SimpleDeclaration 1473 | |-int 1474 | |-SimpleDeclarator 1475 | | |-var 1476 | | |-= 1477 | | `-UnknownExpression 1478 | | `-10 1479 | `-; 1480 `-TemplateDeclaration 1481 |-template 1482 |-< 1483 |-UnknownDeclaration 1484 | |-class 1485 | `-T 1486 |-> 1487 `-SimpleDeclaration 1488 |-int 1489 |-SimpleDeclarator 1490 | |-fun 1491 | `-ParametersAndQualifiers 1492 | |-( 1493 | `-) 1494 `-CompoundStatement 1495 |-{ 1496 `-} 1497 )txt"); 1498 } 1499 1500 TEST_P(SyntaxTreeTest, NestedTemplates) { 1501 if (!GetParam().isCXX()) { 1502 return; 1503 } 1504 expectTreeDumpEqual( 1505 R"cpp( 1506 template <class T> 1507 struct X { 1508 template <class U> 1509 U foo(); 1510 }; 1511 )cpp", 1512 R"txt( 1513 *: TranslationUnit 1514 `-TemplateDeclaration 1515 |-template 1516 |-< 1517 |-UnknownDeclaration 1518 | |-class 1519 | `-T 1520 |-> 1521 `-SimpleDeclaration 1522 |-struct 1523 |-X 1524 |-{ 1525 |-TemplateDeclaration 1526 | |-template 1527 | |-< 1528 | |-UnknownDeclaration 1529 | | |-class 1530 | | `-U 1531 | |-> 1532 | `-SimpleDeclaration 1533 | |-U 1534 | |-SimpleDeclarator 1535 | | |-foo 1536 | | `-ParametersAndQualifiers 1537 | | |-( 1538 | | `-) 1539 | `-; 1540 |-} 1541 `-; 1542 )txt"); 1543 } 1544 1545 TEST_P(SyntaxTreeTest, Templates2) { 1546 if (!GetParam().isCXX()) { 1547 return; 1548 } 1549 expectTreeDumpEqual( 1550 R"cpp( 1551 template <class T> struct X { struct Y; }; 1552 template <class T> struct X<T>::Y {}; 1553 )cpp", 1554 R"txt( 1555 *: TranslationUnit 1556 |-TemplateDeclaration 1557 | |-template 1558 | |-< 1559 | |-UnknownDeclaration 1560 | | |-class 1561 | | `-T 1562 | |-> 1563 | `-SimpleDeclaration 1564 | |-struct 1565 | |-X 1566 | |-{ 1567 | |-SimpleDeclaration 1568 | | |-struct 1569 | | |-Y 1570 | | `-; 1571 | |-} 1572 | `-; 1573 `-TemplateDeclaration 1574 |-template 1575 |-< 1576 |-UnknownDeclaration 1577 | |-class 1578 | `-T 1579 |-> 1580 `-SimpleDeclaration 1581 |-struct 1582 |-X 1583 |-< 1584 |-T 1585 |-> 1586 |-:: 1587 |-Y 1588 |-{ 1589 |-} 1590 `-; 1591 )txt"); 1592 } 1593 1594 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) { 1595 if (!GetParam().isCXX()) { 1596 return; 1597 } 1598 expectTreeDumpEqual( 1599 R"cpp( 1600 template <class T> struct X { 1601 using T::foo; 1602 using typename T::bar; 1603 }; 1604 )cpp", 1605 R"txt( 1606 *: TranslationUnit 1607 `-TemplateDeclaration 1608 |-template 1609 |-< 1610 |-UnknownDeclaration 1611 | |-class 1612 | `-T 1613 |-> 1614 `-SimpleDeclaration 1615 |-struct 1616 |-X 1617 |-{ 1618 |-UsingDeclaration 1619 | |-using 1620 | |-T 1621 | |-:: 1622 | |-foo 1623 | `-; 1624 |-UsingDeclaration 1625 | |-using 1626 | |-typename 1627 | |-T 1628 | |-:: 1629 | |-bar 1630 | `-; 1631 |-} 1632 `-; 1633 )txt"); 1634 } 1635 1636 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) { 1637 if (!GetParam().isCXX()) { 1638 return; 1639 } 1640 expectTreeDumpEqual( 1641 R"cpp( 1642 template <class T> struct X {}; 1643 template <class T> struct X<T*> {}; 1644 template <> struct X<int> {}; 1645 1646 template struct X<double>; 1647 extern template struct X<float>; 1648 )cpp", 1649 R"txt( 1650 *: TranslationUnit 1651 |-TemplateDeclaration 1652 | |-template 1653 | |-< 1654 | |-UnknownDeclaration 1655 | | |-class 1656 | | `-T 1657 | |-> 1658 | `-SimpleDeclaration 1659 | |-struct 1660 | |-X 1661 | |-{ 1662 | |-} 1663 | `-; 1664 |-TemplateDeclaration 1665 | |-template 1666 | |-< 1667 | |-UnknownDeclaration 1668 | | |-class 1669 | | `-T 1670 | |-> 1671 | `-SimpleDeclaration 1672 | |-struct 1673 | |-X 1674 | |-< 1675 | |-T 1676 | |-* 1677 | |-> 1678 | |-{ 1679 | |-} 1680 | `-; 1681 |-TemplateDeclaration 1682 | |-template 1683 | |-< 1684 | |-> 1685 | `-SimpleDeclaration 1686 | |-struct 1687 | |-X 1688 | |-< 1689 | |-int 1690 | |-> 1691 | |-{ 1692 | |-} 1693 | `-; 1694 |-ExplicitTemplateInstantiation 1695 | |-template 1696 | `-SimpleDeclaration 1697 | |-struct 1698 | |-X 1699 | |-< 1700 | |-double 1701 | |-> 1702 | `-; 1703 `-ExplicitTemplateInstantiation 1704 |-extern 1705 |-template 1706 `-SimpleDeclaration 1707 |-struct 1708 |-X 1709 |-< 1710 |-float 1711 |-> 1712 `-; 1713 )txt"); 1714 } 1715 1716 TEST_P(SyntaxTreeTest, UsingType) { 1717 if (!GetParam().isCXX()) { 1718 return; 1719 } 1720 expectTreeDumpEqual( 1721 R"cpp( 1722 using type = int; 1723 )cpp", 1724 R"txt( 1725 *: TranslationUnit 1726 `-TypeAliasDeclaration 1727 |-using 1728 |-type 1729 |-= 1730 |-int 1731 `-; 1732 )txt"); 1733 } 1734 1735 TEST_P(SyntaxTreeTest, EmptyDeclaration) { 1736 expectTreeDumpEqual( 1737 R"cpp( 1738 ; 1739 )cpp", 1740 R"txt( 1741 *: TranslationUnit 1742 `-EmptyDeclaration 1743 `-; 1744 )txt"); 1745 } 1746 1747 TEST_P(SyntaxTreeTest, StaticAssert) { 1748 if (!GetParam().isCXX11OrLater()) { 1749 return; 1750 } 1751 expectTreeDumpEqual( 1752 R"cpp( 1753 static_assert(true, "message"); 1754 static_assert(true); 1755 )cpp", 1756 R"txt( 1757 *: TranslationUnit 1758 |-StaticAssertDeclaration 1759 | |-static_assert 1760 | |-( 1761 | |-UnknownExpression 1762 | | `-true 1763 | |-, 1764 | |-UnknownExpression 1765 | | `-"message" 1766 | |-) 1767 | `-; 1768 `-StaticAssertDeclaration 1769 |-static_assert 1770 |-( 1771 |-UnknownExpression 1772 | `-true 1773 |-) 1774 `-; 1775 )txt"); 1776 } 1777 1778 TEST_P(SyntaxTreeTest, ExternC) { 1779 if (!GetParam().isCXX()) { 1780 return; 1781 } 1782 expectTreeDumpEqual( 1783 R"cpp( 1784 extern "C" int a; 1785 extern "C" { int b; int c; } 1786 )cpp", 1787 R"txt( 1788 *: TranslationUnit 1789 |-LinkageSpecificationDeclaration 1790 | |-extern 1791 | |-"C" 1792 | `-SimpleDeclaration 1793 | |-int 1794 | |-SimpleDeclarator 1795 | | `-a 1796 | `-; 1797 `-LinkageSpecificationDeclaration 1798 |-extern 1799 |-"C" 1800 |-{ 1801 |-SimpleDeclaration 1802 | |-int 1803 | |-SimpleDeclarator 1804 | | `-b 1805 | `-; 1806 |-SimpleDeclaration 1807 | |-int 1808 | |-SimpleDeclarator 1809 | | `-c 1810 | `-; 1811 `-} 1812 )txt"); 1813 } 1814 1815 TEST_P(SyntaxTreeTest, NonModifiableNodes) { 1816 // Some nodes are non-modifiable, they are marked with 'I:'. 1817 expectTreeDumpEqual( 1818 R"cpp( 1819 #define HALF_IF if (1+ 1820 #define HALF_IF_2 1) {} 1821 void test() { 1822 HALF_IF HALF_IF_2 else {} 1823 })cpp", 1824 R"txt( 1825 *: TranslationUnit 1826 `-SimpleDeclaration 1827 |-void 1828 |-SimpleDeclarator 1829 | |-test 1830 | `-ParametersAndQualifiers 1831 | |-( 1832 | `-) 1833 `-CompoundStatement 1834 |-{ 1835 |-IfStatement 1836 | |-I: if 1837 | |-I: ( 1838 | |-I: BinaryOperatorExpression 1839 | | |-I: UnknownExpression 1840 | | | `-I: 1 1841 | | |-I: + 1842 | | `-I: UnknownExpression 1843 | | `-I: 1 1844 | |-I: ) 1845 | |-I: CompoundStatement 1846 | | |-I: { 1847 | | `-I: } 1848 | |-else 1849 | `-CompoundStatement 1850 | |-{ 1851 | `-} 1852 `-} 1853 )txt"); 1854 } 1855 1856 TEST_P(SyntaxTreeTest, ModifiableNodes) { 1857 // All nodes can be mutated. 1858 expectTreeDumpEqual( 1859 R"cpp( 1860 #define OPEN { 1861 #define CLOSE } 1862 1863 void test() { 1864 OPEN 1865 1; 1866 CLOSE 1867 1868 OPEN 1869 2; 1870 } 1871 } 1872 )cpp", 1873 R"txt( 1874 *: TranslationUnit 1875 `-SimpleDeclaration 1876 |-void 1877 |-SimpleDeclarator 1878 | |-test 1879 | `-ParametersAndQualifiers 1880 | |-( 1881 | `-) 1882 `-CompoundStatement 1883 |-{ 1884 |-CompoundStatement 1885 | |-{ 1886 | |-ExpressionStatement 1887 | | |-UnknownExpression 1888 | | | `-1 1889 | | `-; 1890 | `-} 1891 |-CompoundStatement 1892 | |-{ 1893 | |-ExpressionStatement 1894 | | |-UnknownExpression 1895 | | | `-2 1896 | | `-; 1897 | `-} 1898 `-} 1899 )txt"); 1900 } 1901 1902 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) { 1903 expectTreeDumpEqual( 1904 R"cpp( 1905 int a[10]; 1906 int b[1][2][3]; 1907 int c[] = {1,2,3}; 1908 )cpp", 1909 R"txt( 1910 *: TranslationUnit 1911 |-SimpleDeclaration 1912 | |-int 1913 | |-SimpleDeclarator 1914 | | |-a 1915 | | `-ArraySubscript 1916 | | |-[ 1917 | | |-UnknownExpression 1918 | | | `-10 1919 | | `-] 1920 | `-; 1921 |-SimpleDeclaration 1922 | |-int 1923 | |-SimpleDeclarator 1924 | | |-b 1925 | | |-ArraySubscript 1926 | | | |-[ 1927 | | | |-UnknownExpression 1928 | | | | `-1 1929 | | | `-] 1930 | | |-ArraySubscript 1931 | | | |-[ 1932 | | | |-UnknownExpression 1933 | | | | `-2 1934 | | | `-] 1935 | | `-ArraySubscript 1936 | | |-[ 1937 | | |-UnknownExpression 1938 | | | `-3 1939 | | `-] 1940 | `-; 1941 `-SimpleDeclaration 1942 |-int 1943 |-SimpleDeclarator 1944 | |-c 1945 | |-ArraySubscript 1946 | | |-[ 1947 | | `-] 1948 | |-= 1949 | `-UnknownExpression 1950 | `-UnknownExpression 1951 | |-{ 1952 | |-UnknownExpression 1953 | | `-1 1954 | |-, 1955 | |-UnknownExpression 1956 | | `-2 1957 | |-, 1958 | |-UnknownExpression 1959 | | `-3 1960 | `-} 1961 `-; )txt"); 1962 } 1963 1964 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) { 1965 if (!GetParam().isC99OrLater()) { 1966 return; 1967 } 1968 expectTreeDumpEqual( 1969 R"cpp( 1970 void f(int xs[static 10]); 1971 )cpp", 1972 R"txt( 1973 *: TranslationUnit 1974 `-SimpleDeclaration 1975 |-void 1976 |-SimpleDeclarator 1977 | |-f 1978 | `-ParametersAndQualifiers 1979 | |-( 1980 | |-SimpleDeclaration 1981 | | |-int 1982 | | `-SimpleDeclarator 1983 | | |-xs 1984 | | `-ArraySubscript 1985 | | |-[ 1986 | | |-static 1987 | | |-UnknownExpression 1988 | | | `-10 1989 | | `-] 1990 | `-) 1991 `-; )txt"); 1992 } 1993 1994 TEST_P(SyntaxTreeTest, ParameterListsInDeclarators) { 1995 if (!GetParam().isCXX()) { 1996 // TODO: Split parts that depend on C++ into a separate test. 1997 return; 1998 } 1999 expectTreeDumpEqual( 2000 R"cpp( 2001 struct Test { 2002 int a() const; 2003 int b() volatile; 2004 int c() &; 2005 int d() &&; 2006 int foo(int a, int b); 2007 int foo(const int a, volatile int b, const volatile int c, int* d, 2008 int& e, int&& f); 2009 }; 2010 )cpp", 2011 R"txt( 2012 *: TranslationUnit 2013 `-SimpleDeclaration 2014 |-struct 2015 |-Test 2016 |-{ 2017 |-SimpleDeclaration 2018 | |-int 2019 | |-SimpleDeclarator 2020 | | |-a 2021 | | `-ParametersAndQualifiers 2022 | | |-( 2023 | | |-) 2024 | | `-const 2025 | `-; 2026 |-SimpleDeclaration 2027 | |-int 2028 | |-SimpleDeclarator 2029 | | |-b 2030 | | `-ParametersAndQualifiers 2031 | | |-( 2032 | | |-) 2033 | | `-volatile 2034 | `-; 2035 |-SimpleDeclaration 2036 | |-int 2037 | |-SimpleDeclarator 2038 | | |-c 2039 | | `-ParametersAndQualifiers 2040 | | |-( 2041 | | |-) 2042 | | `-& 2043 | `-; 2044 |-SimpleDeclaration 2045 | |-int 2046 | |-SimpleDeclarator 2047 | | |-d 2048 | | `-ParametersAndQualifiers 2049 | | |-( 2050 | | |-) 2051 | | `-&& 2052 | `-; 2053 |-SimpleDeclaration 2054 | |-int 2055 | |-SimpleDeclarator 2056 | | |-foo 2057 | | `-ParametersAndQualifiers 2058 | | |-( 2059 | | |-SimpleDeclaration 2060 | | | |-int 2061 | | | `-SimpleDeclarator 2062 | | | `-a 2063 | | |-, 2064 | | |-SimpleDeclaration 2065 | | | |-int 2066 | | | `-SimpleDeclarator 2067 | | | `-b 2068 | | `-) 2069 | `-; 2070 |-SimpleDeclaration 2071 | |-int 2072 | |-SimpleDeclarator 2073 | | |-foo 2074 | | `-ParametersAndQualifiers 2075 | | |-( 2076 | | |-SimpleDeclaration 2077 | | | |-const 2078 | | | |-int 2079 | | | `-SimpleDeclarator 2080 | | | `-a 2081 | | |-, 2082 | | |-SimpleDeclaration 2083 | | | |-volatile 2084 | | | |-int 2085 | | | `-SimpleDeclarator 2086 | | | `-b 2087 | | |-, 2088 | | |-SimpleDeclaration 2089 | | | |-const 2090 | | | |-volatile 2091 | | | |-int 2092 | | | `-SimpleDeclarator 2093 | | | `-c 2094 | | |-, 2095 | | |-SimpleDeclaration 2096 | | | |-int 2097 | | | `-SimpleDeclarator 2098 | | | |-* 2099 | | | `-d 2100 | | |-, 2101 | | |-SimpleDeclaration 2102 | | | |-int 2103 | | | `-SimpleDeclarator 2104 | | | |-& 2105 | | | `-e 2106 | | |-, 2107 | | |-SimpleDeclaration 2108 | | | |-int 2109 | | | `-SimpleDeclarator 2110 | | | |-&& 2111 | | | `-f 2112 | | `-) 2113 | `-; 2114 |-} 2115 `-; 2116 )txt"); 2117 } 2118 2119 TEST_P(SyntaxTreeTest, TrailingConst) { 2120 if (!GetParam().isCXX()) { 2121 // TODO: Split parts that depend on C++ into a separate test. 2122 return; 2123 } 2124 expectTreeDumpEqual( 2125 R"cpp( 2126 struct X { 2127 int foo() const; 2128 }; 2129 )cpp", 2130 R"txt( 2131 *: TranslationUnit 2132 `-SimpleDeclaration 2133 |-struct 2134 |-X 2135 |-{ 2136 |-SimpleDeclaration 2137 | |-int 2138 | |-SimpleDeclarator 2139 | | |-foo 2140 | | `-ParametersAndQualifiers 2141 | | |-( 2142 | | |-) 2143 | | `-const 2144 | `-; 2145 |-} 2146 `-; 2147 )txt"); 2148 } 2149 2150 TEST_P(SyntaxTreeTest, TrailingReturn) { 2151 if (!GetParam().isCXX11OrLater()) { 2152 return; 2153 } 2154 expectTreeDumpEqual( 2155 R"cpp( 2156 auto foo() -> int; 2157 )cpp", 2158 R"txt( 2159 *: TranslationUnit 2160 `-SimpleDeclaration 2161 |-auto 2162 |-SimpleDeclarator 2163 | |-foo 2164 | `-ParametersAndQualifiers 2165 | |-( 2166 | |-) 2167 | `-TrailingReturnType 2168 | |--> 2169 | `-int 2170 `-; 2171 )txt"); 2172 } 2173 2174 TEST_P(SyntaxTreeTest, ExceptionSpecification) { 2175 if (!GetParam().isCXX11OrLater()) { 2176 // TODO: Split parts that depend on C++11 into a separate test. 2177 return; 2178 } 2179 expectTreeDumpEqual( 2180 R"cpp( 2181 int a() noexcept; 2182 int b() noexcept(true); 2183 int c() throw(); 2184 )cpp", 2185 R"txt( 2186 *: TranslationUnit 2187 |-SimpleDeclaration 2188 | |-int 2189 | |-SimpleDeclarator 2190 | | |-a 2191 | | `-ParametersAndQualifiers 2192 | | |-( 2193 | | |-) 2194 | | `-noexcept 2195 | `-; 2196 |-SimpleDeclaration 2197 | |-int 2198 | |-SimpleDeclarator 2199 | | |-b 2200 | | `-ParametersAndQualifiers 2201 | | |-( 2202 | | |-) 2203 | | |-noexcept 2204 | | |-( 2205 | | |-UnknownExpression 2206 | | | `-true 2207 | | `-) 2208 | `-; 2209 `-SimpleDeclaration 2210 |-int 2211 |-SimpleDeclarator 2212 | |-c 2213 | `-ParametersAndQualifiers 2214 | |-( 2215 | |-) 2216 | |-throw 2217 | |-( 2218 | `-) 2219 `-; 2220 )txt"); 2221 } 2222 2223 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) { 2224 expectTreeDumpEqual( 2225 R"cpp( 2226 int (a); 2227 int *(b); 2228 int (*c)(int); 2229 int *(d)(int); 2230 )cpp", 2231 R"txt( 2232 *: TranslationUnit 2233 |-SimpleDeclaration 2234 | |-int 2235 | |-SimpleDeclarator 2236 | | `-ParenDeclarator 2237 | | |-( 2238 | | |-a 2239 | | `-) 2240 | `-; 2241 |-SimpleDeclaration 2242 | |-int 2243 | |-SimpleDeclarator 2244 | | |-* 2245 | | `-ParenDeclarator 2246 | | |-( 2247 | | |-b 2248 | | `-) 2249 | `-; 2250 |-SimpleDeclaration 2251 | |-int 2252 | |-SimpleDeclarator 2253 | | |-ParenDeclarator 2254 | | | |-( 2255 | | | |-* 2256 | | | |-c 2257 | | | `-) 2258 | | `-ParametersAndQualifiers 2259 | | |-( 2260 | | |-SimpleDeclaration 2261 | | | `-int 2262 | | `-) 2263 | `-; 2264 `-SimpleDeclaration 2265 |-int 2266 |-SimpleDeclarator 2267 | |-* 2268 | |-ParenDeclarator 2269 | | |-( 2270 | | |-d 2271 | | `-) 2272 | `-ParametersAndQualifiers 2273 | |-( 2274 | |-SimpleDeclaration 2275 | | `-int 2276 | `-) 2277 `-; 2278 )txt"); 2279 } 2280 2281 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) { 2282 expectTreeDumpEqual( 2283 R"cpp( 2284 const int west = -1; 2285 int const east = 1; 2286 const int const universal = 0; 2287 const int const *const *volatile b; 2288 )cpp", 2289 R"txt( 2290 *: TranslationUnit 2291 |-SimpleDeclaration 2292 | |-const 2293 | |-int 2294 | |-SimpleDeclarator 2295 | | |-west 2296 | | |-= 2297 | | `-PrefixUnaryOperatorExpression 2298 | | |-- 2299 | | `-UnknownExpression 2300 | | `-1 2301 | `-; 2302 |-SimpleDeclaration 2303 | |-int 2304 | |-const 2305 | |-SimpleDeclarator 2306 | | |-east 2307 | | |-= 2308 | | `-UnknownExpression 2309 | | `-1 2310 | `-; 2311 |-SimpleDeclaration 2312 | |-const 2313 | |-int 2314 | |-const 2315 | |-SimpleDeclarator 2316 | | |-universal 2317 | | |-= 2318 | | `-UnknownExpression 2319 | | `-0 2320 | `-; 2321 `-SimpleDeclaration 2322 |-const 2323 |-int 2324 |-const 2325 |-SimpleDeclarator 2326 | |-* 2327 | |-const 2328 | |-* 2329 | |-volatile 2330 | `-b 2331 `-; 2332 )txt"); 2333 } 2334 2335 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) { 2336 if (!GetParam().isCXX11OrLater()) { 2337 return; 2338 } 2339 expectTreeDumpEqual( 2340 R"cpp( 2341 auto foo() -> auto(*)(int) -> double*; 2342 )cpp", 2343 R"txt( 2344 *: TranslationUnit 2345 `-SimpleDeclaration 2346 |-auto 2347 |-SimpleDeclarator 2348 | |-foo 2349 | `-ParametersAndQualifiers 2350 | |-( 2351 | |-) 2352 | `-TrailingReturnType 2353 | |--> 2354 | |-auto 2355 | `-SimpleDeclarator 2356 | |-ParenDeclarator 2357 | | |-( 2358 | | |-* 2359 | | `-) 2360 | `-ParametersAndQualifiers 2361 | |-( 2362 | |-SimpleDeclaration 2363 | | `-int 2364 | |-) 2365 | `-TrailingReturnType 2366 | |--> 2367 | |-double 2368 | `-SimpleDeclarator 2369 | `-* 2370 `-; 2371 )txt"); 2372 } 2373 2374 TEST_P(SyntaxTreeTest, MemberPointers) { 2375 if (!GetParam().isCXX()) { 2376 return; 2377 } 2378 expectTreeDumpEqual( 2379 R"cpp( 2380 struct X {}; 2381 int X::* a; 2382 const int X::* b; 2383 )cpp", 2384 R"txt( 2385 *: TranslationUnit 2386 |-SimpleDeclaration 2387 | |-struct 2388 | |-X 2389 | |-{ 2390 | |-} 2391 | `-; 2392 |-SimpleDeclaration 2393 | |-int 2394 | |-SimpleDeclarator 2395 | | |-MemberPointer 2396 | | | |-X 2397 | | | |-:: 2398 | | | `-* 2399 | | `-a 2400 | `-; 2401 `-SimpleDeclaration 2402 |-const 2403 |-int 2404 |-SimpleDeclarator 2405 | |-MemberPointer 2406 | | |-X 2407 | | |-:: 2408 | | `-* 2409 | `-b 2410 `-; 2411 )txt"); 2412 } 2413 2414 TEST_P(SyntaxTreeTest, ComplexDeclarator) { 2415 expectTreeDumpEqual( 2416 R"cpp( 2417 void x(char a, short (*b)(int)); 2418 )cpp", 2419 R"txt( 2420 *: TranslationUnit 2421 `-SimpleDeclaration 2422 |-void 2423 |-SimpleDeclarator 2424 | |-x 2425 | `-ParametersAndQualifiers 2426 | |-( 2427 | |-SimpleDeclaration 2428 | | |-char 2429 | | `-SimpleDeclarator 2430 | | `-a 2431 | |-, 2432 | |-SimpleDeclaration 2433 | | |-short 2434 | | `-SimpleDeclarator 2435 | | |-ParenDeclarator 2436 | | | |-( 2437 | | | |-* 2438 | | | |-b 2439 | | | `-) 2440 | | `-ParametersAndQualifiers 2441 | | |-( 2442 | | |-SimpleDeclaration 2443 | | | `-int 2444 | | `-) 2445 | `-) 2446 `-; 2447 )txt"); 2448 } 2449 2450 TEST_P(SyntaxTreeTest, ComplexDeclarator2) { 2451 expectTreeDumpEqual( 2452 R"cpp( 2453 void x(char a, short (*b)(int), long (**c)(long long)); 2454 )cpp", 2455 R"txt( 2456 *: TranslationUnit 2457 `-SimpleDeclaration 2458 |-void 2459 |-SimpleDeclarator 2460 | |-x 2461 | `-ParametersAndQualifiers 2462 | |-( 2463 | |-SimpleDeclaration 2464 | | |-char 2465 | | `-SimpleDeclarator 2466 | | `-a 2467 | |-, 2468 | |-SimpleDeclaration 2469 | | |-short 2470 | | `-SimpleDeclarator 2471 | | |-ParenDeclarator 2472 | | | |-( 2473 | | | |-* 2474 | | | |-b 2475 | | | `-) 2476 | | `-ParametersAndQualifiers 2477 | | |-( 2478 | | |-SimpleDeclaration 2479 | | | `-int 2480 | | `-) 2481 | |-, 2482 | |-SimpleDeclaration 2483 | | |-long 2484 | | `-SimpleDeclarator 2485 | | |-ParenDeclarator 2486 | | | |-( 2487 | | | |-* 2488 | | | |-* 2489 | | | |-c 2490 | | | `-) 2491 | | `-ParametersAndQualifiers 2492 | | |-( 2493 | | |-SimpleDeclaration 2494 | | | |-long 2495 | | | `-long 2496 | | `-) 2497 | `-) 2498 `-; 2499 )txt"); 2500 } 2501 2502 TEST_P(SyntaxTreeTest, Mutations) { 2503 if (!GetParam().isCXX11OrLater()) { 2504 return; 2505 } 2506 2507 using Transformation = std::function<void( 2508 const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>; 2509 auto CheckTransformation = [this](std::string Input, std::string Expected, 2510 Transformation Transform) -> void { 2511 llvm::Annotations Source(Input); 2512 auto *Root = buildTree(Source.code(), GetParam()); 2513 2514 Transform(Source, Root); 2515 2516 auto Replacements = syntax::computeReplacements(*Arena, *Root); 2517 auto Output = tooling::applyAllReplacements(Source.code(), Replacements); 2518 if (!Output) { 2519 ADD_FAILURE() << "could not apply replacements: " 2520 << llvm::toString(Output.takeError()); 2521 return; 2522 } 2523 2524 EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; 2525 }; 2526 2527 // Removes the selected statement. Input should have exactly one selected 2528 // range and it should correspond to a single statement. 2529 auto RemoveStatement = [this](const llvm::Annotations &Input, 2530 syntax::TranslationUnit *TU) { 2531 auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU)); 2532 ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 2533 syntax::removeStatement(*Arena, S); 2534 EXPECT_TRUE(S->isDetached()); 2535 EXPECT_FALSE(S->isOriginal()) 2536 << "node removed from tree cannot be marked as original"; 2537 }; 2538 2539 std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>> 2540 Cases = { 2541 {"void test() { [[100+100;]] test(); }", "void test() { test(); }"}, 2542 {"void test() { if (true) [[{}]] else {} }", 2543 "void test() { if (true) ; else {} }"}, 2544 {"void test() { [[;]] }", "void test() { }"}}; 2545 for (const auto &C : Cases) 2546 CheckTransformation(C.first, C.second, RemoveStatement); 2547 } 2548 2549 TEST_P(SyntaxTreeTest, SynthesizedNodes) { 2550 buildTree("", GetParam()); 2551 2552 auto *C = syntax::createPunctuation(*Arena, tok::comma); 2553 ASSERT_NE(C, nullptr); 2554 EXPECT_EQ(C->token()->kind(), tok::comma); 2555 EXPECT_TRUE(C->canModify()); 2556 EXPECT_FALSE(C->isOriginal()); 2557 EXPECT_TRUE(C->isDetached()); 2558 2559 auto *S = syntax::createEmptyStatement(*Arena); 2560 ASSERT_NE(S, nullptr); 2561 EXPECT_TRUE(S->canModify()); 2562 EXPECT_FALSE(S->isOriginal()); 2563 EXPECT_TRUE(S->isDetached()); 2564 } 2565 2566 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest, 2567 testing::ValuesIn(TestClangConfig::allConfigs())); 2568 2569 } // namespace 2570