TemplateBase.h revision d5532b6cfff2977e0c59fa6ead7f7973984a620d
1//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file provides definitions which are common for all kinds of
11//  template representation.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
16#define LLVM_CLANG_AST_TEMPLATEBASE_H
17
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"
23
24namespace llvm {
25  class FoldingSetNodeID;
26}
27
28namespace clang {
29
30class Decl;
31class Expr;
32class DeclaratorInfo;
33
34/// \brief Represents a template argument within a class template
35/// specialization.
36class TemplateArgument {
37  union {
38    uintptr_t TypeOrValue;
39    struct {
40      char Value[sizeof(llvm::APSInt)];
41      void *Type;
42    } Integer;
43    struct {
44      TemplateArgument *Args;
45      unsigned NumArgs;
46      bool CopyArgs;
47    } Args;
48  };
49
50public:
51  /// \brief The type of template argument we're storing.
52  enum ArgKind {
53    /// \brief Represents an empty template argument, e.g., one that has not
54    /// been deduced.
55    Null = 0,
56    /// The template argument is a type. Its value is stored in the
57    /// TypeOrValue field.
58    Type,
59    /// The template argument is a declaration that was provided for a pointer
60    /// or reference non-type template parameter.
61    Declaration,
62    /// The template argument is an integral value stored in an llvm::APSInt
63    /// that was provided for an integral non-type template parameter.
64    Integral,
65    /// The template argument is a template name that was provided for a
66    /// template template parameter.
67    Template,
68    /// The template argument is a value- or type-dependent expression
69    /// stored in an Expr*.
70    Expression,
71    /// The template argument is actually a parameter pack. Arguments are stored
72    /// in the Args struct.
73    Pack
74  } Kind;
75
76  /// \brief Construct an empty, invalid template argument.
77  TemplateArgument() : TypeOrValue(0), Kind(Null) { }
78
79  /// \brief Construct a template type argument.
80  TemplateArgument(QualType T) : Kind(Type) {
81    TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
82  }
83
84  /// \brief Construct a template argument that refers to a
85  /// declaration, which is either an external declaration or a
86  /// template declaration.
87  TemplateArgument(Decl *D) : Kind(Declaration) {
88    // FIXME: Need to be sure we have the "canonical" declaration!
89    TypeOrValue = reinterpret_cast<uintptr_t>(D);
90  }
91
92  /// \brief Construct an integral constant template argument.
93  TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
94    new (Integer.Value) llvm::APSInt(Value);
95    Integer.Type = Type.getAsOpaquePtr();
96  }
97
98  /// \brief Construct a template argument that is a template.
99  ///
100  /// This form of template argument is generally used for template template
101  /// parameters. However, the template name could be a dependent template
102  /// name that ends up being instantiated to a function template whose address
103  /// is taken.
104  TemplateArgument(TemplateName Name) : Kind(Template) {
105    TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
106  }
107
108  /// \brief Construct a template argument that is an expression.
109  ///
110  /// This form of template argument only occurs in template argument
111  /// lists used for dependent types and for expression; it will not
112  /// occur in a non-dependent, canonical template argument list.
113  TemplateArgument(Expr *E) : Kind(Expression) {
114    TypeOrValue = reinterpret_cast<uintptr_t>(E);
115  }
116
117  /// \brief Copy constructor for a template argument.
118  TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
119    if (Kind == Integral) {
120      new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
121      Integer.Type = Other.Integer.Type;
122    } else if (Kind == Pack) {
123      Args.NumArgs = Other.Args.NumArgs;
124      Args.Args = new TemplateArgument[Args.NumArgs];
125      for (unsigned I = 0; I != Args.NumArgs; ++I)
126        Args.Args[I] = Other.Args.Args[I];
127    }
128    else
129      TypeOrValue = Other.TypeOrValue;
130  }
131
132  TemplateArgument& operator=(const TemplateArgument& Other) {
133    // FIXME: Does not provide the strong guarantee for exception
134    // safety.
135    using llvm::APSInt;
136
137    // FIXME: Handle Packs
138    assert(Kind != Pack && "FIXME: Handle packs");
139    assert(Other.Kind != Pack && "FIXME: Handle packs");
140
141    if (Kind == Other.Kind && Kind == Integral) {
142      // Copy integral values.
143      *this->getAsIntegral() = *Other.getAsIntegral();
144      Integer.Type = Other.Integer.Type;
145    } else {
146      // Destroy the current integral value, if that's what we're holding.
147      if (Kind == Integral)
148        getAsIntegral()->~APSInt();
149
150      Kind = Other.Kind;
151
152      if (Other.Kind == Integral) {
153        new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
154        Integer.Type = Other.Integer.Type;
155      } else
156        TypeOrValue = Other.TypeOrValue;
157    }
158
159    return *this;
160  }
161
162  ~TemplateArgument() {
163    using llvm::APSInt;
164
165    if (Kind == Integral)
166      getAsIntegral()->~APSInt();
167    else if (Kind == Pack && Args.CopyArgs)
168      delete[] Args.Args;
169  }
170
171  /// \brief Return the kind of stored template argument.
172  ArgKind getKind() const { return Kind; }
173
174  /// \brief Determine whether this template argument has no value.
175  bool isNull() const { return Kind == Null; }
176
177  /// \brief Retrieve the template argument as a type.
178  QualType getAsType() const {
179    if (Kind != Type)
180      return QualType();
181
182    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
183  }
184
185  /// \brief Retrieve the template argument as a declaration.
186  Decl *getAsDecl() const {
187    if (Kind != Declaration)
188      return 0;
189    return reinterpret_cast<Decl *>(TypeOrValue);
190  }
191
192  /// \brief Retrieve the template argument as a template name.
193  TemplateName getAsTemplate() const {
194    if (Kind != Template)
195      return TemplateName();
196
197    return TemplateName::getFromVoidPointer(
198                                        reinterpret_cast<void *> (TypeOrValue));
199  }
200
201  /// \brief Retrieve the template argument as an integral value.
202  llvm::APSInt *getAsIntegral() {
203    if (Kind != Integral)
204      return 0;
205    return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
206  }
207
208  const llvm::APSInt *getAsIntegral() const {
209    return const_cast<TemplateArgument*>(this)->getAsIntegral();
210  }
211
212  /// \brief Retrieve the type of the integral value.
213  QualType getIntegralType() const {
214    if (Kind != Integral)
215      return QualType();
216
217    return QualType::getFromOpaquePtr(Integer.Type);
218  }
219
220  void setIntegralType(QualType T) {
221    assert(Kind == Integral &&
222           "Cannot set the integral type of a non-integral template argument");
223    Integer.Type = T.getAsOpaquePtr();
224  };
225
226  /// \brief Retrieve the template argument as an expression.
227  Expr *getAsExpr() const {
228    if (Kind != Expression)
229      return 0;
230
231    return reinterpret_cast<Expr *>(TypeOrValue);
232  }
233
234  /// \brief Iterator that traverses the elements of a template argument pack.
235  typedef const TemplateArgument * pack_iterator;
236
237  /// \brief Iterator referencing the first argument of a template argument
238  /// pack.
239  pack_iterator pack_begin() const {
240    assert(Kind == Pack);
241    return Args.Args;
242  }
243
244  /// \brief Iterator referencing one past the last argument of a template
245  /// argument pack.
246  pack_iterator pack_end() const {
247    assert(Kind == Pack);
248    return Args.Args + Args.NumArgs;
249  }
250
251  /// \brief The number of template arguments in the given template argument
252  /// pack.
253  unsigned pack_size() const {
254    assert(Kind == Pack);
255    return Args.NumArgs;
256  }
257
258  /// \brief Construct a template argument pack.
259  void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
260
261  /// \brief Used to insert TemplateArguments into FoldingSets.
262  void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
263};
264
265/// Location information for a TemplateArgument.
266struct TemplateArgumentLocInfo {
267private:
268  union {
269    Expr *Expression;
270    DeclaratorInfo *Declarator;
271    struct {
272      unsigned QualifierRange[2];
273      unsigned TemplateNameLoc;
274    } Template;
275  };
276
277#ifndef NDEBUG
278  enum Kind {
279    K_None,
280    K_DeclaratorInfo,
281    K_Expression,
282    K_Template
283  } Kind;
284#endif
285
286public:
287  TemplateArgumentLocInfo()
288    : Expression(0)
289#ifndef NDEBUG
290      , Kind(K_None)
291#endif
292    {}
293
294  TemplateArgumentLocInfo(DeclaratorInfo *DInfo)
295    : Declarator(DInfo)
296#ifndef NDEBUG
297      , Kind(K_DeclaratorInfo)
298#endif
299    {}
300
301  TemplateArgumentLocInfo(Expr *E)
302    : Expression(E)
303#ifndef NDEBUG
304      , Kind(K_Expression)
305#endif
306    {}
307
308  TemplateArgumentLocInfo(SourceRange QualifierRange,
309                          SourceLocation TemplateNameLoc)
310#ifndef NDEBUG
311    : Kind(K_Template)
312#endif
313  {
314    Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
315    Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
316    Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
317  }
318
319  DeclaratorInfo *getAsDeclaratorInfo() const {
320    assert(Kind == K_DeclaratorInfo);
321    return Declarator;
322  }
323
324  Expr *getAsExpr() const {
325    assert(Kind == K_Expression);
326    return Expression;
327  }
328
329  SourceRange getTemplateQualifierRange() const {
330    assert(Kind == K_Template);
331    return SourceRange(
332                SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
333                SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
334  }
335
336  SourceLocation getTemplateNameLoc() const {
337    assert(Kind == K_Template);
338    return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
339  }
340
341#ifndef NDEBUG
342  void validateForArgument(const TemplateArgument &Arg) {
343    switch (Arg.getKind()) {
344    case TemplateArgument::Type:
345      assert(Kind == K_DeclaratorInfo);
346      break;
347    case TemplateArgument::Expression:
348    case TemplateArgument::Declaration:
349      assert(Kind == K_Expression);
350      break;
351    case TemplateArgument::Template:
352      assert(Kind == K_Template);
353      break;
354    case TemplateArgument::Integral:
355    case TemplateArgument::Pack:
356      assert(Kind == K_None);
357      break;
358    case TemplateArgument::Null:
359      llvm::llvm_unreachable("source info for null template argument?");
360    }
361  }
362#endif
363};
364
365/// Location wrapper for a TemplateArgument.  TemplateArgument is to
366/// TemplateArgumentLoc as Type is to TypeLoc.
367class TemplateArgumentLoc {
368  TemplateArgument Argument;
369  TemplateArgumentLocInfo LocInfo;
370
371public:
372  TemplateArgumentLoc() {}
373
374  TemplateArgumentLoc(const TemplateArgument &Argument,
375                      TemplateArgumentLocInfo Opaque)
376    : Argument(Argument), LocInfo(Opaque) {
377  }
378
379  TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo)
380    : Argument(Argument), LocInfo(DInfo) {
381    assert(Argument.getKind() == TemplateArgument::Type);
382  }
383
384  TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
385    : Argument(Argument), LocInfo(E) {
386    assert(Argument.getKind() == TemplateArgument::Expression);
387  }
388
389  TemplateArgumentLoc(const TemplateArgument &Argument,
390                      SourceRange QualifierRange,
391                      SourceLocation TemplateNameLoc)
392    : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
393    assert(Argument.getKind() == TemplateArgument::Template);
394  }
395
396  /// \brief - Fetches the primary location of the argument.
397  SourceLocation getLocation() const {
398    if (Argument.getKind() == TemplateArgument::Template)
399      return getTemplateNameLoc();
400
401    return getSourceRange().getBegin();
402  }
403
404  /// \brief - Fetches the full source range of the argument.
405  SourceRange getSourceRange() const;
406
407  const TemplateArgument &getArgument() const {
408    return Argument;
409  }
410
411  TemplateArgumentLocInfo getLocInfo() const {
412    return LocInfo;
413  }
414
415  DeclaratorInfo *getSourceDeclaratorInfo() const {
416    assert(Argument.getKind() == TemplateArgument::Type);
417    return LocInfo.getAsDeclaratorInfo();
418  }
419
420  Expr *getSourceExpression() const {
421    assert(Argument.getKind() == TemplateArgument::Expression);
422    return LocInfo.getAsExpr();
423  }
424
425  Expr *getSourceDeclExpression() const {
426    assert(Argument.getKind() == TemplateArgument::Declaration);
427    return LocInfo.getAsExpr();
428  }
429
430  SourceRange getTemplateQualifierRange() const {
431    assert(Argument.getKind() == TemplateArgument::Template);
432    return LocInfo.getTemplateQualifierRange();
433  }
434
435  SourceLocation getTemplateNameLoc() const {
436    assert(Argument.getKind() == TemplateArgument::Template);
437    return LocInfo.getTemplateNameLoc();
438  }
439};
440
441/// A convenient class for passing around template argument
442/// information.  Designed to be passed by reference.
443class TemplateArgumentListInfo {
444  llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
445  SourceLocation LAngleLoc;
446  SourceLocation RAngleLoc;
447
448public:
449  TemplateArgumentListInfo() {}
450
451  TemplateArgumentListInfo(SourceLocation LAngleLoc,
452                           SourceLocation RAngleLoc)
453    : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
454
455  SourceLocation getLAngleLoc() const { return LAngleLoc; }
456  SourceLocation getRAngleLoc() const { return RAngleLoc; }
457
458  void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
459  void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
460
461  unsigned size() const { return Arguments.size(); }
462
463  const TemplateArgumentLoc *getArgumentArray() const {
464    return Arguments.data();
465  }
466
467  const TemplateArgumentLoc &operator[](unsigned I) const {
468    return Arguments[I];
469  }
470
471  void addArgument(const TemplateArgumentLoc &Loc) {
472    Arguments.push_back(Loc);
473  }
474};
475
476}
477
478#endif
479