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, IntegerLiteral) { 1133 EXPECT_TRUE(treeDumpEqual( 1134 R"cpp( 1135 void test() { 1136 12; 1137 12u; 1138 12l; 1139 12ul; 1140 014; 1141 0XC; 1142 } 1143 )cpp", 1144 R"txt( 1145 *: TranslationUnit 1146 `-SimpleDeclaration 1147 |-void 1148 |-SimpleDeclarator 1149 | |-test 1150 | `-ParametersAndQualifiers 1151 | |-( 1152 | `-) 1153 `-CompoundStatement 1154 |-{ 1155 |-ExpressionStatement 1156 | |-IntegerLiteralExpression 1157 | | `-12 1158 | `-; 1159 |-ExpressionStatement 1160 | |-IntegerLiteralExpression 1161 | | `-12u 1162 | `-; 1163 |-ExpressionStatement 1164 | |-IntegerLiteralExpression 1165 | | `-12l 1166 | `-; 1167 |-ExpressionStatement 1168 | |-IntegerLiteralExpression 1169 | | `-12ul 1170 | `-; 1171 |-ExpressionStatement 1172 | |-IntegerLiteralExpression 1173 | | `-014 1174 | `-; 1175 |-ExpressionStatement 1176 | |-IntegerLiteralExpression 1177 | | `-0XC 1178 | `-; 1179 `-} 1180 )txt")); 1181 } 1182 1183 TEST_P(SyntaxTreeTest, IntegerLiteralLongLong) { 1184 if (!GetParam().isCXX11OrLater()) { 1185 return; 1186 } 1187 EXPECT_TRUE(treeDumpEqual( 1188 R"cpp( 1189 void test() { 1190 12ll; 1191 12ull; 1192 } 1193 )cpp", 1194 R"txt( 1195 *: TranslationUnit 1196 `-SimpleDeclaration 1197 |-void 1198 |-SimpleDeclarator 1199 | |-test 1200 | `-ParametersAndQualifiers 1201 | |-( 1202 | `-) 1203 `-CompoundStatement 1204 |-{ 1205 |-ExpressionStatement 1206 | |-IntegerLiteralExpression 1207 | | `-12ll 1208 | `-; 1209 |-ExpressionStatement 1210 | |-IntegerLiteralExpression 1211 | | `-12ull 1212 | `-; 1213 `-} 1214 )txt")); 1215 } 1216 1217 TEST_P(SyntaxTreeTest, IntegerLiteralBinary) { 1218 if (!GetParam().isCXX14OrLater()) { 1219 return; 1220 } 1221 EXPECT_TRUE(treeDumpEqual( 1222 R"cpp( 1223 void test() { 1224 0b1100; 1225 } 1226 )cpp", 1227 R"txt( 1228 *: TranslationUnit 1229 `-SimpleDeclaration 1230 |-void 1231 |-SimpleDeclarator 1232 | |-test 1233 | `-ParametersAndQualifiers 1234 | |-( 1235 | `-) 1236 `-CompoundStatement 1237 |-{ 1238 |-ExpressionStatement 1239 | |-IntegerLiteralExpression 1240 | | `-0b1100 1241 | `-; 1242 `-} 1243 )txt")); 1244 } 1245 1246 TEST_P(SyntaxTreeTest, IntegerLiteralWithDigitSeparators) { 1247 if (!GetParam().isCXX14OrLater()) { 1248 return; 1249 } 1250 EXPECT_TRUE(treeDumpEqual( 1251 R"cpp( 1252 void test() { 1253 1'2'0ull; 1254 } 1255 )cpp", 1256 R"txt( 1257 *: TranslationUnit 1258 `-SimpleDeclaration 1259 |-void 1260 |-SimpleDeclarator 1261 | |-test 1262 | `-ParametersAndQualifiers 1263 | |-( 1264 | `-) 1265 `-CompoundStatement 1266 |-{ 1267 |-ExpressionStatement 1268 | |-IntegerLiteralExpression 1269 | | `-1'2'0ull 1270 | `-; 1271 `-} 1272 )txt")); 1273 } 1274 1275 TEST_P(SyntaxTreeTest, CharacterLiteral) { 1276 EXPECT_TRUE(treeDumpEqual( 1277 R"cpp( 1278 void test() { 1279 'a'; 1280 '\n'; 1281 '\x20'; 1282 '\0'; 1283 L'a'; 1284 L'α'; 1285 } 1286 )cpp", 1287 R"txt( 1288 *: TranslationUnit 1289 `-SimpleDeclaration 1290 |-void 1291 |-SimpleDeclarator 1292 | |-test 1293 | `-ParametersAndQualifiers 1294 | |-( 1295 | `-) 1296 `-CompoundStatement 1297 |-{ 1298 |-ExpressionStatement 1299 | |-CharacterLiteralExpression 1300 | | `-'a' 1301 | `-; 1302 |-ExpressionStatement 1303 | |-CharacterLiteralExpression 1304 | | `-'\n' 1305 | `-; 1306 |-ExpressionStatement 1307 | |-CharacterLiteralExpression 1308 | | `-'\x20' 1309 | `-; 1310 |-ExpressionStatement 1311 | |-CharacterLiteralExpression 1312 | | `-'\0' 1313 | `-; 1314 |-ExpressionStatement 1315 | |-CharacterLiteralExpression 1316 | | `-L'a' 1317 | `-; 1318 |-ExpressionStatement 1319 | |-CharacterLiteralExpression 1320 | | `-L'α' 1321 | `-; 1322 `-} 1323 )txt")); 1324 } 1325 1326 TEST_P(SyntaxTreeTest, CharacterLiteralUtf) { 1327 if (!GetParam().isCXX11OrLater()) { 1328 return; 1329 } 1330 EXPECT_TRUE(treeDumpEqual( 1331 R"cpp( 1332 void test() { 1333 u'a'; 1334 u'構'; 1335 U'a'; 1336 U''; 1337 } 1338 )cpp", 1339 R"txt( 1340 *: TranslationUnit 1341 `-SimpleDeclaration 1342 |-void 1343 |-SimpleDeclarator 1344 | |-test 1345 | `-ParametersAndQualifiers 1346 | |-( 1347 | `-) 1348 `-CompoundStatement 1349 |-{ 1350 |-ExpressionStatement 1351 | |-CharacterLiteralExpression 1352 | | `-u'a' 1353 | `-; 1354 |-ExpressionStatement 1355 | |-CharacterLiteralExpression 1356 | | `-u'構' 1357 | `-; 1358 |-ExpressionStatement 1359 | |-CharacterLiteralExpression 1360 | | `-U'a' 1361 | `-; 1362 |-ExpressionStatement 1363 | |-CharacterLiteralExpression 1364 | | `-U'' 1365 | `-; 1366 `-} 1367 )txt")); 1368 } 1369 1370 TEST_P(SyntaxTreeTest, CharacterLiteralUtf8) { 1371 if (!GetParam().isCXX17OrLater()) { 1372 return; 1373 } 1374 EXPECT_TRUE(treeDumpEqual( 1375 R"cpp( 1376 void test() { 1377 u8'a'; 1378 u8'\x7f'; 1379 } 1380 )cpp", 1381 R"txt( 1382 *: TranslationUnit 1383 `-SimpleDeclaration 1384 |-void 1385 |-SimpleDeclarator 1386 | |-test 1387 | `-ParametersAndQualifiers 1388 | |-( 1389 | `-) 1390 `-CompoundStatement 1391 |-{ 1392 |-ExpressionStatement 1393 | |-CharacterLiteralExpression 1394 | | `-u8'a' 1395 | `-; 1396 |-ExpressionStatement 1397 | |-CharacterLiteralExpression 1398 | | `-u8'\x7f' 1399 | `-; 1400 `-} 1401 )txt")); 1402 } 1403 1404 TEST_P(SyntaxTreeTest, FloatingLiteral) { 1405 EXPECT_TRUE(treeDumpEqual( 1406 R"cpp( 1407 void test() { 1408 1e-2; 1409 2.; 1410 .2; 1411 2.f; 1412 } 1413 )cpp", 1414 R"txt( 1415 *: TranslationUnit 1416 `-SimpleDeclaration 1417 |-void 1418 |-SimpleDeclarator 1419 | |-test 1420 | `-ParametersAndQualifiers 1421 | |-( 1422 | `-) 1423 `-CompoundStatement 1424 |-{ 1425 |-ExpressionStatement 1426 | |-FloatingLiteralExpression 1427 | | `-1e-2 1428 | `-; 1429 |-ExpressionStatement 1430 | |-FloatingLiteralExpression 1431 | | `-2. 1432 | `-; 1433 |-ExpressionStatement 1434 | |-FloatingLiteralExpression 1435 | | `-.2 1436 | `-; 1437 |-ExpressionStatement 1438 | |-FloatingLiteralExpression 1439 | | `-2.f 1440 | `-; 1441 `-} 1442 )txt")); 1443 } 1444 1445 TEST_P(SyntaxTreeTest, FloatingLiteralHexadecimal) { 1446 if (!GetParam().isCXX17OrLater()) { 1447 return; 1448 } 1449 EXPECT_TRUE(treeDumpEqual( 1450 R"cpp( 1451 void test() { 1452 0xfp1; 1453 0xf.p1; 1454 0x.fp1; 1455 0xf.fp1f; 1456 } 1457 )cpp", 1458 R"txt( 1459 *: TranslationUnit 1460 `-SimpleDeclaration 1461 |-void 1462 |-SimpleDeclarator 1463 | |-test 1464 | `-ParametersAndQualifiers 1465 | |-( 1466 | `-) 1467 `-CompoundStatement 1468 |-{ 1469 |-ExpressionStatement 1470 | |-FloatingLiteralExpression 1471 | | `-0xfp1 1472 | `-; 1473 |-ExpressionStatement 1474 | |-FloatingLiteralExpression 1475 | | `-0xf.p1 1476 | `-; 1477 |-ExpressionStatement 1478 | |-FloatingLiteralExpression 1479 | | `-0x.fp1 1480 | `-; 1481 |-ExpressionStatement 1482 | |-FloatingLiteralExpression 1483 | | `-0xf.fp1f 1484 | `-; 1485 `-} 1486 )txt")); 1487 } 1488 1489 TEST_P(SyntaxTreeTest, StringLiteral) { 1490 EXPECT_TRUE(treeDumpEqual( 1491 R"cpp( 1492 void test() { 1493 "a\n\0\x20"; 1494 L"αβ"; 1495 } 1496 )cpp", 1497 R"txt( 1498 *: TranslationUnit 1499 `-SimpleDeclaration 1500 |-void 1501 |-SimpleDeclarator 1502 | |-test 1503 | `-ParametersAndQualifiers 1504 | |-( 1505 | `-) 1506 `-CompoundStatement 1507 |-{ 1508 |-ExpressionStatement 1509 | |-StringLiteralExpression 1510 | | `-"a\n\0\x20" 1511 | `-; 1512 |-ExpressionStatement 1513 | |-StringLiteralExpression 1514 | | `-L"αβ" 1515 | `-; 1516 `-} 1517 )txt")); 1518 } 1519 1520 TEST_P(SyntaxTreeTest, StringLiteralUtf) { 1521 if (!GetParam().isCXX11OrLater()) { 1522 return; 1523 } 1524 EXPECT_TRUE(treeDumpEqual( 1525 R"cpp( 1526 void test() { 1527 u8"a\x1f\x05"; 1528 u"C++抽象構文木"; 1529 U"\n"; 1530 } 1531 )cpp", 1532 R"txt( 1533 *: TranslationUnit 1534 `-SimpleDeclaration 1535 |-void 1536 |-SimpleDeclarator 1537 | |-test 1538 | `-ParametersAndQualifiers 1539 | |-( 1540 | `-) 1541 `-CompoundStatement 1542 |-{ 1543 |-ExpressionStatement 1544 | |-StringLiteralExpression 1545 | | `-u8"a\x1f\x05" 1546 | `-; 1547 |-ExpressionStatement 1548 | |-StringLiteralExpression 1549 | | `-u"C++抽象構文木" 1550 | `-; 1551 |-ExpressionStatement 1552 | |-StringLiteralExpression 1553 | | `-U"\n" 1554 | `-; 1555 `-} 1556 )txt")); 1557 } 1558 1559 TEST_P(SyntaxTreeTest, StringLiteralRaw) { 1560 if (!GetParam().isCXX11OrLater()) { 1561 return; 1562 } 1563 // This test uses regular string literals instead of raw string literals to 1564 // hold source code and expected output because of a bug in MSVC up to MSVC 1565 // 2019 16.2: 1566 // https://developercommunity.visualstudio.com/content/problem/67300/stringifying-raw-string-literal.html 1567 EXPECT_TRUE(treeDumpEqual( // 1568 "void test() {\n" 1569 " R\"SyntaxTree(\n" 1570 " Hello \"Syntax\" \\\"\n" 1571 " )SyntaxTree\";\n" 1572 "}\n", 1573 "*: TranslationUnit\n" 1574 "`-SimpleDeclaration\n" 1575 " |-void\n" 1576 " |-SimpleDeclarator\n" 1577 " | |-test\n" 1578 " | `-ParametersAndQualifiers\n" 1579 " | |-(\n" 1580 " | `-)\n" 1581 " `-CompoundStatement\n" 1582 " |-{\n" 1583 " |-ExpressionStatement\n" 1584 " | |-StringLiteralExpression\n" 1585 " | | `-R\"SyntaxTree(\n" 1586 " Hello \"Syntax\" \\\"\n" 1587 " )SyntaxTree\"\n" 1588 " | `-;\n" 1589 " `-}\n")); 1590 } 1591 1592 TEST_P(SyntaxTreeTest, BoolLiteral) { 1593 if (GetParam().isC()) { 1594 return; 1595 } 1596 EXPECT_TRUE(treeDumpEqual( 1597 R"cpp( 1598 void test() { 1599 true; 1600 false; 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 | |-BoolLiteralExpression 1616 | | `-true 1617 | `-; 1618 |-ExpressionStatement 1619 | |-BoolLiteralExpression 1620 | | `-false 1621 | `-; 1622 `-} 1623 )txt")); 1624 } 1625 1626 TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) { 1627 if (!GetParam().isCXX11OrLater()) { 1628 return; 1629 } 1630 EXPECT_TRUE(treeDumpEqual( 1631 R"cpp( 1632 void test() { 1633 nullptr; 1634 } 1635 )cpp", 1636 R"txt( 1637 *: TranslationUnit 1638 `-SimpleDeclaration 1639 |-void 1640 |-SimpleDeclarator 1641 | |-test 1642 | `-ParametersAndQualifiers 1643 | |-( 1644 | `-) 1645 `-CompoundStatement 1646 |-{ 1647 |-ExpressionStatement 1648 | |-CxxNullPtrExpression 1649 | | `-nullptr 1650 | `-; 1651 `-} 1652 )txt")); 1653 } 1654 1655 TEST_P(SyntaxTreeTest, PostfixUnaryOperator) { 1656 EXPECT_TRUE(treeDumpEqual( 1657 R"cpp( 1658 void test(int a) { 1659 a++; 1660 a--; 1661 } 1662 )cpp", 1663 R"txt( 1664 *: TranslationUnit 1665 `-SimpleDeclaration 1666 |-void 1667 |-SimpleDeclarator 1668 | |-test 1669 | `-ParametersAndQualifiers 1670 | |-( 1671 | |-SimpleDeclaration 1672 | | |-int 1673 | | `-SimpleDeclarator 1674 | | `-a 1675 | `-) 1676 `-CompoundStatement 1677 |-{ 1678 |-ExpressionStatement 1679 | |-PostfixUnaryOperatorExpression 1680 | | |-IdExpression 1681 | | | `-UnqualifiedId 1682 | | | `-a 1683 | | `-++ 1684 | `-; 1685 |-ExpressionStatement 1686 | |-PostfixUnaryOperatorExpression 1687 | | |-IdExpression 1688 | | | `-UnqualifiedId 1689 | | | `-a 1690 | | `--- 1691 | `-; 1692 `-} 1693 )txt")); 1694 } 1695 1696 TEST_P(SyntaxTreeTest, PrefixUnaryOperator) { 1697 EXPECT_TRUE(treeDumpEqual( 1698 R"cpp( 1699 void test(int a, int *ap) { 1700 --a; ++a; 1701 ~a; 1702 -a; 1703 +a; 1704 &a; 1705 *ap; 1706 !a; 1707 __real a; __imag a; 1708 } 1709 )cpp", 1710 R"txt( 1711 *: TranslationUnit 1712 `-SimpleDeclaration 1713 |-void 1714 |-SimpleDeclarator 1715 | |-test 1716 | `-ParametersAndQualifiers 1717 | |-( 1718 | |-SimpleDeclaration 1719 | | |-int 1720 | | `-SimpleDeclarator 1721 | | `-a 1722 | |-, 1723 | |-SimpleDeclaration 1724 | | |-int 1725 | | `-SimpleDeclarator 1726 | | |-* 1727 | | `-ap 1728 | `-) 1729 `-CompoundStatement 1730 |-{ 1731 |-ExpressionStatement 1732 | |-PrefixUnaryOperatorExpression 1733 | | |--- 1734 | | `-IdExpression 1735 | | `-UnqualifiedId 1736 | | `-a 1737 | `-; 1738 |-ExpressionStatement 1739 | |-PrefixUnaryOperatorExpression 1740 | | |-++ 1741 | | `-IdExpression 1742 | | `-UnqualifiedId 1743 | | `-a 1744 | `-; 1745 |-ExpressionStatement 1746 | |-PrefixUnaryOperatorExpression 1747 | | |-~ 1748 | | `-IdExpression 1749 | | `-UnqualifiedId 1750 | | `-a 1751 | `-; 1752 |-ExpressionStatement 1753 | |-PrefixUnaryOperatorExpression 1754 | | |-- 1755 | | `-IdExpression 1756 | | `-UnqualifiedId 1757 | | `-a 1758 | `-; 1759 |-ExpressionStatement 1760 | |-PrefixUnaryOperatorExpression 1761 | | |-+ 1762 | | `-IdExpression 1763 | | `-UnqualifiedId 1764 | | `-a 1765 | `-; 1766 |-ExpressionStatement 1767 | |-PrefixUnaryOperatorExpression 1768 | | |-& 1769 | | `-IdExpression 1770 | | `-UnqualifiedId 1771 | | `-a 1772 | `-; 1773 |-ExpressionStatement 1774 | |-PrefixUnaryOperatorExpression 1775 | | |-* 1776 | | `-IdExpression 1777 | | `-UnqualifiedId 1778 | | `-ap 1779 | `-; 1780 |-ExpressionStatement 1781 | |-PrefixUnaryOperatorExpression 1782 | | |-! 1783 | | `-IdExpression 1784 | | `-UnqualifiedId 1785 | | `-a 1786 | `-; 1787 |-ExpressionStatement 1788 | |-PrefixUnaryOperatorExpression 1789 | | |-__real 1790 | | `-IdExpression 1791 | | `-UnqualifiedId 1792 | | `-a 1793 | `-; 1794 |-ExpressionStatement 1795 | |-PrefixUnaryOperatorExpression 1796 | | |-__imag 1797 | | `-IdExpression 1798 | | `-UnqualifiedId 1799 | | `-a 1800 | `-; 1801 `-} 1802 )txt")); 1803 } 1804 1805 TEST_P(SyntaxTreeTest, PrefixUnaryOperatorCxx) { 1806 if (!GetParam().isCXX()) { 1807 return; 1808 } 1809 EXPECT_TRUE(treeDumpEqual( 1810 R"cpp( 1811 void test(int a, bool b) { 1812 compl a; 1813 not b; 1814 } 1815 )cpp", 1816 R"txt( 1817 *: TranslationUnit 1818 `-SimpleDeclaration 1819 |-void 1820 |-SimpleDeclarator 1821 | |-test 1822 | `-ParametersAndQualifiers 1823 | |-( 1824 | |-SimpleDeclaration 1825 | | |-int 1826 | | `-SimpleDeclarator 1827 | | `-a 1828 | |-, 1829 | |-SimpleDeclaration 1830 | | |-bool 1831 | | `-SimpleDeclarator 1832 | | `-b 1833 | `-) 1834 `-CompoundStatement 1835 |-{ 1836 |-ExpressionStatement 1837 | |-PrefixUnaryOperatorExpression 1838 | | |-compl 1839 | | `-IdExpression 1840 | | `-UnqualifiedId 1841 | | `-a 1842 | `-; 1843 |-ExpressionStatement 1844 | |-PrefixUnaryOperatorExpression 1845 | | |-not 1846 | | `-IdExpression 1847 | | `-UnqualifiedId 1848 | | `-b 1849 | `-; 1850 `-} 1851 )txt")); 1852 } 1853 1854 TEST_P(SyntaxTreeTest, BinaryOperator) { 1855 EXPECT_TRUE(treeDumpEqual( 1856 R"cpp( 1857 void test(int a) { 1858 1 - 2; 1859 1 == 2; 1860 a = 1; 1861 a <<= 1; 1862 1 || 0; 1863 1 & 2; 1864 a ^= 3; 1865 } 1866 )cpp", 1867 R"txt( 1868 *: TranslationUnit 1869 `-SimpleDeclaration 1870 |-void 1871 |-SimpleDeclarator 1872 | |-test 1873 | `-ParametersAndQualifiers 1874 | |-( 1875 | |-SimpleDeclaration 1876 | | |-int 1877 | | `-SimpleDeclarator 1878 | | `-a 1879 | `-) 1880 `-CompoundStatement 1881 |-{ 1882 |-ExpressionStatement 1883 | |-BinaryOperatorExpression 1884 | | |-IntegerLiteralExpression 1885 | | | `-1 1886 | | |-- 1887 | | `-IntegerLiteralExpression 1888 | | `-2 1889 | `-; 1890 |-ExpressionStatement 1891 | |-BinaryOperatorExpression 1892 | | |-IntegerLiteralExpression 1893 | | | `-1 1894 | | |-== 1895 | | `-IntegerLiteralExpression 1896 | | `-2 1897 | `-; 1898 |-ExpressionStatement 1899 | |-BinaryOperatorExpression 1900 | | |-IdExpression 1901 | | | `-UnqualifiedId 1902 | | | `-a 1903 | | |-= 1904 | | `-IntegerLiteralExpression 1905 | | `-1 1906 | `-; 1907 |-ExpressionStatement 1908 | |-BinaryOperatorExpression 1909 | | |-IdExpression 1910 | | | `-UnqualifiedId 1911 | | | `-a 1912 | | |-<<= 1913 | | `-IntegerLiteralExpression 1914 | | `-1 1915 | `-; 1916 |-ExpressionStatement 1917 | |-BinaryOperatorExpression 1918 | | |-IntegerLiteralExpression 1919 | | | `-1 1920 | | |-|| 1921 | | `-IntegerLiteralExpression 1922 | | `-0 1923 | `-; 1924 |-ExpressionStatement 1925 | |-BinaryOperatorExpression 1926 | | |-IntegerLiteralExpression 1927 | | | `-1 1928 | | |-& 1929 | | `-IntegerLiteralExpression 1930 | | `-2 1931 | `-; 1932 |-ExpressionStatement 1933 | |-BinaryOperatorExpression 1934 | | |-IdExpression 1935 | | | `-UnqualifiedId 1936 | | | `-a 1937 | | |-^= 1938 | | `-IntegerLiteralExpression 1939 | | `-3 1940 | `-; 1941 `-} 1942 )txt")); 1943 } 1944 1945 TEST_P(SyntaxTreeTest, BinaryOperatorCxx) { 1946 if (!GetParam().isCXX()) { 1947 return; 1948 } 1949 EXPECT_TRUE(treeDumpEqual( 1950 R"cpp( 1951 void test(int a) { 1952 true || false; 1953 true or false; 1954 1 bitand 2; 1955 a xor_eq 3; 1956 } 1957 )cpp", 1958 R"txt( 1959 *: TranslationUnit 1960 `-SimpleDeclaration 1961 |-void 1962 |-SimpleDeclarator 1963 | |-test 1964 | `-ParametersAndQualifiers 1965 | |-( 1966 | |-SimpleDeclaration 1967 | | |-int 1968 | | `-SimpleDeclarator 1969 | | `-a 1970 | `-) 1971 `-CompoundStatement 1972 |-{ 1973 |-ExpressionStatement 1974 | |-BinaryOperatorExpression 1975 | | |-BoolLiteralExpression 1976 | | | `-true 1977 | | |-|| 1978 | | `-BoolLiteralExpression 1979 | | `-false 1980 | `-; 1981 |-ExpressionStatement 1982 | |-BinaryOperatorExpression 1983 | | |-BoolLiteralExpression 1984 | | | `-true 1985 | | |-or 1986 | | `-BoolLiteralExpression 1987 | | `-false 1988 | `-; 1989 |-ExpressionStatement 1990 | |-BinaryOperatorExpression 1991 | | |-IntegerLiteralExpression 1992 | | | `-1 1993 | | |-bitand 1994 | | `-IntegerLiteralExpression 1995 | | `-2 1996 | `-; 1997 |-ExpressionStatement 1998 | |-BinaryOperatorExpression 1999 | | |-IdExpression 2000 | | | `-UnqualifiedId 2001 | | | `-a 2002 | | |-xor_eq 2003 | | `-IntegerLiteralExpression 2004 | | `-3 2005 | `-; 2006 `-} 2007 )txt")); 2008 } 2009 2010 TEST_P(SyntaxTreeTest, NestedBinaryOperator) { 2011 EXPECT_TRUE(treeDumpEqual( 2012 R"cpp( 2013 void test(int a, int b) { 2014 (1 + 2) * (4 / 2); 2015 a + b + 42; 2016 a = b = 42; 2017 a + b * 4 + 2; 2018 a % 2 + b * 42; 2019 } 2020 )cpp", 2021 R"txt( 2022 *: TranslationUnit 2023 `-SimpleDeclaration 2024 |-void 2025 |-SimpleDeclarator 2026 | |-test 2027 | `-ParametersAndQualifiers 2028 | |-( 2029 | |-SimpleDeclaration 2030 | | |-int 2031 | | `-SimpleDeclarator 2032 | | `-a 2033 | |-, 2034 | |-SimpleDeclaration 2035 | | |-int 2036 | | `-SimpleDeclarator 2037 | | `-b 2038 | `-) 2039 `-CompoundStatement 2040 |-{ 2041 |-ExpressionStatement 2042 | |-BinaryOperatorExpression 2043 | | |-UnknownExpression 2044 | | | |-( 2045 | | | |-BinaryOperatorExpression 2046 | | | | |-IntegerLiteralExpression 2047 | | | | | `-1 2048 | | | | |-+ 2049 | | | | `-IntegerLiteralExpression 2050 | | | | `-2 2051 | | | `-) 2052 | | |-* 2053 | | `-UnknownExpression 2054 | | |-( 2055 | | |-BinaryOperatorExpression 2056 | | | |-IntegerLiteralExpression 2057 | | | | `-4 2058 | | | |-/ 2059 | | | `-IntegerLiteralExpression 2060 | | | `-2 2061 | | `-) 2062 | `-; 2063 |-ExpressionStatement 2064 | |-BinaryOperatorExpression 2065 | | |-BinaryOperatorExpression 2066 | | | |-IdExpression 2067 | | | | `-UnqualifiedId 2068 | | | | `-a 2069 | | | |-+ 2070 | | | `-IdExpression 2071 | | | `-UnqualifiedId 2072 | | | `-b 2073 | | |-+ 2074 | | `-IntegerLiteralExpression 2075 | | `-42 2076 | `-; 2077 |-ExpressionStatement 2078 | |-BinaryOperatorExpression 2079 | | |-IdExpression 2080 | | | `-UnqualifiedId 2081 | | | `-a 2082 | | |-= 2083 | | `-BinaryOperatorExpression 2084 | | |-IdExpression 2085 | | | `-UnqualifiedId 2086 | | | `-b 2087 | | |-= 2088 | | `-IntegerLiteralExpression 2089 | | `-42 2090 | `-; 2091 |-ExpressionStatement 2092 | |-BinaryOperatorExpression 2093 | | |-BinaryOperatorExpression 2094 | | | |-IdExpression 2095 | | | | `-UnqualifiedId 2096 | | | | `-a 2097 | | | |-+ 2098 | | | `-BinaryOperatorExpression 2099 | | | |-IdExpression 2100 | | | | `-UnqualifiedId 2101 | | | | `-b 2102 | | | |-* 2103 | | | `-IntegerLiteralExpression 2104 | | | `-4 2105 | | |-+ 2106 | | `-IntegerLiteralExpression 2107 | | `-2 2108 | `-; 2109 |-ExpressionStatement 2110 | |-BinaryOperatorExpression 2111 | | |-BinaryOperatorExpression 2112 | | | |-IdExpression 2113 | | | | `-UnqualifiedId 2114 | | | | `-a 2115 | | | |-% 2116 | | | `-IntegerLiteralExpression 2117 | | | `-2 2118 | | |-+ 2119 | | `-BinaryOperatorExpression 2120 | | |-IdExpression 2121 | | | `-UnqualifiedId 2122 | | | `-b 2123 | | |-* 2124 | | `-IntegerLiteralExpression 2125 | | `-42 2126 | `-; 2127 `-} 2128 )txt")); 2129 } 2130 2131 TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) { 2132 if (!GetParam().isCXX()) { 2133 return; 2134 } 2135 EXPECT_TRUE(treeDumpEqual( 2136 R"cpp( 2137 struct X { 2138 X& operator=(const X&); 2139 friend X operator+(X, const X&); 2140 friend bool operator<(const X&, const X&); 2141 }; 2142 void test(X x, X y) { 2143 x = y; 2144 x + y; 2145 x < y; 2146 } 2147 )cpp", 2148 R"txt( 2149 *: TranslationUnit 2150 |-SimpleDeclaration 2151 | |-struct 2152 | |-X 2153 | |-{ 2154 | |-SimpleDeclaration 2155 | | |-X 2156 | | |-SimpleDeclarator 2157 | | | |-& 2158 | | | |-operator 2159 | | | |-= 2160 | | | `-ParametersAndQualifiers 2161 | | | |-( 2162 | | | |-SimpleDeclaration 2163 | | | | |-const 2164 | | | | |-X 2165 | | | | `-SimpleDeclarator 2166 | | | | `-& 2167 | | | `-) 2168 | | `-; 2169 | |-UnknownDeclaration 2170 | | `-SimpleDeclaration 2171 | | |-friend 2172 | | |-X 2173 | | |-SimpleDeclarator 2174 | | | |-operator 2175 | | | |-+ 2176 | | | `-ParametersAndQualifiers 2177 | | | |-( 2178 | | | |-SimpleDeclaration 2179 | | | | `-X 2180 | | | |-, 2181 | | | |-SimpleDeclaration 2182 | | | | |-const 2183 | | | | |-X 2184 | | | | `-SimpleDeclarator 2185 | | | | `-& 2186 | | | `-) 2187 | | `-; 2188 | |-UnknownDeclaration 2189 | | `-SimpleDeclaration 2190 | | |-friend 2191 | | |-bool 2192 | | |-SimpleDeclarator 2193 | | | |-operator 2194 | | | |-< 2195 | | | `-ParametersAndQualifiers 2196 | | | |-( 2197 | | | |-SimpleDeclaration 2198 | | | | |-const 2199 | | | | |-X 2200 | | | | `-SimpleDeclarator 2201 | | | | `-& 2202 | | | |-, 2203 | | | |-SimpleDeclaration 2204 | | | | |-const 2205 | | | | |-X 2206 | | | | `-SimpleDeclarator 2207 | | | | `-& 2208 | | | `-) 2209 | | `-; 2210 | |-} 2211 | `-; 2212 `-SimpleDeclaration 2213 |-void 2214 |-SimpleDeclarator 2215 | |-test 2216 | `-ParametersAndQualifiers 2217 | |-( 2218 | |-SimpleDeclaration 2219 | | |-X 2220 | | `-SimpleDeclarator 2221 | | `-x 2222 | |-, 2223 | |-SimpleDeclaration 2224 | | |-X 2225 | | `-SimpleDeclarator 2226 | | `-y 2227 | `-) 2228 `-CompoundStatement 2229 |-{ 2230 |-ExpressionStatement 2231 | |-BinaryOperatorExpression 2232 | | |-IdExpression 2233 | | | `-UnqualifiedId 2234 | | | `-x 2235 | | |-IdExpression 2236 | | | `-UnqualifiedId 2237 | | | `-= 2238 | | `-IdExpression 2239 | | `-UnqualifiedId 2240 | | `-y 2241 | `-; 2242 |-ExpressionStatement 2243 | |-BinaryOperatorExpression 2244 | | |-UnknownExpression 2245 | | | `-IdExpression 2246 | | | `-UnqualifiedId 2247 | | | `-x 2248 | | |-IdExpression 2249 | | | `-UnqualifiedId 2250 | | | `-+ 2251 | | `-IdExpression 2252 | | `-UnqualifiedId 2253 | | `-y 2254 | `-; 2255 |-ExpressionStatement 2256 | |-BinaryOperatorExpression 2257 | | |-IdExpression 2258 | | | `-UnqualifiedId 2259 | | | `-x 2260 | | |-IdExpression 2261 | | | `-UnqualifiedId 2262 | | | `-< 2263 | | `-IdExpression 2264 | | `-UnqualifiedId 2265 | | `-y 2266 | `-; 2267 `-} 2268 )txt")); 2269 } 2270 2271 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) { 2272 EXPECT_TRUE(treeDumpEqual( 2273 R"cpp( 2274 int *a, b; 2275 int *c, d; 2276 )cpp", 2277 R"txt( 2278 *: TranslationUnit 2279 |-SimpleDeclaration 2280 | |-int 2281 | |-SimpleDeclarator 2282 | | |-* 2283 | | `-a 2284 | |-, 2285 | |-SimpleDeclarator 2286 | | `-b 2287 | `-; 2288 `-SimpleDeclaration 2289 |-int 2290 |-SimpleDeclarator 2291 | |-* 2292 | `-c 2293 |-, 2294 |-SimpleDeclarator 2295 | `-d 2296 `-; 2297 )txt")); 2298 } 2299 2300 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) { 2301 EXPECT_TRUE(treeDumpEqual( 2302 R"cpp( 2303 typedef int *a, b; 2304 )cpp", 2305 R"txt( 2306 *: TranslationUnit 2307 `-SimpleDeclaration 2308 |-typedef 2309 |-int 2310 |-SimpleDeclarator 2311 | |-* 2312 | `-a 2313 |-, 2314 |-SimpleDeclarator 2315 | `-b 2316 `-; 2317 )txt")); 2318 } 2319 2320 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) { 2321 EXPECT_TRUE(treeDumpEqual( 2322 R"cpp( 2323 void foo() { 2324 int *a, b; 2325 typedef int *ta, tb; 2326 } 2327 )cpp", 2328 R"txt( 2329 *: TranslationUnit 2330 `-SimpleDeclaration 2331 |-void 2332 |-SimpleDeclarator 2333 | |-foo 2334 | `-ParametersAndQualifiers 2335 | |-( 2336 | `-) 2337 `-CompoundStatement 2338 |-{ 2339 |-DeclarationStatement 2340 | |-SimpleDeclaration 2341 | | |-int 2342 | | |-SimpleDeclarator 2343 | | | |-* 2344 | | | `-a 2345 | | |-, 2346 | | `-SimpleDeclarator 2347 | | `-b 2348 | `-; 2349 |-DeclarationStatement 2350 | |-SimpleDeclaration 2351 | | |-typedef 2352 | | |-int 2353 | | |-SimpleDeclarator 2354 | | | |-* 2355 | | | `-ta 2356 | | |-, 2357 | | `-SimpleDeclarator 2358 | | `-tb 2359 | `-; 2360 `-} 2361 )txt")); 2362 } 2363 2364 TEST_P(SyntaxTreeTest, Namespaces) { 2365 if (!GetParam().isCXX()) { 2366 return; 2367 } 2368 EXPECT_TRUE(treeDumpEqual( 2369 R"cpp( 2370 namespace a { namespace b {} } 2371 namespace a::b {} 2372 namespace {} 2373 2374 namespace foo = a; 2375 )cpp", 2376 R"txt( 2377 *: TranslationUnit 2378 |-NamespaceDefinition 2379 | |-namespace 2380 | |-a 2381 | |-{ 2382 | |-NamespaceDefinition 2383 | | |-namespace 2384 | | |-b 2385 | | |-{ 2386 | | `-} 2387 | `-} 2388 |-NamespaceDefinition 2389 | |-namespace 2390 | |-a 2391 | |-:: 2392 | |-b 2393 | |-{ 2394 | `-} 2395 |-NamespaceDefinition 2396 | |-namespace 2397 | |-{ 2398 | `-} 2399 `-NamespaceAliasDefinition 2400 |-namespace 2401 |-foo 2402 |-= 2403 |-a 2404 `-; 2405 )txt")); 2406 } 2407 2408 TEST_P(SyntaxTreeTest, UsingDirective) { 2409 if (!GetParam().isCXX()) { 2410 return; 2411 } 2412 EXPECT_TRUE(treeDumpEqual( 2413 R"cpp( 2414 namespace ns {} 2415 using namespace ::ns; 2416 )cpp", 2417 R"txt( 2418 *: TranslationUnit 2419 |-NamespaceDefinition 2420 | |-namespace 2421 | |-ns 2422 | |-{ 2423 | `-} 2424 `-UsingNamespaceDirective 2425 |-using 2426 |-namespace 2427 |-:: 2428 |-ns 2429 `-; 2430 )txt")); 2431 } 2432 2433 TEST_P(SyntaxTreeTest, UsingDeclaration) { 2434 if (!GetParam().isCXX()) { 2435 return; 2436 } 2437 EXPECT_TRUE(treeDumpEqual( 2438 R"cpp( 2439 namespace ns { int a; } 2440 using ns::a; 2441 )cpp", 2442 R"txt( 2443 *: TranslationUnit 2444 |-NamespaceDefinition 2445 | |-namespace 2446 | |-ns 2447 | |-{ 2448 | |-SimpleDeclaration 2449 | | |-int 2450 | | |-SimpleDeclarator 2451 | | | `-a 2452 | | `-; 2453 | `-} 2454 `-UsingDeclaration 2455 |-using 2456 |-ns 2457 |-:: 2458 |-a 2459 `-; 2460 )txt")); 2461 } 2462 2463 TEST_P(SyntaxTreeTest, FreeStandingClasses) { 2464 // Free-standing classes, must live inside a SimpleDeclaration. 2465 EXPECT_TRUE(treeDumpEqual( 2466 R"cpp( 2467 struct X; 2468 struct X {}; 2469 2470 struct Y *y1; 2471 struct Y {} *y2; 2472 2473 struct {} *a1; 2474 )cpp", 2475 R"txt( 2476 *: TranslationUnit 2477 |-SimpleDeclaration 2478 | |-struct 2479 | |-X 2480 | `-; 2481 |-SimpleDeclaration 2482 | |-struct 2483 | |-X 2484 | |-{ 2485 | |-} 2486 | `-; 2487 |-SimpleDeclaration 2488 | |-struct 2489 | |-Y 2490 | |-SimpleDeclarator 2491 | | |-* 2492 | | `-y1 2493 | `-; 2494 |-SimpleDeclaration 2495 | |-struct 2496 | |-Y 2497 | |-{ 2498 | |-} 2499 | |-SimpleDeclarator 2500 | | |-* 2501 | | `-y2 2502 | `-; 2503 `-SimpleDeclaration 2504 |-struct 2505 |-{ 2506 |-} 2507 |-SimpleDeclarator 2508 | |-* 2509 | `-a1 2510 `-; 2511 )txt")); 2512 } 2513 2514 TEST_P(SyntaxTreeTest, Templates) { 2515 if (!GetParam().isCXX()) { 2516 return; 2517 } 2518 if (GetParam().hasDelayedTemplateParsing()) { 2519 // FIXME: Make this test work on Windows by generating the expected syntax 2520 // tree when `-fdelayed-template-parsing` is active. 2521 return; 2522 } 2523 EXPECT_TRUE(treeDumpEqual( 2524 R"cpp( 2525 template <class T> struct cls {}; 2526 template <class T> int var = 10; 2527 template <class T> int fun() {} 2528 )cpp", 2529 R"txt( 2530 *: TranslationUnit 2531 |-TemplateDeclaration 2532 | |-template 2533 | |-< 2534 | |-UnknownDeclaration 2535 | | |-class 2536 | | `-T 2537 | |-> 2538 | `-SimpleDeclaration 2539 | |-struct 2540 | |-cls 2541 | |-{ 2542 | |-} 2543 | `-; 2544 |-TemplateDeclaration 2545 | |-template 2546 | |-< 2547 | |-UnknownDeclaration 2548 | | |-class 2549 | | `-T 2550 | |-> 2551 | `-SimpleDeclaration 2552 | |-int 2553 | |-SimpleDeclarator 2554 | | |-var 2555 | | |-= 2556 | | `-IntegerLiteralExpression 2557 | | `-10 2558 | `-; 2559 `-TemplateDeclaration 2560 |-template 2561 |-< 2562 |-UnknownDeclaration 2563 | |-class 2564 | `-T 2565 |-> 2566 `-SimpleDeclaration 2567 |-int 2568 |-SimpleDeclarator 2569 | |-fun 2570 | `-ParametersAndQualifiers 2571 | |-( 2572 | `-) 2573 `-CompoundStatement 2574 |-{ 2575 `-} 2576 )txt")); 2577 } 2578 2579 TEST_P(SyntaxTreeTest, NestedTemplates) { 2580 if (!GetParam().isCXX()) { 2581 return; 2582 } 2583 EXPECT_TRUE(treeDumpEqual( 2584 R"cpp( 2585 template <class T> 2586 struct X { 2587 template <class U> 2588 U foo(); 2589 }; 2590 )cpp", 2591 R"txt( 2592 *: TranslationUnit 2593 `-TemplateDeclaration 2594 |-template 2595 |-< 2596 |-UnknownDeclaration 2597 | |-class 2598 | `-T 2599 |-> 2600 `-SimpleDeclaration 2601 |-struct 2602 |-X 2603 |-{ 2604 |-TemplateDeclaration 2605 | |-template 2606 | |-< 2607 | |-UnknownDeclaration 2608 | | |-class 2609 | | `-U 2610 | |-> 2611 | `-SimpleDeclaration 2612 | |-U 2613 | |-SimpleDeclarator 2614 | | |-foo 2615 | | `-ParametersAndQualifiers 2616 | | |-( 2617 | | `-) 2618 | `-; 2619 |-} 2620 `-; 2621 )txt")); 2622 } 2623 2624 TEST_P(SyntaxTreeTest, Templates2) { 2625 if (!GetParam().isCXX()) { 2626 return; 2627 } 2628 EXPECT_TRUE(treeDumpEqual( 2629 R"cpp( 2630 template <class T> struct X { struct Y; }; 2631 template <class T> struct X<T>::Y {}; 2632 )cpp", 2633 R"txt( 2634 *: TranslationUnit 2635 |-TemplateDeclaration 2636 | |-template 2637 | |-< 2638 | |-UnknownDeclaration 2639 | | |-class 2640 | | `-T 2641 | |-> 2642 | `-SimpleDeclaration 2643 | |-struct 2644 | |-X 2645 | |-{ 2646 | |-SimpleDeclaration 2647 | | |-struct 2648 | | |-Y 2649 | | `-; 2650 | |-} 2651 | `-; 2652 `-TemplateDeclaration 2653 |-template 2654 |-< 2655 |-UnknownDeclaration 2656 | |-class 2657 | `-T 2658 |-> 2659 `-SimpleDeclaration 2660 |-struct 2661 |-X 2662 |-< 2663 |-T 2664 |-> 2665 |-:: 2666 |-Y 2667 |-{ 2668 |-} 2669 `-; 2670 )txt")); 2671 } 2672 2673 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) { 2674 if (!GetParam().isCXX()) { 2675 return; 2676 } 2677 EXPECT_TRUE(treeDumpEqual( 2678 R"cpp( 2679 template <class T> struct X { 2680 using T::foo; 2681 using typename T::bar; 2682 }; 2683 )cpp", 2684 R"txt( 2685 *: TranslationUnit 2686 `-TemplateDeclaration 2687 |-template 2688 |-< 2689 |-UnknownDeclaration 2690 | |-class 2691 | `-T 2692 |-> 2693 `-SimpleDeclaration 2694 |-struct 2695 |-X 2696 |-{ 2697 |-UsingDeclaration 2698 | |-using 2699 | |-T 2700 | |-:: 2701 | |-foo 2702 | `-; 2703 |-UsingDeclaration 2704 | |-using 2705 | |-typename 2706 | |-T 2707 | |-:: 2708 | |-bar 2709 | `-; 2710 |-} 2711 `-; 2712 )txt")); 2713 } 2714 2715 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) { 2716 if (!GetParam().isCXX()) { 2717 return; 2718 } 2719 EXPECT_TRUE(treeDumpEqual( 2720 R"cpp( 2721 template <class T> struct X {}; 2722 template <class T> struct X<T*> {}; 2723 template <> struct X<int> {}; 2724 2725 template struct X<double>; 2726 extern template struct X<float>; 2727 )cpp", 2728 R"txt( 2729 *: TranslationUnit 2730 |-TemplateDeclaration 2731 | |-template 2732 | |-< 2733 | |-UnknownDeclaration 2734 | | |-class 2735 | | `-T 2736 | |-> 2737 | `-SimpleDeclaration 2738 | |-struct 2739 | |-X 2740 | |-{ 2741 | |-} 2742 | `-; 2743 |-TemplateDeclaration 2744 | |-template 2745 | |-< 2746 | |-UnknownDeclaration 2747 | | |-class 2748 | | `-T 2749 | |-> 2750 | `-SimpleDeclaration 2751 | |-struct 2752 | |-X 2753 | |-< 2754 | |-T 2755 | |-* 2756 | |-> 2757 | |-{ 2758 | |-} 2759 | `-; 2760 |-TemplateDeclaration 2761 | |-template 2762 | |-< 2763 | |-> 2764 | `-SimpleDeclaration 2765 | |-struct 2766 | |-X 2767 | |-< 2768 | |-int 2769 | |-> 2770 | |-{ 2771 | |-} 2772 | `-; 2773 |-ExplicitTemplateInstantiation 2774 | |-template 2775 | `-SimpleDeclaration 2776 | |-struct 2777 | |-X 2778 | |-< 2779 | |-double 2780 | |-> 2781 | `-; 2782 `-ExplicitTemplateInstantiation 2783 |-extern 2784 |-template 2785 `-SimpleDeclaration 2786 |-struct 2787 |-X 2788 |-< 2789 |-float 2790 |-> 2791 `-; 2792 )txt")); 2793 } 2794 2795 TEST_P(SyntaxTreeTest, UsingType) { 2796 if (!GetParam().isCXX()) { 2797 return; 2798 } 2799 EXPECT_TRUE(treeDumpEqual( 2800 R"cpp( 2801 using type = int; 2802 )cpp", 2803 R"txt( 2804 *: TranslationUnit 2805 `-TypeAliasDeclaration 2806 |-using 2807 |-type 2808 |-= 2809 |-int 2810 `-; 2811 )txt")); 2812 } 2813 2814 TEST_P(SyntaxTreeTest, EmptyDeclaration) { 2815 EXPECT_TRUE(treeDumpEqual( 2816 R"cpp( 2817 ; 2818 )cpp", 2819 R"txt( 2820 *: TranslationUnit 2821 `-EmptyDeclaration 2822 `-; 2823 )txt")); 2824 } 2825 2826 TEST_P(SyntaxTreeTest, StaticAssert) { 2827 if (!GetParam().isCXX11OrLater()) { 2828 return; 2829 } 2830 EXPECT_TRUE(treeDumpEqual( 2831 R"cpp( 2832 static_assert(true, "message"); 2833 static_assert(true); 2834 )cpp", 2835 R"txt( 2836 *: TranslationUnit 2837 |-StaticAssertDeclaration 2838 | |-static_assert 2839 | |-( 2840 | |-BoolLiteralExpression 2841 | | `-true 2842 | |-, 2843 | |-StringLiteralExpression 2844 | | `-"message" 2845 | |-) 2846 | `-; 2847 `-StaticAssertDeclaration 2848 |-static_assert 2849 |-( 2850 |-BoolLiteralExpression 2851 | `-true 2852 |-) 2853 `-; 2854 )txt")); 2855 } 2856 2857 TEST_P(SyntaxTreeTest, ExternC) { 2858 if (!GetParam().isCXX()) { 2859 return; 2860 } 2861 EXPECT_TRUE(treeDumpEqual( 2862 R"cpp( 2863 extern "C" int a; 2864 extern "C" { int b; int c; } 2865 )cpp", 2866 R"txt( 2867 *: TranslationUnit 2868 |-LinkageSpecificationDeclaration 2869 | |-extern 2870 | |-"C" 2871 | `-SimpleDeclaration 2872 | |-int 2873 | |-SimpleDeclarator 2874 | | `-a 2875 | `-; 2876 `-LinkageSpecificationDeclaration 2877 |-extern 2878 |-"C" 2879 |-{ 2880 |-SimpleDeclaration 2881 | |-int 2882 | |-SimpleDeclarator 2883 | | `-b 2884 | `-; 2885 |-SimpleDeclaration 2886 | |-int 2887 | |-SimpleDeclarator 2888 | | `-c 2889 | `-; 2890 `-} 2891 )txt")); 2892 } 2893 2894 TEST_P(SyntaxTreeTest, NonModifiableNodes) { 2895 // Some nodes are non-modifiable, they are marked with 'I:'. 2896 EXPECT_TRUE(treeDumpEqual( 2897 R"cpp( 2898 #define HALF_IF if (1+ 2899 #define HALF_IF_2 1) {} 2900 void test() { 2901 HALF_IF HALF_IF_2 else {} 2902 })cpp", 2903 R"txt( 2904 *: TranslationUnit 2905 `-SimpleDeclaration 2906 |-void 2907 |-SimpleDeclarator 2908 | |-test 2909 | `-ParametersAndQualifiers 2910 | |-( 2911 | `-) 2912 `-CompoundStatement 2913 |-{ 2914 |-IfStatement 2915 | |-I: if 2916 | |-I: ( 2917 | |-I: BinaryOperatorExpression 2918 | | |-I: IntegerLiteralExpression 2919 | | | `-I: 1 2920 | | |-I: + 2921 | | `-I: IntegerLiteralExpression 2922 | | `-I: 1 2923 | |-I: ) 2924 | |-I: CompoundStatement 2925 | | |-I: { 2926 | | `-I: } 2927 | |-else 2928 | `-CompoundStatement 2929 | |-{ 2930 | `-} 2931 `-} 2932 )txt")); 2933 } 2934 2935 TEST_P(SyntaxTreeTest, ModifiableNodes) { 2936 // All nodes can be mutated. 2937 EXPECT_TRUE(treeDumpEqual( 2938 R"cpp( 2939 #define OPEN { 2940 #define CLOSE } 2941 2942 void test() { 2943 OPEN 2944 1; 2945 CLOSE 2946 2947 OPEN 2948 2; 2949 } 2950 } 2951 )cpp", 2952 R"txt( 2953 *: TranslationUnit 2954 `-SimpleDeclaration 2955 |-void 2956 |-SimpleDeclarator 2957 | |-test 2958 | `-ParametersAndQualifiers 2959 | |-( 2960 | `-) 2961 `-CompoundStatement 2962 |-{ 2963 |-CompoundStatement 2964 | |-{ 2965 | |-ExpressionStatement 2966 | | |-IntegerLiteralExpression 2967 | | | `-1 2968 | | `-; 2969 | `-} 2970 |-CompoundStatement 2971 | |-{ 2972 | |-ExpressionStatement 2973 | | |-IntegerLiteralExpression 2974 | | | `-2 2975 | | `-; 2976 | `-} 2977 `-} 2978 )txt")); 2979 } 2980 2981 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) { 2982 EXPECT_TRUE(treeDumpEqual( 2983 R"cpp( 2984 int a[10]; 2985 int b[1][2][3]; 2986 int c[] = {1,2,3}; 2987 )cpp", 2988 R"txt( 2989 *: TranslationUnit 2990 |-SimpleDeclaration 2991 | |-int 2992 | |-SimpleDeclarator 2993 | | |-a 2994 | | `-ArraySubscript 2995 | | |-[ 2996 | | |-IntegerLiteralExpression 2997 | | | `-10 2998 | | `-] 2999 | `-; 3000 |-SimpleDeclaration 3001 | |-int 3002 | |-SimpleDeclarator 3003 | | |-b 3004 | | |-ArraySubscript 3005 | | | |-[ 3006 | | | |-IntegerLiteralExpression 3007 | | | | `-1 3008 | | | `-] 3009 | | |-ArraySubscript 3010 | | | |-[ 3011 | | | |-IntegerLiteralExpression 3012 | | | | `-2 3013 | | | `-] 3014 | | `-ArraySubscript 3015 | | |-[ 3016 | | |-IntegerLiteralExpression 3017 | | | `-3 3018 | | `-] 3019 | `-; 3020 `-SimpleDeclaration 3021 |-int 3022 |-SimpleDeclarator 3023 | |-c 3024 | |-ArraySubscript 3025 | | |-[ 3026 | | `-] 3027 | |-= 3028 | `-UnknownExpression 3029 | `-UnknownExpression 3030 | |-{ 3031 | |-IntegerLiteralExpression 3032 | | `-1 3033 | |-, 3034 | |-IntegerLiteralExpression 3035 | | `-2 3036 | |-, 3037 | |-IntegerLiteralExpression 3038 | | `-3 3039 | `-} 3040 `-; 3041 )txt")); 3042 } 3043 3044 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) { 3045 if (!GetParam().isC99OrLater()) { 3046 return; 3047 } 3048 EXPECT_TRUE(treeDumpEqual( 3049 R"cpp( 3050 void f(int xs[static 10]); 3051 )cpp", 3052 R"txt( 3053 *: TranslationUnit 3054 `-SimpleDeclaration 3055 |-void 3056 |-SimpleDeclarator 3057 | |-f 3058 | `-ParametersAndQualifiers 3059 | |-( 3060 | |-SimpleDeclaration 3061 | | |-int 3062 | | `-SimpleDeclarator 3063 | | |-xs 3064 | | `-ArraySubscript 3065 | | |-[ 3066 | | |-static 3067 | | |-IntegerLiteralExpression 3068 | | | `-10 3069 | | `-] 3070 | `-) 3071 `-; 3072 )txt")); 3073 } 3074 3075 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) { 3076 if (!GetParam().isCXX()) { 3077 return; 3078 } 3079 EXPECT_TRUE(treeDumpEqual( 3080 R"cpp( 3081 int func1(); 3082 int func2a(int a); 3083 int func2b(int); 3084 int func3a(int *ap); 3085 int func3b(int *); 3086 int func4a(int a, float b); 3087 int func4b(int, float); 3088 )cpp", 3089 R"txt( 3090 *: TranslationUnit 3091 |-SimpleDeclaration 3092 | |-int 3093 | |-SimpleDeclarator 3094 | | |-func1 3095 | | `-ParametersAndQualifiers 3096 | | |-( 3097 | | `-) 3098 | `-; 3099 |-SimpleDeclaration 3100 | |-int 3101 | |-SimpleDeclarator 3102 | | |-func2a 3103 | | `-ParametersAndQualifiers 3104 | | |-( 3105 | | |-SimpleDeclaration 3106 | | | |-int 3107 | | | `-SimpleDeclarator 3108 | | | `-a 3109 | | `-) 3110 | `-; 3111 |-SimpleDeclaration 3112 | |-int 3113 | |-SimpleDeclarator 3114 | | |-func2b 3115 | | `-ParametersAndQualifiers 3116 | | |-( 3117 | | |-SimpleDeclaration 3118 | | | `-int 3119 | | `-) 3120 | `-; 3121 |-SimpleDeclaration 3122 | |-int 3123 | |-SimpleDeclarator 3124 | | |-func3a 3125 | | `-ParametersAndQualifiers 3126 | | |-( 3127 | | |-SimpleDeclaration 3128 | | | |-int 3129 | | | `-SimpleDeclarator 3130 | | | |-* 3131 | | | `-ap 3132 | | `-) 3133 | `-; 3134 |-SimpleDeclaration 3135 | |-int 3136 | |-SimpleDeclarator 3137 | | |-func3b 3138 | | `-ParametersAndQualifiers 3139 | | |-( 3140 | | |-SimpleDeclaration 3141 | | | |-int 3142 | | | `-SimpleDeclarator 3143 | | | `-* 3144 | | `-) 3145 | `-; 3146 |-SimpleDeclaration 3147 | |-int 3148 | |-SimpleDeclarator 3149 | | |-func4a 3150 | | `-ParametersAndQualifiers 3151 | | |-( 3152 | | |-SimpleDeclaration 3153 | | | |-int 3154 | | | `-SimpleDeclarator 3155 | | | `-a 3156 | | |-, 3157 | | |-SimpleDeclaration 3158 | | | |-float 3159 | | | `-SimpleDeclarator 3160 | | | `-b 3161 | | `-) 3162 | `-; 3163 `-SimpleDeclaration 3164 |-int 3165 |-SimpleDeclarator 3166 | |-func4b 3167 | `-ParametersAndQualifiers 3168 | |-( 3169 | |-SimpleDeclaration 3170 | | `-int 3171 | |-, 3172 | |-SimpleDeclaration 3173 | | `-float 3174 | `-) 3175 `-; 3176 )txt")); 3177 } 3178 3179 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) { 3180 if (!GetParam().isCXX()) { 3181 return; 3182 } 3183 EXPECT_TRUE(treeDumpEqual( 3184 R"cpp( 3185 int func1(const int a, volatile int b, const volatile int c); 3186 int func2(int& a); 3187 )cpp", 3188 R"txt( 3189 *: TranslationUnit 3190 |-SimpleDeclaration 3191 | |-int 3192 | |-SimpleDeclarator 3193 | | |-func1 3194 | | `-ParametersAndQualifiers 3195 | | |-( 3196 | | |-SimpleDeclaration 3197 | | | |-const 3198 | | | |-int 3199 | | | `-SimpleDeclarator 3200 | | | `-a 3201 | | |-, 3202 | | |-SimpleDeclaration 3203 | | | |-volatile 3204 | | | |-int 3205 | | | `-SimpleDeclarator 3206 | | | `-b 3207 | | |-, 3208 | | |-SimpleDeclaration 3209 | | | |-const 3210 | | | |-volatile 3211 | | | |-int 3212 | | | `-SimpleDeclarator 3213 | | | `-c 3214 | | `-) 3215 | `-; 3216 `-SimpleDeclaration 3217 |-int 3218 |-SimpleDeclarator 3219 | |-func2 3220 | `-ParametersAndQualifiers 3221 | |-( 3222 | |-SimpleDeclaration 3223 | | |-int 3224 | | `-SimpleDeclarator 3225 | | |-& 3226 | | `-a 3227 | `-) 3228 `-; 3229 )txt")); 3230 } 3231 3232 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) { 3233 if (!GetParam().isCXX11OrLater()) { 3234 return; 3235 } 3236 EXPECT_TRUE(treeDumpEqual( 3237 R"cpp( 3238 int func1(int&& a); 3239 )cpp", 3240 R"txt( 3241 *: TranslationUnit 3242 `-SimpleDeclaration 3243 |-int 3244 |-SimpleDeclarator 3245 | |-func1 3246 | `-ParametersAndQualifiers 3247 | |-( 3248 | |-SimpleDeclaration 3249 | | |-int 3250 | | `-SimpleDeclarator 3251 | | |-&& 3252 | | `-a 3253 | `-) 3254 `-; 3255 )txt")); 3256 } 3257 3258 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) { 3259 if (!GetParam().isCXX()) { 3260 return; 3261 } 3262 EXPECT_TRUE(treeDumpEqual( 3263 R"cpp( 3264 struct Test { 3265 int a(); 3266 int b() const; 3267 int c() volatile; 3268 int d() const volatile; 3269 int e() &; 3270 int f() &&; 3271 }; 3272 )cpp", 3273 R"txt( 3274 *: TranslationUnit 3275 `-SimpleDeclaration 3276 |-struct 3277 |-Test 3278 |-{ 3279 |-SimpleDeclaration 3280 | |-int 3281 | |-SimpleDeclarator 3282 | | |-a 3283 | | `-ParametersAndQualifiers 3284 | | |-( 3285 | | `-) 3286 | `-; 3287 |-SimpleDeclaration 3288 | |-int 3289 | |-SimpleDeclarator 3290 | | |-b 3291 | | `-ParametersAndQualifiers 3292 | | |-( 3293 | | |-) 3294 | | `-const 3295 | `-; 3296 |-SimpleDeclaration 3297 | |-int 3298 | |-SimpleDeclarator 3299 | | |-c 3300 | | `-ParametersAndQualifiers 3301 | | |-( 3302 | | |-) 3303 | | `-volatile 3304 | `-; 3305 |-SimpleDeclaration 3306 | |-int 3307 | |-SimpleDeclarator 3308 | | |-d 3309 | | `-ParametersAndQualifiers 3310 | | |-( 3311 | | |-) 3312 | | |-const 3313 | | `-volatile 3314 | `-; 3315 |-SimpleDeclaration 3316 | |-int 3317 | |-SimpleDeclarator 3318 | | |-e 3319 | | `-ParametersAndQualifiers 3320 | | |-( 3321 | | |-) 3322 | | `-& 3323 | `-; 3324 |-SimpleDeclaration 3325 | |-int 3326 | |-SimpleDeclarator 3327 | | |-f 3328 | | `-ParametersAndQualifiers 3329 | | |-( 3330 | | |-) 3331 | | `-&& 3332 | `-; 3333 |-} 3334 `-; 3335 )txt")); 3336 } 3337 3338 TEST_P(SyntaxTreeTest, TrailingReturn) { 3339 if (!GetParam().isCXX11OrLater()) { 3340 return; 3341 } 3342 EXPECT_TRUE(treeDumpEqual( 3343 R"cpp( 3344 auto foo() -> int; 3345 )cpp", 3346 R"txt( 3347 *: TranslationUnit 3348 `-SimpleDeclaration 3349 |-auto 3350 |-SimpleDeclarator 3351 | |-foo 3352 | `-ParametersAndQualifiers 3353 | |-( 3354 | |-) 3355 | `-TrailingReturnType 3356 | |--> 3357 | `-int 3358 `-; 3359 )txt")); 3360 } 3361 3362 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) { 3363 if (!GetParam().supportsCXXDynamicExceptionSpecification()) { 3364 return; 3365 } 3366 EXPECT_TRUE(treeDumpEqual( 3367 R"cpp( 3368 struct MyException1 {}; 3369 struct MyException2 {}; 3370 int a() throw(); 3371 int b() throw(...); 3372 int c() throw(MyException1); 3373 int d() throw(MyException1, MyException2); 3374 )cpp", 3375 R"txt( 3376 *: TranslationUnit 3377 |-SimpleDeclaration 3378 | |-struct 3379 | |-MyException1 3380 | |-{ 3381 | |-} 3382 | `-; 3383 |-SimpleDeclaration 3384 | |-struct 3385 | |-MyException2 3386 | |-{ 3387 | |-} 3388 | `-; 3389 |-SimpleDeclaration 3390 | |-int 3391 | |-SimpleDeclarator 3392 | | |-a 3393 | | `-ParametersAndQualifiers 3394 | | |-( 3395 | | |-) 3396 | | |-throw 3397 | | |-( 3398 | | `-) 3399 | `-; 3400 |-SimpleDeclaration 3401 | |-int 3402 | |-SimpleDeclarator 3403 | | |-b 3404 | | `-ParametersAndQualifiers 3405 | | |-( 3406 | | |-) 3407 | | |-throw 3408 | | |-( 3409 | | |-... 3410 | | `-) 3411 | `-; 3412 |-SimpleDeclaration 3413 | |-int 3414 | |-SimpleDeclarator 3415 | | |-c 3416 | | `-ParametersAndQualifiers 3417 | | |-( 3418 | | |-) 3419 | | |-throw 3420 | | |-( 3421 | | |-MyException1 3422 | | `-) 3423 | `-; 3424 `-SimpleDeclaration 3425 |-int 3426 |-SimpleDeclarator 3427 | |-d 3428 | `-ParametersAndQualifiers 3429 | |-( 3430 | |-) 3431 | |-throw 3432 | |-( 3433 | |-MyException1 3434 | |-, 3435 | |-MyException2 3436 | `-) 3437 `-; 3438 )txt")); 3439 } 3440 3441 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) { 3442 if (!GetParam().isCXX11OrLater()) { 3443 return; 3444 } 3445 EXPECT_TRUE(treeDumpEqual( 3446 R"cpp( 3447 int a() noexcept; 3448 int b() noexcept(true); 3449 )cpp", 3450 R"txt( 3451 *: TranslationUnit 3452 |-SimpleDeclaration 3453 | |-int 3454 | |-SimpleDeclarator 3455 | | |-a 3456 | | `-ParametersAndQualifiers 3457 | | |-( 3458 | | |-) 3459 | | `-noexcept 3460 | `-; 3461 `-SimpleDeclaration 3462 |-int 3463 |-SimpleDeclarator 3464 | |-b 3465 | `-ParametersAndQualifiers 3466 | |-( 3467 | |-) 3468 | |-noexcept 3469 | |-( 3470 | |-BoolLiteralExpression 3471 | | `-true 3472 | `-) 3473 `-; 3474 )txt")); 3475 } 3476 3477 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) { 3478 EXPECT_TRUE(treeDumpEqual( 3479 R"cpp( 3480 int (a); 3481 int *(b); 3482 int (*c)(int); 3483 int *(d)(int); 3484 )cpp", 3485 R"txt( 3486 *: TranslationUnit 3487 |-SimpleDeclaration 3488 | |-int 3489 | |-SimpleDeclarator 3490 | | `-ParenDeclarator 3491 | | |-( 3492 | | |-a 3493 | | `-) 3494 | `-; 3495 |-SimpleDeclaration 3496 | |-int 3497 | |-SimpleDeclarator 3498 | | |-* 3499 | | `-ParenDeclarator 3500 | | |-( 3501 | | |-b 3502 | | `-) 3503 | `-; 3504 |-SimpleDeclaration 3505 | |-int 3506 | |-SimpleDeclarator 3507 | | |-ParenDeclarator 3508 | | | |-( 3509 | | | |-* 3510 | | | |-c 3511 | | | `-) 3512 | | `-ParametersAndQualifiers 3513 | | |-( 3514 | | |-SimpleDeclaration 3515 | | | `-int 3516 | | `-) 3517 | `-; 3518 `-SimpleDeclaration 3519 |-int 3520 |-SimpleDeclarator 3521 | |-* 3522 | |-ParenDeclarator 3523 | | |-( 3524 | | |-d 3525 | | `-) 3526 | `-ParametersAndQualifiers 3527 | |-( 3528 | |-SimpleDeclaration 3529 | | `-int 3530 | `-) 3531 `-; 3532 )txt")); 3533 } 3534 3535 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) { 3536 EXPECT_TRUE(treeDumpEqual( 3537 R"cpp( 3538 const int west = -1; 3539 int const east = 1; 3540 const int const universal = 0; 3541 const int const *const *volatile b; 3542 )cpp", 3543 R"txt( 3544 *: TranslationUnit 3545 |-SimpleDeclaration 3546 | |-const 3547 | |-int 3548 | |-SimpleDeclarator 3549 | | |-west 3550 | | |-= 3551 | | `-PrefixUnaryOperatorExpression 3552 | | |-- 3553 | | `-IntegerLiteralExpression 3554 | | `-1 3555 | `-; 3556 |-SimpleDeclaration 3557 | |-int 3558 | |-const 3559 | |-SimpleDeclarator 3560 | | |-east 3561 | | |-= 3562 | | `-IntegerLiteralExpression 3563 | | `-1 3564 | `-; 3565 |-SimpleDeclaration 3566 | |-const 3567 | |-int 3568 | |-const 3569 | |-SimpleDeclarator 3570 | | |-universal 3571 | | |-= 3572 | | `-IntegerLiteralExpression 3573 | | `-0 3574 | `-; 3575 `-SimpleDeclaration 3576 |-const 3577 |-int 3578 |-const 3579 |-SimpleDeclarator 3580 | |-* 3581 | |-const 3582 | |-* 3583 | |-volatile 3584 | `-b 3585 `-; 3586 )txt")); 3587 } 3588 3589 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) { 3590 if (!GetParam().isCXX11OrLater()) { 3591 return; 3592 } 3593 EXPECT_TRUE(treeDumpEqual( 3594 R"cpp( 3595 auto foo() -> auto(*)(int) -> double*; 3596 )cpp", 3597 R"txt( 3598 *: TranslationUnit 3599 `-SimpleDeclaration 3600 |-auto 3601 |-SimpleDeclarator 3602 | |-foo 3603 | `-ParametersAndQualifiers 3604 | |-( 3605 | |-) 3606 | `-TrailingReturnType 3607 | |--> 3608 | |-auto 3609 | `-SimpleDeclarator 3610 | |-ParenDeclarator 3611 | | |-( 3612 | | |-* 3613 | | `-) 3614 | `-ParametersAndQualifiers 3615 | |-( 3616 | |-SimpleDeclaration 3617 | | `-int 3618 | |-) 3619 | `-TrailingReturnType 3620 | |--> 3621 | |-double 3622 | `-SimpleDeclarator 3623 | `-* 3624 `-; 3625 )txt")); 3626 } 3627 3628 TEST_P(SyntaxTreeTest, MemberPointers) { 3629 if (!GetParam().isCXX()) { 3630 return; 3631 } 3632 EXPECT_TRUE(treeDumpEqual( 3633 R"cpp( 3634 struct X {}; 3635 int X::* a; 3636 const int X::* b; 3637 )cpp", 3638 R"txt( 3639 *: TranslationUnit 3640 |-SimpleDeclaration 3641 | |-struct 3642 | |-X 3643 | |-{ 3644 | |-} 3645 | `-; 3646 |-SimpleDeclaration 3647 | |-int 3648 | |-SimpleDeclarator 3649 | | |-MemberPointer 3650 | | | |-X 3651 | | | |-:: 3652 | | | `-* 3653 | | `-a 3654 | `-; 3655 `-SimpleDeclaration 3656 |-const 3657 |-int 3658 |-SimpleDeclarator 3659 | |-MemberPointer 3660 | | |-X 3661 | | |-:: 3662 | | `-* 3663 | `-b 3664 `-; 3665 )txt")); 3666 } 3667 3668 TEST_P(SyntaxTreeTest, ComplexDeclarator) { 3669 EXPECT_TRUE(treeDumpEqual( 3670 R"cpp( 3671 void x(char a, short (*b)(int)); 3672 )cpp", 3673 R"txt( 3674 *: TranslationUnit 3675 `-SimpleDeclaration 3676 |-void 3677 |-SimpleDeclarator 3678 | |-x 3679 | `-ParametersAndQualifiers 3680 | |-( 3681 | |-SimpleDeclaration 3682 | | |-char 3683 | | `-SimpleDeclarator 3684 | | `-a 3685 | |-, 3686 | |-SimpleDeclaration 3687 | | |-short 3688 | | `-SimpleDeclarator 3689 | | |-ParenDeclarator 3690 | | | |-( 3691 | | | |-* 3692 | | | |-b 3693 | | | `-) 3694 | | `-ParametersAndQualifiers 3695 | | |-( 3696 | | |-SimpleDeclaration 3697 | | | `-int 3698 | | `-) 3699 | `-) 3700 `-; 3701 )txt")); 3702 } 3703 3704 TEST_P(SyntaxTreeTest, ComplexDeclarator2) { 3705 EXPECT_TRUE(treeDumpEqual( 3706 R"cpp( 3707 void x(char a, short (*b)(int), long (**c)(long long)); 3708 )cpp", 3709 R"txt( 3710 *: TranslationUnit 3711 `-SimpleDeclaration 3712 |-void 3713 |-SimpleDeclarator 3714 | |-x 3715 | `-ParametersAndQualifiers 3716 | |-( 3717 | |-SimpleDeclaration 3718 | | |-char 3719 | | `-SimpleDeclarator 3720 | | `-a 3721 | |-, 3722 | |-SimpleDeclaration 3723 | | |-short 3724 | | `-SimpleDeclarator 3725 | | |-ParenDeclarator 3726 | | | |-( 3727 | | | |-* 3728 | | | |-b 3729 | | | `-) 3730 | | `-ParametersAndQualifiers 3731 | | |-( 3732 | | |-SimpleDeclaration 3733 | | | `-int 3734 | | `-) 3735 | |-, 3736 | |-SimpleDeclaration 3737 | | |-long 3738 | | `-SimpleDeclarator 3739 | | |-ParenDeclarator 3740 | | | |-( 3741 | | | |-* 3742 | | | |-* 3743 | | | |-c 3744 | | | `-) 3745 | | `-ParametersAndQualifiers 3746 | | |-( 3747 | | |-SimpleDeclaration 3748 | | | |-long 3749 | | | `-long 3750 | | `-) 3751 | `-) 3752 `-; 3753 )txt")); 3754 } 3755 3756 TEST_P(SyntaxTreeTest, Mutations) { 3757 if (!GetParam().isCXX11OrLater()) { 3758 return; 3759 } 3760 3761 using Transformation = std::function<void( 3762 const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>; 3763 auto CheckTransformation = [this](std::string Input, std::string Expected, 3764 Transformation Transform) -> void { 3765 llvm::Annotations Source(Input); 3766 auto *Root = buildTree(Source.code(), GetParam()); 3767 3768 Transform(Source, Root); 3769 3770 auto Replacements = syntax::computeReplacements(*Arena, *Root); 3771 auto Output = tooling::applyAllReplacements(Source.code(), Replacements); 3772 if (!Output) { 3773 ADD_FAILURE() << "could not apply replacements: " 3774 << llvm::toString(Output.takeError()); 3775 return; 3776 } 3777 3778 EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; 3779 }; 3780 3781 // Removes the selected statement. Input should have exactly one selected 3782 // range and it should correspond to a single statement. 3783 auto RemoveStatement = [this](const llvm::Annotations &Input, 3784 syntax::TranslationUnit *TU) { 3785 auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU)); 3786 ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 3787 syntax::removeStatement(*Arena, S); 3788 EXPECT_TRUE(S->isDetached()); 3789 EXPECT_FALSE(S->isOriginal()) 3790 << "node removed from tree cannot be marked as original"; 3791 }; 3792 3793 std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>> 3794 Cases = { 3795 {"void test() { [[100+100;]] test(); }", "void test() { test(); }"}, 3796 {"void test() { if (true) [[{}]] else {} }", 3797 "void test() { if (true) ; else {} }"}, 3798 {"void test() { [[;]] }", "void test() { }"}}; 3799 for (const auto &C : Cases) 3800 CheckTransformation(C.first, C.second, RemoveStatement); 3801 } 3802 3803 TEST_P(SyntaxTreeTest, SynthesizedNodes) { 3804 buildTree("", GetParam()); 3805 3806 auto *C = syntax::createPunctuation(*Arena, tok::comma); 3807 ASSERT_NE(C, nullptr); 3808 EXPECT_EQ(C->token()->kind(), tok::comma); 3809 EXPECT_TRUE(C->canModify()); 3810 EXPECT_FALSE(C->isOriginal()); 3811 EXPECT_TRUE(C->isDetached()); 3812 3813 auto *S = syntax::createEmptyStatement(*Arena); 3814 ASSERT_NE(S, nullptr); 3815 EXPECT_TRUE(S->canModify()); 3816 EXPECT_FALSE(S->isOriginal()); 3817 EXPECT_TRUE(S->isDetached()); 3818 } 3819 3820 static std::vector<TestClangConfig> allTestClangConfigs() { 3821 std::vector<TestClangConfig> all_configs; 3822 for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11, 3823 Lang_CXX14, Lang_CXX17, Lang_CXX20}) { 3824 TestClangConfig config; 3825 config.Language = lang; 3826 config.Target = "x86_64-pc-linux-gnu"; 3827 all_configs.push_back(config); 3828 3829 // Windows target is interesting to test because it enables 3830 // `-fdelayed-template-parsing`. 3831 config.Target = "x86_64-pc-win32-msvc"; 3832 all_configs.push_back(config); 3833 } 3834 return all_configs; 3835 } 3836 3837 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest, 3838 testing::ValuesIn(allTestClangConfigs()), ); 3839 3840 } // namespace 3841