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
26 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
27   return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
28 }
29 
30 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
31   Profile(ID, Parameter, Replacement);
32 }
33 
34 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
35                                            TemplateTemplateParmDecl *parameter,
36                                                TemplateName replacement) {
37   ID.AddPointer(parameter);
38   ID.AddPointer(replacement.getAsVoidPointer());
39 }
40 
41 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
42                                                    ASTContext &Context) {
43   Profile(ID, Context, Parameter, getArgumentPack());
44 }
45 
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 
54 TemplateName::TemplateName(void *Ptr) {
55   Storage = StorageType::getFromOpaqueValue(Ptr);
56 }
57 
58 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
59 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
60     : Storage(Storage) {}
61 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
62     : Storage(Storage) {}
63 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
64     : Storage(Storage) {}
65 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
66 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
67 
68 bool TemplateName::isNull() const { return Storage.isNull(); }
69 
70 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 
87 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 
100 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 *
109 TemplateName::getAsSubstTemplateTemplateParm() const {
110   if (UncommonTemplateNameStorage *uncommon =
111           Storage.dyn_cast<UncommonTemplateNameStorage *>())
112     return uncommon->getAsSubstTemplateTemplateParm();
113 
114   return nullptr;
115 }
116 
117 SubstTemplateTemplateParmPackStorage *
118 TemplateName::getAsSubstTemplateTemplateParmPack() const {
119   if (UncommonTemplateNameStorage *Uncommon =
120           Storage.dyn_cast<UncommonTemplateNameStorage *>())
121     return Uncommon->getAsSubstTemplateTemplateParmPack();
122 
123   return nullptr;
124 }
125 
126 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
127   return Storage.dyn_cast<QualifiedTemplateName *>();
128 }
129 
130 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
131   return Storage.dyn_cast<DependentTemplateName *>();
132 }
133 
134 TemplateName TemplateName::getNameToSubstitute() const {
135   TemplateDecl *Decl = getAsTemplateDecl();
136 
137   // Substituting a dependent template name: preserve it as written.
138   if (!Decl)
139     return *this;
140 
141   // If we have a template declaration, use the most recent non-friend
142   // declaration of that template.
143   Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
144   while (Decl->getFriendObjectKind()) {
145     Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
146     assert(Decl && "all declarations of template are friends");
147   }
148   return TemplateName(Decl);
149 }
150 
151 bool TemplateName::isDependent() const {
152   if (TemplateDecl *Template = getAsTemplateDecl()) {
153     if (isa<TemplateTemplateParmDecl>(Template))
154       return true;
155     // FIXME: Hack, getDeclContext() can be null if Template is still
156     // initializing due to PCH reading, so we check it before using it.
157     // Should probably modify TemplateSpecializationType to allow constructing
158     // it without the isDependent() checking.
159     return Template->getDeclContext() &&
160            Template->getDeclContext()->isDependentContext();
161   }
162 
163   assert(!getAsOverloadedTemplate() &&
164          "overloaded templates shouldn't survive to here");
165 
166   return true;
167 }
168 
169 bool TemplateName::isInstantiationDependent() const {
170   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
171     if (QTN->getQualifier()->isInstantiationDependent())
172       return true;
173   }
174 
175   return isDependent();
176 }
177 
178 bool TemplateName::containsUnexpandedParameterPack() const {
179   if (TemplateDecl *Template = getAsTemplateDecl()) {
180     if (TemplateTemplateParmDecl *TTP
181                                   = dyn_cast<TemplateTemplateParmDecl>(Template))
182       return TTP->isParameterPack();
183 
184     return false;
185   }
186 
187   if (DependentTemplateName *DTN = getAsDependentTemplateName())
188     return DTN->getQualifier() &&
189       DTN->getQualifier()->containsUnexpandedParameterPack();
190 
191   return getAsSubstTemplateTemplateParmPack() != nullptr;
192 }
193 
194 void
195 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
196                     bool SuppressNNS) const {
197   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
198     OS << *Template;
199   else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
200     if (!SuppressNNS)
201       QTN->getQualifier()->print(OS, Policy);
202     if (QTN->hasTemplateKeyword())
203       OS << "template ";
204     OS << *QTN->getDecl();
205   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
206     if (!SuppressNNS && DTN->getQualifier())
207       DTN->getQualifier()->print(OS, Policy);
208     OS << "template ";
209 
210     if (DTN->isIdentifier())
211       OS << DTN->getIdentifier()->getName();
212     else
213       OS << "operator " << getOperatorSpelling(DTN->getOperator());
214   } else if (SubstTemplateTemplateParmStorage *subst
215                = getAsSubstTemplateTemplateParm()) {
216     subst->getReplacement().print(OS, Policy, SuppressNNS);
217   } else if (SubstTemplateTemplateParmPackStorage *SubstPack
218                                         = getAsSubstTemplateTemplateParmPack())
219     OS << *SubstPack->getParameterPack();
220   else {
221     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
222     (*OTS->begin())->printName(OS);
223   }
224 }
225 
226 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
227                                            TemplateName N) {
228   std::string NameStr;
229   raw_string_ostream OS(NameStr);
230   LangOptions LO;
231   LO.CPlusPlus = true;
232   LO.Bool = true;
233   OS << '\'';
234   N.print(OS, PrintingPolicy(LO));
235   OS << '\'';
236   OS.flush();
237   return DB << NameStr;
238 }
239 
240 void TemplateName::dump(raw_ostream &OS) const {
241   LangOptions LO;  // FIXME!
242   LO.CPlusPlus = true;
243   LO.Bool = true;
244   print(OS, PrintingPolicy(LO));
245 }
246 
247 LLVM_DUMP_METHOD void TemplateName::dump() const {
248   dump(llvm::errs());
249 }
250