]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / AST / TemplateName.cpp
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.
10 //
11 //===----------------------------------------------------------------------===//
12
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"
28 #include <cassert>
29 #include <string>
30
31 using namespace clang;
32
33 TemplateArgument
34 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
35   return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
36 }
37
38 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
39   Profile(ID, Parameter, Replacement);
40 }
41
42 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
43                                            TemplateTemplateParmDecl *parameter,
44                                                TemplateName replacement) {
45   ID.AddPointer(parameter);
46   ID.AddPointer(replacement.getAsVoidPointer());
47 }
48
49 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
50                                                    ASTContext &Context) {
51   Profile(ID, Context, Parameter, getArgumentPack());
52 }
53
54 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
55                                                    ASTContext &Context,
56                                            TemplateTemplateParmDecl *Parameter,
57                                              const TemplateArgument &ArgPack) {
58   ID.AddPointer(Parameter);
59   ArgPack.Profile(ID, Context);
60 }
61
62 TemplateName::TemplateName(void *Ptr) {
63   Storage = StorageType::getFromOpaqueValue(Ptr);
64 }
65
66 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
67 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
68     : Storage(Storage) {}
69 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
70     : Storage(Storage) {}
71 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
72     : Storage(Storage) {}
73 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
74     : Storage(Storage) {}
75 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
76 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
77
78 bool TemplateName::isNull() const { return Storage.isNull(); }
79
80 TemplateName::NameKind TemplateName::getKind() const {
81   if (Storage.is<TemplateDecl *>())
82     return Template;
83   if (Storage.is<DependentTemplateName *>())
84     return DependentTemplate;
85   if (Storage.is<QualifiedTemplateName *>())
86     return QualifiedTemplate;
87
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;
97 }
98
99 TemplateDecl *TemplateName::getAsTemplateDecl() const {
100   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
101     return Template;
102
103   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
104     return QTN->getTemplateDecl();
105
106   if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
107     return sub->getReplacement().getAsTemplateDecl();
108
109   return nullptr;
110 }
111
112 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
113   if (UncommonTemplateNameStorage *Uncommon =
114           Storage.dyn_cast<UncommonTemplateNameStorage *>())
115     return Uncommon->getAsOverloadedStorage();
116
117   return nullptr;
118 }
119
120 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
121   if (UncommonTemplateNameStorage *Uncommon =
122           Storage.dyn_cast<UncommonTemplateNameStorage *>())
123     return Uncommon->getAsAssumedTemplateName();
124
125   return nullptr;
126 }
127
128 SubstTemplateTemplateParmStorage *
129 TemplateName::getAsSubstTemplateTemplateParm() const {
130   if (UncommonTemplateNameStorage *uncommon =
131           Storage.dyn_cast<UncommonTemplateNameStorage *>())
132     return uncommon->getAsSubstTemplateTemplateParm();
133
134   return nullptr;
135 }
136
137 SubstTemplateTemplateParmPackStorage *
138 TemplateName::getAsSubstTemplateTemplateParmPack() const {
139   if (UncommonTemplateNameStorage *Uncommon =
140           Storage.dyn_cast<UncommonTemplateNameStorage *>())
141     return Uncommon->getAsSubstTemplateTemplateParmPack();
142
143   return nullptr;
144 }
145
146 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
147   return Storage.dyn_cast<QualifiedTemplateName *>();
148 }
149
150 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
151   return Storage.dyn_cast<DependentTemplateName *>();
152 }
153
154 TemplateName TemplateName::getNameToSubstitute() const {
155   TemplateDecl *Decl = getAsTemplateDecl();
156
157   // Substituting a dependent template name: preserve it as written.
158   if (!Decl)
159     return *this;
160
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");
167   }
168   return TemplateName(Decl);
169 }
170
171 bool TemplateName::isDependent() const {
172   if (TemplateDecl *Template = getAsTemplateDecl()) {
173     if (isa<TemplateTemplateParmDecl>(Template))
174       return true;
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();
181   }
182
183   assert(!getAsOverloadedTemplate() &&
184          "overloaded templates shouldn't survive to here");
185
186   return true;
187 }
188
189 bool TemplateName::isInstantiationDependent() const {
190   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
191     if (QTN->getQualifier()->isInstantiationDependent())
192       return true;
193   }
194
195   return isDependent();
196 }
197
198 bool TemplateName::containsUnexpandedParameterPack() const {
199   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
200     if (QTN->getQualifier()->containsUnexpandedParameterPack())
201       return true;
202   }
203
204   if (TemplateDecl *Template = getAsTemplateDecl()) {
205     if (TemplateTemplateParmDecl *TTP
206                                   = dyn_cast<TemplateTemplateParmDecl>(Template))
207       return TTP->isParameterPack();
208
209     return false;
210   }
211
212   if (DependentTemplateName *DTN = getAsDependentTemplateName())
213     return DTN->getQualifier() &&
214       DTN->getQualifier()->containsUnexpandedParameterPack();
215
216   return getAsSubstTemplateTemplateParmPack() != nullptr;
217 }
218
219 void
220 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
221                     bool SuppressNNS) const {
222   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
223     OS << *Template;
224   else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
225     if (!SuppressNNS)
226       QTN->getQualifier()->print(OS, Policy);
227     if (QTN->hasTemplateKeyword())
228       OS << "template ";
229     OS << *QTN->getDecl();
230   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
231     if (!SuppressNNS && DTN->getQualifier())
232       DTN->getQualifier()->print(OS, Policy);
233     OS << "template ";
234
235     if (DTN->isIdentifier())
236       OS << DTN->getIdentifier()->getName();
237     else
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);
247   } else {
248     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
249     (*OTS->begin())->printName(OS);
250   }
251 }
252
253 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
254                                            TemplateName N) {
255   std::string NameStr;
256   llvm::raw_string_ostream OS(NameStr);
257   LangOptions LO;
258   LO.CPlusPlus = true;
259   LO.Bool = true;
260   OS << '\'';
261   N.print(OS, PrintingPolicy(LO));
262   OS << '\'';
263   OS.flush();
264   return DB << NameStr;
265 }
266
267 const PartialDiagnostic&clang::operator<<(const PartialDiagnostic &PD,
268                                            TemplateName N) {
269   std::string NameStr;
270   llvm::raw_string_ostream OS(NameStr);
271   LangOptions LO;
272   LO.CPlusPlus = true;
273   LO.Bool = true;
274   OS << '\'';
275   N.print(OS, PrintingPolicy(LO));
276   OS << '\'';
277   OS.flush();
278   return PD << NameStr;
279 }
280
281 void TemplateName::dump(raw_ostream &OS) const {
282   LangOptions LO;  // FIXME!
283   LO.CPlusPlus = true;
284   LO.Bool = true;
285   print(OS, PrintingPolicy(LO));
286 }
287
288 LLVM_DUMP_METHOD void TemplateName::dump() const {
289   dump(llvm::errs());
290 }