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