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