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 }; 2197 void test(X x, X y) { 2198 x = y; 2199 x + y; 2200 x < y; 2201 } 2202 )cpp", 2203 R"txt( 2204 *: TranslationUnit 2205 |-SimpleDeclaration 2206 | |-struct 2207 | |-X 2208 | |-{ 2209 | |-SimpleDeclaration 2210 | | |-X 2211 | | |-SimpleDeclarator 2212 | | | |-& 2213 | | | |-operator 2214 | | | |-= 2215 | | | `-ParametersAndQualifiers 2216 | | | |-( 2217 | | | |-SimpleDeclaration 2218 | | | | |-const 2219 | | | | |-X 2220 | | | | `-SimpleDeclarator 2221 | | | | `-& 2222 | | | `-) 2223 | | `-; 2224 | |-UnknownDeclaration 2225 | | `-SimpleDeclaration 2226 | | |-friend 2227 | | |-X 2228 | | |-SimpleDeclarator 2229 | | | |-operator 2230 | | | |-+ 2231 | | | `-ParametersAndQualifiers 2232 | | | |-( 2233 | | | |-SimpleDeclaration 2234 | | | | `-X 2235 | | | |-, 2236 | | | |-SimpleDeclaration 2237 | | | | |-const 2238 | | | | |-X 2239 | | | | `-SimpleDeclarator 2240 | | | | `-& 2241 | | | `-) 2242 | | `-; 2243 | |-UnknownDeclaration 2244 | | `-SimpleDeclaration 2245 | | |-friend 2246 | | |-bool 2247 | | |-SimpleDeclarator 2248 | | | |-operator 2249 | | | |-< 2250 | | | `-ParametersAndQualifiers 2251 | | | |-( 2252 | | | |-SimpleDeclaration 2253 | | | | |-const 2254 | | | | |-X 2255 | | | | `-SimpleDeclarator 2256 | | | | `-& 2257 | | | |-, 2258 | | | |-SimpleDeclaration 2259 | | | | |-const 2260 | | | | |-X 2261 | | | | `-SimpleDeclarator 2262 | | | | `-& 2263 | | | `-) 2264 | | `-; 2265 | |-} 2266 | `-; 2267 `-SimpleDeclaration 2268 |-void 2269 |-SimpleDeclarator 2270 | |-test 2271 | `-ParametersAndQualifiers 2272 | |-( 2273 | |-SimpleDeclaration 2274 | | |-X 2275 | | `-SimpleDeclarator 2276 | | `-x 2277 | |-, 2278 | |-SimpleDeclaration 2279 | | |-X 2280 | | `-SimpleDeclarator 2281 | | `-y 2282 | `-) 2283 `-CompoundStatement 2284 |-{ 2285 |-ExpressionStatement 2286 | |-BinaryOperatorExpression 2287 | | |-IdExpression 2288 | | | `-UnqualifiedId 2289 | | | `-x 2290 | | |-IdExpression 2291 | | | `-UnqualifiedId 2292 | | | `-= 2293 | | `-IdExpression 2294 | | `-UnqualifiedId 2295 | | `-y 2296 | `-; 2297 |-ExpressionStatement 2298 | |-BinaryOperatorExpression 2299 | | |-UnknownExpression 2300 | | | `-IdExpression 2301 | | | `-UnqualifiedId 2302 | | | `-x 2303 | | |-IdExpression 2304 | | | `-UnqualifiedId 2305 | | | `-+ 2306 | | `-IdExpression 2307 | | `-UnqualifiedId 2308 | | `-y 2309 | `-; 2310 |-ExpressionStatement 2311 | |-BinaryOperatorExpression 2312 | | |-IdExpression 2313 | | | `-UnqualifiedId 2314 | | | `-x 2315 | | |-IdExpression 2316 | | | `-UnqualifiedId 2317 | | | `-< 2318 | | `-IdExpression 2319 | | `-UnqualifiedId 2320 | | `-y 2321 | `-; 2322 `-} 2323 )txt")); 2324 } 2325 2326 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) { 2327 EXPECT_TRUE(treeDumpEqual( 2328 R"cpp( 2329 int *a, b; 2330 int *c, d; 2331 )cpp", 2332 R"txt( 2333 *: TranslationUnit 2334 |-SimpleDeclaration 2335 | |-int 2336 | |-SimpleDeclarator 2337 | | |-* 2338 | | `-a 2339 | |-, 2340 | |-SimpleDeclarator 2341 | | `-b 2342 | `-; 2343 `-SimpleDeclaration 2344 |-int 2345 |-SimpleDeclarator 2346 | |-* 2347 | `-c 2348 |-, 2349 |-SimpleDeclarator 2350 | `-d 2351 `-; 2352 )txt")); 2353 } 2354 2355 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) { 2356 EXPECT_TRUE(treeDumpEqual( 2357 R"cpp( 2358 typedef int *a, b; 2359 )cpp", 2360 R"txt( 2361 *: TranslationUnit 2362 `-SimpleDeclaration 2363 |-typedef 2364 |-int 2365 |-SimpleDeclarator 2366 | |-* 2367 | `-a 2368 |-, 2369 |-SimpleDeclarator 2370 | `-b 2371 `-; 2372 )txt")); 2373 } 2374 2375 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) { 2376 EXPECT_TRUE(treeDumpEqual( 2377 R"cpp( 2378 void foo() { 2379 int *a, b; 2380 typedef int *ta, tb; 2381 } 2382 )cpp", 2383 R"txt( 2384 *: TranslationUnit 2385 `-SimpleDeclaration 2386 |-void 2387 |-SimpleDeclarator 2388 | |-foo 2389 | `-ParametersAndQualifiers 2390 | |-( 2391 | `-) 2392 `-CompoundStatement 2393 |-{ 2394 |-DeclarationStatement 2395 | |-SimpleDeclaration 2396 | | |-int 2397 | | |-SimpleDeclarator 2398 | | | |-* 2399 | | | `-a 2400 | | |-, 2401 | | `-SimpleDeclarator 2402 | | `-b 2403 | `-; 2404 |-DeclarationStatement 2405 | |-SimpleDeclaration 2406 | | |-typedef 2407 | | |-int 2408 | | |-SimpleDeclarator 2409 | | | |-* 2410 | | | `-ta 2411 | | |-, 2412 | | `-SimpleDeclarator 2413 | | `-tb 2414 | `-; 2415 `-} 2416 )txt")); 2417 } 2418 2419 TEST_P(SyntaxTreeTest, Namespaces) { 2420 if (!GetParam().isCXX()) { 2421 return; 2422 } 2423 EXPECT_TRUE(treeDumpEqual( 2424 R"cpp( 2425 namespace a { namespace b {} } 2426 namespace a::b {} 2427 namespace {} 2428 2429 namespace foo = a; 2430 )cpp", 2431 R"txt( 2432 *: TranslationUnit 2433 |-NamespaceDefinition 2434 | |-namespace 2435 | |-a 2436 | |-{ 2437 | |-NamespaceDefinition 2438 | | |-namespace 2439 | | |-b 2440 | | |-{ 2441 | | `-} 2442 | `-} 2443 |-NamespaceDefinition 2444 | |-namespace 2445 | |-a 2446 | |-:: 2447 | |-b 2448 | |-{ 2449 | `-} 2450 |-NamespaceDefinition 2451 | |-namespace 2452 | |-{ 2453 | `-} 2454 `-NamespaceAliasDefinition 2455 |-namespace 2456 |-foo 2457 |-= 2458 |-a 2459 `-; 2460 )txt")); 2461 } 2462 2463 TEST_P(SyntaxTreeTest, UsingDirective) { 2464 if (!GetParam().isCXX()) { 2465 return; 2466 } 2467 EXPECT_TRUE(treeDumpEqual( 2468 R"cpp( 2469 namespace ns {} 2470 using namespace ::ns; 2471 )cpp", 2472 R"txt( 2473 *: TranslationUnit 2474 |-NamespaceDefinition 2475 | |-namespace 2476 | |-ns 2477 | |-{ 2478 | `-} 2479 `-UsingNamespaceDirective 2480 |-using 2481 |-namespace 2482 |-:: 2483 |-ns 2484 `-; 2485 )txt")); 2486 } 2487 2488 TEST_P(SyntaxTreeTest, UsingDeclaration) { 2489 if (!GetParam().isCXX()) { 2490 return; 2491 } 2492 EXPECT_TRUE(treeDumpEqual( 2493 R"cpp( 2494 namespace ns { int a; } 2495 using ns::a; 2496 )cpp", 2497 R"txt( 2498 *: TranslationUnit 2499 |-NamespaceDefinition 2500 | |-namespace 2501 | |-ns 2502 | |-{ 2503 | |-SimpleDeclaration 2504 | | |-int 2505 | | |-SimpleDeclarator 2506 | | | `-a 2507 | | `-; 2508 | `-} 2509 `-UsingDeclaration 2510 |-using 2511 |-ns 2512 |-:: 2513 |-a 2514 `-; 2515 )txt")); 2516 } 2517 2518 TEST_P(SyntaxTreeTest, FreeStandingClasses) { 2519 // Free-standing classes, must live inside a SimpleDeclaration. 2520 EXPECT_TRUE(treeDumpEqual( 2521 R"cpp( 2522 struct X; 2523 struct X {}; 2524 2525 struct Y *y1; 2526 struct Y {} *y2; 2527 2528 struct {} *a1; 2529 )cpp", 2530 R"txt( 2531 *: TranslationUnit 2532 |-SimpleDeclaration 2533 | |-struct 2534 | |-X 2535 | `-; 2536 |-SimpleDeclaration 2537 | |-struct 2538 | |-X 2539 | |-{ 2540 | |-} 2541 | `-; 2542 |-SimpleDeclaration 2543 | |-struct 2544 | |-Y 2545 | |-SimpleDeclarator 2546 | | |-* 2547 | | `-y1 2548 | `-; 2549 |-SimpleDeclaration 2550 | |-struct 2551 | |-Y 2552 | |-{ 2553 | |-} 2554 | |-SimpleDeclarator 2555 | | |-* 2556 | | `-y2 2557 | `-; 2558 `-SimpleDeclaration 2559 |-struct 2560 |-{ 2561 |-} 2562 |-SimpleDeclarator 2563 | |-* 2564 | `-a1 2565 `-; 2566 )txt")); 2567 } 2568 2569 TEST_P(SyntaxTreeTest, Templates) { 2570 if (!GetParam().isCXX()) { 2571 return; 2572 } 2573 if (GetParam().hasDelayedTemplateParsing()) { 2574 // FIXME: Make this test work on Windows by generating the expected syntax 2575 // tree when `-fdelayed-template-parsing` is active. 2576 return; 2577 } 2578 EXPECT_TRUE(treeDumpEqual( 2579 R"cpp( 2580 template <class T> struct cls {}; 2581 template <class T> int var = 10; 2582 template <class T> int fun() {} 2583 )cpp", 2584 R"txt( 2585 *: TranslationUnit 2586 |-TemplateDeclaration 2587 | |-template 2588 | |-< 2589 | |-UnknownDeclaration 2590 | | |-class 2591 | | `-T 2592 | |-> 2593 | `-SimpleDeclaration 2594 | |-struct 2595 | |-cls 2596 | |-{ 2597 | |-} 2598 | `-; 2599 |-TemplateDeclaration 2600 | |-template 2601 | |-< 2602 | |-UnknownDeclaration 2603 | | |-class 2604 | | `-T 2605 | |-> 2606 | `-SimpleDeclaration 2607 | |-int 2608 | |-SimpleDeclarator 2609 | | |-var 2610 | | |-= 2611 | | `-IntegerLiteralExpression 2612 | | `-10 2613 | `-; 2614 `-TemplateDeclaration 2615 |-template 2616 |-< 2617 |-UnknownDeclaration 2618 | |-class 2619 | `-T 2620 |-> 2621 `-SimpleDeclaration 2622 |-int 2623 |-SimpleDeclarator 2624 | |-fun 2625 | `-ParametersAndQualifiers 2626 | |-( 2627 | `-) 2628 `-CompoundStatement 2629 |-{ 2630 `-} 2631 )txt")); 2632 } 2633 2634 TEST_P(SyntaxTreeTest, NestedTemplates) { 2635 if (!GetParam().isCXX()) { 2636 return; 2637 } 2638 EXPECT_TRUE(treeDumpEqual( 2639 R"cpp( 2640 template <class T> 2641 struct X { 2642 template <class U> 2643 U foo(); 2644 }; 2645 )cpp", 2646 R"txt( 2647 *: TranslationUnit 2648 `-TemplateDeclaration 2649 |-template 2650 |-< 2651 |-UnknownDeclaration 2652 | |-class 2653 | `-T 2654 |-> 2655 `-SimpleDeclaration 2656 |-struct 2657 |-X 2658 |-{ 2659 |-TemplateDeclaration 2660 | |-template 2661 | |-< 2662 | |-UnknownDeclaration 2663 | | |-class 2664 | | `-U 2665 | |-> 2666 | `-SimpleDeclaration 2667 | |-U 2668 | |-SimpleDeclarator 2669 | | |-foo 2670 | | `-ParametersAndQualifiers 2671 | | |-( 2672 | | `-) 2673 | `-; 2674 |-} 2675 `-; 2676 )txt")); 2677 } 2678 2679 TEST_P(SyntaxTreeTest, Templates2) { 2680 if (!GetParam().isCXX()) { 2681 return; 2682 } 2683 EXPECT_TRUE(treeDumpEqual( 2684 R"cpp( 2685 template <class T> struct X { struct Y; }; 2686 template <class T> struct X<T>::Y {}; 2687 )cpp", 2688 R"txt( 2689 *: TranslationUnit 2690 |-TemplateDeclaration 2691 | |-template 2692 | |-< 2693 | |-UnknownDeclaration 2694 | | |-class 2695 | | `-T 2696 | |-> 2697 | `-SimpleDeclaration 2698 | |-struct 2699 | |-X 2700 | |-{ 2701 | |-SimpleDeclaration 2702 | | |-struct 2703 | | |-Y 2704 | | `-; 2705 | |-} 2706 | `-; 2707 `-TemplateDeclaration 2708 |-template 2709 |-< 2710 |-UnknownDeclaration 2711 | |-class 2712 | `-T 2713 |-> 2714 `-SimpleDeclaration 2715 |-struct 2716 |-X 2717 |-< 2718 |-T 2719 |-> 2720 |-:: 2721 |-Y 2722 |-{ 2723 |-} 2724 `-; 2725 )txt")); 2726 } 2727 2728 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) { 2729 if (!GetParam().isCXX()) { 2730 return; 2731 } 2732 EXPECT_TRUE(treeDumpEqual( 2733 R"cpp( 2734 template <class T> struct X { 2735 using T::foo; 2736 using typename T::bar; 2737 }; 2738 )cpp", 2739 R"txt( 2740 *: TranslationUnit 2741 `-TemplateDeclaration 2742 |-template 2743 |-< 2744 |-UnknownDeclaration 2745 | |-class 2746 | `-T 2747 |-> 2748 `-SimpleDeclaration 2749 |-struct 2750 |-X 2751 |-{ 2752 |-UsingDeclaration 2753 | |-using 2754 | |-T 2755 | |-:: 2756 | |-foo 2757 | `-; 2758 |-UsingDeclaration 2759 | |-using 2760 | |-typename 2761 | |-T 2762 | |-:: 2763 | |-bar 2764 | `-; 2765 |-} 2766 `-; 2767 )txt")); 2768 } 2769 2770 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) { 2771 if (!GetParam().isCXX()) { 2772 return; 2773 } 2774 EXPECT_TRUE(treeDumpEqual( 2775 R"cpp( 2776 template <class T> struct X {}; 2777 template <class T> struct X<T*> {}; 2778 template <> struct X<int> {}; 2779 2780 template struct X<double>; 2781 extern template struct X<float>; 2782 )cpp", 2783 R"txt( 2784 *: TranslationUnit 2785 |-TemplateDeclaration 2786 | |-template 2787 | |-< 2788 | |-UnknownDeclaration 2789 | | |-class 2790 | | `-T 2791 | |-> 2792 | `-SimpleDeclaration 2793 | |-struct 2794 | |-X 2795 | |-{ 2796 | |-} 2797 | `-; 2798 |-TemplateDeclaration 2799 | |-template 2800 | |-< 2801 | |-UnknownDeclaration 2802 | | |-class 2803 | | `-T 2804 | |-> 2805 | `-SimpleDeclaration 2806 | |-struct 2807 | |-X 2808 | |-< 2809 | |-T 2810 | |-* 2811 | |-> 2812 | |-{ 2813 | |-} 2814 | `-; 2815 |-TemplateDeclaration 2816 | |-template 2817 | |-< 2818 | |-> 2819 | `-SimpleDeclaration 2820 | |-struct 2821 | |-X 2822 | |-< 2823 | |-int 2824 | |-> 2825 | |-{ 2826 | |-} 2827 | `-; 2828 |-ExplicitTemplateInstantiation 2829 | |-template 2830 | `-SimpleDeclaration 2831 | |-struct 2832 | |-X 2833 | |-< 2834 | |-double 2835 | |-> 2836 | `-; 2837 `-ExplicitTemplateInstantiation 2838 |-extern 2839 |-template 2840 `-SimpleDeclaration 2841 |-struct 2842 |-X 2843 |-< 2844 |-float 2845 |-> 2846 `-; 2847 )txt")); 2848 } 2849 2850 TEST_P(SyntaxTreeTest, UsingType) { 2851 if (!GetParam().isCXX()) { 2852 return; 2853 } 2854 EXPECT_TRUE(treeDumpEqual( 2855 R"cpp( 2856 using type = int; 2857 )cpp", 2858 R"txt( 2859 *: TranslationUnit 2860 `-TypeAliasDeclaration 2861 |-using 2862 |-type 2863 |-= 2864 |-int 2865 `-; 2866 )txt")); 2867 } 2868 2869 TEST_P(SyntaxTreeTest, EmptyDeclaration) { 2870 EXPECT_TRUE(treeDumpEqual( 2871 R"cpp( 2872 ; 2873 )cpp", 2874 R"txt( 2875 *: TranslationUnit 2876 `-EmptyDeclaration 2877 `-; 2878 )txt")); 2879 } 2880 2881 TEST_P(SyntaxTreeTest, StaticAssert) { 2882 if (!GetParam().isCXX11OrLater()) { 2883 return; 2884 } 2885 EXPECT_TRUE(treeDumpEqual( 2886 R"cpp( 2887 static_assert(true, "message"); 2888 static_assert(true); 2889 )cpp", 2890 R"txt( 2891 *: TranslationUnit 2892 |-StaticAssertDeclaration 2893 | |-static_assert 2894 | |-( 2895 | |-BoolLiteralExpression 2896 | | `-true 2897 | |-, 2898 | |-StringLiteralExpression 2899 | | `-"message" 2900 | |-) 2901 | `-; 2902 `-StaticAssertDeclaration 2903 |-static_assert 2904 |-( 2905 |-BoolLiteralExpression 2906 | `-true 2907 |-) 2908 `-; 2909 )txt")); 2910 } 2911 2912 TEST_P(SyntaxTreeTest, ExternC) { 2913 if (!GetParam().isCXX()) { 2914 return; 2915 } 2916 EXPECT_TRUE(treeDumpEqual( 2917 R"cpp( 2918 extern "C" int a; 2919 extern "C" { int b; int c; } 2920 )cpp", 2921 R"txt( 2922 *: TranslationUnit 2923 |-LinkageSpecificationDeclaration 2924 | |-extern 2925 | |-"C" 2926 | `-SimpleDeclaration 2927 | |-int 2928 | |-SimpleDeclarator 2929 | | `-a 2930 | `-; 2931 `-LinkageSpecificationDeclaration 2932 |-extern 2933 |-"C" 2934 |-{ 2935 |-SimpleDeclaration 2936 | |-int 2937 | |-SimpleDeclarator 2938 | | `-b 2939 | `-; 2940 |-SimpleDeclaration 2941 | |-int 2942 | |-SimpleDeclarator 2943 | | `-c 2944 | `-; 2945 `-} 2946 )txt")); 2947 } 2948 2949 TEST_P(SyntaxTreeTest, NonModifiableNodes) { 2950 // Some nodes are non-modifiable, they are marked with 'I:'. 2951 EXPECT_TRUE(treeDumpEqual( 2952 R"cpp( 2953 #define HALF_IF if (1+ 2954 #define HALF_IF_2 1) {} 2955 void test() { 2956 HALF_IF HALF_IF_2 else {} 2957 })cpp", 2958 R"txt( 2959 *: TranslationUnit 2960 `-SimpleDeclaration 2961 |-void 2962 |-SimpleDeclarator 2963 | |-test 2964 | `-ParametersAndQualifiers 2965 | |-( 2966 | `-) 2967 `-CompoundStatement 2968 |-{ 2969 |-IfStatement 2970 | |-I: if 2971 | |-I: ( 2972 | |-I: BinaryOperatorExpression 2973 | | |-I: IntegerLiteralExpression 2974 | | | `-I: 1 2975 | | |-I: + 2976 | | `-I: IntegerLiteralExpression 2977 | | `-I: 1 2978 | |-I: ) 2979 | |-I: CompoundStatement 2980 | | |-I: { 2981 | | `-I: } 2982 | |-else 2983 | `-CompoundStatement 2984 | |-{ 2985 | `-} 2986 `-} 2987 )txt")); 2988 } 2989 2990 TEST_P(SyntaxTreeTest, ModifiableNodes) { 2991 // All nodes can be mutated. 2992 EXPECT_TRUE(treeDumpEqual( 2993 R"cpp( 2994 #define OPEN { 2995 #define CLOSE } 2996 2997 void test() { 2998 OPEN 2999 1; 3000 CLOSE 3001 3002 OPEN 3003 2; 3004 } 3005 } 3006 )cpp", 3007 R"txt( 3008 *: TranslationUnit 3009 `-SimpleDeclaration 3010 |-void 3011 |-SimpleDeclarator 3012 | |-test 3013 | `-ParametersAndQualifiers 3014 | |-( 3015 | `-) 3016 `-CompoundStatement 3017 |-{ 3018 |-CompoundStatement 3019 | |-{ 3020 | |-ExpressionStatement 3021 | | |-IntegerLiteralExpression 3022 | | | `-1 3023 | | `-; 3024 | `-} 3025 |-CompoundStatement 3026 | |-{ 3027 | |-ExpressionStatement 3028 | | |-IntegerLiteralExpression 3029 | | | `-2 3030 | | `-; 3031 | `-} 3032 `-} 3033 )txt")); 3034 } 3035 3036 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) { 3037 EXPECT_TRUE(treeDumpEqual( 3038 R"cpp( 3039 int a[10]; 3040 int b[1][2][3]; 3041 int c[] = {1,2,3}; 3042 )cpp", 3043 R"txt( 3044 *: TranslationUnit 3045 |-SimpleDeclaration 3046 | |-int 3047 | |-SimpleDeclarator 3048 | | |-a 3049 | | `-ArraySubscript 3050 | | |-[ 3051 | | |-IntegerLiteralExpression 3052 | | | `-10 3053 | | `-] 3054 | `-; 3055 |-SimpleDeclaration 3056 | |-int 3057 | |-SimpleDeclarator 3058 | | |-b 3059 | | |-ArraySubscript 3060 | | | |-[ 3061 | | | |-IntegerLiteralExpression 3062 | | | | `-1 3063 | | | `-] 3064 | | |-ArraySubscript 3065 | | | |-[ 3066 | | | |-IntegerLiteralExpression 3067 | | | | `-2 3068 | | | `-] 3069 | | `-ArraySubscript 3070 | | |-[ 3071 | | |-IntegerLiteralExpression 3072 | | | `-3 3073 | | `-] 3074 | `-; 3075 `-SimpleDeclaration 3076 |-int 3077 |-SimpleDeclarator 3078 | |-c 3079 | |-ArraySubscript 3080 | | |-[ 3081 | | `-] 3082 | |-= 3083 | `-UnknownExpression 3084 | `-UnknownExpression 3085 | |-{ 3086 | |-IntegerLiteralExpression 3087 | | `-1 3088 | |-, 3089 | |-IntegerLiteralExpression 3090 | | `-2 3091 | |-, 3092 | |-IntegerLiteralExpression 3093 | | `-3 3094 | `-} 3095 `-; 3096 )txt")); 3097 } 3098 3099 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) { 3100 if (!GetParam().isC99OrLater()) { 3101 return; 3102 } 3103 EXPECT_TRUE(treeDumpEqual( 3104 R"cpp( 3105 void f(int xs[static 10]); 3106 )cpp", 3107 R"txt( 3108 *: TranslationUnit 3109 `-SimpleDeclaration 3110 |-void 3111 |-SimpleDeclarator 3112 | |-f 3113 | `-ParametersAndQualifiers 3114 | |-( 3115 | |-SimpleDeclaration 3116 | | |-int 3117 | | `-SimpleDeclarator 3118 | | |-xs 3119 | | `-ArraySubscript 3120 | | |-[ 3121 | | |-static 3122 | | |-IntegerLiteralExpression 3123 | | | `-10 3124 | | `-] 3125 | `-) 3126 `-; 3127 )txt")); 3128 } 3129 3130 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) { 3131 if (!GetParam().isCXX()) { 3132 return; 3133 } 3134 EXPECT_TRUE(treeDumpEqual( 3135 R"cpp( 3136 int func1(); 3137 int func2a(int a); 3138 int func2b(int); 3139 int func3a(int *ap); 3140 int func3b(int *); 3141 int func4a(int a, float b); 3142 int func4b(int, float); 3143 )cpp", 3144 R"txt( 3145 *: TranslationUnit 3146 |-SimpleDeclaration 3147 | |-int 3148 | |-SimpleDeclarator 3149 | | |-func1 3150 | | `-ParametersAndQualifiers 3151 | | |-( 3152 | | `-) 3153 | `-; 3154 |-SimpleDeclaration 3155 | |-int 3156 | |-SimpleDeclarator 3157 | | |-func2a 3158 | | `-ParametersAndQualifiers 3159 | | |-( 3160 | | |-SimpleDeclaration 3161 | | | |-int 3162 | | | `-SimpleDeclarator 3163 | | | `-a 3164 | | `-) 3165 | `-; 3166 |-SimpleDeclaration 3167 | |-int 3168 | |-SimpleDeclarator 3169 | | |-func2b 3170 | | `-ParametersAndQualifiers 3171 | | |-( 3172 | | |-SimpleDeclaration 3173 | | | `-int 3174 | | `-) 3175 | `-; 3176 |-SimpleDeclaration 3177 | |-int 3178 | |-SimpleDeclarator 3179 | | |-func3a 3180 | | `-ParametersAndQualifiers 3181 | | |-( 3182 | | |-SimpleDeclaration 3183 | | | |-int 3184 | | | `-SimpleDeclarator 3185 | | | |-* 3186 | | | `-ap 3187 | | `-) 3188 | `-; 3189 |-SimpleDeclaration 3190 | |-int 3191 | |-SimpleDeclarator 3192 | | |-func3b 3193 | | `-ParametersAndQualifiers 3194 | | |-( 3195 | | |-SimpleDeclaration 3196 | | | |-int 3197 | | | `-SimpleDeclarator 3198 | | | `-* 3199 | | `-) 3200 | `-; 3201 |-SimpleDeclaration 3202 | |-int 3203 | |-SimpleDeclarator 3204 | | |-func4a 3205 | | `-ParametersAndQualifiers 3206 | | |-( 3207 | | |-SimpleDeclaration 3208 | | | |-int 3209 | | | `-SimpleDeclarator 3210 | | | `-a 3211 | | |-, 3212 | | |-SimpleDeclaration 3213 | | | |-float 3214 | | | `-SimpleDeclarator 3215 | | | `-b 3216 | | `-) 3217 | `-; 3218 `-SimpleDeclaration 3219 |-int 3220 |-SimpleDeclarator 3221 | |-func4b 3222 | `-ParametersAndQualifiers 3223 | |-( 3224 | |-SimpleDeclaration 3225 | | `-int 3226 | |-, 3227 | |-SimpleDeclaration 3228 | | `-float 3229 | `-) 3230 `-; 3231 )txt")); 3232 } 3233 3234 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) { 3235 if (!GetParam().isCXX()) { 3236 return; 3237 } 3238 EXPECT_TRUE(treeDumpEqual( 3239 R"cpp( 3240 int func1(const int a, volatile int b, const volatile int c); 3241 int func2(int& a); 3242 )cpp", 3243 R"txt( 3244 *: TranslationUnit 3245 |-SimpleDeclaration 3246 | |-int 3247 | |-SimpleDeclarator 3248 | | |-func1 3249 | | `-ParametersAndQualifiers 3250 | | |-( 3251 | | |-SimpleDeclaration 3252 | | | |-const 3253 | | | |-int 3254 | | | `-SimpleDeclarator 3255 | | | `-a 3256 | | |-, 3257 | | |-SimpleDeclaration 3258 | | | |-volatile 3259 | | | |-int 3260 | | | `-SimpleDeclarator 3261 | | | `-b 3262 | | |-, 3263 | | |-SimpleDeclaration 3264 | | | |-const 3265 | | | |-volatile 3266 | | | |-int 3267 | | | `-SimpleDeclarator 3268 | | | `-c 3269 | | `-) 3270 | `-; 3271 `-SimpleDeclaration 3272 |-int 3273 |-SimpleDeclarator 3274 | |-func2 3275 | `-ParametersAndQualifiers 3276 | |-( 3277 | |-SimpleDeclaration 3278 | | |-int 3279 | | `-SimpleDeclarator 3280 | | |-& 3281 | | `-a 3282 | `-) 3283 `-; 3284 )txt")); 3285 } 3286 3287 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) { 3288 if (!GetParam().isCXX11OrLater()) { 3289 return; 3290 } 3291 EXPECT_TRUE(treeDumpEqual( 3292 R"cpp( 3293 int func1(int&& a); 3294 )cpp", 3295 R"txt( 3296 *: TranslationUnit 3297 `-SimpleDeclaration 3298 |-int 3299 |-SimpleDeclarator 3300 | |-func1 3301 | `-ParametersAndQualifiers 3302 | |-( 3303 | |-SimpleDeclaration 3304 | | |-int 3305 | | `-SimpleDeclarator 3306 | | |-&& 3307 | | `-a 3308 | `-) 3309 `-; 3310 )txt")); 3311 } 3312 3313 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) { 3314 if (!GetParam().isCXX()) { 3315 return; 3316 } 3317 EXPECT_TRUE(treeDumpEqual( 3318 R"cpp( 3319 struct Test { 3320 int a(); 3321 int b() const; 3322 int c() volatile; 3323 int d() const volatile; 3324 int e() &; 3325 int f() &&; 3326 }; 3327 )cpp", 3328 R"txt( 3329 *: TranslationUnit 3330 `-SimpleDeclaration 3331 |-struct 3332 |-Test 3333 |-{ 3334 |-SimpleDeclaration 3335 | |-int 3336 | |-SimpleDeclarator 3337 | | |-a 3338 | | `-ParametersAndQualifiers 3339 | | |-( 3340 | | `-) 3341 | `-; 3342 |-SimpleDeclaration 3343 | |-int 3344 | |-SimpleDeclarator 3345 | | |-b 3346 | | `-ParametersAndQualifiers 3347 | | |-( 3348 | | |-) 3349 | | `-const 3350 | `-; 3351 |-SimpleDeclaration 3352 | |-int 3353 | |-SimpleDeclarator 3354 | | |-c 3355 | | `-ParametersAndQualifiers 3356 | | |-( 3357 | | |-) 3358 | | `-volatile 3359 | `-; 3360 |-SimpleDeclaration 3361 | |-int 3362 | |-SimpleDeclarator 3363 | | |-d 3364 | | `-ParametersAndQualifiers 3365 | | |-( 3366 | | |-) 3367 | | |-const 3368 | | `-volatile 3369 | `-; 3370 |-SimpleDeclaration 3371 | |-int 3372 | |-SimpleDeclarator 3373 | | |-e 3374 | | `-ParametersAndQualifiers 3375 | | |-( 3376 | | |-) 3377 | | `-& 3378 | `-; 3379 |-SimpleDeclaration 3380 | |-int 3381 | |-SimpleDeclarator 3382 | | |-f 3383 | | `-ParametersAndQualifiers 3384 | | |-( 3385 | | |-) 3386 | | `-&& 3387 | `-; 3388 |-} 3389 `-; 3390 )txt")); 3391 } 3392 3393 TEST_P(SyntaxTreeTest, TrailingReturn) { 3394 if (!GetParam().isCXX11OrLater()) { 3395 return; 3396 } 3397 EXPECT_TRUE(treeDumpEqual( 3398 R"cpp( 3399 auto foo() -> int; 3400 )cpp", 3401 R"txt( 3402 *: TranslationUnit 3403 `-SimpleDeclaration 3404 |-auto 3405 |-SimpleDeclarator 3406 | |-foo 3407 | `-ParametersAndQualifiers 3408 | |-( 3409 | |-) 3410 | `-TrailingReturnType 3411 | |--> 3412 | `-int 3413 `-; 3414 )txt")); 3415 } 3416 3417 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) { 3418 if (!GetParam().supportsCXXDynamicExceptionSpecification()) { 3419 return; 3420 } 3421 EXPECT_TRUE(treeDumpEqual( 3422 R"cpp( 3423 struct MyException1 {}; 3424 struct MyException2 {}; 3425 int a() throw(); 3426 int b() throw(...); 3427 int c() throw(MyException1); 3428 int d() throw(MyException1, MyException2); 3429 )cpp", 3430 R"txt( 3431 *: TranslationUnit 3432 |-SimpleDeclaration 3433 | |-struct 3434 | |-MyException1 3435 | |-{ 3436 | |-} 3437 | `-; 3438 |-SimpleDeclaration 3439 | |-struct 3440 | |-MyException2 3441 | |-{ 3442 | |-} 3443 | `-; 3444 |-SimpleDeclaration 3445 | |-int 3446 | |-SimpleDeclarator 3447 | | |-a 3448 | | `-ParametersAndQualifiers 3449 | | |-( 3450 | | |-) 3451 | | |-throw 3452 | | |-( 3453 | | `-) 3454 | `-; 3455 |-SimpleDeclaration 3456 | |-int 3457 | |-SimpleDeclarator 3458 | | |-b 3459 | | `-ParametersAndQualifiers 3460 | | |-( 3461 | | |-) 3462 | | |-throw 3463 | | |-( 3464 | | |-... 3465 | | `-) 3466 | `-; 3467 |-SimpleDeclaration 3468 | |-int 3469 | |-SimpleDeclarator 3470 | | |-c 3471 | | `-ParametersAndQualifiers 3472 | | |-( 3473 | | |-) 3474 | | |-throw 3475 | | |-( 3476 | | |-MyException1 3477 | | `-) 3478 | `-; 3479 `-SimpleDeclaration 3480 |-int 3481 |-SimpleDeclarator 3482 | |-d 3483 | `-ParametersAndQualifiers 3484 | |-( 3485 | |-) 3486 | |-throw 3487 | |-( 3488 | |-MyException1 3489 | |-, 3490 | |-MyException2 3491 | `-) 3492 `-; 3493 )txt")); 3494 } 3495 3496 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) { 3497 if (!GetParam().isCXX11OrLater()) { 3498 return; 3499 } 3500 EXPECT_TRUE(treeDumpEqual( 3501 R"cpp( 3502 int a() noexcept; 3503 int b() noexcept(true); 3504 )cpp", 3505 R"txt( 3506 *: TranslationUnit 3507 |-SimpleDeclaration 3508 | |-int 3509 | |-SimpleDeclarator 3510 | | |-a 3511 | | `-ParametersAndQualifiers 3512 | | |-( 3513 | | |-) 3514 | | `-noexcept 3515 | `-; 3516 `-SimpleDeclaration 3517 |-int 3518 |-SimpleDeclarator 3519 | |-b 3520 | `-ParametersAndQualifiers 3521 | |-( 3522 | |-) 3523 | |-noexcept 3524 | |-( 3525 | |-BoolLiteralExpression 3526 | | `-true 3527 | `-) 3528 `-; 3529 )txt")); 3530 } 3531 3532 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) { 3533 EXPECT_TRUE(treeDumpEqual( 3534 R"cpp( 3535 int (a); 3536 int *(b); 3537 int (*c)(int); 3538 int *(d)(int); 3539 )cpp", 3540 R"txt( 3541 *: TranslationUnit 3542 |-SimpleDeclaration 3543 | |-int 3544 | |-SimpleDeclarator 3545 | | `-ParenDeclarator 3546 | | |-( 3547 | | |-a 3548 | | `-) 3549 | `-; 3550 |-SimpleDeclaration 3551 | |-int 3552 | |-SimpleDeclarator 3553 | | |-* 3554 | | `-ParenDeclarator 3555 | | |-( 3556 | | |-b 3557 | | `-) 3558 | `-; 3559 |-SimpleDeclaration 3560 | |-int 3561 | |-SimpleDeclarator 3562 | | |-ParenDeclarator 3563 | | | |-( 3564 | | | |-* 3565 | | | |-c 3566 | | | `-) 3567 | | `-ParametersAndQualifiers 3568 | | |-( 3569 | | |-SimpleDeclaration 3570 | | | `-int 3571 | | `-) 3572 | `-; 3573 `-SimpleDeclaration 3574 |-int 3575 |-SimpleDeclarator 3576 | |-* 3577 | |-ParenDeclarator 3578 | | |-( 3579 | | |-d 3580 | | `-) 3581 | `-ParametersAndQualifiers 3582 | |-( 3583 | |-SimpleDeclaration 3584 | | `-int 3585 | `-) 3586 `-; 3587 )txt")); 3588 } 3589 3590 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) { 3591 EXPECT_TRUE(treeDumpEqual( 3592 R"cpp( 3593 const int west = -1; 3594 int const east = 1; 3595 const int const universal = 0; 3596 const int const *const *volatile b; 3597 )cpp", 3598 R"txt( 3599 *: TranslationUnit 3600 |-SimpleDeclaration 3601 | |-const 3602 | |-int 3603 | |-SimpleDeclarator 3604 | | |-west 3605 | | |-= 3606 | | `-PrefixUnaryOperatorExpression 3607 | | |-- 3608 | | `-IntegerLiteralExpression 3609 | | `-1 3610 | `-; 3611 |-SimpleDeclaration 3612 | |-int 3613 | |-const 3614 | |-SimpleDeclarator 3615 | | |-east 3616 | | |-= 3617 | | `-IntegerLiteralExpression 3618 | | `-1 3619 | `-; 3620 |-SimpleDeclaration 3621 | |-const 3622 | |-int 3623 | |-const 3624 | |-SimpleDeclarator 3625 | | |-universal 3626 | | |-= 3627 | | `-IntegerLiteralExpression 3628 | | `-0 3629 | `-; 3630 `-SimpleDeclaration 3631 |-const 3632 |-int 3633 |-const 3634 |-SimpleDeclarator 3635 | |-* 3636 | |-const 3637 | |-* 3638 | |-volatile 3639 | `-b 3640 `-; 3641 )txt")); 3642 } 3643 3644 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) { 3645 if (!GetParam().isCXX11OrLater()) { 3646 return; 3647 } 3648 EXPECT_TRUE(treeDumpEqual( 3649 R"cpp( 3650 auto foo() -> auto(*)(int) -> double*; 3651 )cpp", 3652 R"txt( 3653 *: TranslationUnit 3654 `-SimpleDeclaration 3655 |-auto 3656 |-SimpleDeclarator 3657 | |-foo 3658 | `-ParametersAndQualifiers 3659 | |-( 3660 | |-) 3661 | `-TrailingReturnType 3662 | |--> 3663 | |-auto 3664 | `-SimpleDeclarator 3665 | |-ParenDeclarator 3666 | | |-( 3667 | | |-* 3668 | | `-) 3669 | `-ParametersAndQualifiers 3670 | |-( 3671 | |-SimpleDeclaration 3672 | | `-int 3673 | |-) 3674 | `-TrailingReturnType 3675 | |--> 3676 | |-double 3677 | `-SimpleDeclarator 3678 | `-* 3679 `-; 3680 )txt")); 3681 } 3682 3683 TEST_P(SyntaxTreeTest, MemberPointers) { 3684 if (!GetParam().isCXX()) { 3685 return; 3686 } 3687 EXPECT_TRUE(treeDumpEqual( 3688 R"cpp( 3689 struct X {}; 3690 int X::* a; 3691 const int X::* b; 3692 )cpp", 3693 R"txt( 3694 *: TranslationUnit 3695 |-SimpleDeclaration 3696 | |-struct 3697 | |-X 3698 | |-{ 3699 | |-} 3700 | `-; 3701 |-SimpleDeclaration 3702 | |-int 3703 | |-SimpleDeclarator 3704 | | |-MemberPointer 3705 | | | |-X 3706 | | | |-:: 3707 | | | `-* 3708 | | `-a 3709 | `-; 3710 `-SimpleDeclaration 3711 |-const 3712 |-int 3713 |-SimpleDeclarator 3714 | |-MemberPointer 3715 | | |-X 3716 | | |-:: 3717 | | `-* 3718 | `-b 3719 `-; 3720 )txt")); 3721 } 3722 3723 TEST_P(SyntaxTreeTest, ComplexDeclarator) { 3724 EXPECT_TRUE(treeDumpEqual( 3725 R"cpp( 3726 void x(char a, short (*b)(int)); 3727 )cpp", 3728 R"txt( 3729 *: TranslationUnit 3730 `-SimpleDeclaration 3731 |-void 3732 |-SimpleDeclarator 3733 | |-x 3734 | `-ParametersAndQualifiers 3735 | |-( 3736 | |-SimpleDeclaration 3737 | | |-char 3738 | | `-SimpleDeclarator 3739 | | `-a 3740 | |-, 3741 | |-SimpleDeclaration 3742 | | |-short 3743 | | `-SimpleDeclarator 3744 | | |-ParenDeclarator 3745 | | | |-( 3746 | | | |-* 3747 | | | |-b 3748 | | | `-) 3749 | | `-ParametersAndQualifiers 3750 | | |-( 3751 | | |-SimpleDeclaration 3752 | | | `-int 3753 | | `-) 3754 | `-) 3755 `-; 3756 )txt")); 3757 } 3758 3759 TEST_P(SyntaxTreeTest, ComplexDeclarator2) { 3760 EXPECT_TRUE(treeDumpEqual( 3761 R"cpp( 3762 void x(char a, short (*b)(int), long (**c)(long long)); 3763 )cpp", 3764 R"txt( 3765 *: TranslationUnit 3766 `-SimpleDeclaration 3767 |-void 3768 |-SimpleDeclarator 3769 | |-x 3770 | `-ParametersAndQualifiers 3771 | |-( 3772 | |-SimpleDeclaration 3773 | | |-char 3774 | | `-SimpleDeclarator 3775 | | `-a 3776 | |-, 3777 | |-SimpleDeclaration 3778 | | |-short 3779 | | `-SimpleDeclarator 3780 | | |-ParenDeclarator 3781 | | | |-( 3782 | | | |-* 3783 | | | |-b 3784 | | | `-) 3785 | | `-ParametersAndQualifiers 3786 | | |-( 3787 | | |-SimpleDeclaration 3788 | | | `-int 3789 | | `-) 3790 | |-, 3791 | |-SimpleDeclaration 3792 | | |-long 3793 | | `-SimpleDeclarator 3794 | | |-ParenDeclarator 3795 | | | |-( 3796 | | | |-* 3797 | | | |-* 3798 | | | |-c 3799 | | | `-) 3800 | | `-ParametersAndQualifiers 3801 | | |-( 3802 | | |-SimpleDeclaration 3803 | | | |-long 3804 | | | `-long 3805 | | `-) 3806 | `-) 3807 `-; 3808 )txt")); 3809 } 3810 3811 TEST_P(SyntaxTreeTest, Mutations) { 3812 if (!GetParam().isCXX11OrLater()) { 3813 return; 3814 } 3815 3816 using Transformation = std::function<void( 3817 const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>; 3818 auto CheckTransformation = [this](std::string Input, std::string Expected, 3819 Transformation Transform) -> void { 3820 llvm::Annotations Source(Input); 3821 auto *Root = buildTree(Source.code(), GetParam()); 3822 3823 Transform(Source, Root); 3824 3825 auto Replacements = syntax::computeReplacements(*Arena, *Root); 3826 auto Output = tooling::applyAllReplacements(Source.code(), Replacements); 3827 if (!Output) { 3828 ADD_FAILURE() << "could not apply replacements: " 3829 << llvm::toString(Output.takeError()); 3830 return; 3831 } 3832 3833 EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; 3834 }; 3835 3836 // Removes the selected statement. Input should have exactly one selected 3837 // range and it should correspond to a single statement. 3838 auto RemoveStatement = [this](const llvm::Annotations &Input, 3839 syntax::TranslationUnit *TU) { 3840 auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU)); 3841 ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 3842 syntax::removeStatement(*Arena, S); 3843 EXPECT_TRUE(S->isDetached()); 3844 EXPECT_FALSE(S->isOriginal()) 3845 << "node removed from tree cannot be marked as original"; 3846 }; 3847 3848 std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>> 3849 Cases = { 3850 {"void test() { [[100+100;]] test(); }", "void test() { test(); }"}, 3851 {"void test() { if (true) [[{}]] else {} }", 3852 "void test() { if (true) ; else {} }"}, 3853 {"void test() { [[;]] }", "void test() { }"}}; 3854 for (const auto &C : Cases) 3855 CheckTransformation(C.first, C.second, RemoveStatement); 3856 } 3857 3858 TEST_P(SyntaxTreeTest, SynthesizedNodes) { 3859 buildTree("", GetParam()); 3860 3861 auto *C = syntax::createPunctuation(*Arena, tok::comma); 3862 ASSERT_NE(C, nullptr); 3863 EXPECT_EQ(C->token()->kind(), tok::comma); 3864 EXPECT_TRUE(C->canModify()); 3865 EXPECT_FALSE(C->isOriginal()); 3866 EXPECT_TRUE(C->isDetached()); 3867 3868 auto *S = syntax::createEmptyStatement(*Arena); 3869 ASSERT_NE(S, nullptr); 3870 EXPECT_TRUE(S->canModify()); 3871 EXPECT_FALSE(S->isOriginal()); 3872 EXPECT_TRUE(S->isDetached()); 3873 } 3874 3875 static std::vector<TestClangConfig> allTestClangConfigs() { 3876 std::vector<TestClangConfig> all_configs; 3877 for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11, 3878 Lang_CXX14, Lang_CXX17, Lang_CXX20}) { 3879 TestClangConfig config; 3880 config.Language = lang; 3881 config.Target = "x86_64-pc-linux-gnu"; 3882 all_configs.push_back(config); 3883 3884 // Windows target is interesting to test because it enables 3885 // `-fdelayed-template-parsing`. 3886 config.Target = "x86_64-pc-win32-msvc"; 3887 all_configs.push_back(config); 3888 } 3889 return all_configs; 3890 } 3891 3892 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest, 3893 testing::ValuesIn(allTestClangConfigs()), ); 3894 3895 } // namespace 3896