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