• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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