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