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