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
15namespace clang {
16namespace {
17using namespace ast_matchers;
18
19std::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(OS&: Out, Policy, Qual);
24 return Out.str();
25}
26
27TEST(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(Matcher: templateArgumentLoc().bind(ID: "id"), Context&: Ctx);
43 const auto *Template = selectFirst<TemplateArgumentLoc>(BoundTo: "id", Results: 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
61TEST(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: "id");
75 auto MatchResults = match(Matcher, Context&: AST->getASTContext());
76 const auto *TAL = MatchResults.front().getNodeAs<TemplateArgumentLoc>(ID: "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
88TEST(TemplateName, UsingTemplate) {
89 auto AST = tooling::buildASTFromCode(Code: 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(InnerMatcher: loc(InnerMatcher: templateSpecializationType().bind(ID: "id"))));
101 auto MatchResults = match(Matcher, Context&: AST->getASTContext());
102 const auto *TST =
103 MatchResults.front().getNodeAs<TemplateSpecializationType>(ID: "id");
104 ASSERT_TRUE(TST);
105 EXPECT_EQ(TST->getTemplateName().getKind(), TemplateName::UsingTemplate);
106
107 AST = tooling::buildASTFromCodeWithArgs(Code: 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 Args: {"-std=c++17"});
117 Matcher = elaboratedTypeLoc(
118 hasNamedTypeLoc(InnerMatcher: loc(InnerMatcher: deducedTemplateSpecializationType().bind(ID: "id"))));
119 MatchResults = match(Matcher, Context&: AST->getASTContext());
120 const auto *DTST =
121 MatchResults.front().getNodeAs<DeducedTemplateSpecializationType>(ID: "id");
122 ASSERT_TRUE(DTST);
123 EXPECT_EQ(DTST->getTemplateName().getKind(), TemplateName::UsingTemplate);
124}
125
126} // namespace
127} // namespace clang
128

source code of clang/unittests/AST/TemplateNameTest.cpp