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 EXPECT_EQ(TN.getAsUsingShadowDecl(), USD); 86 } 87 88 TEST(TemplateName, UsingTemplate) { 89 auto AST = tooling::buildASTFromCode(R"cpp( 90 namespace std { 91 template <typename T> struct vector { vector(T); }; 92 } 93 namespace absl { using std::vector; } 94 // The "absl::vector<int>" is an elaborated TemplateSpecializationType with 95 // an inner Using TemplateName (not a Qualified TemplateName, the qualifiers 96 // are rather part of the ElaboratedType)! 97 absl::vector<int> v(123); 98 )cpp"); 99 auto Matcher = elaboratedTypeLoc( 100 hasNamedTypeLoc(loc(templateSpecializationType().bind("id")))); 101 auto MatchResults = match(Matcher, AST->getASTContext()); 102 const auto *TST = 103 MatchResults.front().getNodeAs<TemplateSpecializationType>("id"); 104 ASSERT_TRUE(TST); 105 EXPECT_EQ(TST->getTemplateName().getKind(), TemplateName::UsingTemplate); 106 107 AST = tooling::buildASTFromCodeWithArgs(R"cpp( 108 namespace std { 109 template <typename T> struct vector { vector(T); }; 110 } 111 namespace absl { using std::vector; } 112 // Similiar to the TemplateSpecializationType, absl::vector is an elaborated 113 // DeducedTemplateSpecializationType with an inner Using TemplateName! 114 absl::vector DTST(123); 115 )cpp", 116 {"-std=c++17"}); 117 Matcher = elaboratedTypeLoc( 118 hasNamedTypeLoc(loc(deducedTemplateSpecializationType().bind("id")))); 119 MatchResults = match(Matcher, AST->getASTContext()); 120 const auto *DTST = 121 MatchResults.front().getNodeAs<DeducedTemplateSpecializationType>("id"); 122 ASSERT_TRUE(DTST); 123 EXPECT_EQ(DTST->getTemplateName().getKind(), TemplateName::UsingTemplate); 124 } 125 126 } // namespace 127 } // namespace clang 128