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