1 //===- TemplateBase.h - Core classes for C++ templates ----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file provides definitions which are common for all kinds of
10 // template representation.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
15 #define LLVM_CLANG_AST_TEMPLATEBASE_H
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/None.h"
27 #include "llvm/ADT/Optional.h"
28 #include "llvm/ADT/SmallVector.h"
29 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/TrailingObjects.h"
37 class FoldingSetNodeID;
44 class DiagnosticBuilder;
46 struct PrintingPolicy;
50 /// Represents a template argument.
51 class TemplateArgument {
53 /// The kind of template argument we're storing.
55 /// Represents an empty template argument, e.g., one that has not
59 /// The template argument is a type.
62 /// The template argument is a declaration that was provided for a pointer,
63 /// reference, or pointer to member non-type template parameter.
66 /// The template argument is a null pointer or null pointer to member that
67 /// was provided for a non-type template parameter.
70 /// The template argument is an integral value stored in an llvm::APSInt
71 /// that was provided for an integral non-type template parameter.
74 /// The template argument is a template name that was provided for a
75 /// template template parameter.
78 /// The template argument is a pack expansion of a template name that was
79 /// provided for a template template parameter.
82 /// The template argument is an expression, and we've not resolved it to one
83 /// of the other forms yet, either because it's dependent or because we're
84 /// representing a non-canonical template argument (for instance, in a
85 /// TemplateSpecializationType).
88 /// The template argument is actually a parameter pack. Arguments are stored
89 /// in the Args struct.
94 /// The kind of template argument we're storing.
103 // We store a decomposed APSInt with the data allocated by ASTContext if
104 // BitWidth > 64. The memory may be shared between multiple
105 // TemplateArgument instances.
106 unsigned BitWidth : 31;
107 unsigned IsUnsigned : 1;
109 /// Used to store the <= 64 bits integer value.
112 /// Used to store the >64 bits integer value.
113 const uint64_t *pVal;
120 const TemplateArgument *Args;
124 unsigned NumExpansions;
135 struct TA TemplateArg;
136 struct TV TypeOrValue;
140 /// Construct an empty, invalid template argument.
141 constexpr TemplateArgument() : TypeOrValue({Null, 0}) {}
143 /// Construct a template type argument.
144 TemplateArgument(QualType T, bool isNullPtr = false) {
145 TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
146 TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
149 /// Construct a template argument that refers to a
150 /// declaration, which is either an external declaration or a
151 /// template declaration.
152 TemplateArgument(ValueDecl *D, QualType QT) {
153 assert(D && "Expected decl");
154 DeclArg.Kind = Declaration;
155 DeclArg.QT = QT.getAsOpaquePtr();
159 /// Construct an integral constant template argument. The memory to
160 /// store the value is allocated with Ctx.
161 TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
163 /// Construct an integral constant template argument with the same
164 /// value as Other but a different type.
165 TemplateArgument(const TemplateArgument &Other, QualType Type) {
166 Integer = Other.Integer;
167 Integer.Type = Type.getAsOpaquePtr();
170 /// Construct a template argument that is a template.
172 /// This form of template argument is generally used for template template
173 /// parameters. However, the template name could be a dependent template
174 /// name that ends up being instantiated to a function template whose address
177 /// \param Name The template name.
178 TemplateArgument(TemplateName Name) {
179 TemplateArg.Kind = Template;
180 TemplateArg.Name = Name.getAsVoidPointer();
181 TemplateArg.NumExpansions = 0;
184 /// Construct a template argument that is a template pack expansion.
186 /// This form of template argument is generally used for template template
187 /// parameters. However, the template name could be a dependent template
188 /// name that ends up being instantiated to a function template whose address
191 /// \param Name The template name.
193 /// \param NumExpansions The number of expansions that will be generated by
195 TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) {
196 TemplateArg.Kind = TemplateExpansion;
197 TemplateArg.Name = Name.getAsVoidPointer();
199 TemplateArg.NumExpansions = *NumExpansions + 1;
201 TemplateArg.NumExpansions = 0;
204 /// Construct a template argument that is an expression.
206 /// This form of template argument only occurs in template argument
207 /// lists used for dependent types and for expression; it will not
208 /// occur in a non-dependent, canonical template argument list.
209 TemplateArgument(Expr *E) {
210 TypeOrValue.Kind = Expression;
211 TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
214 /// Construct a template argument that is a template argument pack.
216 /// We assume that storage for the template arguments provided
217 /// outlives the TemplateArgument itself.
218 explicit TemplateArgument(ArrayRef<TemplateArgument> Args) {
219 this->Args.Kind = Pack;
220 this->Args.Args = Args.data();
221 this->Args.NumArgs = Args.size();
224 TemplateArgument(TemplateName, bool) = delete;
226 static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
228 /// Create a new template argument pack by copying the given set of
229 /// template arguments.
230 static TemplateArgument CreatePackCopy(ASTContext &Context,
231 ArrayRef<TemplateArgument> Args);
233 /// Return the kind of stored template argument.
234 ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
236 /// Determine whether this template argument has no value.
237 bool isNull() const { return getKind() == Null; }
239 TemplateArgumentDependence getDependence() const;
241 /// Whether this template argument is dependent on a template
242 /// parameter such that its result can change from one instantiation to
244 bool isDependent() const;
246 /// Whether this template argument is dependent on a template
248 bool isInstantiationDependent() const;
250 /// Whether this template argument contains an unexpanded
252 bool containsUnexpandedParameterPack() const;
254 /// Determine whether this template argument is a pack expansion.
255 bool isPackExpansion() const;
257 /// Retrieve the type for a type template argument.
258 QualType getAsType() const {
259 assert(getKind() == Type && "Unexpected kind");
260 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
263 /// Retrieve the declaration for a declaration non-type
264 /// template argument.
265 ValueDecl *getAsDecl() const {
266 assert(getKind() == Declaration && "Unexpected kind");
270 QualType getParamTypeForDecl() const {
271 assert(getKind() == Declaration && "Unexpected kind");
272 return QualType::getFromOpaquePtr(DeclArg.QT);
275 /// Retrieve the type for null non-type template argument.
276 QualType getNullPtrType() const {
277 assert(getKind() == NullPtr && "Unexpected kind");
278 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
281 /// Retrieve the template name for a template name argument.
282 TemplateName getAsTemplate() const {
283 assert(getKind() == Template && "Unexpected kind");
284 return TemplateName::getFromVoidPointer(TemplateArg.Name);
287 /// Retrieve the template argument as a template name; if the argument
288 /// is a pack expansion, return the pattern as a template name.
289 TemplateName getAsTemplateOrTemplatePattern() const {
290 assert((getKind() == Template || getKind() == TemplateExpansion) &&
293 return TemplateName::getFromVoidPointer(TemplateArg.Name);
296 /// Retrieve the number of expansions that a template template argument
297 /// expansion will produce, if known.
298 Optional<unsigned> getNumTemplateExpansions() const;
300 /// Retrieve the template argument as an integral value.
301 // FIXME: Provide a way to read the integral data without copying the value.
302 llvm::APSInt getAsIntegral() const {
303 assert(getKind() == Integral && "Unexpected kind");
305 using namespace llvm;
307 if (Integer.BitWidth <= 64)
308 return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
310 unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
311 return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
315 /// Retrieve the type of the integral value.
316 QualType getIntegralType() const {
317 assert(getKind() == Integral && "Unexpected kind");
318 return QualType::getFromOpaquePtr(Integer.Type);
321 void setIntegralType(QualType T) {
322 assert(getKind() == Integral && "Unexpected kind");
323 Integer.Type = T.getAsOpaquePtr();
326 /// If this is a non-type template argument, get its type. Otherwise,
327 /// returns a null QualType.
328 QualType getNonTypeTemplateArgumentType() const;
330 /// Retrieve the template argument as an expression.
331 Expr *getAsExpr() const {
332 assert(getKind() == Expression && "Unexpected kind");
333 return reinterpret_cast<Expr *>(TypeOrValue.V);
336 /// Iterator that traverses the elements of a template argument pack.
337 using pack_iterator = const TemplateArgument *;
339 /// Iterator referencing the first argument of a template argument
341 pack_iterator pack_begin() const {
342 assert(getKind() == Pack);
346 /// Iterator referencing one past the last argument of a template
348 pack_iterator pack_end() const {
349 assert(getKind() == Pack);
350 return Args.Args + Args.NumArgs;
353 /// Iterator range referencing all of the elements of a template
355 ArrayRef<TemplateArgument> pack_elements() const {
356 return llvm::makeArrayRef(pack_begin(), pack_end());
359 /// The number of template arguments in the given template argument
361 unsigned pack_size() const {
362 assert(getKind() == Pack);
366 /// Return the array of arguments in this template argument pack.
367 ArrayRef<TemplateArgument> getPackAsArray() const {
368 assert(getKind() == Pack);
369 return llvm::makeArrayRef(Args.Args, Args.NumArgs);
372 /// Determines whether two template arguments are superficially the
374 bool structurallyEquals(const TemplateArgument &Other) const;
376 /// When the template argument is a pack expansion, returns
377 /// the pattern of the pack expansion.
378 TemplateArgument getPackExpansionPattern() const;
380 /// Print this template argument to the given output stream.
381 void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
383 /// Debugging aid that dumps the template argument.
384 void dump(raw_ostream &Out) const;
386 /// Debugging aid that dumps the template argument to standard error.
389 /// Used to insert TemplateArguments into FoldingSets.
390 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
393 /// Location information for a TemplateArgument.
394 struct TemplateArgumentLocInfo {
397 // FIXME: We'd like to just use the qualifier in the TemplateName,
398 // but template arguments get canonicalized too quickly.
399 NestedNameSpecifier *Qualifier;
400 void *QualifierLocData;
401 unsigned TemplateNameLoc;
402 unsigned EllipsisLoc;
408 TypeSourceInfo *Declarator;
412 constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {}
414 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
416 TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
418 TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
419 SourceLocation TemplateNameLoc,
420 SourceLocation EllipsisLoc) {
421 Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
422 Template.QualifierLocData = QualifierLoc.getOpaqueData();
423 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
424 Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
427 TypeSourceInfo *getAsTypeSourceInfo() const {
431 Expr *getAsExpr() const {
435 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
436 return NestedNameSpecifierLoc(Template.Qualifier,
437 Template.QualifierLocData);
440 SourceLocation getTemplateNameLoc() const {
441 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
444 SourceLocation getTemplateEllipsisLoc() const {
445 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
449 /// Location wrapper for a TemplateArgument. TemplateArgument is to
450 /// TemplateArgumentLoc as Type is to TypeLoc.
451 class TemplateArgumentLoc {
452 TemplateArgument Argument;
453 TemplateArgumentLocInfo LocInfo;
456 constexpr TemplateArgumentLoc() {}
458 TemplateArgumentLoc(const TemplateArgument &Argument,
459 TemplateArgumentLocInfo Opaque)
460 : Argument(Argument), LocInfo(Opaque) {}
462 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
463 : Argument(Argument), LocInfo(TInfo) {
464 assert(Argument.getKind() == TemplateArgument::Type);
467 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
468 : Argument(Argument), LocInfo(E) {
470 // Permit any kind of template argument that can be represented with an
472 assert(Argument.getKind() == TemplateArgument::NullPtr ||
473 Argument.getKind() == TemplateArgument::Integral ||
474 Argument.getKind() == TemplateArgument::Declaration ||
475 Argument.getKind() == TemplateArgument::Expression);
478 TemplateArgumentLoc(const TemplateArgument &Argument,
479 NestedNameSpecifierLoc QualifierLoc,
480 SourceLocation TemplateNameLoc,
481 SourceLocation EllipsisLoc = SourceLocation())
482 : Argument(Argument),
483 LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
484 assert(Argument.getKind() == TemplateArgument::Template ||
485 Argument.getKind() == TemplateArgument::TemplateExpansion);
488 /// - Fetches the primary location of the argument.
489 SourceLocation getLocation() const {
490 if (Argument.getKind() == TemplateArgument::Template ||
491 Argument.getKind() == TemplateArgument::TemplateExpansion)
492 return getTemplateNameLoc();
494 return getSourceRange().getBegin();
497 /// - Fetches the full source range of the argument.
498 SourceRange getSourceRange() const LLVM_READONLY;
500 const TemplateArgument &getArgument() const {
504 TemplateArgumentLocInfo getLocInfo() const {
508 TypeSourceInfo *getTypeSourceInfo() const {
509 assert(Argument.getKind() == TemplateArgument::Type);
510 return LocInfo.getAsTypeSourceInfo();
513 Expr *getSourceExpression() const {
514 assert(Argument.getKind() == TemplateArgument::Expression);
515 return LocInfo.getAsExpr();
518 Expr *getSourceDeclExpression() const {
519 assert(Argument.getKind() == TemplateArgument::Declaration);
520 return LocInfo.getAsExpr();
523 Expr *getSourceNullPtrExpression() const {
524 assert(Argument.getKind() == TemplateArgument::NullPtr);
525 return LocInfo.getAsExpr();
528 Expr *getSourceIntegralExpression() const {
529 assert(Argument.getKind() == TemplateArgument::Integral);
530 return LocInfo.getAsExpr();
533 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
534 if (Argument.getKind() != TemplateArgument::Template &&
535 Argument.getKind() != TemplateArgument::TemplateExpansion)
536 return NestedNameSpecifierLoc();
537 return LocInfo.getTemplateQualifierLoc();
540 SourceLocation getTemplateNameLoc() const {
541 if (Argument.getKind() != TemplateArgument::Template &&
542 Argument.getKind() != TemplateArgument::TemplateExpansion)
543 return SourceLocation();
544 return LocInfo.getTemplateNameLoc();
547 SourceLocation getTemplateEllipsisLoc() const {
548 if (Argument.getKind() != TemplateArgument::TemplateExpansion)
549 return SourceLocation();
550 return LocInfo.getTemplateEllipsisLoc();
554 /// A convenient class for passing around template argument
555 /// information. Designed to be passed by reference.
556 class TemplateArgumentListInfo {
557 SmallVector<TemplateArgumentLoc, 8> Arguments;
558 SourceLocation LAngleLoc;
559 SourceLocation RAngleLoc;
562 TemplateArgumentListInfo() = default;
564 TemplateArgumentListInfo(SourceLocation LAngleLoc,
565 SourceLocation RAngleLoc)
566 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
568 // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
570 void *operator new(size_t bytes, ASTContext &C) = delete;
572 SourceLocation getLAngleLoc() const { return LAngleLoc; }
573 SourceLocation getRAngleLoc() const { return RAngleLoc; }
575 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
576 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
578 unsigned size() const { return Arguments.size(); }
580 const TemplateArgumentLoc *getArgumentArray() const {
581 return Arguments.data();
584 llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
588 const TemplateArgumentLoc &operator[](unsigned I) const {
592 TemplateArgumentLoc &operator[](unsigned I) {
596 void addArgument(const TemplateArgumentLoc &Loc) {
597 Arguments.push_back(Loc);
601 /// Represents an explicit template argument list in C++, e.g.,
602 /// the "<int>" in "sort<int>".
603 /// This is safe to be used inside an AST node, in contrast with
604 /// TemplateArgumentListInfo.
605 struct ASTTemplateArgumentListInfo final
606 : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
607 TemplateArgumentLoc> {
609 friend class ASTNodeImporter;
610 friend TrailingObjects;
612 ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
615 /// The source location of the left angle bracket ('<').
616 SourceLocation LAngleLoc;
618 /// The source location of the right angle bracket ('>').
619 SourceLocation RAngleLoc;
621 /// The number of template arguments in TemplateArgs.
622 unsigned NumTemplateArgs;
624 SourceLocation getLAngleLoc() const { return LAngleLoc; }
625 SourceLocation getRAngleLoc() const { return RAngleLoc; }
627 /// Retrieve the template arguments
628 const TemplateArgumentLoc *getTemplateArgs() const {
629 return getTrailingObjects<TemplateArgumentLoc>();
631 unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
633 llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
634 return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
637 const TemplateArgumentLoc &operator[](unsigned I) const {
638 return getTemplateArgs()[I];
641 static const ASTTemplateArgumentListInfo *
642 Create(const ASTContext &C, const TemplateArgumentListInfo &List);
645 /// Represents an explicit template argument list in C++, e.g.,
646 /// the "<int>" in "sort<int>".
648 /// It is intended to be used as a trailing object on AST nodes, and
649 /// as such, doesn't contain the array of TemplateArgumentLoc itself,
650 /// but expects the containing object to also provide storage for
652 struct alignas(void *) ASTTemplateKWAndArgsInfo {
653 /// The source location of the left angle bracket ('<').
654 SourceLocation LAngleLoc;
656 /// The source location of the right angle bracket ('>').
657 SourceLocation RAngleLoc;
659 /// The source location of the template keyword; this is used
660 /// as part of the representation of qualified identifiers, such as
661 /// S<T>::template apply<T>. Will be empty if this expression does
662 /// not have a template keyword.
663 SourceLocation TemplateKWLoc;
665 /// The number of template arguments in TemplateArgs.
666 unsigned NumTemplateArgs;
668 void initializeFrom(SourceLocation TemplateKWLoc,
669 const TemplateArgumentListInfo &List,
670 TemplateArgumentLoc *OutArgArray);
671 // FIXME: The parameter Deps is the result populated by this method, the
672 // caller doesn't need it since it is populated by computeDependence. remove
674 void initializeFrom(SourceLocation TemplateKWLoc,
675 const TemplateArgumentListInfo &List,
676 TemplateArgumentLoc *OutArgArray,
677 TemplateArgumentDependence &Deps);
678 void initializeFrom(SourceLocation TemplateKWLoc);
680 void copyInto(const TemplateArgumentLoc *ArgArray,
681 TemplateArgumentListInfo &List) const;
684 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
685 const TemplateArgument &Arg);
687 inline TemplateSpecializationType::iterator
688 TemplateSpecializationType::end() const {
689 return getArgs() + getNumArgs();
692 inline DependentTemplateSpecializationType::iterator
693 DependentTemplateSpecializationType::end() const {
694 return getArgs() + getNumArgs();
697 inline const TemplateArgument &
698 TemplateSpecializationType::getArg(unsigned Idx) const {
699 assert(Idx < getNumArgs() && "Template argument out of range");
700 return getArgs()[Idx];
703 inline const TemplateArgument &
704 DependentTemplateSpecializationType::getArg(unsigned Idx) const {
705 assert(Idx < getNumArgs() && "Template argument out of range");
706 return getArgs()[Idx];
709 inline const TemplateArgument &AutoType::getArg(unsigned Idx) const {
710 assert(Idx < getNumArgs() && "Template argument out of range");
711 return getArgs()[Idx];
716 #endif // LLVM_CLANG_AST_TEMPLATEBASE_H