1 | //===- TemplateBase.h - Core classes for C++ templates ----------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file provides definitions which are common for all kinds of |
10 | // template representation. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H |
15 | #define LLVM_CLANG_AST_TEMPLATEBASE_H |
16 | |
17 | #include "clang/AST/DependenceFlags.h" |
18 | #include "clang/AST/NestedNameSpecifier.h" |
19 | #include "clang/AST/TemplateName.h" |
20 | #include "clang/AST/Type.h" |
21 | #include "clang/Basic/LLVM.h" |
22 | #include "clang/Basic/SourceLocation.h" |
23 | #include "llvm/ADT/APInt.h" |
24 | #include "llvm/ADT/APSInt.h" |
25 | #include "llvm/ADT/ArrayRef.h" |
26 | #include "llvm/ADT/SmallVector.h" |
27 | #include "llvm/Support/Compiler.h" |
28 | #include "llvm/Support/TrailingObjects.h" |
29 | #include <cassert> |
30 | #include <cstddef> |
31 | #include <cstdint> |
32 | #include <optional> |
33 | |
34 | namespace llvm { |
35 | |
36 | class FoldingSetNodeID; |
37 | |
38 | // Provide PointerLikeTypeTraits for clang::Expr*, this default one requires a |
39 | // full definition of Expr, but this file only sees a forward del because of |
40 | // the dependency. |
41 | template <> struct PointerLikeTypeTraits<clang::Expr *> { |
42 | static inline void *getAsVoidPointer(clang::Expr *P) { return P; } |
43 | static inline clang::Expr *getFromVoidPointer(void *P) { |
44 | return static_cast<clang::Expr *>(P); |
45 | } |
46 | static constexpr int NumLowBitsAvailable = 2; |
47 | }; |
48 | |
49 | } // namespace llvm |
50 | |
51 | namespace clang { |
52 | |
53 | class APValue; |
54 | class ASTContext; |
55 | class Expr; |
56 | struct PrintingPolicy; |
57 | class TypeSourceInfo; |
58 | class ValueDecl; |
59 | |
60 | /// Represents a template argument. |
61 | class TemplateArgument { |
62 | public: |
63 | /// The kind of template argument we're storing. |
64 | enum ArgKind { |
65 | /// Represents an empty template argument, e.g., one that has not |
66 | /// been deduced. |
67 | Null = 0, |
68 | |
69 | /// The template argument is a type. |
70 | Type, |
71 | |
72 | /// The template argument is a declaration that was provided for a pointer, |
73 | /// reference, or pointer to member non-type template parameter. |
74 | Declaration, |
75 | |
76 | /// The template argument is a null pointer or null pointer to member that |
77 | /// was provided for a non-type template parameter. |
78 | NullPtr, |
79 | |
80 | /// The template argument is an integral value stored in an llvm::APSInt |
81 | /// that was provided for an integral non-type template parameter. |
82 | Integral, |
83 | |
84 | /// The template argument is a non-type template argument that can't be |
85 | /// represented by the special-case Declaration, NullPtr, or Integral |
86 | /// forms. These values are only ever produced by constant evaluation, |
87 | /// so cannot be dependent. |
88 | /// TODO: merge Declaration, NullPtr and Integral into this? |
89 | StructuralValue, |
90 | |
91 | /// The template argument is a template name that was provided for a |
92 | /// template template parameter. |
93 | Template, |
94 | |
95 | /// The template argument is a pack expansion of a template name that was |
96 | /// provided for a template template parameter. |
97 | TemplateExpansion, |
98 | |
99 | /// The template argument is an expression, and we've not resolved it to one |
100 | /// of the other forms yet, either because it's dependent or because we're |
101 | /// representing a non-canonical template argument (for instance, in a |
102 | /// TemplateSpecializationType). |
103 | Expression, |
104 | |
105 | /// The template argument is actually a parameter pack. Arguments are stored |
106 | /// in the Args struct. |
107 | Pack |
108 | }; |
109 | |
110 | private: |
111 | /// The kind of template argument we're storing. |
112 | |
113 | struct DA { |
114 | LLVM_PREFERRED_TYPE(ArgKind) |
115 | unsigned Kind : 31; |
116 | LLVM_PREFERRED_TYPE(bool) |
117 | unsigned IsDefaulted : 1; |
118 | void *QT; |
119 | ValueDecl *D; |
120 | }; |
121 | struct I { |
122 | LLVM_PREFERRED_TYPE(ArgKind) |
123 | unsigned Kind : 31; |
124 | LLVM_PREFERRED_TYPE(bool) |
125 | unsigned IsDefaulted : 1; |
126 | // We store a decomposed APSInt with the data allocated by ASTContext if |
127 | // BitWidth > 64. The memory may be shared between multiple |
128 | // TemplateArgument instances. |
129 | unsigned BitWidth : 31; |
130 | LLVM_PREFERRED_TYPE(bool) |
131 | unsigned IsUnsigned : 1; |
132 | union { |
133 | /// Used to store the <= 64 bits integer value. |
134 | uint64_t VAL; |
135 | |
136 | /// Used to store the >64 bits integer value. |
137 | const uint64_t *pVal; |
138 | }; |
139 | void *Type; |
140 | }; |
141 | struct V { |
142 | LLVM_PREFERRED_TYPE(ArgKind) |
143 | unsigned Kind : 31; |
144 | LLVM_PREFERRED_TYPE(bool) |
145 | unsigned IsDefaulted : 1; |
146 | APValue *Value; |
147 | void *Type; |
148 | }; |
149 | struct A { |
150 | LLVM_PREFERRED_TYPE(ArgKind) |
151 | unsigned Kind : 31; |
152 | LLVM_PREFERRED_TYPE(bool) |
153 | unsigned IsDefaulted : 1; |
154 | unsigned NumArgs; |
155 | const TemplateArgument *Args; |
156 | }; |
157 | struct TA { |
158 | LLVM_PREFERRED_TYPE(ArgKind) |
159 | unsigned Kind : 31; |
160 | LLVM_PREFERRED_TYPE(bool) |
161 | unsigned IsDefaulted : 1; |
162 | unsigned NumExpansions; |
163 | void *Name; |
164 | }; |
165 | struct TV { |
166 | LLVM_PREFERRED_TYPE(ArgKind) |
167 | unsigned Kind : 31; |
168 | LLVM_PREFERRED_TYPE(bool) |
169 | unsigned IsDefaulted : 1; |
170 | uintptr_t V; |
171 | }; |
172 | union { |
173 | struct DA DeclArg; |
174 | struct I Integer; |
175 | struct V Value; |
176 | struct A Args; |
177 | struct TA TemplateArg; |
178 | struct TV TypeOrValue; |
179 | }; |
180 | |
181 | void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted); |
182 | void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted); |
183 | void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, |
184 | QualType Type, bool IsDefaulted); |
185 | void initFromStructural(const ASTContext &Ctx, QualType Type, |
186 | const APValue &V, bool IsDefaulted); |
187 | |
188 | public: |
189 | /// Construct an empty, invalid template argument. |
190 | constexpr TemplateArgument() : TypeOrValue({.Kind: Null, .IsDefaulted: 0, /* IsDefaulted */ .V: 0}) {} |
191 | |
192 | /// Construct a template type argument. |
193 | TemplateArgument(QualType T, bool isNullPtr = false, |
194 | bool IsDefaulted = false) { |
195 | initFromType(T, IsNullPtr: isNullPtr, IsDefaulted); |
196 | } |
197 | |
198 | /// Construct a template argument that refers to a (non-dependent) |
199 | /// declaration. |
200 | TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) { |
201 | initFromDeclaration(D, QT, IsDefaulted); |
202 | } |
203 | |
204 | /// Construct an integral constant template argument. The memory to |
205 | /// store the value is allocated with Ctx. |
206 | TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value, |
207 | QualType Type, bool IsDefaulted = false); |
208 | |
209 | /// Construct a template argument from an arbitrary constant value. |
210 | TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value, |
211 | bool IsDefaulted = false); |
212 | |
213 | /// Construct an integral constant template argument with the same |
214 | /// value as Other but a different type. |
215 | TemplateArgument(const TemplateArgument &Other, QualType Type) { |
216 | Integer = Other.Integer; |
217 | Integer.Type = Type.getAsOpaquePtr(); |
218 | } |
219 | |
220 | /// Construct a template argument that is a template. |
221 | /// |
222 | /// This form of template argument is generally used for template template |
223 | /// parameters. However, the template name could be a dependent template |
224 | /// name that ends up being instantiated to a function template whose address |
225 | /// is taken. |
226 | /// |
227 | /// \param Name The template name. |
228 | /// |
229 | /// \param IsDefaulted If 'true', implies that this TemplateArgument |
230 | /// corresponds to a default template parameter |
231 | TemplateArgument(TemplateName Name, bool IsDefaulted = false) { |
232 | TemplateArg.Kind = Template; |
233 | TemplateArg.IsDefaulted = IsDefaulted; |
234 | TemplateArg.Name = Name.getAsVoidPointer(); |
235 | TemplateArg.NumExpansions = 0; |
236 | } |
237 | |
238 | /// Construct a template argument that is a template pack expansion. |
239 | /// |
240 | /// This form of template argument is generally used for template template |
241 | /// parameters. However, the template name could be a dependent template |
242 | /// name that ends up being instantiated to a function template whose address |
243 | /// is taken. |
244 | /// |
245 | /// \param Name The template name. |
246 | /// |
247 | /// \param NumExpansions The number of expansions that will be generated by |
248 | /// instantiating |
249 | /// |
250 | /// \param IsDefaulted If 'true', implies that this TemplateArgument |
251 | /// corresponds to a default template parameter |
252 | TemplateArgument(TemplateName Name, std::optional<unsigned> NumExpansions, |
253 | bool IsDefaulted = false) { |
254 | TemplateArg.Kind = TemplateExpansion; |
255 | TemplateArg.IsDefaulted = IsDefaulted; |
256 | TemplateArg.Name = Name.getAsVoidPointer(); |
257 | if (NumExpansions) |
258 | TemplateArg.NumExpansions = *NumExpansions + 1; |
259 | else |
260 | TemplateArg.NumExpansions = 0; |
261 | } |
262 | |
263 | /// Construct a template argument that is an expression. |
264 | /// |
265 | /// This form of template argument only occurs in template argument |
266 | /// lists used for dependent types and for expression; it will not |
267 | /// occur in a non-dependent, canonical template argument list. |
268 | TemplateArgument(Expr *E, bool IsDefaulted = false) { |
269 | TypeOrValue.Kind = Expression; |
270 | TypeOrValue.IsDefaulted = IsDefaulted; |
271 | TypeOrValue.V = reinterpret_cast<uintptr_t>(E); |
272 | } |
273 | |
274 | /// Construct a template argument that is a template argument pack. |
275 | /// |
276 | /// We assume that storage for the template arguments provided |
277 | /// outlives the TemplateArgument itself. |
278 | explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { |
279 | this->Args.Kind = Pack; |
280 | this->Args.IsDefaulted = false; |
281 | this->Args.Args = Args.data(); |
282 | this->Args.NumArgs = Args.size(); |
283 | } |
284 | |
285 | static TemplateArgument getEmptyPack() { |
286 | return TemplateArgument(std::nullopt); |
287 | } |
288 | |
289 | /// Create a new template argument pack by copying the given set of |
290 | /// template arguments. |
291 | static TemplateArgument CreatePackCopy(ASTContext &Context, |
292 | ArrayRef<TemplateArgument> Args); |
293 | |
294 | /// Return the kind of stored template argument. |
295 | ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } |
296 | |
297 | /// Determine whether this template argument has no value. |
298 | bool isNull() const { return getKind() == Null; } |
299 | |
300 | TemplateArgumentDependence getDependence() const; |
301 | |
302 | /// Whether this template argument is dependent on a template |
303 | /// parameter such that its result can change from one instantiation to |
304 | /// another. |
305 | bool isDependent() const; |
306 | |
307 | /// Whether this template argument is dependent on a template |
308 | /// parameter. |
309 | bool isInstantiationDependent() const; |
310 | |
311 | /// Whether this template argument contains an unexpanded |
312 | /// parameter pack. |
313 | bool containsUnexpandedParameterPack() const; |
314 | |
315 | /// Determine whether this template argument is a pack expansion. |
316 | bool isPackExpansion() const; |
317 | |
318 | /// Retrieve the type for a type template argument. |
319 | QualType getAsType() const { |
320 | assert(getKind() == Type && "Unexpected kind" ); |
321 | return QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void *>(TypeOrValue.V)); |
322 | } |
323 | |
324 | /// Retrieve the declaration for a declaration non-type |
325 | /// template argument. |
326 | ValueDecl *getAsDecl() const { |
327 | assert(getKind() == Declaration && "Unexpected kind" ); |
328 | return DeclArg.D; |
329 | } |
330 | |
331 | QualType getParamTypeForDecl() const { |
332 | assert(getKind() == Declaration && "Unexpected kind" ); |
333 | return QualType::getFromOpaquePtr(Ptr: DeclArg.QT); |
334 | } |
335 | |
336 | /// Retrieve the type for null non-type template argument. |
337 | QualType getNullPtrType() const { |
338 | assert(getKind() == NullPtr && "Unexpected kind" ); |
339 | return QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void *>(TypeOrValue.V)); |
340 | } |
341 | |
342 | /// Retrieve the template name for a template name argument. |
343 | TemplateName getAsTemplate() const { |
344 | assert(getKind() == Template && "Unexpected kind" ); |
345 | return TemplateName::getFromVoidPointer(Ptr: TemplateArg.Name); |
346 | } |
347 | |
348 | /// Retrieve the template argument as a template name; if the argument |
349 | /// is a pack expansion, return the pattern as a template name. |
350 | TemplateName getAsTemplateOrTemplatePattern() const { |
351 | assert((getKind() == Template || getKind() == TemplateExpansion) && |
352 | "Unexpected kind" ); |
353 | |
354 | return TemplateName::getFromVoidPointer(Ptr: TemplateArg.Name); |
355 | } |
356 | |
357 | /// Retrieve the number of expansions that a template template argument |
358 | /// expansion will produce, if known. |
359 | std::optional<unsigned> getNumTemplateExpansions() const; |
360 | |
361 | /// Retrieve the template argument as an integral value. |
362 | // FIXME: Provide a way to read the integral data without copying the value. |
363 | llvm::APSInt getAsIntegral() const { |
364 | assert(getKind() == Integral && "Unexpected kind" ); |
365 | |
366 | using namespace llvm; |
367 | |
368 | if (Integer.BitWidth <= 64) |
369 | return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); |
370 | |
371 | unsigned NumWords = APInt::getNumWords(BitWidth: Integer.BitWidth); |
372 | return APSInt(APInt(Integer.BitWidth, ArrayRef(Integer.pVal, NumWords)), |
373 | Integer.IsUnsigned); |
374 | } |
375 | |
376 | /// Retrieve the type of the integral value. |
377 | QualType getIntegralType() const { |
378 | assert(getKind() == Integral && "Unexpected kind" ); |
379 | return QualType::getFromOpaquePtr(Ptr: Integer.Type); |
380 | } |
381 | |
382 | void setIntegralType(QualType T) { |
383 | assert(getKind() == Integral && "Unexpected kind" ); |
384 | Integer.Type = T.getAsOpaquePtr(); |
385 | } |
386 | |
387 | /// Set to 'true' if this TemplateArgument corresponds to a |
388 | /// default template parameter. |
389 | void setIsDefaulted(bool v) { TypeOrValue.IsDefaulted = v; } |
390 | |
391 | /// If returns 'true', this TemplateArgument corresponds to a |
392 | /// default template parameter. |
393 | bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } |
394 | |
395 | /// Get the value of a StructuralValue. |
396 | const APValue &getAsStructuralValue() const { return *Value.Value; } |
397 | |
398 | /// Get the type of a StructuralValue. |
399 | QualType getStructuralValueType() const { |
400 | return QualType::getFromOpaquePtr(Ptr: Value.Type); |
401 | } |
402 | |
403 | /// If this is a non-type template argument, get its type. Otherwise, |
404 | /// returns a null QualType. |
405 | QualType getNonTypeTemplateArgumentType() const; |
406 | |
407 | /// Retrieve the template argument as an expression. |
408 | Expr *getAsExpr() const { |
409 | assert(getKind() == Expression && "Unexpected kind" ); |
410 | return reinterpret_cast<Expr *>(TypeOrValue.V); |
411 | } |
412 | |
413 | /// Iterator that traverses the elements of a template argument pack. |
414 | using pack_iterator = const TemplateArgument *; |
415 | |
416 | /// Iterator referencing the first argument of a template argument |
417 | /// pack. |
418 | pack_iterator pack_begin() const { |
419 | assert(getKind() == Pack); |
420 | return Args.Args; |
421 | } |
422 | |
423 | /// Iterator referencing one past the last argument of a template |
424 | /// argument pack. |
425 | pack_iterator pack_end() const { |
426 | assert(getKind() == Pack); |
427 | return Args.Args + Args.NumArgs; |
428 | } |
429 | |
430 | /// Iterator range referencing all of the elements of a template |
431 | /// argument pack. |
432 | ArrayRef<TemplateArgument> pack_elements() const { |
433 | return llvm::ArrayRef(pack_begin(), pack_end()); |
434 | } |
435 | |
436 | /// The number of template arguments in the given template argument |
437 | /// pack. |
438 | unsigned pack_size() const { |
439 | assert(getKind() == Pack); |
440 | return Args.NumArgs; |
441 | } |
442 | |
443 | /// Return the array of arguments in this template argument pack. |
444 | ArrayRef<TemplateArgument> getPackAsArray() const { |
445 | assert(getKind() == Pack); |
446 | return llvm::ArrayRef(Args.Args, Args.NumArgs); |
447 | } |
448 | |
449 | /// Determines whether two template arguments are superficially the |
450 | /// same. |
451 | bool structurallyEquals(const TemplateArgument &Other) const; |
452 | |
453 | /// When the template argument is a pack expansion, returns |
454 | /// the pattern of the pack expansion. |
455 | TemplateArgument getPackExpansionPattern() const; |
456 | |
457 | /// Print this template argument to the given output stream. |
458 | void print(const PrintingPolicy &Policy, raw_ostream &Out, |
459 | bool IncludeType) const; |
460 | |
461 | /// Debugging aid that dumps the template argument. |
462 | void dump(raw_ostream &Out) const; |
463 | |
464 | /// Debugging aid that dumps the template argument to standard error. |
465 | void dump() const; |
466 | |
467 | /// Used to insert TemplateArguments into FoldingSets. |
468 | void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; |
469 | }; |
470 | |
471 | /// Location information for a TemplateArgument. |
472 | struct TemplateArgumentLocInfo { |
473 | private: |
474 | struct TemplateTemplateArgLocInfo { |
475 | // FIXME: We'd like to just use the qualifier in the TemplateName, |
476 | // but template arguments get canonicalized too quickly. |
477 | NestedNameSpecifier *Qualifier; |
478 | void *QualifierLocData; |
479 | SourceLocation TemplateNameLoc; |
480 | SourceLocation EllipsisLoc; |
481 | }; |
482 | |
483 | llvm::PointerUnion<TemplateTemplateArgLocInfo *, Expr *, TypeSourceInfo *> |
484 | Pointer; |
485 | |
486 | TemplateTemplateArgLocInfo *getTemplate() const { |
487 | return Pointer.get<TemplateTemplateArgLocInfo *>(); |
488 | } |
489 | |
490 | public: |
491 | TemplateArgumentLocInfo() {} |
492 | TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; } |
493 | |
494 | TemplateArgumentLocInfo(Expr *E) { Pointer = E; } |
495 | // Ctx is used for allocation -- this case is unusually large and also rare, |
496 | // so we store the payload out-of-line. |
497 | TemplateArgumentLocInfo(ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, |
498 | SourceLocation TemplateNameLoc, |
499 | SourceLocation EllipsisLoc); |
500 | |
501 | TypeSourceInfo *getAsTypeSourceInfo() const { |
502 | return Pointer.get<TypeSourceInfo *>(); |
503 | } |
504 | |
505 | Expr *getAsExpr() const { return Pointer.get<Expr *>(); } |
506 | |
507 | NestedNameSpecifierLoc getTemplateQualifierLoc() const { |
508 | const auto *Template = getTemplate(); |
509 | return NestedNameSpecifierLoc(Template->Qualifier, |
510 | Template->QualifierLocData); |
511 | } |
512 | |
513 | SourceLocation getTemplateNameLoc() const { |
514 | return getTemplate()->TemplateNameLoc; |
515 | } |
516 | |
517 | SourceLocation getTemplateEllipsisLoc() const { |
518 | return getTemplate()->EllipsisLoc; |
519 | } |
520 | }; |
521 | |
522 | /// Location wrapper for a TemplateArgument. TemplateArgument is to |
523 | /// TemplateArgumentLoc as Type is to TypeLoc. |
524 | class TemplateArgumentLoc { |
525 | TemplateArgument Argument; |
526 | TemplateArgumentLocInfo LocInfo; |
527 | |
528 | public: |
529 | TemplateArgumentLoc() {} |
530 | |
531 | TemplateArgumentLoc(const TemplateArgument &Argument, |
532 | TemplateArgumentLocInfo Opaque) |
533 | : Argument(Argument), LocInfo(Opaque) {} |
534 | |
535 | TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) |
536 | : Argument(Argument), LocInfo(TInfo) { |
537 | assert(Argument.getKind() == TemplateArgument::Type); |
538 | } |
539 | |
540 | TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) |
541 | : Argument(Argument), LocInfo(E) { |
542 | |
543 | // Permit any kind of template argument that can be represented with an |
544 | // expression. |
545 | assert(Argument.getKind() == TemplateArgument::NullPtr || |
546 | Argument.getKind() == TemplateArgument::Integral || |
547 | Argument.getKind() == TemplateArgument::Declaration || |
548 | Argument.getKind() == TemplateArgument::StructuralValue || |
549 | Argument.getKind() == TemplateArgument::Expression); |
550 | } |
551 | |
552 | TemplateArgumentLoc(ASTContext &Ctx, const TemplateArgument &Argument, |
553 | NestedNameSpecifierLoc QualifierLoc, |
554 | SourceLocation TemplateNameLoc, |
555 | SourceLocation EllipsisLoc = SourceLocation()) |
556 | : Argument(Argument), |
557 | LocInfo(Ctx, QualifierLoc, TemplateNameLoc, EllipsisLoc) { |
558 | assert(Argument.getKind() == TemplateArgument::Template || |
559 | Argument.getKind() == TemplateArgument::TemplateExpansion); |
560 | } |
561 | |
562 | /// - Fetches the primary location of the argument. |
563 | SourceLocation getLocation() const { |
564 | if (Argument.getKind() == TemplateArgument::Template || |
565 | Argument.getKind() == TemplateArgument::TemplateExpansion) |
566 | return getTemplateNameLoc(); |
567 | |
568 | return getSourceRange().getBegin(); |
569 | } |
570 | |
571 | /// - Fetches the full source range of the argument. |
572 | SourceRange getSourceRange() const LLVM_READONLY; |
573 | |
574 | const TemplateArgument &getArgument() const { return Argument; } |
575 | |
576 | TemplateArgumentLocInfo getLocInfo() const { return LocInfo; } |
577 | |
578 | TypeSourceInfo *getTypeSourceInfo() const { |
579 | if (Argument.getKind() != TemplateArgument::Type) |
580 | return nullptr; |
581 | return LocInfo.getAsTypeSourceInfo(); |
582 | } |
583 | |
584 | Expr *getSourceExpression() const { |
585 | assert(Argument.getKind() == TemplateArgument::Expression); |
586 | return LocInfo.getAsExpr(); |
587 | } |
588 | |
589 | Expr *getSourceDeclExpression() const { |
590 | assert(Argument.getKind() == TemplateArgument::Declaration); |
591 | return LocInfo.getAsExpr(); |
592 | } |
593 | |
594 | Expr *getSourceNullPtrExpression() const { |
595 | assert(Argument.getKind() == TemplateArgument::NullPtr); |
596 | return LocInfo.getAsExpr(); |
597 | } |
598 | |
599 | Expr *getSourceIntegralExpression() const { |
600 | assert(Argument.getKind() == TemplateArgument::Integral); |
601 | return LocInfo.getAsExpr(); |
602 | } |
603 | |
604 | Expr *getSourceStructuralValueExpression() const { |
605 | assert(Argument.getKind() == TemplateArgument::StructuralValue); |
606 | return LocInfo.getAsExpr(); |
607 | } |
608 | |
609 | NestedNameSpecifierLoc getTemplateQualifierLoc() const { |
610 | if (Argument.getKind() != TemplateArgument::Template && |
611 | Argument.getKind() != TemplateArgument::TemplateExpansion) |
612 | return NestedNameSpecifierLoc(); |
613 | return LocInfo.getTemplateQualifierLoc(); |
614 | } |
615 | |
616 | SourceLocation getTemplateNameLoc() const { |
617 | if (Argument.getKind() != TemplateArgument::Template && |
618 | Argument.getKind() != TemplateArgument::TemplateExpansion) |
619 | return SourceLocation(); |
620 | return LocInfo.getTemplateNameLoc(); |
621 | } |
622 | |
623 | SourceLocation getTemplateEllipsisLoc() const { |
624 | if (Argument.getKind() != TemplateArgument::TemplateExpansion) |
625 | return SourceLocation(); |
626 | return LocInfo.getTemplateEllipsisLoc(); |
627 | } |
628 | }; |
629 | |
630 | /// A convenient class for passing around template argument |
631 | /// information. Designed to be passed by reference. |
632 | class TemplateArgumentListInfo { |
633 | SmallVector<TemplateArgumentLoc, 8> Arguments; |
634 | SourceLocation LAngleLoc; |
635 | SourceLocation RAngleLoc; |
636 | |
637 | public: |
638 | TemplateArgumentListInfo() = default; |
639 | |
640 | TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc) |
641 | : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} |
642 | |
643 | // This can leak if used in an AST node, use ASTTemplateArgumentListInfo |
644 | // instead. |
645 | void *operator new(size_t bytes, ASTContext &C) = delete; |
646 | |
647 | SourceLocation getLAngleLoc() const { return LAngleLoc; } |
648 | SourceLocation getRAngleLoc() const { return RAngleLoc; } |
649 | |
650 | void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } |
651 | void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } |
652 | |
653 | unsigned size() const { return Arguments.size(); } |
654 | |
655 | const TemplateArgumentLoc *getArgumentArray() const { |
656 | return Arguments.data(); |
657 | } |
658 | |
659 | llvm::ArrayRef<TemplateArgumentLoc> arguments() const { return Arguments; } |
660 | |
661 | const TemplateArgumentLoc &operator[](unsigned I) const { |
662 | return Arguments[I]; |
663 | } |
664 | |
665 | TemplateArgumentLoc &operator[](unsigned I) { return Arguments[I]; } |
666 | |
667 | void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Elt: Loc); } |
668 | }; |
669 | |
670 | /// Represents an explicit template argument list in C++, e.g., |
671 | /// the "<int>" in "sort<int>". |
672 | /// This is safe to be used inside an AST node, in contrast with |
673 | /// TemplateArgumentListInfo. |
674 | struct ASTTemplateArgumentListInfo final |
675 | : private llvm::TrailingObjects<ASTTemplateArgumentListInfo, |
676 | TemplateArgumentLoc> { |
677 | private: |
678 | friend class ASTNodeImporter; |
679 | friend TrailingObjects; |
680 | |
681 | ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); |
682 | |
683 | // FIXME: Is it ever necessary to copy to another context? |
684 | ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List); |
685 | |
686 | public: |
687 | /// The source location of the left angle bracket ('<'). |
688 | SourceLocation LAngleLoc; |
689 | |
690 | /// The source location of the right angle bracket ('>'). |
691 | SourceLocation RAngleLoc; |
692 | |
693 | /// The number of template arguments in TemplateArgs. |
694 | unsigned NumTemplateArgs; |
695 | |
696 | SourceLocation getLAngleLoc() const { return LAngleLoc; } |
697 | SourceLocation getRAngleLoc() const { return RAngleLoc; } |
698 | |
699 | /// Retrieve the template arguments |
700 | const TemplateArgumentLoc *getTemplateArgs() const { |
701 | return getTrailingObjects<TemplateArgumentLoc>(); |
702 | } |
703 | unsigned getNumTemplateArgs() const { return NumTemplateArgs; } |
704 | |
705 | llvm::ArrayRef<TemplateArgumentLoc> arguments() const { |
706 | return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs()); |
707 | } |
708 | |
709 | const TemplateArgumentLoc &operator[](unsigned I) const { |
710 | return getTemplateArgs()[I]; |
711 | } |
712 | |
713 | static const ASTTemplateArgumentListInfo * |
714 | Create(const ASTContext &C, const TemplateArgumentListInfo &List); |
715 | |
716 | // FIXME: Is it ever necessary to copy to another context? |
717 | static const ASTTemplateArgumentListInfo * |
718 | Create(const ASTContext &C, const ASTTemplateArgumentListInfo *List); |
719 | }; |
720 | |
721 | /// Represents an explicit template argument list in C++, e.g., |
722 | /// the "<int>" in "sort<int>". |
723 | /// |
724 | /// It is intended to be used as a trailing object on AST nodes, and |
725 | /// as such, doesn't contain the array of TemplateArgumentLoc itself, |
726 | /// but expects the containing object to also provide storage for |
727 | /// that. |
728 | struct alignas(void *) ASTTemplateKWAndArgsInfo { |
729 | /// The source location of the left angle bracket ('<'). |
730 | SourceLocation LAngleLoc; |
731 | |
732 | /// The source location of the right angle bracket ('>'). |
733 | SourceLocation RAngleLoc; |
734 | |
735 | /// The source location of the template keyword; this is used |
736 | /// as part of the representation of qualified identifiers, such as |
737 | /// S<T>::template apply<T>. Will be empty if this expression does |
738 | /// not have a template keyword. |
739 | SourceLocation TemplateKWLoc; |
740 | |
741 | /// The number of template arguments in TemplateArgs. |
742 | unsigned NumTemplateArgs; |
743 | |
744 | void initializeFrom(SourceLocation TemplateKWLoc, |
745 | const TemplateArgumentListInfo &List, |
746 | TemplateArgumentLoc *OutArgArray); |
747 | // FIXME: The parameter Deps is the result populated by this method, the |
748 | // caller doesn't need it since it is populated by computeDependence. remove |
749 | // it. |
750 | void initializeFrom(SourceLocation TemplateKWLoc, |
751 | const TemplateArgumentListInfo &List, |
752 | TemplateArgumentLoc *OutArgArray, |
753 | TemplateArgumentDependence &Deps); |
754 | void initializeFrom(SourceLocation TemplateKWLoc); |
755 | |
756 | void copyInto(const TemplateArgumentLoc *ArgArray, |
757 | TemplateArgumentListInfo &List) const; |
758 | }; |
759 | |
760 | const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
761 | const TemplateArgument &Arg); |
762 | |
763 | } // namespace clang |
764 | |
765 | #endif // LLVM_CLANG_AST_TEMPLATEBASE_H |
766 | |