TemplateBase.h revision 6939fff69a3dfff2552261a1d7f1f609380fe6b0
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
286public:
287  TemplateArgumentLocInfo() : Expression(0) {}
288
289  TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
290
291  TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
292
293  TemplateArgumentLocInfo(SourceRange QualifierRange,
294                          SourceLocation TemplateNameLoc)
295  {
296    Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
297    Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
298    Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
299  }
300
301  TypeSourceInfo *getAsTypeSourceInfo() const {
302    return Declarator;
303  }
304
305  Expr *getAsExpr() const {
306    return Expression;
307  }
308
309  SourceRange getTemplateQualifierRange() const {
310    return SourceRange(
311                SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
312                SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
313  }
314
315  SourceLocation getTemplateNameLoc() const {
316    return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
317  }
318};
319
320/// Location wrapper for a TemplateArgument.  TemplateArgument is to
321/// TemplateArgumentLoc as Type is to TypeLoc.
322class TemplateArgumentLoc {
323  TemplateArgument Argument;
324  TemplateArgumentLocInfo LocInfo;
325
326public:
327  TemplateArgumentLoc() {}
328
329  TemplateArgumentLoc(const TemplateArgument &Argument,
330                      TemplateArgumentLocInfo Opaque)
331    : Argument(Argument), LocInfo(Opaque) {
332  }
333
334  TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
335    : Argument(Argument), LocInfo(TInfo) {
336    assert(Argument.getKind() == TemplateArgument::Type);
337  }
338
339  TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
340    : Argument(Argument), LocInfo(E) {
341    assert(Argument.getKind() == TemplateArgument::Expression);
342  }
343
344  TemplateArgumentLoc(const TemplateArgument &Argument,
345                      SourceRange QualifierRange,
346                      SourceLocation TemplateNameLoc)
347    : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
348    assert(Argument.getKind() == TemplateArgument::Template);
349  }
350
351  /// \brief - Fetches the primary location of the argument.
352  SourceLocation getLocation() const {
353    if (Argument.getKind() == TemplateArgument::Template)
354      return getTemplateNameLoc();
355
356    return getSourceRange().getBegin();
357  }
358
359  /// \brief - Fetches the full source range of the argument.
360  SourceRange getSourceRange() const;
361
362  const TemplateArgument &getArgument() const {
363    return Argument;
364  }
365
366  TemplateArgumentLocInfo getLocInfo() const {
367    return LocInfo;
368  }
369
370  TypeSourceInfo *getTypeSourceInfo() const {
371    assert(Argument.getKind() == TemplateArgument::Type);
372    return LocInfo.getAsTypeSourceInfo();
373  }
374
375  Expr *getSourceExpression() const {
376    assert(Argument.getKind() == TemplateArgument::Expression);
377    return LocInfo.getAsExpr();
378  }
379
380  Expr *getSourceDeclExpression() const {
381    assert(Argument.getKind() == TemplateArgument::Declaration);
382    return LocInfo.getAsExpr();
383  }
384
385  SourceRange getTemplateQualifierRange() const {
386    assert(Argument.getKind() == TemplateArgument::Template);
387    return LocInfo.getTemplateQualifierRange();
388  }
389
390  SourceLocation getTemplateNameLoc() const {
391    assert(Argument.getKind() == TemplateArgument::Template);
392    return LocInfo.getTemplateNameLoc();
393  }
394};
395
396/// A convenient class for passing around template argument
397/// information.  Designed to be passed by reference.
398class TemplateArgumentListInfo {
399  llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
400  SourceLocation LAngleLoc;
401  SourceLocation RAngleLoc;
402
403public:
404  TemplateArgumentListInfo() {}
405
406  TemplateArgumentListInfo(SourceLocation LAngleLoc,
407                           SourceLocation RAngleLoc)
408    : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
409
410  SourceLocation getLAngleLoc() const { return LAngleLoc; }
411  SourceLocation getRAngleLoc() const { return RAngleLoc; }
412
413  void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
414  void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
415
416  unsigned size() const { return Arguments.size(); }
417
418  const TemplateArgumentLoc *getArgumentArray() const {
419    return Arguments.data();
420  }
421
422  const TemplateArgumentLoc &operator[](unsigned I) const {
423    return Arguments[I];
424  }
425
426  void addArgument(const TemplateArgumentLoc &Loc) {
427    Arguments.push_back(Loc);
428  }
429};
430
431const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
432                                    const TemplateArgument &Arg);
433
434inline TemplateSpecializationType::iterator
435    TemplateSpecializationType::end() const {
436  return getArgs() + getNumArgs();
437}
438
439inline DependentTemplateSpecializationType::iterator
440    DependentTemplateSpecializationType::end() const {
441  return getArgs() + getNumArgs();
442}
443
444inline const TemplateArgument &
445    TemplateSpecializationType::getArg(unsigned Idx) const {
446  assert(Idx < getNumArgs() && "Template argument out of range");
447  return getArgs()[Idx];
448}
449
450inline const TemplateArgument &
451    DependentTemplateSpecializationType::getArg(unsigned Idx) const {
452  assert(Idx < getNumArgs() && "Template argument out of range");
453  return getArgs()[Idx];
454}
455
456} // end namespace clang
457
458#endif
459