16ba1b907SHaojian Wu //===- unittests/AST/TemplateNameTest.cpp --- Tests for TemplateName ------===// 26ba1b907SHaojian Wu // 36ba1b907SHaojian Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 46ba1b907SHaojian Wu // See https://llvm.org/LICENSE.txt for license information. 56ba1b907SHaojian Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 66ba1b907SHaojian Wu // 76ba1b907SHaojian Wu //===----------------------------------------------------------------------===// 86ba1b907SHaojian Wu 96ba1b907SHaojian Wu #include "ASTPrint.h" 106ba1b907SHaojian Wu #include "clang/AST/ASTContext.h" 116ba1b907SHaojian Wu #include "clang/ASTMatchers/ASTMatchers.h" 126ba1b907SHaojian Wu #include "llvm/Support/raw_ostream.h" 136ba1b907SHaojian Wu #include "gtest/gtest.h" 146ba1b907SHaojian Wu 156ba1b907SHaojian Wu namespace clang { 166ba1b907SHaojian Wu namespace { 176ba1b907SHaojian Wu using namespace ast_matchers; 186ba1b907SHaojian Wu 196ba1b907SHaojian Wu std::string printTemplateName(TemplateName TN, const PrintingPolicy &Policy, 206ba1b907SHaojian Wu TemplateName::Qualified Qual) { 216ba1b907SHaojian Wu std::string Result; 226ba1b907SHaojian Wu llvm::raw_string_ostream Out(Result); 236ba1b907SHaojian Wu TN.print(Out, Policy, Qual); 24*918972bdSJOE1994 return Result; 256ba1b907SHaojian Wu } 266ba1b907SHaojian Wu 279c4a716cSMatheus Izvekov TEST(TemplateName, PrintTemplate) { 289c4a716cSMatheus Izvekov std::string Code = R"cpp( 299c4a716cSMatheus Izvekov namespace std { 309c4a716cSMatheus Izvekov template <typename> struct vector {}; 319c4a716cSMatheus Izvekov } 329c4a716cSMatheus Izvekov template<template <typename> class T> class X; 339c4a716cSMatheus Izvekov using A = X<std::vector>; 349c4a716cSMatheus Izvekov )cpp"; 359c4a716cSMatheus Izvekov auto AST = tooling::buildASTFromCode(Code); 369c4a716cSMatheus Izvekov ASTContext &Ctx = AST->getASTContext(); 379c4a716cSMatheus Izvekov // Match the template argument vector in X<std::vector>. 389c4a716cSMatheus Izvekov auto MatchResults = match(templateArgumentLoc().bind("id"), Ctx); 399c4a716cSMatheus Izvekov const auto *Template = selectFirst<TemplateArgumentLoc>("id", MatchResults); 409c4a716cSMatheus Izvekov ASSERT_TRUE(Template); 419c4a716cSMatheus Izvekov 429c4a716cSMatheus Izvekov TemplateName TN = Template->getArgument().getAsTemplate(); 439c4a716cSMatheus Izvekov EXPECT_EQ(TN.getKind(), TemplateName::QualifiedTemplate); 449c4a716cSMatheus Izvekov EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(), 459c4a716cSMatheus Izvekov TemplateName::Qualified::AsWritten), 469c4a716cSMatheus Izvekov "std::vector"); 479c4a716cSMatheus Izvekov EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(), 489c4a716cSMatheus Izvekov TemplateName::Qualified::None), 499c4a716cSMatheus Izvekov "vector"); 509c4a716cSMatheus Izvekov } 519c4a716cSMatheus Izvekov 526ba1b907SHaojian Wu TEST(TemplateName, PrintUsingTemplate) { 536ba1b907SHaojian Wu std::string Code = R"cpp( 546ba1b907SHaojian Wu namespace std { 556ba1b907SHaojian Wu template <typename> struct vector {}; 566ba1b907SHaojian Wu } 576ba1b907SHaojian Wu namespace absl { using std::vector; } 586ba1b907SHaojian Wu 596ba1b907SHaojian Wu template<template <typename> class T> class X; 606ba1b907SHaojian Wu 616ba1b907SHaojian Wu using absl::vector; 626ba1b907SHaojian Wu using A = X<vector>; 636ba1b907SHaojian Wu )cpp"; 646ba1b907SHaojian Wu auto AST = tooling::buildASTFromCode(Code); 656ba1b907SHaojian Wu ASTContext &Ctx = AST->getASTContext(); 666ba1b907SHaojian Wu // Match the template argument vector in X<vector>. 676ba1b907SHaojian Wu auto MatchResults = match(templateArgumentLoc().bind("id"), Ctx); 686ba1b907SHaojian Wu const auto *Template = selectFirst<TemplateArgumentLoc>("id", MatchResults); 696ba1b907SHaojian Wu ASSERT_TRUE(Template); 706ba1b907SHaojian Wu 716ba1b907SHaojian Wu TemplateName TN = Template->getArgument().getAsTemplate(); 729c4a716cSMatheus Izvekov EXPECT_EQ(TN.getKind(), TemplateName::QualifiedTemplate); 739c4a716cSMatheus Izvekov UsingShadowDecl *USD = TN.getAsUsingShadowDecl(); 749c4a716cSMatheus Izvekov EXPECT_TRUE(USD != nullptr); 759c4a716cSMatheus Izvekov EXPECT_EQ(USD->getTargetDecl(), TN.getAsTemplateDecl()); 766ba1b907SHaojian Wu 776ba1b907SHaojian Wu EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(), 786ba1b907SHaojian Wu TemplateName::Qualified::AsWritten), 796ba1b907SHaojian Wu "vector"); 806ba1b907SHaojian Wu EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(), 816ba1b907SHaojian Wu TemplateName::Qualified::None), 826ba1b907SHaojian Wu "vector"); 836ba1b907SHaojian Wu } 846ba1b907SHaojian Wu 851234b1c6SHaojian Wu TEST(TemplateName, QualifiedUsingTemplate) { 861234b1c6SHaojian Wu std::string Code = R"cpp( 871234b1c6SHaojian Wu namespace std { 881234b1c6SHaojian Wu template <typename> struct vector {}; 891234b1c6SHaojian Wu } 901234b1c6SHaojian Wu namespace absl { using std::vector; } 911234b1c6SHaojian Wu 921234b1c6SHaojian Wu template<template <typename> class T> class X; 931234b1c6SHaojian Wu 941234b1c6SHaojian Wu using A = X<absl::vector>; // QualifiedTemplateName in a template argument. 951234b1c6SHaojian Wu )cpp"; 961234b1c6SHaojian Wu auto AST = tooling::buildASTFromCode(Code); 971234b1c6SHaojian Wu // Match the template argument absl::vector in X<absl::vector>. 981234b1c6SHaojian Wu auto Matcher = templateArgumentLoc().bind("id"); 991234b1c6SHaojian Wu auto MatchResults = match(Matcher, AST->getASTContext()); 1001234b1c6SHaojian Wu const auto *TAL = MatchResults.front().getNodeAs<TemplateArgumentLoc>("id"); 1011234b1c6SHaojian Wu ASSERT_TRUE(TAL); 1021234b1c6SHaojian Wu TemplateName TN = TAL->getArgument().getAsTemplate(); 1031234b1c6SHaojian Wu EXPECT_EQ(TN.getKind(), TemplateName::QualifiedTemplate); 1041234b1c6SHaojian Wu const auto *QTN = TN.getAsQualifiedTemplateName(); 1051234b1c6SHaojian Wu // Verify that we have the Using template name in the QualifiedTemplateName. 1061234b1c6SHaojian Wu const auto *USD = QTN->getUnderlyingTemplate().getAsUsingShadowDecl(); 1071234b1c6SHaojian Wu EXPECT_TRUE(USD); 1081234b1c6SHaojian Wu EXPECT_EQ(USD->getTargetDecl(), TN.getAsTemplateDecl()); 1098052f4d2SHaojian Wu EXPECT_EQ(TN.getAsUsingShadowDecl(), USD); 1101234b1c6SHaojian Wu } 1111234b1c6SHaojian Wu 1121234b1c6SHaojian Wu TEST(TemplateName, UsingTemplate) { 1131234b1c6SHaojian Wu auto AST = tooling::buildASTFromCode(R"cpp( 1141234b1c6SHaojian Wu namespace std { 1151234b1c6SHaojian Wu template <typename T> struct vector { vector(T); }; 1161234b1c6SHaojian Wu } 1171234b1c6SHaojian Wu namespace absl { using std::vector; } 1181234b1c6SHaojian Wu // The "absl::vector<int>" is an elaborated TemplateSpecializationType with 1191234b1c6SHaojian Wu // an inner Using TemplateName (not a Qualified TemplateName, the qualifiers 1201234b1c6SHaojian Wu // are rather part of the ElaboratedType)! 1211234b1c6SHaojian Wu absl::vector<int> v(123); 1221234b1c6SHaojian Wu )cpp"); 1231234b1c6SHaojian Wu auto Matcher = elaboratedTypeLoc( 1241234b1c6SHaojian Wu hasNamedTypeLoc(loc(templateSpecializationType().bind("id")))); 1251234b1c6SHaojian Wu auto MatchResults = match(Matcher, AST->getASTContext()); 1261234b1c6SHaojian Wu const auto *TST = 1271234b1c6SHaojian Wu MatchResults.front().getNodeAs<TemplateSpecializationType>("id"); 1281234b1c6SHaojian Wu ASSERT_TRUE(TST); 1299c4a716cSMatheus Izvekov EXPECT_EQ(TST->getTemplateName().getKind(), TemplateName::QualifiedTemplate); 1309c4a716cSMatheus Izvekov EXPECT_TRUE(TST->getTemplateName().getAsUsingShadowDecl() != nullptr); 1311234b1c6SHaojian Wu 1321234b1c6SHaojian Wu AST = tooling::buildASTFromCodeWithArgs(R"cpp( 1331234b1c6SHaojian Wu namespace std { 1341234b1c6SHaojian Wu template <typename T> struct vector { vector(T); }; 1351234b1c6SHaojian Wu } 1361234b1c6SHaojian Wu namespace absl { using std::vector; } 1371234b1c6SHaojian Wu // Similiar to the TemplateSpecializationType, absl::vector is an elaborated 1381234b1c6SHaojian Wu // DeducedTemplateSpecializationType with an inner Using TemplateName! 1391234b1c6SHaojian Wu absl::vector DTST(123); 1401234b1c6SHaojian Wu )cpp", 1411234b1c6SHaojian Wu {"-std=c++17"}); 1421234b1c6SHaojian Wu Matcher = elaboratedTypeLoc( 1431234b1c6SHaojian Wu hasNamedTypeLoc(loc(deducedTemplateSpecializationType().bind("id")))); 1441234b1c6SHaojian Wu MatchResults = match(Matcher, AST->getASTContext()); 1451234b1c6SHaojian Wu const auto *DTST = 1461234b1c6SHaojian Wu MatchResults.front().getNodeAs<DeducedTemplateSpecializationType>("id"); 1471234b1c6SHaojian Wu ASSERT_TRUE(DTST); 1489c4a716cSMatheus Izvekov EXPECT_EQ(DTST->getTemplateName().getKind(), TemplateName::QualifiedTemplate); 1499c4a716cSMatheus Izvekov EXPECT_TRUE(DTST->getTemplateName().getAsUsingShadowDecl() != nullptr); 1501234b1c6SHaojian Wu } 1511234b1c6SHaojian Wu 1526ba1b907SHaojian Wu } // namespace 1536ba1b907SHaojian Wu } // namespace clang 154