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