1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_AST_TEMPLATENAME_H |
14 | #define LLVM_CLANG_AST_TEMPLATENAME_H |
15 | |
16 | #include "clang/AST/NestedNameSpecifier.h" |
17 | #include "clang/Basic/LLVM.h" |
18 | #include "llvm/ADT/FoldingSet.h" |
19 | #include "llvm/ADT/PointerIntPair.h" |
20 | #include "llvm/ADT/PointerUnion.h" |
21 | #include "llvm/Support/PointerLikeTypeTraits.h" |
22 | #include <cassert> |
23 | |
24 | namespace clang { |
25 | |
26 | class ASTContext; |
27 | class DependentTemplateName; |
28 | class DiagnosticBuilder; |
29 | class IdentifierInfo; |
30 | class NamedDecl; |
31 | class NestedNameSpecifier; |
32 | enum OverloadedOperatorKind : int; |
33 | class OverloadedTemplateStorage; |
34 | struct PrintingPolicy; |
35 | class QualifiedTemplateName; |
36 | class SubstTemplateTemplateParmPackStorage; |
37 | class SubstTemplateTemplateParmStorage; |
38 | class TemplateArgument; |
39 | class TemplateDecl; |
40 | class TemplateTemplateParmDecl; |
41 | |
42 | |
43 | |
44 | class UncommonTemplateNameStorage { |
45 | protected: |
46 | enum Kind { |
47 | Overloaded, |
48 | SubstTemplateTemplateParm, |
49 | SubstTemplateTemplateParmPack |
50 | }; |
51 | |
52 | struct BitsTag { |
53 | |
54 | unsigned Kind : 2; |
55 | |
56 | |
57 | |
58 | unsigned Size : 30; |
59 | }; |
60 | |
61 | union { |
62 | struct BitsTag Bits; |
63 | void *PointerAlignment; |
64 | }; |
65 | |
66 | UncommonTemplateNameStorage(Kind kind, unsigned size) { |
67 | Bits.Kind = kind; |
68 | Bits.Size = size; |
69 | } |
70 | |
71 | public: |
72 | unsigned size() const { return Bits.Size; } |
73 | |
74 | OverloadedTemplateStorage *getAsOverloadedStorage() { |
75 | return Bits.Kind == Overloaded |
76 | ? reinterpret_cast<OverloadedTemplateStorage *>(this) |
77 | : nullptr; |
78 | } |
79 | |
80 | SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() { |
81 | return Bits.Kind == SubstTemplateTemplateParm |
82 | ? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this) |
83 | : nullptr; |
84 | } |
85 | |
86 | SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() { |
87 | return Bits.Kind == SubstTemplateTemplateParmPack |
88 | ? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) |
89 | : nullptr; |
90 | } |
91 | }; |
92 | |
93 | |
94 | |
95 | class OverloadedTemplateStorage : public UncommonTemplateNameStorage { |
96 | friend class ASTContext; |
97 | |
98 | OverloadedTemplateStorage(unsigned size) |
99 | : UncommonTemplateNameStorage(Overloaded, size) {} |
100 | |
101 | NamedDecl **getStorage() { |
102 | return reinterpret_cast<NamedDecl **>(this + 1); |
103 | } |
104 | NamedDecl * const *getStorage() const { |
105 | return reinterpret_cast<NamedDecl *const *>(this + 1); |
106 | } |
107 | |
108 | public: |
109 | using iterator = NamedDecl *const *; |
110 | |
111 | iterator begin() const { return getStorage(); } |
112 | iterator end() const { return getStorage() + size(); } |
113 | }; |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | class SubstTemplateTemplateParmPackStorage |
122 | : public UncommonTemplateNameStorage, public llvm::FoldingSetNode |
123 | { |
124 | TemplateTemplateParmDecl *Parameter; |
125 | const TemplateArgument *Arguments; |
126 | |
127 | public: |
128 | SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter, |
129 | unsigned Size, |
130 | const TemplateArgument *Arguments) |
131 | : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), |
132 | Parameter(Parameter), Arguments(Arguments) {} |
133 | |
134 | |
135 | TemplateTemplateParmDecl *getParameterPack() const { |
136 | return Parameter; |
137 | } |
138 | |
139 | |
140 | |
141 | TemplateArgument getArgumentPack() const; |
142 | |
143 | void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context); |
144 | |
145 | static void Profile(llvm::FoldingSetNodeID &ID, |
146 | ASTContext &Context, |
147 | TemplateTemplateParmDecl *Parameter, |
148 | const TemplateArgument &ArgPack); |
149 | }; |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | class TemplateName { |
179 | using StorageType = |
180 | llvm::PointerUnion4<TemplateDecl *, UncommonTemplateNameStorage *, |
181 | QualifiedTemplateName *, DependentTemplateName *>; |
182 | |
183 | StorageType Storage; |
184 | |
185 | explicit TemplateName(void *Ptr); |
186 | |
187 | public: |
188 | |
189 | enum NameKind { |
190 | |
191 | Template, |
192 | |
193 | |
194 | OverloadedTemplate, |
195 | |
196 | |
197 | |
198 | QualifiedTemplate, |
199 | |
200 | |
201 | |
202 | DependentTemplate, |
203 | |
204 | |
205 | |
206 | SubstTemplateTemplateParm, |
207 | |
208 | |
209 | |
210 | |
211 | SubstTemplateTemplateParmPack |
212 | }; |
213 | |
214 | TemplateName() = default; |
215 | explicit TemplateName(TemplateDecl *Template); |
216 | explicit TemplateName(OverloadedTemplateStorage *Storage); |
217 | explicit TemplateName(SubstTemplateTemplateParmStorage *Storage); |
218 | explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage); |
219 | explicit TemplateName(QualifiedTemplateName *Qual); |
220 | explicit TemplateName(DependentTemplateName *Dep); |
221 | |
222 | |
223 | bool isNull() const; |
224 | |
225 | |
226 | NameKind getKind() const; |
227 | |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | TemplateDecl *getAsTemplateDecl() const; |
236 | |
237 | |
238 | |
239 | |
240 | |
241 | |
242 | |
243 | |
244 | OverloadedTemplateStorage *getAsOverloadedTemplate() const; |
245 | |
246 | |
247 | |
248 | |
249 | |
250 | |
251 | SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const; |
252 | |
253 | |
254 | |
255 | |
256 | |
257 | |
258 | SubstTemplateTemplateParmPackStorage * |
259 | getAsSubstTemplateTemplateParmPack() const; |
260 | |
261 | |
262 | |
263 | QualifiedTemplateName *getAsQualifiedTemplateName() const; |
264 | |
265 | |
266 | |
267 | DependentTemplateName *getAsDependentTemplateName() const; |
268 | |
269 | TemplateName getUnderlying() const; |
270 | |
271 | |
272 | |
273 | |
274 | TemplateName getNameToSubstitute() const; |
275 | |
276 | |
277 | bool isDependent() const; |
278 | |
279 | |
280 | |
281 | bool isInstantiationDependent() const; |
282 | |
283 | |
284 | |
285 | bool containsUnexpandedParameterPack() const; |
286 | |
287 | |
288 | |
289 | |
290 | |
291 | |
292 | |
293 | |
294 | |
295 | void print(raw_ostream &OS, const PrintingPolicy &Policy, |
296 | bool SuppressNNS = false) const; |
297 | |
298 | |
299 | void dump(raw_ostream &OS) const; |
300 | |
301 | |
302 | |
303 | void dump() const; |
304 | |
305 | void Profile(llvm::FoldingSetNodeID &ID) { |
306 | ID.AddPointer(Storage.getOpaqueValue()); |
307 | } |
308 | |
309 | |
310 | void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } |
311 | |
312 | |
313 | static TemplateName getFromVoidPointer(void *Ptr) { |
314 | return TemplateName(Ptr); |
315 | } |
316 | }; |
317 | |
318 | |
319 | |
320 | const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
321 | TemplateName N); |
322 | |
323 | |
324 | |
325 | class SubstTemplateTemplateParmStorage |
326 | : public UncommonTemplateNameStorage, public llvm::FoldingSetNode { |
327 | friend class ASTContext; |
328 | |
329 | TemplateTemplateParmDecl *Parameter; |
330 | TemplateName Replacement; |
331 | |
332 | SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter, |
333 | TemplateName replacement) |
334 | : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0), |
335 | Parameter(parameter), Replacement(replacement) {} |
336 | |
337 | public: |
338 | TemplateTemplateParmDecl *getParameter() const { return Parameter; } |
339 | TemplateName getReplacement() const { return Replacement; } |
340 | |
341 | void Profile(llvm::FoldingSetNodeID &ID); |
342 | |
343 | static void Profile(llvm::FoldingSetNodeID &ID, |
344 | TemplateTemplateParmDecl *parameter, |
345 | TemplateName replacement); |
346 | }; |
347 | |
348 | inline TemplateName TemplateName::getUnderlying() const { |
349 | if (SubstTemplateTemplateParmStorage *subst |
350 | = getAsSubstTemplateTemplateParm()) |
351 | return subst->getReplacement().getUnderlying(); |
352 | return *this; |
353 | } |
354 | |
355 | |
356 | |
357 | |
358 | |
359 | |
360 | |
361 | |
362 | |
363 | |
364 | |
365 | |
366 | class QualifiedTemplateName : public llvm::FoldingSetNode { |
367 | friend class ASTContext; |
368 | |
369 | |
370 | |
371 | |
372 | |
373 | |
374 | |
375 | |
376 | llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier; |
377 | |
378 | |
379 | |
380 | TemplateDecl *Template; |
381 | |
382 | QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, |
383 | TemplateDecl *Template) |
384 | : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {} |
385 | |
386 | public: |
387 | |
388 | NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } |
389 | |
390 | |
391 | |
392 | bool hasTemplateKeyword() const { return Qualifier.getInt(); } |
393 | |
394 | |
395 | |
396 | TemplateDecl *getDecl() const { return Template; } |
397 | |
398 | |
399 | |
400 | TemplateDecl *getTemplateDecl() const { return Template; } |
401 | |
402 | void Profile(llvm::FoldingSetNodeID &ID) { |
403 | Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl()); |
404 | } |
405 | |
406 | static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, |
407 | bool TemplateKeyword, TemplateDecl *Template) { |
408 | ID.AddPointer(NNS); |
409 | ID.AddBoolean(TemplateKeyword); |
410 | ID.AddPointer(Template); |
411 | } |
412 | }; |
413 | |
414 | |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | |
422 | class DependentTemplateName : public llvm::FoldingSetNode { |
423 | friend class ASTContext; |
424 | |
425 | |
426 | |
427 | |
428 | |
429 | |
430 | |
431 | llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier; |
432 | |
433 | |
434 | union { |
435 | |
436 | |
437 | |
438 | const IdentifierInfo *Identifier; |
439 | |
440 | |
441 | |
442 | |
443 | OverloadedOperatorKind Operator; |
444 | }; |
445 | |
446 | |
447 | |
448 | |
449 | |
450 | |
451 | |
452 | TemplateName CanonicalTemplateName; |
453 | |
454 | DependentTemplateName(NestedNameSpecifier *Qualifier, |
455 | const IdentifierInfo *Identifier) |
456 | : Qualifier(Qualifier, false), Identifier(Identifier), |
457 | CanonicalTemplateName(this) {} |
458 | |
459 | DependentTemplateName(NestedNameSpecifier *Qualifier, |
460 | const IdentifierInfo *Identifier, |
461 | TemplateName Canon) |
462 | : Qualifier(Qualifier, false), Identifier(Identifier), |
463 | CanonicalTemplateName(Canon) {} |
464 | |
465 | DependentTemplateName(NestedNameSpecifier *Qualifier, |
466 | OverloadedOperatorKind Operator) |
467 | : Qualifier(Qualifier, true), Operator(Operator), |
468 | CanonicalTemplateName(this) {} |
469 | |
470 | DependentTemplateName(NestedNameSpecifier *Qualifier, |
471 | OverloadedOperatorKind Operator, |
472 | TemplateName Canon) |
473 | : Qualifier(Qualifier, true), Operator(Operator), |
474 | CanonicalTemplateName(Canon) {} |
475 | |
476 | public: |
477 | |
478 | NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } |
479 | |
480 | |
481 | bool isIdentifier() const { return !Qualifier.getInt(); } |
482 | |
483 | |
484 | const IdentifierInfo *getIdentifier() const { |
485 | (0) . __assert_fail ("isIdentifier() && \"Template name isn't an identifier?\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/TemplateName.h", 485, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIdentifier() && "Template name isn't an identifier?"); |
486 | return Identifier; |
487 | } |
488 | |
489 | |
490 | |
491 | bool isOverloadedOperator() const { return Qualifier.getInt(); } |
492 | |
493 | |
494 | OverloadedOperatorKind getOperator() const { |
495 | (0) . __assert_fail ("isOverloadedOperator() && \"Template name isn't an overloaded operator?\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/TemplateName.h", 496, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isOverloadedOperator() && |
496 | (0) . __assert_fail ("isOverloadedOperator() && \"Template name isn't an overloaded operator?\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/TemplateName.h", 496, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Template name isn't an overloaded operator?"); |
497 | return Operator; |
498 | } |
499 | |
500 | void Profile(llvm::FoldingSetNodeID &ID) { |
501 | if (isIdentifier()) |
502 | Profile(ID, getQualifier(), getIdentifier()); |
503 | else |
504 | Profile(ID, getQualifier(), getOperator()); |
505 | } |
506 | |
507 | static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, |
508 | const IdentifierInfo *Identifier) { |
509 | ID.AddPointer(NNS); |
510 | ID.AddBoolean(false); |
511 | ID.AddPointer(Identifier); |
512 | } |
513 | |
514 | static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, |
515 | OverloadedOperatorKind Operator) { |
516 | ID.AddPointer(NNS); |
517 | ID.AddBoolean(true); |
518 | ID.AddInteger(Operator); |
519 | } |
520 | }; |
521 | |
522 | } |
523 | |
524 | namespace llvm { |
525 | |
526 | |
527 | template<> |
528 | struct PointerLikeTypeTraits<clang::TemplateName> { |
529 | static inline void *getAsVoidPointer(clang::TemplateName TN) { |
530 | return TN.getAsVoidPointer(); |
531 | } |
532 | |
533 | static inline clang::TemplateName getFromVoidPointer(void *Ptr) { |
534 | return clang::TemplateName::getFromVoidPointer(Ptr); |
535 | } |
536 | |
537 | |
538 | enum { NumLowBitsAvailable = 0 }; |
539 | }; |
540 | |
541 | } |
542 | |
543 | #endif |
544 | |