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