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