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