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