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 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
190public:
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.
478struct TemplateArgumentLocInfo {
479private:
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
496public:
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.
530class TemplateArgumentLoc {
531 TemplateArgument Argument;
532 TemplateArgumentLocInfo LocInfo;
533
534public:
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.
638class TemplateArgumentListInfo {
639 SmallVector<TemplateArgumentLoc, 8> Arguments;
640 SourceLocation LAngleLoc;
641 SourceLocation RAngleLoc;
642
643public:
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.
680struct ASTTemplateArgumentListInfo final
681 : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
682 TemplateArgumentLoc> {
683private:
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
692public:
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.
734struct 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
766const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
767 const TemplateArgument &Arg);
768
769} // namespace clang
770
771#endif // LLVM_CLANG_AST_TEMPLATEBASE_H
772