TemplateBase.h revision 9532add6f24ae449c22f8c98f2246a974eee95be
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/Support/ErrorHandling.h"
20#include "clang/AST/Type.h"
21
22namespace llvm {
23  class FoldingSetNodeID;
24}
25
26namespace clang {
27
28class Decl;
29class Expr;
30class DeclaratorInfo;
31
32/// \brief Represents a template argument within a class template
33/// specialization.
34class TemplateArgument {
35  union {
36    uintptr_t TypeOrValue;
37    struct {
38      char Value[sizeof(llvm::APSInt)];
39      void *Type;
40    } Integer;
41    struct {
42      TemplateArgument *Args;
43      unsigned NumArgs;
44      bool CopyArgs;
45    } Args;
46  };
47
48public:
49  /// \brief The type of template argument we're storing.
50  enum ArgKind {
51    Null = 0,
52    /// The template argument is a type. Its value is stored in the
53    /// TypeOrValue field.
54    Type = 1,
55    /// The template argument is a declaration
56    Declaration = 2,
57    /// The template argument is an integral value stored in an llvm::APSInt.
58    Integral = 3,
59    /// The template argument is a value- or type-dependent expression
60    /// stored in an Expr*.
61    Expression = 4,
62
63    /// The template argument is actually a parameter pack. Arguments are stored
64    /// in the Args struct.
65    Pack = 5
66  } Kind;
67
68  /// \brief Construct an empty, invalid template argument.
69  TemplateArgument() : TypeOrValue(0), Kind(Null) { }
70
71  /// \brief Construct a template type argument.
72  TemplateArgument(QualType T) : Kind(Type) {
73    TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
74  }
75
76  /// \brief Construct a template argument that refers to a
77  /// declaration, which is either an external declaration or a
78  /// template declaration.
79  TemplateArgument(Decl *D) : Kind(Declaration) {
80    // FIXME: Need to be sure we have the "canonical" declaration!
81    TypeOrValue = reinterpret_cast<uintptr_t>(D);
82  }
83
84  /// \brief Construct an integral constant template argument.
85  TemplateArgument(const llvm::APSInt &Value, QualType Type)
86  : Kind(Integral) {
87    new (Integer.Value) llvm::APSInt(Value);
88    Integer.Type = Type.getAsOpaquePtr();
89  }
90
91  /// \brief Construct a template argument that is an expression.
92  ///
93  /// This form of template argument only occurs in template argument
94  /// lists used for dependent types and for expression; it will not
95  /// occur in a non-dependent, canonical template argument list.
96  TemplateArgument(Expr *E) : Kind(Expression) {
97    TypeOrValue = reinterpret_cast<uintptr_t>(E);
98  }
99
100  /// \brief Copy constructor for a template argument.
101  TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
102    if (Kind == Integral) {
103      new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
104      Integer.Type = Other.Integer.Type;
105    } else if (Kind == Pack) {
106      Args.NumArgs = Other.Args.NumArgs;
107      Args.Args = new TemplateArgument[Args.NumArgs];
108      for (unsigned I = 0; I != Args.NumArgs; ++I)
109        Args.Args[I] = Other.Args.Args[I];
110    }
111    else
112      TypeOrValue = Other.TypeOrValue;
113  }
114
115  TemplateArgument& operator=(const TemplateArgument& Other) {
116    // FIXME: Does not provide the strong guarantee for exception
117    // safety.
118    using llvm::APSInt;
119
120    // FIXME: Handle Packs
121    assert(Kind != Pack && "FIXME: Handle packs");
122    assert(Other.Kind != Pack && "FIXME: Handle packs");
123
124    if (Kind == Other.Kind && Kind == Integral) {
125      // Copy integral values.
126      *this->getAsIntegral() = *Other.getAsIntegral();
127      Integer.Type = Other.Integer.Type;
128    } else {
129      // Destroy the current integral value, if that's what we're holding.
130      if (Kind == Integral)
131        getAsIntegral()->~APSInt();
132
133      Kind = Other.Kind;
134
135      if (Other.Kind == Integral) {
136        new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
137        Integer.Type = Other.Integer.Type;
138      } else
139        TypeOrValue = Other.TypeOrValue;
140    }
141
142    return *this;
143  }
144
145  ~TemplateArgument() {
146    using llvm::APSInt;
147
148    if (Kind == Integral)
149      getAsIntegral()->~APSInt();
150    else if (Kind == Pack && Args.CopyArgs)
151      delete[] Args.Args;
152  }
153
154  /// \brief Return the kind of stored template argument.
155  ArgKind getKind() const { return Kind; }
156
157  /// \brief Determine whether this template argument has no value.
158  bool isNull() const { return Kind == Null; }
159
160  /// \brief Retrieve the template argument as a type.
161  QualType getAsType() const {
162    if (Kind != Type)
163      return QualType();
164
165    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
166  }
167
168  /// \brief Retrieve the template argument as a declaration.
169  Decl *getAsDecl() const {
170    if (Kind != Declaration)
171      return 0;
172    return reinterpret_cast<Decl *>(TypeOrValue);
173  }
174
175  /// \brief Retrieve the template argument as an integral value.
176  llvm::APSInt *getAsIntegral() {
177    if (Kind != Integral)
178      return 0;
179    return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
180  }
181
182  const llvm::APSInt *getAsIntegral() const {
183    return const_cast<TemplateArgument*>(this)->getAsIntegral();
184  }
185
186  /// \brief Retrieve the type of the integral value.
187  QualType getIntegralType() const {
188    if (Kind != Integral)
189      return QualType();
190
191    return QualType::getFromOpaquePtr(Integer.Type);
192  }
193
194  void setIntegralType(QualType T) {
195    assert(Kind == Integral &&
196           "Cannot set the integral type of a non-integral template argument");
197    Integer.Type = T.getAsOpaquePtr();
198  };
199
200  /// \brief Retrieve the template argument as an expression.
201  Expr *getAsExpr() const {
202    if (Kind != Expression)
203      return 0;
204
205    return reinterpret_cast<Expr *>(TypeOrValue);
206  }
207
208  /// \brief Iterator that traverses the elements of a template argument pack.
209  typedef const TemplateArgument * pack_iterator;
210
211  /// \brief Iterator referencing the first argument of a template argument
212  /// pack.
213  pack_iterator pack_begin() const {
214    assert(Kind == Pack);
215    return Args.Args;
216  }
217
218  /// \brief Iterator referencing one past the last argument of a template
219  /// argument pack.
220  pack_iterator pack_end() const {
221    assert(Kind == Pack);
222    return Args.Args + Args.NumArgs;
223  }
224
225  /// \brief The number of template arguments in the given template argument
226  /// pack.
227  unsigned pack_size() const {
228    assert(Kind == Pack);
229    return Args.NumArgs;
230  }
231
232  /// \brief Construct a template argument pack.
233  void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
234
235  /// \brief Used to insert TemplateArguments into FoldingSets.
236  void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
237};
238
239/// Location information for a TemplateArgument.
240struct TemplateArgumentLocInfo {
241private:
242  void *Union;
243
244#ifndef NDEBUG
245  enum Kind {
246    K_None,
247    K_DeclaratorInfo,
248    K_Expression
249  } Kind;
250#endif
251
252public:
253  TemplateArgumentLocInfo()
254    : Union()
255#ifndef NDEBUG
256      , Kind(K_None)
257#endif
258    {}
259
260  TemplateArgumentLocInfo(DeclaratorInfo *DInfo)
261    : Union(DInfo)
262#ifndef NDEBUG
263      , Kind(K_DeclaratorInfo)
264#endif
265    {}
266
267  TemplateArgumentLocInfo(Expr *E)
268    : Union(E)
269#ifndef NDEBUG
270      , Kind(K_Expression)
271#endif
272    {}
273
274  /// \brief Returns whether this
275  bool empty() const {
276    return Union == NULL;
277  }
278
279  DeclaratorInfo *getAsDeclaratorInfo() const {
280    assert(Kind == K_DeclaratorInfo);
281    return reinterpret_cast<DeclaratorInfo*>(Union);
282  }
283
284  Expr *getAsExpr() const {
285    assert(Kind == K_Expression);
286    return reinterpret_cast<Expr*>(Union);
287  }
288
289#ifndef NDEBUG
290  void validateForArgument(const TemplateArgument &Arg) {
291    switch (Arg.getKind()) {
292    case TemplateArgument::Type:
293      assert(Kind == K_DeclaratorInfo);
294      break;
295    case TemplateArgument::Expression:
296      assert(Kind == K_Expression);
297      break;
298    case TemplateArgument::Declaration:
299    case TemplateArgument::Integral:
300    case TemplateArgument::Pack:
301      assert(Kind == K_None);
302      break;
303    case TemplateArgument::Null:
304      llvm::llvm_unreachable("source info for null template argument?");
305    }
306  }
307#endif
308};
309
310/// Location wrapper for a TemplateArgument.  TemplateArgument is to
311/// TemplateArgumentLoc as Type is to TypeLoc.
312class TemplateArgumentLoc {
313  TemplateArgument Argument;
314  TemplateArgumentLocInfo LocInfo;
315
316  friend class TemplateSpecializationTypeLoc;
317  TemplateArgumentLoc(const TemplateArgument &Argument,
318                      TemplateArgumentLocInfo Opaque)
319    : Argument(Argument), LocInfo(Opaque) {
320  }
321
322public:
323  TemplateArgumentLoc() {}
324
325  TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo)
326    : Argument(Argument), LocInfo(DInfo) {
327    assert(Argument.getKind() == TemplateArgument::Type);
328  }
329
330  TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
331    : Argument(Argument), LocInfo(E) {
332    assert(Argument.getKind() == TemplateArgument::Expression);
333  }
334
335  /// This is a temporary measure.
336  TemplateArgumentLoc(const TemplateArgument &Argument)
337    : Argument(Argument), LocInfo() {
338    assert(Argument.getKind() != TemplateArgument::Expression &&
339           Argument.getKind() != TemplateArgument::Type);
340  }
341
342  /// \brief - Fetches the start location of the argument, if possible.
343  SourceLocation getLocation() const;
344
345  const TemplateArgument &getArgument() const {
346    return Argument;
347  }
348
349  TemplateArgumentLocInfo getLocInfo() const {
350    return LocInfo;
351  }
352
353  DeclaratorInfo *getSourceDeclaratorInfo() const {
354    assert(Argument.getKind() == TemplateArgument::Type);
355    if (LocInfo.empty()) return 0;
356    return LocInfo.getAsDeclaratorInfo();
357  }
358
359  Expr *getSourceExpression() const {
360    assert(Argument.getKind() == TemplateArgument::Expression);
361    if (LocInfo.empty()) return 0;
362    return LocInfo.getAsExpr();
363  }
364};
365
366}
367
368#endif
369