]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
Merge clang 7.0.1 and several follow-up changes
[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 (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
209 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
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
254 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
261 LLVM_DUMP_METHOD void TemplateName::dump() const {
262   dump(llvm::errs());
263 }