TemplateBase.h revision 910f8008fea79120489a53593fe971b0b8a4a740
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 DiagnosticBuilder;
32class Expr;
33class TypeSourceInfo;
34
35/// \brief Represents a template argument within a class template
36/// specialization.
37class TemplateArgument {
38  union {
39    uintptr_t TypeOrValue;
40    struct {
41      char Value[sizeof(llvm::APSInt)];
42      void *Type;
43    } Integer;
44    struct {
45      TemplateArgument *Args;
46      unsigned NumArgs;
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    // FIXME: Large integral values will get leaked. Do something
95    // similar to what we did with IntegerLiteral.
96    new (Integer.Value) llvm::APSInt(Value);
97    Integer.Type = Type.getAsOpaquePtr();
98  }
99
100  /// \brief Construct a template argument that is a template.
101  ///
102  /// This form of template argument is generally used for template template
103  /// parameters. However, the template name could be a dependent template
104  /// name that ends up being instantiated to a function template whose address
105  /// is taken.
106  TemplateArgument(TemplateName Name) : Kind(Template) {
107    TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
108  }
109
110  /// \brief Construct a template argument that is an expression.
111  ///
112  /// This form of template argument only occurs in template argument
113  /// lists used for dependent types and for expression; it will not
114  /// occur in a non-dependent, canonical template argument list.
115  TemplateArgument(Expr *E) : Kind(Expression) {
116    TypeOrValue = reinterpret_cast<uintptr_t>(E);
117  }
118
119  /// \brief Construct a template argument that is a template argument pack.
120  ///
121  /// We assume that storage for the template arguments provided
122  /// outlives the TemplateArgument itself.
123  TemplateArgument(TemplateArgument *Args, unsigned NumArgs) : Kind(Pack) {
124    this->Args.Args = Args;
125    this->Args.NumArgs = NumArgs;
126  }
127
128  /// \brief Copy constructor for a template argument.
129  TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
130    // FIXME: Large integral values will get leaked. Do something
131    // similar to what we did with IntegerLiteral.
132    if (Kind == Integral) {
133      new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
134      Integer.Type = Other.Integer.Type;
135    } else if (Kind == Pack) {
136      Args.NumArgs = Other.Args.NumArgs;
137      Args.Args = Other.Args.Args;
138    }
139    else
140      TypeOrValue = Other.TypeOrValue;
141  }
142
143  TemplateArgument& operator=(const TemplateArgument& Other) {
144    using llvm::APSInt;
145
146    if (Kind == Other.Kind && Kind == Integral) {
147      // Copy integral values.
148      *this->getAsIntegral() = *Other.getAsIntegral();
149      Integer.Type = Other.Integer.Type;
150      return *this;
151    }
152
153    // Destroy the current integral value, if that's what we're holding.
154    if (Kind == Integral)
155      getAsIntegral()->~APSInt();
156
157    Kind = Other.Kind;
158
159    if (Other.Kind == Integral) {
160      new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
161      Integer.Type = Other.Integer.Type;
162    } else if (Other.Kind == Pack) {
163      Args.NumArgs = Other.Args.NumArgs;
164      Args.Args = Other.Args.Args;
165    } else {
166      TypeOrValue = Other.TypeOrValue;
167    }
168
169    return *this;
170  }
171
172  ~TemplateArgument() {
173    using llvm::APSInt;
174
175    if (Kind == Integral)
176      getAsIntegral()->~APSInt();
177  }
178
179  /// \brief Return the kind of stored template argument.
180  ArgKind getKind() const { return Kind; }
181
182  /// \brief Determine whether this template argument has no value.
183  bool isNull() const { return Kind == Null; }
184
185  /// \brief Retrieve the template argument as a type.
186  QualType getAsType() const {
187    if (Kind != Type)
188      return QualType();
189
190    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
191  }
192
193  /// \brief Retrieve the template argument as a declaration.
194  Decl *getAsDecl() const {
195    if (Kind != Declaration)
196      return 0;
197    return reinterpret_cast<Decl *>(TypeOrValue);
198  }
199
200  /// \brief Retrieve the template argument as a template name.
201  TemplateName getAsTemplate() const {
202    if (Kind != Template)
203      return TemplateName();
204
205    return TemplateName::getFromVoidPointer(
206                                        reinterpret_cast<void *> (TypeOrValue));
207  }
208
209  /// \brief Retrieve the template argument as an integral value.
210  llvm::APSInt *getAsIntegral() {
211    if (Kind != Integral)
212      return 0;
213    return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
214  }
215
216  const llvm::APSInt *getAsIntegral() const {
217    return const_cast<TemplateArgument*>(this)->getAsIntegral();
218  }
219
220  /// \brief Retrieve the type of the integral value.
221  QualType getIntegralType() const {
222    if (Kind != Integral)
223      return QualType();
224
225    return QualType::getFromOpaquePtr(Integer.Type);
226  }
227
228  void setIntegralType(QualType T) {
229    assert(Kind == Integral &&
230           "Cannot set the integral type of a non-integral template argument");
231    Integer.Type = T.getAsOpaquePtr();
232  }
233
234  /// \brief Retrieve the template argument as an expression.
235  Expr *getAsExpr() const {
236    if (Kind != Expression)
237      return 0;
238
239    return reinterpret_cast<Expr *>(TypeOrValue);
240  }
241
242  /// \brief Iterator that traverses the elements of a template argument pack.
243  typedef const TemplateArgument * pack_iterator;
244
245  /// \brief Iterator referencing the first argument of a template argument
246  /// pack.
247  pack_iterator pack_begin() const {
248    assert(Kind == Pack);
249    return Args.Args;
250  }
251
252  /// \brief Iterator referencing one past the last argument of a template
253  /// argument pack.
254  pack_iterator pack_end() const {
255    assert(Kind == Pack);
256    return Args.Args + Args.NumArgs;
257  }
258
259  /// \brief The number of template arguments in the given template argument
260  /// pack.
261  unsigned pack_size() const {
262    assert(Kind == Pack);
263    return Args.NumArgs;
264  }
265
266  /// Determines whether two template arguments are superficially the
267  /// same.
268  bool structurallyEquals(const TemplateArgument &Other) const;
269
270  /// \brief Used to insert TemplateArguments into FoldingSets.
271  void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
272};
273
274/// Location information for a TemplateArgument.
275struct TemplateArgumentLocInfo {
276private:
277  union {
278    Expr *Expression;
279    TypeSourceInfo *Declarator;
280    struct {
281      unsigned QualifierRange[2];
282      unsigned TemplateNameLoc;
283    } Template;
284  };
285
286#ifndef NDEBUG
287  enum Kind {
288    K_None,
289    K_TypeSourceInfo,
290    K_Expression,
291    K_Template
292  } Kind;
293#endif
294
295public:
296  TemplateArgumentLocInfo()
297    : Expression(0)
298#ifndef NDEBUG
299      , Kind(K_None)
300#endif
301    {}
302
303  TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
304    : Declarator(TInfo)
305#ifndef NDEBUG
306      , Kind(K_TypeSourceInfo)
307#endif
308    {}
309
310  TemplateArgumentLocInfo(Expr *E)
311    : Expression(E)
312#ifndef NDEBUG
313      , Kind(K_Expression)
314#endif
315    {}
316
317  TemplateArgumentLocInfo(SourceRange QualifierRange,
318                          SourceLocation TemplateNameLoc)
319#ifndef NDEBUG
320    : Kind(K_Template)
321#endif
322  {
323    Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
324    Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
325    Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
326  }
327
328  TypeSourceInfo *getAsTypeSourceInfo() const {
329    assert(Kind == K_TypeSourceInfo);
330    return Declarator;
331  }
332
333  Expr *getAsExpr() const {
334    assert(Kind == K_Expression);
335    return Expression;
336  }
337
338  SourceRange getTemplateQualifierRange() const {
339    assert(Kind == K_Template);
340    return SourceRange(
341                SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
342                SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
343  }
344
345  SourceLocation getTemplateNameLoc() const {
346    assert(Kind == K_Template);
347    return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
348  }
349
350#ifndef NDEBUG
351  void validateForArgument(const TemplateArgument &Arg) {
352    switch (Arg.getKind()) {
353    case TemplateArgument::Type:
354      assert(Kind == K_TypeSourceInfo);
355      break;
356    case TemplateArgument::Expression:
357    case TemplateArgument::Declaration:
358      assert(Kind == K_Expression);
359      break;
360    case TemplateArgument::Template:
361      assert(Kind == K_Template);
362      break;
363    case TemplateArgument::Integral:
364    case TemplateArgument::Pack:
365      assert(Kind == K_None);
366      break;
367    case TemplateArgument::Null:
368      llvm_unreachable("source info for null template argument?");
369    }
370  }
371#endif
372};
373
374/// Location wrapper for a TemplateArgument.  TemplateArgument is to
375/// TemplateArgumentLoc as Type is to TypeLoc.
376class TemplateArgumentLoc {
377  TemplateArgument Argument;
378  TemplateArgumentLocInfo LocInfo;
379
380public:
381  TemplateArgumentLoc() {}
382
383  TemplateArgumentLoc(const TemplateArgument &Argument,
384                      TemplateArgumentLocInfo Opaque)
385    : Argument(Argument), LocInfo(Opaque) {
386  }
387
388  TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
389    : Argument(Argument), LocInfo(TInfo) {
390    assert(Argument.getKind() == TemplateArgument::Type);
391  }
392
393  TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
394    : Argument(Argument), LocInfo(E) {
395    assert(Argument.getKind() == TemplateArgument::Expression);
396  }
397
398  TemplateArgumentLoc(const TemplateArgument &Argument,
399                      SourceRange QualifierRange,
400                      SourceLocation TemplateNameLoc)
401    : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
402    assert(Argument.getKind() == TemplateArgument::Template);
403  }
404
405  /// \brief - Fetches the primary location of the argument.
406  SourceLocation getLocation() const {
407    if (Argument.getKind() == TemplateArgument::Template)
408      return getTemplateNameLoc();
409
410    return getSourceRange().getBegin();
411  }
412
413  /// \brief - Fetches the full source range of the argument.
414  SourceRange getSourceRange() const;
415
416  const TemplateArgument &getArgument() const {
417    return Argument;
418  }
419
420  TemplateArgumentLocInfo getLocInfo() const {
421    return LocInfo;
422  }
423
424  TypeSourceInfo *getTypeSourceInfo() const {
425    assert(Argument.getKind() == TemplateArgument::Type);
426    return LocInfo.getAsTypeSourceInfo();
427  }
428
429  Expr *getSourceExpression() const {
430    assert(Argument.getKind() == TemplateArgument::Expression);
431    return LocInfo.getAsExpr();
432  }
433
434  Expr *getSourceDeclExpression() const {
435    assert(Argument.getKind() == TemplateArgument::Declaration);
436    return LocInfo.getAsExpr();
437  }
438
439  SourceRange getTemplateQualifierRange() const {
440    assert(Argument.getKind() == TemplateArgument::Template);
441    return LocInfo.getTemplateQualifierRange();
442  }
443
444  SourceLocation getTemplateNameLoc() const {
445    assert(Argument.getKind() == TemplateArgument::Template);
446    return LocInfo.getTemplateNameLoc();
447  }
448};
449
450/// A convenient class for passing around template argument
451/// information.  Designed to be passed by reference.
452class TemplateArgumentListInfo {
453  llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
454  SourceLocation LAngleLoc;
455  SourceLocation RAngleLoc;
456
457public:
458  TemplateArgumentListInfo() {}
459
460  TemplateArgumentListInfo(SourceLocation LAngleLoc,
461                           SourceLocation RAngleLoc)
462    : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
463
464  SourceLocation getLAngleLoc() const { return LAngleLoc; }
465  SourceLocation getRAngleLoc() const { return RAngleLoc; }
466
467  void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
468  void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
469
470  unsigned size() const { return Arguments.size(); }
471
472  const TemplateArgumentLoc *getArgumentArray() const {
473    return Arguments.data();
474  }
475
476  const TemplateArgumentLoc &operator[](unsigned I) const {
477    return Arguments[I];
478  }
479
480  void addArgument(const TemplateArgumentLoc &Loc) {
481    Arguments.push_back(Loc);
482  }
483};
484
485const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
486                                    const TemplateArgument &Arg);
487
488inline TemplateSpecializationType::iterator
489    TemplateSpecializationType::end() const {
490  return getArgs() + getNumArgs();
491}
492
493inline DependentTemplateSpecializationType::iterator
494    DependentTemplateSpecializationType::end() const {
495  return getArgs() + getNumArgs();
496}
497
498inline const TemplateArgument &
499    TemplateSpecializationType::getArg(unsigned Idx) const {
500  assert(Idx < getNumArgs() && "Template argument out of range");
501  return getArgs()[Idx];
502}
503
504inline const TemplateArgument &
505    DependentTemplateSpecializationType::getArg(unsigned Idx) const {
506  assert(Idx < getNumArgs() && "Template argument out of range");
507  return getArgs()[Idx];
508}
509
510} // end namespace clang
511
512#endif
513