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