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/Decl.h"
15 #include "clang/AST/DeclBase.h"
16 #include "clang/AST/DeclTemplate.h"
17 #include "clang/AST/DependenceFlags.h"
18 #include "clang/AST/NestedNameSpecifier.h"
19 #include "clang/AST/PrettyPrinter.h"
20 #include "clang/AST/TemplateBase.h"
21 #include "clang/Basic/Diagnostic.h"
22 #include "clang/Basic/LLVM.h"
23 #include "clang/Basic/LangOptions.h"
24 #include "clang/Basic/OperatorKinds.h"
25 #include "llvm/ADT/ArrayRef.h"
26 #include "llvm/ADT/FoldingSet.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/Compiler.h"
29 #include "llvm/Support/raw_ostream.h"
33 using namespace clang;
36 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
37 return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
40 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
41 Profile(ID, Parameter, Replacement);
44 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
45 TemplateTemplateParmDecl *parameter,
46 TemplateName replacement) {
47 ID.AddPointer(parameter);
48 ID.AddPointer(replacement.getAsVoidPointer());
51 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
52 ASTContext &Context) {
53 Profile(ID, Context, Parameter, getArgumentPack());
56 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
58 TemplateTemplateParmDecl *Parameter,
59 const TemplateArgument &ArgPack) {
60 ID.AddPointer(Parameter);
61 ArgPack.Profile(ID, Context);
64 TemplateName::TemplateName(void *Ptr) {
65 Storage = StorageType::getFromOpaqueValue(Ptr);
68 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
69 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
71 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
73 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
75 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
77 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
78 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
80 bool TemplateName::isNull() const { return Storage.isNull(); }
82 TemplateName::NameKind TemplateName::getKind() const {
83 if (Storage.is<TemplateDecl *>())
85 if (Storage.is<DependentTemplateName *>())
86 return DependentTemplate;
87 if (Storage.is<QualifiedTemplateName *>())
88 return QualifiedTemplate;
90 UncommonTemplateNameStorage *uncommon
91 = Storage.get<UncommonTemplateNameStorage*>();
92 if (uncommon->getAsOverloadedStorage())
93 return OverloadedTemplate;
94 if (uncommon->getAsAssumedTemplateName())
95 return AssumedTemplate;
96 if (uncommon->getAsSubstTemplateTemplateParm())
97 return SubstTemplateTemplateParm;
98 return SubstTemplateTemplateParmPack;
101 TemplateDecl *TemplateName::getAsTemplateDecl() const {
102 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
105 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
106 return QTN->getTemplateDecl();
108 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
109 return sub->getReplacement().getAsTemplateDecl();
114 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
115 if (UncommonTemplateNameStorage *Uncommon =
116 Storage.dyn_cast<UncommonTemplateNameStorage *>())
117 return Uncommon->getAsOverloadedStorage();
122 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
123 if (UncommonTemplateNameStorage *Uncommon =
124 Storage.dyn_cast<UncommonTemplateNameStorage *>())
125 return Uncommon->getAsAssumedTemplateName();
130 SubstTemplateTemplateParmStorage *
131 TemplateName::getAsSubstTemplateTemplateParm() const {
132 if (UncommonTemplateNameStorage *uncommon =
133 Storage.dyn_cast<UncommonTemplateNameStorage *>())
134 return uncommon->getAsSubstTemplateTemplateParm();
139 SubstTemplateTemplateParmPackStorage *
140 TemplateName::getAsSubstTemplateTemplateParmPack() const {
141 if (UncommonTemplateNameStorage *Uncommon =
142 Storage.dyn_cast<UncommonTemplateNameStorage *>())
143 return Uncommon->getAsSubstTemplateTemplateParmPack();
148 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
149 return Storage.dyn_cast<QualifiedTemplateName *>();
152 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
153 return Storage.dyn_cast<DependentTemplateName *>();
156 TemplateName TemplateName::getNameToSubstitute() const {
157 TemplateDecl *Decl = getAsTemplateDecl();
159 // Substituting a dependent template name: preserve it as written.
163 // If we have a template declaration, use the most recent non-friend
164 // declaration of that template.
165 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
166 while (Decl->getFriendObjectKind()) {
167 Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
168 assert(Decl && "all declarations of template are friends");
170 return TemplateName(Decl);
173 TemplateNameDependence TemplateName::getDependence() const {
174 auto D = TemplateNameDependence::None;
176 case TemplateName::NameKind::QualifiedTemplate:
177 D |= toTemplateNameDependence(
178 getAsQualifiedTemplateName()->getQualifier()->getDependence());
180 case TemplateName::NameKind::DependentTemplate:
181 D |= toTemplateNameDependence(
182 getAsDependentTemplateName()->getQualifier()->getDependence());
184 case TemplateName::NameKind::SubstTemplateTemplateParmPack:
185 D |= TemplateNameDependence::UnexpandedPack;
187 case TemplateName::NameKind::OverloadedTemplate:
188 llvm_unreachable("overloaded templates shouldn't survive to here.");
192 if (TemplateDecl *Template = getAsTemplateDecl()) {
193 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
194 D |= TemplateNameDependence::DependentInstantiation;
195 if (TTP->isParameterPack())
196 D |= TemplateNameDependence::UnexpandedPack;
198 // FIXME: Hack, getDeclContext() can be null if Template is still
199 // initializing due to PCH reading, so we check it before using it.
200 // Should probably modify TemplateSpecializationType to allow constructing
201 // it without the isDependent() checking.
202 if (Template->getDeclContext() &&
203 Template->getDeclContext()->isDependentContext())
204 D |= TemplateNameDependence::DependentInstantiation;
206 D |= TemplateNameDependence::DependentInstantiation;
211 bool TemplateName::isDependent() const {
212 return getDependence() & TemplateNameDependence::Dependent;
215 bool TemplateName::isInstantiationDependent() const {
216 return getDependence() & TemplateNameDependence::Instantiation;
219 bool TemplateName::containsUnexpandedParameterPack() const {
220 return getDependence() & TemplateNameDependence::UnexpandedPack;
224 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
225 bool SuppressNNS) const {
226 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
228 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
230 QTN->getQualifier()->print(OS, Policy);
231 if (QTN->hasTemplateKeyword())
233 OS << *QTN->getDecl();
234 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
235 if (!SuppressNNS && DTN->getQualifier())
236 DTN->getQualifier()->print(OS, Policy);
239 if (DTN->isIdentifier())
240 OS << DTN->getIdentifier()->getName();
242 OS << "operator " << getOperatorSpelling(DTN->getOperator());
243 } else if (SubstTemplateTemplateParmStorage *subst
244 = getAsSubstTemplateTemplateParm()) {
245 subst->getReplacement().print(OS, Policy, SuppressNNS);
246 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
247 = getAsSubstTemplateTemplateParmPack())
248 OS << *SubstPack->getParameterPack();
249 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
250 Assumed->getDeclName().print(OS, Policy);
252 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
253 (*OTS->begin())->printName(OS);
257 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
260 llvm::raw_string_ostream OS(NameStr);
265 N.print(OS, PrintingPolicy(LO));
268 return DB << NameStr;
271 const PartialDiagnostic&clang::operator<<(const PartialDiagnostic &PD,
274 llvm::raw_string_ostream OS(NameStr);
279 N.print(OS, PrintingPolicy(LO));
282 return PD << NameStr;
285 void TemplateName::dump(raw_ostream &OS) const {
286 LangOptions LO; // FIXME!
289 print(OS, PrintingPolicy(LO));
292 LLVM_DUMP_METHOD void TemplateName::dump() const {