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 | |-UnknownExpression 489 | | `-a 490 | |-) 491 | `-EmptyStatement 492 | `-; 493 `-} 494 )txt")); 495 } 496 497 TEST_P(SyntaxTreeTest, DeclarationStatement) { 498 EXPECT_TRUE(treeDumpEqual( 499 R"cpp( 500 void test() { 501 int a = 10; 502 } 503 )cpp", 504 R"txt( 505 *: TranslationUnit 506 `-SimpleDeclaration 507 |-void 508 |-SimpleDeclarator 509 | |-test 510 | `-ParametersAndQualifiers 511 | |-( 512 | `-) 513 `-CompoundStatement 514 |-{ 515 |-DeclarationStatement 516 | |-SimpleDeclaration 517 | | |-int 518 | | `-SimpleDeclarator 519 | | |-a 520 | | |-= 521 | | `-IntegerLiteralExpression 522 | | `-10 523 | `-; 524 `-} 525 )txt")); 526 } 527 528 TEST_P(SyntaxTreeTest, Switch) { 529 EXPECT_TRUE(treeDumpEqual( 530 R"cpp( 531 void test() { 532 switch (1) { 533 case 0: 534 default:; 535 } 536 } 537 )cpp", 538 R"txt( 539 *: TranslationUnit 540 `-SimpleDeclaration 541 |-void 542 |-SimpleDeclarator 543 | |-test 544 | `-ParametersAndQualifiers 545 | |-( 546 | `-) 547 `-CompoundStatement 548 |-{ 549 |-SwitchStatement 550 | |-switch 551 | |-( 552 | |-IntegerLiteralExpression 553 | | `-1 554 | |-) 555 | `-CompoundStatement 556 | |-{ 557 | |-CaseStatement 558 | | |-case 559 | | |-IntegerLiteralExpression 560 | | | `-0 561 | | |-: 562 | | `-DefaultStatement 563 | | |-default 564 | | |-: 565 | | `-EmptyStatement 566 | | `-; 567 | `-} 568 `-} 569 )txt")); 570 } 571 572 TEST_P(SyntaxTreeTest, While) { 573 EXPECT_TRUE(treeDumpEqual( 574 R"cpp( 575 void test() { 576 while (1) { continue; break; } 577 } 578 )cpp", 579 R"txt( 580 *: TranslationUnit 581 `-SimpleDeclaration 582 |-void 583 |-SimpleDeclarator 584 | |-test 585 | `-ParametersAndQualifiers 586 | |-( 587 | `-) 588 `-CompoundStatement 589 |-{ 590 |-WhileStatement 591 | |-while 592 | |-( 593 | |-IntegerLiteralExpression 594 | | `-1 595 | |-) 596 | `-CompoundStatement 597 | |-{ 598 | |-ContinueStatement 599 | | |-continue 600 | | `-; 601 | |-BreakStatement 602 | | |-break 603 | | `-; 604 | `-} 605 `-} 606 )txt")); 607 } 608 609 TEST_P(SyntaxTreeTest, UnhandledStatement) { 610 // Unhandled statements should end up as 'unknown statement'. 611 // This example uses a 'label statement', which does not yet have a syntax 612 // counterpart. 613 EXPECT_TRUE(treeDumpEqual( 614 R"cpp( 615 int main() { 616 foo: return 100; 617 } 618 )cpp", 619 R"txt( 620 *: TranslationUnit 621 `-SimpleDeclaration 622 |-int 623 |-SimpleDeclarator 624 | |-main 625 | `-ParametersAndQualifiers 626 | |-( 627 | `-) 628 `-CompoundStatement 629 |-{ 630 |-UnknownStatement 631 | |-foo 632 | |-: 633 | `-ReturnStatement 634 | |-return 635 | |-IntegerLiteralExpression 636 | | `-100 637 | `-; 638 `-} 639 )txt")); 640 } 641 642 TEST_P(SyntaxTreeTest, Expressions) { 643 // expressions should be wrapped in 'ExpressionStatement' when they appear 644 // in a statement position. 645 EXPECT_TRUE(treeDumpEqual( 646 R"cpp( 647 void test() { 648 test(); 649 if (1) test(); else test(); 650 } 651 )cpp", 652 R"txt( 653 *: TranslationUnit 654 `-SimpleDeclaration 655 |-void 656 |-SimpleDeclarator 657 | |-test 658 | `-ParametersAndQualifiers 659 | |-( 660 | `-) 661 `-CompoundStatement 662 |-{ 663 |-ExpressionStatement 664 | |-UnknownExpression 665 | | |-UnknownExpression 666 | | | `-test 667 | | |-( 668 | | `-) 669 | `-; 670 |-IfStatement 671 | |-if 672 | |-( 673 | |-IntegerLiteralExpression 674 | | `-1 675 | |-) 676 | |-ExpressionStatement 677 | | |-UnknownExpression 678 | | | |-UnknownExpression 679 | | | | `-test 680 | | | |-( 681 | | | `-) 682 | | `-; 683 | |-else 684 | `-ExpressionStatement 685 | |-UnknownExpression 686 | | |-UnknownExpression 687 | | | `-test 688 | | |-( 689 | | `-) 690 | `-; 691 `-} 692 )txt")); 693 } 694 695 TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) { 696 if (!GetParam().isCXX11OrLater()) { 697 return; 698 } 699 EXPECT_TRUE(treeDumpEqual( 700 R"cpp( 701 void test() { 702 nullptr; 703 } 704 )cpp", 705 R"txt( 706 *: TranslationUnit 707 `-SimpleDeclaration 708 |-void 709 |-SimpleDeclarator 710 | |-test 711 | `-ParametersAndQualifiers 712 | |-( 713 | `-) 714 `-CompoundStatement 715 |-{ 716 |-ExpressionStatement 717 | |-CxxNullPtrExpression 718 | | `-nullptr 719 | `-; 720 `-} 721 )txt")); 722 } 723 724 TEST_P(SyntaxTreeTest, IntegerLiteral) { 725 EXPECT_TRUE(treeDumpEqual( 726 R"cpp( 727 void test() { 728 12; 729 12u; 730 12l; 731 12ul; 732 014; 733 0XC; 734 } 735 )cpp", 736 R"txt( 737 *: TranslationUnit 738 `-SimpleDeclaration 739 |-void 740 |-SimpleDeclarator 741 | |-test 742 | `-ParametersAndQualifiers 743 | |-( 744 | `-) 745 `-CompoundStatement 746 |-{ 747 |-ExpressionStatement 748 | |-IntegerLiteralExpression 749 | | `-12 750 | `-; 751 |-ExpressionStatement 752 | |-IntegerLiteralExpression 753 | | `-12u 754 | `-; 755 |-ExpressionStatement 756 | |-IntegerLiteralExpression 757 | | `-12l 758 | `-; 759 |-ExpressionStatement 760 | |-IntegerLiteralExpression 761 | | `-12ul 762 | `-; 763 |-ExpressionStatement 764 | |-IntegerLiteralExpression 765 | | `-014 766 | `-; 767 |-ExpressionStatement 768 | |-IntegerLiteralExpression 769 | | `-0XC 770 | `-; 771 `-} 772 )txt")); 773 } 774 775 TEST_P(SyntaxTreeTest, IntegerLiteralLongLong) { 776 if (!GetParam().isCXX11OrLater()) { 777 return; 778 } 779 EXPECT_TRUE(treeDumpEqual( 780 R"cpp( 781 void test() { 782 12ll; 783 12ull; 784 } 785 )cpp", 786 R"txt( 787 *: TranslationUnit 788 `-SimpleDeclaration 789 |-void 790 |-SimpleDeclarator 791 | |-test 792 | `-ParametersAndQualifiers 793 | |-( 794 | `-) 795 `-CompoundStatement 796 |-{ 797 |-ExpressionStatement 798 | |-IntegerLiteralExpression 799 | | `-12ll 800 | `-; 801 |-ExpressionStatement 802 | |-IntegerLiteralExpression 803 | | `-12ull 804 | `-; 805 `-} 806 )txt")); 807 } 808 809 TEST_P(SyntaxTreeTest, IntegerLiteralBinary) { 810 if (!GetParam().isCXX14OrLater()) { 811 return; 812 } 813 EXPECT_TRUE(treeDumpEqual( 814 R"cpp( 815 void test() { 816 0b1100; 817 } 818 )cpp", 819 R"txt( 820 *: TranslationUnit 821 `-SimpleDeclaration 822 |-void 823 |-SimpleDeclarator 824 | |-test 825 | `-ParametersAndQualifiers 826 | |-( 827 | `-) 828 `-CompoundStatement 829 |-{ 830 |-ExpressionStatement 831 | |-IntegerLiteralExpression 832 | | `-0b1100 833 | `-; 834 `-} 835 )txt")); 836 } 837 838 TEST_P(SyntaxTreeTest, IntegerLiteralWithDigitSeparators) { 839 if (!GetParam().isCXX14OrLater()) { 840 return; 841 } 842 EXPECT_TRUE(treeDumpEqual( 843 R"cpp( 844 void test() { 845 1'2'0ull; 846 } 847 )cpp", 848 R"txt( 849 *: TranslationUnit 850 `-SimpleDeclaration 851 |-void 852 |-SimpleDeclarator 853 | |-test 854 | `-ParametersAndQualifiers 855 | |-( 856 | `-) 857 `-CompoundStatement 858 |-{ 859 |-ExpressionStatement 860 | |-IntegerLiteralExpression 861 | | `-1'2'0ull 862 | `-; 863 `-} 864 )txt")); 865 } 866 867 TEST_P(SyntaxTreeTest, PostfixUnaryOperator) { 868 EXPECT_TRUE(treeDumpEqual( 869 R"cpp( 870 void test(int a) { 871 a++; 872 a--; 873 } 874 )cpp", 875 R"txt( 876 *: TranslationUnit 877 `-SimpleDeclaration 878 |-void 879 |-SimpleDeclarator 880 | |-test 881 | `-ParametersAndQualifiers 882 | |-( 883 | |-SimpleDeclaration 884 | | |-int 885 | | `-SimpleDeclarator 886 | | `-a 887 | `-) 888 `-CompoundStatement 889 |-{ 890 |-ExpressionStatement 891 | |-PostfixUnaryOperatorExpression 892 | | |-UnknownExpression 893 | | | `-a 894 | | `-++ 895 | `-; 896 |-ExpressionStatement 897 | |-PostfixUnaryOperatorExpression 898 | | |-UnknownExpression 899 | | | `-a 900 | | `--- 901 | `-; 902 `-} 903 )txt")); 904 } 905 906 TEST_P(SyntaxTreeTest, PrefixUnaryOperator) { 907 EXPECT_TRUE(treeDumpEqual( 908 R"cpp( 909 void test(int a, int *ap) { 910 --a; ++a; 911 ~a; 912 -a; 913 +a; 914 &a; 915 *ap; 916 !a; 917 __real a; __imag a; 918 } 919 )cpp", 920 R"txt( 921 *: TranslationUnit 922 `-SimpleDeclaration 923 |-void 924 |-SimpleDeclarator 925 | |-test 926 | `-ParametersAndQualifiers 927 | |-( 928 | |-SimpleDeclaration 929 | | |-int 930 | | `-SimpleDeclarator 931 | | `-a 932 | |-, 933 | |-SimpleDeclaration 934 | | |-int 935 | | `-SimpleDeclarator 936 | | |-* 937 | | `-ap 938 | `-) 939 `-CompoundStatement 940 |-{ 941 |-ExpressionStatement 942 | |-PrefixUnaryOperatorExpression 943 | | |--- 944 | | `-UnknownExpression 945 | | `-a 946 | `-; 947 |-ExpressionStatement 948 | |-PrefixUnaryOperatorExpression 949 | | |-++ 950 | | `-UnknownExpression 951 | | `-a 952 | `-; 953 |-ExpressionStatement 954 | |-PrefixUnaryOperatorExpression 955 | | |-~ 956 | | `-UnknownExpression 957 | | `-a 958 | `-; 959 |-ExpressionStatement 960 | |-PrefixUnaryOperatorExpression 961 | | |-- 962 | | `-UnknownExpression 963 | | `-a 964 | `-; 965 |-ExpressionStatement 966 | |-PrefixUnaryOperatorExpression 967 | | |-+ 968 | | `-UnknownExpression 969 | | `-a 970 | `-; 971 |-ExpressionStatement 972 | |-PrefixUnaryOperatorExpression 973 | | |-& 974 | | `-UnknownExpression 975 | | `-a 976 | `-; 977 |-ExpressionStatement 978 | |-PrefixUnaryOperatorExpression 979 | | |-* 980 | | `-UnknownExpression 981 | | `-ap 982 | `-; 983 |-ExpressionStatement 984 | |-PrefixUnaryOperatorExpression 985 | | |-! 986 | | `-UnknownExpression 987 | | `-a 988 | `-; 989 |-ExpressionStatement 990 | |-PrefixUnaryOperatorExpression 991 | | |-__real 992 | | `-UnknownExpression 993 | | `-a 994 | `-; 995 |-ExpressionStatement 996 | |-PrefixUnaryOperatorExpression 997 | | |-__imag 998 | | `-UnknownExpression 999 | | `-a 1000 | `-; 1001 `-} 1002 )txt")); 1003 } 1004 1005 TEST_P(SyntaxTreeTest, PrefixUnaryOperatorCxx) { 1006 if (!GetParam().isCXX()) { 1007 return; 1008 } 1009 EXPECT_TRUE(treeDumpEqual( 1010 R"cpp( 1011 void test(int a, bool b) { 1012 compl a; 1013 not b; 1014 } 1015 )cpp", 1016 R"txt( 1017 *: TranslationUnit 1018 `-SimpleDeclaration 1019 |-void 1020 |-SimpleDeclarator 1021 | |-test 1022 | `-ParametersAndQualifiers 1023 | |-( 1024 | |-SimpleDeclaration 1025 | | |-int 1026 | | `-SimpleDeclarator 1027 | | `-a 1028 | |-, 1029 | |-SimpleDeclaration 1030 | | |-bool 1031 | | `-SimpleDeclarator 1032 | | `-b 1033 | `-) 1034 `-CompoundStatement 1035 |-{ 1036 |-ExpressionStatement 1037 | |-PrefixUnaryOperatorExpression 1038 | | |-compl 1039 | | `-UnknownExpression 1040 | | `-a 1041 | `-; 1042 |-ExpressionStatement 1043 | |-PrefixUnaryOperatorExpression 1044 | | |-not 1045 | | `-UnknownExpression 1046 | | `-b 1047 | `-; 1048 `-} 1049 )txt")); 1050 } 1051 1052 TEST_P(SyntaxTreeTest, BinaryOperator) { 1053 EXPECT_TRUE(treeDumpEqual( 1054 R"cpp( 1055 void test(int a) { 1056 1 - 2; 1057 1 == 2; 1058 a = 1; 1059 a <<= 1; 1060 1 || 0; 1061 1 & 2; 1062 a ^= 3; 1063 } 1064 )cpp", 1065 R"txt( 1066 *: TranslationUnit 1067 `-SimpleDeclaration 1068 |-void 1069 |-SimpleDeclarator 1070 | |-test 1071 | `-ParametersAndQualifiers 1072 | |-( 1073 | |-SimpleDeclaration 1074 | | |-int 1075 | | `-SimpleDeclarator 1076 | | `-a 1077 | `-) 1078 `-CompoundStatement 1079 |-{ 1080 |-ExpressionStatement 1081 | |-BinaryOperatorExpression 1082 | | |-IntegerLiteralExpression 1083 | | | `-1 1084 | | |-- 1085 | | `-IntegerLiteralExpression 1086 | | `-2 1087 | `-; 1088 |-ExpressionStatement 1089 | |-BinaryOperatorExpression 1090 | | |-IntegerLiteralExpression 1091 | | | `-1 1092 | | |-== 1093 | | `-IntegerLiteralExpression 1094 | | `-2 1095 | `-; 1096 |-ExpressionStatement 1097 | |-BinaryOperatorExpression 1098 | | |-UnknownExpression 1099 | | | `-a 1100 | | |-= 1101 | | `-IntegerLiteralExpression 1102 | | `-1 1103 | `-; 1104 |-ExpressionStatement 1105 | |-BinaryOperatorExpression 1106 | | |-UnknownExpression 1107 | | | `-a 1108 | | |-<<= 1109 | | `-IntegerLiteralExpression 1110 | | `-1 1111 | `-; 1112 |-ExpressionStatement 1113 | |-BinaryOperatorExpression 1114 | | |-IntegerLiteralExpression 1115 | | | `-1 1116 | | |-|| 1117 | | `-IntegerLiteralExpression 1118 | | `-0 1119 | `-; 1120 |-ExpressionStatement 1121 | |-BinaryOperatorExpression 1122 | | |-IntegerLiteralExpression 1123 | | | `-1 1124 | | |-& 1125 | | `-IntegerLiteralExpression 1126 | | `-2 1127 | `-; 1128 |-ExpressionStatement 1129 | |-BinaryOperatorExpression 1130 | | |-UnknownExpression 1131 | | | `-a 1132 | | |-^= 1133 | | `-IntegerLiteralExpression 1134 | | `-3 1135 | `-; 1136 `-} 1137 )txt")); 1138 } 1139 1140 TEST_P(SyntaxTreeTest, BinaryOperatorCxx) { 1141 if (!GetParam().isCXX()) { 1142 return; 1143 } 1144 EXPECT_TRUE(treeDumpEqual( 1145 R"cpp( 1146 void test(int a) { 1147 true || false; 1148 true or false; 1149 1 bitand 2; 1150 a xor_eq 3; 1151 } 1152 )cpp", 1153 R"txt( 1154 *: TranslationUnit 1155 `-SimpleDeclaration 1156 |-void 1157 |-SimpleDeclarator 1158 | |-test 1159 | `-ParametersAndQualifiers 1160 | |-( 1161 | |-SimpleDeclaration 1162 | | |-int 1163 | | `-SimpleDeclarator 1164 | | `-a 1165 | `-) 1166 `-CompoundStatement 1167 |-{ 1168 |-ExpressionStatement 1169 | |-BinaryOperatorExpression 1170 | | |-UnknownExpression 1171 | | | `-true 1172 | | |-|| 1173 | | `-UnknownExpression 1174 | | `-false 1175 | `-; 1176 |-ExpressionStatement 1177 | |-BinaryOperatorExpression 1178 | | |-UnknownExpression 1179 | | | `-true 1180 | | |-or 1181 | | `-UnknownExpression 1182 | | `-false 1183 | `-; 1184 |-ExpressionStatement 1185 | |-BinaryOperatorExpression 1186 | | |-IntegerLiteralExpression 1187 | | | `-1 1188 | | |-bitand 1189 | | `-IntegerLiteralExpression 1190 | | `-2 1191 | `-; 1192 |-ExpressionStatement 1193 | |-BinaryOperatorExpression 1194 | | |-UnknownExpression 1195 | | | `-a 1196 | | |-xor_eq 1197 | | `-IntegerLiteralExpression 1198 | | `-3 1199 | `-; 1200 `-} 1201 )txt")); 1202 } 1203 1204 TEST_P(SyntaxTreeTest, NestedBinaryOperator) { 1205 EXPECT_TRUE(treeDumpEqual( 1206 R"cpp( 1207 void test(int a, int b) { 1208 (1 + 2) * (4 / 2); 1209 a + b + 42; 1210 a = b = 42; 1211 a + b * 4 + 2; 1212 a % 2 + b * 42; 1213 } 1214 )cpp", 1215 R"txt( 1216 *: TranslationUnit 1217 `-SimpleDeclaration 1218 |-void 1219 |-SimpleDeclarator 1220 | |-test 1221 | `-ParametersAndQualifiers 1222 | |-( 1223 | |-SimpleDeclaration 1224 | | |-int 1225 | | `-SimpleDeclarator 1226 | | `-a 1227 | |-, 1228 | |-SimpleDeclaration 1229 | | |-int 1230 | | `-SimpleDeclarator 1231 | | `-b 1232 | `-) 1233 `-CompoundStatement 1234 |-{ 1235 |-ExpressionStatement 1236 | |-BinaryOperatorExpression 1237 | | |-UnknownExpression 1238 | | | |-( 1239 | | | |-BinaryOperatorExpression 1240 | | | | |-IntegerLiteralExpression 1241 | | | | | `-1 1242 | | | | |-+ 1243 | | | | `-IntegerLiteralExpression 1244 | | | | `-2 1245 | | | `-) 1246 | | |-* 1247 | | `-UnknownExpression 1248 | | |-( 1249 | | |-BinaryOperatorExpression 1250 | | | |-IntegerLiteralExpression 1251 | | | | `-4 1252 | | | |-/ 1253 | | | `-IntegerLiteralExpression 1254 | | | `-2 1255 | | `-) 1256 | `-; 1257 |-ExpressionStatement 1258 | |-BinaryOperatorExpression 1259 | | |-BinaryOperatorExpression 1260 | | | |-UnknownExpression 1261 | | | | `-a 1262 | | | |-+ 1263 | | | `-UnknownExpression 1264 | | | `-b 1265 | | |-+ 1266 | | `-IntegerLiteralExpression 1267 | | `-42 1268 | `-; 1269 |-ExpressionStatement 1270 | |-BinaryOperatorExpression 1271 | | |-UnknownExpression 1272 | | | `-a 1273 | | |-= 1274 | | `-BinaryOperatorExpression 1275 | | |-UnknownExpression 1276 | | | `-b 1277 | | |-= 1278 | | `-IntegerLiteralExpression 1279 | | `-42 1280 | `-; 1281 |-ExpressionStatement 1282 | |-BinaryOperatorExpression 1283 | | |-BinaryOperatorExpression 1284 | | | |-UnknownExpression 1285 | | | | `-a 1286 | | | |-+ 1287 | | | `-BinaryOperatorExpression 1288 | | | |-UnknownExpression 1289 | | | | `-b 1290 | | | |-* 1291 | | | `-IntegerLiteralExpression 1292 | | | `-4 1293 | | |-+ 1294 | | `-IntegerLiteralExpression 1295 | | `-2 1296 | `-; 1297 |-ExpressionStatement 1298 | |-BinaryOperatorExpression 1299 | | |-BinaryOperatorExpression 1300 | | | |-UnknownExpression 1301 | | | | `-a 1302 | | | |-% 1303 | | | `-IntegerLiteralExpression 1304 | | | `-2 1305 | | |-+ 1306 | | `-BinaryOperatorExpression 1307 | | |-UnknownExpression 1308 | | | `-b 1309 | | |-* 1310 | | `-IntegerLiteralExpression 1311 | | `-42 1312 | `-; 1313 `-} 1314 )txt")); 1315 } 1316 1317 TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) { 1318 if (!GetParam().isCXX()) { 1319 return; 1320 } 1321 EXPECT_TRUE(treeDumpEqual( 1322 R"cpp( 1323 struct X { 1324 X& operator=(const X&); 1325 friend X operator+(X, const X&); 1326 friend bool operator<(const X&, const X&); 1327 }; 1328 void test(X x, X y) { 1329 x = y; 1330 x + y; 1331 x < y; 1332 } 1333 )cpp", 1334 R"txt( 1335 *: TranslationUnit 1336 |-SimpleDeclaration 1337 | |-struct 1338 | |-X 1339 | |-{ 1340 | |-SimpleDeclaration 1341 | | |-X 1342 | | |-SimpleDeclarator 1343 | | | |-& 1344 | | | |-operator 1345 | | | |-= 1346 | | | `-ParametersAndQualifiers 1347 | | | |-( 1348 | | | |-SimpleDeclaration 1349 | | | | |-const 1350 | | | | |-X 1351 | | | | `-SimpleDeclarator 1352 | | | | `-& 1353 | | | `-) 1354 | | `-; 1355 | |-UnknownDeclaration 1356 | | `-SimpleDeclaration 1357 | | |-friend 1358 | | |-X 1359 | | |-SimpleDeclarator 1360 | | | |-operator 1361 | | | |-+ 1362 | | | `-ParametersAndQualifiers 1363 | | | |-( 1364 | | | |-SimpleDeclaration 1365 | | | | `-X 1366 | | | |-, 1367 | | | |-SimpleDeclaration 1368 | | | | |-const 1369 | | | | |-X 1370 | | | | `-SimpleDeclarator 1371 | | | | `-& 1372 | | | `-) 1373 | | `-; 1374 | |-UnknownDeclaration 1375 | | `-SimpleDeclaration 1376 | | |-friend 1377 | | |-bool 1378 | | |-SimpleDeclarator 1379 | | | |-operator 1380 | | | |-< 1381 | | | `-ParametersAndQualifiers 1382 | | | |-( 1383 | | | |-SimpleDeclaration 1384 | | | | |-const 1385 | | | | |-X 1386 | | | | `-SimpleDeclarator 1387 | | | | `-& 1388 | | | |-, 1389 | | | |-SimpleDeclaration 1390 | | | | |-const 1391 | | | | |-X 1392 | | | | `-SimpleDeclarator 1393 | | | | `-& 1394 | | | `-) 1395 | | `-; 1396 | |-} 1397 | `-; 1398 `-SimpleDeclaration 1399 |-void 1400 |-SimpleDeclarator 1401 | |-test 1402 | `-ParametersAndQualifiers 1403 | |-( 1404 | |-SimpleDeclaration 1405 | | |-X 1406 | | `-SimpleDeclarator 1407 | | `-x 1408 | |-, 1409 | |-SimpleDeclaration 1410 | | |-X 1411 | | `-SimpleDeclarator 1412 | | `-y 1413 | `-) 1414 `-CompoundStatement 1415 |-{ 1416 |-ExpressionStatement 1417 | |-BinaryOperatorExpression 1418 | | |-UnknownExpression 1419 | | | `-x 1420 | | |-UnknownExpression 1421 | | | `-= 1422 | | `-UnknownExpression 1423 | | `-y 1424 | `-; 1425 |-ExpressionStatement 1426 | |-BinaryOperatorExpression 1427 | | |-UnknownExpression 1428 | | | `-UnknownExpression 1429 | | | `-x 1430 | | |-UnknownExpression 1431 | | | `-+ 1432 | | `-UnknownExpression 1433 | | `-y 1434 | `-; 1435 |-ExpressionStatement 1436 | |-BinaryOperatorExpression 1437 | | |-UnknownExpression 1438 | | | `-x 1439 | | |-UnknownExpression 1440 | | | `-< 1441 | | `-UnknownExpression 1442 | | `-y 1443 | `-; 1444 `-} 1445 )txt")); 1446 } 1447 1448 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) { 1449 EXPECT_TRUE(treeDumpEqual( 1450 R"cpp( 1451 int *a, b; 1452 int *c, d; 1453 )cpp", 1454 R"txt( 1455 *: TranslationUnit 1456 |-SimpleDeclaration 1457 | |-int 1458 | |-SimpleDeclarator 1459 | | |-* 1460 | | `-a 1461 | |-, 1462 | |-SimpleDeclarator 1463 | | `-b 1464 | `-; 1465 `-SimpleDeclaration 1466 |-int 1467 |-SimpleDeclarator 1468 | |-* 1469 | `-c 1470 |-, 1471 |-SimpleDeclarator 1472 | `-d 1473 `-; 1474 )txt")); 1475 } 1476 1477 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) { 1478 EXPECT_TRUE(treeDumpEqual( 1479 R"cpp( 1480 typedef int *a, b; 1481 )cpp", 1482 R"txt( 1483 *: TranslationUnit 1484 `-SimpleDeclaration 1485 |-typedef 1486 |-int 1487 |-SimpleDeclarator 1488 | |-* 1489 | `-a 1490 |-, 1491 |-SimpleDeclarator 1492 | `-b 1493 `-; 1494 )txt")); 1495 } 1496 1497 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) { 1498 EXPECT_TRUE(treeDumpEqual( 1499 R"cpp( 1500 void foo() { 1501 int *a, b; 1502 typedef int *ta, tb; 1503 } 1504 )cpp", 1505 R"txt( 1506 *: TranslationUnit 1507 `-SimpleDeclaration 1508 |-void 1509 |-SimpleDeclarator 1510 | |-foo 1511 | `-ParametersAndQualifiers 1512 | |-( 1513 | `-) 1514 `-CompoundStatement 1515 |-{ 1516 |-DeclarationStatement 1517 | |-SimpleDeclaration 1518 | | |-int 1519 | | |-SimpleDeclarator 1520 | | | |-* 1521 | | | `-a 1522 | | |-, 1523 | | `-SimpleDeclarator 1524 | | `-b 1525 | `-; 1526 |-DeclarationStatement 1527 | |-SimpleDeclaration 1528 | | |-typedef 1529 | | |-int 1530 | | |-SimpleDeclarator 1531 | | | |-* 1532 | | | `-ta 1533 | | |-, 1534 | | `-SimpleDeclarator 1535 | | `-tb 1536 | `-; 1537 `-} 1538 )txt")); 1539 } 1540 1541 TEST_P(SyntaxTreeTest, Namespaces) { 1542 if (!GetParam().isCXX()) { 1543 return; 1544 } 1545 EXPECT_TRUE(treeDumpEqual( 1546 R"cpp( 1547 namespace a { namespace b {} } 1548 namespace a::b {} 1549 namespace {} 1550 1551 namespace foo = a; 1552 )cpp", 1553 R"txt( 1554 *: TranslationUnit 1555 |-NamespaceDefinition 1556 | |-namespace 1557 | |-a 1558 | |-{ 1559 | |-NamespaceDefinition 1560 | | |-namespace 1561 | | |-b 1562 | | |-{ 1563 | | `-} 1564 | `-} 1565 |-NamespaceDefinition 1566 | |-namespace 1567 | |-a 1568 | |-:: 1569 | |-b 1570 | |-{ 1571 | `-} 1572 |-NamespaceDefinition 1573 | |-namespace 1574 | |-{ 1575 | `-} 1576 `-NamespaceAliasDefinition 1577 |-namespace 1578 |-foo 1579 |-= 1580 |-a 1581 `-; 1582 )txt")); 1583 } 1584 1585 TEST_P(SyntaxTreeTest, UsingDirective) { 1586 if (!GetParam().isCXX()) { 1587 return; 1588 } 1589 EXPECT_TRUE(treeDumpEqual( 1590 R"cpp( 1591 namespace ns {} 1592 using namespace ::ns; 1593 )cpp", 1594 R"txt( 1595 *: TranslationUnit 1596 |-NamespaceDefinition 1597 | |-namespace 1598 | |-ns 1599 | |-{ 1600 | `-} 1601 `-UsingNamespaceDirective 1602 |-using 1603 |-namespace 1604 |-:: 1605 |-ns 1606 `-; 1607 )txt")); 1608 } 1609 1610 TEST_P(SyntaxTreeTest, UsingDeclaration) { 1611 if (!GetParam().isCXX()) { 1612 return; 1613 } 1614 EXPECT_TRUE(treeDumpEqual( 1615 R"cpp( 1616 namespace ns { int a; } 1617 using ns::a; 1618 )cpp", 1619 R"txt( 1620 *: TranslationUnit 1621 |-NamespaceDefinition 1622 | |-namespace 1623 | |-ns 1624 | |-{ 1625 | |-SimpleDeclaration 1626 | | |-int 1627 | | |-SimpleDeclarator 1628 | | | `-a 1629 | | `-; 1630 | `-} 1631 `-UsingDeclaration 1632 |-using 1633 |-ns 1634 |-:: 1635 |-a 1636 `-; 1637 )txt")); 1638 } 1639 1640 TEST_P(SyntaxTreeTest, FreeStandingClasses) { 1641 // Free-standing classes, must live inside a SimpleDeclaration. 1642 EXPECT_TRUE(treeDumpEqual( 1643 R"cpp( 1644 struct X; 1645 struct X {}; 1646 1647 struct Y *y1; 1648 struct Y {} *y2; 1649 1650 struct {} *a1; 1651 )cpp", 1652 R"txt( 1653 *: TranslationUnit 1654 |-SimpleDeclaration 1655 | |-struct 1656 | |-X 1657 | `-; 1658 |-SimpleDeclaration 1659 | |-struct 1660 | |-X 1661 | |-{ 1662 | |-} 1663 | `-; 1664 |-SimpleDeclaration 1665 | |-struct 1666 | |-Y 1667 | |-SimpleDeclarator 1668 | | |-* 1669 | | `-y1 1670 | `-; 1671 |-SimpleDeclaration 1672 | |-struct 1673 | |-Y 1674 | |-{ 1675 | |-} 1676 | |-SimpleDeclarator 1677 | | |-* 1678 | | `-y2 1679 | `-; 1680 `-SimpleDeclaration 1681 |-struct 1682 |-{ 1683 |-} 1684 |-SimpleDeclarator 1685 | |-* 1686 | `-a1 1687 `-; 1688 )txt")); 1689 } 1690 1691 TEST_P(SyntaxTreeTest, Templates) { 1692 if (!GetParam().isCXX()) { 1693 return; 1694 } 1695 if (GetParam().hasDelayedTemplateParsing()) { 1696 // FIXME: Make this test work on Windows by generating the expected syntax 1697 // tree when `-fdelayed-template-parsing` is active. 1698 return; 1699 } 1700 EXPECT_TRUE(treeDumpEqual( 1701 R"cpp( 1702 template <class T> struct cls {}; 1703 template <class T> int var = 10; 1704 template <class T> int fun() {} 1705 )cpp", 1706 R"txt( 1707 *: TranslationUnit 1708 |-TemplateDeclaration 1709 | |-template 1710 | |-< 1711 | |-UnknownDeclaration 1712 | | |-class 1713 | | `-T 1714 | |-> 1715 | `-SimpleDeclaration 1716 | |-struct 1717 | |-cls 1718 | |-{ 1719 | |-} 1720 | `-; 1721 |-TemplateDeclaration 1722 | |-template 1723 | |-< 1724 | |-UnknownDeclaration 1725 | | |-class 1726 | | `-T 1727 | |-> 1728 | `-SimpleDeclaration 1729 | |-int 1730 | |-SimpleDeclarator 1731 | | |-var 1732 | | |-= 1733 | | `-IntegerLiteralExpression 1734 | | `-10 1735 | `-; 1736 `-TemplateDeclaration 1737 |-template 1738 |-< 1739 |-UnknownDeclaration 1740 | |-class 1741 | `-T 1742 |-> 1743 `-SimpleDeclaration 1744 |-int 1745 |-SimpleDeclarator 1746 | |-fun 1747 | `-ParametersAndQualifiers 1748 | |-( 1749 | `-) 1750 `-CompoundStatement 1751 |-{ 1752 `-} 1753 )txt")); 1754 } 1755 1756 TEST_P(SyntaxTreeTest, NestedTemplates) { 1757 if (!GetParam().isCXX()) { 1758 return; 1759 } 1760 EXPECT_TRUE(treeDumpEqual( 1761 R"cpp( 1762 template <class T> 1763 struct X { 1764 template <class U> 1765 U foo(); 1766 }; 1767 )cpp", 1768 R"txt( 1769 *: TranslationUnit 1770 `-TemplateDeclaration 1771 |-template 1772 |-< 1773 |-UnknownDeclaration 1774 | |-class 1775 | `-T 1776 |-> 1777 `-SimpleDeclaration 1778 |-struct 1779 |-X 1780 |-{ 1781 |-TemplateDeclaration 1782 | |-template 1783 | |-< 1784 | |-UnknownDeclaration 1785 | | |-class 1786 | | `-U 1787 | |-> 1788 | `-SimpleDeclaration 1789 | |-U 1790 | |-SimpleDeclarator 1791 | | |-foo 1792 | | `-ParametersAndQualifiers 1793 | | |-( 1794 | | `-) 1795 | `-; 1796 |-} 1797 `-; 1798 )txt")); 1799 } 1800 1801 TEST_P(SyntaxTreeTest, Templates2) { 1802 if (!GetParam().isCXX()) { 1803 return; 1804 } 1805 EXPECT_TRUE(treeDumpEqual( 1806 R"cpp( 1807 template <class T> struct X { struct Y; }; 1808 template <class T> struct X<T>::Y {}; 1809 )cpp", 1810 R"txt( 1811 *: TranslationUnit 1812 |-TemplateDeclaration 1813 | |-template 1814 | |-< 1815 | |-UnknownDeclaration 1816 | | |-class 1817 | | `-T 1818 | |-> 1819 | `-SimpleDeclaration 1820 | |-struct 1821 | |-X 1822 | |-{ 1823 | |-SimpleDeclaration 1824 | | |-struct 1825 | | |-Y 1826 | | `-; 1827 | |-} 1828 | `-; 1829 `-TemplateDeclaration 1830 |-template 1831 |-< 1832 |-UnknownDeclaration 1833 | |-class 1834 | `-T 1835 |-> 1836 `-SimpleDeclaration 1837 |-struct 1838 |-X 1839 |-< 1840 |-T 1841 |-> 1842 |-:: 1843 |-Y 1844 |-{ 1845 |-} 1846 `-; 1847 )txt")); 1848 } 1849 1850 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) { 1851 if (!GetParam().isCXX()) { 1852 return; 1853 } 1854 EXPECT_TRUE(treeDumpEqual( 1855 R"cpp( 1856 template <class T> struct X { 1857 using T::foo; 1858 using typename T::bar; 1859 }; 1860 )cpp", 1861 R"txt( 1862 *: TranslationUnit 1863 `-TemplateDeclaration 1864 |-template 1865 |-< 1866 |-UnknownDeclaration 1867 | |-class 1868 | `-T 1869 |-> 1870 `-SimpleDeclaration 1871 |-struct 1872 |-X 1873 |-{ 1874 |-UsingDeclaration 1875 | |-using 1876 | |-T 1877 | |-:: 1878 | |-foo 1879 | `-; 1880 |-UsingDeclaration 1881 | |-using 1882 | |-typename 1883 | |-T 1884 | |-:: 1885 | |-bar 1886 | `-; 1887 |-} 1888 `-; 1889 )txt")); 1890 } 1891 1892 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) { 1893 if (!GetParam().isCXX()) { 1894 return; 1895 } 1896 EXPECT_TRUE(treeDumpEqual( 1897 R"cpp( 1898 template <class T> struct X {}; 1899 template <class T> struct X<T*> {}; 1900 template <> struct X<int> {}; 1901 1902 template struct X<double>; 1903 extern template struct X<float>; 1904 )cpp", 1905 R"txt( 1906 *: TranslationUnit 1907 |-TemplateDeclaration 1908 | |-template 1909 | |-< 1910 | |-UnknownDeclaration 1911 | | |-class 1912 | | `-T 1913 | |-> 1914 | `-SimpleDeclaration 1915 | |-struct 1916 | |-X 1917 | |-{ 1918 | |-} 1919 | `-; 1920 |-TemplateDeclaration 1921 | |-template 1922 | |-< 1923 | |-UnknownDeclaration 1924 | | |-class 1925 | | `-T 1926 | |-> 1927 | `-SimpleDeclaration 1928 | |-struct 1929 | |-X 1930 | |-< 1931 | |-T 1932 | |-* 1933 | |-> 1934 | |-{ 1935 | |-} 1936 | `-; 1937 |-TemplateDeclaration 1938 | |-template 1939 | |-< 1940 | |-> 1941 | `-SimpleDeclaration 1942 | |-struct 1943 | |-X 1944 | |-< 1945 | |-int 1946 | |-> 1947 | |-{ 1948 | |-} 1949 | `-; 1950 |-ExplicitTemplateInstantiation 1951 | |-template 1952 | `-SimpleDeclaration 1953 | |-struct 1954 | |-X 1955 | |-< 1956 | |-double 1957 | |-> 1958 | `-; 1959 `-ExplicitTemplateInstantiation 1960 |-extern 1961 |-template 1962 `-SimpleDeclaration 1963 |-struct 1964 |-X 1965 |-< 1966 |-float 1967 |-> 1968 `-; 1969 )txt")); 1970 } 1971 1972 TEST_P(SyntaxTreeTest, UsingType) { 1973 if (!GetParam().isCXX()) { 1974 return; 1975 } 1976 EXPECT_TRUE(treeDumpEqual( 1977 R"cpp( 1978 using type = int; 1979 )cpp", 1980 R"txt( 1981 *: TranslationUnit 1982 `-TypeAliasDeclaration 1983 |-using 1984 |-type 1985 |-= 1986 |-int 1987 `-; 1988 )txt")); 1989 } 1990 1991 TEST_P(SyntaxTreeTest, EmptyDeclaration) { 1992 EXPECT_TRUE(treeDumpEqual( 1993 R"cpp( 1994 ; 1995 )cpp", 1996 R"txt( 1997 *: TranslationUnit 1998 `-EmptyDeclaration 1999 `-; 2000 )txt")); 2001 } 2002 2003 TEST_P(SyntaxTreeTest, StaticAssert) { 2004 if (!GetParam().isCXX11OrLater()) { 2005 return; 2006 } 2007 EXPECT_TRUE(treeDumpEqual( 2008 R"cpp( 2009 static_assert(true, "message"); 2010 static_assert(true); 2011 )cpp", 2012 R"txt( 2013 *: TranslationUnit 2014 |-StaticAssertDeclaration 2015 | |-static_assert 2016 | |-( 2017 | |-UnknownExpression 2018 | | `-true 2019 | |-, 2020 | |-UnknownExpression 2021 | | `-"message" 2022 | |-) 2023 | `-; 2024 `-StaticAssertDeclaration 2025 |-static_assert 2026 |-( 2027 |-UnknownExpression 2028 | `-true 2029 |-) 2030 `-; 2031 )txt")); 2032 } 2033 2034 TEST_P(SyntaxTreeTest, ExternC) { 2035 if (!GetParam().isCXX()) { 2036 return; 2037 } 2038 EXPECT_TRUE(treeDumpEqual( 2039 R"cpp( 2040 extern "C" int a; 2041 extern "C" { int b; int c; } 2042 )cpp", 2043 R"txt( 2044 *: TranslationUnit 2045 |-LinkageSpecificationDeclaration 2046 | |-extern 2047 | |-"C" 2048 | `-SimpleDeclaration 2049 | |-int 2050 | |-SimpleDeclarator 2051 | | `-a 2052 | `-; 2053 `-LinkageSpecificationDeclaration 2054 |-extern 2055 |-"C" 2056 |-{ 2057 |-SimpleDeclaration 2058 | |-int 2059 | |-SimpleDeclarator 2060 | | `-b 2061 | `-; 2062 |-SimpleDeclaration 2063 | |-int 2064 | |-SimpleDeclarator 2065 | | `-c 2066 | `-; 2067 `-} 2068 )txt")); 2069 } 2070 2071 TEST_P(SyntaxTreeTest, NonModifiableNodes) { 2072 // Some nodes are non-modifiable, they are marked with 'I:'. 2073 EXPECT_TRUE(treeDumpEqual( 2074 R"cpp( 2075 #define HALF_IF if (1+ 2076 #define HALF_IF_2 1) {} 2077 void test() { 2078 HALF_IF HALF_IF_2 else {} 2079 })cpp", 2080 R"txt( 2081 *: TranslationUnit 2082 `-SimpleDeclaration 2083 |-void 2084 |-SimpleDeclarator 2085 | |-test 2086 | `-ParametersAndQualifiers 2087 | |-( 2088 | `-) 2089 `-CompoundStatement 2090 |-{ 2091 |-IfStatement 2092 | |-I: if 2093 | |-I: ( 2094 | |-I: BinaryOperatorExpression 2095 | | |-I: IntegerLiteralExpression 2096 | | | `-I: 1 2097 | | |-I: + 2098 | | `-I: IntegerLiteralExpression 2099 | | `-I: 1 2100 | |-I: ) 2101 | |-I: CompoundStatement 2102 | | |-I: { 2103 | | `-I: } 2104 | |-else 2105 | `-CompoundStatement 2106 | |-{ 2107 | `-} 2108 `-} 2109 )txt")); 2110 } 2111 2112 TEST_P(SyntaxTreeTest, ModifiableNodes) { 2113 // All nodes can be mutated. 2114 EXPECT_TRUE(treeDumpEqual( 2115 R"cpp( 2116 #define OPEN { 2117 #define CLOSE } 2118 2119 void test() { 2120 OPEN 2121 1; 2122 CLOSE 2123 2124 OPEN 2125 2; 2126 } 2127 } 2128 )cpp", 2129 R"txt( 2130 *: TranslationUnit 2131 `-SimpleDeclaration 2132 |-void 2133 |-SimpleDeclarator 2134 | |-test 2135 | `-ParametersAndQualifiers 2136 | |-( 2137 | `-) 2138 `-CompoundStatement 2139 |-{ 2140 |-CompoundStatement 2141 | |-{ 2142 | |-ExpressionStatement 2143 | | |-IntegerLiteralExpression 2144 | | | `-1 2145 | | `-; 2146 | `-} 2147 |-CompoundStatement 2148 | |-{ 2149 | |-ExpressionStatement 2150 | | |-IntegerLiteralExpression 2151 | | | `-2 2152 | | `-; 2153 | `-} 2154 `-} 2155 )txt")); 2156 } 2157 2158 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) { 2159 EXPECT_TRUE(treeDumpEqual( 2160 R"cpp( 2161 int a[10]; 2162 int b[1][2][3]; 2163 int c[] = {1,2,3}; 2164 )cpp", 2165 R"txt( 2166 *: TranslationUnit 2167 |-SimpleDeclaration 2168 | |-int 2169 | |-SimpleDeclarator 2170 | | |-a 2171 | | `-ArraySubscript 2172 | | |-[ 2173 | | |-IntegerLiteralExpression 2174 | | | `-10 2175 | | `-] 2176 | `-; 2177 |-SimpleDeclaration 2178 | |-int 2179 | |-SimpleDeclarator 2180 | | |-b 2181 | | |-ArraySubscript 2182 | | | |-[ 2183 | | | |-IntegerLiteralExpression 2184 | | | | `-1 2185 | | | `-] 2186 | | |-ArraySubscript 2187 | | | |-[ 2188 | | | |-IntegerLiteralExpression 2189 | | | | `-2 2190 | | | `-] 2191 | | `-ArraySubscript 2192 | | |-[ 2193 | | |-IntegerLiteralExpression 2194 | | | `-3 2195 | | `-] 2196 | `-; 2197 `-SimpleDeclaration 2198 |-int 2199 |-SimpleDeclarator 2200 | |-c 2201 | |-ArraySubscript 2202 | | |-[ 2203 | | `-] 2204 | |-= 2205 | `-UnknownExpression 2206 | `-UnknownExpression 2207 | |-{ 2208 | |-IntegerLiteralExpression 2209 | | `-1 2210 | |-, 2211 | |-IntegerLiteralExpression 2212 | | `-2 2213 | |-, 2214 | |-IntegerLiteralExpression 2215 | | `-3 2216 | `-} 2217 `-; 2218 )txt")); 2219 } 2220 2221 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) { 2222 if (!GetParam().isC99OrLater()) { 2223 return; 2224 } 2225 EXPECT_TRUE(treeDumpEqual( 2226 R"cpp( 2227 void f(int xs[static 10]); 2228 )cpp", 2229 R"txt( 2230 *: TranslationUnit 2231 `-SimpleDeclaration 2232 |-void 2233 |-SimpleDeclarator 2234 | |-f 2235 | `-ParametersAndQualifiers 2236 | |-( 2237 | |-SimpleDeclaration 2238 | | |-int 2239 | | `-SimpleDeclarator 2240 | | |-xs 2241 | | `-ArraySubscript 2242 | | |-[ 2243 | | |-static 2244 | | |-IntegerLiteralExpression 2245 | | | `-10 2246 | | `-] 2247 | `-) 2248 `-; 2249 )txt")); 2250 } 2251 2252 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) { 2253 if (!GetParam().isCXX()) { 2254 return; 2255 } 2256 EXPECT_TRUE(treeDumpEqual( 2257 R"cpp( 2258 int func1(); 2259 int func2a(int a); 2260 int func2b(int); 2261 int func3a(int *ap); 2262 int func3b(int *); 2263 int func4a(int a, float b); 2264 int func4b(int, float); 2265 )cpp", 2266 R"txt( 2267 *: TranslationUnit 2268 |-SimpleDeclaration 2269 | |-int 2270 | |-SimpleDeclarator 2271 | | |-func1 2272 | | `-ParametersAndQualifiers 2273 | | |-( 2274 | | `-) 2275 | `-; 2276 |-SimpleDeclaration 2277 | |-int 2278 | |-SimpleDeclarator 2279 | | |-func2a 2280 | | `-ParametersAndQualifiers 2281 | | |-( 2282 | | |-SimpleDeclaration 2283 | | | |-int 2284 | | | `-SimpleDeclarator 2285 | | | `-a 2286 | | `-) 2287 | `-; 2288 |-SimpleDeclaration 2289 | |-int 2290 | |-SimpleDeclarator 2291 | | |-func2b 2292 | | `-ParametersAndQualifiers 2293 | | |-( 2294 | | |-SimpleDeclaration 2295 | | | `-int 2296 | | `-) 2297 | `-; 2298 |-SimpleDeclaration 2299 | |-int 2300 | |-SimpleDeclarator 2301 | | |-func3a 2302 | | `-ParametersAndQualifiers 2303 | | |-( 2304 | | |-SimpleDeclaration 2305 | | | |-int 2306 | | | `-SimpleDeclarator 2307 | | | |-* 2308 | | | `-ap 2309 | | `-) 2310 | `-; 2311 |-SimpleDeclaration 2312 | |-int 2313 | |-SimpleDeclarator 2314 | | |-func3b 2315 | | `-ParametersAndQualifiers 2316 | | |-( 2317 | | |-SimpleDeclaration 2318 | | | |-int 2319 | | | `-SimpleDeclarator 2320 | | | `-* 2321 | | `-) 2322 | `-; 2323 |-SimpleDeclaration 2324 | |-int 2325 | |-SimpleDeclarator 2326 | | |-func4a 2327 | | `-ParametersAndQualifiers 2328 | | |-( 2329 | | |-SimpleDeclaration 2330 | | | |-int 2331 | | | `-SimpleDeclarator 2332 | | | `-a 2333 | | |-, 2334 | | |-SimpleDeclaration 2335 | | | |-float 2336 | | | `-SimpleDeclarator 2337 | | | `-b 2338 | | `-) 2339 | `-; 2340 `-SimpleDeclaration 2341 |-int 2342 |-SimpleDeclarator 2343 | |-func4b 2344 | `-ParametersAndQualifiers 2345 | |-( 2346 | |-SimpleDeclaration 2347 | | `-int 2348 | |-, 2349 | |-SimpleDeclaration 2350 | | `-float 2351 | `-) 2352 `-; 2353 )txt")); 2354 } 2355 2356 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) { 2357 if (!GetParam().isCXX()) { 2358 return; 2359 } 2360 EXPECT_TRUE(treeDumpEqual( 2361 R"cpp( 2362 int func1(const int a, volatile int b, const volatile int c); 2363 int func2(int& a); 2364 )cpp", 2365 R"txt( 2366 *: TranslationUnit 2367 |-SimpleDeclaration 2368 | |-int 2369 | |-SimpleDeclarator 2370 | | |-func1 2371 | | `-ParametersAndQualifiers 2372 | | |-( 2373 | | |-SimpleDeclaration 2374 | | | |-const 2375 | | | |-int 2376 | | | `-SimpleDeclarator 2377 | | | `-a 2378 | | |-, 2379 | | |-SimpleDeclaration 2380 | | | |-volatile 2381 | | | |-int 2382 | | | `-SimpleDeclarator 2383 | | | `-b 2384 | | |-, 2385 | | |-SimpleDeclaration 2386 | | | |-const 2387 | | | |-volatile 2388 | | | |-int 2389 | | | `-SimpleDeclarator 2390 | | | `-c 2391 | | `-) 2392 | `-; 2393 `-SimpleDeclaration 2394 |-int 2395 |-SimpleDeclarator 2396 | |-func2 2397 | `-ParametersAndQualifiers 2398 | |-( 2399 | |-SimpleDeclaration 2400 | | |-int 2401 | | `-SimpleDeclarator 2402 | | |-& 2403 | | `-a 2404 | `-) 2405 `-; 2406 )txt")); 2407 } 2408 2409 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) { 2410 if (!GetParam().isCXX11OrLater()) { 2411 return; 2412 } 2413 EXPECT_TRUE(treeDumpEqual( 2414 R"cpp( 2415 int func1(int&& a); 2416 )cpp", 2417 R"txt( 2418 *: TranslationUnit 2419 `-SimpleDeclaration 2420 |-int 2421 |-SimpleDeclarator 2422 | |-func1 2423 | `-ParametersAndQualifiers 2424 | |-( 2425 | |-SimpleDeclaration 2426 | | |-int 2427 | | `-SimpleDeclarator 2428 | | |-&& 2429 | | `-a 2430 | `-) 2431 `-; 2432 )txt")); 2433 } 2434 2435 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) { 2436 if (!GetParam().isCXX()) { 2437 return; 2438 } 2439 EXPECT_TRUE(treeDumpEqual( 2440 R"cpp( 2441 struct Test { 2442 int a(); 2443 int b() const; 2444 int c() volatile; 2445 int d() const volatile; 2446 int e() &; 2447 int f() &&; 2448 }; 2449 )cpp", 2450 R"txt( 2451 *: TranslationUnit 2452 `-SimpleDeclaration 2453 |-struct 2454 |-Test 2455 |-{ 2456 |-SimpleDeclaration 2457 | |-int 2458 | |-SimpleDeclarator 2459 | | |-a 2460 | | `-ParametersAndQualifiers 2461 | | |-( 2462 | | `-) 2463 | `-; 2464 |-SimpleDeclaration 2465 | |-int 2466 | |-SimpleDeclarator 2467 | | |-b 2468 | | `-ParametersAndQualifiers 2469 | | |-( 2470 | | |-) 2471 | | `-const 2472 | `-; 2473 |-SimpleDeclaration 2474 | |-int 2475 | |-SimpleDeclarator 2476 | | |-c 2477 | | `-ParametersAndQualifiers 2478 | | |-( 2479 | | |-) 2480 | | `-volatile 2481 | `-; 2482 |-SimpleDeclaration 2483 | |-int 2484 | |-SimpleDeclarator 2485 | | |-d 2486 | | `-ParametersAndQualifiers 2487 | | |-( 2488 | | |-) 2489 | | |-const 2490 | | `-volatile 2491 | `-; 2492 |-SimpleDeclaration 2493 | |-int 2494 | |-SimpleDeclarator 2495 | | |-e 2496 | | `-ParametersAndQualifiers 2497 | | |-( 2498 | | |-) 2499 | | `-& 2500 | `-; 2501 |-SimpleDeclaration 2502 | |-int 2503 | |-SimpleDeclarator 2504 | | |-f 2505 | | `-ParametersAndQualifiers 2506 | | |-( 2507 | | |-) 2508 | | `-&& 2509 | `-; 2510 |-} 2511 `-; 2512 )txt")); 2513 } 2514 2515 TEST_P(SyntaxTreeTest, TrailingReturn) { 2516 if (!GetParam().isCXX11OrLater()) { 2517 return; 2518 } 2519 EXPECT_TRUE(treeDumpEqual( 2520 R"cpp( 2521 auto foo() -> int; 2522 )cpp", 2523 R"txt( 2524 *: TranslationUnit 2525 `-SimpleDeclaration 2526 |-auto 2527 |-SimpleDeclarator 2528 | |-foo 2529 | `-ParametersAndQualifiers 2530 | |-( 2531 | |-) 2532 | `-TrailingReturnType 2533 | |--> 2534 | `-int 2535 `-; 2536 )txt")); 2537 } 2538 2539 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) { 2540 if (!GetParam().supportsCXXDynamicExceptionSpecification()) { 2541 return; 2542 } 2543 EXPECT_TRUE(treeDumpEqual( 2544 R"cpp( 2545 struct MyException1 {}; 2546 struct MyException2 {}; 2547 int a() throw(); 2548 int b() throw(...); 2549 int c() throw(MyException1); 2550 int d() throw(MyException1, MyException2); 2551 )cpp", 2552 R"txt( 2553 *: TranslationUnit 2554 |-SimpleDeclaration 2555 | |-struct 2556 | |-MyException1 2557 | |-{ 2558 | |-} 2559 | `-; 2560 |-SimpleDeclaration 2561 | |-struct 2562 | |-MyException2 2563 | |-{ 2564 | |-} 2565 | `-; 2566 |-SimpleDeclaration 2567 | |-int 2568 | |-SimpleDeclarator 2569 | | |-a 2570 | | `-ParametersAndQualifiers 2571 | | |-( 2572 | | |-) 2573 | | |-throw 2574 | | |-( 2575 | | `-) 2576 | `-; 2577 |-SimpleDeclaration 2578 | |-int 2579 | |-SimpleDeclarator 2580 | | |-b 2581 | | `-ParametersAndQualifiers 2582 | | |-( 2583 | | |-) 2584 | | |-throw 2585 | | |-( 2586 | | |-... 2587 | | `-) 2588 | `-; 2589 |-SimpleDeclaration 2590 | |-int 2591 | |-SimpleDeclarator 2592 | | |-c 2593 | | `-ParametersAndQualifiers 2594 | | |-( 2595 | | |-) 2596 | | |-throw 2597 | | |-( 2598 | | |-MyException1 2599 | | `-) 2600 | `-; 2601 `-SimpleDeclaration 2602 |-int 2603 |-SimpleDeclarator 2604 | |-d 2605 | `-ParametersAndQualifiers 2606 | |-( 2607 | |-) 2608 | |-throw 2609 | |-( 2610 | |-MyException1 2611 | |-, 2612 | |-MyException2 2613 | `-) 2614 `-; 2615 )txt")); 2616 } 2617 2618 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) { 2619 if (!GetParam().isCXX11OrLater()) { 2620 return; 2621 } 2622 EXPECT_TRUE(treeDumpEqual( 2623 R"cpp( 2624 int a() noexcept; 2625 int b() noexcept(true); 2626 )cpp", 2627 R"txt( 2628 *: TranslationUnit 2629 |-SimpleDeclaration 2630 | |-int 2631 | |-SimpleDeclarator 2632 | | |-a 2633 | | `-ParametersAndQualifiers 2634 | | |-( 2635 | | |-) 2636 | | `-noexcept 2637 | `-; 2638 `-SimpleDeclaration 2639 |-int 2640 |-SimpleDeclarator 2641 | |-b 2642 | `-ParametersAndQualifiers 2643 | |-( 2644 | |-) 2645 | |-noexcept 2646 | |-( 2647 | |-UnknownExpression 2648 | | `-true 2649 | `-) 2650 `-; 2651 )txt")); 2652 } 2653 2654 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) { 2655 EXPECT_TRUE(treeDumpEqual( 2656 R"cpp( 2657 int (a); 2658 int *(b); 2659 int (*c)(int); 2660 int *(d)(int); 2661 )cpp", 2662 R"txt( 2663 *: TranslationUnit 2664 |-SimpleDeclaration 2665 | |-int 2666 | |-SimpleDeclarator 2667 | | `-ParenDeclarator 2668 | | |-( 2669 | | |-a 2670 | | `-) 2671 | `-; 2672 |-SimpleDeclaration 2673 | |-int 2674 | |-SimpleDeclarator 2675 | | |-* 2676 | | `-ParenDeclarator 2677 | | |-( 2678 | | |-b 2679 | | `-) 2680 | `-; 2681 |-SimpleDeclaration 2682 | |-int 2683 | |-SimpleDeclarator 2684 | | |-ParenDeclarator 2685 | | | |-( 2686 | | | |-* 2687 | | | |-c 2688 | | | `-) 2689 | | `-ParametersAndQualifiers 2690 | | |-( 2691 | | |-SimpleDeclaration 2692 | | | `-int 2693 | | `-) 2694 | `-; 2695 `-SimpleDeclaration 2696 |-int 2697 |-SimpleDeclarator 2698 | |-* 2699 | |-ParenDeclarator 2700 | | |-( 2701 | | |-d 2702 | | `-) 2703 | `-ParametersAndQualifiers 2704 | |-( 2705 | |-SimpleDeclaration 2706 | | `-int 2707 | `-) 2708 `-; 2709 )txt")); 2710 } 2711 2712 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) { 2713 EXPECT_TRUE(treeDumpEqual( 2714 R"cpp( 2715 const int west = -1; 2716 int const east = 1; 2717 const int const universal = 0; 2718 const int const *const *volatile b; 2719 )cpp", 2720 R"txt( 2721 *: TranslationUnit 2722 |-SimpleDeclaration 2723 | |-const 2724 | |-int 2725 | |-SimpleDeclarator 2726 | | |-west 2727 | | |-= 2728 | | `-PrefixUnaryOperatorExpression 2729 | | |-- 2730 | | `-IntegerLiteralExpression 2731 | | `-1 2732 | `-; 2733 |-SimpleDeclaration 2734 | |-int 2735 | |-const 2736 | |-SimpleDeclarator 2737 | | |-east 2738 | | |-= 2739 | | `-IntegerLiteralExpression 2740 | | `-1 2741 | `-; 2742 |-SimpleDeclaration 2743 | |-const 2744 | |-int 2745 | |-const 2746 | |-SimpleDeclarator 2747 | | |-universal 2748 | | |-= 2749 | | `-IntegerLiteralExpression 2750 | | `-0 2751 | `-; 2752 `-SimpleDeclaration 2753 |-const 2754 |-int 2755 |-const 2756 |-SimpleDeclarator 2757 | |-* 2758 | |-const 2759 | |-* 2760 | |-volatile 2761 | `-b 2762 `-; 2763 )txt")); 2764 } 2765 2766 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) { 2767 if (!GetParam().isCXX11OrLater()) { 2768 return; 2769 } 2770 EXPECT_TRUE(treeDumpEqual( 2771 R"cpp( 2772 auto foo() -> auto(*)(int) -> double*; 2773 )cpp", 2774 R"txt( 2775 *: TranslationUnit 2776 `-SimpleDeclaration 2777 |-auto 2778 |-SimpleDeclarator 2779 | |-foo 2780 | `-ParametersAndQualifiers 2781 | |-( 2782 | |-) 2783 | `-TrailingReturnType 2784 | |--> 2785 | |-auto 2786 | `-SimpleDeclarator 2787 | |-ParenDeclarator 2788 | | |-( 2789 | | |-* 2790 | | `-) 2791 | `-ParametersAndQualifiers 2792 | |-( 2793 | |-SimpleDeclaration 2794 | | `-int 2795 | |-) 2796 | `-TrailingReturnType 2797 | |--> 2798 | |-double 2799 | `-SimpleDeclarator 2800 | `-* 2801 `-; 2802 )txt")); 2803 } 2804 2805 TEST_P(SyntaxTreeTest, MemberPointers) { 2806 if (!GetParam().isCXX()) { 2807 return; 2808 } 2809 EXPECT_TRUE(treeDumpEqual( 2810 R"cpp( 2811 struct X {}; 2812 int X::* a; 2813 const int X::* b; 2814 )cpp", 2815 R"txt( 2816 *: TranslationUnit 2817 |-SimpleDeclaration 2818 | |-struct 2819 | |-X 2820 | |-{ 2821 | |-} 2822 | `-; 2823 |-SimpleDeclaration 2824 | |-int 2825 | |-SimpleDeclarator 2826 | | |-MemberPointer 2827 | | | |-X 2828 | | | |-:: 2829 | | | `-* 2830 | | `-a 2831 | `-; 2832 `-SimpleDeclaration 2833 |-const 2834 |-int 2835 |-SimpleDeclarator 2836 | |-MemberPointer 2837 | | |-X 2838 | | |-:: 2839 | | `-* 2840 | `-b 2841 `-; 2842 )txt")); 2843 } 2844 2845 TEST_P(SyntaxTreeTest, ComplexDeclarator) { 2846 EXPECT_TRUE(treeDumpEqual( 2847 R"cpp( 2848 void x(char a, short (*b)(int)); 2849 )cpp", 2850 R"txt( 2851 *: TranslationUnit 2852 `-SimpleDeclaration 2853 |-void 2854 |-SimpleDeclarator 2855 | |-x 2856 | `-ParametersAndQualifiers 2857 | |-( 2858 | |-SimpleDeclaration 2859 | | |-char 2860 | | `-SimpleDeclarator 2861 | | `-a 2862 | |-, 2863 | |-SimpleDeclaration 2864 | | |-short 2865 | | `-SimpleDeclarator 2866 | | |-ParenDeclarator 2867 | | | |-( 2868 | | | |-* 2869 | | | |-b 2870 | | | `-) 2871 | | `-ParametersAndQualifiers 2872 | | |-( 2873 | | |-SimpleDeclaration 2874 | | | `-int 2875 | | `-) 2876 | `-) 2877 `-; 2878 )txt")); 2879 } 2880 2881 TEST_P(SyntaxTreeTest, ComplexDeclarator2) { 2882 EXPECT_TRUE(treeDumpEqual( 2883 R"cpp( 2884 void x(char a, short (*b)(int), long (**c)(long long)); 2885 )cpp", 2886 R"txt( 2887 *: TranslationUnit 2888 `-SimpleDeclaration 2889 |-void 2890 |-SimpleDeclarator 2891 | |-x 2892 | `-ParametersAndQualifiers 2893 | |-( 2894 | |-SimpleDeclaration 2895 | | |-char 2896 | | `-SimpleDeclarator 2897 | | `-a 2898 | |-, 2899 | |-SimpleDeclaration 2900 | | |-short 2901 | | `-SimpleDeclarator 2902 | | |-ParenDeclarator 2903 | | | |-( 2904 | | | |-* 2905 | | | |-b 2906 | | | `-) 2907 | | `-ParametersAndQualifiers 2908 | | |-( 2909 | | |-SimpleDeclaration 2910 | | | `-int 2911 | | `-) 2912 | |-, 2913 | |-SimpleDeclaration 2914 | | |-long 2915 | | `-SimpleDeclarator 2916 | | |-ParenDeclarator 2917 | | | |-( 2918 | | | |-* 2919 | | | |-* 2920 | | | |-c 2921 | | | `-) 2922 | | `-ParametersAndQualifiers 2923 | | |-( 2924 | | |-SimpleDeclaration 2925 | | | |-long 2926 | | | `-long 2927 | | `-) 2928 | `-) 2929 `-; 2930 )txt")); 2931 } 2932 2933 TEST_P(SyntaxTreeTest, Mutations) { 2934 if (!GetParam().isCXX11OrLater()) { 2935 return; 2936 } 2937 2938 using Transformation = std::function<void( 2939 const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>; 2940 auto CheckTransformation = [this](std::string Input, std::string Expected, 2941 Transformation Transform) -> void { 2942 llvm::Annotations Source(Input); 2943 auto *Root = buildTree(Source.code(), GetParam()); 2944 2945 Transform(Source, Root); 2946 2947 auto Replacements = syntax::computeReplacements(*Arena, *Root); 2948 auto Output = tooling::applyAllReplacements(Source.code(), Replacements); 2949 if (!Output) { 2950 ADD_FAILURE() << "could not apply replacements: " 2951 << llvm::toString(Output.takeError()); 2952 return; 2953 } 2954 2955 EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; 2956 }; 2957 2958 // Removes the selected statement. Input should have exactly one selected 2959 // range and it should correspond to a single statement. 2960 auto RemoveStatement = [this](const llvm::Annotations &Input, 2961 syntax::TranslationUnit *TU) { 2962 auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU)); 2963 ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 2964 syntax::removeStatement(*Arena, S); 2965 EXPECT_TRUE(S->isDetached()); 2966 EXPECT_FALSE(S->isOriginal()) 2967 << "node removed from tree cannot be marked as original"; 2968 }; 2969 2970 std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>> 2971 Cases = { 2972 {"void test() { [[100+100;]] test(); }", "void test() { test(); }"}, 2973 {"void test() { if (true) [[{}]] else {} }", 2974 "void test() { if (true) ; else {} }"}, 2975 {"void test() { [[;]] }", "void test() { }"}}; 2976 for (const auto &C : Cases) 2977 CheckTransformation(C.first, C.second, RemoveStatement); 2978 } 2979 2980 TEST_P(SyntaxTreeTest, SynthesizedNodes) { 2981 buildTree("", GetParam()); 2982 2983 auto *C = syntax::createPunctuation(*Arena, tok::comma); 2984 ASSERT_NE(C, nullptr); 2985 EXPECT_EQ(C->token()->kind(), tok::comma); 2986 EXPECT_TRUE(C->canModify()); 2987 EXPECT_FALSE(C->isOriginal()); 2988 EXPECT_TRUE(C->isDetached()); 2989 2990 auto *S = syntax::createEmptyStatement(*Arena); 2991 ASSERT_NE(S, nullptr); 2992 EXPECT_TRUE(S->canModify()); 2993 EXPECT_FALSE(S->isOriginal()); 2994 EXPECT_TRUE(S->isDetached()); 2995 } 2996 2997 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest, 2998 testing::ValuesIn(TestClangConfig::allConfigs()), ); 2999 3000 } // namespace 3001