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/NestedNameSpecifier.h"
18 #include "clang/AST/TemplateName.h"
19 #include "clang/AST/Type.h"
20 #include "clang/Basic/LLVM.h"
21 #include "clang/Basic/SourceLocation.h"
22 #include "llvm/ADT/APInt.h"
23 #include "llvm/ADT/APSInt.h"
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/None.h"
26 #include "llvm/ADT/Optional.h"
27 #include "llvm/ADT/SmallVector.h"
28 #include "llvm/Support/Compiler.h"
29 #include "llvm/Support/TrailingObjects.h"
36 class FoldingSetNodeID;
43 class DiagnosticBuilder;
45 struct PrintingPolicy;
49 /// Represents a template argument.
50 class TemplateArgument {
52 /// The kind of template argument we're storing.
54 /// Represents an empty template argument, e.g., one that has not
58 /// The template argument is a type.
61 /// The template argument is a declaration that was provided for a pointer,
62 /// reference, or pointer to member non-type template parameter.
65 /// The template argument is a null pointer or null pointer to member that
66 /// was provided for a non-type template parameter.
69 /// The template argument is an integral value stored in an llvm::APSInt
70 /// that was provided for an integral non-type template parameter.
73 /// The template argument is a template name that was provided for a
74 /// template template parameter.
77 /// The template argument is a pack expansion of a template name that was
78 /// provided for a template template parameter.
81 /// The template argument is an expression, and we've not resolved it to one
82 /// of the other forms yet, either because it's dependent or because we're
83 /// representing a non-canonical template argument (for instance, in a
84 /// TemplateSpecializationType). Also used to represent a non-dependent
85 /// __uuidof expression (a Microsoft extension).
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 /// Whether this template argument is dependent on a template
240 /// parameter such that its result can change from one instantiation to
242 bool isDependent() const;
244 /// Whether this template argument is dependent on a template
246 bool isInstantiationDependent() const;
248 /// Whether this template argument contains an unexpanded
250 bool containsUnexpandedParameterPack() const;
252 /// Determine whether this template argument is a pack expansion.
253 bool isPackExpansion() const;
255 /// Retrieve the type for a type template argument.
256 QualType getAsType() const {
257 assert(getKind() == Type && "Unexpected kind");
258 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
261 /// Retrieve the declaration for a declaration non-type
262 /// template argument.
263 ValueDecl *getAsDecl() const {
264 assert(getKind() == Declaration && "Unexpected kind");
268 QualType getParamTypeForDecl() const {
269 assert(getKind() == Declaration && "Unexpected kind");
270 return QualType::getFromOpaquePtr(DeclArg.QT);
273 /// Retrieve the type for null non-type template argument.
274 QualType getNullPtrType() const {
275 assert(getKind() == NullPtr && "Unexpected kind");
276 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
279 /// Retrieve the template name for a template name argument.
280 TemplateName getAsTemplate() const {
281 assert(getKind() == Template && "Unexpected kind");
282 return TemplateName::getFromVoidPointer(TemplateArg.Name);
285 /// Retrieve the template argument as a template name; if the argument
286 /// is a pack expansion, return the pattern as a template name.
287 TemplateName getAsTemplateOrTemplatePattern() const {
288 assert((getKind() == Template || getKind() == TemplateExpansion) &&
291 return TemplateName::getFromVoidPointer(TemplateArg.Name);
294 /// Retrieve the number of expansions that a template template argument
295 /// expansion will produce, if known.
296 Optional<unsigned> getNumTemplateExpansions() const;
298 /// Retrieve the template argument as an integral value.
299 // FIXME: Provide a way to read the integral data without copying the value.
300 llvm::APSInt getAsIntegral() const {
301 assert(getKind() == Integral && "Unexpected kind");
303 using namespace llvm;
305 if (Integer.BitWidth <= 64)
306 return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
308 unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
309 return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
313 /// Retrieve the type of the integral value.
314 QualType getIntegralType() const {
315 assert(getKind() == Integral && "Unexpected kind");
316 return QualType::getFromOpaquePtr(Integer.Type);
319 void setIntegralType(QualType T) {
320 assert(getKind() == Integral && "Unexpected kind");
321 Integer.Type = T.getAsOpaquePtr();
324 /// If this is a non-type template argument, get its type. Otherwise,
325 /// returns a null QualType.
326 QualType getNonTypeTemplateArgumentType() const;
328 /// Retrieve the template argument as an expression.
329 Expr *getAsExpr() const {
330 assert(getKind() == Expression && "Unexpected kind");
331 return reinterpret_cast<Expr *>(TypeOrValue.V);
334 /// Iterator that traverses the elements of a template argument pack.
335 using pack_iterator = const TemplateArgument *;
337 /// Iterator referencing the first argument of a template argument
339 pack_iterator pack_begin() const {
340 assert(getKind() == Pack);
344 /// Iterator referencing one past the last argument of a template
346 pack_iterator pack_end() const {
347 assert(getKind() == Pack);
348 return Args.Args + Args.NumArgs;
351 /// Iterator range referencing all of the elements of a template
353 ArrayRef<TemplateArgument> pack_elements() const {
354 return llvm::makeArrayRef(pack_begin(), pack_end());
357 /// The number of template arguments in the given template argument
359 unsigned pack_size() const {
360 assert(getKind() == Pack);
364 /// Return the array of arguments in this template argument pack.
365 ArrayRef<TemplateArgument> getPackAsArray() const {
366 assert(getKind() == Pack);
367 return llvm::makeArrayRef(Args.Args, Args.NumArgs);
370 /// Determines whether two template arguments are superficially the
372 bool structurallyEquals(const TemplateArgument &Other) const;
374 /// When the template argument is a pack expansion, returns
375 /// the pattern of the pack expansion.
376 TemplateArgument getPackExpansionPattern() const;
378 /// Print this template argument to the given output stream.
379 void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
381 /// Debugging aid that dumps the template argument.
382 void dump(raw_ostream &Out) const;
384 /// Debugging aid that dumps the template argument to standard error.
387 /// Used to insert TemplateArguments into FoldingSets.
388 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
391 /// Location information for a TemplateArgument.
392 struct TemplateArgumentLocInfo {
395 // FIXME: We'd like to just use the qualifier in the TemplateName,
396 // but template arguments get canonicalized too quickly.
397 NestedNameSpecifier *Qualifier;
398 void *QualifierLocData;
399 unsigned TemplateNameLoc;
400 unsigned EllipsisLoc;
406 TypeSourceInfo *Declarator;
410 constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {}
412 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
414 TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
416 TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
417 SourceLocation TemplateNameLoc,
418 SourceLocation EllipsisLoc) {
419 Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
420 Template.QualifierLocData = QualifierLoc.getOpaqueData();
421 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
422 Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
425 TypeSourceInfo *getAsTypeSourceInfo() const {
429 Expr *getAsExpr() const {
433 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
434 return NestedNameSpecifierLoc(Template.Qualifier,
435 Template.QualifierLocData);
438 SourceLocation getTemplateNameLoc() const {
439 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
442 SourceLocation getTemplateEllipsisLoc() const {
443 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
447 /// Location wrapper for a TemplateArgument. TemplateArgument is to
448 /// TemplateArgumentLoc as Type is to TypeLoc.
449 class TemplateArgumentLoc {
450 TemplateArgument Argument;
451 TemplateArgumentLocInfo LocInfo;
454 constexpr TemplateArgumentLoc() {}
456 TemplateArgumentLoc(const TemplateArgument &Argument,
457 TemplateArgumentLocInfo Opaque)
458 : Argument(Argument), LocInfo(Opaque) {}
460 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
461 : Argument(Argument), LocInfo(TInfo) {
462 assert(Argument.getKind() == TemplateArgument::Type);
465 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
466 : Argument(Argument), LocInfo(E) {
468 // Permit any kind of template argument that can be represented with an
470 assert(Argument.getKind() == TemplateArgument::NullPtr ||
471 Argument.getKind() == TemplateArgument::Integral ||
472 Argument.getKind() == TemplateArgument::Declaration ||
473 Argument.getKind() == TemplateArgument::Expression);
476 TemplateArgumentLoc(const TemplateArgument &Argument,
477 NestedNameSpecifierLoc QualifierLoc,
478 SourceLocation TemplateNameLoc,
479 SourceLocation EllipsisLoc = SourceLocation())
480 : Argument(Argument),
481 LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
482 assert(Argument.getKind() == TemplateArgument::Template ||
483 Argument.getKind() == TemplateArgument::TemplateExpansion);
486 /// - Fetches the primary location of the argument.
487 SourceLocation getLocation() const {
488 if (Argument.getKind() == TemplateArgument::Template ||
489 Argument.getKind() == TemplateArgument::TemplateExpansion)
490 return getTemplateNameLoc();
492 return getSourceRange().getBegin();
495 /// - Fetches the full source range of the argument.
496 SourceRange getSourceRange() const LLVM_READONLY;
498 const TemplateArgument &getArgument() const {
502 TemplateArgumentLocInfo getLocInfo() const {
506 TypeSourceInfo *getTypeSourceInfo() const {
507 assert(Argument.getKind() == TemplateArgument::Type);
508 return LocInfo.getAsTypeSourceInfo();
511 Expr *getSourceExpression() const {
512 assert(Argument.getKind() == TemplateArgument::Expression);
513 return LocInfo.getAsExpr();
516 Expr *getSourceDeclExpression() const {
517 assert(Argument.getKind() == TemplateArgument::Declaration);
518 return LocInfo.getAsExpr();
521 Expr *getSourceNullPtrExpression() const {
522 assert(Argument.getKind() == TemplateArgument::NullPtr);
523 return LocInfo.getAsExpr();
526 Expr *getSourceIntegralExpression() const {
527 assert(Argument.getKind() == TemplateArgument::Integral);
528 return LocInfo.getAsExpr();
531 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
532 if (Argument.getKind() != TemplateArgument::Template &&
533 Argument.getKind() != TemplateArgument::TemplateExpansion)
534 return NestedNameSpecifierLoc();
535 return LocInfo.getTemplateQualifierLoc();
538 SourceLocation getTemplateNameLoc() const {
539 if (Argument.getKind() != TemplateArgument::Template &&
540 Argument.getKind() != TemplateArgument::TemplateExpansion)
541 return SourceLocation();
542 return LocInfo.getTemplateNameLoc();
545 SourceLocation getTemplateEllipsisLoc() const {
546 if (Argument.getKind() != TemplateArgument::TemplateExpansion)
547 return SourceLocation();
548 return LocInfo.getTemplateEllipsisLoc();
552 /// A convenient class for passing around template argument
553 /// information. Designed to be passed by reference.
554 class TemplateArgumentListInfo {
555 SmallVector<TemplateArgumentLoc, 8> Arguments;
556 SourceLocation LAngleLoc;
557 SourceLocation RAngleLoc;
560 TemplateArgumentListInfo() = default;
562 TemplateArgumentListInfo(SourceLocation LAngleLoc,
563 SourceLocation RAngleLoc)
564 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
566 // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
568 void *operator new(size_t bytes, ASTContext &C) = delete;
570 SourceLocation getLAngleLoc() const { return LAngleLoc; }
571 SourceLocation getRAngleLoc() const { return RAngleLoc; }
573 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
574 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
576 unsigned size() const { return Arguments.size(); }
578 const TemplateArgumentLoc *getArgumentArray() const {
579 return Arguments.data();
582 llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
586 const TemplateArgumentLoc &operator[](unsigned I) const {
590 TemplateArgumentLoc &operator[](unsigned I) {
594 void addArgument(const TemplateArgumentLoc &Loc) {
595 Arguments.push_back(Loc);
599 /// Represents an explicit template argument list in C++, e.g.,
600 /// the "<int>" in "sort<int>".
601 /// This is safe to be used inside an AST node, in contrast with
602 /// TemplateArgumentListInfo.
603 struct ASTTemplateArgumentListInfo final
604 : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
605 TemplateArgumentLoc> {
607 friend class ASTNodeImporter;
608 friend TrailingObjects;
610 ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
613 /// The source location of the left angle bracket ('<').
614 SourceLocation LAngleLoc;
616 /// The source location of the right angle bracket ('>').
617 SourceLocation RAngleLoc;
619 /// The number of template arguments in TemplateArgs.
620 unsigned NumTemplateArgs;
622 SourceLocation getLAngleLoc() const { return LAngleLoc; }
623 SourceLocation getRAngleLoc() const { return RAngleLoc; }
625 /// Retrieve the template arguments
626 const TemplateArgumentLoc *getTemplateArgs() const {
627 return getTrailingObjects<TemplateArgumentLoc>();
629 unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
631 llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
632 return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
635 const TemplateArgumentLoc &operator[](unsigned I) const {
636 return getTemplateArgs()[I];
639 static const ASTTemplateArgumentListInfo *
640 Create(ASTContext &C, const TemplateArgumentListInfo &List);
643 /// Represents an explicit template argument list in C++, e.g.,
644 /// the "<int>" in "sort<int>".
646 /// It is intended to be used as a trailing object on AST nodes, and
647 /// as such, doesn't contain the array of TemplateArgumentLoc itself,
648 /// but expects the containing object to also provide storage for
650 struct alignas(void *) ASTTemplateKWAndArgsInfo {
651 /// The source location of the left angle bracket ('<').
652 SourceLocation LAngleLoc;
654 /// The source location of the right angle bracket ('>').
655 SourceLocation RAngleLoc;
657 /// The source location of the template keyword; this is used
658 /// as part of the representation of qualified identifiers, such as
659 /// S<T>::template apply<T>. Will be empty if this expression does
660 /// not have a template keyword.
661 SourceLocation TemplateKWLoc;
663 /// The number of template arguments in TemplateArgs.
664 unsigned NumTemplateArgs;
666 void initializeFrom(SourceLocation TemplateKWLoc,
667 const TemplateArgumentListInfo &List,
668 TemplateArgumentLoc *OutArgArray);
669 void initializeFrom(SourceLocation TemplateKWLoc,
670 const TemplateArgumentListInfo &List,
671 TemplateArgumentLoc *OutArgArray, bool &Dependent,
672 bool &InstantiationDependent,
673 bool &ContainsUnexpandedParameterPack);
674 void initializeFrom(SourceLocation TemplateKWLoc);
676 void copyInto(const TemplateArgumentLoc *ArgArray,
677 TemplateArgumentListInfo &List) const;
680 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
681 const TemplateArgument &Arg);
683 inline TemplateSpecializationType::iterator
684 TemplateSpecializationType::end() const {
685 return getArgs() + getNumArgs();
688 inline DependentTemplateSpecializationType::iterator
689 DependentTemplateSpecializationType::end() const {
690 return getArgs() + getNumArgs();
693 inline const TemplateArgument &
694 TemplateSpecializationType::getArg(unsigned Idx) const {
695 assert(Idx < getNumArgs() && "Template argument out of range");
696 return getArgs()[Idx];
699 inline const TemplateArgument &
700 DependentTemplateSpecializationType::getArg(unsigned Idx) const {
701 assert(Idx < getNumArgs() && "Template argument out of range");
702 return getArgs()[Idx];
707 #endif // LLVM_CLANG_AST_TEMPLATEBASE_H