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