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