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