[RISCV] Add missing SiFive P400 scheduling model test for divisions. NFC
[llvm-project.git] / clang / unittests / AST / TypePrinterTest.cpp
blob494085a2ebca6b88d5a743e2dbc9c6d3eafef2ee
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.
11 //===----------------------------------------------------------------------===//
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"
20 using namespace clang;
21 using namespace ast_matchers;
22 using namespace tooling;
24 namespace {
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);
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);
45 } // unnamed namespace
47 TEST(TypePrinter, TemplateId) {
48 std::string Code = R"cpp(
49 namespace N {
50 template <typename> struct Type {};
52 template <typename T>
53 void Foo(const Type<T> &Param);
55 )cpp";
56 auto Matcher = parmVarDecl(hasType(qualType().bind("id")));
58 ASSERT_TRUE(PrintedTypeMatches(
59 Code, {}, Matcher, "const Type<T> &",
60 [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = false; }));
62 ASSERT_TRUE(PrintedTypeMatches(
63 Code, {}, Matcher, "const Type<T> &",
64 [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = true; }));
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")));
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 }));
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;
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));
100 TEST(TypePrinter, SuppressElaboration) {
101 llvm::StringLiteral Code = R"cpp(
102 namespace shared {
103 namespace a {
104 template <typename T>
105 struct S {};
106 } // namespace a
107 namespace b {
108 struct Foo {};
109 } // namespace b
110 using Alias = a::S<b::Foo>;
111 } // namespace shared
112 )cpp";
114 auto Matcher = typedefNameDecl(hasName("::shared::Alias"),
115 hasType(qualType().bind("id")));
116 ASSERT_TRUE(PrintedTypeMatches(
117 Code, {}, Matcher, "a::S<b::Foo>",
118 [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = true; }));
119 ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher,
120 "shared::a::S<shared::b::Foo>",
121 [](PrintingPolicy &Policy) {
122 Policy.SuppressElaboration = true;
123 Policy.FullyQualifiedName = true;
124 }));
127 TEST(TypePrinter, TemplateIdWithNTTP) {
128 constexpr char Code[] = R"cpp(
129 template <int N>
130 struct Str {
131 constexpr Str(char const (&s)[N]) { __builtin_memcpy(value, s, N); }
132 char value[N];
134 template <Str> class ASCII {};
136 ASCII<"this nontype template argument is too long to print"> x;
137 )cpp";
138 auto Matcher = classTemplateSpecializationDecl(
139 hasName("ASCII"), has(cxxConstructorDecl(
140 isMoveConstructor(),
141 has(parmVarDecl(hasType(qualType().bind("id")))))));
143 ASSERT_TRUE(PrintedTypeMatches(
144 Code, {"-std=c++20"}, Matcher,
145 R"(ASCII<Str<52>{"this nontype template argument is [...]"}> &&)",
146 [](PrintingPolicy &Policy) {
147 Policy.EntireContentsOfLargeArray = false;
148 }));
150 ASSERT_TRUE(PrintedTypeMatches(
151 Code, {"-std=c++20"}, Matcher,
152 R"(ASCII<Str<52>{"this nontype template argument is too long to print"}> &&)",
153 [](PrintingPolicy &Policy) {
154 Policy.EntireContentsOfLargeArray = true;
155 }));
158 TEST(TypePrinter, TemplateArgumentsSubstitution) {
159 constexpr char Code[] = R"cpp(
160 template <typename Y> class X {};
161 typedef X<int> A;
162 int foo() {
163 return sizeof(A);
165 )cpp";
166 auto Matcher = typedefNameDecl(hasName("A"), hasType(qualType().bind("id")));
167 ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher, "X<int>",
168 [](PrintingPolicy &Policy) {
169 Policy.SuppressTagKeyword = false;
170 Policy.SuppressScope = true;
171 }));
174 TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
175 /// Tests clang::isSubstitutedDefaultArgument on TemplateArguments
176 /// that are of kind TemplateArgument::Expression
177 constexpr char Code[] = R"cpp(
178 constexpr bool func() { return true; }
180 template <typename T1 = int,
181 int T2 = 42,
182 T1 T3 = 43,
183 int T4 = sizeof(T1),
184 bool T5 = func()
186 struct Foo {
189 Foo<int, 40 + 2> X;
190 )cpp";
192 auto AST = tooling::buildASTFromCodeWithArgs(Code, /*Args=*/{"-std=c++20"});
193 ASTContext &Ctx = AST->getASTContext();
195 auto const *CTD = selectFirst<ClassTemplateDecl>(
196 "id", match(classTemplateDecl(hasName("Foo")).bind("id"), Ctx));
197 ASSERT_NE(CTD, nullptr);
198 auto const *CTSD = *CTD->specializations().begin();
199 ASSERT_NE(CTSD, nullptr);
200 auto const *Params = CTD->getTemplateParameters();
201 ASSERT_NE(Params, nullptr);
202 auto const &ArgList = CTSD->getTemplateArgs();
204 auto createBinOpExpr = [&](uint32_t LHS, uint32_t RHS,
205 uint32_t Result) -> ConstantExpr * {
206 const int numBits = 32;
207 clang::APValue ResultVal{llvm::APSInt(llvm::APInt(numBits, Result))};
208 auto *LHSInt = IntegerLiteral::Create(Ctx, llvm::APInt(numBits, LHS),
209 Ctx.UnsignedIntTy, {});
210 auto *RHSInt = IntegerLiteral::Create(Ctx, llvm::APInt(numBits, RHS),
211 Ctx.UnsignedIntTy, {});
212 auto *BinOp = BinaryOperator::Create(
213 Ctx, LHSInt, RHSInt, BinaryOperatorKind::BO_Add, Ctx.UnsignedIntTy,
214 ExprValueKind::VK_PRValue, ExprObjectKind::OK_Ordinary, {}, {});
215 return ConstantExpr::Create(Ctx, dyn_cast<Expr>(BinOp), ResultVal);
219 // Arg is an integral '42'
220 auto const &Arg = ArgList.get(1);
221 ASSERT_EQ(Arg.getKind(), TemplateArgument::Integral);
223 // Param has default expr which evaluates to '42'
224 auto const *Param = Params->getParam(1);
226 EXPECT_TRUE(clang::isSubstitutedDefaultArgument(
227 Ctx, Arg, Param, ArgList.asArray(), Params->getDepth()));
231 // Arg is an integral '41'
232 llvm::APInt Int(32, 41);
233 TemplateArgument Arg(Ctx, llvm::APSInt(Int), Ctx.UnsignedIntTy);
235 // Param has default expr which evaluates to '42'
236 auto const *Param = Params->getParam(1);
238 EXPECT_FALSE(clang::isSubstitutedDefaultArgument(
239 Ctx, Arg, Param, ArgList.asArray(), Params->getDepth()));
243 // Arg is an integral '4'
244 llvm::APInt Int(32, 4);
245 TemplateArgument Arg(Ctx, llvm::APSInt(Int), Ctx.UnsignedIntTy);
247 // Param has is value-dependent expression (i.e., sizeof(T))
248 auto const *Param = Params->getParam(3);
250 EXPECT_FALSE(clang::isSubstitutedDefaultArgument(
251 Ctx, Arg, Param, ArgList.asArray(), Params->getDepth()));
255 const int LHS = 40;
256 const int RHS = 2;
257 const int Result = 42;
258 auto *ConstExpr = createBinOpExpr(LHS, RHS, Result);
259 // Arg is instantiated with '40 + 2'
260 TemplateArgument Arg(ConstExpr);
262 // Param has default expr of '42'
263 auto const *Param = Params->getParam(1);
265 EXPECT_TRUE(clang::isSubstitutedDefaultArgument(
266 Ctx, Arg, Param, ArgList.asArray(), Params->getDepth()));
270 const int LHS = 40;
271 const int RHS = 1;
272 const int Result = 41;
273 auto *ConstExpr = createBinOpExpr(LHS, RHS, Result);
275 // Arg is instantiated with '40 + 1'
276 TemplateArgument Arg(ConstExpr);
278 // Param has default expr of '42'
279 auto const *Param = Params->getParam(1);
281 EXPECT_FALSE(clang::isSubstitutedDefaultArgument(
282 Ctx, Arg, Param, ArgList.asArray(), Params->getDepth()));
286 const int LHS = 4;
287 const int RHS = 0;
288 const int Result = 4;
289 auto *ConstExpr = createBinOpExpr(LHS, RHS, Result);
291 // Arg is instantiated with '4 + 0'
292 TemplateArgument Arg(ConstExpr);
294 // Param has is value-dependent expression (i.e., sizeof(T))
295 auto const *Param = Params->getParam(3);
297 EXPECT_FALSE(clang::isSubstitutedDefaultArgument(
298 Ctx, Arg, Param, ArgList.asArray(), Params->getDepth()));