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
34namespace llvm {
35
36class 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.
41template <> 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
51namespace clang {
52
53class APValue;
54class ASTContext;
55class Expr;
56struct PrintingPolicy;
57class TypeSourceInfo;
58class ValueDecl;
59
60/// Represents a template argument.
61class TemplateArgument {
62public:
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
110private:
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
188public:
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.
472struct TemplateArgumentLocInfo {
473private:
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
490public:
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.
524class TemplateArgumentLoc {
525 TemplateArgument Argument;
526 TemplateArgumentLocInfo LocInfo;
527
528public:
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.
632class TemplateArgumentListInfo {
633 SmallVector<TemplateArgumentLoc, 8> Arguments;
634 SourceLocation LAngleLoc;
635 SourceLocation RAngleLoc;
636
637public:
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.
674struct ASTTemplateArgumentListInfo final
675 : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
676 TemplateArgumentLoc> {
677private:
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
686public:
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.
728struct 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
760const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
761 const TemplateArgument &Arg);
762
763} // namespace clang
764
765#endif // LLVM_CLANG_AST_TEMPLATEBASE_H
766

source code of clang/include/clang/AST/TemplateBase.h