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