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;
31 class DiagnosticBuilder;
35 /// \brief Represents a template argument within a class template
37 class TemplateArgument {
39 uintptr_t TypeOrValue;
41 char Value[sizeof(llvm::APSInt)];
45 TemplateArgument *Args;
52 /// \brief The type of template argument we're storing.
54 /// \brief Represents an empty template argument, e.g., one that has not
57 /// The template argument is a type. Its value is stored in the
58 /// TypeOrValue field.
60 /// The template argument is a declaration that was provided for a pointer
61 /// or reference non-type template parameter.
63 /// The template argument is an integral value stored in an llvm::APSInt
64 /// that was provided for an integral non-type template parameter.
66 /// The template argument is a template name that was provided for a
67 /// template template parameter.
69 /// The template argument is a value- or type-dependent expression
70 /// stored in an Expr*.
72 /// The template argument is actually a parameter pack. Arguments are stored
73 /// in the Args struct.
77 /// \brief Construct an empty, invalid template argument.
78 TemplateArgument() : TypeOrValue(0), Kind(Null) { }
80 /// \brief Construct a template type argument.
81 TemplateArgument(QualType T) : Kind(Type) {
82 TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
85 /// \brief Construct a template argument that refers to a
86 /// declaration, which is either an external declaration or a
87 /// template declaration.
88 TemplateArgument(Decl *D) : Kind(Declaration) {
89 // FIXME: Need to be sure we have the "canonical" declaration!
90 TypeOrValue = reinterpret_cast<uintptr_t>(D);
93 /// \brief Construct an integral constant template argument.
94 TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
95 new (Integer.Value) llvm::APSInt(Value);
96 Integer.Type = Type.getAsOpaquePtr();
99 /// \brief Construct a template argument that is a template.
101 /// This form of template argument is generally used for template template
102 /// parameters. However, the template name could be a dependent template
103 /// name that ends up being instantiated to a function template whose address
105 TemplateArgument(TemplateName Name) : Kind(Template) {
106 TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
109 /// \brief Construct a template argument that is an expression.
111 /// This form of template argument only occurs in template argument
112 /// lists used for dependent types and for expression; it will not
113 /// occur in a non-dependent, canonical template argument list.
114 TemplateArgument(Expr *E) : Kind(Expression) {
115 TypeOrValue = reinterpret_cast<uintptr_t>(E);
118 /// \brief Copy constructor for a template argument.
119 TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
120 if (Kind == Integral) {
121 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
122 Integer.Type = Other.Integer.Type;
123 } else if (Kind == Pack) {
124 Args.NumArgs = Other.Args.NumArgs;
125 Args.Args = new TemplateArgument[Args.NumArgs];
126 for (unsigned I = 0; I != Args.NumArgs; ++I)
127 Args.Args[I] = Other.Args.Args[I];
130 TypeOrValue = Other.TypeOrValue;
133 TemplateArgument& operator=(const TemplateArgument& Other) {
134 // FIXME: Does not provide the strong guarantee for exception
138 // FIXME: Handle Packs
139 assert(Kind != Pack && "FIXME: Handle packs");
140 assert(Other.Kind != Pack && "FIXME: Handle packs");
142 if (Kind == Other.Kind && Kind == Integral) {
143 // Copy integral values.
144 *this->getAsIntegral() = *Other.getAsIntegral();
145 Integer.Type = Other.Integer.Type;
147 // Destroy the current integral value, if that's what we're holding.
148 if (Kind == Integral)
149 getAsIntegral()->~APSInt();
153 if (Other.Kind == Integral) {
154 new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
155 Integer.Type = Other.Integer.Type;
157 TypeOrValue = Other.TypeOrValue;
163 ~TemplateArgument() {
166 if (Kind == Integral)
167 getAsIntegral()->~APSInt();
168 else if (Kind == Pack && Args.CopyArgs)
172 /// \brief Return the kind of stored template argument.
173 ArgKind getKind() const { return Kind; }
175 /// \brief Determine whether this template argument has no value.
176 bool isNull() const { return Kind == Null; }
178 /// \brief Retrieve the template argument as a type.
179 QualType getAsType() const {
183 return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
186 /// \brief Retrieve the template argument as a declaration.
187 Decl *getAsDecl() const {
188 if (Kind != Declaration)
190 return reinterpret_cast<Decl *>(TypeOrValue);
193 /// \brief Retrieve the template argument as a template name.
194 TemplateName getAsTemplate() const {
195 if (Kind != Template)
196 return TemplateName();
198 return TemplateName::getFromVoidPointer(
199 reinterpret_cast<void *> (TypeOrValue));
202 /// \brief Retrieve the template argument as an integral value.
203 llvm::APSInt *getAsIntegral() {
204 if (Kind != Integral)
206 return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
209 const llvm::APSInt *getAsIntegral() const {
210 return const_cast<TemplateArgument*>(this)->getAsIntegral();
213 /// \brief Retrieve the type of the integral value.
214 QualType getIntegralType() const {
215 if (Kind != Integral)
218 return QualType::getFromOpaquePtr(Integer.Type);
221 void setIntegralType(QualType T) {
222 assert(Kind == Integral &&
223 "Cannot set the integral type of a non-integral template argument");
224 Integer.Type = T.getAsOpaquePtr();
227 /// \brief Retrieve the template argument as an expression.
228 Expr *getAsExpr() const {
229 if (Kind != Expression)
232 return reinterpret_cast<Expr *>(TypeOrValue);
235 /// \brief Iterator that traverses the elements of a template argument pack.
236 typedef const TemplateArgument * pack_iterator;
238 /// \brief Iterator referencing the first argument of a template argument
240 pack_iterator pack_begin() const {
241 assert(Kind == Pack);
245 /// \brief Iterator referencing one past the last argument of a template
247 pack_iterator pack_end() const {
248 assert(Kind == Pack);
249 return Args.Args + Args.NumArgs;
252 /// \brief The number of template arguments in the given template argument
254 unsigned pack_size() const {
255 assert(Kind == Pack);
259 /// Determines whether two template arguments are superficially the
261 bool structurallyEquals(const TemplateArgument &Other) const;
263 /// \brief Construct a template argument pack.
264 void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
266 /// \brief Used to insert TemplateArguments into FoldingSets.
267 void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
270 /// Location information for a TemplateArgument.
271 struct TemplateArgumentLocInfo {
275 TypeSourceInfo *Declarator;
277 unsigned QualifierRange[2];
278 unsigned TemplateNameLoc;
292 TemplateArgumentLocInfo()
299 TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
302 , Kind(K_TypeSourceInfo)
306 TemplateArgumentLocInfo(Expr *E)
313 TemplateArgumentLocInfo(SourceRange QualifierRange,
314 SourceLocation TemplateNameLoc)
319 Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
320 Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
321 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
324 TypeSourceInfo *getAsTypeSourceInfo() const {
325 assert(Kind == K_TypeSourceInfo);
329 Expr *getAsExpr() const {
330 assert(Kind == K_Expression);
334 SourceRange getTemplateQualifierRange() const {
335 assert(Kind == K_Template);
337 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
338 SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
341 SourceLocation getTemplateNameLoc() const {
342 assert(Kind == K_Template);
343 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
347 void validateForArgument(const TemplateArgument &Arg) {
348 switch (Arg.getKind()) {
349 case TemplateArgument::Type:
350 assert(Kind == K_TypeSourceInfo);
352 case TemplateArgument::Expression:
353 case TemplateArgument::Declaration:
354 assert(Kind == K_Expression);
356 case TemplateArgument::Template:
357 assert(Kind == K_Template);
359 case TemplateArgument::Integral:
360 case TemplateArgument::Pack:
361 assert(Kind == K_None);
363 case TemplateArgument::Null:
364 llvm_unreachable("source info for null template argument?");
370 /// Location wrapper for a TemplateArgument. TemplateArgument is to
371 /// TemplateArgumentLoc as Type is to TypeLoc.
372 class TemplateArgumentLoc {
373 TemplateArgument Argument;
374 TemplateArgumentLocInfo LocInfo;
377 TemplateArgumentLoc() {}
379 TemplateArgumentLoc(const TemplateArgument &Argument,
380 TemplateArgumentLocInfo Opaque)
381 : Argument(Argument), LocInfo(Opaque) {
384 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
385 : Argument(Argument), LocInfo(TInfo) {
386 assert(Argument.getKind() == TemplateArgument::Type);
389 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
390 : Argument(Argument), LocInfo(E) {
391 assert(Argument.getKind() == TemplateArgument::Expression);
394 TemplateArgumentLoc(const TemplateArgument &Argument,
395 SourceRange QualifierRange,
396 SourceLocation TemplateNameLoc)
397 : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
398 assert(Argument.getKind() == TemplateArgument::Template);
401 /// \brief - Fetches the primary location of the argument.
402 SourceLocation getLocation() const {
403 if (Argument.getKind() == TemplateArgument::Template)
404 return getTemplateNameLoc();
406 return getSourceRange().getBegin();
409 /// \brief - Fetches the full source range of the argument.
410 SourceRange getSourceRange() const;
412 const TemplateArgument &getArgument() const {
416 TemplateArgumentLocInfo getLocInfo() const {
420 TypeSourceInfo *getTypeSourceInfo() const {
421 assert(Argument.getKind() == TemplateArgument::Type);
422 return LocInfo.getAsTypeSourceInfo();
425 Expr *getSourceExpression() const {
426 assert(Argument.getKind() == TemplateArgument::Expression);
427 return LocInfo.getAsExpr();
430 Expr *getSourceDeclExpression() const {
431 assert(Argument.getKind() == TemplateArgument::Declaration);
432 return LocInfo.getAsExpr();
435 SourceRange getTemplateQualifierRange() const {
436 assert(Argument.getKind() == TemplateArgument::Template);
437 return LocInfo.getTemplateQualifierRange();
440 SourceLocation getTemplateNameLoc() const {
441 assert(Argument.getKind() == TemplateArgument::Template);
442 return LocInfo.getTemplateNameLoc();
446 /// A convenient class for passing around template argument
447 /// information. Designed to be passed by reference.
448 class TemplateArgumentListInfo {
449 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
450 SourceLocation LAngleLoc;
451 SourceLocation RAngleLoc;
454 TemplateArgumentListInfo() {}
456 TemplateArgumentListInfo(SourceLocation LAngleLoc,
457 SourceLocation RAngleLoc)
458 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
460 SourceLocation getLAngleLoc() const { return LAngleLoc; }
461 SourceLocation getRAngleLoc() const { return RAngleLoc; }
463 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
464 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
466 unsigned size() const { return Arguments.size(); }
468 const TemplateArgumentLoc *getArgumentArray() const {
469 return Arguments.data();
472 const TemplateArgumentLoc &operator[](unsigned I) const {
476 void addArgument(const TemplateArgumentLoc &Loc) {
477 Arguments.push_back(Loc);
481 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
482 const TemplateArgument &Arg);
484 inline TemplateSpecializationType::iterator
485 TemplateSpecializationType::end() const {
486 return getArgs() + getNumArgs();
489 inline DependentTemplateSpecializationType::iterator
490 DependentTemplateSpecializationType::end() const {
491 return getArgs() + getNumArgs();
494 inline const TemplateArgument &
495 TemplateSpecializationType::getArg(unsigned Idx) const {
496 assert(Idx < getNumArgs() && "Template argument out of range");
497 return getArgs()[Idx];
500 inline const TemplateArgument &
501 DependentTemplateSpecializationType::getArg(unsigned Idx) const {
502 assert(Idx < getNumArgs() && "Template argument out of range");
503 return getArgs()[Idx];
506 } // end namespace clang