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