]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
MFV r337206: 9338 moved dnode has incorrect dn_next_type
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / AST / TemplateName.cpp
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 
35 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
36   return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
37 }
38
39 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
40   Profile(ID, Parameter, Replacement);
41 }
42
43 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, 
44                                            TemplateTemplateParmDecl *parameter,
45                                                TemplateName replacement) {
46   ID.AddPointer(parameter);
47   ID.AddPointer(replacement.getAsVoidPointer());
48 }
49
50 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
51                                                    ASTContext &Context) {
52   Profile(ID, Context, Parameter, getArgumentPack());
53 }
54
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
63 TemplateName::TemplateName(void *Ptr) {
64   Storage = StorageType::getFromOpaqueValue(Ptr);
65 }
66
67 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
68 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
69     : Storage(Storage) {}
70 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
71     : Storage(Storage) {}
72 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
73     : Storage(Storage) {}
74 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
75 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
76
77 bool TemplateName::isNull() const { return Storage.isNull(); }
78
79 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
96 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
109 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 *
118 TemplateName::getAsSubstTemplateTemplateParm() const {
119   if (UncommonTemplateNameStorage *uncommon =
120           Storage.dyn_cast<UncommonTemplateNameStorage *>())
121     return uncommon->getAsSubstTemplateTemplateParm();
122
123   return nullptr;
124 }
125
126 SubstTemplateTemplateParmPackStorage *
127 TemplateName::getAsSubstTemplateTemplateParmPack() const {
128   if (UncommonTemplateNameStorage *Uncommon =
129           Storage.dyn_cast<UncommonTemplateNameStorage *>())
130     return Uncommon->getAsSubstTemplateTemplateParmPack();
131
132   return nullptr;
133 }
134
135 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
136   return Storage.dyn_cast<QualifiedTemplateName *>();
137 }
138
139 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
140   return Storage.dyn_cast<DependentTemplateName *>();
141 }
142
143 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
160 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
178 bool TemplateName::isInstantiationDependent() const {
179   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
180     if (QTN->getQualifier()->isInstantiationDependent())
181       return true;
182   }
183   
184   return isDependent();
185 }
186
187 bool TemplateName::containsUnexpandedParameterPack() const {
188   if (TemplateDecl *Template = getAsTemplateDecl()) {
189     if (TemplateTemplateParmDecl *TTP 
190                                   = dyn_cast<TemplateTemplateParmDecl>(Template))
191       return TTP->isParameterPack();
192
193     return false;
194   }
195
196   if (DependentTemplateName *DTN = getAsDependentTemplateName())
197     return DTN->getQualifier() && 
198       DTN->getQualifier()->containsUnexpandedParameterPack();
199
200   return getAsSubstTemplateTemplateParmPack() != nullptr;
201 }
202
203 void
204 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
205                     bool SuppressNNS) const {
206   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
207     OS << *Template;
208   else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
209     if (!SuppressNNS)
210       QTN->getQualifier()->print(OS, Policy);
211     if (QTN->hasTemplateKeyword())
212       OS << "template ";
213     OS << *QTN->getDecl();
214   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
215     if (!SuppressNNS && DTN->getQualifier())
216       DTN->getQualifier()->print(OS, Policy);
217     OS << "template ";
218     
219     if (DTN->isIdentifier())
220       OS << DTN->getIdentifier()->getName();
221     else
222       OS << "operator " << getOperatorSpelling(DTN->getOperator());
223   } else if (SubstTemplateTemplateParmStorage *subst
224                = getAsSubstTemplateTemplateParm()) {
225     subst->getReplacement().print(OS, Policy, SuppressNNS);
226   } else if (SubstTemplateTemplateParmPackStorage *SubstPack
227                                         = getAsSubstTemplateTemplateParmPack())
228     OS << *SubstPack->getParameterPack();
229   else {
230     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
231     (*OTS->begin())->printName(OS);
232   }
233 }
234
235 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
236                                            TemplateName N) {
237   std::string NameStr;
238   llvm::raw_string_ostream OS(NameStr);
239   LangOptions LO;
240   LO.CPlusPlus = true;
241   LO.Bool = true;
242   OS << '\'';
243   N.print(OS, PrintingPolicy(LO));
244   OS << '\'';
245   OS.flush();
246   return DB << NameStr;
247 }
248
249 void TemplateName::dump(raw_ostream &OS) const {
250   LangOptions LO;  // FIXME!
251   LO.CPlusPlus = true;
252   LO.Bool = true;
253   print(OS, PrintingPolicy(LO));
254 }
255
256 LLVM_DUMP_METHOD void TemplateName::dump() const {
257   dump(llvm::errs());
258 }