1 //===- TemplateName.cpp - C++ Template Name Representation ----------------===//
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 //===----------------------------------------------------------------------===//
9 // This file defines the TemplateName interface and subclasses.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/TemplateName.h"
14 #include "clang/AST/DeclBase.h"
15 #include "clang/AST/DeclTemplate.h"
16 #include "clang/AST/NestedNameSpecifier.h"
17 #include "clang/AST/PrettyPrinter.h"
18 #include "clang/AST/TemplateBase.h"
19 #include "clang/Basic/Diagnostic.h"
20 #include "clang/Basic/LLVM.h"
21 #include "clang/Basic/LangOptions.h"
22 #include "clang/Basic/OperatorKinds.h"
23 #include "llvm/ADT/ArrayRef.h"
24 #include "llvm/ADT/FoldingSet.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/Compiler.h"
27 #include "llvm/Support/raw_ostream.h"
31 using namespace clang;
34 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
35 return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
38 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
39 Profile(ID, Parameter, Replacement);
42 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
43 TemplateTemplateParmDecl *parameter,
44 TemplateName replacement) {
45 ID.AddPointer(parameter);
46 ID.AddPointer(replacement.getAsVoidPointer());
49 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
50 ASTContext &Context) {
51 Profile(ID, Context, Parameter, getArgumentPack());
54 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
56 TemplateTemplateParmDecl *Parameter,
57 const TemplateArgument &ArgPack) {
58 ID.AddPointer(Parameter);
59 ArgPack.Profile(ID, Context);
62 TemplateName::TemplateName(void *Ptr) {
63 Storage = StorageType::getFromOpaqueValue(Ptr);
66 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
67 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
69 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
71 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
73 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
75 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
76 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
78 bool TemplateName::isNull() const { return Storage.isNull(); }
80 TemplateName::NameKind TemplateName::getKind() const {
81 if (Storage.is<TemplateDecl *>())
83 if (Storage.is<DependentTemplateName *>())
84 return DependentTemplate;
85 if (Storage.is<QualifiedTemplateName *>())
86 return QualifiedTemplate;
88 UncommonTemplateNameStorage *uncommon
89 = Storage.get<UncommonTemplateNameStorage*>();
90 if (uncommon->getAsOverloadedStorage())
91 return OverloadedTemplate;
92 if (uncommon->getAsAssumedTemplateName())
93 return AssumedTemplate;
94 if (uncommon->getAsSubstTemplateTemplateParm())
95 return SubstTemplateTemplateParm;
96 return SubstTemplateTemplateParmPack;
99 TemplateDecl *TemplateName::getAsTemplateDecl() const {
100 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
103 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
104 return QTN->getTemplateDecl();
106 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
107 return sub->getReplacement().getAsTemplateDecl();
112 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
113 if (UncommonTemplateNameStorage *Uncommon =
114 Storage.dyn_cast<UncommonTemplateNameStorage *>())
115 return Uncommon->getAsOverloadedStorage();
120 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
121 if (UncommonTemplateNameStorage *Uncommon =
122 Storage.dyn_cast<UncommonTemplateNameStorage *>())
123 return Uncommon->getAsAssumedTemplateName();
128 SubstTemplateTemplateParmStorage *
129 TemplateName::getAsSubstTemplateTemplateParm() const {
130 if (UncommonTemplateNameStorage *uncommon =
131 Storage.dyn_cast<UncommonTemplateNameStorage *>())
132 return uncommon->getAsSubstTemplateTemplateParm();
137 SubstTemplateTemplateParmPackStorage *
138 TemplateName::getAsSubstTemplateTemplateParmPack() const {
139 if (UncommonTemplateNameStorage *Uncommon =
140 Storage.dyn_cast<UncommonTemplateNameStorage *>())
141 return Uncommon->getAsSubstTemplateTemplateParmPack();
146 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
147 return Storage.dyn_cast<QualifiedTemplateName *>();
150 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
151 return Storage.dyn_cast<DependentTemplateName *>();
154 TemplateName TemplateName::getNameToSubstitute() const {
155 TemplateDecl *Decl = getAsTemplateDecl();
157 // Substituting a dependent template name: preserve it as written.
161 // If we have a template declaration, use the most recent non-friend
162 // declaration of that template.
163 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
164 while (Decl->getFriendObjectKind()) {
165 Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
166 assert(Decl && "all declarations of template are friends");
168 return TemplateName(Decl);
171 bool TemplateName::isDependent() const {
172 if (TemplateDecl *Template = getAsTemplateDecl()) {
173 if (isa<TemplateTemplateParmDecl>(Template))
175 // FIXME: Hack, getDeclContext() can be null if Template is still
176 // initializing due to PCH reading, so we check it before using it.
177 // Should probably modify TemplateSpecializationType to allow constructing
178 // it without the isDependent() checking.
179 return Template->getDeclContext() &&
180 Template->getDeclContext()->isDependentContext();
183 assert(!getAsOverloadedTemplate() &&
184 "overloaded templates shouldn't survive to here");
189 bool TemplateName::isInstantiationDependent() const {
190 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
191 if (QTN->getQualifier()->isInstantiationDependent())
195 return isDependent();
198 bool TemplateName::containsUnexpandedParameterPack() const {
199 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
200 if (QTN->getQualifier()->containsUnexpandedParameterPack())
204 if (TemplateDecl *Template = getAsTemplateDecl()) {
205 if (TemplateTemplateParmDecl *TTP
206 = dyn_cast<TemplateTemplateParmDecl>(Template))
207 return TTP->isParameterPack();
212 if (DependentTemplateName *DTN = getAsDependentTemplateName())
213 return DTN->getQualifier() &&
214 DTN->getQualifier()->containsUnexpandedParameterPack();
216 return getAsSubstTemplateTemplateParmPack() != nullptr;
220 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
221 bool SuppressNNS) const {
222 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
224 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
226 QTN->getQualifier()->print(OS, Policy);
227 if (QTN->hasTemplateKeyword())
229 OS << *QTN->getDecl();
230 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
231 if (!SuppressNNS && DTN->getQualifier())
232 DTN->getQualifier()->print(OS, Policy);
235 if (DTN->isIdentifier())
236 OS << DTN->getIdentifier()->getName();
238 OS << "operator " << getOperatorSpelling(DTN->getOperator());
239 } else if (SubstTemplateTemplateParmStorage *subst
240 = getAsSubstTemplateTemplateParm()) {
241 subst->getReplacement().print(OS, Policy, SuppressNNS);
242 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
243 = getAsSubstTemplateTemplateParmPack())
244 OS << *SubstPack->getParameterPack();
245 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
246 Assumed->getDeclName().print(OS, Policy);
248 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
249 (*OTS->begin())->printName(OS);
253 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
256 llvm::raw_string_ostream OS(NameStr);
261 N.print(OS, PrintingPolicy(LO));
264 return DB << NameStr;
267 const PartialDiagnostic&clang::operator<<(const PartialDiagnostic &PD,
270 llvm::raw_string_ostream OS(NameStr);
275 N.print(OS, PrintingPolicy(LO));
278 return PD << NameStr;
281 void TemplateName::dump(raw_ostream &OS) const {
282 LangOptions LO; // FIXME!
285 print(OS, PrintingPolicy(LO));
288 LLVM_DUMP_METHOD void TemplateName::dump() const {