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