xref: /llvm-project/clang/unittests/AST/TypePrinterTest.cpp (revision 3968936b92bf4c800e4163b038ba970abce3d90f)
1 //===- unittests/AST/TypePrinterTest.cpp --- Type 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 QualType::print() and related methods.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "ASTPrint.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/ASTMatchers/ASTMatchFinder.h"
16 #include "clang/Tooling/Tooling.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "gtest/gtest.h"
19 
20 using namespace clang;
21 using namespace ast_matchers;
22 using namespace tooling;
23 
24 namespace {
25 
26 static void PrintType(raw_ostream &Out, const ASTContext *Context,
27                       const QualType *T,
28                       PrintingPolicyAdjuster PolicyAdjuster) {
29   assert(T && !T->isNull() && "Expected non-null Type");
30   PrintingPolicy Policy = Context->getPrintingPolicy();
31   if (PolicyAdjuster)
32     PolicyAdjuster(Policy);
33   T->print(Out, Policy);
34 }
35 
36 ::testing::AssertionResult
37 PrintedTypeMatches(StringRef Code, const std::vector<std::string> &Args,
38                    const DeclarationMatcher &NodeMatch,
39                    StringRef ExpectedPrinted,
40                    PrintingPolicyAdjuster PolicyAdjuster) {
41   return PrintedNodeMatches<QualType>(Code, Args, NodeMatch, ExpectedPrinted,
42                                       "", PrintType, PolicyAdjuster);
43 }
44 
45 } // unnamed namespace
46 
47 TEST(TypePrinter, TemplateId) {
48   std::string Code = R"cpp(
49     namespace N {
50       template <typename> struct Type {};
51 
52       template <typename T>
53       void Foo(const Type<T> &Param);
54     }
55   )cpp";
56   auto Matcher = parmVarDecl(hasType(qualType().bind("id")));
57 
58   ASSERT_TRUE(PrintedTypeMatches(
59       Code, {}, Matcher, "const Type<T> &",
60       [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = false; }));
61 
62   ASSERT_TRUE(PrintedTypeMatches(
63       Code, {}, Matcher, "const N::Type<T> &",
64       [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = true; }));
65 }
66 
67 TEST(TypePrinter, TemplateId2) {
68   std::string Code = R"cpp(
69       template <template <typename ...> class TemplatedType>
70       void func(TemplatedType<int> Param);
71     )cpp";
72   auto Matcher = parmVarDecl(hasType(qualType().bind("id")));
73 
74   // Regression test ensuring we do not segfault getting the QualType as a
75   // string.
76   ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher, "<int>",
77                                  [](PrintingPolicy &Policy) {
78                                    Policy.FullyQualifiedName = true;
79                                    Policy.PrintCanonicalTypes = true;
80                                  }));
81 }
82 
83 TEST(TypePrinter, ParamsUglified) {
84   llvm::StringLiteral Code = R"cpp(
85     template <typename _Tp, template <typename> class __f>
86     const __f<_Tp&> *A = nullptr;
87   )cpp";
88   auto Clean = [](PrintingPolicy &Policy) {
89     Policy.CleanUglifiedParameters = true;
90   };
91 
92   ASSERT_TRUE(PrintedTypeMatches(Code, {},
93                                  varDecl(hasType(qualType().bind("id"))),
94                                  "const __f<_Tp &> *", nullptr));
95   ASSERT_TRUE(PrintedTypeMatches(Code, {},
96                                  varDecl(hasType(qualType().bind("id"))),
97                                  "const f<Tp &> *", Clean));
98 }
99 
100 TEST(TypePrinter, TemplateIdWithNTTP) {
101   constexpr char Code[] = R"cpp(
102     template <int N>
103     struct Str {
104       constexpr Str(char const (&s)[N]) { __builtin_memcpy(value, s, N); }
105       char value[N];
106     };
107     template <Str> class ASCII {};
108 
109     ASCII<"this nontype template argument is too long to print"> x;
110   )cpp";
111   auto Matcher = classTemplateSpecializationDecl(
112       hasName("ASCII"), has(cxxConstructorDecl(
113                             isMoveConstructor(),
114                             has(parmVarDecl(hasType(qualType().bind("id")))))));
115 
116   ASSERT_TRUE(PrintedTypeMatches(
117       Code, {"-std=c++20"}, Matcher,
118       R"(ASCII<{"this nontype template argument is [...]"}> &&)",
119       [](PrintingPolicy &Policy) {
120         Policy.EntireContentsOfLargeArray = false;
121       }));
122 
123   ASSERT_TRUE(PrintedTypeMatches(
124       Code, {"-std=c++20"}, Matcher,
125       R"(ASCII<{"this nontype template argument is too long to print"}> &&)",
126       [](PrintingPolicy &Policy) {
127         Policy.EntireContentsOfLargeArray = true;
128       }));
129 }
130