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, ParamsUglified) {
68   llvm::StringLiteral Code = R"cpp(
69     template <typename _Tp, template <typename> class __f>
70     const __f<_Tp&> *A = nullptr;
71   )cpp";
72   auto Clean = [](PrintingPolicy &Policy) {
73     Policy.CleanUglifiedParameters = true;
74   };
75 
76   ASSERT_TRUE(PrintedTypeMatches(Code, {},
77                                  varDecl(hasType(qualType().bind("id"))),
78                                  "const __f<_Tp &> *", nullptr));
79   ASSERT_TRUE(PrintedTypeMatches(Code, {},
80                                  varDecl(hasType(qualType().bind("id"))),
81                                  "const f<Tp &> *", Clean));
82 }
83 
84 TEST(TypePrinter, TemplateIdWithNTTP) {
85   constexpr char Code[] = R"cpp(
86     template <int N>
87     struct Str {
88       constexpr Str(char const (&s)[N]) { __builtin_memcpy(value, s, N); }
89       char value[N];
90     };
91     template <Str> class ASCII {};
92 
93     ASCII<"this nontype template argument is too long to print"> x;
94   )cpp";
95   auto Matcher = classTemplateSpecializationDecl(
96       hasName("ASCII"), has(cxxConstructorDecl(
97                             isMoveConstructor(),
98                             has(parmVarDecl(hasType(qualType().bind("id")))))));
99 
100   ASSERT_TRUE(PrintedTypeMatches(
101       Code, {"-std=c++20"}, Matcher,
102       R"(ASCII<{"this nontype template argument is [...]"}> &&)",
103       [](PrintingPolicy &Policy) {
104         Policy.EntireContentsOfLargeArray = false;
105       }));
106 
107   ASSERT_TRUE(PrintedTypeMatches(
108       Code, {"-std=c++20"}, Matcher,
109       R"(ASCII<{"this nontype template argument is too long to print"}> &&)",
110       [](PrintingPolicy &Policy) {
111         Policy.EntireContentsOfLargeArray = true;
112       }));
113 }
114