cmake: Inline the add_llvm_symbol_exports.py script
[llvm-project.git] / clang / lib / AST / TemplateName.cpp
blobc348d76ed56064740eff05085666adc7bbd77324
1 //===- TemplateName.cpp - C++ Template Name Representation ----------------===//
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 // 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/DeclCXX.h"
17 #include "clang/AST/DeclTemplate.h"
18 #include "clang/AST/DependenceFlags.h"
19 #include "clang/AST/NestedNameSpecifier.h"
20 #include "clang/AST/PrettyPrinter.h"
21 #include "clang/AST/TemplateBase.h"
22 #include "clang/Basic/Diagnostic.h"
23 #include "clang/Basic/LLVM.h"
24 #include "clang/Basic/LangOptions.h"
25 #include "clang/Basic/OperatorKinds.h"
26 #include "llvm/ADT/ArrayRef.h"
27 #include "llvm/ADT/FoldingSet.h"
28 #include "llvm/Support/Casting.h"
29 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/raw_ostream.h"
31 #include <cassert>
32 #include <string>
34 using namespace clang;
36 TemplateArgument
37 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
38 return TemplateArgument(llvm::makeArrayRef(Arguments, Bits.Data));
41 TemplateTemplateParmDecl *
42 SubstTemplateTemplateParmPackStorage::getParameterPack() const {
43 return cast<TemplateTemplateParmDecl>(
44 getReplacedTemplateParameterList(getAssociatedDecl())
45 ->asArray()[Bits.Index]);
48 TemplateTemplateParmDecl *
49 SubstTemplateTemplateParmStorage::getParameter() const {
50 return cast<TemplateTemplateParmDecl>(
51 getReplacedTemplateParameterList(getAssociatedDecl())
52 ->asArray()[Bits.Index]);
55 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
56 Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
59 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
60 TemplateName Replacement,
61 Decl *AssociatedDecl,
62 unsigned Index,
63 Optional<unsigned> PackIndex) {
64 Replacement.Profile(ID);
65 ID.AddPointer(AssociatedDecl);
66 ID.AddInteger(Index);
67 ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
70 SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
71 ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
72 bool Final)
73 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
74 ArgPack.size()),
75 Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
76 assert(AssociatedDecl != nullptr);
79 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
80 ASTContext &Context) {
81 Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),
82 getFinal());
85 Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
86 return AssociatedDeclAndFinal.getPointer();
89 bool SubstTemplateTemplateParmPackStorage::getFinal() const {
90 return AssociatedDeclAndFinal.getInt();
93 void SubstTemplateTemplateParmPackStorage::Profile(
94 llvm::FoldingSetNodeID &ID, ASTContext &Context,
95 const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
96 bool Final) {
97 ArgPack.Profile(ID, Context);
98 ID.AddPointer(AssociatedDecl);
99 ID.AddInteger(Index);
100 ID.AddBoolean(Final);
103 TemplateName::TemplateName(void *Ptr) {
104 Storage = StorageType::getFromOpaqueValue(Ptr);
107 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
108 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
109 : Storage(Storage) {}
110 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
111 : Storage(Storage) {}
112 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
113 : Storage(Storage) {}
114 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
115 : Storage(Storage) {}
116 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
117 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
118 TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
120 bool TemplateName::isNull() const { return Storage.isNull(); }
122 TemplateName::NameKind TemplateName::getKind() const {
123 if (auto *ND = Storage.dyn_cast<Decl *>()) {
124 if (isa<UsingShadowDecl>(ND))
125 return UsingTemplate;
126 assert(isa<TemplateDecl>(ND));
127 return Template;
130 if (Storage.is<DependentTemplateName *>())
131 return DependentTemplate;
132 if (Storage.is<QualifiedTemplateName *>())
133 return QualifiedTemplate;
135 UncommonTemplateNameStorage *uncommon
136 = Storage.get<UncommonTemplateNameStorage*>();
137 if (uncommon->getAsOverloadedStorage())
138 return OverloadedTemplate;
139 if (uncommon->getAsAssumedTemplateName())
140 return AssumedTemplate;
141 if (uncommon->getAsSubstTemplateTemplateParm())
142 return SubstTemplateTemplateParm;
143 return SubstTemplateTemplateParmPack;
146 TemplateDecl *TemplateName::getAsTemplateDecl() const {
147 if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) {
148 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing))
149 return cast<TemplateDecl>(USD->getTargetDecl());
151 assert(isa<TemplateDecl>(TemplateOrUsing));
152 return cast<TemplateDecl>(TemplateOrUsing);
155 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
156 return QTN->getUnderlyingTemplate().getAsTemplateDecl();
158 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
159 return sub->getReplacement().getAsTemplateDecl();
161 if (UsingShadowDecl *USD = getAsUsingShadowDecl())
162 return cast<TemplateDecl>(USD->getTargetDecl());
164 return nullptr;
167 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
168 if (UncommonTemplateNameStorage *Uncommon =
169 Storage.dyn_cast<UncommonTemplateNameStorage *>())
170 return Uncommon->getAsOverloadedStorage();
172 return nullptr;
175 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
176 if (UncommonTemplateNameStorage *Uncommon =
177 Storage.dyn_cast<UncommonTemplateNameStorage *>())
178 return Uncommon->getAsAssumedTemplateName();
180 return nullptr;
183 SubstTemplateTemplateParmStorage *
184 TemplateName::getAsSubstTemplateTemplateParm() const {
185 if (UncommonTemplateNameStorage *uncommon =
186 Storage.dyn_cast<UncommonTemplateNameStorage *>())
187 return uncommon->getAsSubstTemplateTemplateParm();
189 return nullptr;
192 SubstTemplateTemplateParmPackStorage *
193 TemplateName::getAsSubstTemplateTemplateParmPack() const {
194 if (UncommonTemplateNameStorage *Uncommon =
195 Storage.dyn_cast<UncommonTemplateNameStorage *>())
196 return Uncommon->getAsSubstTemplateTemplateParmPack();
198 return nullptr;
201 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
202 return Storage.dyn_cast<QualifiedTemplateName *>();
205 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
206 return Storage.dyn_cast<DependentTemplateName *>();
209 UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
210 if (Decl *D = Storage.dyn_cast<Decl *>())
211 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
212 return USD;
213 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
214 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
215 return nullptr;
218 TemplateName TemplateName::getNameToSubstitute() const {
219 TemplateDecl *Decl = getAsTemplateDecl();
221 // Substituting a dependent template name: preserve it as written.
222 if (!Decl)
223 return *this;
225 // If we have a template declaration, use the most recent non-friend
226 // declaration of that template.
227 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
228 while (Decl->getFriendObjectKind()) {
229 Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
230 assert(Decl && "all declarations of template are friends");
232 return TemplateName(Decl);
235 TemplateNameDependence TemplateName::getDependence() const {
236 auto D = TemplateNameDependence::None;
237 switch (getKind()) {
238 case TemplateName::NameKind::QualifiedTemplate:
239 D |= toTemplateNameDependence(
240 getAsQualifiedTemplateName()->getQualifier()->getDependence());
241 break;
242 case TemplateName::NameKind::DependentTemplate:
243 D |= toTemplateNameDependence(
244 getAsDependentTemplateName()->getQualifier()->getDependence());
245 break;
246 case TemplateName::NameKind::SubstTemplateTemplateParmPack:
247 D |= TemplateNameDependence::UnexpandedPack;
248 break;
249 case TemplateName::NameKind::OverloadedTemplate:
250 llvm_unreachable("overloaded templates shouldn't survive to here.");
251 default:
252 break;
254 if (TemplateDecl *Template = getAsTemplateDecl()) {
255 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
256 D |= TemplateNameDependence::DependentInstantiation;
257 if (TTP->isParameterPack())
258 D |= TemplateNameDependence::UnexpandedPack;
260 // FIXME: Hack, getDeclContext() can be null if Template is still
261 // initializing due to PCH reading, so we check it before using it.
262 // Should probably modify TemplateSpecializationType to allow constructing
263 // it without the isDependent() checking.
264 if (Template->getDeclContext() &&
265 Template->getDeclContext()->isDependentContext())
266 D |= TemplateNameDependence::DependentInstantiation;
267 } else {
268 D |= TemplateNameDependence::DependentInstantiation;
270 return D;
273 bool TemplateName::isDependent() const {
274 return getDependence() & TemplateNameDependence::Dependent;
277 bool TemplateName::isInstantiationDependent() const {
278 return getDependence() & TemplateNameDependence::Instantiation;
281 bool TemplateName::containsUnexpandedParameterPack() const {
282 return getDependence() & TemplateNameDependence::UnexpandedPack;
285 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
286 Qualified Qual) const {
287 auto Kind = getKind();
288 TemplateDecl *Template = nullptr;
289 if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
290 // After `namespace ns { using std::vector }`, what is the fully-qualified
291 // name of the UsingTemplateName `vector` within ns?
293 // - ns::vector (the qualified name of the using-shadow decl)
294 // - std::vector (the qualified name of the underlying template decl)
296 // Similar to the UsingType behavior, using declarations are used to import
297 // names more often than to export them, thus using the original name is
298 // most useful in this case.
299 Template = getAsTemplateDecl();
302 if (Template)
303 if (Policy.CleanUglifiedParameters &&
304 isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier())
305 OS << Template->getIdentifier()->deuglifiedName();
306 else if (Qual == Qualified::Fully &&
307 getDependence() !=
308 TemplateNameDependenceScope::DependentInstantiation)
309 Template->printQualifiedName(OS, Policy);
310 else
311 OS << *Template;
312 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
313 if (Qual == Qualified::Fully &&
314 getDependence() !=
315 TemplateNameDependenceScope::DependentInstantiation) {
316 QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
317 OS, Policy);
318 return;
320 if (Qual == Qualified::AsWritten)
321 QTN->getQualifier()->print(OS, Policy);
322 if (QTN->hasTemplateKeyword())
323 OS << "template ";
324 OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl();
325 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
326 if (Qual == Qualified::AsWritten && DTN->getQualifier())
327 DTN->getQualifier()->print(OS, Policy);
328 OS << "template ";
330 if (DTN->isIdentifier())
331 OS << DTN->getIdentifier()->getName();
332 else
333 OS << "operator " << getOperatorSpelling(DTN->getOperator());
334 } else if (SubstTemplateTemplateParmStorage *subst
335 = getAsSubstTemplateTemplateParm()) {
336 subst->getReplacement().print(OS, Policy, Qual);
337 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
338 = getAsSubstTemplateTemplateParmPack())
339 OS << *SubstPack->getParameterPack();
340 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
341 Assumed->getDeclName().print(OS, Policy);
342 } else {
343 assert(getKind() == TemplateName::OverloadedTemplate);
344 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
345 (*OTS->begin())->printName(OS, Policy);
349 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
350 TemplateName N) {
351 std::string NameStr;
352 llvm::raw_string_ostream OS(NameStr);
353 LangOptions LO;
354 LO.CPlusPlus = true;
355 LO.Bool = true;
356 OS << '\'';
357 N.print(OS, PrintingPolicy(LO));
358 OS << '\'';
359 OS.flush();
360 return DB << NameStr;
363 void TemplateName::dump(raw_ostream &OS) const {
364 LangOptions LO; // FIXME!
365 LO.CPlusPlus = true;
366 LO.Bool = true;
367 print(OS, PrintingPolicy(LO));
370 LLVM_DUMP_METHOD void TemplateName::dump() const {
371 dump(llvm::errs());