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