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 |-NestedNameSpecifier 2977 | `-:: 2978 |-ns 2979 `-; 2980 )txt")); 2981 } 2982 2983 TEST_P(SyntaxTreeTest, UsingDeclaration) { 2984 if (!GetParam().isCXX()) { 2985 return; 2986 } 2987 EXPECT_TRUE(treeDumpEqual( 2988 R"cpp( 2989 namespace ns { int a; } 2990 using ns::a; 2991 )cpp", 2992 R"txt( 2993 *: TranslationUnit 2994 |-NamespaceDefinition 2995 | |-namespace 2996 | |-ns 2997 | |-{ 2998 | |-SimpleDeclaration 2999 | | |-int 3000 | | |-SimpleDeclarator 3001 | | | `-a 3002 | | `-; 3003 | `-} 3004 `-UsingDeclaration 3005 |-using 3006 |-NestedNameSpecifier 3007 | |-IdentifierNameSpecifier 3008 | | `-ns 3009 | `-:: 3010 |-a 3011 `-; 3012 )txt")); 3013 } 3014 3015 TEST_P(SyntaxTreeTest, FreeStandingClasses) { 3016 // Free-standing classes, must live inside a SimpleDeclaration. 3017 EXPECT_TRUE(treeDumpEqual( 3018 R"cpp( 3019 struct X; 3020 struct X {}; 3021 3022 struct Y *y1; 3023 struct Y {} *y2; 3024 3025 struct {} *a1; 3026 )cpp", 3027 R"txt( 3028 *: TranslationUnit 3029 |-SimpleDeclaration 3030 | |-struct 3031 | |-X 3032 | `-; 3033 |-SimpleDeclaration 3034 | |-struct 3035 | |-X 3036 | |-{ 3037 | |-} 3038 | `-; 3039 |-SimpleDeclaration 3040 | |-struct 3041 | |-Y 3042 | |-SimpleDeclarator 3043 | | |-* 3044 | | `-y1 3045 | `-; 3046 |-SimpleDeclaration 3047 | |-struct 3048 | |-Y 3049 | |-{ 3050 | |-} 3051 | |-SimpleDeclarator 3052 | | |-* 3053 | | `-y2 3054 | `-; 3055 `-SimpleDeclaration 3056 |-struct 3057 |-{ 3058 |-} 3059 |-SimpleDeclarator 3060 | |-* 3061 | `-a1 3062 `-; 3063 )txt")); 3064 } 3065 3066 TEST_P(SyntaxTreeTest, Templates) { 3067 if (!GetParam().isCXX()) { 3068 return; 3069 } 3070 if (GetParam().hasDelayedTemplateParsing()) { 3071 // FIXME: Make this test work on Windows by generating the expected syntax 3072 // tree when `-fdelayed-template-parsing` is active. 3073 return; 3074 } 3075 EXPECT_TRUE(treeDumpEqual( 3076 R"cpp( 3077 template <class T> struct cls {}; 3078 template <class T> int var = 10; 3079 template <class T> int fun() {} 3080 )cpp", 3081 R"txt( 3082 *: TranslationUnit 3083 |-TemplateDeclaration 3084 | |-template 3085 | |-< 3086 | |-UnknownDeclaration 3087 | | |-class 3088 | | `-T 3089 | |-> 3090 | `-SimpleDeclaration 3091 | |-struct 3092 | |-cls 3093 | |-{ 3094 | |-} 3095 | `-; 3096 |-TemplateDeclaration 3097 | |-template 3098 | |-< 3099 | |-UnknownDeclaration 3100 | | |-class 3101 | | `-T 3102 | |-> 3103 | `-SimpleDeclaration 3104 | |-int 3105 | |-SimpleDeclarator 3106 | | |-var 3107 | | |-= 3108 | | `-IntegerLiteralExpression 3109 | | `-10 3110 | `-; 3111 `-TemplateDeclaration 3112 |-template 3113 |-< 3114 |-UnknownDeclaration 3115 | |-class 3116 | `-T 3117 |-> 3118 `-SimpleDeclaration 3119 |-int 3120 |-SimpleDeclarator 3121 | |-fun 3122 | `-ParametersAndQualifiers 3123 | |-( 3124 | `-) 3125 `-CompoundStatement 3126 |-{ 3127 `-} 3128 )txt")); 3129 } 3130 3131 TEST_P(SyntaxTreeTest, NestedTemplates) { 3132 if (!GetParam().isCXX()) { 3133 return; 3134 } 3135 EXPECT_TRUE(treeDumpEqual( 3136 R"cpp( 3137 template <class T> 3138 struct X { 3139 template <class U> 3140 U foo(); 3141 }; 3142 )cpp", 3143 R"txt( 3144 *: TranslationUnit 3145 `-TemplateDeclaration 3146 |-template 3147 |-< 3148 |-UnknownDeclaration 3149 | |-class 3150 | `-T 3151 |-> 3152 `-SimpleDeclaration 3153 |-struct 3154 |-X 3155 |-{ 3156 |-TemplateDeclaration 3157 | |-template 3158 | |-< 3159 | |-UnknownDeclaration 3160 | | |-class 3161 | | `-U 3162 | |-> 3163 | `-SimpleDeclaration 3164 | |-U 3165 | |-SimpleDeclarator 3166 | | |-foo 3167 | | `-ParametersAndQualifiers 3168 | | |-( 3169 | | `-) 3170 | `-; 3171 |-} 3172 `-; 3173 )txt")); 3174 } 3175 3176 TEST_P(SyntaxTreeTest, Templates2) { 3177 if (!GetParam().isCXX()) { 3178 return; 3179 } 3180 EXPECT_TRUE(treeDumpEqual( 3181 R"cpp( 3182 template <class T> struct X { struct Y; }; 3183 template <class T> struct X<T>::Y {}; 3184 )cpp", 3185 R"txt( 3186 *: TranslationUnit 3187 |-TemplateDeclaration 3188 | |-template 3189 | |-< 3190 | |-UnknownDeclaration 3191 | | |-class 3192 | | `-T 3193 | |-> 3194 | `-SimpleDeclaration 3195 | |-struct 3196 | |-X 3197 | |-{ 3198 | |-SimpleDeclaration 3199 | | |-struct 3200 | | |-Y 3201 | | `-; 3202 | |-} 3203 | `-; 3204 `-TemplateDeclaration 3205 |-template 3206 |-< 3207 |-UnknownDeclaration 3208 | |-class 3209 | `-T 3210 |-> 3211 `-SimpleDeclaration 3212 |-struct 3213 |-NestedNameSpecifier 3214 | |-SimpleTemplateNameSpecifier 3215 | | |-X 3216 | | |-< 3217 | | |-T 3218 | | `-> 3219 | `-:: 3220 |-Y 3221 |-{ 3222 |-} 3223 `-; 3224 )txt")); 3225 } 3226 3227 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) { 3228 if (!GetParam().isCXX()) { 3229 return; 3230 } 3231 EXPECT_TRUE(treeDumpEqual( 3232 R"cpp( 3233 template <class T> struct X { 3234 using T::foo; 3235 using typename T::bar; 3236 }; 3237 )cpp", 3238 R"txt( 3239 *: TranslationUnit 3240 `-TemplateDeclaration 3241 |-template 3242 |-< 3243 |-UnknownDeclaration 3244 | |-class 3245 | `-T 3246 |-> 3247 `-SimpleDeclaration 3248 |-struct 3249 |-X 3250 |-{ 3251 |-UsingDeclaration 3252 | |-using 3253 | |-NestedNameSpecifier 3254 | | |-IdentifierNameSpecifier 3255 | | | `-T 3256 | | `-:: 3257 | |-foo 3258 | `-; 3259 |-UsingDeclaration 3260 | |-using 3261 | |-typename 3262 | |-NestedNameSpecifier 3263 | | |-IdentifierNameSpecifier 3264 | | | `-T 3265 | | `-:: 3266 | |-bar 3267 | `-; 3268 |-} 3269 `-; 3270 )txt")); 3271 } 3272 3273 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) { 3274 if (!GetParam().isCXX()) { 3275 return; 3276 } 3277 EXPECT_TRUE(treeDumpEqual( 3278 R"cpp( 3279 template <class T> struct X {}; 3280 template <class T> struct X<T*> {}; 3281 template <> struct X<int> {}; 3282 3283 template struct X<double>; 3284 extern template struct X<float>; 3285 )cpp", 3286 R"txt( 3287 *: TranslationUnit 3288 |-TemplateDeclaration 3289 | |-template 3290 | |-< 3291 | |-UnknownDeclaration 3292 | | |-class 3293 | | `-T 3294 | |-> 3295 | `-SimpleDeclaration 3296 | |-struct 3297 | |-X 3298 | |-{ 3299 | |-} 3300 | `-; 3301 |-TemplateDeclaration 3302 | |-template 3303 | |-< 3304 | |-UnknownDeclaration 3305 | | |-class 3306 | | `-T 3307 | |-> 3308 | `-SimpleDeclaration 3309 | |-struct 3310 | |-X 3311 | |-< 3312 | |-T 3313 | |-* 3314 | |-> 3315 | |-{ 3316 | |-} 3317 | `-; 3318 |-TemplateDeclaration 3319 | |-template 3320 | |-< 3321 | |-> 3322 | `-SimpleDeclaration 3323 | |-struct 3324 | |-X 3325 | |-< 3326 | |-int 3327 | |-> 3328 | |-{ 3329 | |-} 3330 | `-; 3331 |-ExplicitTemplateInstantiation 3332 | |-template 3333 | `-SimpleDeclaration 3334 | |-struct 3335 | |-X 3336 | |-< 3337 | |-double 3338 | |-> 3339 | `-; 3340 `-ExplicitTemplateInstantiation 3341 |-extern 3342 |-template 3343 `-SimpleDeclaration 3344 |-struct 3345 |-X 3346 |-< 3347 |-float 3348 |-> 3349 `-; 3350 )txt")); 3351 } 3352 3353 TEST_P(SyntaxTreeTest, UsingType) { 3354 if (!GetParam().isCXX()) { 3355 return; 3356 } 3357 EXPECT_TRUE(treeDumpEqual( 3358 R"cpp( 3359 using type = int; 3360 )cpp", 3361 R"txt( 3362 *: TranslationUnit 3363 `-TypeAliasDeclaration 3364 |-using 3365 |-type 3366 |-= 3367 |-int 3368 `-; 3369 )txt")); 3370 } 3371 3372 TEST_P(SyntaxTreeTest, EmptyDeclaration) { 3373 EXPECT_TRUE(treeDumpEqual( 3374 R"cpp( 3375 ; 3376 )cpp", 3377 R"txt( 3378 *: TranslationUnit 3379 `-EmptyDeclaration 3380 `-; 3381 )txt")); 3382 } 3383 3384 TEST_P(SyntaxTreeTest, StaticAssert) { 3385 if (!GetParam().isCXX11OrLater()) { 3386 return; 3387 } 3388 EXPECT_TRUE(treeDumpEqual( 3389 R"cpp( 3390 static_assert(true, "message"); 3391 static_assert(true); 3392 )cpp", 3393 R"txt( 3394 *: TranslationUnit 3395 |-StaticAssertDeclaration 3396 | |-static_assert 3397 | |-( 3398 | |-BoolLiteralExpression 3399 | | `-true 3400 | |-, 3401 | |-StringLiteralExpression 3402 | | `-"message" 3403 | |-) 3404 | `-; 3405 `-StaticAssertDeclaration 3406 |-static_assert 3407 |-( 3408 |-BoolLiteralExpression 3409 | `-true 3410 |-) 3411 `-; 3412 )txt")); 3413 } 3414 3415 TEST_P(SyntaxTreeTest, ExternC) { 3416 if (!GetParam().isCXX()) { 3417 return; 3418 } 3419 EXPECT_TRUE(treeDumpEqual( 3420 R"cpp( 3421 extern "C" int a; 3422 extern "C" { int b; int c; } 3423 )cpp", 3424 R"txt( 3425 *: TranslationUnit 3426 |-LinkageSpecificationDeclaration 3427 | |-extern 3428 | |-"C" 3429 | `-SimpleDeclaration 3430 | |-int 3431 | |-SimpleDeclarator 3432 | | `-a 3433 | `-; 3434 `-LinkageSpecificationDeclaration 3435 |-extern 3436 |-"C" 3437 |-{ 3438 |-SimpleDeclaration 3439 | |-int 3440 | |-SimpleDeclarator 3441 | | `-b 3442 | `-; 3443 |-SimpleDeclaration 3444 | |-int 3445 | |-SimpleDeclarator 3446 | | `-c 3447 | `-; 3448 `-} 3449 )txt")); 3450 } 3451 3452 TEST_P(SyntaxTreeTest, NonModifiableNodes) { 3453 // Some nodes are non-modifiable, they are marked with 'I:'. 3454 EXPECT_TRUE(treeDumpEqual( 3455 R"cpp( 3456 #define HALF_IF if (1+ 3457 #define HALF_IF_2 1) {} 3458 void test() { 3459 HALF_IF HALF_IF_2 else {} 3460 })cpp", 3461 R"txt( 3462 *: TranslationUnit 3463 `-SimpleDeclaration 3464 |-void 3465 |-SimpleDeclarator 3466 | |-test 3467 | `-ParametersAndQualifiers 3468 | |-( 3469 | `-) 3470 `-CompoundStatement 3471 |-{ 3472 |-IfStatement 3473 | |-I: if 3474 | |-I: ( 3475 | |-I: BinaryOperatorExpression 3476 | | |-I: IntegerLiteralExpression 3477 | | | `-I: 1 3478 | | |-I: + 3479 | | `-I: IntegerLiteralExpression 3480 | | `-I: 1 3481 | |-I: ) 3482 | |-I: CompoundStatement 3483 | | |-I: { 3484 | | `-I: } 3485 | |-else 3486 | `-CompoundStatement 3487 | |-{ 3488 | `-} 3489 `-} 3490 )txt")); 3491 } 3492 3493 TEST_P(SyntaxTreeTest, ModifiableNodes) { 3494 // All nodes can be mutated. 3495 EXPECT_TRUE(treeDumpEqual( 3496 R"cpp( 3497 #define OPEN { 3498 #define CLOSE } 3499 3500 void test() { 3501 OPEN 3502 1; 3503 CLOSE 3504 3505 OPEN 3506 2; 3507 } 3508 } 3509 )cpp", 3510 R"txt( 3511 *: TranslationUnit 3512 `-SimpleDeclaration 3513 |-void 3514 |-SimpleDeclarator 3515 | |-test 3516 | `-ParametersAndQualifiers 3517 | |-( 3518 | `-) 3519 `-CompoundStatement 3520 |-{ 3521 |-CompoundStatement 3522 | |-{ 3523 | |-ExpressionStatement 3524 | | |-IntegerLiteralExpression 3525 | | | `-1 3526 | | `-; 3527 | `-} 3528 |-CompoundStatement 3529 | |-{ 3530 | |-ExpressionStatement 3531 | | |-IntegerLiteralExpression 3532 | | | `-2 3533 | | `-; 3534 | `-} 3535 `-} 3536 )txt")); 3537 } 3538 3539 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) { 3540 EXPECT_TRUE(treeDumpEqual( 3541 R"cpp( 3542 int a[10]; 3543 int b[1][2][3]; 3544 int c[] = {1,2,3}; 3545 )cpp", 3546 R"txt( 3547 *: TranslationUnit 3548 |-SimpleDeclaration 3549 | |-int 3550 | |-SimpleDeclarator 3551 | | |-a 3552 | | `-ArraySubscript 3553 | | |-[ 3554 | | |-IntegerLiteralExpression 3555 | | | `-10 3556 | | `-] 3557 | `-; 3558 |-SimpleDeclaration 3559 | |-int 3560 | |-SimpleDeclarator 3561 | | |-b 3562 | | |-ArraySubscript 3563 | | | |-[ 3564 | | | |-IntegerLiteralExpression 3565 | | | | `-1 3566 | | | `-] 3567 | | |-ArraySubscript 3568 | | | |-[ 3569 | | | |-IntegerLiteralExpression 3570 | | | | `-2 3571 | | | `-] 3572 | | `-ArraySubscript 3573 | | |-[ 3574 | | |-IntegerLiteralExpression 3575 | | | `-3 3576 | | `-] 3577 | `-; 3578 `-SimpleDeclaration 3579 |-int 3580 |-SimpleDeclarator 3581 | |-c 3582 | |-ArraySubscript 3583 | | |-[ 3584 | | `-] 3585 | |-= 3586 | `-UnknownExpression 3587 | `-UnknownExpression 3588 | |-{ 3589 | |-IntegerLiteralExpression 3590 | | `-1 3591 | |-, 3592 | |-IntegerLiteralExpression 3593 | | `-2 3594 | |-, 3595 | |-IntegerLiteralExpression 3596 | | `-3 3597 | `-} 3598 `-; 3599 )txt")); 3600 } 3601 3602 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) { 3603 if (!GetParam().isC99OrLater()) { 3604 return; 3605 } 3606 EXPECT_TRUE(treeDumpEqual( 3607 R"cpp( 3608 void f(int xs[static 10]); 3609 )cpp", 3610 R"txt( 3611 *: TranslationUnit 3612 `-SimpleDeclaration 3613 |-void 3614 |-SimpleDeclarator 3615 | |-f 3616 | `-ParametersAndQualifiers 3617 | |-( 3618 | |-SimpleDeclaration 3619 | | |-int 3620 | | `-SimpleDeclarator 3621 | | |-xs 3622 | | `-ArraySubscript 3623 | | |-[ 3624 | | |-static 3625 | | |-IntegerLiteralExpression 3626 | | | `-10 3627 | | `-] 3628 | `-) 3629 `-; 3630 )txt")); 3631 } 3632 3633 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) { 3634 if (!GetParam().isCXX()) { 3635 return; 3636 } 3637 EXPECT_TRUE(treeDumpEqual( 3638 R"cpp( 3639 int func1(); 3640 int func2a(int a); 3641 int func2b(int); 3642 int func3a(int *ap); 3643 int func3b(int *); 3644 int func4a(int a, float b); 3645 int func4b(int, float); 3646 )cpp", 3647 R"txt( 3648 *: TranslationUnit 3649 |-SimpleDeclaration 3650 | |-int 3651 | |-SimpleDeclarator 3652 | | |-func1 3653 | | `-ParametersAndQualifiers 3654 | | |-( 3655 | | `-) 3656 | `-; 3657 |-SimpleDeclaration 3658 | |-int 3659 | |-SimpleDeclarator 3660 | | |-func2a 3661 | | `-ParametersAndQualifiers 3662 | | |-( 3663 | | |-SimpleDeclaration 3664 | | | |-int 3665 | | | `-SimpleDeclarator 3666 | | | `-a 3667 | | `-) 3668 | `-; 3669 |-SimpleDeclaration 3670 | |-int 3671 | |-SimpleDeclarator 3672 | | |-func2b 3673 | | `-ParametersAndQualifiers 3674 | | |-( 3675 | | |-SimpleDeclaration 3676 | | | `-int 3677 | | `-) 3678 | `-; 3679 |-SimpleDeclaration 3680 | |-int 3681 | |-SimpleDeclarator 3682 | | |-func3a 3683 | | `-ParametersAndQualifiers 3684 | | |-( 3685 | | |-SimpleDeclaration 3686 | | | |-int 3687 | | | `-SimpleDeclarator 3688 | | | |-* 3689 | | | `-ap 3690 | | `-) 3691 | `-; 3692 |-SimpleDeclaration 3693 | |-int 3694 | |-SimpleDeclarator 3695 | | |-func3b 3696 | | `-ParametersAndQualifiers 3697 | | |-( 3698 | | |-SimpleDeclaration 3699 | | | |-int 3700 | | | `-SimpleDeclarator 3701 | | | `-* 3702 | | `-) 3703 | `-; 3704 |-SimpleDeclaration 3705 | |-int 3706 | |-SimpleDeclarator 3707 | | |-func4a 3708 | | `-ParametersAndQualifiers 3709 | | |-( 3710 | | |-SimpleDeclaration 3711 | | | |-int 3712 | | | `-SimpleDeclarator 3713 | | | `-a 3714 | | |-, 3715 | | |-SimpleDeclaration 3716 | | | |-float 3717 | | | `-SimpleDeclarator 3718 | | | `-b 3719 | | `-) 3720 | `-; 3721 `-SimpleDeclaration 3722 |-int 3723 |-SimpleDeclarator 3724 | |-func4b 3725 | `-ParametersAndQualifiers 3726 | |-( 3727 | |-SimpleDeclaration 3728 | | `-int 3729 | |-, 3730 | |-SimpleDeclaration 3731 | | `-float 3732 | `-) 3733 `-; 3734 )txt")); 3735 } 3736 3737 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) { 3738 if (!GetParam().isCXX()) { 3739 return; 3740 } 3741 EXPECT_TRUE(treeDumpEqual( 3742 R"cpp( 3743 int func1(const int a, volatile int b, const volatile int c); 3744 int func2(int& a); 3745 )cpp", 3746 R"txt( 3747 *: TranslationUnit 3748 |-SimpleDeclaration 3749 | |-int 3750 | |-SimpleDeclarator 3751 | | |-func1 3752 | | `-ParametersAndQualifiers 3753 | | |-( 3754 | | |-SimpleDeclaration 3755 | | | |-const 3756 | | | |-int 3757 | | | `-SimpleDeclarator 3758 | | | `-a 3759 | | |-, 3760 | | |-SimpleDeclaration 3761 | | | |-volatile 3762 | | | |-int 3763 | | | `-SimpleDeclarator 3764 | | | `-b 3765 | | |-, 3766 | | |-SimpleDeclaration 3767 | | | |-const 3768 | | | |-volatile 3769 | | | |-int 3770 | | | `-SimpleDeclarator 3771 | | | `-c 3772 | | `-) 3773 | `-; 3774 `-SimpleDeclaration 3775 |-int 3776 |-SimpleDeclarator 3777 | |-func2 3778 | `-ParametersAndQualifiers 3779 | |-( 3780 | |-SimpleDeclaration 3781 | | |-int 3782 | | `-SimpleDeclarator 3783 | | |-& 3784 | | `-a 3785 | `-) 3786 `-; 3787 )txt")); 3788 } 3789 3790 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) { 3791 if (!GetParam().isCXX11OrLater()) { 3792 return; 3793 } 3794 EXPECT_TRUE(treeDumpEqual( 3795 R"cpp( 3796 int func1(int&& a); 3797 )cpp", 3798 R"txt( 3799 *: TranslationUnit 3800 `-SimpleDeclaration 3801 |-int 3802 |-SimpleDeclarator 3803 | |-func1 3804 | `-ParametersAndQualifiers 3805 | |-( 3806 | |-SimpleDeclaration 3807 | | |-int 3808 | | `-SimpleDeclarator 3809 | | |-&& 3810 | | `-a 3811 | `-) 3812 `-; 3813 )txt")); 3814 } 3815 3816 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) { 3817 if (!GetParam().isCXX()) { 3818 return; 3819 } 3820 EXPECT_TRUE(treeDumpEqual( 3821 R"cpp( 3822 struct Test { 3823 int a(); 3824 int b() const; 3825 int c() volatile; 3826 int d() const volatile; 3827 int e() &; 3828 int f() &&; 3829 }; 3830 )cpp", 3831 R"txt( 3832 *: TranslationUnit 3833 `-SimpleDeclaration 3834 |-struct 3835 |-Test 3836 |-{ 3837 |-SimpleDeclaration 3838 | |-int 3839 | |-SimpleDeclarator 3840 | | |-a 3841 | | `-ParametersAndQualifiers 3842 | | |-( 3843 | | `-) 3844 | `-; 3845 |-SimpleDeclaration 3846 | |-int 3847 | |-SimpleDeclarator 3848 | | |-b 3849 | | `-ParametersAndQualifiers 3850 | | |-( 3851 | | |-) 3852 | | `-const 3853 | `-; 3854 |-SimpleDeclaration 3855 | |-int 3856 | |-SimpleDeclarator 3857 | | |-c 3858 | | `-ParametersAndQualifiers 3859 | | |-( 3860 | | |-) 3861 | | `-volatile 3862 | `-; 3863 |-SimpleDeclaration 3864 | |-int 3865 | |-SimpleDeclarator 3866 | | |-d 3867 | | `-ParametersAndQualifiers 3868 | | |-( 3869 | | |-) 3870 | | |-const 3871 | | `-volatile 3872 | `-; 3873 |-SimpleDeclaration 3874 | |-int 3875 | |-SimpleDeclarator 3876 | | |-e 3877 | | `-ParametersAndQualifiers 3878 | | |-( 3879 | | |-) 3880 | | `-& 3881 | `-; 3882 |-SimpleDeclaration 3883 | |-int 3884 | |-SimpleDeclarator 3885 | | |-f 3886 | | `-ParametersAndQualifiers 3887 | | |-( 3888 | | |-) 3889 | | `-&& 3890 | `-; 3891 |-} 3892 `-; 3893 )txt")); 3894 } 3895 3896 TEST_P(SyntaxTreeTest, TrailingReturn) { 3897 if (!GetParam().isCXX11OrLater()) { 3898 return; 3899 } 3900 EXPECT_TRUE(treeDumpEqual( 3901 R"cpp( 3902 auto foo() -> int; 3903 )cpp", 3904 R"txt( 3905 *: TranslationUnit 3906 `-SimpleDeclaration 3907 |-auto 3908 |-SimpleDeclarator 3909 | |-foo 3910 | `-ParametersAndQualifiers 3911 | |-( 3912 | |-) 3913 | `-TrailingReturnType 3914 | |--> 3915 | `-int 3916 `-; 3917 )txt")); 3918 } 3919 3920 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) { 3921 if (!GetParam().supportsCXXDynamicExceptionSpecification()) { 3922 return; 3923 } 3924 EXPECT_TRUE(treeDumpEqual( 3925 R"cpp( 3926 struct MyException1 {}; 3927 struct MyException2 {}; 3928 int a() throw(); 3929 int b() throw(...); 3930 int c() throw(MyException1); 3931 int d() throw(MyException1, MyException2); 3932 )cpp", 3933 R"txt( 3934 *: TranslationUnit 3935 |-SimpleDeclaration 3936 | |-struct 3937 | |-MyException1 3938 | |-{ 3939 | |-} 3940 | `-; 3941 |-SimpleDeclaration 3942 | |-struct 3943 | |-MyException2 3944 | |-{ 3945 | |-} 3946 | `-; 3947 |-SimpleDeclaration 3948 | |-int 3949 | |-SimpleDeclarator 3950 | | |-a 3951 | | `-ParametersAndQualifiers 3952 | | |-( 3953 | | |-) 3954 | | |-throw 3955 | | |-( 3956 | | `-) 3957 | `-; 3958 |-SimpleDeclaration 3959 | |-int 3960 | |-SimpleDeclarator 3961 | | |-b 3962 | | `-ParametersAndQualifiers 3963 | | |-( 3964 | | |-) 3965 | | |-throw 3966 | | |-( 3967 | | |-... 3968 | | `-) 3969 | `-; 3970 |-SimpleDeclaration 3971 | |-int 3972 | |-SimpleDeclarator 3973 | | |-c 3974 | | `-ParametersAndQualifiers 3975 | | |-( 3976 | | |-) 3977 | | |-throw 3978 | | |-( 3979 | | |-MyException1 3980 | | `-) 3981 | `-; 3982 `-SimpleDeclaration 3983 |-int 3984 |-SimpleDeclarator 3985 | |-d 3986 | `-ParametersAndQualifiers 3987 | |-( 3988 | |-) 3989 | |-throw 3990 | |-( 3991 | |-MyException1 3992 | |-, 3993 | |-MyException2 3994 | `-) 3995 `-; 3996 )txt")); 3997 } 3998 3999 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) { 4000 if (!GetParam().isCXX11OrLater()) { 4001 return; 4002 } 4003 EXPECT_TRUE(treeDumpEqual( 4004 R"cpp( 4005 int a() noexcept; 4006 int b() noexcept(true); 4007 )cpp", 4008 R"txt( 4009 *: TranslationUnit 4010 |-SimpleDeclaration 4011 | |-int 4012 | |-SimpleDeclarator 4013 | | |-a 4014 | | `-ParametersAndQualifiers 4015 | | |-( 4016 | | |-) 4017 | | `-noexcept 4018 | `-; 4019 `-SimpleDeclaration 4020 |-int 4021 |-SimpleDeclarator 4022 | |-b 4023 | `-ParametersAndQualifiers 4024 | |-( 4025 | |-) 4026 | |-noexcept 4027 | |-( 4028 | |-BoolLiteralExpression 4029 | | `-true 4030 | `-) 4031 `-; 4032 )txt")); 4033 } 4034 4035 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) { 4036 EXPECT_TRUE(treeDumpEqual( 4037 R"cpp( 4038 int (a); 4039 int *(b); 4040 int (*c)(int); 4041 int *(d)(int); 4042 )cpp", 4043 R"txt( 4044 *: TranslationUnit 4045 |-SimpleDeclaration 4046 | |-int 4047 | |-SimpleDeclarator 4048 | | `-ParenDeclarator 4049 | | |-( 4050 | | |-a 4051 | | `-) 4052 | `-; 4053 |-SimpleDeclaration 4054 | |-int 4055 | |-SimpleDeclarator 4056 | | |-* 4057 | | `-ParenDeclarator 4058 | | |-( 4059 | | |-b 4060 | | `-) 4061 | `-; 4062 |-SimpleDeclaration 4063 | |-int 4064 | |-SimpleDeclarator 4065 | | |-ParenDeclarator 4066 | | | |-( 4067 | | | |-* 4068 | | | |-c 4069 | | | `-) 4070 | | `-ParametersAndQualifiers 4071 | | |-( 4072 | | |-SimpleDeclaration 4073 | | | `-int 4074 | | `-) 4075 | `-; 4076 `-SimpleDeclaration 4077 |-int 4078 |-SimpleDeclarator 4079 | |-* 4080 | |-ParenDeclarator 4081 | | |-( 4082 | | |-d 4083 | | `-) 4084 | `-ParametersAndQualifiers 4085 | |-( 4086 | |-SimpleDeclaration 4087 | | `-int 4088 | `-) 4089 `-; 4090 )txt")); 4091 } 4092 4093 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) { 4094 EXPECT_TRUE(treeDumpEqual( 4095 R"cpp( 4096 const int west = -1; 4097 int const east = 1; 4098 const int const universal = 0; 4099 const int const *const *volatile b; 4100 )cpp", 4101 R"txt( 4102 *: TranslationUnit 4103 |-SimpleDeclaration 4104 | |-const 4105 | |-int 4106 | |-SimpleDeclarator 4107 | | |-west 4108 | | |-= 4109 | | `-PrefixUnaryOperatorExpression 4110 | | |-- 4111 | | `-IntegerLiteralExpression 4112 | | `-1 4113 | `-; 4114 |-SimpleDeclaration 4115 | |-int 4116 | |-const 4117 | |-SimpleDeclarator 4118 | | |-east 4119 | | |-= 4120 | | `-IntegerLiteralExpression 4121 | | `-1 4122 | `-; 4123 |-SimpleDeclaration 4124 | |-const 4125 | |-int 4126 | |-const 4127 | |-SimpleDeclarator 4128 | | |-universal 4129 | | |-= 4130 | | `-IntegerLiteralExpression 4131 | | `-0 4132 | `-; 4133 `-SimpleDeclaration 4134 |-const 4135 |-int 4136 |-const 4137 |-SimpleDeclarator 4138 | |-* 4139 | |-const 4140 | |-* 4141 | |-volatile 4142 | `-b 4143 `-; 4144 )txt")); 4145 } 4146 4147 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) { 4148 if (!GetParam().isCXX11OrLater()) { 4149 return; 4150 } 4151 EXPECT_TRUE(treeDumpEqual( 4152 R"cpp( 4153 auto foo() -> auto(*)(int) -> double*; 4154 )cpp", 4155 R"txt( 4156 *: TranslationUnit 4157 `-SimpleDeclaration 4158 |-auto 4159 |-SimpleDeclarator 4160 | |-foo 4161 | `-ParametersAndQualifiers 4162 | |-( 4163 | |-) 4164 | `-TrailingReturnType 4165 | |--> 4166 | |-auto 4167 | `-SimpleDeclarator 4168 | |-ParenDeclarator 4169 | | |-( 4170 | | |-* 4171 | | `-) 4172 | `-ParametersAndQualifiers 4173 | |-( 4174 | |-SimpleDeclaration 4175 | | `-int 4176 | |-) 4177 | `-TrailingReturnType 4178 | |--> 4179 | |-double 4180 | `-SimpleDeclarator 4181 | `-* 4182 `-; 4183 )txt")); 4184 } 4185 4186 TEST_P(SyntaxTreeTest, MemberPointers) { 4187 if (!GetParam().isCXX()) { 4188 return; 4189 } 4190 EXPECT_TRUE(treeDumpEqual( 4191 R"cpp( 4192 struct X {}; 4193 int X::* a; 4194 const int X::* b; 4195 )cpp", 4196 R"txt( 4197 *: TranslationUnit 4198 |-SimpleDeclaration 4199 | |-struct 4200 | |-X 4201 | |-{ 4202 | |-} 4203 | `-; 4204 |-SimpleDeclaration 4205 | |-int 4206 | |-SimpleDeclarator 4207 | | |-MemberPointer 4208 | | | |-X 4209 | | | |-:: 4210 | | | `-* 4211 | | `-a 4212 | `-; 4213 `-SimpleDeclaration 4214 |-const 4215 |-int 4216 |-SimpleDeclarator 4217 | |-MemberPointer 4218 | | |-X 4219 | | |-:: 4220 | | `-* 4221 | `-b 4222 `-; 4223 )txt")); 4224 } 4225 4226 TEST_P(SyntaxTreeTest, MemberFunctionPointer) { 4227 if (!GetParam().isCXX()) { 4228 return; 4229 } 4230 EXPECT_TRUE(treeDumpEqual( 4231 R"cpp( 4232 struct X { 4233 struct Y {}; 4234 }; 4235 void (X::*xp)(); 4236 void (X::**xpp)(const int*); 4237 // FIXME: Generate the right syntax tree for this type, 4238 // i.e. create a syntax node for the outer member pointer 4239 void (X::Y::*xyp)(const int*, char); 4240 )cpp", 4241 R"txt( 4242 *: TranslationUnit 4243 |-SimpleDeclaration 4244 | |-struct 4245 | |-X 4246 | |-{ 4247 | |-SimpleDeclaration 4248 | | |-struct 4249 | | |-Y 4250 | | |-{ 4251 | | |-} 4252 | | `-; 4253 | |-} 4254 | `-; 4255 |-SimpleDeclaration 4256 | |-void 4257 | |-SimpleDeclarator 4258 | | |-ParenDeclarator 4259 | | | |-( 4260 | | | |-MemberPointer 4261 | | | | |-X 4262 | | | | |-:: 4263 | | | | `-* 4264 | | | |-xp 4265 | | | `-) 4266 | | `-ParametersAndQualifiers 4267 | | |-( 4268 | | `-) 4269 | `-; 4270 |-SimpleDeclaration 4271 | |-void 4272 | |-SimpleDeclarator 4273 | | |-ParenDeclarator 4274 | | | |-( 4275 | | | |-MemberPointer 4276 | | | | |-X 4277 | | | | |-:: 4278 | | | | `-* 4279 | | | |-* 4280 | | | |-xpp 4281 | | | `-) 4282 | | `-ParametersAndQualifiers 4283 | | |-( 4284 | | |-SimpleDeclaration 4285 | | | |-const 4286 | | | |-int 4287 | | | `-SimpleDeclarator 4288 | | | `-* 4289 | | `-) 4290 | `-; 4291 `-SimpleDeclaration 4292 |-void 4293 |-SimpleDeclarator 4294 | |-ParenDeclarator 4295 | | |-( 4296 | | |-X 4297 | | |-:: 4298 | | |-MemberPointer 4299 | | | |-Y 4300 | | | |-:: 4301 | | | `-* 4302 | | |-xyp 4303 | | `-) 4304 | `-ParametersAndQualifiers 4305 | |-( 4306 | |-SimpleDeclaration 4307 | | |-const 4308 | | |-int 4309 | | `-SimpleDeclarator 4310 | | `-* 4311 | |-, 4312 | |-SimpleDeclaration 4313 | | `-char 4314 | `-) 4315 `-; 4316 )txt")); 4317 } 4318 4319 TEST_P(SyntaxTreeTest, ComplexDeclarator) { 4320 EXPECT_TRUE(treeDumpEqual( 4321 R"cpp( 4322 void x(char a, short (*b)(int)); 4323 )cpp", 4324 R"txt( 4325 *: TranslationUnit 4326 `-SimpleDeclaration 4327 |-void 4328 |-SimpleDeclarator 4329 | |-x 4330 | `-ParametersAndQualifiers 4331 | |-( 4332 | |-SimpleDeclaration 4333 | | |-char 4334 | | `-SimpleDeclarator 4335 | | `-a 4336 | |-, 4337 | |-SimpleDeclaration 4338 | | |-short 4339 | | `-SimpleDeclarator 4340 | | |-ParenDeclarator 4341 | | | |-( 4342 | | | |-* 4343 | | | |-b 4344 | | | `-) 4345 | | `-ParametersAndQualifiers 4346 | | |-( 4347 | | |-SimpleDeclaration 4348 | | | `-int 4349 | | `-) 4350 | `-) 4351 `-; 4352 )txt")); 4353 } 4354 4355 TEST_P(SyntaxTreeTest, ComplexDeclarator2) { 4356 EXPECT_TRUE(treeDumpEqual( 4357 R"cpp( 4358 void x(char a, short (*b)(int), long (**c)(long long)); 4359 )cpp", 4360 R"txt( 4361 *: TranslationUnit 4362 `-SimpleDeclaration 4363 |-void 4364 |-SimpleDeclarator 4365 | |-x 4366 | `-ParametersAndQualifiers 4367 | |-( 4368 | |-SimpleDeclaration 4369 | | |-char 4370 | | `-SimpleDeclarator 4371 | | `-a 4372 | |-, 4373 | |-SimpleDeclaration 4374 | | |-short 4375 | | `-SimpleDeclarator 4376 | | |-ParenDeclarator 4377 | | | |-( 4378 | | | |-* 4379 | | | |-b 4380 | | | `-) 4381 | | `-ParametersAndQualifiers 4382 | | |-( 4383 | | |-SimpleDeclaration 4384 | | | `-int 4385 | | `-) 4386 | |-, 4387 | |-SimpleDeclaration 4388 | | |-long 4389 | | `-SimpleDeclarator 4390 | | |-ParenDeclarator 4391 | | | |-( 4392 | | | |-* 4393 | | | |-* 4394 | | | |-c 4395 | | | `-) 4396 | | `-ParametersAndQualifiers 4397 | | |-( 4398 | | |-SimpleDeclaration 4399 | | | |-long 4400 | | | `-long 4401 | | `-) 4402 | `-) 4403 `-; 4404 )txt")); 4405 } 4406 4407 TEST_P(SyntaxTreeTest, Mutations) { 4408 if (!GetParam().isCXX11OrLater()) { 4409 return; 4410 } 4411 4412 using Transformation = std::function<void( 4413 const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>; 4414 auto CheckTransformation = [this](std::string Input, std::string Expected, 4415 Transformation Transform) -> void { 4416 llvm::Annotations Source(Input); 4417 auto *Root = buildTree(Source.code(), GetParam()); 4418 4419 Transform(Source, Root); 4420 4421 auto Replacements = syntax::computeReplacements(*Arena, *Root); 4422 auto Output = tooling::applyAllReplacements(Source.code(), Replacements); 4423 if (!Output) { 4424 ADD_FAILURE() << "could not apply replacements: " 4425 << llvm::toString(Output.takeError()); 4426 return; 4427 } 4428 4429 EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; 4430 }; 4431 4432 // Removes the selected statement. Input should have exactly one selected 4433 // range and it should correspond to a single statement. 4434 auto RemoveStatement = [this](const llvm::Annotations &Input, 4435 syntax::TranslationUnit *TU) { 4436 auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU)); 4437 ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 4438 syntax::removeStatement(*Arena, S); 4439 EXPECT_TRUE(S->isDetached()); 4440 EXPECT_FALSE(S->isOriginal()) 4441 << "node removed from tree cannot be marked as original"; 4442 }; 4443 4444 std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>> 4445 Cases = { 4446 {"void test() { [[100+100;]] test(); }", "void test() { test(); }"}, 4447 {"void test() { if (true) [[{}]] else {} }", 4448 "void test() { if (true) ; else {} }"}, 4449 {"void test() { [[;]] }", "void test() { }"}}; 4450 for (const auto &C : Cases) 4451 CheckTransformation(C.first, C.second, RemoveStatement); 4452 } 4453 4454 TEST_P(SyntaxTreeTest, SynthesizedNodes) { 4455 buildTree("", GetParam()); 4456 4457 auto *C = syntax::createPunctuation(*Arena, tok::comma); 4458 ASSERT_NE(C, nullptr); 4459 EXPECT_EQ(C->token()->kind(), tok::comma); 4460 EXPECT_TRUE(C->canModify()); 4461 EXPECT_FALSE(C->isOriginal()); 4462 EXPECT_TRUE(C->isDetached()); 4463 4464 auto *S = syntax::createEmptyStatement(*Arena); 4465 ASSERT_NE(S, nullptr); 4466 EXPECT_TRUE(S->canModify()); 4467 EXPECT_FALSE(S->isOriginal()); 4468 EXPECT_TRUE(S->isDetached()); 4469 } 4470 4471 static std::vector<TestClangConfig> allTestClangConfigs() { 4472 std::vector<TestClangConfig> all_configs; 4473 for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11, 4474 Lang_CXX14, Lang_CXX17, Lang_CXX20}) { 4475 TestClangConfig config; 4476 config.Language = lang; 4477 config.Target = "x86_64-pc-linux-gnu"; 4478 all_configs.push_back(config); 4479 4480 // Windows target is interesting to test because it enables 4481 // `-fdelayed-template-parsing`. 4482 config.Target = "x86_64-pc-win32-msvc"; 4483 all_configs.push_back(config); 4484 } 4485 return all_configs; 4486 } 4487 4488 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest, 4489 testing::ValuesIn(allTestClangConfigs()), ); 4490 4491 } // namespace 4492