1 //===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file provides definitions which are common for all kinds of
11 // template representation.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
16 #define LLVM_CLANG_AST_TEMPLATEBASE_H
18 #include "llvm/ADT/APSInt.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "clang/AST/Type.h"
22 #include "clang/AST/TemplateName.h"
25 class FoldingSetNodeID;
32 class DiagnosticBuilder;
34 struct PrintingPolicy;
37 /// \brief Represents a template argument within a class template
39 class TemplateArgument {
41 /// \brief The kind of template argument we're storing.
43 /// \brief Represents an empty template argument, e.g., one that has not
46 /// The template argument is a type. Its value is stored in the
47 /// TypeOrValue field.
49 /// The template argument is a declaration that was provided for a pointer
50 /// or reference non-type template parameter.
52 /// The template argument is an integral value stored in an llvm::APSInt
53 /// that was provided for an integral non-type template parameter.
55 /// The template argument is a template name that was provided for a
56 /// template template parameter.
58 /// The template argument is a pack expansion of a template name that was
59 /// provided for a template template parameter.
61 /// The template argument is a value- or type-dependent expression
62 /// stored in an Expr*.
64 /// The template argument is actually a parameter pack. Arguments are stored
65 /// in the Args struct.
70 /// \brief The kind of template argument we're storing.
74 uintptr_t TypeOrValue;
76 char Value[sizeof(llvm::APSInt)];
80 const TemplateArgument *Args;
85 unsigned NumExpansions;
89 TemplateArgument(TemplateName, bool); // DO NOT USE
92 /// \brief Construct an empty, invalid template argument.
93 TemplateArgument() : Kind(Null), TypeOrValue(0) { }
95 /// \brief Construct a template type argument.
96 TemplateArgument(QualType T) : Kind(Type) {
97 TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
100 /// \brief Construct a template argument that refers to a
101 /// declaration, which is either an external declaration or a
102 /// template declaration.
103 TemplateArgument(Decl *D) : Kind(Declaration) {
104 // FIXME: Need to be sure we have the "canonical" declaration!
105 TypeOrValue = reinterpret_cast<uintptr_t>(D);
108 /// \brief Construct an integral constant template argument.
109 TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
110 // FIXME: Large integral values will get leaked. Do something
111 // similar to what we did with IntegerLiteral.
112 new (Integer.Value) llvm::APSInt(Value);
113 Integer.Type = Type.getAsOpaquePtr();
116 /// \brief Construct a template argument that is a template.
118 /// This form of template argument is generally used for template template
119 /// parameters. However, the template name could be a dependent template
120 /// name that ends up being instantiated to a function template whose address
123 /// \param Name The template name.
124 TemplateArgument(TemplateName Name) : Kind(Template)
126 TemplateArg.Name = Name.getAsVoidPointer();
127 TemplateArg.NumExpansions = 0;
130 /// \brief Construct a template argument that is a template pack expansion.
132 /// This form of template argument is generally used for template template
133 /// parameters. However, the template name could be a dependent template
134 /// name that ends up being instantiated to a function template whose address
137 /// \param Name The template name.
139 /// \param NumExpansions The number of expansions that will be generated by
141 TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
142 : Kind(TemplateExpansion)
144 TemplateArg.Name = Name.getAsVoidPointer();
146 TemplateArg.NumExpansions = *NumExpansions + 1;
148 TemplateArg.NumExpansions = 0;
151 /// \brief Construct a template argument that is an expression.
153 /// This form of template argument only occurs in template argument
154 /// lists used for dependent types and for expression; it will not
155 /// occur in a non-dependent, canonical template argument list.
156 TemplateArgument(Expr *E) : Kind(Expression) {
157 TypeOrValue = reinterpret_cast<uintptr_t>(E);
160 /// \brief Construct a template argument that is a template argument pack.
162 /// We assume that storage for the template arguments provided
163 /// outlives the TemplateArgument itself.
164 TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
165 this->Args.Args = Args;
166 this->Args.NumArgs = NumArgs;
169 /// \brief Copy constructor for a template argument.
170 TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
171 // FIXME: Large integral values will get leaked. Do something
172 // similar to what we did with IntegerLiteral.
173 if (Kind == Integral) {
174 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
175 Integer.Type = Other.Integer.Type;
176 } else if (Kind == Pack) {
177 Args.NumArgs = Other.Args.NumArgs;
178 Args.Args = Other.Args.Args;
179 } else if (Kind == Template || Kind == TemplateExpansion) {
180 TemplateArg.Name = Other.TemplateArg.Name;
181 TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
183 TypeOrValue = Other.TypeOrValue;
186 TemplateArgument& operator=(const TemplateArgument& Other) {
189 if (Kind == Other.Kind && Kind == Integral) {
190 // Copy integral values.
191 *this->getAsIntegral() = *Other.getAsIntegral();
192 Integer.Type = Other.Integer.Type;
196 // Destroy the current integral value, if that's what we're holding.
197 if (Kind == Integral)
198 getAsIntegral()->~APSInt();
202 if (Other.Kind == Integral) {
203 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
204 Integer.Type = Other.Integer.Type;
205 } else if (Other.Kind == Pack) {
206 Args.NumArgs = Other.Args.NumArgs;
207 Args.Args = Other.Args.Args;
208 } else if (Kind == Template || Kind == TemplateExpansion) {
209 TemplateArg.Name = Other.TemplateArg.Name;
210 TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
212 TypeOrValue = Other.TypeOrValue;
218 ~TemplateArgument() {
221 if (Kind == Integral)
222 getAsIntegral()->~APSInt();
225 /// \brief Create a new template argument pack by copying the given set of
226 /// template arguments.
227 static TemplateArgument CreatePackCopy(ASTContext &Context,
228 const TemplateArgument *Args,
231 /// \brief Return the kind of stored template argument.
232 ArgKind getKind() const { return (ArgKind)Kind; }
234 /// \brief Determine whether this template argument has no value.
235 bool isNull() const { return Kind == Null; }
237 /// \brief Whether this template argument is dependent on a template
239 bool isDependent() const;
241 /// \brief Whether this template argument contains an unexpanded
243 bool containsUnexpandedParameterPack() const;
245 /// \brief Determine whether this template argument is a pack expansion.
246 bool isPackExpansion() const;
248 /// \brief Retrieve the template argument as a type.
249 QualType getAsType() const {
253 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
256 /// \brief Retrieve the template argument as a declaration.
257 Decl *getAsDecl() const {
258 if (Kind != Declaration)
260 return reinterpret_cast<Decl *>(TypeOrValue);
263 /// \brief Retrieve the template argument as a template name.
264 TemplateName getAsTemplate() const {
265 if (Kind != Template)
266 return TemplateName();
268 return TemplateName::getFromVoidPointer(TemplateArg.Name);
271 /// \brief Retrieve the template argument as a template name; if the argument
272 /// is a pack expansion, return the pattern as a template name.
273 TemplateName getAsTemplateOrTemplatePattern() const {
274 if (Kind != Template && Kind != TemplateExpansion)
275 return TemplateName();
277 return TemplateName::getFromVoidPointer(TemplateArg.Name);
280 /// \brief Retrieve the number of expansions that a template template argument
281 /// expansion will produce, if known.
282 llvm::Optional<unsigned> getNumTemplateExpansions() const;
284 /// \brief Retrieve the template argument as an integral value.
285 llvm::APSInt *getAsIntegral() {
286 if (Kind != Integral)
288 return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
291 const llvm::APSInt *getAsIntegral() const {
292 return const_cast<TemplateArgument*>(this)->getAsIntegral();
295 /// \brief Retrieve the type of the integral value.
296 QualType getIntegralType() const {
297 if (Kind != Integral)
300 return QualType::getFromOpaquePtr(Integer.Type);
303 void setIntegralType(QualType T) {
304 assert(Kind == Integral &&
305 "Cannot set the integral type of a non-integral template argument");
306 Integer.Type = T.getAsOpaquePtr();
309 /// \brief Retrieve the template argument as an expression.
310 Expr *getAsExpr() const {
311 if (Kind != Expression)
314 return reinterpret_cast<Expr *>(TypeOrValue);
317 /// \brief Iterator that traverses the elements of a template argument pack.
318 typedef const TemplateArgument * pack_iterator;
320 /// \brief Iterator referencing the first argument of a template argument
322 pack_iterator pack_begin() const {
323 assert(Kind == Pack);
327 /// \brief Iterator referencing one past the last argument of a template
329 pack_iterator pack_end() const {
330 assert(Kind == Pack);
331 return Args.Args + Args.NumArgs;
334 /// \brief The number of template arguments in the given template argument
336 unsigned pack_size() const {
337 assert(Kind == Pack);
341 /// Determines whether two template arguments are superficially the
343 bool structurallyEquals(const TemplateArgument &Other) const;
345 /// \brief When the template argument is a pack expansion, returns
346 /// the pattern of the pack expansion.
348 /// \param Ellipsis Will be set to the location of the ellipsis.
349 TemplateArgument getPackExpansionPattern() const;
351 /// \brief Print this template argument to the given output stream.
352 void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
354 /// \brief Used to insert TemplateArguments into FoldingSets.
355 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
358 /// Location information for a TemplateArgument.
359 struct TemplateArgumentLocInfo {
363 TypeSourceInfo *Declarator;
365 unsigned QualifierRange[2];
366 unsigned TemplateNameLoc;
367 unsigned EllipsisLoc;
372 TemplateArgumentLocInfo();
374 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
376 TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
378 TemplateArgumentLocInfo(SourceRange QualifierRange,
379 SourceLocation TemplateNameLoc,
380 SourceLocation EllipsisLoc)
382 Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
383 Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
384 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
385 Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
388 TypeSourceInfo *getAsTypeSourceInfo() const {
392 Expr *getAsExpr() const {
396 SourceRange getTemplateQualifierRange() const {
398 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
399 SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
402 SourceLocation getTemplateNameLoc() const {
403 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
406 SourceLocation getTemplateEllipsisLoc() const {
407 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
411 /// Location wrapper for a TemplateArgument. TemplateArgument is to
412 /// TemplateArgumentLoc as Type is to TypeLoc.
413 class TemplateArgumentLoc {
414 TemplateArgument Argument;
415 TemplateArgumentLocInfo LocInfo;
418 TemplateArgumentLoc() {}
420 TemplateArgumentLoc(const TemplateArgument &Argument,
421 TemplateArgumentLocInfo Opaque)
422 : Argument(Argument), LocInfo(Opaque) {
425 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
426 : Argument(Argument), LocInfo(TInfo) {
427 assert(Argument.getKind() == TemplateArgument::Type);
430 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
431 : Argument(Argument), LocInfo(E) {
432 assert(Argument.getKind() == TemplateArgument::Expression);
435 TemplateArgumentLoc(const TemplateArgument &Argument,
436 SourceRange QualifierRange,
437 SourceLocation TemplateNameLoc,
438 SourceLocation EllipsisLoc = SourceLocation())
439 : Argument(Argument),
440 LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) {
441 assert(Argument.getKind() == TemplateArgument::Template ||
442 Argument.getKind() == TemplateArgument::TemplateExpansion);
445 /// \brief - Fetches the primary location of the argument.
446 SourceLocation getLocation() const {
447 if (Argument.getKind() == TemplateArgument::Template ||
448 Argument.getKind() == TemplateArgument::TemplateExpansion)
449 return getTemplateNameLoc();
451 return getSourceRange().getBegin();
454 /// \brief - Fetches the full source range of the argument.
455 SourceRange getSourceRange() const;
457 const TemplateArgument &getArgument() const {
461 TemplateArgumentLocInfo getLocInfo() const {
465 TypeSourceInfo *getTypeSourceInfo() const {
466 assert(Argument.getKind() == TemplateArgument::Type);
467 return LocInfo.getAsTypeSourceInfo();
470 Expr *getSourceExpression() const {
471 assert(Argument.getKind() == TemplateArgument::Expression);
472 return LocInfo.getAsExpr();
475 Expr *getSourceDeclExpression() const {
476 assert(Argument.getKind() == TemplateArgument::Declaration);
477 return LocInfo.getAsExpr();
480 SourceRange getTemplateQualifierRange() const {
481 assert(Argument.getKind() == TemplateArgument::Template ||
482 Argument.getKind() == TemplateArgument::TemplateExpansion);
483 return LocInfo.getTemplateQualifierRange();
486 SourceLocation getTemplateNameLoc() const {
487 assert(Argument.getKind() == TemplateArgument::Template ||
488 Argument.getKind() == TemplateArgument::TemplateExpansion);
489 return LocInfo.getTemplateNameLoc();
492 SourceLocation getTemplateEllipsisLoc() const {
493 assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
494 return LocInfo.getTemplateEllipsisLoc();
497 /// \brief When the template argument is a pack expansion, returns
498 /// the pattern of the pack expansion.
500 /// \param Ellipsis Will be set to the location of the ellipsis.
502 /// \param NumExpansions Will be set to the number of expansions that will
503 /// be generated from this pack expansion, if known a priori.
504 TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
505 llvm::Optional<unsigned> &NumExpansions,
506 ASTContext &Context) const;
509 /// A convenient class for passing around template argument
510 /// information. Designed to be passed by reference.
511 class TemplateArgumentListInfo {
512 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
513 SourceLocation LAngleLoc;
514 SourceLocation RAngleLoc;
517 TemplateArgumentListInfo() {}
519 TemplateArgumentListInfo(SourceLocation LAngleLoc,
520 SourceLocation RAngleLoc)
521 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
523 SourceLocation getLAngleLoc() const { return LAngleLoc; }
524 SourceLocation getRAngleLoc() const { return RAngleLoc; }
526 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
527 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
529 unsigned size() const { return Arguments.size(); }
531 const TemplateArgumentLoc *getArgumentArray() const {
532 return Arguments.data();
535 const TemplateArgumentLoc &operator[](unsigned I) const {
539 void addArgument(const TemplateArgumentLoc &Loc) {
540 Arguments.push_back(Loc);
544 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
545 const TemplateArgument &Arg);
547 inline TemplateSpecializationType::iterator
548 TemplateSpecializationType::end() const {
549 return getArgs() + getNumArgs();
552 inline DependentTemplateSpecializationType::iterator
553 DependentTemplateSpecializationType::end() const {
554 return getArgs() + getNumArgs();
557 inline const TemplateArgument &
558 TemplateSpecializationType::getArg(unsigned Idx) const {
559 assert(Idx < getNumArgs() && "Template argument out of range");
560 return getArgs()[Idx];
563 inline const TemplateArgument &
564 DependentTemplateSpecializationType::getArg(unsigned Idx) const {
565 assert(Idx < getNumArgs() && "Template argument out of range");
566 return getArgs()[Idx];
569 } // end namespace clang