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/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/LangOptions.h"
21 #include "llvm/Support/raw_ostream.h"
22 using namespace clang;
23 using namespace llvm;
24
25 TemplateArgument
getArgumentPack() const26 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
27 return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
28 }
29
Profile(llvm::FoldingSetNodeID & ID)30 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
31 Profile(ID, Parameter, Replacement);
32 }
33
Profile(llvm::FoldingSetNodeID & ID,TemplateTemplateParmDecl * parameter,TemplateName replacement)34 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
35 TemplateTemplateParmDecl *parameter,
36 TemplateName replacement) {
37 ID.AddPointer(parameter);
38 ID.AddPointer(replacement.getAsVoidPointer());
39 }
40
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context)41 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
42 ASTContext &Context) {
43 Profile(ID, Context, Parameter, getArgumentPack());
44 }
45
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context,TemplateTemplateParmDecl * Parameter,const TemplateArgument & ArgPack)46 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
47 ASTContext &Context,
48 TemplateTemplateParmDecl *Parameter,
49 const TemplateArgument &ArgPack) {
50 ID.AddPointer(Parameter);
51 ArgPack.Profile(ID, Context);
52 }
53
TemplateName(void * Ptr)54 TemplateName::TemplateName(void *Ptr) {
55 Storage = StorageType::getFromOpaqueValue(Ptr);
56 }
57
TemplateName(TemplateDecl * Template)58 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
TemplateName(OverloadedTemplateStorage * Storage)59 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
60 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmStorage * Storage)61 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
62 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmPackStorage * Storage)63 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
64 : Storage(Storage) {}
TemplateName(QualifiedTemplateName * Qual)65 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
TemplateName(DependentTemplateName * Dep)66 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
67
isNull() const68 bool TemplateName::isNull() const { return Storage.isNull(); }
69
getKind() const70 TemplateName::NameKind TemplateName::getKind() const {
71 if (Storage.is<TemplateDecl *>())
72 return Template;
73 if (Storage.is<DependentTemplateName *>())
74 return DependentTemplate;
75 if (Storage.is<QualifiedTemplateName *>())
76 return QualifiedTemplate;
77
78 UncommonTemplateNameStorage *uncommon
79 = Storage.get<UncommonTemplateNameStorage*>();
80 if (uncommon->getAsOverloadedStorage())
81 return OverloadedTemplate;
82 if (uncommon->getAsSubstTemplateTemplateParm())
83 return SubstTemplateTemplateParm;
84 return SubstTemplateTemplateParmPack;
85 }
86
getAsTemplateDecl() const87 TemplateDecl *TemplateName::getAsTemplateDecl() const {
88 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
89 return Template;
90
91 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
92 return QTN->getTemplateDecl();
93
94 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
95 return sub->getReplacement().getAsTemplateDecl();
96
97 return nullptr;
98 }
99
getAsOverloadedTemplate() const100 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
101 if (UncommonTemplateNameStorage *Uncommon =
102 Storage.dyn_cast<UncommonTemplateNameStorage *>())
103 return Uncommon->getAsOverloadedStorage();
104
105 return nullptr;
106 }
107
108 SubstTemplateTemplateParmStorage *
getAsSubstTemplateTemplateParm() const109 TemplateName::getAsSubstTemplateTemplateParm() const {
110 if (UncommonTemplateNameStorage *uncommon =
111 Storage.dyn_cast<UncommonTemplateNameStorage *>())
112 return uncommon->getAsSubstTemplateTemplateParm();
113
114 return nullptr;
115 }
116
117 SubstTemplateTemplateParmPackStorage *
getAsSubstTemplateTemplateParmPack() const118 TemplateName::getAsSubstTemplateTemplateParmPack() const {
119 if (UncommonTemplateNameStorage *Uncommon =
120 Storage.dyn_cast<UncommonTemplateNameStorage *>())
121 return Uncommon->getAsSubstTemplateTemplateParmPack();
122
123 return nullptr;
124 }
125
getAsQualifiedTemplateName() const126 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
127 return Storage.dyn_cast<QualifiedTemplateName *>();
128 }
129
getAsDependentTemplateName() const130 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
131 return Storage.dyn_cast<DependentTemplateName *>();
132 }
133
isDependent() const134 bool TemplateName::isDependent() const {
135 if (TemplateDecl *Template = getAsTemplateDecl()) {
136 if (isa<TemplateTemplateParmDecl>(Template))
137 return true;
138 // FIXME: Hack, getDeclContext() can be null if Template is still
139 // initializing due to PCH reading, so we check it before using it.
140 // Should probably modify TemplateSpecializationType to allow constructing
141 // it without the isDependent() checking.
142 return Template->getDeclContext() &&
143 Template->getDeclContext()->isDependentContext();
144 }
145
146 assert(!getAsOverloadedTemplate() &&
147 "overloaded templates shouldn't survive to here");
148
149 return true;
150 }
151
isInstantiationDependent() const152 bool TemplateName::isInstantiationDependent() const {
153 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
154 if (QTN->getQualifier()->isInstantiationDependent())
155 return true;
156 }
157
158 return isDependent();
159 }
160
containsUnexpandedParameterPack() const161 bool TemplateName::containsUnexpandedParameterPack() const {
162 if (TemplateDecl *Template = getAsTemplateDecl()) {
163 if (TemplateTemplateParmDecl *TTP
164 = dyn_cast<TemplateTemplateParmDecl>(Template))
165 return TTP->isParameterPack();
166
167 return false;
168 }
169
170 if (DependentTemplateName *DTN = getAsDependentTemplateName())
171 return DTN->getQualifier() &&
172 DTN->getQualifier()->containsUnexpandedParameterPack();
173
174 return getAsSubstTemplateTemplateParmPack() != nullptr;
175 }
176
177 void
print(raw_ostream & OS,const PrintingPolicy & Policy,bool SuppressNNS) const178 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
179 bool SuppressNNS) const {
180 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
181 OS << *Template;
182 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
183 if (!SuppressNNS)
184 QTN->getQualifier()->print(OS, Policy);
185 if (QTN->hasTemplateKeyword())
186 OS << "template ";
187 OS << *QTN->getDecl();
188 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
189 if (!SuppressNNS && DTN->getQualifier())
190 DTN->getQualifier()->print(OS, Policy);
191 OS << "template ";
192
193 if (DTN->isIdentifier())
194 OS << DTN->getIdentifier()->getName();
195 else
196 OS << "operator " << getOperatorSpelling(DTN->getOperator());
197 } else if (SubstTemplateTemplateParmStorage *subst
198 = getAsSubstTemplateTemplateParm()) {
199 subst->getReplacement().print(OS, Policy, SuppressNNS);
200 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
201 = getAsSubstTemplateTemplateParmPack())
202 OS << *SubstPack->getParameterPack();
203 else {
204 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
205 (*OTS->begin())->printName(OS);
206 }
207 }
208
operator <<(const DiagnosticBuilder & DB,TemplateName N)209 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
210 TemplateName N) {
211 std::string NameStr;
212 raw_string_ostream OS(NameStr);
213 LangOptions LO;
214 LO.CPlusPlus = true;
215 LO.Bool = true;
216 OS << '\'';
217 N.print(OS, PrintingPolicy(LO));
218 OS << '\'';
219 OS.flush();
220 return DB << NameStr;
221 }
222
dump(raw_ostream & OS) const223 void TemplateName::dump(raw_ostream &OS) const {
224 LangOptions LO; // FIXME!
225 LO.CPlusPlus = true;
226 LO.Bool = true;
227 print(OS, PrintingPolicy(LO));
228 }
229
dump() const230 LLVM_DUMP_METHOD void TemplateName::dump() const {
231 dump(llvm::errs());
232 }
233