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
30using namespace clang;
31using namespace ast_matchers;
32using namespace tooling;
33
34namespace {
35
36void 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
47PrintedDeclMatches(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, Printer: PrintDecl,
54 PolicyAdjuster: PolicyModifier, AllowError,
55 // Filter out implicit decls
56 Filter: [](const Decl *D) { return !D->isImplicit(); });
57}
58
59::testing::AssertionResult
60PrintedDeclCXX98Matches(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, NodeMatch: namedDecl(hasName(Name: DeclName)).bind(ID: "id"),
65 ExpectedPrinted, FileName: "input.cc", PolicyModifier);
66}
67
68::testing::AssertionResult
69PrintedDeclCXX98Matches(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 FileName: "input.cc",
78 PolicyModifier);
79}
80
81::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code,
82 StringRef DeclName,
83 StringRef ExpectedPrinted) {
84 std::vector<std::string> Args(1, "-std=c++11");
85 return PrintedDeclMatches(Code, Args, NodeMatch: namedDecl(hasName(Name: DeclName)).bind(ID: "id"),
86 ExpectedPrinted, FileName: "input.cc");
87}
88
89::testing::AssertionResult
90PrintedDeclCXX11Matches(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, FileName: "input.cc",
95 PolicyModifier);
96}
97
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 FileName: "input.cc");
108}
109
110::testing::AssertionResult
111PrintedDeclCXX17Matches(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, FileName: "input.cc",
116 PolicyModifier);
117}
118
119::testing::AssertionResult
120PrintedDeclC11Matches(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, FileName: "input.c",
125 PolicyModifier);
126}
127
128::testing::AssertionResult
129PrintedDeclObjCMatches(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, FileName: "input.m",
133 /*PolicyModifier=*/nullptr, AllowError);
134}
135
136} // unnamed namespace
137
138TEST(DeclPrinter, TestTypedef1) {
139 ASSERT_TRUE(PrintedDeclCXX98Matches(
140 "typedef int A;",
141 "A",
142 "typedef int A"));
143 // Should be: with semicolon
144}
145
146TEST(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
154TEST(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
163TEST(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
172TEST(DeclPrinter, TestNamespace1) {
173 ASSERT_TRUE(PrintedDeclCXX98Matches(
174 "namespace A { int B; }",
175 "A",
176 "namespace A {\n}"));
177 // Should be: with { ... }
178}
179
180TEST(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
188TEST(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
197TEST(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
206TEST(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
214TEST(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
222TEST(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
229TEST(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
236TEST(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
244TEST(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
251TEST(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
258TEST(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
265TEST(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
272TEST(DeclPrinter, TestCXXRecordDecl1) {
273 ASSERT_TRUE(PrintedDeclCXX98Matches(
274 "class A { int a; };",
275 "A",
276 "class A {}"));
277}
278
279TEST(DeclPrinter, TestCXXRecordDecl2) {
280 ASSERT_TRUE(PrintedDeclCXX98Matches(
281 "struct A { int a; };",
282 "A",
283 "struct A {}"));
284}
285
286TEST(DeclPrinter, TestCXXRecordDecl3) {
287 ASSERT_TRUE(PrintedDeclCXX98Matches(
288 "union A { int a; };",
289 "A",
290 "union A {}"));
291}
292
293TEST(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
301TEST(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
309TEST(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
317TEST(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
325TEST(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
333TEST(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
341TEST(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
349TEST(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
358TEST(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
373TEST(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
385TEST(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}
396TEST(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
411TEST(DeclPrinter, TestFunctionDecl1) {
412 ASSERT_TRUE(PrintedDeclCXX98Matches(
413 "void A();",
414 "A",
415 "void A()"));
416}
417
418TEST(DeclPrinter, TestFreeFunctionDecl_FullyQualifiedName) {
419 ASSERT_TRUE(PrintedDeclCXX98Matches(
420 "void A();",
421 "A",
422 "void A()",
423 [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
424}
425
426TEST(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
434TEST(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
442TEST(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
450TEST(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
459TEST(DeclPrinter, TestFunctionDecl2) {
460 ASSERT_TRUE(PrintedDeclCXX98Matches(
461 "void A() {}",
462 "A",
463 "void A()"));
464}
465
466TEST(DeclPrinter, TestFunctionDecl3) {
467 ASSERT_TRUE(PrintedDeclCXX98Matches(
468 "void Z();"
469 "void A() { Z(); }",
470 "A",
471 "void A()"));
472}
473
474TEST(DeclPrinter, TestFunctionDecl4) {
475 ASSERT_TRUE(PrintedDeclCXX98Matches(
476 "extern void A();",
477 "A",
478 "extern void A()"));
479}
480
481TEST(DeclPrinter, TestFunctionDecl5) {
482 ASSERT_TRUE(PrintedDeclCXX98Matches(
483 "static void A();",
484 "A",
485 "static void A()"));
486}
487
488TEST(DeclPrinter, TestFunctionDecl6) {
489 ASSERT_TRUE(PrintedDeclCXX98Matches(
490 "inline void A();",
491 "A",
492 "inline void A()"));
493}
494
495TEST(DeclPrinter, TestFunctionDecl7) {
496 ASSERT_TRUE(PrintedDeclCXX11Matches(
497 "constexpr int A(int a);",
498 "A",
499 "constexpr int A(int a)"));
500}
501
502TEST(DeclPrinter, TestFunctionDecl8) {
503 ASSERT_TRUE(PrintedDeclCXX98Matches(
504 "void A(int a);",
505 "A",
506 "void A(int a)"));
507}
508
509TEST(DeclPrinter, TestFunctionDecl9) {
510 ASSERT_TRUE(PrintedDeclCXX98Matches(
511 "void A(...);",
512 "A",
513 "void A(...)"));
514}
515
516TEST(DeclPrinter, TestFunctionDecl10) {
517 ASSERT_TRUE(PrintedDeclCXX98Matches(
518 "void A(int a, ...);",
519 "A",
520 "void A(int a, ...)"));
521}
522
523TEST(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
532TEST(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
539TEST(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
547TEST(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
558TEST(DeclPrinter, TestCXXConstructorDecl1) {
559 ASSERT_TRUE(PrintedDeclCXX98Matches(
560 "struct A {"
561 " A();"
562 "};",
563 cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
564 "A()"));
565}
566
567TEST(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
576TEST(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
585TEST(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
594TEST(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
604TEST(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
615TEST(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
624TEST(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
633TEST(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
642TEST(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
651TEST(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
660TEST(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
670TEST(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
680TEST(DeclPrinter, TestCXXDestructorDecl1) {
681 ASSERT_TRUE(PrintedDeclCXX98Matches(
682 "struct A {"
683 " ~A();"
684 "};",
685 cxxDestructorDecl(ofClass(hasName("A"))).bind("id"),
686 "~A()"));
687}
688
689TEST(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
698TEST(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
707TEST(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
716TEST(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
726TEST(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
736TEST(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
746TEST(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
756TEST(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
765TEST(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
775TEST(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(RHS: "struct Z { void operator");
787 Code.append(RHS: OperatorNames[i]);
788 Code.append(RHS: "(Z z); };");
789
790 SmallString<128> Expected;
791 Expected.append(RHS: "void operator");
792 Expected.append(RHS: OperatorNames[i]);
793 Expected.append(RHS: "(Z z)");
794
795 ASSERT_TRUE(PrintedDeclCXX98Matches(
796 Code,
797 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
798 Expected));
799 }
800}
801
802TEST(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(RHS: "struct Z { void operator");
810 Code.append(RHS: OperatorNames[i]);
811 Code.append(RHS: "(); };");
812
813 SmallString<128> Expected;
814 Expected.append(RHS: "void operator");
815 Expected.append(RHS: OperatorNames[i]);
816 Expected.append(RHS: "()");
817
818 ASSERT_TRUE(PrintedDeclCXX98Matches(
819 Code,
820 cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
821 Expected));
822 }
823}
824
825TEST(DeclPrinter, TestCXXMethodDecl1) {
826 ASSERT_TRUE(PrintedDeclCXX98Matches(
827 "struct Z {"
828 " void A(int a);"
829 "};",
830 "A",
831 "void A(int a)"));
832}
833
834TEST(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
843TEST(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
856TEST(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
865TEST(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
874TEST(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
883TEST(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
892TEST(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
901TEST(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
910TEST(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
919TEST(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
928TEST(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
937TEST(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
947TEST(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
956TEST(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
965TEST(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
974TEST(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
984TEST(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
992TEST(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
1000TEST(DeclPrinter, TestVarDecl3) {
1001 ASSERT_TRUE(PrintedDeclCXX11Matches(
1002 "void (*A)() noexcept;",
1003 "A",
1004 "void (*A)() noexcept"));
1005 // Should be: with semicolon
1006}
1007
1008TEST(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
1017TEST(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
1026TEST(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
1034TEST(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
1042TEST(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
1050TEST(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
1058TEST(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
1066TEST(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
1074TEST(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
1083TEST(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
1090TEST(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
1098TEST(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
1106TEST(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
1114TEST(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
1124TEST(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
1134TEST(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
1144TEST(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
1152TEST(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
1160TEST(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
1168TEST(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
1175TEST(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
1182TEST(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
1191TEST(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
1198TEST(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
1207TEST(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
1216TEST(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
1223TEST(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
1233TEST(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
1244TEST(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
1254TEST(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
1264TEST(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
1273TEST(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
1283TEST(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
1294TEST(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
1305TEST(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
1314TEST(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
1323TEST(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
1332TEST(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
1342TEST(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
1353TEST(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
1365TEST(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
1376TEST(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
1385TEST(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
1394TEST(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
1406TEST(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
1418TEST(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
1438TEST(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
1458TEST(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
1473TEST(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
1493TEST(DeclPrinter, TestStaticAssert1) {
1494 ASSERT_TRUE(PrintedDeclCXX17Matches("static_assert(true);",
1495 staticAssertDecl().bind("id"),
1496 "static_assert(true)"));
1497}
1498
1499TEST(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
1512TEST(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
1523TEST(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
1531TEST(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
1538TEST(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
1545TEST(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
1556TEST(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
1566TEST(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

source code of clang/unittests/AST/DeclPrinterTest.cpp