1 //===- unittests/AST/TemplateNameTest.cpp --- Tests for TemplateName ------===// 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 #include "ASTPrint.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchers.h" 12 #include "llvm/Support/raw_ostream.h" 13 #include "gtest/gtest.h" 14 15 namespace clang { 16 namespace { 17 using namespace ast_matchers; 18 19 std::string printTemplateName(TemplateName TN, const PrintingPolicy &Policy, 20 TemplateName::Qualified Qual) { 21 std::string Result; 22 llvm::raw_string_ostream Out(Result); 23 TN.print(Out, Policy, Qual); 24 return Out.str(); 25 } 26 27 TEST(TemplateName, PrintUsingTemplate) { 28 std::string Code = R"cpp( 29 namespace std { 30 template <typename> struct vector {}; 31 } 32 namespace absl { using std::vector; } 33 34 template<template <typename> class T> class X; 35 36 using absl::vector; 37 using A = X<vector>; 38 )cpp"; 39 auto AST = tooling::buildASTFromCode(Code); 40 ASTContext &Ctx = AST->getASTContext(); 41 // Match the template argument vector in X<vector>. 42 auto MatchResults = match(templateArgumentLoc().bind("id"), Ctx); 43 const auto *Template = selectFirst<TemplateArgumentLoc>("id", MatchResults); 44 ASSERT_TRUE(Template); 45 46 TemplateName TN = Template->getArgument().getAsTemplate(); 47 EXPECT_EQ(TN.getKind(), TemplateName::UsingTemplate); 48 EXPECT_EQ(TN.getAsUsingShadowDecl()->getTargetDecl(), TN.getAsTemplateDecl()); 49 50 EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(), 51 TemplateName::Qualified::Fully), 52 "std::vector"); 53 EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(), 54 TemplateName::Qualified::AsWritten), 55 "vector"); 56 EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(), 57 TemplateName::Qualified::None), 58 "vector"); 59 } 60 61 TEST(TemplateName, QualifiedUsingTemplate) { 62 std::string Code = R"cpp( 63 namespace std { 64 template <typename> struct vector {}; 65 } 66 namespace absl { using std::vector; } 67 68 template<template <typename> class T> class X; 69 70 using A = X<absl::vector>; // QualifiedTemplateName in a template argument. 71 )cpp"; 72 auto AST = tooling::buildASTFromCode(Code); 73 // Match the template argument absl::vector in X<absl::vector>. 74 auto Matcher = templateArgumentLoc().bind("id"); 75 auto MatchResults = match(Matcher, AST->getASTContext()); 76 const auto *TAL = MatchResults.front().getNodeAs<TemplateArgumentLoc>("id"); 77 ASSERT_TRUE(TAL); 78 TemplateName TN = TAL->getArgument().getAsTemplate(); 79 EXPECT_EQ(TN.getKind(), TemplateName::QualifiedTemplate); 80 const auto *QTN = TN.getAsQualifiedTemplateName(); 81 // Verify that we have the Using template name in the QualifiedTemplateName. 82 const auto *USD = QTN->getUnderlyingTemplate().getAsUsingShadowDecl(); 83 EXPECT_TRUE(USD); 84 EXPECT_EQ(USD->getTargetDecl(), TN.getAsTemplateDecl()); 85 } 86 87 TEST(TemplateName, UsingTemplate) { 88 auto AST = tooling::buildASTFromCode(R"cpp( 89 namespace std { 90 template <typename T> struct vector { vector(T); }; 91 } 92 namespace absl { using std::vector; } 93 // The "absl::vector<int>" is an elaborated TemplateSpecializationType with 94 // an inner Using TemplateName (not a Qualified TemplateName, the qualifiers 95 // are rather part of the ElaboratedType)! 96 absl::vector<int> v(123); 97 )cpp"); 98 auto Matcher = elaboratedTypeLoc( 99 hasNamedTypeLoc(loc(templateSpecializationType().bind("id")))); 100 auto MatchResults = match(Matcher, AST->getASTContext()); 101 const auto *TST = 102 MatchResults.front().getNodeAs<TemplateSpecializationType>("id"); 103 ASSERT_TRUE(TST); 104 EXPECT_EQ(TST->getTemplateName().getKind(), TemplateName::UsingTemplate); 105 106 AST = tooling::buildASTFromCodeWithArgs(R"cpp( 107 namespace std { 108 template <typename T> struct vector { vector(T); }; 109 } 110 namespace absl { using std::vector; } 111 // Similiar to the TemplateSpecializationType, absl::vector is an elaborated 112 // DeducedTemplateSpecializationType with an inner Using TemplateName! 113 absl::vector DTST(123); 114 )cpp", 115 {"-std=c++17"}); 116 Matcher = elaboratedTypeLoc( 117 hasNamedTypeLoc(loc(deducedTemplateSpecializationType().bind("id")))); 118 MatchResults = match(Matcher, AST->getASTContext()); 119 const auto *DTST = 120 MatchResults.front().getNodeAs<DeducedTemplateSpecializationType>("id"); 121 ASSERT_TRUE(DTST); 122 EXPECT_EQ(DTST->getTemplateName().getKind(), TemplateName::UsingTemplate); 123 } 124 125 } // namespace 126 } // namespace clang 127