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 | UnsignedOrNone 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 | LLVM_PREFERRED_TYPE(bool) |
171 | unsigned IsCanonicalExpr : 1; |
172 | uintptr_t V; |
173 | }; |
174 | union { |
175 | struct DA DeclArg; |
176 | struct I Integer; |
177 | struct V Value; |
178 | struct A Args; |
179 | struct TA TemplateArg; |
180 | struct TV TypeOrValue; |
181 | }; |
182 | |
183 | void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted); |
184 | void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted); |
185 | void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, |
186 | QualType Type, bool IsDefaulted); |
187 | void initFromStructural(const ASTContext &Ctx, QualType Type, |
188 | const APValue &V, bool IsDefaulted); |
189 | |
190 | public: |
191 | /// Construct an empty, invalid template argument. |
192 | constexpr TemplateArgument() |
193 | : TypeOrValue{.Kind: Null, /*IsDefaulted=*/.IsDefaulted: 0, /*IsCanonicalExpr=*/.IsCanonicalExpr: 0, /*V=*/.V: 0} {} |
194 | |
195 | /// Construct a template type argument. |
196 | TemplateArgument(QualType T, bool isNullPtr = false, |
197 | bool IsDefaulted = false) { |
198 | initFromType(T, IsNullPtr: isNullPtr, IsDefaulted); |
199 | } |
200 | |
201 | /// Construct a template argument that refers to a (non-dependent) |
202 | /// declaration. |
203 | TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) { |
204 | initFromDeclaration(D, QT, IsDefaulted); |
205 | } |
206 | |
207 | /// Construct an integral constant template argument. The memory to |
208 | /// store the value is allocated with Ctx. |
209 | TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value, |
210 | QualType Type, bool IsDefaulted = false); |
211 | |
212 | /// Construct a template argument from an arbitrary constant value. |
213 | TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value, |
214 | bool IsDefaulted = false); |
215 | |
216 | /// Construct an integral constant template argument with the same |
217 | /// value as Other but a different type. |
218 | TemplateArgument(const TemplateArgument &Other, QualType Type) { |
219 | Integer = Other.Integer; |
220 | Integer.Type = Type.getAsOpaquePtr(); |
221 | } |
222 | |
223 | /// Construct a template argument that is a template. |
224 | /// |
225 | /// This form of template argument is generally used for template template |
226 | /// parameters. However, the template name could be a dependent template |
227 | /// name that ends up being instantiated to a function template whose address |
228 | /// is taken. |
229 | /// |
230 | /// \param Name The template name. |
231 | /// |
232 | /// \param IsDefaulted If 'true', implies that this TemplateArgument |
233 | /// corresponds to a default template parameter |
234 | TemplateArgument(TemplateName Name, bool IsDefaulted = false) { |
235 | TemplateArg.Kind = Template; |
236 | TemplateArg.IsDefaulted = IsDefaulted; |
237 | TemplateArg.Name = Name.getAsVoidPointer(); |
238 | TemplateArg.NumExpansions = std::nullopt; |
239 | } |
240 | |
241 | /// Construct a template argument that is a template pack expansion. |
242 | /// |
243 | /// This form of template argument is generally used for template template |
244 | /// parameters. However, the template name could be a dependent template |
245 | /// name that ends up being instantiated to a function template whose address |
246 | /// is taken. |
247 | /// |
248 | /// \param Name The template name. |
249 | /// |
250 | /// \param NumExpansions The number of expansions that will be generated by |
251 | /// instantiating |
252 | /// |
253 | /// \param IsDefaulted If 'true', implies that this TemplateArgument |
254 | /// corresponds to a default template parameter |
255 | TemplateArgument(TemplateName Name, UnsignedOrNone NumExpansions, |
256 | bool IsDefaulted = false) { |
257 | TemplateArg.Kind = TemplateExpansion; |
258 | TemplateArg.IsDefaulted = IsDefaulted; |
259 | TemplateArg.Name = Name.getAsVoidPointer(); |
260 | TemplateArg.NumExpansions = NumExpansions; |
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 IsCanonical, bool IsDefaulted = false) { |
269 | TypeOrValue.Kind = Expression; |
270 | TypeOrValue.IsDefaulted = IsDefaulted; |
271 | TypeOrValue.IsCanonicalExpr = IsCanonical; |
272 | TypeOrValue.V = reinterpret_cast<uintptr_t>(E); |
273 | } |
274 | |
275 | /// Construct a template argument that is a template argument pack. |
276 | /// |
277 | /// We assume that storage for the template arguments provided |
278 | /// outlives the TemplateArgument itself. |
279 | explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { |
280 | this->Args.Kind = Pack; |
281 | this->Args.IsDefaulted = false; |
282 | this->Args.Args = Args.data(); |
283 | this->Args.NumArgs = Args.size(); |
284 | } |
285 | |
286 | static TemplateArgument getEmptyPack() { |
287 | return TemplateArgument(ArrayRef<TemplateArgument>()); |
288 | } |
289 | |
290 | /// Create a new template argument pack by copying the given set of |
291 | /// template arguments. |
292 | static TemplateArgument CreatePackCopy(ASTContext &Context, |
293 | ArrayRef<TemplateArgument> Args); |
294 | |
295 | /// Return the kind of stored template argument. |
296 | ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } |
297 | |
298 | /// Determine whether this template argument has no value. |
299 | bool isNull() const { return getKind() == Null; } |
300 | |
301 | TemplateArgumentDependence getDependence() const; |
302 | |
303 | /// Whether this template argument is dependent on a template |
304 | /// parameter such that its result can change from one instantiation to |
305 | /// another. |
306 | bool isDependent() const; |
307 | |
308 | /// Whether this template argument is dependent on a template |
309 | /// parameter. |
310 | bool isInstantiationDependent() const; |
311 | |
312 | /// Whether this template argument contains an unexpanded |
313 | /// parameter pack. |
314 | bool containsUnexpandedParameterPack() const; |
315 | |
316 | /// Determine whether this template argument is a pack expansion. |
317 | bool isPackExpansion() const; |
318 | |
319 | /// Retrieve the type for a type template argument. |
320 | QualType getAsType() const { |
321 | assert(getKind() == Type && "Unexpected kind" ); |
322 | return QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void *>(TypeOrValue.V)); |
323 | } |
324 | |
325 | /// Retrieve the declaration for a declaration non-type |
326 | /// template argument. |
327 | ValueDecl *getAsDecl() const { |
328 | assert(getKind() == Declaration && "Unexpected kind" ); |
329 | return DeclArg.D; |
330 | } |
331 | |
332 | QualType getParamTypeForDecl() const { |
333 | assert(getKind() == Declaration && "Unexpected kind" ); |
334 | return QualType::getFromOpaquePtr(Ptr: DeclArg.QT); |
335 | } |
336 | |
337 | /// Retrieve the type for null non-type template argument. |
338 | QualType getNullPtrType() const { |
339 | assert(getKind() == NullPtr && "Unexpected kind" ); |
340 | return QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void *>(TypeOrValue.V)); |
341 | } |
342 | |
343 | /// Retrieve the template name for a template name argument. |
344 | TemplateName getAsTemplate() const { |
345 | assert(getKind() == Template && "Unexpected kind" ); |
346 | return TemplateName::getFromVoidPointer(Ptr: TemplateArg.Name); |
347 | } |
348 | |
349 | /// Retrieve the template argument as a template name; if the argument |
350 | /// is a pack expansion, return the pattern as a template name. |
351 | TemplateName getAsTemplateOrTemplatePattern() const { |
352 | assert((getKind() == Template || getKind() == TemplateExpansion) && |
353 | "Unexpected kind" ); |
354 | |
355 | return TemplateName::getFromVoidPointer(Ptr: TemplateArg.Name); |
356 | } |
357 | |
358 | /// Retrieve the number of expansions that a template template argument |
359 | /// expansion will produce, if known. |
360 | UnsignedOrNone getNumTemplateExpansions() const; |
361 | |
362 | /// Retrieve the template argument as an integral value. |
363 | // FIXME: Provide a way to read the integral data without copying the value. |
364 | llvm::APSInt getAsIntegral() const { |
365 | assert(getKind() == Integral && "Unexpected kind" ); |
366 | |
367 | using namespace llvm; |
368 | |
369 | if (Integer.BitWidth <= 64) |
370 | return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); |
371 | |
372 | unsigned NumWords = APInt::getNumWords(BitWidth: Integer.BitWidth); |
373 | return APSInt(APInt(Integer.BitWidth, ArrayRef(Integer.pVal, NumWords)), |
374 | Integer.IsUnsigned); |
375 | } |
376 | |
377 | /// Retrieve the type of the integral value. |
378 | QualType getIntegralType() const { |
379 | assert(getKind() == Integral && "Unexpected kind" ); |
380 | return QualType::getFromOpaquePtr(Ptr: Integer.Type); |
381 | } |
382 | |
383 | void setIntegralType(QualType T) { |
384 | assert(getKind() == Integral && "Unexpected kind" ); |
385 | Integer.Type = T.getAsOpaquePtr(); |
386 | } |
387 | |
388 | /// Set to 'true' if this TemplateArgument corresponds to a |
389 | /// default template parameter. |
390 | void setIsDefaulted(bool v) { TypeOrValue.IsDefaulted = v; } |
391 | |
392 | /// If returns 'true', this TemplateArgument corresponds to a |
393 | /// default template parameter. |
394 | bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } |
395 | |
396 | /// Get the value of a StructuralValue. |
397 | const APValue &getAsStructuralValue() const { return *Value.Value; } |
398 | |
399 | /// Get the type of a StructuralValue. |
400 | QualType getStructuralValueType() const { |
401 | return QualType::getFromOpaquePtr(Ptr: Value.Type); |
402 | } |
403 | |
404 | /// If this is a non-type template argument, get its type. Otherwise, |
405 | /// returns a null QualType. |
406 | QualType getNonTypeTemplateArgumentType() const; |
407 | |
408 | /// Retrieve the template argument as an expression. |
409 | Expr *getAsExpr() const { |
410 | assert(getKind() == Expression && "Unexpected kind" ); |
411 | return reinterpret_cast<Expr *>(TypeOrValue.V); |
412 | } |
413 | |
414 | bool isCanonicalExpr() const { |
415 | assert(getKind() == Expression && "Unexpected kind" ); |
416 | return TypeOrValue.IsCanonicalExpr; |
417 | } |
418 | |
419 | /// Iterator that traverses the elements of a template argument pack. |
420 | using pack_iterator = const TemplateArgument *; |
421 | |
422 | /// Iterator referencing the first argument of a template argument |
423 | /// pack. |
424 | pack_iterator pack_begin() const { |
425 | assert(getKind() == Pack); |
426 | return Args.Args; |
427 | } |
428 | |
429 | /// Iterator referencing one past the last argument of a template |
430 | /// argument pack. |
431 | pack_iterator pack_end() const { |
432 | assert(getKind() == Pack); |
433 | return Args.Args + Args.NumArgs; |
434 | } |
435 | |
436 | /// Iterator range referencing all of the elements of a template |
437 | /// argument pack. |
438 | ArrayRef<TemplateArgument> pack_elements() const { |
439 | return {pack_begin(), pack_end()}; |
440 | } |
441 | |
442 | /// The number of template arguments in the given template argument |
443 | /// pack. |
444 | unsigned pack_size() const { |
445 | assert(getKind() == Pack); |
446 | return Args.NumArgs; |
447 | } |
448 | |
449 | /// Return the array of arguments in this template argument pack. |
450 | ArrayRef<TemplateArgument> getPackAsArray() const { |
451 | assert(getKind() == Pack); |
452 | return {Args.Args, Args.NumArgs}; |
453 | } |
454 | |
455 | /// Determines whether two template arguments are superficially the |
456 | /// same. |
457 | bool structurallyEquals(const TemplateArgument &Other) const; |
458 | |
459 | /// When the template argument is a pack expansion, returns |
460 | /// the pattern of the pack expansion. |
461 | TemplateArgument getPackExpansionPattern() const; |
462 | |
463 | /// Print this template argument to the given output stream. |
464 | void print(const PrintingPolicy &Policy, raw_ostream &Out, |
465 | bool IncludeType) const; |
466 | |
467 | /// Debugging aid that dumps the template argument. |
468 | void dump(raw_ostream &Out, const ASTContext &Context) const; |
469 | |
470 | /// Debugging aid that dumps the template argument to standard error. |
471 | void dump() const; |
472 | |
473 | /// Used to insert TemplateArguments into FoldingSets. |
474 | void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; |
475 | }; |
476 | |
477 | /// Location information for a TemplateArgument. |
478 | struct TemplateArgumentLocInfo { |
479 | private: |
480 | struct TemplateTemplateArgLocInfo { |
481 | // FIXME: We'd like to just use the qualifier in the TemplateName, |
482 | // but template arguments get canonicalized too quickly. |
483 | NestedNameSpecifier *Qualifier; |
484 | void *QualifierLocData; |
485 | SourceLocation TemplateNameLoc; |
486 | SourceLocation EllipsisLoc; |
487 | }; |
488 | |
489 | llvm::PointerUnion<TemplateTemplateArgLocInfo *, Expr *, TypeSourceInfo *> |
490 | Pointer; |
491 | |
492 | TemplateTemplateArgLocInfo *getTemplate() const { |
493 | return cast<TemplateTemplateArgLocInfo *>(Val: Pointer); |
494 | } |
495 | |
496 | public: |
497 | TemplateArgumentLocInfo() {} |
498 | TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; } |
499 | |
500 | TemplateArgumentLocInfo(Expr *E) { Pointer = E; } |
501 | // Ctx is used for allocation -- this case is unusually large and also rare, |
502 | // so we store the payload out-of-line. |
503 | TemplateArgumentLocInfo(ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, |
504 | SourceLocation TemplateNameLoc, |
505 | SourceLocation EllipsisLoc); |
506 | |
507 | TypeSourceInfo *getAsTypeSourceInfo() const { |
508 | return cast<TypeSourceInfo *>(Val: Pointer); |
509 | } |
510 | |
511 | Expr *getAsExpr() const { return cast<Expr *>(Val: Pointer); } |
512 | |
513 | NestedNameSpecifierLoc getTemplateQualifierLoc() const { |
514 | const auto *Template = getTemplate(); |
515 | return NestedNameSpecifierLoc(Template->Qualifier, |
516 | Template->QualifierLocData); |
517 | } |
518 | |
519 | SourceLocation getTemplateNameLoc() const { |
520 | return getTemplate()->TemplateNameLoc; |
521 | } |
522 | |
523 | SourceLocation getTemplateEllipsisLoc() const { |
524 | return getTemplate()->EllipsisLoc; |
525 | } |
526 | }; |
527 | |
528 | /// Location wrapper for a TemplateArgument. TemplateArgument is to |
529 | /// TemplateArgumentLoc as Type is to TypeLoc. |
530 | class TemplateArgumentLoc { |
531 | TemplateArgument Argument; |
532 | TemplateArgumentLocInfo LocInfo; |
533 | |
534 | public: |
535 | TemplateArgumentLoc() {} |
536 | |
537 | TemplateArgumentLoc(const TemplateArgument &Argument, |
538 | TemplateArgumentLocInfo Opaque) |
539 | : Argument(Argument), LocInfo(Opaque) {} |
540 | |
541 | TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) |
542 | : Argument(Argument), LocInfo(TInfo) { |
543 | assert(Argument.getKind() == TemplateArgument::Type); |
544 | } |
545 | |
546 | TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) |
547 | : Argument(Argument), LocInfo(E) { |
548 | |
549 | // Permit any kind of template argument that can be represented with an |
550 | // expression. |
551 | assert(Argument.getKind() == TemplateArgument::NullPtr || |
552 | Argument.getKind() == TemplateArgument::Integral || |
553 | Argument.getKind() == TemplateArgument::Declaration || |
554 | Argument.getKind() == TemplateArgument::StructuralValue || |
555 | Argument.getKind() == TemplateArgument::Expression); |
556 | } |
557 | |
558 | TemplateArgumentLoc(ASTContext &Ctx, const TemplateArgument &Argument, |
559 | NestedNameSpecifierLoc QualifierLoc, |
560 | SourceLocation TemplateNameLoc, |
561 | SourceLocation EllipsisLoc = SourceLocation()) |
562 | : Argument(Argument), |
563 | LocInfo(Ctx, QualifierLoc, TemplateNameLoc, EllipsisLoc) { |
564 | assert(Argument.getKind() == TemplateArgument::Template || |
565 | Argument.getKind() == TemplateArgument::TemplateExpansion); |
566 | } |
567 | |
568 | /// - Fetches the primary location of the argument. |
569 | SourceLocation getLocation() const { |
570 | if (Argument.getKind() == TemplateArgument::Template || |
571 | Argument.getKind() == TemplateArgument::TemplateExpansion) |
572 | return getTemplateNameLoc(); |
573 | |
574 | return getSourceRange().getBegin(); |
575 | } |
576 | |
577 | /// - Fetches the full source range of the argument. |
578 | SourceRange getSourceRange() const LLVM_READONLY; |
579 | |
580 | const TemplateArgument &getArgument() const { return Argument; } |
581 | |
582 | TemplateArgumentLocInfo getLocInfo() const { return LocInfo; } |
583 | |
584 | TypeSourceInfo *getTypeSourceInfo() const { |
585 | if (Argument.getKind() != TemplateArgument::Type) |
586 | return nullptr; |
587 | return LocInfo.getAsTypeSourceInfo(); |
588 | } |
589 | |
590 | Expr *getSourceExpression() const { |
591 | assert(Argument.getKind() == TemplateArgument::Expression); |
592 | return LocInfo.getAsExpr(); |
593 | } |
594 | |
595 | Expr *getSourceDeclExpression() const { |
596 | assert(Argument.getKind() == TemplateArgument::Declaration); |
597 | return LocInfo.getAsExpr(); |
598 | } |
599 | |
600 | Expr *getSourceNullPtrExpression() const { |
601 | assert(Argument.getKind() == TemplateArgument::NullPtr); |
602 | return LocInfo.getAsExpr(); |
603 | } |
604 | |
605 | Expr *getSourceIntegralExpression() const { |
606 | assert(Argument.getKind() == TemplateArgument::Integral); |
607 | return LocInfo.getAsExpr(); |
608 | } |
609 | |
610 | Expr *getSourceStructuralValueExpression() const { |
611 | assert(Argument.getKind() == TemplateArgument::StructuralValue); |
612 | return LocInfo.getAsExpr(); |
613 | } |
614 | |
615 | NestedNameSpecifierLoc getTemplateQualifierLoc() const { |
616 | if (Argument.getKind() != TemplateArgument::Template && |
617 | Argument.getKind() != TemplateArgument::TemplateExpansion) |
618 | return NestedNameSpecifierLoc(); |
619 | return LocInfo.getTemplateQualifierLoc(); |
620 | } |
621 | |
622 | SourceLocation getTemplateNameLoc() const { |
623 | if (Argument.getKind() != TemplateArgument::Template && |
624 | Argument.getKind() != TemplateArgument::TemplateExpansion) |
625 | return SourceLocation(); |
626 | return LocInfo.getTemplateNameLoc(); |
627 | } |
628 | |
629 | SourceLocation getTemplateEllipsisLoc() const { |
630 | if (Argument.getKind() != TemplateArgument::TemplateExpansion) |
631 | return SourceLocation(); |
632 | return LocInfo.getTemplateEllipsisLoc(); |
633 | } |
634 | }; |
635 | |
636 | /// A convenient class for passing around template argument |
637 | /// information. Designed to be passed by reference. |
638 | class TemplateArgumentListInfo { |
639 | SmallVector<TemplateArgumentLoc, 8> Arguments; |
640 | SourceLocation LAngleLoc; |
641 | SourceLocation RAngleLoc; |
642 | |
643 | public: |
644 | TemplateArgumentListInfo() = default; |
645 | |
646 | TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc) |
647 | : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} |
648 | |
649 | // This can leak if used in an AST node, use ASTTemplateArgumentListInfo |
650 | // instead. |
651 | void *operator new(size_t bytes, ASTContext &C) = delete; |
652 | |
653 | SourceLocation getLAngleLoc() const { return LAngleLoc; } |
654 | SourceLocation getRAngleLoc() const { return RAngleLoc; } |
655 | |
656 | void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } |
657 | void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } |
658 | |
659 | unsigned size() const { return Arguments.size(); } |
660 | |
661 | const TemplateArgumentLoc *getArgumentArray() const { |
662 | return Arguments.data(); |
663 | } |
664 | |
665 | ArrayRef<TemplateArgumentLoc> arguments() const { return Arguments; } |
666 | |
667 | const TemplateArgumentLoc &operator[](unsigned I) const { |
668 | return Arguments[I]; |
669 | } |
670 | |
671 | TemplateArgumentLoc &operator[](unsigned I) { return Arguments[I]; } |
672 | |
673 | void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Elt: Loc); } |
674 | }; |
675 | |
676 | /// Represents an explicit template argument list in C++, e.g., |
677 | /// the "<int>" in "sort<int>". |
678 | /// This is safe to be used inside an AST node, in contrast with |
679 | /// TemplateArgumentListInfo. |
680 | struct ASTTemplateArgumentListInfo final |
681 | : private llvm::TrailingObjects<ASTTemplateArgumentListInfo, |
682 | TemplateArgumentLoc> { |
683 | private: |
684 | friend class ASTNodeImporter; |
685 | friend TrailingObjects; |
686 | |
687 | ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); |
688 | |
689 | // FIXME: Is it ever necessary to copy to another context? |
690 | ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List); |
691 | |
692 | public: |
693 | /// The source location of the left angle bracket ('<'). |
694 | SourceLocation LAngleLoc; |
695 | |
696 | /// The source location of the right angle bracket ('>'). |
697 | SourceLocation RAngleLoc; |
698 | |
699 | /// The number of template arguments in TemplateArgs. |
700 | unsigned NumTemplateArgs; |
701 | |
702 | SourceLocation getLAngleLoc() const { return LAngleLoc; } |
703 | SourceLocation getRAngleLoc() const { return RAngleLoc; } |
704 | |
705 | /// Retrieve the template arguments |
706 | const TemplateArgumentLoc *getTemplateArgs() const { |
707 | return getTrailingObjects(); |
708 | } |
709 | unsigned getNumTemplateArgs() const { return NumTemplateArgs; } |
710 | |
711 | ArrayRef<TemplateArgumentLoc> arguments() const { |
712 | return {getTemplateArgs(), getNumTemplateArgs()}; |
713 | } |
714 | |
715 | const TemplateArgumentLoc &operator[](unsigned I) const { |
716 | return getTemplateArgs()[I]; |
717 | } |
718 | |
719 | static const ASTTemplateArgumentListInfo * |
720 | Create(const ASTContext &C, const TemplateArgumentListInfo &List); |
721 | |
722 | // FIXME: Is it ever necessary to copy to another context? |
723 | static const ASTTemplateArgumentListInfo * |
724 | Create(const ASTContext &C, const ASTTemplateArgumentListInfo *List); |
725 | }; |
726 | |
727 | /// Represents an explicit template argument list in C++, e.g., |
728 | /// the "<int>" in "sort<int>". |
729 | /// |
730 | /// It is intended to be used as a trailing object on AST nodes, and |
731 | /// as such, doesn't contain the array of TemplateArgumentLoc itself, |
732 | /// but expects the containing object to also provide storage for |
733 | /// that. |
734 | struct alignas(void *) ASTTemplateKWAndArgsInfo { |
735 | /// The source location of the left angle bracket ('<'). |
736 | SourceLocation LAngleLoc; |
737 | |
738 | /// The source location of the right angle bracket ('>'). |
739 | SourceLocation RAngleLoc; |
740 | |
741 | /// The source location of the template keyword; this is used |
742 | /// as part of the representation of qualified identifiers, such as |
743 | /// S<T>::template apply<T>. Will be empty if this expression does |
744 | /// not have a template keyword. |
745 | SourceLocation TemplateKWLoc; |
746 | |
747 | /// The number of template arguments in TemplateArgs. |
748 | unsigned NumTemplateArgs; |
749 | |
750 | void initializeFrom(SourceLocation TemplateKWLoc, |
751 | const TemplateArgumentListInfo &List, |
752 | TemplateArgumentLoc *OutArgArray); |
753 | // FIXME: The parameter Deps is the result populated by this method, the |
754 | // caller doesn't need it since it is populated by computeDependence. remove |
755 | // it. |
756 | void initializeFrom(SourceLocation TemplateKWLoc, |
757 | const TemplateArgumentListInfo &List, |
758 | TemplateArgumentLoc *OutArgArray, |
759 | TemplateArgumentDependence &Deps); |
760 | void initializeFrom(SourceLocation TemplateKWLoc); |
761 | |
762 | void copyInto(const TemplateArgumentLoc *ArgArray, |
763 | TemplateArgumentListInfo &List) const; |
764 | }; |
765 | |
766 | const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
767 | const TemplateArgument &Arg); |
768 | |
769 | } // namespace clang |
770 | |
771 | #endif // LLVM_CLANG_AST_TEMPLATEBASE_H |
772 | |