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