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