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