xref: /llvm-project/clang/unittests/AST/TemplateNameTest.cpp (revision 918972bded27de6a2bfacc15b4ad3edebd81f405)
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