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