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 Result;
25}
26
27TEST(TemplateName, PrintTemplate) {
28 std::string Code = R"cpp(
29 namespace std {
30 template <typename> struct vector {};
31 }
32 template<template <typename> class T> class X;
33 using A = X<std::vector>;
34 )cpp";
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(Matcher: templateArgumentLoc().bind(ID: "id"), Context&: Ctx);
39 const auto *Template = selectFirst<TemplateArgumentLoc>(BoundTo: "id", Results: MatchResults);
40 ASSERT_TRUE(Template);
41
42 TemplateName TN = Template->getArgument().getAsTemplate();
43 EXPECT_EQ(TN.getKind(), TemplateName::QualifiedTemplate);
44 EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(),
45 TemplateName::Qualified::AsWritten),
46 "std::vector");
47 EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(),
48 TemplateName::Qualified::None),
49 "vector");
50}
51
52TEST(TemplateName, PrintUsingTemplate) {
53 std::string Code = R"cpp(
54 namespace std {
55 template <typename> struct vector {};
56 }
57 namespace absl { using std::vector; }
58
59 template<template <typename> class T> class X;
60
61 using absl::vector;
62 using A = X<vector>;
63 )cpp";
64 auto AST = tooling::buildASTFromCode(Code);
65 ASTContext &Ctx = AST->getASTContext();
66 // Match the template argument vector in X<vector>.
67 auto MatchResults = match(Matcher: templateArgumentLoc().bind(ID: "id"), Context&: Ctx);
68 const auto *Template = selectFirst<TemplateArgumentLoc>(BoundTo: "id", Results: MatchResults);
69 ASSERT_TRUE(Template);
70
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());
76
77 EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(),
78 TemplateName::Qualified::AsWritten),
79 "vector");
80 EXPECT_EQ(printTemplateName(TN, Ctx.getPrintingPolicy(),
81 TemplateName::Qualified::None),
82 "vector");
83}
84
85TEST(TemplateName, QualifiedUsingTemplate) {
86 std::string Code = R"cpp(
87 namespace std {
88 template <typename> struct vector {};
89 }
90 namespace absl { using std::vector; }
91
92 template<template <typename> class T> class X;
93
94 using A = X<absl::vector>; // QualifiedTemplateName in a template argument.
95 )cpp";
96 auto AST = tooling::buildASTFromCode(Code);
97 // Match the template argument absl::vector in X<absl::vector>.
98 auto Matcher = templateArgumentLoc().bind(ID: "id");
99 auto MatchResults = match(Matcher, Context&: AST->getASTContext());
100 const auto *TAL = MatchResults.front().getNodeAs<TemplateArgumentLoc>(ID: "id");
101 ASSERT_TRUE(TAL);
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();
107 EXPECT_TRUE(USD);
108 EXPECT_EQ(USD->getTargetDecl(), TN.getAsTemplateDecl());
109 EXPECT_EQ(TN.getAsUsingShadowDecl(), USD);
110}
111
112TEST(TemplateName, UsingTemplate) {
113 auto AST = tooling::buildASTFromCode(Code: R"cpp(
114 namespace std {
115 template <typename T> struct vector { vector(T); };
116 }
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);
122 )cpp");
123 auto Matcher = elaboratedTypeLoc(
124 hasNamedTypeLoc(InnerMatcher: loc(InnerMatcher: templateSpecializationType().bind(ID: "id"))));
125 auto MatchResults = match(Matcher, Context&: AST->getASTContext());
126 const auto *TST =
127 MatchResults.front().getNodeAs<TemplateSpecializationType>(ID: "id");
128 ASSERT_TRUE(TST);
129 EXPECT_EQ(TST->getTemplateName().getKind(), TemplateName::QualifiedTemplate);
130 EXPECT_TRUE(TST->getTemplateName().getAsUsingShadowDecl() != nullptr);
131
132 AST = tooling::buildASTFromCodeWithArgs(Code: R"cpp(
133 namespace std {
134 template <typename T> struct vector { vector(T); };
135 }
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);
140 )cpp",
141 Args: {"-std=c++17"});
142 Matcher = elaboratedTypeLoc(
143 hasNamedTypeLoc(InnerMatcher: loc(InnerMatcher: deducedTemplateSpecializationType().bind(ID: "id"))));
144 MatchResults = match(Matcher, Context&: AST->getASTContext());
145 const auto *DTST =
146 MatchResults.front().getNodeAs<DeducedTemplateSpecializationType>(ID: "id");
147 ASSERT_TRUE(DTST);
148 EXPECT_EQ(DTST->getTemplateName().getKind(), TemplateName::QualifiedTemplate);
149 EXPECT_TRUE(DTST->getTemplateName().getAsUsingShadowDecl() != nullptr);
150}
151
152} // namespace
153} // namespace clang
154

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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