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 /// \brief Construct a template argument pack.
260 void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
262 /// \brief Used to insert TemplateArguments into FoldingSets.
263 void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
266 /// Location information for a TemplateArgument.
267 struct TemplateArgumentLocInfo {
271 TypeSourceInfo *Declarator;
273 unsigned QualifierRange[2];
274 unsigned TemplateNameLoc;
288 TemplateArgumentLocInfo()
295 TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
298 , Kind(K_TypeSourceInfo)
302 TemplateArgumentLocInfo(Expr *E)
309 TemplateArgumentLocInfo(SourceRange QualifierRange,
310 SourceLocation TemplateNameLoc)
315 Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
316 Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
317 Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
320 TypeSourceInfo *getAsTypeSourceInfo() const {
321 assert(Kind == K_TypeSourceInfo);
325 Expr *getAsExpr() const {
326 assert(Kind == K_Expression);
330 SourceRange getTemplateQualifierRange() const {
331 assert(Kind == K_Template);
333 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
334 SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
337 SourceLocation getTemplateNameLoc() const {
338 assert(Kind == K_Template);
339 return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
343 void validateForArgument(const TemplateArgument &Arg) {
344 switch (Arg.getKind()) {
345 case TemplateArgument::Type:
346 assert(Kind == K_TypeSourceInfo);
348 case TemplateArgument::Expression:
349 case TemplateArgument::Declaration:
350 assert(Kind == K_Expression);
352 case TemplateArgument::Template:
353 assert(Kind == K_Template);
355 case TemplateArgument::Integral:
356 case TemplateArgument::Pack:
357 assert(Kind == K_None);
359 case TemplateArgument::Null:
360 llvm_unreachable("source info for null template argument?");
366 /// Location wrapper for a TemplateArgument. TemplateArgument is to
367 /// TemplateArgumentLoc as Type is to TypeLoc.
368 class TemplateArgumentLoc {
369 TemplateArgument Argument;
370 TemplateArgumentLocInfo LocInfo;
373 TemplateArgumentLoc() {}
375 TemplateArgumentLoc(const TemplateArgument &Argument,
376 TemplateArgumentLocInfo Opaque)
377 : Argument(Argument), LocInfo(Opaque) {
380 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
381 : Argument(Argument), LocInfo(TInfo) {
382 assert(Argument.getKind() == TemplateArgument::Type);
385 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
386 : Argument(Argument), LocInfo(E) {
387 assert(Argument.getKind() == TemplateArgument::Expression);
390 TemplateArgumentLoc(const TemplateArgument &Argument,
391 SourceRange QualifierRange,
392 SourceLocation TemplateNameLoc)
393 : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
394 assert(Argument.getKind() == TemplateArgument::Template);
397 /// \brief - Fetches the primary location of the argument.
398 SourceLocation getLocation() const {
399 if (Argument.getKind() == TemplateArgument::Template)
400 return getTemplateNameLoc();
402 return getSourceRange().getBegin();
405 /// \brief - Fetches the full source range of the argument.
406 SourceRange getSourceRange() const;
408 const TemplateArgument &getArgument() const {
412 TemplateArgumentLocInfo getLocInfo() const {
416 TypeSourceInfo *getTypeSourceInfo() const {
417 assert(Argument.getKind() == TemplateArgument::Type);
418 return LocInfo.getAsTypeSourceInfo();
421 Expr *getSourceExpression() const {
422 assert(Argument.getKind() == TemplateArgument::Expression);
423 return LocInfo.getAsExpr();
426 Expr *getSourceDeclExpression() const {
427 assert(Argument.getKind() == TemplateArgument::Declaration);
428 return LocInfo.getAsExpr();
431 SourceRange getTemplateQualifierRange() const {
432 assert(Argument.getKind() == TemplateArgument::Template);
433 return LocInfo.getTemplateQualifierRange();
436 SourceLocation getTemplateNameLoc() const {
437 assert(Argument.getKind() == TemplateArgument::Template);
438 return LocInfo.getTemplateNameLoc();
442 /// A convenient class for passing around template argument
443 /// information. Designed to be passed by reference.
444 class TemplateArgumentListInfo {
445 llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
446 SourceLocation LAngleLoc;
447 SourceLocation RAngleLoc;
450 TemplateArgumentListInfo() {}
452 TemplateArgumentListInfo(SourceLocation LAngleLoc,
453 SourceLocation RAngleLoc)
454 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
456 SourceLocation getLAngleLoc() const { return LAngleLoc; }
457 SourceLocation getRAngleLoc() const { return RAngleLoc; }
459 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
460 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
462 unsigned size() const { return Arguments.size(); }
464 const TemplateArgumentLoc *getArgumentArray() const {
465 return Arguments.data();
468 const TemplateArgumentLoc &operator[](unsigned I) const {
472 void addArgument(const TemplateArgumentLoc &Loc) {
473 Arguments.push_back(Loc);
477 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
478 const TemplateArgument &Arg);
480 } // end namespace clang