1 //===- TemplateName.cpp - C++ Template Name Representation ----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the TemplateName interface and subclasses.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/AST/TemplateName.h"
15 #include "clang/AST/DeclBase.h"
16 #include "clang/AST/DeclTemplate.h"
17 #include "clang/AST/NestedNameSpecifier.h"
18 #include "clang/AST/PrettyPrinter.h"
19 #include "clang/AST/TemplateBase.h"
20 #include "clang/Basic/Diagnostic.h"
21 #include "clang/Basic/LLVM.h"
22 #include "clang/Basic/LangOptions.h"
23 #include "clang/Basic/OperatorKinds.h"
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/FoldingSet.h"
26 #include "llvm/Support/Casting.h"
27 #include "llvm/Support/Compiler.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include <cassert>
30 #include <string>
31
32 using namespace clang;
33
34 TemplateArgument
getArgumentPack() const35 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
36 return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
37 }
38
Profile(llvm::FoldingSetNodeID & ID)39 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
40 Profile(ID, Parameter, Replacement);
41 }
42
Profile(llvm::FoldingSetNodeID & ID,TemplateTemplateParmDecl * parameter,TemplateName replacement)43 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
44 TemplateTemplateParmDecl *parameter,
45 TemplateName replacement) {
46 ID.AddPointer(parameter);
47 ID.AddPointer(replacement.getAsVoidPointer());
48 }
49
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context)50 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
51 ASTContext &Context) {
52 Profile(ID, Context, Parameter, getArgumentPack());
53 }
54
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context,TemplateTemplateParmDecl * Parameter,const TemplateArgument & ArgPack)55 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
56 ASTContext &Context,
57 TemplateTemplateParmDecl *Parameter,
58 const TemplateArgument &ArgPack) {
59 ID.AddPointer(Parameter);
60 ArgPack.Profile(ID, Context);
61 }
62
TemplateName(void * Ptr)63 TemplateName::TemplateName(void *Ptr) {
64 Storage = StorageType::getFromOpaqueValue(Ptr);
65 }
66
TemplateName(TemplateDecl * Template)67 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
TemplateName(OverloadedTemplateStorage * Storage)68 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
69 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmStorage * Storage)70 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
71 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmPackStorage * Storage)72 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
73 : Storage(Storage) {}
TemplateName(QualifiedTemplateName * Qual)74 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
TemplateName(DependentTemplateName * Dep)75 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
76
isNull() const77 bool TemplateName::isNull() const { return Storage.isNull(); }
78
getKind() const79 TemplateName::NameKind TemplateName::getKind() const {
80 if (Storage.is<TemplateDecl *>())
81 return Template;
82 if (Storage.is<DependentTemplateName *>())
83 return DependentTemplate;
84 if (Storage.is<QualifiedTemplateName *>())
85 return QualifiedTemplate;
86
87 UncommonTemplateNameStorage *uncommon
88 = Storage.get<UncommonTemplateNameStorage*>();
89 if (uncommon->getAsOverloadedStorage())
90 return OverloadedTemplate;
91 if (uncommon->getAsSubstTemplateTemplateParm())
92 return SubstTemplateTemplateParm;
93 return SubstTemplateTemplateParmPack;
94 }
95
getAsTemplateDecl() const96 TemplateDecl *TemplateName::getAsTemplateDecl() const {
97 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
98 return Template;
99
100 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
101 return QTN->getTemplateDecl();
102
103 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
104 return sub->getReplacement().getAsTemplateDecl();
105
106 return nullptr;
107 }
108
getAsOverloadedTemplate() const109 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
110 if (UncommonTemplateNameStorage *Uncommon =
111 Storage.dyn_cast<UncommonTemplateNameStorage *>())
112 return Uncommon->getAsOverloadedStorage();
113
114 return nullptr;
115 }
116
117 SubstTemplateTemplateParmStorage *
getAsSubstTemplateTemplateParm() const118 TemplateName::getAsSubstTemplateTemplateParm() const {
119 if (UncommonTemplateNameStorage *uncommon =
120 Storage.dyn_cast<UncommonTemplateNameStorage *>())
121 return uncommon->getAsSubstTemplateTemplateParm();
122
123 return nullptr;
124 }
125
126 SubstTemplateTemplateParmPackStorage *
getAsSubstTemplateTemplateParmPack() const127 TemplateName::getAsSubstTemplateTemplateParmPack() const {
128 if (UncommonTemplateNameStorage *Uncommon =
129 Storage.dyn_cast<UncommonTemplateNameStorage *>())
130 return Uncommon->getAsSubstTemplateTemplateParmPack();
131
132 return nullptr;
133 }
134
getAsQualifiedTemplateName() const135 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
136 return Storage.dyn_cast<QualifiedTemplateName *>();
137 }
138
getAsDependentTemplateName() const139 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
140 return Storage.dyn_cast<DependentTemplateName *>();
141 }
142
getNameToSubstitute() const143 TemplateName TemplateName::getNameToSubstitute() const {
144 TemplateDecl *Decl = getAsTemplateDecl();
145
146 // Substituting a dependent template name: preserve it as written.
147 if (!Decl)
148 return *this;
149
150 // If we have a template declaration, use the most recent non-friend
151 // declaration of that template.
152 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
153 while (Decl->getFriendObjectKind()) {
154 Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
155 assert(Decl && "all declarations of template are friends");
156 }
157 return TemplateName(Decl);
158 }
159
isDependent() const160 bool TemplateName::isDependent() const {
161 if (TemplateDecl *Template = getAsTemplateDecl()) {
162 if (isa<TemplateTemplateParmDecl>(Template))
163 return true;
164 // FIXME: Hack, getDeclContext() can be null if Template is still
165 // initializing due to PCH reading, so we check it before using it.
166 // Should probably modify TemplateSpecializationType to allow constructing
167 // it without the isDependent() checking.
168 return Template->getDeclContext() &&
169 Template->getDeclContext()->isDependentContext();
170 }
171
172 assert(!getAsOverloadedTemplate() &&
173 "overloaded templates shouldn't survive to here");
174
175 return true;
176 }
177
isInstantiationDependent() const178 bool TemplateName::isInstantiationDependent() const {
179 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
180 if (QTN->getQualifier()->isInstantiationDependent())
181 return true;
182 }
183
184 return isDependent();
185 }
186
containsUnexpandedParameterPack() const187 bool TemplateName::containsUnexpandedParameterPack() const {
188 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
189 if (QTN->getQualifier()->containsUnexpandedParameterPack())
190 return true;
191 }
192
193 if (TemplateDecl *Template = getAsTemplateDecl()) {
194 if (TemplateTemplateParmDecl *TTP
195 = dyn_cast<TemplateTemplateParmDecl>(Template))
196 return TTP->isParameterPack();
197
198 return false;
199 }
200
201 if (DependentTemplateName *DTN = getAsDependentTemplateName())
202 return DTN->getQualifier() &&
203 DTN->getQualifier()->containsUnexpandedParameterPack();
204
205 return getAsSubstTemplateTemplateParmPack() != nullptr;
206 }
207
208 void
print(raw_ostream & OS,const PrintingPolicy & Policy,bool SuppressNNS) const209 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
210 bool SuppressNNS) const {
211 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
212 OS << *Template;
213 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
214 if (!SuppressNNS)
215 QTN->getQualifier()->print(OS, Policy);
216 if (QTN->hasTemplateKeyword())
217 OS << "template ";
218 OS << *QTN->getDecl();
219 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
220 if (!SuppressNNS && DTN->getQualifier())
221 DTN->getQualifier()->print(OS, Policy);
222 OS << "template ";
223
224 if (DTN->isIdentifier())
225 OS << DTN->getIdentifier()->getName();
226 else
227 OS << "operator " << getOperatorSpelling(DTN->getOperator());
228 } else if (SubstTemplateTemplateParmStorage *subst
229 = getAsSubstTemplateTemplateParm()) {
230 subst->getReplacement().print(OS, Policy, SuppressNNS);
231 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
232 = getAsSubstTemplateTemplateParmPack())
233 OS << *SubstPack->getParameterPack();
234 else {
235 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
236 (*OTS->begin())->printName(OS);
237 }
238 }
239
operator <<(const DiagnosticBuilder & DB,TemplateName N)240 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
241 TemplateName N) {
242 std::string NameStr;
243 llvm::raw_string_ostream OS(NameStr);
244 LangOptions LO;
245 LO.CPlusPlus = true;
246 LO.Bool = true;
247 OS << '\'';
248 N.print(OS, PrintingPolicy(LO));
249 OS << '\'';
250 OS.flush();
251 return DB << NameStr;
252 }
253
dump(raw_ostream & OS) const254 void TemplateName::dump(raw_ostream &OS) const {
255 LangOptions LO; // FIXME!
256 LO.CPlusPlus = true;
257 LO.Bool = true;
258 print(OS, PrintingPolicy(LO));
259 }
260
dump() const261 LLVM_DUMP_METHOD void TemplateName::dump() const {
262 dump(llvm::errs());
263 }
264