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;
39 // Provide PointerLikeTypeTraits for clang::Expr*, this default one requires a
40 // full definition of Expr, but this file only sees a forward del because of
42 template <> struct PointerLikeTypeTraits<clang::Expr *> {
43 static inline void *getAsVoidPointer(clang::Expr *P) { return P; }
44 static inline clang::Expr *getFromVoidPointer(void *P) {
45 return static_cast<clang::Expr *>(P);
47 static constexpr int NumLowBitsAvailable = 2;
55 class DiagnosticBuilder;
57 struct PrintingPolicy;
61 /// Represents a template argument.
62 class TemplateArgument {
64 /// The kind of template argument we're storing.
66 /// Represents an empty template argument, e.g., one that has not
70 /// The template argument is a type.
73 /// The template argument is a declaration that was provided for a pointer,
74 /// reference, or pointer to member non-type template parameter.
77 /// The template argument is a null pointer or null pointer to member that
78 /// was provided for a non-type template parameter.
81 /// The template argument is an integral value stored in an llvm::APSInt
82 /// that was provided for an integral non-type template parameter.
85 /// The template argument is a template name that was provided for a
86 /// template template parameter.
89 /// The template argument is a pack expansion of a template name that was
90 /// provided for a template template parameter.
93 /// The template argument is an expression, and we've not resolved it to one
94 /// of the other forms yet, either because it's dependent or because we're
95 /// representing a non-canonical template argument (for instance, in a
96 /// TemplateSpecializationType).
99 /// The template argument is actually a parameter pack. Arguments are stored
100 /// in the Args struct.
105 /// The kind of template argument we're storing.
114 // We store a decomposed APSInt with the data allocated by ASTContext if
115 // BitWidth > 64. The memory may be shared between multiple
116 // TemplateArgument instances.
117 unsigned BitWidth : 31;
118 unsigned IsUnsigned : 1;
120 /// Used to store the <= 64 bits integer value.
123 /// Used to store the >64 bits integer value.
124 const uint64_t *pVal;
131 const TemplateArgument *Args;
135 unsigned NumExpansions;
146 struct TA TemplateArg;
147 struct TV TypeOrValue;
151 /// Construct an empty, invalid template argument.
152 constexpr TemplateArgument() : TypeOrValue({Null, 0}) {}
154 /// Construct a template type argument.
155 TemplateArgument(QualType T, bool isNullPtr = false) {
156 TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
157 TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
160 /// Construct a template argument that refers to a
161 /// declaration, which is either an external declaration or a
162 /// template declaration.
163 TemplateArgument(ValueDecl *D, QualType QT) {
164 assert(D && "Expected decl");
165 DeclArg.Kind = Declaration;
166 DeclArg.QT = QT.getAsOpaquePtr();
170 /// Construct an integral constant template argument. The memory to
171 /// store the value is allocated with Ctx.
172 TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
174 /// Construct an integral constant template argument with the same
175 /// value as Other but a different type.
176 TemplateArgument(const TemplateArgument &Other, QualType Type) {
177 Integer = Other.Integer;
178 Integer.Type = Type.getAsOpaquePtr();
181 /// Construct a template argument that is a template.
183 /// This form of template argument is generally used for template template
184 /// parameters. However, the template name could be a dependent template
185 /// name that ends up being instantiated to a function template whose address
188 /// \param Name The template name.
189 TemplateArgument(TemplateName Name) {
190 TemplateArg.Kind = Template;
191 TemplateArg.Name = Name.getAsVoidPointer();
192 TemplateArg.NumExpansions = 0;
195 /// Construct a template argument that is a template pack expansion.
197 /// This form of template argument is generally used for template template
198 /// parameters. However, the template name could be a dependent template
199 /// name that ends up being instantiated to a function template whose address
202 /// \param Name The template name.
204 /// \param NumExpansions The number of expansions that will be generated by
206 TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) {
207 TemplateArg.Kind = TemplateExpansion;
208 TemplateArg.Name = Name.getAsVoidPointer();
210 TemplateArg.NumExpansions = *NumExpansions + 1;
212 TemplateArg.NumExpansions = 0;
215 /// Construct a template argument that is an expression.
217 /// This form of template argument only occurs in template argument
218 /// lists used for dependent types and for expression; it will not
219 /// occur in a non-dependent, canonical template argument list.
220 TemplateArgument(Expr *E) {
221 TypeOrValue.Kind = Expression;
222 TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
225 /// Construct a template argument that is a template argument pack.
227 /// We assume that storage for the template arguments provided
228 /// outlives the TemplateArgument itself.
229 explicit TemplateArgument(ArrayRef<TemplateArgument> Args) {
230 this->Args.Kind = Pack;
231 this->Args.Args = Args.data();
232 this->Args.NumArgs = Args.size();
235 TemplateArgument(TemplateName, bool) = delete;
237 static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
239 /// Create a new template argument pack by copying the given set of
240 /// template arguments.
241 static TemplateArgument CreatePackCopy(ASTContext &Context,
242 ArrayRef<TemplateArgument> Args);
244 /// Return the kind of stored template argument.
245 ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
247 /// Determine whether this template argument has no value.
248 bool isNull() const { return getKind() == Null; }
250 TemplateArgumentDependence getDependence() const;
252 /// Whether this template argument is dependent on a template
253 /// parameter such that its result can change from one instantiation to
255 bool isDependent() const;
257 /// Whether this template argument is dependent on a template
259 bool isInstantiationDependent() const;
261 /// Whether this template argument contains an unexpanded
263 bool containsUnexpandedParameterPack() const;
265 /// Determine whether this template argument is a pack expansion.
266 bool isPackExpansion() const;
268 /// Retrieve the type for a type template argument.
269 QualType getAsType() const {
270 assert(getKind() == Type && "Unexpected kind");
271 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
274 /// Retrieve the declaration for a declaration non-type
275 /// template argument.
276 ValueDecl *getAsDecl() const {
277 assert(getKind() == Declaration && "Unexpected kind");
281 QualType getParamTypeForDecl() const {
282 assert(getKind() == Declaration && "Unexpected kind");
283 return QualType::getFromOpaquePtr(DeclArg.QT);
286 /// Retrieve the type for null non-type template argument.
287 QualType getNullPtrType() const {
288 assert(getKind() == NullPtr && "Unexpected kind");
289 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
292 /// Retrieve the template name for a template name argument.
293 TemplateName getAsTemplate() const {
294 assert(getKind() == Template && "Unexpected kind");
295 return TemplateName::getFromVoidPointer(TemplateArg.Name);
298 /// Retrieve the template argument as a template name; if the argument
299 /// is a pack expansion, return the pattern as a template name.
300 TemplateName getAsTemplateOrTemplatePattern() const {
301 assert((getKind() == Template || getKind() == TemplateExpansion) &&
304 return TemplateName::getFromVoidPointer(TemplateArg.Name);
307 /// Retrieve the number of expansions that a template template argument
308 /// expansion will produce, if known.
309 Optional<unsigned> getNumTemplateExpansions() const;
311 /// Retrieve the template argument as an integral value.
312 // FIXME: Provide a way to read the integral data without copying the value.
313 llvm::APSInt getAsIntegral() const {
314 assert(getKind() == Integral && "Unexpected kind");
316 using namespace llvm;
318 if (Integer.BitWidth <= 64)
319 return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
321 unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
322 return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
326 /// Retrieve the type of the integral value.
327 QualType getIntegralType() const {
328 assert(getKind() == Integral && "Unexpected kind");
329 return QualType::getFromOpaquePtr(Integer.Type);
332 void setIntegralType(QualType T) {
333 assert(getKind() == Integral && "Unexpected kind");
334 Integer.Type = T.getAsOpaquePtr();
337 /// If this is a non-type template argument, get its type. Otherwise,
338 /// returns a null QualType.
339 QualType getNonTypeTemplateArgumentType() const;
341 /// Retrieve the template argument as an expression.
342 Expr *getAsExpr() const {
343 assert(getKind() == Expression && "Unexpected kind");
344 return reinterpret_cast<Expr *>(TypeOrValue.V);
347 /// Iterator that traverses the elements of a template argument pack.
348 using pack_iterator = const TemplateArgument *;
350 /// Iterator referencing the first argument of a template argument
352 pack_iterator pack_begin() const {
353 assert(getKind() == Pack);
357 /// Iterator referencing one past the last argument of a template
359 pack_iterator pack_end() const {
360 assert(getKind() == Pack);
361 return Args.Args + Args.NumArgs;
364 /// Iterator range referencing all of the elements of a template
366 ArrayRef<TemplateArgument> pack_elements() const {
367 return llvm::makeArrayRef(pack_begin(), pack_end());
370 /// The number of template arguments in the given template argument
372 unsigned pack_size() const {
373 assert(getKind() == Pack);
377 /// Return the array of arguments in this template argument pack.
378 ArrayRef<TemplateArgument> getPackAsArray() const {
379 assert(getKind() == Pack);
380 return llvm::makeArrayRef(Args.Args, Args.NumArgs);
383 /// Determines whether two template arguments are superficially the
385 bool structurallyEquals(const TemplateArgument &Other) const;
387 /// When the template argument is a pack expansion, returns
388 /// the pattern of the pack expansion.
389 TemplateArgument getPackExpansionPattern() const;
391 /// Print this template argument to the given output stream.
392 void print(const PrintingPolicy &Policy, raw_ostream &Out,
393 bool IncludeType) const;
395 /// Debugging aid that dumps the template argument.
396 void dump(raw_ostream &Out) const;
398 /// Debugging aid that dumps the template argument to standard error.
401 /// Used to insert TemplateArguments into FoldingSets.
402 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
405 /// Location information for a TemplateArgument.
406 struct TemplateArgumentLocInfo {
408 struct TemplateTemplateArgLocInfo {
409 // FIXME: We'd like to just use the qualifier in the TemplateName,
410 // but template arguments get canonicalized too quickly.
411 NestedNameSpecifier *Qualifier;
412 void *QualifierLocData;
413 SourceLocation TemplateNameLoc;
414 SourceLocation EllipsisLoc;
417 llvm::PointerUnion<TemplateTemplateArgLocInfo *, Expr *, TypeSourceInfo *>
420 TemplateTemplateArgLocInfo *getTemplate() const {
421 return Pointer.get<TemplateTemplateArgLocInfo *>();
425 TemplateArgumentLocInfo() {}
426 TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; }
428 TemplateArgumentLocInfo(Expr *E) { Pointer = E; }
429 // Ctx is used for allocation -- this case is unusually large and also rare,
430 // so we store the payload out-of-line.
431 TemplateArgumentLocInfo(ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
432 SourceLocation TemplateNameLoc,
433 SourceLocation EllipsisLoc);
435 TypeSourceInfo *getAsTypeSourceInfo() const {
436 return Pointer.get<TypeSourceInfo *>();
439 Expr *getAsExpr() const { return Pointer.get<Expr *>(); }
441 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
442 const auto *Template = getTemplate();
443 return NestedNameSpecifierLoc(Template->Qualifier,
444 Template->QualifierLocData);
447 SourceLocation getTemplateNameLoc() const {
448 return getTemplate()->TemplateNameLoc;
451 SourceLocation getTemplateEllipsisLoc() const {
452 return getTemplate()->EllipsisLoc;
456 /// Location wrapper for a TemplateArgument. TemplateArgument is to
457 /// TemplateArgumentLoc as Type is to TypeLoc.
458 class TemplateArgumentLoc {
459 TemplateArgument Argument;
460 TemplateArgumentLocInfo LocInfo;
463 TemplateArgumentLoc() {}
465 TemplateArgumentLoc(const TemplateArgument &Argument,
466 TemplateArgumentLocInfo Opaque)
467 : Argument(Argument), LocInfo(Opaque) {}
469 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
470 : Argument(Argument), LocInfo(TInfo) {
471 assert(Argument.getKind() == TemplateArgument::Type);
474 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
475 : Argument(Argument), LocInfo(E) {
477 // Permit any kind of template argument that can be represented with an
479 assert(Argument.getKind() == TemplateArgument::NullPtr ||
480 Argument.getKind() == TemplateArgument::Integral ||
481 Argument.getKind() == TemplateArgument::Declaration ||
482 Argument.getKind() == TemplateArgument::Expression);
485 TemplateArgumentLoc(ASTContext &Ctx, const TemplateArgument &Argument,
486 NestedNameSpecifierLoc QualifierLoc,
487 SourceLocation TemplateNameLoc,
488 SourceLocation EllipsisLoc = SourceLocation())
489 : Argument(Argument),
490 LocInfo(Ctx, QualifierLoc, TemplateNameLoc, EllipsisLoc) {
491 assert(Argument.getKind() == TemplateArgument::Template ||
492 Argument.getKind() == TemplateArgument::TemplateExpansion);
495 /// - Fetches the primary location of the argument.
496 SourceLocation getLocation() const {
497 if (Argument.getKind() == TemplateArgument::Template ||
498 Argument.getKind() == TemplateArgument::TemplateExpansion)
499 return getTemplateNameLoc();
501 return getSourceRange().getBegin();
504 /// - Fetches the full source range of the argument.
505 SourceRange getSourceRange() const LLVM_READONLY;
507 const TemplateArgument &getArgument() const {
511 TemplateArgumentLocInfo getLocInfo() const {
515 TypeSourceInfo *getTypeSourceInfo() const {
516 if (Argument.getKind() != TemplateArgument::Type)
518 return LocInfo.getAsTypeSourceInfo();
521 Expr *getSourceExpression() const {
522 assert(Argument.getKind() == TemplateArgument::Expression);
523 return LocInfo.getAsExpr();
526 Expr *getSourceDeclExpression() const {
527 assert(Argument.getKind() == TemplateArgument::Declaration);
528 return LocInfo.getAsExpr();
531 Expr *getSourceNullPtrExpression() const {
532 assert(Argument.getKind() == TemplateArgument::NullPtr);
533 return LocInfo.getAsExpr();
536 Expr *getSourceIntegralExpression() const {
537 assert(Argument.getKind() == TemplateArgument::Integral);
538 return LocInfo.getAsExpr();
541 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
542 if (Argument.getKind() != TemplateArgument::Template &&
543 Argument.getKind() != TemplateArgument::TemplateExpansion)
544 return NestedNameSpecifierLoc();
545 return LocInfo.getTemplateQualifierLoc();
548 SourceLocation getTemplateNameLoc() const {
549 if (Argument.getKind() != TemplateArgument::Template &&
550 Argument.getKind() != TemplateArgument::TemplateExpansion)
551 return SourceLocation();
552 return LocInfo.getTemplateNameLoc();
555 SourceLocation getTemplateEllipsisLoc() const {
556 if (Argument.getKind() != TemplateArgument::TemplateExpansion)
557 return SourceLocation();
558 return LocInfo.getTemplateEllipsisLoc();
562 /// A convenient class for passing around template argument
563 /// information. Designed to be passed by reference.
564 class TemplateArgumentListInfo {
565 SmallVector<TemplateArgumentLoc, 8> Arguments;
566 SourceLocation LAngleLoc;
567 SourceLocation RAngleLoc;
570 TemplateArgumentListInfo() = default;
572 TemplateArgumentListInfo(SourceLocation LAngleLoc,
573 SourceLocation RAngleLoc)
574 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
576 // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
578 void *operator new(size_t bytes, ASTContext &C) = delete;
580 SourceLocation getLAngleLoc() const { return LAngleLoc; }
581 SourceLocation getRAngleLoc() const { return RAngleLoc; }
583 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
584 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
586 unsigned size() const { return Arguments.size(); }
588 const TemplateArgumentLoc *getArgumentArray() const {
589 return Arguments.data();
592 llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
596 const TemplateArgumentLoc &operator[](unsigned I) const {
600 TemplateArgumentLoc &operator[](unsigned I) {
604 void addArgument(const TemplateArgumentLoc &Loc) {
605 Arguments.push_back(Loc);
609 /// Represents an explicit template argument list in C++, e.g.,
610 /// the "<int>" in "sort<int>".
611 /// This is safe to be used inside an AST node, in contrast with
612 /// TemplateArgumentListInfo.
613 struct ASTTemplateArgumentListInfo final
614 : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
615 TemplateArgumentLoc> {
617 friend class ASTNodeImporter;
618 friend TrailingObjects;
620 ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
623 /// The source location of the left angle bracket ('<').
624 SourceLocation LAngleLoc;
626 /// The source location of the right angle bracket ('>').
627 SourceLocation RAngleLoc;
629 /// The number of template arguments in TemplateArgs.
630 unsigned NumTemplateArgs;
632 SourceLocation getLAngleLoc() const { return LAngleLoc; }
633 SourceLocation getRAngleLoc() const { return RAngleLoc; }
635 /// Retrieve the template arguments
636 const TemplateArgumentLoc *getTemplateArgs() const {
637 return getTrailingObjects<TemplateArgumentLoc>();
639 unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
641 llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
642 return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
645 const TemplateArgumentLoc &operator[](unsigned I) const {
646 return getTemplateArgs()[I];
649 static const ASTTemplateArgumentListInfo *
650 Create(const ASTContext &C, const TemplateArgumentListInfo &List);
653 /// Represents an explicit template argument list in C++, e.g.,
654 /// the "<int>" in "sort<int>".
656 /// It is intended to be used as a trailing object on AST nodes, and
657 /// as such, doesn't contain the array of TemplateArgumentLoc itself,
658 /// but expects the containing object to also provide storage for
660 struct alignas(void *) ASTTemplateKWAndArgsInfo {
661 /// The source location of the left angle bracket ('<').
662 SourceLocation LAngleLoc;
664 /// The source location of the right angle bracket ('>').
665 SourceLocation RAngleLoc;
667 /// The source location of the template keyword; this is used
668 /// as part of the representation of qualified identifiers, such as
669 /// S<T>::template apply<T>. Will be empty if this expression does
670 /// not have a template keyword.
671 SourceLocation TemplateKWLoc;
673 /// The number of template arguments in TemplateArgs.
674 unsigned NumTemplateArgs;
676 void initializeFrom(SourceLocation TemplateKWLoc,
677 const TemplateArgumentListInfo &List,
678 TemplateArgumentLoc *OutArgArray);
679 // FIXME: The parameter Deps is the result populated by this method, the
680 // caller doesn't need it since it is populated by computeDependence. remove
682 void initializeFrom(SourceLocation TemplateKWLoc,
683 const TemplateArgumentListInfo &List,
684 TemplateArgumentLoc *OutArgArray,
685 TemplateArgumentDependence &Deps);
686 void initializeFrom(SourceLocation TemplateKWLoc);
688 void copyInto(const TemplateArgumentLoc *ArgArray,
689 TemplateArgumentListInfo &List) const;
692 const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
693 const TemplateArgument &Arg);
695 inline TemplateSpecializationType::iterator
696 TemplateSpecializationType::end() const {
697 return getArgs() + getNumArgs();
700 inline DependentTemplateSpecializationType::iterator
701 DependentTemplateSpecializationType::end() const {
702 return getArgs() + getNumArgs();
705 inline const TemplateArgument &
706 TemplateSpecializationType::getArg(unsigned Idx) const {
707 assert(Idx < getNumArgs() && "Template argument out of range");
708 return getArgs()[Idx];
711 inline const TemplateArgument &
712 DependentTemplateSpecializationType::getArg(unsigned Idx) const {
713 assert(Idx < getNumArgs() && "Template argument out of range");
714 return getArgs()[Idx];
717 inline const TemplateArgument &AutoType::getArg(unsigned Idx) const {
718 assert(Idx < getNumArgs() && "Template argument out of range");
719 return getArgs()[Idx];
724 #endif // LLVM_CLANG_AST_TEMPLATEBASE_H