 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
47.3% |
44 / 93 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
75.3% |
70 / 93 |
| |
|
Line Coverage: |
84.4% |
152 / 180 |
| |
 |
|
 |
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 Expr;
32 : class TypeSourceInfo;
33 :
34 : /// \brief Represents a template argument within a class template
35 : /// specialization.
36 : class TemplateArgument {
37 : union {
38 : uintptr_t TypeOrValue;
39 : struct {
40 : char Value[sizeof(llvm::APSInt)];
41 : void *Type;
42 : } Integer;
43 : struct {
44 : TemplateArgument *Args;
45 : unsigned NumArgs;
46 : bool CopyArgs;
47 : } Args;
48 : };
49 :
50 : public:
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 17596: TemplateArgument() : TypeOrValue(0), Kind(Null) { }
78 :
79 : /// \brief Construct a template type argument.
80 12326: TemplateArgument(QualType T) : Kind(Type) {
81 12326: TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
82 12326: }
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 79: TemplateArgument(Decl *D) : Kind(Declaration) {
88 : // FIXME: Need to be sure we have the "canonical" declaration!
89 79: TypeOrValue = reinterpret_cast<uintptr_t>(D);
90 79: }
91 :
92 : /// \brief Construct an integral constant template argument.
93 2008: TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
2008: branch 1 taken
0: branch 2 not taken
94 2008: new (Integer.Value) llvm::APSInt(Value);
95 2008: Integer.Type = Type.getAsOpaquePtr();
96 2008: }
97 :
98 : /// \brief Construct a template argument that is a template.
99 : ///
100 : /// This form of template argument is generally used for template template
101 : /// parameters. However, the template name could be a dependent template
102 : /// name that ends up being instantiated to a function template whose address
103 : /// is taken.
104 91: TemplateArgument(TemplateName Name) : Kind(Template) {
105 91: TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
106 91: }
107 :
108 : /// \brief Construct a template argument that is an expression.
109 : ///
110 : /// This form of template argument only occurs in template argument
111 : /// lists used for dependent types and for expression; it will not
112 : /// occur in a non-dependent, canonical template argument list.
113 1856: TemplateArgument(Expr *E) : Kind(Expression) {
114 1856: TypeOrValue = reinterpret_cast<uintptr_t>(E);
115 1856: }
116 :
117 : /// \brief Copy constructor for a template argument.
118 29344: TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
356: branch 0 taken
28988: branch 1 taken
119 29344: if (Kind == Integral) {
356: branch 2 taken
0: branch 3 not taken
120 356: new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
121 356: Integer.Type = Other.Integer.Type;
0: branch 0 not taken
28988: branch 1 taken
122 28988: } else if (Kind == Pack) {
123 0: Args.NumArgs = Other.Args.NumArgs;
0: branch 2 not taken
0: branch 3 not taken
124 0: Args.Args = new TemplateArgument[Args.NumArgs];
0: branch 0 not taken
0: branch 1 not taken
125 0: for (unsigned I = 0; I != Args.NumArgs; ++I)
126 0: Args.Args[I] = Other.Args.Args[I];
127 : }
128 : else
129 28988: TypeOrValue = Other.TypeOrValue;
130 29344: }
131 :
132 16241: TemplateArgument& operator=(const TemplateArgument& Other) {
133 : // FIXME: Does not provide the strong guarantee for exception
134 : // safety.
135 : using llvm::APSInt;
136 :
137 : // FIXME: Handle Packs
0: branch 0 not taken
16241: branch 1 taken
138 16241: assert(Kind != Pack && "FIXME: Handle packs");
0: branch 0 not taken
16241: branch 1 taken
139 16241: assert(Other.Kind != Pack && "FIXME: Handle packs");
140 :
722: branch 0 taken
15519: branch 1 taken
0: branch 2 not taken
722: branch 3 taken
141 16241: if (Kind == Other.Kind && Kind == Integral) {
142 : // Copy integral values.
143 0: *this->getAsIntegral() = *Other.getAsIntegral();
144 0: Integer.Type = Other.Integer.Type;
145 : } else {
146 : // Destroy the current integral value, if that's what we're holding.
0: branch 0 not taken
16241: branch 1 taken
147 16241: if (Kind == Integral)
148 0: getAsIntegral()->~APSInt();
149 :
150 16241: Kind = Other.Kind;
151 :
4697: branch 0 taken
11544: branch 1 taken
152 16241: if (Other.Kind == Integral) {
4697: branch 2 taken
0: branch 3 not taken
153 4697: new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
154 4697: Integer.Type = Other.Integer.Type;
155 : } else
156 11544: TypeOrValue = Other.TypeOrValue;
157 : }
158 :
159 16241: return *this;
160 : }
161 :
162 49232: ~TemplateArgument() {
163 : using llvm::APSInt;
164 :
5331: branch 0 taken
43901: branch 1 taken
165 49232: if (Kind == Integral)
166 5331: getAsIntegral()->~APSInt();
0: branch 0 not taken
43901: branch 1 taken
43901: branch 2 taken
43901: branch 3 taken
167 43901: else if (Kind == Pack && Args.CopyArgs)
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
168 0: delete[] Args.Args;
169 49232: }
170 :
171 : /// \brief Return the kind of stored template argument.
172 58051: ArgKind getKind() const { return Kind; }
173 :
174 : /// \brief Determine whether this template argument has no value.
175 7509: bool isNull() const { return Kind == Null; }
176 :
177 : /// \brief Retrieve the template argument as a type.
178 32633: QualType getAsType() const {
0: branch 0 not taken
32633: branch 1 taken
179 32633: if (Kind != Type)
180 0: return QualType();
181 :
182 32633: return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
183 : }
184 :
185 : /// \brief Retrieve the template argument as a declaration.
186 261: Decl *getAsDecl() const {
0: branch 0 not taken
261: branch 1 taken
187 261: if (Kind != Declaration)
188 0: return 0;
189 261: return reinterpret_cast<Decl *>(TypeOrValue);
190 : }
191 :
192 : /// \brief Retrieve the template argument as a template name.
193 235: TemplateName getAsTemplate() const {
0: branch 0 not taken
235: branch 1 taken
194 235: if (Kind != Template)
195 0: return TemplateName();
196 :
197 : return TemplateName::getFromVoidPointer(
198 235: reinterpret_cast<void *> (TypeOrValue));
199 : }
200 :
201 : /// \brief Retrieve the template argument as an integral value.
202 18098: llvm::APSInt *getAsIntegral() {
0: branch 0 not taken
18098: branch 1 taken
203 18098: if (Kind != Integral)
204 0: return 0;
205 18098: return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
206 : }
207 :
208 12764: const llvm::APSInt *getAsIntegral() const {
209 12764: return const_cast<TemplateArgument*>(this)->getAsIntegral();
210 : }
211 :
212 : /// \brief Retrieve the type of the integral value.
213 4354: QualType getIntegralType() const {
0: branch 1 not taken
0: branch 1 not taken
214 4354: if (Kind != Integral)
215 0: return QualType();
216 :
217 4354: return QualType::getFromOpaquePtr(Integer.Type);
218 : }
219 :
220 : void setIntegralType(QualType T) {
221 : assert(Kind == Integral &&
222 : "Cannot set the integral type of a non-integral template argument");
223 : Integer.Type = T.getAsOpaquePtr();
224 : }
225 :
226 : /// \brief Retrieve the template argument as an expression.
227 8931: Expr *getAsExpr() const {
8: branch 1 taken
8923: branch 1 taken
228 8931: if (Kind != Expression)
229 8: return 0;
230 :
231 8923: return reinterpret_cast<Expr *>(TypeOrValue);
232 : }
233 :
234 : /// \brief Iterator that traverses the elements of a template argument pack.
235 : typedef const TemplateArgument * pack_iterator;
236 :
237 : /// \brief Iterator referencing the first argument of a template argument
238 : /// pack.
239 0: pack_iterator pack_begin() const {
0: branch 0 not taken
0: branch 1 not taken
240 0: assert(Kind == Pack);
241 0: return Args.Args;
242 : }
243 :
244 : /// \brief Iterator referencing one past the last argument of a template
245 : /// argument pack.
246 0: pack_iterator pack_end() const {
0: branch 1 not taken
0: branch 1 not taken
247 0: assert(Kind == Pack);
248 0: return Args.Args + Args.NumArgs;
249 : }
250 :
251 : /// \brief The number of template arguments in the given template argument
252 : /// pack.
253 0: unsigned pack_size() const {
0: branch 0 not taken
0: branch 1 not taken
254 0: assert(Kind == Pack);
255 0: return Args.NumArgs;
256 : }
257 :
258 : /// \brief Construct a template argument pack.
259 : void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
260 :
261 : /// \brief Used to insert TemplateArguments into FoldingSets.
262 : void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
263 : };
264 :
265 : /// Location information for a TemplateArgument.
266 : struct TemplateArgumentLocInfo {
267 : private:
268 : union {
269 : Expr *Expression;
270 : TypeSourceInfo *Declarator;
271 : struct {
272 : unsigned QualifierRange[2];
273 : unsigned TemplateNameLoc;
274 : } Template;
275 : };
276 :
277 : #ifndef NDEBUG
278 : enum Kind {
279 : K_None,
280 : K_TypeSourceInfo,
281 : K_Expression,
282 : K_Template
283 : } Kind;
284 : #endif
285 :
286 : public:
287 4422: TemplateArgumentLocInfo()
288 : : Expression(0)
289 : #ifndef NDEBUG
290 4422: , Kind(K_None)
291 : #endif
292 4422: {}
293 :
294 4572: TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
295 : : Declarator(TInfo)
296 : #ifndef NDEBUG
297 4572: , Kind(K_TypeSourceInfo)
298 : #endif
299 4572: {}
300 :
301 2616: TemplateArgumentLocInfo(Expr *E)
302 : : Expression(E)
303 : #ifndef NDEBUG
304 2616: , Kind(K_Expression)
305 : #endif
306 2616: {}
307 :
308 : TemplateArgumentLocInfo(SourceRange QualifierRange,
309 54: SourceLocation TemplateNameLoc)
310 : #ifndef NDEBUG
311 54: : Kind(K_Template)
312 : #endif
313 : {
314 54: Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
315 54: Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
316 54: Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
317 54: }
318 :
319 4897: TypeSourceInfo *getAsTypeSourceInfo() const {
4897: branch 1 taken
320 4897: assert(Kind == K_TypeSourceInfo);
321 4897: return Declarator;
322 : }
323 :
324 1198: Expr *getAsExpr() const {
0: branch 0 not taken
1198: branch 1 taken
325 1198: assert(Kind == K_Expression);
326 1198: return Expression;
327 : }
328 :
329 24: SourceRange getTemplateQualifierRange() const {
0: branch 0 not taken
24: branch 1 taken
330 24: assert(Kind == K_Template);
331 : return SourceRange(
332 : SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
333 24: SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
334 : }
335 :
336 83: SourceLocation getTemplateNameLoc() const {
0: branch 0 not taken
83: branch 1 taken
337 83: assert(Kind == K_Template);
338 83: return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
339 : }
340 :
341 : #ifndef NDEBUG
342 4034: void validateForArgument(const TemplateArgument &Arg) {
2731: branch 1 taken
1281: branch 2 taken
22: branch 3 taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
343 4034: switch (Arg.getKind()) {
344 : case TemplateArgument::Type:
0: branch 0 not taken
2731: branch 1 taken
345 2731: assert(Kind == K_TypeSourceInfo);
346 2731: break;
347 : case TemplateArgument::Expression:
348 : case TemplateArgument::Declaration:
0: branch 0 not taken
1281: branch 1 taken
349 1281: assert(Kind == K_Expression);
350 1281: break;
351 : case TemplateArgument::Template:
0: branch 0 not taken
22: branch 1 taken
352 22: assert(Kind == K_Template);
353 22: break;
354 : case TemplateArgument::Integral:
355 : case TemplateArgument::Pack:
0: branch 0 not taken
0: branch 1 not taken
356 0: assert(Kind == K_None);
357 0: break;
358 : case TemplateArgument::Null:
359 0: llvm_unreachable("source info for null template argument?");
360 : }
361 4034: }
362 : #endif
363 : };
364 :
365 : /// Location wrapper for a TemplateArgument. TemplateArgument is to
366 : /// TemplateArgumentLoc as Type is to TypeLoc.
367 24308: class TemplateArgumentLoc {
368 : TemplateArgument Argument;
369 : TemplateArgumentLocInfo LocInfo;
370 :
371 : public:
372 2717: TemplateArgumentLoc() {}
373 :
374 : TemplateArgumentLoc(const TemplateArgument &Argument,
375 1835: TemplateArgumentLocInfo Opaque)
376 1835: : Argument(Argument), LocInfo(Opaque) {
377 1835: }
378 :
379 3773: TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
380 3773: : Argument(Argument), LocInfo(TInfo) {
3773: branch 2 taken
0: branch 2 not taken
381 3773: assert(Argument.getKind() == TemplateArgument::Type);
382 3773: }
383 :
384 1710: TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
385 1710: : Argument(Argument), LocInfo(E) {
0: branch 1 not taken
1710: branch 2 taken
386 1710: assert(Argument.getKind() == TemplateArgument::Expression);
387 1710: }
388 :
389 : TemplateArgumentLoc(const TemplateArgument &Argument,
390 : SourceRange QualifierRange,
391 54: SourceLocation TemplateNameLoc)
392 54: : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
0: branch 1 not taken
54: branch 2 taken
393 54: assert(Argument.getKind() == TemplateArgument::Template);
394 54: }
395 :
396 : /// \brief - Fetches the primary location of the argument.
397 58: SourceLocation getLocation() const {
56: branch 1 taken
2: branch 2 taken
398 58: if (Argument.getKind() == TemplateArgument::Template)
399 56: return getTemplateNameLoc();
400 :
401 2: return getSourceRange().getBegin();
402 : }
403 :
404 : /// \brief - Fetches the full source range of the argument.
405 : SourceRange getSourceRange() const;
406 :
407 20346: const TemplateArgument &getArgument() const {
408 20346: return Argument;
409 : }
410 :
411 4034: TemplateArgumentLocInfo getLocInfo() const {
412 4034: return LocInfo;
413 : }
414 :
415 4897: TypeSourceInfo *getTypeSourceInfo() const {
0: branch 1 not taken
4897: branch 2 taken
416 4897: assert(Argument.getKind() == TemplateArgument::Type);
417 4897: return LocInfo.getAsTypeSourceInfo();
418 : }
419 :
420 1198: Expr *getSourceExpression() const {
0: branch 1 not taken
1198: branch 2 taken
421 1198: assert(Argument.getKind() == TemplateArgument::Expression);
422 1198: return LocInfo.getAsExpr();
423 : }
424 :
425 0: Expr *getSourceDeclExpression() const {
0: branch 1 not taken
0: branch 2 not taken
426 0: assert(Argument.getKind() == TemplateArgument::Declaration);
427 0: return LocInfo.getAsExpr();
428 : }
429 :
430 24: SourceRange getTemplateQualifierRange() const {
0: branch 1 not taken
24: branch 2 taken
431 24: assert(Argument.getKind() == TemplateArgument::Template);
432 24: return LocInfo.getTemplateQualifierRange();
433 : }
434 :
435 83: SourceLocation getTemplateNameLoc() const {
0: branch 1 not taken
83: branch 2 taken
436 83: assert(Argument.getKind() == TemplateArgument::Template);
437 83: return LocInfo.getTemplateNameLoc();
438 : }
439 : };
440 :
441 : /// A convenient class for passing around template argument
442 : /// information. Designed to be passed by reference.
443 53081: class TemplateArgumentListInfo {
444 : llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
445 : SourceLocation LAngleLoc;
446 : SourceLocation RAngleLoc;
447 :
448 : public:
449 50969: TemplateArgumentListInfo() {}
450 :
451 : TemplateArgumentListInfo(SourceLocation LAngleLoc,
452 2112: SourceLocation RAngleLoc)
453 2112: : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
454 :
455 315: SourceLocation getLAngleLoc() const { return LAngleLoc; }
456 4427: SourceLocation getRAngleLoc() const { return RAngleLoc; }
457 :
458 2097: void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
459 2097: void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
460 :
461 17195: unsigned size() const { return Arguments.size(); }
462 :
463 3307: const TemplateArgumentLoc *getArgumentArray() const {
464 3307: return Arguments.data();
465 : }
466 :
467 14626: const TemplateArgumentLoc &operator[](unsigned I) const {
468 14626: return Arguments[I];
469 : }
470 :
471 5770: void addArgument(const TemplateArgumentLoc &Loc) {
472 5770: Arguments.push_back(Loc);
473 5770: }
474 : };
475 :
476 : }
477 :
478 : #endif
Generated: 2010-02-10 01:31 by zcov