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