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
238 /// parameter such that its result can change from one instantiation to
240 bool isDependent() const;
242 /// \brief Whether this template argument is dependent on a template
244 bool isInstantiationDependent() const;
246 /// \brief Whether this template argument contains an unexpanded
248 bool containsUnexpandedParameterPack() const;
250 /// \brief Determine whether this template argument is a pack expansion.
251 bool isPackExpansion() const;
253 /// \brief Retrieve the template argument as a type.
254 QualType getAsType() const {
258 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
261 /// \brief Retrieve the template argument as a declaration.
262 Decl *getAsDecl() const {
263 if (Kind != Declaration)
265 return reinterpret_cast<Decl *>(TypeOrValue);
268 /// \brief Retrieve the template argument as a template name.
269 TemplateName getAsTemplate() const {
270 if (Kind != Template)
271 return TemplateName();
273 return TemplateName::getFromVoidPointer(TemplateArg.Name);
276 /// \brief Retrieve the template argument as a template name; if the argument
277 /// is a pack expansion, return the pattern as a template name.
278 TemplateName getAsTemplateOrTemplatePattern() const {
279 if (Kind != Template && Kind != TemplateExpansion)
280 return TemplateName();
282 return TemplateName::getFromVoidPointer(TemplateArg.Name);
285 /// \brief Retrieve the number of expansions that a template template argument
286 /// expansion will produce, if known.
287 llvm::Optional<unsigned> getNumTemplateExpansions() const;
289 /// \brief Retrieve the template argument as an integral value.
290 llvm::APSInt *getAsIntegral() {
291 if (Kind != Integral)
293 return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
296 const llvm::APSInt *getAsIntegral() const {
297 return const_cast<TemplateArgument*>(this)->getAsIntegral();
300 /// \brief Retrieve the type of the integral value.
301 QualType getIntegralType() const {
302 if (Kind != Integral)
305 return QualType::getFromOpaquePtr(Integer.Type);
308 void setIntegralType(QualType T) {
309 assert(Kind == Integral &&
310 "Cannot set the integral type of a non-integral template argument");
311 Integer.Type = T.getAsOpaquePtr();
314 /// \brief Retrieve the template argument as an expression.
315 Expr *getAsExpr() const {
316 if (Kind != Expression)
319 return reinterpret_cast<Expr *>(TypeOrValue);
322 /// \brief Iterator that traverses the elements of a template argument pack.
323 typedef const TemplateArgument * pack_iterator;
325 /// \brief Iterator referencing the first argument of a template argument
327 pack_iterator pack_begin() const {
328 assert(Kind == Pack);
332 /// \brief Iterator referencing one past the last argument of a template
334 pack_iterator pack_end() const {
335 assert(Kind == Pack);
336 return Args.Args + Args.NumArgs;
339 /// \brief The number of template arguments in the given template argument
341 unsigned pack_size() const {
342 assert(Kind == Pack);
346 /// Determines whether two template arguments are superficially the
348 bool structurallyEquals(const TemplateArgument &Other) const;
350 /// \brief When the template argument is a pack expansion, returns
351 /// the pattern of the pack expansion.
353 /// \param Ellipsis Will be set to the location of the ellipsis.
354 TemplateArgument getPackExpansionPattern() const;
356 /// \brief Print this template argument to the given output stream.
357 void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
359 /// \brief Used to insert TemplateArguments into FoldingSets.
360 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
363 /// Location information for a TemplateArgument.
364 struct TemplateArgumentLocInfo {
368 TypeSourceInfo *Declarator;
370 // FIXME: We'd like to just use the qualifier in the TemplateName,
371 // but template arguments get canonicalized too quickly.
372 NestedNameSpecifier *Qualifier;
373 void *QualifierLocData;
374 unsigned TemplateNameLoc;
375 unsigned EllipsisLoc;
380 TemplateArgumentLocInfo();
382 TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
384 TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
386 TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
387 SourceLocation TemplateNameLoc,
388 SourceLocation EllipsisLoc)
390 Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
391 Template.QualifierLocData = QualifierLoc.getOpaqueData();
392 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
393 Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
396 TypeSourceInfo *getAsTypeSourceInfo() const {
400 Expr *getAsExpr() const {
404 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
405 return NestedNameSpecifierLoc(Template.Qualifier,
406 Template.QualifierLocData);
409 SourceLocation getTemplateNameLoc() const {
410 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
413 SourceLocation getTemplateEllipsisLoc() const {
414 return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
418 /// Location wrapper for a TemplateArgument. TemplateArgument is to
419 /// TemplateArgumentLoc as Type is to TypeLoc.
420 class TemplateArgumentLoc {
421 TemplateArgument Argument;
422 TemplateArgumentLocInfo LocInfo;
425 TemplateArgumentLoc() {}
427 TemplateArgumentLoc(const TemplateArgument &Argument,
428 TemplateArgumentLocInfo Opaque)
429 : Argument(Argument), LocInfo(Opaque) {
432 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
433 : Argument(Argument), LocInfo(TInfo) {
434 assert(Argument.getKind() == TemplateArgument::Type);
437 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
438 : Argument(Argument), LocInfo(E) {
439 assert(Argument.getKind() == TemplateArgument::Expression);
442 TemplateArgumentLoc(const TemplateArgument &Argument,
443 NestedNameSpecifierLoc QualifierLoc,
444 SourceLocation TemplateNameLoc,
445 SourceLocation EllipsisLoc = SourceLocation())
446 : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
447 assert(Argument.getKind() == TemplateArgument::Template ||
448 Argument.getKind() == TemplateArgument::TemplateExpansion);
451 /// \brief - Fetches the primary location of the argument.
452 SourceLocation getLocation() const {
453 if (Argument.getKind() == TemplateArgument::Template ||
454 Argument.getKind() == TemplateArgument::TemplateExpansion)
455 return getTemplateNameLoc();
457 return getSourceRange().getBegin();
460 /// \brief - Fetches the full source range of the argument.
461 SourceRange getSourceRange() const;
463 const TemplateArgument &getArgument() const {
467 TemplateArgumentLocInfo getLocInfo() const {
471 TypeSourceInfo *getTypeSourceInfo() const {
472 assert(Argument.getKind() == TemplateArgument::Type);
473 return LocInfo.getAsTypeSourceInfo();
476 Expr *getSourceExpression() const {
477 assert(Argument.getKind() == TemplateArgument::Expression);
478 return LocInfo.getAsExpr();
481 Expr *getSourceDeclExpression() const {
482 assert(Argument.getKind() == TemplateArgument::Declaration);
483 return LocInfo.getAsExpr();
486 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
487 assert(Argument.getKind() == TemplateArgument::Template ||
488 Argument.getKind() == TemplateArgument::TemplateExpansion);
489 return LocInfo.getTemplateQualifierLoc();
492 SourceLocation getTemplateNameLoc() const {
493 assert(Argument.getKind() == TemplateArgument::Template ||
494 Argument.getKind() == TemplateArgument::TemplateExpansion);
495 return LocInfo.getTemplateNameLoc();
498 SourceLocation getTemplateEllipsisLoc() const {
499 assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
500 return LocInfo.getTemplateEllipsisLoc();
503 /// \brief When the template argument is a pack expansion, returns
504 /// the pattern of the pack expansion.
506 /// \param Ellipsis Will be set to the location of the ellipsis.
508 /// \param NumExpansions Will be set to the number of expansions that will
509 /// be generated from this pack expansion, if known a priori.
510 TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
511 llvm::Optional<unsigned> &NumExpansions,
512 ASTContext &Context) const;
515 /// A convenient class for passing around template argument
516 /// information. Designed to be passed by reference.
517 class TemplateArgumentListInfo {
518 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
519 SourceLocation LAngleLoc;
520 SourceLocation RAngleLoc;
523 TemplateArgumentListInfo() {}
525 TemplateArgumentListInfo(SourceLocation LAngleLoc,
526 SourceLocation RAngleLoc)
527 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
529 SourceLocation getLAngleLoc() const { return LAngleLoc; }
530 SourceLocation getRAngleLoc() const { return RAngleLoc; }
532 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
533 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
535 unsigned size() const { return Arguments.size(); }
537 const TemplateArgumentLoc *getArgumentArray() const {
538 return Arguments.data();
541 const TemplateArgumentLoc &operator[](unsigned I) const {
545 void addArgument(const TemplateArgumentLoc &Loc) {
546 Arguments.push_back(Loc);
550 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
551 const TemplateArgument &Arg);
553 inline TemplateSpecializationType::iterator
554 TemplateSpecializationType::end() const {
555 return getArgs() + getNumArgs();
558 inline DependentTemplateSpecializationType::iterator
559 DependentTemplateSpecializationType::end() const {
560 return getArgs() + getNumArgs();
563 inline const TemplateArgument &
564 TemplateSpecializationType::getArg(unsigned Idx) const {
565 assert(Idx < getNumArgs() && "Template argument out of range");
566 return getArgs()[Idx];
569 inline const TemplateArgument &
570 DependentTemplateSpecializationType::getArg(unsigned Idx) const {
571 assert(Idx < getNumArgs() && "Template argument out of range");
572 return getArgs()[Idx];
575 } // end namespace clang