1 //===- unittests/AST/TemplateNameTest.cpp --- Tests for TemplateName ------===//
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
7 //===----------------------------------------------------------------------===//
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchers.h"
12 #include "llvm/Support/raw_ostream.h"
13 #include "gtest/gtest.h"
17 using namespace ast_matchers
;
19 std::string
printTemplateName(TemplateName TN
, const PrintingPolicy
&Policy
,
20 TemplateName::Qualified Qual
) {
22 llvm::raw_string_ostream
Out(Result
);
23 TN
.print(Out
, Policy
, Qual
);
27 TEST(TemplateName
, PrintTemplate
) {
28 std::string Code
= R
"cpp(
30 template <typename> struct vector {};
32 template<template <typename> class T> class X;
33 using A = X<std::vector>;
35 auto AST
= tooling::buildASTFromCode(Code
);
36 ASTContext
&Ctx
= AST
->getASTContext();
37 // Match the template argument vector in X<std::vector>.
38 auto MatchResults
= match(templateArgumentLoc().bind("id"), Ctx
);
39 const auto *Template
= selectFirst
<TemplateArgumentLoc
>("id", MatchResults
);
40 ASSERT_TRUE(Template
);
42 TemplateName TN
= Template
->getArgument().getAsTemplate();
43 EXPECT_EQ(TN
.getKind(), TemplateName::QualifiedTemplate
);
44 EXPECT_EQ(printTemplateName(TN
, Ctx
.getPrintingPolicy(),
45 TemplateName::Qualified::AsWritten
),
47 EXPECT_EQ(printTemplateName(TN
, Ctx
.getPrintingPolicy(),
48 TemplateName::Qualified::None
),
52 TEST(TemplateName
, PrintUsingTemplate
) {
53 std::string Code
= R
"cpp(
55 template <typename> struct vector {};
57 namespace absl { using std::vector; }
59 template<template <typename> class T> class X;
64 auto AST
= tooling::buildASTFromCode(Code
);
65 ASTContext
&Ctx
= AST
->getASTContext();
66 // Match the template argument vector in X<vector>.
67 auto MatchResults
= match(templateArgumentLoc().bind("id"), Ctx
);
68 const auto *Template
= selectFirst
<TemplateArgumentLoc
>("id", MatchResults
);
69 ASSERT_TRUE(Template
);
71 TemplateName TN
= Template
->getArgument().getAsTemplate();
72 EXPECT_EQ(TN
.getKind(), TemplateName::QualifiedTemplate
);
73 UsingShadowDecl
*USD
= TN
.getAsUsingShadowDecl();
74 EXPECT_TRUE(USD
!= nullptr);
75 EXPECT_EQ(USD
->getTargetDecl(), TN
.getAsTemplateDecl());
77 EXPECT_EQ(printTemplateName(TN
, Ctx
.getPrintingPolicy(),
78 TemplateName::Qualified::AsWritten
),
80 EXPECT_EQ(printTemplateName(TN
, Ctx
.getPrintingPolicy(),
81 TemplateName::Qualified::None
),
85 TEST(TemplateName
, QualifiedUsingTemplate
) {
86 std::string Code
= R
"cpp(
88 template <typename> struct vector {};
90 namespace absl { using std::vector; }
92 template<template <typename> class T> class X;
94 using A = X<absl::vector>; // QualifiedTemplateName in a template argument.
96 auto AST
= tooling::buildASTFromCode(Code
);
97 // Match the template argument absl::vector in X<absl::vector>.
98 auto Matcher
= templateArgumentLoc().bind("id");
99 auto MatchResults
= match(Matcher
, AST
->getASTContext());
100 const auto *TAL
= MatchResults
.front().getNodeAs
<TemplateArgumentLoc
>("id");
102 TemplateName TN
= TAL
->getArgument().getAsTemplate();
103 EXPECT_EQ(TN
.getKind(), TemplateName::QualifiedTemplate
);
104 const auto *QTN
= TN
.getAsQualifiedTemplateName();
105 // Verify that we have the Using template name in the QualifiedTemplateName.
106 const auto *USD
= QTN
->getUnderlyingTemplate().getAsUsingShadowDecl();
108 EXPECT_EQ(USD
->getTargetDecl(), TN
.getAsTemplateDecl());
109 EXPECT_EQ(TN
.getAsUsingShadowDecl(), USD
);
112 TEST(TemplateName
, UsingTemplate
) {
113 auto AST
= tooling::buildASTFromCode(R
"cpp(
115 template <typename T> struct vector { vector(T); };
117 namespace absl { using std::vector; }
118 // The "absl::vector
<int>" is an elaborated TemplateSpecializationType with
119 // an inner Using TemplateName (not a Qualified TemplateName, the qualifiers
120 // are rather part of the ElaboratedType)!
121 absl::vector<int> v(123);
123 auto Matcher
= elaboratedTypeLoc(
124 hasNamedTypeLoc(loc(templateSpecializationType().bind("id"))));
125 auto MatchResults
= match(Matcher
, AST
->getASTContext());
127 MatchResults
.front().getNodeAs
<TemplateSpecializationType
>("id");
129 EXPECT_EQ(TST
->getTemplateName().getKind(), TemplateName::QualifiedTemplate
);
130 EXPECT_TRUE(TST
->getTemplateName().getAsUsingShadowDecl() != nullptr);
132 AST
= tooling::buildASTFromCodeWithArgs(R
"cpp(
134 template <typename T> struct vector { vector(T); };
136 namespace absl { using std::vector; }
137 // Similiar to the TemplateSpecializationType, absl::vector is an elaborated
138 // DeducedTemplateSpecializationType with an inner Using TemplateName!
139 absl::vector DTST(123);
142 Matcher
= elaboratedTypeLoc(
143 hasNamedTypeLoc(loc(deducedTemplateSpecializationType().bind("id"))));
144 MatchResults
= match(Matcher
, AST
->getASTContext());
146 MatchResults
.front().getNodeAs
<DeducedTemplateSpecializationType
>("id");
148 EXPECT_EQ(DTST
->getTemplateName().getKind(), TemplateName::QualifiedTemplate
);
149 EXPECT_TRUE(DTST
->getTemplateName().getAsUsingShadowDecl() != nullptr);