]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
Merge ACPICA 20100702.
[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   /// \brief Construct a template argument pack.
260   void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
261
262   /// \brief Used to insert TemplateArguments into FoldingSets.
263   void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
264 };
265
266 /// Location information for a TemplateArgument.
267 struct TemplateArgumentLocInfo {
268 private:
269   union {
270     Expr *Expression;
271     TypeSourceInfo *Declarator;
272     struct {
273       unsigned QualifierRange[2];
274       unsigned TemplateNameLoc;
275     } Template;
276   };
277
278 #ifndef NDEBUG
279   enum Kind {
280     K_None,
281     K_TypeSourceInfo,
282     K_Expression,
283     K_Template
284   } Kind;
285 #endif
286
287 public:
288   TemplateArgumentLocInfo()
289     : Expression(0)
290 #ifndef NDEBUG
291       , Kind(K_None) 
292 #endif
293     {}
294   
295   TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
296     : Declarator(TInfo)
297 #ifndef NDEBUG
298       , Kind(K_TypeSourceInfo) 
299 #endif
300     {}
301   
302   TemplateArgumentLocInfo(Expr *E)
303     : Expression(E)
304 #ifndef NDEBUG
305       , Kind(K_Expression) 
306 #endif
307     {}
308   
309   TemplateArgumentLocInfo(SourceRange QualifierRange, 
310                           SourceLocation TemplateNameLoc)
311 #ifndef NDEBUG
312     : Kind(K_Template)
313 #endif
314   {
315     Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
316     Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
317     Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
318   }
319
320   TypeSourceInfo *getAsTypeSourceInfo() const {
321     assert(Kind == K_TypeSourceInfo);
322     return Declarator;
323   }
324
325   Expr *getAsExpr() const {
326     assert(Kind == K_Expression);
327     return Expression;
328   }
329
330   SourceRange getTemplateQualifierRange() const {
331     assert(Kind == K_Template);
332     return SourceRange(
333                 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
334                 SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
335   }
336   
337   SourceLocation getTemplateNameLoc() const {
338     assert(Kind == K_Template);
339     return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
340   }
341   
342 #ifndef NDEBUG
343   void validateForArgument(const TemplateArgument &Arg) {
344     switch (Arg.getKind()) {
345     case TemplateArgument::Type:
346       assert(Kind == K_TypeSourceInfo);
347       break;
348     case TemplateArgument::Expression:
349     case TemplateArgument::Declaration:
350       assert(Kind == K_Expression);
351       break;
352     case TemplateArgument::Template:
353       assert(Kind == K_Template);
354       break;
355     case TemplateArgument::Integral:
356     case TemplateArgument::Pack:
357       assert(Kind == K_None);
358       break;
359     case TemplateArgument::Null:
360       llvm_unreachable("source info for null template argument?");
361     }
362   }
363 #endif
364 };
365
366 /// Location wrapper for a TemplateArgument.  TemplateArgument is to
367 /// TemplateArgumentLoc as Type is to TypeLoc.
368 class TemplateArgumentLoc {
369   TemplateArgument Argument;
370   TemplateArgumentLocInfo LocInfo;
371
372 public:
373   TemplateArgumentLoc() {}
374
375   TemplateArgumentLoc(const TemplateArgument &Argument,
376                       TemplateArgumentLocInfo Opaque)
377     : Argument(Argument), LocInfo(Opaque) {
378   }
379
380   TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
381     : Argument(Argument), LocInfo(TInfo) {
382     assert(Argument.getKind() == TemplateArgument::Type);
383   }
384
385   TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
386     : Argument(Argument), LocInfo(E) {
387     assert(Argument.getKind() == TemplateArgument::Expression);
388   }
389
390   TemplateArgumentLoc(const TemplateArgument &Argument, 
391                       SourceRange QualifierRange,
392                       SourceLocation TemplateNameLoc)
393     : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
394     assert(Argument.getKind() == TemplateArgument::Template);
395   }
396   
397   /// \brief - Fetches the primary location of the argument.
398   SourceLocation getLocation() const {
399     if (Argument.getKind() == TemplateArgument::Template)
400       return getTemplateNameLoc();
401     
402     return getSourceRange().getBegin();
403   }
404
405   /// \brief - Fetches the full source range of the argument.
406   SourceRange getSourceRange() const;
407
408   const TemplateArgument &getArgument() const {
409     return Argument;
410   }
411
412   TemplateArgumentLocInfo getLocInfo() const {
413     return LocInfo;
414   }
415
416   TypeSourceInfo *getTypeSourceInfo() const {
417     assert(Argument.getKind() == TemplateArgument::Type);
418     return LocInfo.getAsTypeSourceInfo();
419   }
420
421   Expr *getSourceExpression() const {
422     assert(Argument.getKind() == TemplateArgument::Expression);
423     return LocInfo.getAsExpr();
424   }
425
426   Expr *getSourceDeclExpression() const {
427     assert(Argument.getKind() == TemplateArgument::Declaration);
428     return LocInfo.getAsExpr();
429   }
430   
431   SourceRange getTemplateQualifierRange() const {
432     assert(Argument.getKind() == TemplateArgument::Template);
433     return LocInfo.getTemplateQualifierRange();
434   }
435   
436   SourceLocation getTemplateNameLoc() const {
437     assert(Argument.getKind() == TemplateArgument::Template);
438     return LocInfo.getTemplateNameLoc();
439   }  
440 };
441
442 /// A convenient class for passing around template argument
443 /// information.  Designed to be passed by reference.
444 class TemplateArgumentListInfo {
445   llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
446   SourceLocation LAngleLoc;
447   SourceLocation RAngleLoc;
448
449 public:
450   TemplateArgumentListInfo() {}
451
452   TemplateArgumentListInfo(SourceLocation LAngleLoc,
453                            SourceLocation RAngleLoc)
454     : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
455
456   SourceLocation getLAngleLoc() const { return LAngleLoc; }
457   SourceLocation getRAngleLoc() const { return RAngleLoc; }
458
459   void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
460   void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
461
462   unsigned size() const { return Arguments.size(); }
463
464   const TemplateArgumentLoc *getArgumentArray() const {
465     return Arguments.data();
466   }
467
468   const TemplateArgumentLoc &operator[](unsigned I) const {
469     return Arguments[I];
470   }
471
472   void addArgument(const TemplateArgumentLoc &Loc) {
473     Arguments.push_back(Loc);
474   }
475 };
476
477 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
478                                     const TemplateArgument &Arg);
479   
480 } // end namespace clang
481
482 #endif