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