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/Lex/PreprocessorOptions.h" 19 #include "clang/Tooling/Core/Replacement.h" 20 #include "clang/Tooling/Syntax/BuildTree.h" 21 #include "clang/Tooling/Syntax/Mutations.h" 22 #include "clang/Tooling/Syntax/Nodes.h" 23 #include "clang/Tooling/Syntax/Tokens.h" 24 #include "clang/Tooling/Tooling.h" 25 #include "llvm/ADT/ArrayRef.h" 26 #include "llvm/ADT/STLExtras.h" 27 #include "llvm/ADT/StringRef.h" 28 #include "llvm/Support/Casting.h" 29 #include "llvm/Support/Error.h" 30 #include "llvm/Testing/Support/Annotations.h" 31 #include "gmock/gmock.h" 32 #include "gtest/gtest.h" 33 #include <cstdlib> 34 35 using namespace clang; 36 37 namespace { 38 static llvm::ArrayRef<syntax::Token> tokens(syntax::Node *N) { 39 assert(N->isOriginal() && "tokens of modified nodes are not well-defined"); 40 if (auto *L = dyn_cast<syntax::Leaf>(N)) 41 return llvm::makeArrayRef(L->token(), 1); 42 auto *T = cast<syntax::Tree>(N); 43 return llvm::makeArrayRef(T->firstLeaf()->token(), 44 T->lastLeaf()->token() + 1); 45 } 46 47 class SyntaxTreeTest : public ::testing::Test { 48 protected: 49 // Build a syntax tree for the code. 50 syntax::TranslationUnit *buildTree(llvm::StringRef Code) { 51 // FIXME: this code is almost the identical to the one in TokensTest. Share 52 // it. 53 class BuildSyntaxTree : public ASTConsumer { 54 public: 55 BuildSyntaxTree(syntax::TranslationUnit *&Root, 56 std::unique_ptr<syntax::Arena> &Arena, 57 std::unique_ptr<syntax::TokenCollector> Tokens) 58 : Root(Root), Arena(Arena), Tokens(std::move(Tokens)) { 59 assert(this->Tokens); 60 } 61 62 void HandleTranslationUnit(ASTContext &Ctx) override { 63 Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(), 64 Ctx.getLangOpts(), 65 std::move(*Tokens).consume()); 66 Tokens = nullptr; // make sure we fail if this gets called twice. 67 Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl()); 68 } 69 70 private: 71 syntax::TranslationUnit *&Root; 72 std::unique_ptr<syntax::Arena> &Arena; 73 std::unique_ptr<syntax::TokenCollector> Tokens; 74 }; 75 76 class BuildSyntaxTreeAction : public ASTFrontendAction { 77 public: 78 BuildSyntaxTreeAction(syntax::TranslationUnit *&Root, 79 std::unique_ptr<syntax::Arena> &Arena) 80 : Root(Root), Arena(Arena) {} 81 82 std::unique_ptr<ASTConsumer> 83 CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { 84 // We start recording the tokens, ast consumer will take on the result. 85 auto Tokens = 86 std::make_unique<syntax::TokenCollector>(CI.getPreprocessor()); 87 return std::make_unique<BuildSyntaxTree>(Root, Arena, 88 std::move(Tokens)); 89 } 90 91 private: 92 syntax::TranslationUnit *&Root; 93 std::unique_ptr<syntax::Arena> &Arena; 94 }; 95 96 constexpr const char *FileName = "./input.cpp"; 97 FS->addFile(FileName, time_t(), llvm::MemoryBuffer::getMemBufferCopy("")); 98 if (!Diags->getClient()) 99 Diags->setClient(new IgnoringDiagConsumer); 100 // Prepare to run a compiler. 101 std::vector<const char *> Args = {"syntax-test", "-std=c++11", 102 "-fsyntax-only", FileName}; 103 Invocation = createInvocationFromCommandLine(Args, Diags, FS); 104 assert(Invocation); 105 Invocation->getFrontendOpts().DisableFree = false; 106 Invocation->getPreprocessorOpts().addRemappedFile( 107 FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release()); 108 CompilerInstance Compiler; 109 Compiler.setInvocation(Invocation); 110 Compiler.setDiagnostics(Diags.get()); 111 Compiler.setFileManager(FileMgr.get()); 112 Compiler.setSourceManager(SourceMgr.get()); 113 114 syntax::TranslationUnit *Root = nullptr; 115 BuildSyntaxTreeAction Recorder(Root, this->Arena); 116 if (!Compiler.ExecuteAction(Recorder)) { 117 ADD_FAILURE() << "failed to run the frontend"; 118 std::abort(); 119 } 120 return Root; 121 } 122 123 // Adds a file to the test VFS. 124 void addFile(llvm::StringRef Path, llvm::StringRef Contents) { 125 if (!FS->addFile(Path, time_t(), 126 llvm::MemoryBuffer::getMemBufferCopy(Contents))) { 127 ADD_FAILURE() << "could not add a file to VFS: " << Path; 128 } 129 } 130 131 /// Finds the deepest node in the tree that covers exactly \p R. 132 /// FIXME: implement this efficiently and move to public syntax tree API. 133 syntax::Node *nodeByRange(llvm::Annotations::Range R, syntax::Node *Root) { 134 llvm::ArrayRef<syntax::Token> Toks = tokens(Root); 135 136 if (Toks.front().location().isFileID() && 137 Toks.back().location().isFileID() && 138 syntax::Token::range(*SourceMgr, Toks.front(), Toks.back()) == 139 syntax::FileRange(SourceMgr->getMainFileID(), R.Begin, R.End)) 140 return Root; 141 142 auto *T = dyn_cast<syntax::Tree>(Root); 143 if (!T) 144 return nullptr; 145 for (auto *C = T->firstChild(); C != nullptr; C = C->nextSibling()) { 146 if (auto *Result = nodeByRange(R, C)) 147 return Result; 148 } 149 return nullptr; 150 } 151 152 // Data fields. 153 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags = 154 new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions); 155 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS = 156 new llvm::vfs::InMemoryFileSystem; 157 llvm::IntrusiveRefCntPtr<FileManager> FileMgr = 158 new FileManager(FileSystemOptions(), FS); 159 llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr = 160 new SourceManager(*Diags, *FileMgr); 161 std::shared_ptr<CompilerInvocation> Invocation; 162 // Set after calling buildTree(). 163 std::unique_ptr<syntax::Arena> Arena; 164 }; 165 166 TEST_F(SyntaxTreeTest, Basic) { 167 std::pair</*Input*/ std::string, /*Expected*/ std::string> Cases[] = { 168 { 169 R"cpp( 170 int main() {} 171 void foo() {} 172 )cpp", 173 R"txt( 174 *: TranslationUnit 175 |-SimpleDeclaration 176 | |-int 177 | |-SimpleDeclarator 178 | | |-main 179 | | `-ParametersAndQualifiers 180 | | |-( 181 | | `-) 182 | `-CompoundStatement 183 | |-{ 184 | `-} 185 `-SimpleDeclaration 186 |-void 187 |-SimpleDeclarator 188 | |-foo 189 | `-ParametersAndQualifiers 190 | |-( 191 | `-) 192 `-CompoundStatement 193 |-{ 194 `-} 195 )txt"}, 196 // if. 197 { 198 R"cpp( 199 int main() { 200 if (true) {} 201 if (true) {} else if (false) {} 202 } 203 )cpp", 204 R"txt( 205 *: TranslationUnit 206 `-SimpleDeclaration 207 |-int 208 |-SimpleDeclarator 209 | |-main 210 | `-ParametersAndQualifiers 211 | |-( 212 | `-) 213 `-CompoundStatement 214 |-{ 215 |-IfStatement 216 | |-if 217 | |-( 218 | |-UnknownExpression 219 | | `-true 220 | |-) 221 | `-CompoundStatement 222 | |-{ 223 | `-} 224 |-IfStatement 225 | |-if 226 | |-( 227 | |-UnknownExpression 228 | | `-true 229 | |-) 230 | |-CompoundStatement 231 | | |-{ 232 | | `-} 233 | |-else 234 | `-IfStatement 235 | |-if 236 | |-( 237 | |-UnknownExpression 238 | | `-false 239 | |-) 240 | `-CompoundStatement 241 | |-{ 242 | `-} 243 `-} 244 )txt"}, 245 // for. 246 {R"cpp( 247 void test() { 248 for (;;) {} 249 } 250 )cpp", 251 R"txt( 252 *: TranslationUnit 253 `-SimpleDeclaration 254 |-void 255 |-SimpleDeclarator 256 | |-test 257 | `-ParametersAndQualifiers 258 | |-( 259 | `-) 260 `-CompoundStatement 261 |-{ 262 |-ForStatement 263 | |-for 264 | |-( 265 | |-; 266 | |-; 267 | |-) 268 | `-CompoundStatement 269 | |-{ 270 | `-} 271 `-} 272 )txt"}, 273 // declaration statement. 274 {"void test() { int a = 10; }", 275 R"txt( 276 *: TranslationUnit 277 `-SimpleDeclaration 278 |-void 279 |-SimpleDeclarator 280 | |-test 281 | `-ParametersAndQualifiers 282 | |-( 283 | `-) 284 `-CompoundStatement 285 |-{ 286 |-DeclarationStatement 287 | |-SimpleDeclaration 288 | | |-int 289 | | `-SimpleDeclarator 290 | | |-a 291 | | |-= 292 | | `-UnknownExpression 293 | | `-10 294 | `-; 295 `-} 296 )txt"}, 297 {"void test() { ; }", R"txt( 298 *: TranslationUnit 299 `-SimpleDeclaration 300 |-void 301 |-SimpleDeclarator 302 | |-test 303 | `-ParametersAndQualifiers 304 | |-( 305 | `-) 306 `-CompoundStatement 307 |-{ 308 |-EmptyStatement 309 | `-; 310 `-} 311 )txt"}, 312 // switch, case and default. 313 {R"cpp( 314 void test() { 315 switch (true) { 316 case 0: 317 default:; 318 } 319 } 320 )cpp", 321 R"txt( 322 *: TranslationUnit 323 `-SimpleDeclaration 324 |-void 325 |-SimpleDeclarator 326 | |-test 327 | `-ParametersAndQualifiers 328 | |-( 329 | `-) 330 `-CompoundStatement 331 |-{ 332 |-SwitchStatement 333 | |-switch 334 | |-( 335 | |-UnknownExpression 336 | | `-true 337 | |-) 338 | `-CompoundStatement 339 | |-{ 340 | |-CaseStatement 341 | | |-case 342 | | |-UnknownExpression 343 | | | `-0 344 | | |-: 345 | | `-DefaultStatement 346 | | |-default 347 | | |-: 348 | | `-EmptyStatement 349 | | `-; 350 | `-} 351 `-} 352 )txt"}, 353 // while. 354 {R"cpp( 355 void test() { 356 while (true) { continue; break; } 357 } 358 )cpp", 359 R"txt( 360 *: TranslationUnit 361 `-SimpleDeclaration 362 |-void 363 |-SimpleDeclarator 364 | |-test 365 | `-ParametersAndQualifiers 366 | |-( 367 | `-) 368 `-CompoundStatement 369 |-{ 370 |-WhileStatement 371 | |-while 372 | |-( 373 | |-UnknownExpression 374 | | `-true 375 | |-) 376 | `-CompoundStatement 377 | |-{ 378 | |-ContinueStatement 379 | | |-continue 380 | | `-; 381 | |-BreakStatement 382 | | |-break 383 | | `-; 384 | `-} 385 `-} 386 )txt"}, 387 // return. 388 {R"cpp( 389 int test() { return 1; } 390 )cpp", 391 R"txt( 392 *: TranslationUnit 393 `-SimpleDeclaration 394 |-int 395 |-SimpleDeclarator 396 | |-test 397 | `-ParametersAndQualifiers 398 | |-( 399 | `-) 400 `-CompoundStatement 401 |-{ 402 |-ReturnStatement 403 | |-return 404 | |-UnknownExpression 405 | | `-1 406 | `-; 407 `-} 408 )txt"}, 409 // Range-based for. 410 {R"cpp( 411 void test() { 412 int a[3]; 413 for (int x : a) ; 414 } 415 )cpp", 416 R"txt( 417 *: TranslationUnit 418 `-SimpleDeclaration 419 |-void 420 |-SimpleDeclarator 421 | |-test 422 | `-ParametersAndQualifiers 423 | |-( 424 | `-) 425 `-CompoundStatement 426 |-{ 427 |-DeclarationStatement 428 | |-SimpleDeclaration 429 | | |-int 430 | | `-SimpleDeclarator 431 | | |-a 432 | | `-ArraySubscript 433 | | |-[ 434 | | |-UnknownExpression 435 | | | `-3 436 | | `-] 437 | `-; 438 |-RangeBasedForStatement 439 | |-for 440 | |-( 441 | |-SimpleDeclaration 442 | | |-int 443 | | |-SimpleDeclarator 444 | | | `-x 445 | | `-: 446 | |-UnknownExpression 447 | | `-a 448 | |-) 449 | `-EmptyStatement 450 | `-; 451 `-} 452 )txt"}, 453 // Unhandled statements should end up as 'unknown statement'. 454 // This example uses a 'label statement', which does not yet have a syntax 455 // counterpart. 456 {"void main() { foo: return 100; }", R"txt( 457 *: TranslationUnit 458 `-SimpleDeclaration 459 |-void 460 |-SimpleDeclarator 461 | |-main 462 | `-ParametersAndQualifiers 463 | |-( 464 | `-) 465 `-CompoundStatement 466 |-{ 467 |-UnknownStatement 468 | |-foo 469 | |-: 470 | `-ReturnStatement 471 | |-return 472 | |-UnknownExpression 473 | | `-100 474 | `-; 475 `-} 476 )txt"}, 477 // expressions should be wrapped in 'ExpressionStatement' when they appear 478 // in a statement position. 479 {R"cpp( 480 void test() { 481 test(); 482 if (true) test(); else test(); 483 } 484 )cpp", 485 R"txt( 486 *: TranslationUnit 487 `-SimpleDeclaration 488 |-void 489 |-SimpleDeclarator 490 | |-test 491 | `-ParametersAndQualifiers 492 | |-( 493 | `-) 494 `-CompoundStatement 495 |-{ 496 |-ExpressionStatement 497 | |-UnknownExpression 498 | | |-test 499 | | |-( 500 | | `-) 501 | `-; 502 |-IfStatement 503 | |-if 504 | |-( 505 | |-UnknownExpression 506 | | `-true 507 | |-) 508 | |-ExpressionStatement 509 | | |-UnknownExpression 510 | | | |-test 511 | | | |-( 512 | | | `-) 513 | | `-; 514 | |-else 515 | `-ExpressionStatement 516 | |-UnknownExpression 517 | | |-test 518 | | |-( 519 | | `-) 520 | `-; 521 `-} 522 )txt"}, 523 // Multiple declarators group into a single SimpleDeclaration. 524 {R"cpp( 525 int *a, b; 526 )cpp", 527 R"txt( 528 *: TranslationUnit 529 `-SimpleDeclaration 530 |-int 531 |-SimpleDeclarator 532 | |-* 533 | `-a 534 |-, 535 |-SimpleDeclarator 536 | `-b 537 `-; 538 )txt"}, 539 {R"cpp( 540 typedef int *a, b; 541 )cpp", 542 R"txt( 543 *: TranslationUnit 544 `-SimpleDeclaration 545 |-typedef 546 |-int 547 |-SimpleDeclarator 548 | |-* 549 | `-a 550 |-, 551 |-SimpleDeclarator 552 | `-b 553 `-; 554 )txt"}, 555 // Multiple declarators inside a statement. 556 {R"cpp( 557 void foo() { 558 int *a, b; 559 typedef int *ta, tb; 560 } 561 )cpp", 562 R"txt( 563 *: TranslationUnit 564 `-SimpleDeclaration 565 |-void 566 |-SimpleDeclarator 567 | |-foo 568 | `-ParametersAndQualifiers 569 | |-( 570 | `-) 571 `-CompoundStatement 572 |-{ 573 |-DeclarationStatement 574 | |-SimpleDeclaration 575 | | |-int 576 | | |-SimpleDeclarator 577 | | | |-* 578 | | | `-a 579 | | |-, 580 | | `-SimpleDeclarator 581 | | `-b 582 | `-; 583 |-DeclarationStatement 584 | |-SimpleDeclaration 585 | | |-typedef 586 | | |-int 587 | | |-SimpleDeclarator 588 | | | |-* 589 | | | `-ta 590 | | |-, 591 | | `-SimpleDeclarator 592 | | `-tb 593 | `-; 594 `-} 595 )txt"}, 596 {R"cpp( 597 namespace a { namespace b {} } 598 namespace a::b {} 599 namespace {} 600 601 namespace foo = a; 602 )cpp", 603 R"txt( 604 *: TranslationUnit 605 |-NamespaceDefinition 606 | |-namespace 607 | |-a 608 | |-{ 609 | |-NamespaceDefinition 610 | | |-namespace 611 | | |-b 612 | | |-{ 613 | | `-} 614 | `-} 615 |-NamespaceDefinition 616 | |-namespace 617 | |-a 618 | |-:: 619 | |-b 620 | |-{ 621 | `-} 622 |-NamespaceDefinition 623 | |-namespace 624 | |-{ 625 | `-} 626 `-NamespaceAliasDefinition 627 |-namespace 628 |-foo 629 |-= 630 |-a 631 `-; 632 )txt"}, 633 // Free-standing classes, must live inside a SimpleDeclaration. 634 {R"cpp( 635 sturct X; 636 struct X {}; 637 638 struct Y *y1; 639 struct Y {} *y2; 640 641 struct {} *a1; 642 )cpp", 643 R"txt( 644 *: TranslationUnit 645 |-SimpleDeclaration 646 | |-sturct 647 | |-X 648 | `-; 649 |-SimpleDeclaration 650 | |-struct 651 | |-X 652 | |-{ 653 | |-} 654 | `-; 655 |-SimpleDeclaration 656 | |-struct 657 | |-Y 658 | |-SimpleDeclarator 659 | | |-* 660 | | `-y1 661 | `-; 662 |-SimpleDeclaration 663 | |-struct 664 | |-Y 665 | |-{ 666 | |-} 667 | |-SimpleDeclarator 668 | | |-* 669 | | `-y2 670 | `-; 671 `-SimpleDeclaration 672 |-struct 673 |-{ 674 |-} 675 |-SimpleDeclarator 676 | |-* 677 | `-a1 678 `-; 679 )txt"}, 680 {R"cpp( 681 template <class T> struct cls {}; 682 template <class T> int var = 10; 683 template <class T> int fun() {} 684 )cpp", 685 R"txt( 686 *: TranslationUnit 687 |-TemplateDeclaration 688 | |-template 689 | |-< 690 | |-UnknownDeclaration 691 | | |-class 692 | | `-T 693 | |-> 694 | `-SimpleDeclaration 695 | |-struct 696 | |-cls 697 | |-{ 698 | |-} 699 | `-; 700 |-TemplateDeclaration 701 | |-template 702 | |-< 703 | |-UnknownDeclaration 704 | | |-class 705 | | `-T 706 | |-> 707 | `-SimpleDeclaration 708 | |-int 709 | |-SimpleDeclarator 710 | | |-var 711 | | |-= 712 | | `-UnknownExpression 713 | | `-10 714 | `-; 715 `-TemplateDeclaration 716 |-template 717 |-< 718 |-UnknownDeclaration 719 | |-class 720 | `-T 721 |-> 722 `-SimpleDeclaration 723 |-int 724 |-SimpleDeclarator 725 | |-fun 726 | `-ParametersAndQualifiers 727 | |-( 728 | `-) 729 `-CompoundStatement 730 |-{ 731 `-} 732 )txt"}, 733 {R"cpp( 734 template <class T> 735 struct X { 736 template <class U> 737 U foo(); 738 }; 739 )cpp", 740 R"txt( 741 *: TranslationUnit 742 `-TemplateDeclaration 743 |-template 744 |-< 745 |-UnknownDeclaration 746 | |-class 747 | `-T 748 |-> 749 `-SimpleDeclaration 750 |-struct 751 |-X 752 |-{ 753 |-TemplateDeclaration 754 | |-template 755 | |-< 756 | |-UnknownDeclaration 757 | | |-class 758 | | `-U 759 | |-> 760 | `-SimpleDeclaration 761 | |-U 762 | |-SimpleDeclarator 763 | | |-foo 764 | | `-ParametersAndQualifiers 765 | | |-( 766 | | `-) 767 | `-; 768 |-} 769 `-; 770 )txt"}, 771 {R"cpp( 772 template <class T> struct X {}; 773 template <class T> struct X<T*> {}; 774 template <> struct X<int> {}; 775 776 template struct X<double>; 777 extern template struct X<float>; 778 )cpp", 779 R"txt( 780 *: TranslationUnit 781 |-TemplateDeclaration 782 | |-template 783 | |-< 784 | |-UnknownDeclaration 785 | | |-class 786 | | `-T 787 | |-> 788 | `-SimpleDeclaration 789 | |-struct 790 | |-X 791 | |-{ 792 | |-} 793 | `-; 794 |-TemplateDeclaration 795 | |-template 796 | |-< 797 | |-UnknownDeclaration 798 | | |-class 799 | | `-T 800 | |-> 801 | `-SimpleDeclaration 802 | |-struct 803 | |-X 804 | |-< 805 | |-T 806 | |-* 807 | |-> 808 | |-{ 809 | |-} 810 | `-; 811 |-TemplateDeclaration 812 | |-template 813 | |-< 814 | |-> 815 | `-SimpleDeclaration 816 | |-struct 817 | |-X 818 | |-< 819 | |-int 820 | |-> 821 | |-{ 822 | |-} 823 | `-; 824 |-ExplicitTemplateInstantiation 825 | |-template 826 | `-SimpleDeclaration 827 | |-struct 828 | |-X 829 | |-< 830 | |-double 831 | |-> 832 | `-; 833 `-ExplicitTemplateInstantiation 834 |-extern 835 |-template 836 `-SimpleDeclaration 837 |-struct 838 |-X 839 |-< 840 |-float 841 |-> 842 `-; 843 )txt"}, 844 {R"cpp( 845 template <class T> struct X { struct Y; }; 846 template <class T> struct X<T>::Y {}; 847 )cpp", 848 R"txt( 849 *: TranslationUnit 850 |-TemplateDeclaration 851 | |-template 852 | |-< 853 | |-UnknownDeclaration 854 | | |-class 855 | | `-T 856 | |-> 857 | `-SimpleDeclaration 858 | |-struct 859 | |-X 860 | |-{ 861 | |-SimpleDeclaration 862 | | |-struct 863 | | |-Y 864 | | `-; 865 | |-} 866 | `-; 867 `-TemplateDeclaration 868 |-template 869 |-< 870 |-UnknownDeclaration 871 | |-class 872 | `-T 873 |-> 874 `-SimpleDeclaration 875 |-struct 876 |-X 877 |-< 878 |-T 879 |-> 880 |-:: 881 |-Y 882 |-{ 883 |-} 884 `-; 885 )txt"}, 886 {R"cpp( 887 namespace ns {} 888 using namespace ::ns; 889 )cpp", 890 R"txt( 891 *: TranslationUnit 892 |-NamespaceDefinition 893 | |-namespace 894 | |-ns 895 | |-{ 896 | `-} 897 `-UsingNamespaceDirective 898 |-using 899 |-namespace 900 |-:: 901 |-ns 902 `-; 903 )txt"}, 904 {R"cpp( 905 namespace ns { int a; } 906 using ns::a; 907 )cpp", 908 R"txt( 909 *: TranslationUnit 910 |-NamespaceDefinition 911 | |-namespace 912 | |-ns 913 | |-{ 914 | |-SimpleDeclaration 915 | | |-int 916 | | |-SimpleDeclarator 917 | | | `-a 918 | | `-; 919 | `-} 920 `-UsingDeclaration 921 |-using 922 |-ns 923 |-:: 924 |-a 925 `-; 926 )txt"}, 927 {R"cpp( 928 template <class T> struct X { 929 using T::foo; 930 using typename T::bar; 931 }; 932 )cpp", 933 R"txt( 934 *: TranslationUnit 935 `-TemplateDeclaration 936 |-template 937 |-< 938 |-UnknownDeclaration 939 | |-class 940 | `-T 941 |-> 942 `-SimpleDeclaration 943 |-struct 944 |-X 945 |-{ 946 |-UsingDeclaration 947 | |-using 948 | |-T 949 | |-:: 950 | |-foo 951 | `-; 952 |-UsingDeclaration 953 | |-using 954 | |-typename 955 | |-T 956 | |-:: 957 | |-bar 958 | `-; 959 |-} 960 `-; 961 )txt"}, 962 {R"cpp( 963 using type = int; 964 )cpp", 965 R"txt( 966 *: TranslationUnit 967 `-TypeAliasDeclaration 968 |-using 969 |-type 970 |-= 971 |-int 972 `-; 973 )txt"}, 974 {R"cpp( 975 ; 976 )cpp", 977 R"txt( 978 *: TranslationUnit 979 `-EmptyDeclaration 980 `-; 981 )txt"}, 982 {R"cpp( 983 static_assert(true, "message"); 984 static_assert(true); 985 )cpp", 986 R"txt( 987 *: TranslationUnit 988 |-StaticAssertDeclaration 989 | |-static_assert 990 | |-( 991 | |-UnknownExpression 992 | | `-true 993 | |-, 994 | |-UnknownExpression 995 | | `-"message" 996 | |-) 997 | `-; 998 `-StaticAssertDeclaration 999 |-static_assert 1000 |-( 1001 |-UnknownExpression 1002 | `-true 1003 |-) 1004 `-; 1005 )txt"}, 1006 {R"cpp( 1007 extern "C" int a; 1008 extern "C" { int b; int c; } 1009 )cpp", 1010 R"txt( 1011 *: TranslationUnit 1012 |-LinkageSpecificationDeclaration 1013 | |-extern 1014 | |-"C" 1015 | `-SimpleDeclaration 1016 | |-int 1017 | |-SimpleDeclarator 1018 | | `-a 1019 | `-; 1020 `-LinkageSpecificationDeclaration 1021 |-extern 1022 |-"C" 1023 |-{ 1024 |-SimpleDeclaration 1025 | |-int 1026 | |-SimpleDeclarator 1027 | | `-b 1028 | `-; 1029 |-SimpleDeclaration 1030 | |-int 1031 | |-SimpleDeclarator 1032 | | `-c 1033 | `-; 1034 `-} 1035 )txt"}, 1036 // Some nodes are non-modifiable, they are marked with 'I:'. 1037 {R"cpp( 1038 #define HALF_IF if (1+ 1039 #define HALF_IF_2 1) {} 1040 void test() { 1041 HALF_IF HALF_IF_2 else {} 1042 })cpp", 1043 R"txt( 1044 *: TranslationUnit 1045 `-SimpleDeclaration 1046 |-void 1047 |-SimpleDeclarator 1048 | |-test 1049 | `-ParametersAndQualifiers 1050 | |-( 1051 | `-) 1052 `-CompoundStatement 1053 |-{ 1054 |-IfStatement 1055 | |-I: if 1056 | |-I: ( 1057 | |-I: UnknownExpression 1058 | | |-I: 1 1059 | | |-I: + 1060 | | `-I: 1 1061 | |-I: ) 1062 | |-I: CompoundStatement 1063 | | |-I: { 1064 | | `-I: } 1065 | |-else 1066 | `-CompoundStatement 1067 | |-{ 1068 | `-} 1069 `-} 1070 )txt"}, 1071 // All nodes can be mutated. 1072 {R"cpp( 1073 #define OPEN { 1074 #define CLOSE } 1075 1076 void test() { 1077 OPEN 1078 1; 1079 CLOSE 1080 1081 OPEN 1082 2; 1083 } 1084 } 1085 )cpp", 1086 R"txt( 1087 *: TranslationUnit 1088 `-SimpleDeclaration 1089 |-void 1090 |-SimpleDeclarator 1091 | |-test 1092 | `-ParametersAndQualifiers 1093 | |-( 1094 | `-) 1095 `-CompoundStatement 1096 |-{ 1097 |-CompoundStatement 1098 | |-{ 1099 | |-ExpressionStatement 1100 | | |-UnknownExpression 1101 | | | `-1 1102 | | `-; 1103 | `-} 1104 |-CompoundStatement 1105 | |-{ 1106 | |-ExpressionStatement 1107 | | |-UnknownExpression 1108 | | | `-2 1109 | | `-; 1110 | `-} 1111 `-} 1112 )txt"}, 1113 // Array subscripts in declarators. 1114 {R"cpp( 1115 int a[10]; 1116 int b[1][2][3]; 1117 int c[] = {1,2,3}; 1118 void f(int xs[static 10]); 1119 )cpp", 1120 R"txt( 1121 *: TranslationUnit 1122 |-SimpleDeclaration 1123 | |-int 1124 | |-SimpleDeclarator 1125 | | |-a 1126 | | `-ArraySubscript 1127 | | |-[ 1128 | | |-UnknownExpression 1129 | | | `-10 1130 | | `-] 1131 | `-; 1132 |-SimpleDeclaration 1133 | |-int 1134 | |-SimpleDeclarator 1135 | | |-b 1136 | | |-ArraySubscript 1137 | | | |-[ 1138 | | | |-UnknownExpression 1139 | | | | `-1 1140 | | | `-] 1141 | | |-ArraySubscript 1142 | | | |-[ 1143 | | | |-UnknownExpression 1144 | | | | `-2 1145 | | | `-] 1146 | | `-ArraySubscript 1147 | | |-[ 1148 | | |-UnknownExpression 1149 | | | `-3 1150 | | `-] 1151 | `-; 1152 |-SimpleDeclaration 1153 | |-int 1154 | |-SimpleDeclarator 1155 | | |-c 1156 | | |-ArraySubscript 1157 | | | |-[ 1158 | | | `-] 1159 | | |-= 1160 | | `-UnknownExpression 1161 | | |-{ 1162 | | |-1 1163 | | |-, 1164 | | |-2 1165 | | |-, 1166 | | |-3 1167 | | `-} 1168 | `-; 1169 `-SimpleDeclaration 1170 |-void 1171 |-SimpleDeclarator 1172 | |-f 1173 | `-ParametersAndQualifiers 1174 | |-( 1175 | |-SimpleDeclaration 1176 | | |-int 1177 | | `-SimpleDeclarator 1178 | | |-xs 1179 | | `-ArraySubscript 1180 | | |-[ 1181 | | |-static 1182 | | |-UnknownExpression 1183 | | | `-10 1184 | | `-] 1185 | `-) 1186 `-; 1187 )txt"}, 1188 // Parameter lists in declarators. 1189 {R"cpp( 1190 int a() const; 1191 int b() volatile; 1192 int c() &; 1193 int d() &&; 1194 int foo(int a, int b); 1195 int foo( 1196 const int a, 1197 volatile int b, 1198 const volatile int c, 1199 int* d, 1200 int& e, 1201 int&& f 1202 ); 1203 )cpp", 1204 R"txt( 1205 *: TranslationUnit 1206 |-SimpleDeclaration 1207 | |-int 1208 | |-SimpleDeclarator 1209 | | |-a 1210 | | `-ParametersAndQualifiers 1211 | | |-( 1212 | | |-) 1213 | | `-const 1214 | `-; 1215 |-SimpleDeclaration 1216 | |-int 1217 | |-SimpleDeclarator 1218 | | |-b 1219 | | `-ParametersAndQualifiers 1220 | | |-( 1221 | | |-) 1222 | | `-volatile 1223 | `-; 1224 |-SimpleDeclaration 1225 | |-int 1226 | |-SimpleDeclarator 1227 | | |-c 1228 | | `-ParametersAndQualifiers 1229 | | |-( 1230 | | |-) 1231 | | `-& 1232 | `-; 1233 |-SimpleDeclaration 1234 | |-int 1235 | |-SimpleDeclarator 1236 | | |-d 1237 | | `-ParametersAndQualifiers 1238 | | |-( 1239 | | |-) 1240 | | `-&& 1241 | `-; 1242 |-SimpleDeclaration 1243 | |-int 1244 | |-SimpleDeclarator 1245 | | |-foo 1246 | | `-ParametersAndQualifiers 1247 | | |-( 1248 | | |-SimpleDeclaration 1249 | | | |-int 1250 | | | `-SimpleDeclarator 1251 | | | `-a 1252 | | |-, 1253 | | |-SimpleDeclaration 1254 | | | |-int 1255 | | | `-SimpleDeclarator 1256 | | | `-b 1257 | | `-) 1258 | `-; 1259 `-SimpleDeclaration 1260 |-int 1261 |-SimpleDeclarator 1262 | |-foo 1263 | `-ParametersAndQualifiers 1264 | |-( 1265 | |-SimpleDeclaration 1266 | | |-const 1267 | | |-int 1268 | | `-SimpleDeclarator 1269 | | `-a 1270 | |-, 1271 | |-SimpleDeclaration 1272 | | |-volatile 1273 | | |-int 1274 | | `-SimpleDeclarator 1275 | | `-b 1276 | |-, 1277 | |-SimpleDeclaration 1278 | | |-const 1279 | | |-volatile 1280 | | |-int 1281 | | `-SimpleDeclarator 1282 | | `-c 1283 | |-, 1284 | |-SimpleDeclaration 1285 | | |-int 1286 | | `-SimpleDeclarator 1287 | | |-* 1288 | | `-d 1289 | |-, 1290 | |-SimpleDeclaration 1291 | | |-int 1292 | | `-SimpleDeclarator 1293 | | |-& 1294 | | `-e 1295 | |-, 1296 | |-SimpleDeclaration 1297 | | |-int 1298 | | `-SimpleDeclarator 1299 | | |-&& 1300 | | `-f 1301 | `-) 1302 `-; 1303 )txt"}, 1304 // Trailing const qualifier. 1305 {R"cpp( 1306 struct X { 1307 int foo() const; 1308 } 1309 )cpp", 1310 R"txt( 1311 *: TranslationUnit 1312 `-SimpleDeclaration 1313 |-struct 1314 |-X 1315 |-{ 1316 |-SimpleDeclaration 1317 | |-int 1318 | |-SimpleDeclarator 1319 | | |-foo 1320 | | `-ParametersAndQualifiers 1321 | | |-( 1322 | | |-) 1323 | | `-const 1324 | `-; 1325 `-} 1326 )txt"}, 1327 // Trailing return type in parameter lists. 1328 {R"cpp( 1329 auto foo() -> int; 1330 )cpp", 1331 R"txt( 1332 *: TranslationUnit 1333 `-SimpleDeclaration 1334 |-auto 1335 |-SimpleDeclarator 1336 | |-foo 1337 | `-ParametersAndQualifiers 1338 | |-( 1339 | |-) 1340 | `-TrailingReturnType 1341 | |--> 1342 | `-int 1343 `-; 1344 )txt"}, 1345 // Exception specification in parameter lists. 1346 {R"cpp( 1347 int a() noexcept; 1348 int b() noexcept(true); 1349 int c() throw(); 1350 )cpp", 1351 R"txt( 1352 *: TranslationUnit 1353 |-SimpleDeclaration 1354 | |-int 1355 | |-SimpleDeclarator 1356 | | |-a 1357 | | `-ParametersAndQualifiers 1358 | | |-( 1359 | | |-) 1360 | | `-noexcept 1361 | `-; 1362 |-SimpleDeclaration 1363 | |-int 1364 | |-SimpleDeclarator 1365 | | |-b 1366 | | `-ParametersAndQualifiers 1367 | | |-( 1368 | | |-) 1369 | | |-noexcept 1370 | | |-( 1371 | | |-UnknownExpression 1372 | | | `-true 1373 | | `-) 1374 | `-; 1375 `-SimpleDeclaration 1376 |-int 1377 |-SimpleDeclarator 1378 | |-c 1379 | `-ParametersAndQualifiers 1380 | |-( 1381 | |-) 1382 | |-throw 1383 | |-( 1384 | `-) 1385 `-; 1386 )txt"}, 1387 // Declarators in parentheses. 1388 {R"cpp( 1389 int (a); 1390 int *(b); 1391 int (*c)(int); 1392 int *(d)(int); 1393 )cpp", 1394 R"txt( 1395 *: TranslationUnit 1396 |-SimpleDeclaration 1397 | |-int 1398 | |-SimpleDeclarator 1399 | | `-ParenDeclarator 1400 | | |-( 1401 | | |-a 1402 | | `-) 1403 | `-; 1404 |-SimpleDeclaration 1405 | |-int 1406 | |-SimpleDeclarator 1407 | | |-* 1408 | | `-ParenDeclarator 1409 | | |-( 1410 | | |-b 1411 | | `-) 1412 | `-; 1413 |-SimpleDeclaration 1414 | |-int 1415 | |-SimpleDeclarator 1416 | | |-ParenDeclarator 1417 | | | |-( 1418 | | | |-* 1419 | | | |-c 1420 | | | `-) 1421 | | `-ParametersAndQualifiers 1422 | | |-( 1423 | | |-SimpleDeclaration 1424 | | | `-int 1425 | | `-) 1426 | `-; 1427 `-SimpleDeclaration 1428 |-int 1429 |-SimpleDeclarator 1430 | |-* 1431 | |-ParenDeclarator 1432 | | |-( 1433 | | |-d 1434 | | `-) 1435 | `-ParametersAndQualifiers 1436 | |-( 1437 | |-SimpleDeclaration 1438 | | `-int 1439 | `-) 1440 `-; 1441 )txt"}, 1442 // CV qualifiers. 1443 {R"cpp( 1444 const int west = -1; 1445 int const east = 1; 1446 const int const universal = 0; 1447 const int const *const *volatile b; 1448 )cpp", 1449 R"txt( 1450 *: TranslationUnit 1451 |-SimpleDeclaration 1452 | |-const 1453 | |-int 1454 | |-SimpleDeclarator 1455 | | |-west 1456 | | |-= 1457 | | `-UnknownExpression 1458 | | |-- 1459 | | `-1 1460 | `-; 1461 |-SimpleDeclaration 1462 | |-int 1463 | |-const 1464 | |-SimpleDeclarator 1465 | | |-east 1466 | | |-= 1467 | | `-UnknownExpression 1468 | | `-1 1469 | `-; 1470 |-SimpleDeclaration 1471 | |-const 1472 | |-int 1473 | |-const 1474 | |-SimpleDeclarator 1475 | | |-universal 1476 | | |-= 1477 | | `-UnknownExpression 1478 | | `-0 1479 | `-; 1480 `-SimpleDeclaration 1481 |-const 1482 |-int 1483 |-const 1484 |-SimpleDeclarator 1485 | |-* 1486 | |-const 1487 | |-* 1488 | |-volatile 1489 | `-b 1490 `-; 1491 )txt"}, 1492 // Ranges of declarators with trailing return types. 1493 {R"cpp( 1494 auto foo() -> auto(*)(int) -> double*; 1495 )cpp", 1496 R"txt( 1497 *: TranslationUnit 1498 `-SimpleDeclaration 1499 |-auto 1500 |-SimpleDeclarator 1501 | |-foo 1502 | `-ParametersAndQualifiers 1503 | |-( 1504 | |-) 1505 | `-TrailingReturnType 1506 | |--> 1507 | |-auto 1508 | `-SimpleDeclarator 1509 | |-ParenDeclarator 1510 | | |-( 1511 | | |-* 1512 | | `-) 1513 | `-ParametersAndQualifiers 1514 | |-( 1515 | |-SimpleDeclaration 1516 | | `-int 1517 | |-) 1518 | `-TrailingReturnType 1519 | |--> 1520 | |-double 1521 | `-SimpleDeclarator 1522 | `-* 1523 `-; 1524 )txt"}, 1525 // Member pointers. 1526 {R"cpp( 1527 struct X {}; 1528 int X::* a; 1529 const int X::* b; 1530 )cpp", 1531 R"txt( 1532 *: TranslationUnit 1533 |-SimpleDeclaration 1534 | |-struct 1535 | |-X 1536 | |-{ 1537 | |-} 1538 | `-; 1539 |-SimpleDeclaration 1540 | |-int 1541 | |-SimpleDeclarator 1542 | | |-MemberPointer 1543 | | | |-X 1544 | | | |-:: 1545 | | | `-* 1546 | | `-a 1547 | `-; 1548 `-SimpleDeclaration 1549 |-const 1550 |-int 1551 |-SimpleDeclarator 1552 | |-MemberPointer 1553 | | |-X 1554 | | |-:: 1555 | | `-* 1556 | `-b 1557 `-; 1558 )txt"}, 1559 // All-in-one tests. 1560 {R"cpp( 1561 void x(char a, short (*b)(int)); 1562 )cpp", 1563 R"txt( 1564 *: TranslationUnit 1565 `-SimpleDeclaration 1566 |-void 1567 |-SimpleDeclarator 1568 | |-x 1569 | `-ParametersAndQualifiers 1570 | |-( 1571 | |-SimpleDeclaration 1572 | | |-char 1573 | | `-SimpleDeclarator 1574 | | `-a 1575 | |-, 1576 | |-SimpleDeclaration 1577 | | |-short 1578 | | `-SimpleDeclarator 1579 | | |-ParenDeclarator 1580 | | | |-( 1581 | | | |-* 1582 | | | |-b 1583 | | | `-) 1584 | | `-ParametersAndQualifiers 1585 | | |-( 1586 | | |-SimpleDeclaration 1587 | | | `-int 1588 | | `-) 1589 | `-) 1590 `-; 1591 )txt"}, 1592 {R"cpp( 1593 void x(char a, short (*b)(int), long (**c)(long long)); 1594 )cpp", 1595 R"txt( 1596 *: TranslationUnit 1597 `-SimpleDeclaration 1598 |-void 1599 |-SimpleDeclarator 1600 | |-x 1601 | `-ParametersAndQualifiers 1602 | |-( 1603 | |-SimpleDeclaration 1604 | | |-char 1605 | | `-SimpleDeclarator 1606 | | `-a 1607 | |-, 1608 | |-SimpleDeclaration 1609 | | |-short 1610 | | `-SimpleDeclarator 1611 | | |-ParenDeclarator 1612 | | | |-( 1613 | | | |-* 1614 | | | |-b 1615 | | | `-) 1616 | | `-ParametersAndQualifiers 1617 | | |-( 1618 | | |-SimpleDeclaration 1619 | | | `-int 1620 | | `-) 1621 | |-, 1622 | |-SimpleDeclaration 1623 | | |-long 1624 | | `-SimpleDeclarator 1625 | | |-ParenDeclarator 1626 | | | |-( 1627 | | | |-* 1628 | | | |-* 1629 | | | |-c 1630 | | | `-) 1631 | | `-ParametersAndQualifiers 1632 | | |-( 1633 | | |-SimpleDeclaration 1634 | | | |-long 1635 | | | `-long 1636 | | `-) 1637 | `-) 1638 `-; 1639 )txt"}, 1640 }; 1641 1642 for (const auto &T : Cases) { 1643 SCOPED_TRACE(T.first); 1644 1645 auto *Root = buildTree(T.first); 1646 std::string Expected = llvm::StringRef(T.second).trim().str(); 1647 std::string Actual = 1648 std::string(llvm::StringRef(Root->dump(*Arena)).trim()); 1649 EXPECT_EQ(Expected, Actual) << "the resulting dump is:\n" << Actual; 1650 } 1651 } 1652 1653 TEST_F(SyntaxTreeTest, Mutations) { 1654 using Transformation = std::function<void( 1655 const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>; 1656 auto CheckTransformation = [this](std::string Input, std::string Expected, 1657 Transformation Transform) -> void { 1658 llvm::Annotations Source(Input); 1659 auto *Root = buildTree(Source.code()); 1660 1661 Transform(Source, Root); 1662 1663 auto Replacements = syntax::computeReplacements(*Arena, *Root); 1664 auto Output = tooling::applyAllReplacements(Source.code(), Replacements); 1665 if (!Output) { 1666 ADD_FAILURE() << "could not apply replacements: " 1667 << llvm::toString(Output.takeError()); 1668 return; 1669 } 1670 1671 EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; 1672 }; 1673 1674 // Removes the selected statement. Input should have exactly one selected 1675 // range and it should correspond to a single statement. 1676 auto RemoveStatement = [this](const llvm::Annotations &Input, 1677 syntax::TranslationUnit *TU) { 1678 auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU)); 1679 ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 1680 syntax::removeStatement(*Arena, S); 1681 EXPECT_TRUE(S->isDetached()); 1682 EXPECT_FALSE(S->isOriginal()) 1683 << "node removed from tree cannot be marked as original"; 1684 }; 1685 1686 std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>> 1687 Cases = { 1688 {"void test() { [[100+100;]] test(); }", "void test() { test(); }"}, 1689 {"void test() { if (true) [[{}]] else {} }", 1690 "void test() { if (true) ; else {} }"}, 1691 {"void test() { [[;]] }", "void test() { }"}}; 1692 for (const auto &C : Cases) 1693 CheckTransformation(C.first, C.second, RemoveStatement); 1694 } 1695 1696 TEST_F(SyntaxTreeTest, SynthesizedNodes) { 1697 buildTree(""); 1698 1699 auto *C = syntax::createPunctuation(*Arena, tok::comma); 1700 ASSERT_NE(C, nullptr); 1701 EXPECT_EQ(C->token()->kind(), tok::comma); 1702 EXPECT_TRUE(C->canModify()); 1703 EXPECT_FALSE(C->isOriginal()); 1704 EXPECT_TRUE(C->isDetached()); 1705 1706 auto *S = syntax::createEmptyStatement(*Arena); 1707 ASSERT_NE(S, nullptr); 1708 EXPECT_TRUE(S->canModify()); 1709 EXPECT_FALSE(S->isOriginal()); 1710 EXPECT_TRUE(S->isDetached()); 1711 } 1712 1713 } // namespace 1714