1 //===- unittests/AST/DeclPrinterTest.cpp --- Declaration printer tests ----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains tests for Decl::print() and related methods. 11 // 12 // Search this file for WRONG to see test cases that are producing something 13 // completely wrong, invalid C++ or just misleading. 14 // 15 // These tests have a coding convention: 16 // * declaration to be printed is named 'A' unless it should have some special 17 // name (e.g., 'operator+'); 18 // * additional helper declarations are 'Z', 'Y', 'X' and so on. 19 // 20 //===----------------------------------------------------------------------===// 21 22 #include "clang/AST/ASTContext.h" 23 #include "clang/ASTMatchers/ASTMatchFinder.h" 24 #include "clang/Tooling/Tooling.h" 25 #include "llvm/ADT/SmallString.h" 26 #include "gtest/gtest.h" 27 28 using namespace clang; 29 using namespace ast_matchers; 30 using namespace tooling; 31 32 namespace { 33 34 using PrintingPolicyModifier = void (*)(PrintingPolicy &policy); 35 36 void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D, 37 PrintingPolicyModifier PolicyModifier) { 38 PrintingPolicy Policy = Context->getPrintingPolicy(); 39 Policy.TerseOutput = true; 40 if (PolicyModifier) 41 PolicyModifier(Policy); 42 D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false); 43 } 44 45 class PrintMatch : public MatchFinder::MatchCallback { 46 SmallString<1024> Printed; 47 unsigned NumFoundDecls; 48 PrintingPolicyModifier PolicyModifier; 49 50 public: 51 PrintMatch(PrintingPolicyModifier PolicyModifier) 52 : NumFoundDecls(0), PolicyModifier(PolicyModifier) {} 53 54 void run(const MatchFinder::MatchResult &Result) override { 55 const Decl *D = Result.Nodes.getNodeAs<Decl>("id"); 56 if (!D || D->isImplicit()) 57 return; 58 NumFoundDecls++; 59 if (NumFoundDecls > 1) 60 return; 61 62 llvm::raw_svector_ostream Out(Printed); 63 PrintDecl(Out, Result.Context, D, PolicyModifier); 64 } 65 66 StringRef getPrinted() const { 67 return Printed; 68 } 69 70 unsigned getNumFoundDecls() const { 71 return NumFoundDecls; 72 } 73 }; 74 75 ::testing::AssertionResult 76 PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args, 77 const DeclarationMatcher &NodeMatch, 78 StringRef ExpectedPrinted, StringRef FileName, 79 PrintingPolicyModifier PolicyModifier = nullptr) { 80 PrintMatch Printer(PolicyModifier); 81 MatchFinder Finder; 82 Finder.addMatcher(NodeMatch, &Printer); 83 std::unique_ptr<FrontendActionFactory> Factory( 84 newFrontendActionFactory(&Finder)); 85 86 if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName)) 87 return testing::AssertionFailure() 88 << "Parsing error in \"" << Code.str() << "\""; 89 90 if (Printer.getNumFoundDecls() == 0) 91 return testing::AssertionFailure() 92 << "Matcher didn't find any declarations"; 93 94 if (Printer.getNumFoundDecls() > 1) 95 return testing::AssertionFailure() 96 << "Matcher should match only one declaration " 97 "(found " << Printer.getNumFoundDecls() << ")"; 98 99 if (Printer.getPrinted() != ExpectedPrinted) 100 return ::testing::AssertionFailure() 101 << "Expected \"" << ExpectedPrinted.str() << "\", " 102 "got \"" << Printer.getPrinted().str() << "\""; 103 104 return ::testing::AssertionSuccess(); 105 } 106 107 ::testing::AssertionResult 108 PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName, 109 StringRef ExpectedPrinted, 110 PrintingPolicyModifier PolicyModifier = nullptr) { 111 std::vector<std::string> Args(1, "-std=c++98"); 112 return PrintedDeclMatches(Code, 113 Args, 114 namedDecl(hasName(DeclName)).bind("id"), 115 ExpectedPrinted, 116 "input.cc", 117 PolicyModifier); 118 } 119 120 ::testing::AssertionResult 121 PrintedDeclCXX98Matches(StringRef Code, const DeclarationMatcher &NodeMatch, 122 StringRef ExpectedPrinted, 123 PrintingPolicyModifier PolicyModifier = nullptr) { 124 std::vector<std::string> Args(1, "-std=c++98"); 125 return PrintedDeclMatches(Code, 126 Args, 127 NodeMatch, 128 ExpectedPrinted, 129 "input.cc", 130 PolicyModifier); 131 } 132 133 ::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code, 134 StringRef DeclName, 135 StringRef ExpectedPrinted) { 136 std::vector<std::string> Args(1, "-std=c++11"); 137 return PrintedDeclMatches(Code, 138 Args, 139 namedDecl(hasName(DeclName)).bind("id"), 140 ExpectedPrinted, 141 "input.cc"); 142 } 143 144 ::testing::AssertionResult PrintedDeclCXX11Matches( 145 StringRef Code, 146 const DeclarationMatcher &NodeMatch, 147 StringRef ExpectedPrinted) { 148 std::vector<std::string> Args(1, "-std=c++11"); 149 return PrintedDeclMatches(Code, 150 Args, 151 NodeMatch, 152 ExpectedPrinted, 153 "input.cc"); 154 } 155 156 ::testing::AssertionResult PrintedDeclCXX11nonMSCMatches( 157 StringRef Code, 158 const DeclarationMatcher &NodeMatch, 159 StringRef ExpectedPrinted) { 160 std::vector<std::string> Args(1, "-std=c++11"); 161 Args.push_back("-fno-delayed-template-parsing"); 162 return PrintedDeclMatches(Code, 163 Args, 164 NodeMatch, 165 ExpectedPrinted, 166 "input.cc"); 167 } 168 169 ::testing::AssertionResult 170 PrintedDeclCXX1ZMatches(StringRef Code, const DeclarationMatcher &NodeMatch, 171 StringRef ExpectedPrinted) { 172 std::vector<std::string> Args(1, "-std=c++1z"); 173 return PrintedDeclMatches(Code, 174 Args, 175 NodeMatch, 176 ExpectedPrinted, 177 "input.cc"); 178 } 179 180 ::testing::AssertionResult PrintedDeclObjCMatches( 181 StringRef Code, 182 const DeclarationMatcher &NodeMatch, 183 StringRef ExpectedPrinted) { 184 std::vector<std::string> Args(1, ""); 185 return PrintedDeclMatches(Code, 186 Args, 187 NodeMatch, 188 ExpectedPrinted, 189 "input.m"); 190 } 191 192 } // unnamed namespace 193 194 TEST(DeclPrinter, TestTypedef1) { 195 ASSERT_TRUE(PrintedDeclCXX98Matches( 196 "typedef int A;", 197 "A", 198 "typedef int A")); 199 // Should be: with semicolon 200 } 201 202 TEST(DeclPrinter, TestTypedef2) { 203 ASSERT_TRUE(PrintedDeclCXX98Matches( 204 "typedef const char *A;", 205 "A", 206 "typedef const char *A")); 207 // Should be: with semicolon 208 } 209 210 TEST(DeclPrinter, TestTypedef3) { 211 ASSERT_TRUE(PrintedDeclCXX98Matches( 212 "template <typename Y> class X {};" 213 "typedef X<int> A;", 214 "A", 215 "typedef X<int> A")); 216 // Should be: with semicolon 217 } 218 219 TEST(DeclPrinter, TestTypedef4) { 220 ASSERT_TRUE(PrintedDeclCXX98Matches( 221 "namespace X { class Y {}; }" 222 "typedef X::Y A;", 223 "A", 224 "typedef X::Y A")); 225 // Should be: with semicolon 226 } 227 228 TEST(DeclPrinter, TestNamespace1) { 229 ASSERT_TRUE(PrintedDeclCXX98Matches( 230 "namespace A { int B; }", 231 "A", 232 "namespace A {\n}")); 233 // Should be: with { ... } 234 } 235 236 TEST(DeclPrinter, TestNamespace2) { 237 ASSERT_TRUE(PrintedDeclCXX11Matches( 238 "inline namespace A { int B; }", 239 "A", 240 "inline namespace A {\n}")); 241 // Should be: with { ... } 242 } 243 244 TEST(DeclPrinter, TestNamespaceAlias1) { 245 ASSERT_TRUE(PrintedDeclCXX98Matches( 246 "namespace Z { }" 247 "namespace A = Z;", 248 "A", 249 "namespace A = Z")); 250 // Should be: with semicolon 251 } 252 253 TEST(DeclPrinter, TestNamespaceAlias2) { 254 ASSERT_TRUE(PrintedDeclCXX98Matches( 255 "namespace X { namespace Y {} }" 256 "namespace A = X::Y;", 257 "A", 258 "namespace A = X::Y")); 259 // Should be: with semicolon 260 } 261 262 TEST(DeclPrinter, TestCXXRecordDecl1) { 263 ASSERT_TRUE(PrintedDeclCXX98Matches( 264 "class A { int a; };", 265 "A", 266 "class A {}")); 267 } 268 269 TEST(DeclPrinter, TestCXXRecordDecl2) { 270 ASSERT_TRUE(PrintedDeclCXX98Matches( 271 "struct A { int a; };", 272 "A", 273 "struct A {}")); 274 } 275 276 TEST(DeclPrinter, TestCXXRecordDecl3) { 277 ASSERT_TRUE(PrintedDeclCXX98Matches( 278 "union A { int a; };", 279 "A", 280 "union A {}")); 281 } 282 283 TEST(DeclPrinter, TestCXXRecordDecl4) { 284 ASSERT_TRUE(PrintedDeclCXX98Matches( 285 "class Z { int a; };" 286 "class A : Z { int b; };", 287 "A", 288 "class A : Z {}")); 289 } 290 291 TEST(DeclPrinter, TestCXXRecordDecl5) { 292 ASSERT_TRUE(PrintedDeclCXX98Matches( 293 "struct Z { int a; };" 294 "struct A : Z { int b; };", 295 "A", 296 "struct A : Z {}")); 297 } 298 299 TEST(DeclPrinter, TestCXXRecordDecl6) { 300 ASSERT_TRUE(PrintedDeclCXX98Matches( 301 "class Z { int a; };" 302 "class A : public Z { int b; };", 303 "A", 304 "class A : public Z {}")); 305 } 306 307 TEST(DeclPrinter, TestCXXRecordDecl7) { 308 ASSERT_TRUE(PrintedDeclCXX98Matches( 309 "class Z { int a; };" 310 "class A : protected Z { int b; };", 311 "A", 312 "class A : protected Z {}")); 313 } 314 315 TEST(DeclPrinter, TestCXXRecordDecl8) { 316 ASSERT_TRUE(PrintedDeclCXX98Matches( 317 "class Z { int a; };" 318 "class A : private Z { int b; };", 319 "A", 320 "class A : private Z {}")); 321 } 322 323 TEST(DeclPrinter, TestCXXRecordDecl9) { 324 ASSERT_TRUE(PrintedDeclCXX98Matches( 325 "class Z { int a; };" 326 "class A : virtual Z { int b; };", 327 "A", 328 "class A : virtual Z {}")); 329 } 330 331 TEST(DeclPrinter, TestCXXRecordDecl10) { 332 ASSERT_TRUE(PrintedDeclCXX98Matches( 333 "class Z { int a; };" 334 "class A : virtual public Z { int b; };", 335 "A", 336 "class A : virtual public Z {}")); 337 } 338 339 TEST(DeclPrinter, TestCXXRecordDecl11) { 340 ASSERT_TRUE(PrintedDeclCXX98Matches( 341 "class Z { int a; };" 342 "class Y : virtual public Z { int b; };" 343 "class A : virtual public Z, private Y { int c; };", 344 "A", 345 "class A : virtual public Z, private Y {}")); 346 } 347 348 TEST(DeclPrinter, TestFunctionDecl1) { 349 ASSERT_TRUE(PrintedDeclCXX98Matches( 350 "void A();", 351 "A", 352 "void A()")); 353 } 354 355 TEST(DeclPrinter, TestFreeFunctionDecl_FullyQualifiedName) { 356 ASSERT_TRUE(PrintedDeclCXX98Matches( 357 "void A();", 358 "A", 359 "void A()", 360 [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; })); 361 } 362 363 TEST(DeclPrinter, TestFreeFunctionDeclInNamespace_FullyQualifiedName) { 364 ASSERT_TRUE(PrintedDeclCXX98Matches( 365 "namespace X { void A(); };", 366 "A", 367 "void X::A()", 368 [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; })); 369 } 370 371 TEST(DeclPrinter, TestMemberFunction_FullyQualifiedName) { 372 ASSERT_TRUE(PrintedDeclCXX98Matches( 373 "struct X { void A(); };", 374 "A", 375 "void X::A()", 376 [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; })); 377 } 378 379 TEST(DeclPrinter, TestMemberFunctionInNamespace_FullyQualifiedName) { 380 ASSERT_TRUE(PrintedDeclCXX98Matches( 381 "namespace Z { struct X { void A(); }; }", 382 "A", 383 "void Z::X::A()", 384 [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; })); 385 } 386 387 TEST(DeclPrinter, TestMemberFunctionOutside_FullyQualifiedName) { 388 ASSERT_TRUE(PrintedDeclCXX98Matches( 389 "struct X { void A(); };" 390 "void X::A() {}", 391 functionDecl(hasName("A"), isDefinition()).bind("id"), 392 "void X::A()", 393 [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; })); 394 } 395 396 TEST(DeclPrinter, TestFunctionDecl2) { 397 ASSERT_TRUE(PrintedDeclCXX98Matches( 398 "void A() {}", 399 "A", 400 "void A()")); 401 } 402 403 TEST(DeclPrinter, TestFunctionDecl3) { 404 ASSERT_TRUE(PrintedDeclCXX98Matches( 405 "void Z();" 406 "void A() { Z(); }", 407 "A", 408 "void A()")); 409 } 410 411 TEST(DeclPrinter, TestFunctionDecl4) { 412 ASSERT_TRUE(PrintedDeclCXX98Matches( 413 "extern void A();", 414 "A", 415 "extern void A()")); 416 } 417 418 TEST(DeclPrinter, TestFunctionDecl5) { 419 ASSERT_TRUE(PrintedDeclCXX98Matches( 420 "static void A();", 421 "A", 422 "static void A()")); 423 } 424 425 TEST(DeclPrinter, TestFunctionDecl6) { 426 ASSERT_TRUE(PrintedDeclCXX98Matches( 427 "inline void A();", 428 "A", 429 "inline void A()")); 430 } 431 432 TEST(DeclPrinter, TestFunctionDecl7) { 433 ASSERT_TRUE(PrintedDeclCXX11Matches( 434 "constexpr int A(int a);", 435 "A", 436 "constexpr int A(int a)")); 437 } 438 439 TEST(DeclPrinter, TestFunctionDecl8) { 440 ASSERT_TRUE(PrintedDeclCXX98Matches( 441 "void A(int a);", 442 "A", 443 "void A(int a)")); 444 } 445 446 TEST(DeclPrinter, TestFunctionDecl9) { 447 ASSERT_TRUE(PrintedDeclCXX98Matches( 448 "void A(...);", 449 "A", 450 "void A(...)")); 451 } 452 453 TEST(DeclPrinter, TestFunctionDecl10) { 454 ASSERT_TRUE(PrintedDeclCXX98Matches( 455 "void A(int a, ...);", 456 "A", 457 "void A(int a, ...)")); 458 } 459 460 TEST(DeclPrinter, TestFunctionDecl11) { 461 ASSERT_TRUE(PrintedDeclCXX98Matches( 462 "typedef long ssize_t;" 463 "typedef int *pInt;" 464 "void A(int a, pInt b, ssize_t c);", 465 "A", 466 "void A(int a, pInt b, ssize_t c)")); 467 } 468 469 TEST(DeclPrinter, TestFunctionDecl12) { 470 ASSERT_TRUE(PrintedDeclCXX98Matches( 471 "void A(int a, int b = 0);", 472 "A", 473 "void A(int a, int b = 0)")); 474 } 475 476 TEST(DeclPrinter, TestFunctionDecl13) { 477 ASSERT_TRUE(PrintedDeclCXX98Matches( 478 "void (*A(int a))(int b);", 479 "A", 480 "void (*A(int a))(int)")); 481 // Should be: with parameter name (?) 482 } 483 484 TEST(DeclPrinter, TestFunctionDecl14) { 485 ASSERT_TRUE(PrintedDeclCXX98Matches( 486 "template<typename T>" 487 "void A(T t) { }" 488 "template<>" 489 "void A(int N) { }", 490 functionDecl(hasName("A"), isExplicitTemplateSpecialization()).bind("id"), 491 "template<> void A<int>(int N)")); 492 } 493 494 495 TEST(DeclPrinter, TestCXXConstructorDecl1) { 496 ASSERT_TRUE(PrintedDeclCXX98Matches( 497 "struct A {" 498 " A();" 499 "};", 500 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 501 "A()")); 502 } 503 504 TEST(DeclPrinter, TestCXXConstructorDecl2) { 505 ASSERT_TRUE(PrintedDeclCXX98Matches( 506 "struct A {" 507 " A(int a);" 508 "};", 509 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 510 "A(int a)")); 511 } 512 513 TEST(DeclPrinter, TestCXXConstructorDecl3) { 514 ASSERT_TRUE(PrintedDeclCXX98Matches( 515 "struct A {" 516 " A(const A &a);" 517 "};", 518 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 519 "A(const A &a)")); 520 } 521 522 TEST(DeclPrinter, TestCXXConstructorDecl4) { 523 ASSERT_TRUE(PrintedDeclCXX98Matches( 524 "struct A {" 525 " A(const A &a, int = 0);" 526 "};", 527 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 528 "A(const A &a, int = 0)")); 529 } 530 531 TEST(DeclPrinter, TestCXXConstructorDeclWithMemberInitializer) { 532 ASSERT_TRUE(PrintedDeclCXX98Matches( 533 "struct A {" 534 " int m;" 535 " A() : m(2) {}" 536 "};", 537 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 538 "A()")); 539 } 540 541 TEST(DeclPrinter, TestCXXConstructorDeclWithMemberInitializer_NoTerseOutput) { 542 ASSERT_TRUE(PrintedDeclCXX98Matches( 543 "struct A {" 544 " int m;" 545 " A() : m(2) {}" 546 "};", 547 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 548 "A() : m(2) {\n}\n", 549 [](PrintingPolicy &Policy){ Policy.TerseOutput = false; })); 550 } 551 552 TEST(DeclPrinter, TestCXXConstructorDecl5) { 553 ASSERT_TRUE(PrintedDeclCXX11Matches( 554 "struct A {" 555 " A(const A &&a);" 556 "};", 557 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 558 "A(const A &&a)")); 559 } 560 561 TEST(DeclPrinter, TestCXXConstructorDecl6) { 562 ASSERT_TRUE(PrintedDeclCXX98Matches( 563 "struct A {" 564 " explicit A(int a);" 565 "};", 566 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 567 "explicit A(int a)")); 568 } 569 570 TEST(DeclPrinter, TestCXXConstructorDecl7) { 571 ASSERT_TRUE(PrintedDeclCXX11Matches( 572 "struct A {" 573 " constexpr A();" 574 "};", 575 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 576 "constexpr A()")); 577 } 578 579 TEST(DeclPrinter, TestCXXConstructorDecl8) { 580 ASSERT_TRUE(PrintedDeclCXX11Matches( 581 "struct A {" 582 " A() = default;" 583 "};", 584 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 585 "A() = default")); 586 } 587 588 TEST(DeclPrinter, TestCXXConstructorDecl9) { 589 ASSERT_TRUE(PrintedDeclCXX11Matches( 590 "struct A {" 591 " A() = delete;" 592 "};", 593 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 594 "A() = delete")); 595 } 596 597 TEST(DeclPrinter, TestCXXConstructorDecl10) { 598 ASSERT_TRUE(PrintedDeclCXX11Matches( 599 "template<typename... T>" 600 "struct A {" 601 " A(const A &a);" 602 "};", 603 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 604 "A<T...>(const A<T...> &a)")); 605 } 606 607 TEST(DeclPrinter, TestCXXConstructorDecl11) { 608 ASSERT_TRUE(PrintedDeclCXX11nonMSCMatches( 609 "template<typename... T>" 610 "struct A : public T... {" 611 " A(T&&... ts) : T(ts)... {}" 612 "};", 613 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"), 614 "A<T...>(T &&...ts)")); 615 } 616 617 TEST(DeclPrinter, TestCXXDestructorDecl1) { 618 ASSERT_TRUE(PrintedDeclCXX98Matches( 619 "struct A {" 620 " ~A();" 621 "};", 622 cxxDestructorDecl(ofClass(hasName("A"))).bind("id"), 623 "~A()")); 624 } 625 626 TEST(DeclPrinter, TestCXXDestructorDecl2) { 627 ASSERT_TRUE(PrintedDeclCXX98Matches( 628 "struct A {" 629 " virtual ~A();" 630 "};", 631 cxxDestructorDecl(ofClass(hasName("A"))).bind("id"), 632 "virtual ~A()")); 633 } 634 635 TEST(DeclPrinter, TestCXXConversionDecl1) { 636 ASSERT_TRUE(PrintedDeclCXX98Matches( 637 "struct A {" 638 " operator int();" 639 "};", 640 cxxMethodDecl(ofClass(hasName("A"))).bind("id"), 641 "operator int()")); 642 } 643 644 TEST(DeclPrinter, TestCXXConversionDecl2) { 645 ASSERT_TRUE(PrintedDeclCXX98Matches( 646 "struct A {" 647 " operator bool();" 648 "};", 649 cxxMethodDecl(ofClass(hasName("A"))).bind("id"), 650 "operator bool()")); 651 } 652 653 TEST(DeclPrinter, TestCXXConversionDecl3) { 654 ASSERT_TRUE(PrintedDeclCXX98Matches( 655 "struct Z {};" 656 "struct A {" 657 " operator Z();" 658 "};", 659 cxxMethodDecl(ofClass(hasName("A"))).bind("id"), 660 "operator Z()")); 661 } 662 663 TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction1) { 664 ASSERT_TRUE(PrintedDeclCXX11Matches( 665 "namespace std { typedef decltype(sizeof(int)) size_t; }" 666 "struct Z {" 667 " void *operator new(std::size_t);" 668 "};", 669 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"), 670 "void *operator new(std::size_t)")); 671 } 672 673 TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction2) { 674 ASSERT_TRUE(PrintedDeclCXX11Matches( 675 "namespace std { typedef decltype(sizeof(int)) size_t; }" 676 "struct Z {" 677 " void *operator new[](std::size_t);" 678 "};", 679 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"), 680 "void *operator new[](std::size_t)")); 681 } 682 683 TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction3) { 684 ASSERT_TRUE(PrintedDeclCXX11Matches( 685 "struct Z {" 686 " void operator delete(void *);" 687 "};", 688 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"), 689 "void operator delete(void *) noexcept")); 690 // Should be: without noexcept? 691 } 692 693 TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction4) { 694 ASSERT_TRUE(PrintedDeclCXX98Matches( 695 "struct Z {" 696 " void operator delete(void *);" 697 "};", 698 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"), 699 "void operator delete(void *)")); 700 } 701 702 TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction5) { 703 ASSERT_TRUE(PrintedDeclCXX11Matches( 704 "struct Z {" 705 " void operator delete[](void *);" 706 "};", 707 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"), 708 "void operator delete[](void *) noexcept")); 709 // Should be: without noexcept? 710 } 711 712 TEST(DeclPrinter, TestCXXMethodDecl_Operator1) { 713 const char *OperatorNames[] = { 714 "+", "-", "*", "/", "%", "^", "&", "|", 715 "=", "<", ">", "+=", "-=", "*=", "/=", "%=", 716 "^=", "&=", "|=", "<<", ">>", ">>=", "<<=", "==", "!=", 717 "<=", ">=", "&&", "||", ",", "->*", 718 "()", "[]" 719 }; 720 721 for (unsigned i = 0, e = llvm::array_lengthof(OperatorNames); i != e; ++i) { 722 SmallString<128> Code; 723 Code.append("struct Z { void operator"); 724 Code.append(OperatorNames[i]); 725 Code.append("(Z z); };"); 726 727 SmallString<128> Expected; 728 Expected.append("void operator"); 729 Expected.append(OperatorNames[i]); 730 Expected.append("(Z z)"); 731 732 ASSERT_TRUE(PrintedDeclCXX98Matches( 733 Code, 734 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"), 735 Expected)); 736 } 737 } 738 739 TEST(DeclPrinter, TestCXXMethodDecl_Operator2) { 740 const char *OperatorNames[] = { 741 "~", "!", "++", "--", "->" 742 }; 743 744 for (unsigned i = 0, e = llvm::array_lengthof(OperatorNames); i != e; ++i) { 745 SmallString<128> Code; 746 Code.append("struct Z { void operator"); 747 Code.append(OperatorNames[i]); 748 Code.append("(); };"); 749 750 SmallString<128> Expected; 751 Expected.append("void operator"); 752 Expected.append(OperatorNames[i]); 753 Expected.append("()"); 754 755 ASSERT_TRUE(PrintedDeclCXX98Matches( 756 Code, 757 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"), 758 Expected)); 759 } 760 } 761 762 TEST(DeclPrinter, TestCXXMethodDecl1) { 763 ASSERT_TRUE(PrintedDeclCXX98Matches( 764 "struct Z {" 765 " void A(int a);" 766 "};", 767 "A", 768 "void A(int a)")); 769 } 770 771 TEST(DeclPrinter, TestCXXMethodDecl2) { 772 ASSERT_TRUE(PrintedDeclCXX98Matches( 773 "struct Z {" 774 " virtual void A(int a);" 775 "};", 776 "A", 777 "virtual void A(int a)")); 778 } 779 780 TEST(DeclPrinter, TestCXXMethodDecl3) { 781 ASSERT_TRUE(PrintedDeclCXX98Matches( 782 "struct Z {" 783 " virtual void A(int a);" 784 "};" 785 "struct ZZ : Z {" 786 " void A(int a);" 787 "};", 788 "ZZ::A", 789 "void A(int a)")); 790 // TODO: should we print "virtual"? 791 } 792 793 TEST(DeclPrinter, TestCXXMethodDecl4) { 794 ASSERT_TRUE(PrintedDeclCXX98Matches( 795 "struct Z {" 796 " inline void A(int a);" 797 "};", 798 "A", 799 "inline void A(int a)")); 800 } 801 802 TEST(DeclPrinter, TestCXXMethodDecl5) { 803 ASSERT_TRUE(PrintedDeclCXX98Matches( 804 "struct Z {" 805 " virtual void A(int a) = 0;" 806 "};", 807 "A", 808 "virtual void A(int a) = 0")); 809 } 810 811 TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier1) { 812 ASSERT_TRUE(PrintedDeclCXX98Matches( 813 "struct Z {" 814 " void A(int a) const;" 815 "};", 816 "A", 817 "void A(int a) const")); 818 } 819 820 TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier2) { 821 ASSERT_TRUE(PrintedDeclCXX98Matches( 822 "struct Z {" 823 " void A(int a) volatile;" 824 "};", 825 "A", 826 "void A(int a) volatile")); 827 } 828 829 TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier3) { 830 ASSERT_TRUE(PrintedDeclCXX98Matches( 831 "struct Z {" 832 " void A(int a) const volatile;" 833 "};", 834 "A", 835 "void A(int a) const volatile")); 836 } 837 838 TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier1) { 839 ASSERT_TRUE(PrintedDeclCXX11Matches( 840 "struct Z {" 841 " void A(int a) &;" 842 "};", 843 "A", 844 "void A(int a) &")); 845 } 846 847 TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier2) { 848 ASSERT_TRUE(PrintedDeclCXX11Matches( 849 "struct Z {" 850 " void A(int a) &&;" 851 "};", 852 "A", 853 "void A(int a) &&")); 854 } 855 856 TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification1) { 857 ASSERT_TRUE(PrintedDeclCXX98Matches( 858 "struct Z {" 859 " void A(int a) throw();" 860 "};", 861 "A", 862 "void A(int a) throw()")); 863 } 864 865 TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification2) { 866 ASSERT_TRUE(PrintedDeclCXX98Matches( 867 "struct Z {" 868 " void A(int a) throw(int);" 869 "};", 870 "A", 871 "void A(int a) throw(int)")); 872 } 873 874 TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification3) { 875 ASSERT_TRUE(PrintedDeclCXX98Matches( 876 "class ZZ {};" 877 "struct Z {" 878 " void A(int a) throw(ZZ, int);" 879 "};", 880 "A", 881 "void A(int a) throw(ZZ, int)")); 882 } 883 884 TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification4) { 885 ASSERT_TRUE(PrintedDeclCXX11Matches( 886 "struct Z {" 887 " void A(int a) noexcept;" 888 "};", 889 "A", 890 "void A(int a) noexcept")); 891 } 892 893 TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification5) { 894 ASSERT_TRUE(PrintedDeclCXX11Matches( 895 "struct Z {" 896 " void A(int a) noexcept(true);" 897 "};", 898 "A", 899 "void A(int a) noexcept(trueA(int a) noexcept(true)")); 900 // WRONG; Should be: "void A(int a) noexcept(true);" 901 } 902 903 TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification6) { 904 ASSERT_TRUE(PrintedDeclCXX11Matches( 905 "struct Z {" 906 " void A(int a) noexcept(1 < 2);" 907 "};", 908 "A", 909 "void A(int a) noexcept(1 < 2A(int a) noexcept(1 < 2)")); 910 // WRONG; Should be: "void A(int a) noexcept(1 < 2);" 911 } 912 913 TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification7) { 914 ASSERT_TRUE(PrintedDeclCXX11Matches( 915 "template<int N>" 916 "struct Z {" 917 " void A(int a) noexcept(N < 2);" 918 "};", 919 "A", 920 "void A(int a) noexcept(N < 2A(int a) noexcept(N < 2)")); 921 // WRONG; Should be: "void A(int a) noexcept(N < 2);" 922 } 923 924 TEST(DeclPrinter, TestVarDecl1) { 925 ASSERT_TRUE(PrintedDeclCXX98Matches( 926 "char *const (*(*A)[5])(int);", 927 "A", 928 "char *const (*(*A)[5])(int)")); 929 // Should be: with semicolon 930 } 931 932 TEST(DeclPrinter, TestVarDecl2) { 933 ASSERT_TRUE(PrintedDeclCXX98Matches( 934 "void (*A)() throw(int);", 935 "A", 936 "void (*A)() throw(int)")); 937 // Should be: with semicolon 938 } 939 940 TEST(DeclPrinter, TestVarDecl3) { 941 ASSERT_TRUE(PrintedDeclCXX11Matches( 942 "void (*A)() noexcept;", 943 "A", 944 "void (*A)() noexcept")); 945 // Should be: with semicolon 946 } 947 948 TEST(DeclPrinter, TestFieldDecl1) { 949 ASSERT_TRUE(PrintedDeclCXX98Matches( 950 "template<typename T>" 951 "struct Z { T A; };", 952 "A", 953 "T A")); 954 // Should be: with semicolon 955 } 956 957 TEST(DeclPrinter, TestFieldDecl2) { 958 ASSERT_TRUE(PrintedDeclCXX98Matches( 959 "template<int N>" 960 "struct Z { int A[N]; };", 961 "A", 962 "int A[N]")); 963 // Should be: with semicolon 964 } 965 966 TEST(DeclPrinter, TestClassTemplateDecl1) { 967 ASSERT_TRUE(PrintedDeclCXX98Matches( 968 "template<typename T>" 969 "struct A { T a; };", 970 classTemplateDecl(hasName("A")).bind("id"), 971 "template <typename T> struct A {}")); 972 } 973 974 TEST(DeclPrinter, TestClassTemplateDecl2) { 975 ASSERT_TRUE(PrintedDeclCXX98Matches( 976 "template<typename T = int>" 977 "struct A { T a; };", 978 classTemplateDecl(hasName("A")).bind("id"), 979 "template <typename T = int> struct A {}")); 980 } 981 982 TEST(DeclPrinter, TestClassTemplateDecl3) { 983 ASSERT_TRUE(PrintedDeclCXX98Matches( 984 "template<class T>" 985 "struct A { T a; };", 986 classTemplateDecl(hasName("A")).bind("id"), 987 "template <class T> struct A {}")); 988 } 989 990 TEST(DeclPrinter, TestClassTemplateDecl4) { 991 ASSERT_TRUE(PrintedDeclCXX98Matches( 992 "template<typename T, typename U>" 993 "struct A { T a; U b; };", 994 classTemplateDecl(hasName("A")).bind("id"), 995 "template <typename T, typename U> struct A {}")); 996 } 997 998 TEST(DeclPrinter, TestClassTemplateDecl5) { 999 ASSERT_TRUE(PrintedDeclCXX98Matches( 1000 "template<int N>" 1001 "struct A { int a[N]; };", 1002 classTemplateDecl(hasName("A")).bind("id"), 1003 "template <int N> struct A {}")); 1004 } 1005 1006 TEST(DeclPrinter, TestClassTemplateDecl6) { 1007 ASSERT_TRUE(PrintedDeclCXX98Matches( 1008 "template<int N = 42>" 1009 "struct A { int a[N]; };", 1010 classTemplateDecl(hasName("A")).bind("id"), 1011 "template <int N = 42> struct A {}")); 1012 } 1013 1014 TEST(DeclPrinter, TestClassTemplateDecl7) { 1015 ASSERT_TRUE(PrintedDeclCXX98Matches( 1016 "typedef int MyInt;" 1017 "template<MyInt N>" 1018 "struct A { int a[N]; };", 1019 classTemplateDecl(hasName("A")).bind("id"), 1020 "template <MyInt N> struct A {}")); 1021 } 1022 1023 TEST(DeclPrinter, TestClassTemplateDecl8) { 1024 ASSERT_TRUE(PrintedDeclCXX98Matches( 1025 "template<template<typename U> class T> struct A { };", 1026 classTemplateDecl(hasName("A")).bind("id"), 1027 "template <template <typename U> class T> struct A {}")); 1028 } 1029 1030 TEST(DeclPrinter, TestClassTemplateDecl9) { 1031 ASSERT_TRUE(PrintedDeclCXX98Matches( 1032 "template<typename T> struct Z { };" 1033 "template<template<typename U> class T = Z> struct A { };", 1034 classTemplateDecl(hasName("A")).bind("id"), 1035 "template <template <typename U> class T> struct A {}")); 1036 } 1037 1038 TEST(DeclPrinter, TestClassTemplateDecl10) { 1039 ASSERT_TRUE(PrintedDeclCXX11Matches( 1040 "template<typename... T>" 1041 "struct A { int a; };", 1042 classTemplateDecl(hasName("A")).bind("id"), 1043 "template <typename ...T> struct A {}")); 1044 } 1045 1046 TEST(DeclPrinter, TestClassTemplateDecl11) { 1047 ASSERT_TRUE(PrintedDeclCXX11Matches( 1048 "template<typename... T>" 1049 "struct A : public T... { int a; };", 1050 classTemplateDecl(hasName("A")).bind("id"), 1051 "template <typename ...T> struct A : public T... {}")); 1052 } 1053 1054 TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl1) { 1055 ASSERT_TRUE(PrintedDeclCXX98Matches( 1056 "template<typename T, typename U>" 1057 "struct A { T a; U b; };" 1058 "template<typename T>" 1059 "struct A<T, int> { T a; };", 1060 classTemplateSpecializationDecl().bind("id"), 1061 "template <typename T> struct A<T, int> {}")); 1062 } 1063 1064 TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl2) { 1065 ASSERT_TRUE(PrintedDeclCXX98Matches( 1066 "template<typename T>" 1067 "struct A { T a; };" 1068 "template<typename T>" 1069 "struct A<T *> { T a; };", 1070 classTemplateSpecializationDecl().bind("id"), 1071 "template <typename T> struct A<type-parameter-0-0 *> {}")); 1072 // WRONG; Should be: "template<typename T> struct A<T *> { ... }" 1073 } 1074 1075 TEST(DeclPrinter, TestClassTemplateSpecializationDecl1) { 1076 ASSERT_TRUE(PrintedDeclCXX98Matches( 1077 "template<typename T>" 1078 "struct A { T a; };" 1079 "template<>" 1080 "struct A<int> { int a; };", 1081 classTemplateSpecializationDecl().bind("id"), 1082 "template<> struct A<int> {}")); 1083 } 1084 1085 TEST(DeclPrinter, TestFunctionTemplateDecl1) { 1086 ASSERT_TRUE(PrintedDeclCXX98Matches( 1087 "template<typename T>" 1088 "void A(T &t);", 1089 functionTemplateDecl(hasName("A")).bind("id"), 1090 "template <typename T> void A(T &t)")); 1091 } 1092 1093 TEST(DeclPrinter, TestFunctionTemplateDecl2) { 1094 ASSERT_TRUE(PrintedDeclCXX98Matches( 1095 "template<typename T>" 1096 "void A(T &t) { }", 1097 functionTemplateDecl(hasName("A")).bind("id"), 1098 "template <typename T> void A(T &t)")); 1099 } 1100 1101 TEST(DeclPrinter, TestFunctionTemplateDecl3) { 1102 ASSERT_TRUE(PrintedDeclCXX11Matches( 1103 "template<typename... T>" 1104 "void A(T... a);", 1105 functionTemplateDecl(hasName("A")).bind("id"), 1106 "template <typename ...T> void A(T ...a)")); 1107 } 1108 1109 TEST(DeclPrinter, TestFunctionTemplateDecl4) { 1110 ASSERT_TRUE(PrintedDeclCXX98Matches( 1111 "struct Z { template<typename T> void A(T t); };", 1112 functionTemplateDecl(hasName("A")).bind("id"), 1113 "template <typename T> void A(T t)")); 1114 } 1115 1116 TEST(DeclPrinter, TestFunctionTemplateDecl5) { 1117 ASSERT_TRUE(PrintedDeclCXX98Matches( 1118 "struct Z { template<typename T> void A(T t) {} };", 1119 functionTemplateDecl(hasName("A")).bind("id"), 1120 "template <typename T> void A(T t)")); 1121 } 1122 1123 TEST(DeclPrinter, TestFunctionTemplateDecl6) { 1124 ASSERT_TRUE(PrintedDeclCXX98Matches( 1125 "template<typename T >struct Z {" 1126 " template<typename U> void A(U t) {}" 1127 "};", 1128 functionTemplateDecl(hasName("A")).bind("id"), 1129 "template <typename U> void A(U t)")); 1130 } 1131 1132 TEST(DeclPrinter, TestTemplateArgumentList1) { 1133 ASSERT_TRUE(PrintedDeclCXX98Matches( 1134 "template<typename T> struct Z {};" 1135 "struct X {};" 1136 "Z<X> A;", 1137 "A", 1138 "Z<X> A")); 1139 // Should be: with semicolon 1140 } 1141 1142 TEST(DeclPrinter, TestTemplateArgumentList2) { 1143 ASSERT_TRUE(PrintedDeclCXX98Matches( 1144 "template<typename T, typename U> struct Z {};" 1145 "struct X {};" 1146 "typedef int Y;" 1147 "Z<X, Y> A;", 1148 "A", 1149 "Z<X, Y> A")); 1150 // Should be: with semicolon 1151 } 1152 1153 TEST(DeclPrinter, TestTemplateArgumentList3) { 1154 ASSERT_TRUE(PrintedDeclCXX98Matches( 1155 "template<typename T> struct Z {};" 1156 "template<typename T> struct X {};" 1157 "Z<X<int> > A;", 1158 "A", 1159 "Z<X<int> > A")); 1160 // Should be: with semicolon 1161 } 1162 1163 TEST(DeclPrinter, TestTemplateArgumentList4) { 1164 ASSERT_TRUE(PrintedDeclCXX11Matches( 1165 "template<typename T> struct Z {};" 1166 "template<typename T> struct X {};" 1167 "Z<X<int>> A;", 1168 "A", 1169 "Z<X<int> > A")); 1170 // Should be: with semicolon, without extra space in "> >" 1171 } 1172 1173 TEST(DeclPrinter, TestTemplateArgumentList5) { 1174 ASSERT_TRUE(PrintedDeclCXX98Matches( 1175 "template<typename T> struct Z {};" 1176 "template<typename T> struct X { Z<T> A; };", 1177 "A", 1178 "Z<T> A")); 1179 // Should be: with semicolon 1180 } 1181 1182 TEST(DeclPrinter, TestTemplateArgumentList6) { 1183 ASSERT_TRUE(PrintedDeclCXX98Matches( 1184 "template<template<typename T> class U> struct Z {};" 1185 "template<typename T> struct X {};" 1186 "Z<X> A;", 1187 "A", 1188 "Z<X> A")); 1189 // Should be: with semicolon 1190 } 1191 1192 TEST(DeclPrinter, TestTemplateArgumentList7) { 1193 ASSERT_TRUE(PrintedDeclCXX98Matches( 1194 "template<template<typename T> class U> struct Z {};" 1195 "template<template<typename T> class U> struct Y {" 1196 " Z<U> A;" 1197 "};", 1198 "A", 1199 "Z<U> A")); 1200 // Should be: with semicolon 1201 } 1202 1203 TEST(DeclPrinter, TestTemplateArgumentList8) { 1204 ASSERT_TRUE(PrintedDeclCXX98Matches( 1205 "template<typename T> struct Z {};" 1206 "template<template<typename T> class U> struct Y {" 1207 " Z<U<int> > A;" 1208 "};", 1209 "A", 1210 "Z<U<int> > A")); 1211 // Should be: with semicolon 1212 } 1213 1214 TEST(DeclPrinter, TestTemplateArgumentList9) { 1215 ASSERT_TRUE(PrintedDeclCXX98Matches( 1216 "template<unsigned I> struct Z {};" 1217 "Z<0> A;", 1218 "A", 1219 "Z<0> A")); 1220 // Should be: with semicolon 1221 } 1222 1223 TEST(DeclPrinter, TestTemplateArgumentList10) { 1224 ASSERT_TRUE(PrintedDeclCXX98Matches( 1225 "template<unsigned I> struct Z {};" 1226 "template<unsigned I> struct X { Z<I> A; };", 1227 "A", 1228 "Z<I> A")); 1229 // Should be: with semicolon 1230 } 1231 1232 TEST(DeclPrinter, TestTemplateArgumentList11) { 1233 ASSERT_TRUE(PrintedDeclCXX98Matches( 1234 "template<int I> struct Z {};" 1235 "Z<42 * 10 - 420 / 1> A;", 1236 "A", 1237 "Z<42 * 10 - 420 / 1> A")); 1238 // Should be: with semicolon 1239 } 1240 1241 TEST(DeclPrinter, TestTemplateArgumentList12) { 1242 ASSERT_TRUE(PrintedDeclCXX98Matches( 1243 "template<const char *p> struct Z {};" 1244 "extern const char X[] = \"aaa\";" 1245 "Z<X> A;", 1246 "A", 1247 "Z<X> A")); 1248 // Should be: with semicolon 1249 } 1250 1251 TEST(DeclPrinter, TestTemplateArgumentList13) { 1252 ASSERT_TRUE(PrintedDeclCXX11Matches( 1253 "template<typename... T> struct Z {};" 1254 "template<typename... T> struct X {" 1255 " Z<T...> A;" 1256 "};", 1257 "A", 1258 "Z<T...> A")); 1259 // Should be: with semicolon 1260 } 1261 1262 TEST(DeclPrinter, TestTemplateArgumentList14) { 1263 ASSERT_TRUE(PrintedDeclCXX11Matches( 1264 "template<typename... T> struct Z {};" 1265 "template<typename T> struct Y {};" 1266 "template<typename... T> struct X {" 1267 " Z<Y<T>...> A;" 1268 "};", 1269 "A", 1270 "Z<Y<T>...> A")); 1271 // Should be: with semicolon 1272 } 1273 1274 TEST(DeclPrinter, TestTemplateArgumentList15) { 1275 ASSERT_TRUE(PrintedDeclCXX11Matches( 1276 "template<unsigned I> struct Z {};" 1277 "template<typename... T> struct X {" 1278 " Z<sizeof...(T)> A;" 1279 "};", 1280 "A", 1281 "Z<sizeof...(T)> A")); 1282 // Should be: with semicolon 1283 } 1284 1285 TEST(DeclPrinter, TestStaticAssert1) { 1286 ASSERT_TRUE(PrintedDeclCXX1ZMatches( 1287 "static_assert(true);", 1288 staticAssertDecl().bind("id"), 1289 "static_assert(true)")); 1290 } 1291 1292 TEST(DeclPrinter, TestObjCMethod1) { 1293 ASSERT_TRUE(PrintedDeclObjCMatches( 1294 "__attribute__((objc_root_class)) @interface X\n" 1295 "- (int)A:(id)anObject inRange:(long)range;\n" 1296 "@end\n" 1297 "@implementation X\n" 1298 "- (int)A:(id)anObject inRange:(long)range { int printThis; return 0; }\n" 1299 "@end\n", 1300 namedDecl(hasName("A:inRange:"), 1301 hasDescendant(namedDecl(hasName("printThis")))).bind("id"), 1302 "- (int)A:(id)anObject inRange:(long)range")); 1303 } 1304 1305 TEST(DeclPrinter, TestObjCProtocol1) { 1306 ASSERT_TRUE(PrintedDeclObjCMatches( 1307 "@protocol P1, P2;", 1308 namedDecl(hasName("P1")).bind("id"), 1309 "@protocol P1;\n")); 1310 ASSERT_TRUE(PrintedDeclObjCMatches( 1311 "@protocol P1, P2;", 1312 namedDecl(hasName("P2")).bind("id"), 1313 "@protocol P2;\n")); 1314 } 1315 1316 TEST(DeclPrinter, TestObjCProtocol2) { 1317 ASSERT_TRUE(PrintedDeclObjCMatches( 1318 "@protocol P2 @end" 1319 "@protocol P1<P2> @end", 1320 namedDecl(hasName("P1")).bind("id"), 1321 "@protocol P1<P2>\n@end")); 1322 } 1323