/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/TemplateBase.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- TemplateBase.h - Core classes for C++ templates ----------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file provides definitions which are common for all kinds of |
10 | | // template representation. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H |
15 | | #define LLVM_CLANG_AST_TEMPLATEBASE_H |
16 | | |
17 | | #include "clang/AST/DependenceFlags.h" |
18 | | #include "clang/AST/NestedNameSpecifier.h" |
19 | | #include "clang/AST/TemplateName.h" |
20 | | #include "clang/AST/Type.h" |
21 | | #include "clang/Basic/LLVM.h" |
22 | | #include "clang/Basic/SourceLocation.h" |
23 | | #include "llvm/ADT/APInt.h" |
24 | | #include "llvm/ADT/APSInt.h" |
25 | | #include "llvm/ADT/ArrayRef.h" |
26 | | #include "llvm/ADT/None.h" |
27 | | #include "llvm/ADT/Optional.h" |
28 | | #include "llvm/ADT/SmallVector.h" |
29 | | #include "llvm/Support/Compiler.h" |
30 | | #include "llvm/Support/TrailingObjects.h" |
31 | | #include <cassert> |
32 | | #include <cstddef> |
33 | | #include <cstdint> |
34 | | |
35 | | namespace llvm { |
36 | | |
37 | | class FoldingSetNodeID; |
38 | | |
39 | | // Provide PointerLikeTypeTraits for clang::Expr*, this default one requires a |
40 | | // full definition of Expr, but this file only sees a forward del because of |
41 | | // the dependency. |
42 | | template <> struct PointerLikeTypeTraits<clang::Expr *> { |
43 | 579M | static inline void *getAsVoidPointer(clang::Expr *P) { return P; } |
44 | 1.03G | static inline clang::Expr *getFromVoidPointer(void *P) { |
45 | 1.03G | return static_cast<clang::Expr *>(P); |
46 | 1.03G | } |
47 | | static constexpr int NumLowBitsAvailable = 2; |
48 | | }; |
49 | | |
50 | | } // namespace llvm |
51 | | |
52 | | namespace clang { |
53 | | |
54 | | class ASTContext; |
55 | | class Expr; |
56 | | struct PrintingPolicy; |
57 | | class TypeSourceInfo; |
58 | | class ValueDecl; |
59 | | |
60 | | /// Represents a template argument. |
61 | | class TemplateArgument { |
62 | | public: |
63 | | /// The kind of template argument we're storing. |
64 | | enum ArgKind { |
65 | | /// Represents an empty template argument, e.g., one that has not |
66 | | /// been deduced. |
67 | | Null = 0, |
68 | | |
69 | | /// The template argument is a type. |
70 | | Type, |
71 | | |
72 | | /// The template argument is a declaration that was provided for a pointer, |
73 | | /// reference, or pointer to member non-type template parameter. |
74 | | Declaration, |
75 | | |
76 | | /// The template argument is a null pointer or null pointer to member that |
77 | | /// was provided for a non-type template parameter. |
78 | | NullPtr, |
79 | | |
80 | | /// The template argument is an integral value stored in an llvm::APSInt |
81 | | /// that was provided for an integral non-type template parameter. |
82 | | Integral, |
83 | | |
84 | | /// The template argument is a template name that was provided for a |
85 | | /// template template parameter. |
86 | | Template, |
87 | | |
88 | | /// The template argument is a pack expansion of a template name that was |
89 | | /// provided for a template template parameter. |
90 | | TemplateExpansion, |
91 | | |
92 | | /// The template argument is an expression, and we've not resolved it to one |
93 | | /// of the other forms yet, either because it's dependent or because we're |
94 | | /// representing a non-canonical template argument (for instance, in a |
95 | | /// TemplateSpecializationType). |
96 | | Expression, |
97 | | |
98 | | /// The template argument is actually a parameter pack. Arguments are stored |
99 | | /// in the Args struct. |
100 | | Pack |
101 | | }; |
102 | | |
103 | | private: |
104 | | /// The kind of template argument we're storing. |
105 | | |
106 | | struct DA { |
107 | | unsigned Kind; |
108 | | void *QT; |
109 | | ValueDecl *D; |
110 | | }; |
111 | | struct I { |
112 | | unsigned Kind; |
113 | | // We store a decomposed APSInt with the data allocated by ASTContext if |
114 | | // BitWidth > 64. The memory may be shared between multiple |
115 | | // TemplateArgument instances. |
116 | | unsigned BitWidth : 31; |
117 | | unsigned IsUnsigned : 1; |
118 | | union { |
119 | | /// Used to store the <= 64 bits integer value. |
120 | | uint64_t VAL; |
121 | | |
122 | | /// Used to store the >64 bits integer value. |
123 | | const uint64_t *pVal; |
124 | | }; |
125 | | void *Type; |
126 | | }; |
127 | | struct A { |
128 | | unsigned Kind; |
129 | | unsigned NumArgs; |
130 | | const TemplateArgument *Args; |
131 | | }; |
132 | | struct TA { |
133 | | unsigned Kind; |
134 | | unsigned NumExpansions; |
135 | | void *Name; |
136 | | }; |
137 | | struct TV { |
138 | | unsigned Kind; |
139 | | uintptr_t V; |
140 | | }; |
141 | | union { |
142 | | struct DA DeclArg; |
143 | | struct I Integer; |
144 | | struct A Args; |
145 | | struct TA TemplateArg; |
146 | | struct TV TypeOrValue; |
147 | | }; |
148 | | |
149 | | public: |
150 | | /// Construct an empty, invalid template argument. |
151 | 39.8M | constexpr TemplateArgument() : TypeOrValue({Null, 0}) {} |
152 | | |
153 | | /// Construct a template type argument. |
154 | 56.4M | TemplateArgument(QualType T, bool isNullPtr = false) { |
155 | 56.4M | TypeOrValue.Kind = isNullPtr ? NullPtr32.3k : Type56.4M ; |
156 | 56.4M | TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); |
157 | 56.4M | } |
158 | | |
159 | | /// Construct a template argument that refers to a |
160 | | /// declaration, which is either an external declaration or a |
161 | | /// template declaration. |
162 | 5.02k | TemplateArgument(ValueDecl *D, QualType QT) { |
163 | 5.02k | assert(D && "Expected decl"); |
164 | 0 | DeclArg.Kind = Declaration; |
165 | 5.02k | DeclArg.QT = QT.getAsOpaquePtr(); |
166 | 5.02k | DeclArg.D = D; |
167 | 5.02k | } |
168 | | |
169 | | /// Construct an integral constant template argument. The memory to |
170 | | /// store the value is allocated with Ctx. |
171 | | TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); |
172 | | |
173 | | /// Construct an integral constant template argument with the same |
174 | | /// value as Other but a different type. |
175 | 1.08M | TemplateArgument(const TemplateArgument &Other, QualType Type) { |
176 | 1.08M | Integer = Other.Integer; |
177 | 1.08M | Integer.Type = Type.getAsOpaquePtr(); |
178 | 1.08M | } |
179 | | |
180 | | /// Construct a template argument that is a template. |
181 | | /// |
182 | | /// This form of template argument is generally used for template template |
183 | | /// parameters. However, the template name could be a dependent template |
184 | | /// name that ends up being instantiated to a function template whose address |
185 | | /// is taken. |
186 | | /// |
187 | | /// \param Name The template name. |
188 | 471k | TemplateArgument(TemplateName Name) { |
189 | 471k | TemplateArg.Kind = Template; |
190 | 471k | TemplateArg.Name = Name.getAsVoidPointer(); |
191 | 471k | TemplateArg.NumExpansions = 0; |
192 | 471k | } |
193 | | |
194 | | /// Construct a template argument that is a template pack expansion. |
195 | | /// |
196 | | /// This form of template argument is generally used for template template |
197 | | /// parameters. However, the template name could be a dependent template |
198 | | /// name that ends up being instantiated to a function template whose address |
199 | | /// is taken. |
200 | | /// |
201 | | /// \param Name The template name. |
202 | | /// |
203 | | /// \param NumExpansions The number of expansions that will be generated by |
204 | | /// instantiating |
205 | 220 | TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) { |
206 | 220 | TemplateArg.Kind = TemplateExpansion; |
207 | 220 | TemplateArg.Name = Name.getAsVoidPointer(); |
208 | 220 | if (NumExpansions) |
209 | 4 | TemplateArg.NumExpansions = *NumExpansions + 1; |
210 | 216 | else |
211 | 216 | TemplateArg.NumExpansions = 0; |
212 | 220 | } |
213 | | |
214 | | /// Construct a template argument that is an expression. |
215 | | /// |
216 | | /// This form of template argument only occurs in template argument |
217 | | /// lists used for dependent types and for expression; it will not |
218 | | /// occur in a non-dependent, canonical template argument list. |
219 | 9.25M | TemplateArgument(Expr *E) { |
220 | 9.25M | TypeOrValue.Kind = Expression; |
221 | 9.25M | TypeOrValue.V = reinterpret_cast<uintptr_t>(E); |
222 | 9.25M | } |
223 | | |
224 | | /// Construct a template argument that is a template argument pack. |
225 | | /// |
226 | | /// We assume that storage for the template arguments provided |
227 | | /// outlives the TemplateArgument itself. |
228 | 1.36M | explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { |
229 | 1.36M | this->Args.Kind = Pack; |
230 | 1.36M | this->Args.Args = Args.data(); |
231 | 1.36M | this->Args.NumArgs = Args.size(); |
232 | 1.36M | } |
233 | | |
234 | | TemplateArgument(TemplateName, bool) = delete; |
235 | | |
236 | 39.7k | static TemplateArgument getEmptyPack() { return TemplateArgument(None); } |
237 | | |
238 | | /// Create a new template argument pack by copying the given set of |
239 | | /// template arguments. |
240 | | static TemplateArgument CreatePackCopy(ASTContext &Context, |
241 | | ArrayRef<TemplateArgument> Args); |
242 | | |
243 | | /// Return the kind of stored template argument. |
244 | 709M | ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } |
245 | | |
246 | | /// Determine whether this template argument has no value. |
247 | 16.3M | bool isNull() const { return getKind() == Null; } |
248 | | |
249 | | TemplateArgumentDependence getDependence() const; |
250 | | |
251 | | /// Whether this template argument is dependent on a template |
252 | | /// parameter such that its result can change from one instantiation to |
253 | | /// another. |
254 | | bool isDependent() const; |
255 | | |
256 | | /// Whether this template argument is dependent on a template |
257 | | /// parameter. |
258 | | bool isInstantiationDependent() const; |
259 | | |
260 | | /// Whether this template argument contains an unexpanded |
261 | | /// parameter pack. |
262 | | bool containsUnexpandedParameterPack() const; |
263 | | |
264 | | /// Determine whether this template argument is a pack expansion. |
265 | | bool isPackExpansion() const; |
266 | | |
267 | | /// Retrieve the type for a type template argument. |
268 | 213M | QualType getAsType() const { |
269 | 213M | assert(getKind() == Type && "Unexpected kind"); |
270 | 0 | return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); |
271 | 213M | } |
272 | | |
273 | | /// Retrieve the declaration for a declaration non-type |
274 | | /// template argument. |
275 | 37.7k | ValueDecl *getAsDecl() const { |
276 | 37.7k | assert(getKind() == Declaration && "Unexpected kind"); |
277 | 0 | return DeclArg.D; |
278 | 37.7k | } |
279 | | |
280 | 18.8k | QualType getParamTypeForDecl() const { |
281 | 18.8k | assert(getKind() == Declaration && "Unexpected kind"); |
282 | 0 | return QualType::getFromOpaquePtr(DeclArg.QT); |
283 | 18.8k | } |
284 | | |
285 | | /// Retrieve the type for null non-type template argument. |
286 | 68.6k | QualType getNullPtrType() const { |
287 | 68.6k | assert(getKind() == NullPtr && "Unexpected kind"); |
288 | 0 | return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); |
289 | 68.6k | } |
290 | | |
291 | | /// Retrieve the template name for a template name argument. |
292 | 276k | TemplateName getAsTemplate() const { |
293 | 276k | assert(getKind() == Template && "Unexpected kind"); |
294 | 0 | return TemplateName::getFromVoidPointer(TemplateArg.Name); |
295 | 276k | } |
296 | | |
297 | | /// Retrieve the template argument as a template name; if the argument |
298 | | /// is a pack expansion, return the pattern as a template name. |
299 | 198k | TemplateName getAsTemplateOrTemplatePattern() const { |
300 | 198k | assert((getKind() == Template || getKind() == TemplateExpansion) && |
301 | 198k | "Unexpected kind"); |
302 | | |
303 | 0 | return TemplateName::getFromVoidPointer(TemplateArg.Name); |
304 | 198k | } |
305 | | |
306 | | /// Retrieve the number of expansions that a template template argument |
307 | | /// expansion will produce, if known. |
308 | | Optional<unsigned> getNumTemplateExpansions() const; |
309 | | |
310 | | /// Retrieve the template argument as an integral value. |
311 | | // FIXME: Provide a way to read the integral data without copying the value. |
312 | 7.83M | llvm::APSInt getAsIntegral() const { |
313 | 7.83M | assert(getKind() == Integral && "Unexpected kind"); |
314 | | |
315 | 0 | using namespace llvm; |
316 | | |
317 | 7.83M | if (Integer.BitWidth <= 64) |
318 | 7.83M | return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); |
319 | | |
320 | 119 | unsigned NumWords = APInt::getNumWords(Integer.BitWidth); |
321 | 119 | return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)), |
322 | 119 | Integer.IsUnsigned); |
323 | 7.83M | } |
324 | | |
325 | | /// Retrieve the type of the integral value. |
326 | 8.49M | QualType getIntegralType() const { |
327 | 8.49M | assert(getKind() == Integral && "Unexpected kind"); |
328 | 0 | return QualType::getFromOpaquePtr(Integer.Type); |
329 | 8.49M | } |
330 | | |
331 | 0 | void setIntegralType(QualType T) { |
332 | 0 | assert(getKind() == Integral && "Unexpected kind"); |
333 | 0 | Integer.Type = T.getAsOpaquePtr(); |
334 | 0 | } |
335 | | |
336 | | /// If this is a non-type template argument, get its type. Otherwise, |
337 | | /// returns a null QualType. |
338 | | QualType getNonTypeTemplateArgumentType() const; |
339 | | |
340 | | /// Retrieve the template argument as an expression. |
341 | 33.7M | Expr *getAsExpr() const { |
342 | 33.7M | assert(getKind() == Expression && "Unexpected kind"); |
343 | 0 | return reinterpret_cast<Expr *>(TypeOrValue.V); |
344 | 33.7M | } |
345 | | |
346 | | /// Iterator that traverses the elements of a template argument pack. |
347 | | using pack_iterator = const TemplateArgument *; |
348 | | |
349 | | /// Iterator referencing the first argument of a template argument |
350 | | /// pack. |
351 | 2.42M | pack_iterator pack_begin() const { |
352 | 2.42M | assert(getKind() == Pack); |
353 | 0 | return Args.Args; |
354 | 2.42M | } |
355 | | |
356 | | /// Iterator referencing one past the last argument of a template |
357 | | /// argument pack. |
358 | 1.78M | pack_iterator pack_end() const { |
359 | 1.78M | assert(getKind() == Pack); |
360 | 0 | return Args.Args + Args.NumArgs; |
361 | 1.78M | } |
362 | | |
363 | | /// Iterator range referencing all of the elements of a template |
364 | | /// argument pack. |
365 | 1.27M | ArrayRef<TemplateArgument> pack_elements() const { |
366 | 1.27M | return llvm::makeArrayRef(pack_begin(), pack_end()); |
367 | 1.27M | } |
368 | | |
369 | | /// The number of template arguments in the given template argument |
370 | | /// pack. |
371 | 2.50M | unsigned pack_size() const { |
372 | 2.50M | assert(getKind() == Pack); |
373 | 0 | return Args.NumArgs; |
374 | 2.50M | } |
375 | | |
376 | | /// Return the array of arguments in this template argument pack. |
377 | 201k | ArrayRef<TemplateArgument> getPackAsArray() const { |
378 | 201k | assert(getKind() == Pack); |
379 | 0 | return llvm::makeArrayRef(Args.Args, Args.NumArgs); |
380 | 201k | } |
381 | | |
382 | | /// Determines whether two template arguments are superficially the |
383 | | /// same. |
384 | | bool structurallyEquals(const TemplateArgument &Other) const; |
385 | | |
386 | | /// When the template argument is a pack expansion, returns |
387 | | /// the pattern of the pack expansion. |
388 | | TemplateArgument getPackExpansionPattern() const; |
389 | | |
390 | | /// Print this template argument to the given output stream. |
391 | | void print(const PrintingPolicy &Policy, raw_ostream &Out, |
392 | | bool IncludeType) const; |
393 | | |
394 | | /// Debugging aid that dumps the template argument. |
395 | | void dump(raw_ostream &Out) const; |
396 | | |
397 | | /// Debugging aid that dumps the template argument to standard error. |
398 | | void dump() const; |
399 | | |
400 | | /// Used to insert TemplateArguments into FoldingSets. |
401 | | void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; |
402 | | }; |
403 | | |
404 | | /// Location information for a TemplateArgument. |
405 | | struct TemplateArgumentLocInfo { |
406 | | private: |
407 | | struct TemplateTemplateArgLocInfo { |
408 | | // FIXME: We'd like to just use the qualifier in the TemplateName, |
409 | | // but template arguments get canonicalized too quickly. |
410 | | NestedNameSpecifier *Qualifier; |
411 | | void *QualifierLocData; |
412 | | SourceLocation TemplateNameLoc; |
413 | | SourceLocation EllipsisLoc; |
414 | | }; |
415 | | |
416 | | llvm::PointerUnion<TemplateTemplateArgLocInfo *, Expr *, TypeSourceInfo *> |
417 | | Pointer; |
418 | | |
419 | 246k | TemplateTemplateArgLocInfo *getTemplate() const { |
420 | 246k | return Pointer.get<TemplateTemplateArgLocInfo *>(); |
421 | 246k | } |
422 | | |
423 | | public: |
424 | 10.6M | TemplateArgumentLocInfo() {} |
425 | 20.9M | TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; } |
426 | | |
427 | 8.06M | TemplateArgumentLocInfo(Expr *E) { Pointer = E; } |
428 | | // Ctx is used for allocation -- this case is unusually large and also rare, |
429 | | // so we store the payload out-of-line. |
430 | | TemplateArgumentLocInfo(ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, |
431 | | SourceLocation TemplateNameLoc, |
432 | | SourceLocation EllipsisLoc); |
433 | | |
434 | 23.3M | TypeSourceInfo *getAsTypeSourceInfo() const { |
435 | 23.3M | return Pointer.get<TypeSourceInfo *>(); |
436 | 23.3M | } |
437 | | |
438 | 2.70M | Expr *getAsExpr() const { return Pointer.get<Expr *>(); } |
439 | | |
440 | 70.1k | NestedNameSpecifierLoc getTemplateQualifierLoc() const { |
441 | 70.1k | const auto *Template = getTemplate(); |
442 | 70.1k | return NestedNameSpecifierLoc(Template->Qualifier, |
443 | 70.1k | Template->QualifierLocData); |
444 | 70.1k | } |
445 | | |
446 | 174k | SourceLocation getTemplateNameLoc() const { |
447 | 174k | return getTemplate()->TemplateNameLoc; |
448 | 174k | } |
449 | | |
450 | 1.42k | SourceLocation getTemplateEllipsisLoc() const { |
451 | 1.42k | return getTemplate()->EllipsisLoc; |
452 | 1.42k | } |
453 | | }; |
454 | | |
455 | | /// Location wrapper for a TemplateArgument. TemplateArgument is to |
456 | | /// TemplateArgumentLoc as Type is to TypeLoc. |
457 | | class TemplateArgumentLoc { |
458 | | TemplateArgument Argument; |
459 | | TemplateArgumentLocInfo LocInfo; |
460 | | |
461 | | public: |
462 | 10.5M | TemplateArgumentLoc() {} |
463 | | |
464 | | TemplateArgumentLoc(const TemplateArgument &Argument, |
465 | | TemplateArgumentLocInfo Opaque) |
466 | 10.7M | : Argument(Argument), LocInfo(Opaque) {} |
467 | | |
468 | | TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) |
469 | 14.6M | : Argument(Argument), LocInfo(TInfo) { |
470 | 14.6M | assert(Argument.getKind() == TemplateArgument::Type); |
471 | 14.6M | } |
472 | | |
473 | | TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) |
474 | 6.37M | : Argument(Argument), LocInfo(E) { |
475 | | |
476 | | // Permit any kind of template argument that can be represented with an |
477 | | // expression. |
478 | 6.37M | assert(Argument.getKind() == TemplateArgument::NullPtr || |
479 | 6.37M | Argument.getKind() == TemplateArgument::Integral || |
480 | 6.37M | Argument.getKind() == TemplateArgument::Declaration || |
481 | 6.37M | Argument.getKind() == TemplateArgument::Expression); |
482 | 6.37M | } |
483 | | |
484 | | TemplateArgumentLoc(ASTContext &Ctx, const TemplateArgument &Argument, |
485 | | NestedNameSpecifierLoc QualifierLoc, |
486 | | SourceLocation TemplateNameLoc, |
487 | | SourceLocation EllipsisLoc = SourceLocation()) |
488 | | : Argument(Argument), |
489 | 71.5k | LocInfo(Ctx, QualifierLoc, TemplateNameLoc, EllipsisLoc) { |
490 | 71.5k | assert(Argument.getKind() == TemplateArgument::Template || |
491 | 71.5k | Argument.getKind() == TemplateArgument::TemplateExpansion); |
492 | 71.5k | } |
493 | | |
494 | | /// - Fetches the primary location of the argument. |
495 | 86.9k | SourceLocation getLocation() const { |
496 | 86.9k | if (Argument.getKind() == TemplateArgument::Template || |
497 | 86.9k | Argument.getKind() == TemplateArgument::TemplateExpansion19.2k ) |
498 | 67.6k | return getTemplateNameLoc(); |
499 | | |
500 | 19.2k | return getSourceRange().getBegin(); |
501 | 86.9k | } |
502 | | |
503 | | /// - Fetches the full source range of the argument. |
504 | | SourceRange getSourceRange() const LLVM_READONLY; |
505 | | |
506 | 88.0M | const TemplateArgument &getArgument() const { |
507 | 88.0M | return Argument; |
508 | 88.0M | } |
509 | | |
510 | 14.2M | TemplateArgumentLocInfo getLocInfo() const { |
511 | 14.2M | return LocInfo; |
512 | 14.2M | } |
513 | | |
514 | 22.7M | TypeSourceInfo *getTypeSourceInfo() const { |
515 | 22.7M | if (Argument.getKind() != TemplateArgument::Type) |
516 | 0 | return nullptr; |
517 | 22.7M | return LocInfo.getAsTypeSourceInfo(); |
518 | 22.7M | } |
519 | | |
520 | 2.60M | Expr *getSourceExpression() const { |
521 | 2.60M | assert(Argument.getKind() == TemplateArgument::Expression); |
522 | 0 | return LocInfo.getAsExpr(); |
523 | 2.60M | } |
524 | | |
525 | 0 | Expr *getSourceDeclExpression() const { |
526 | 0 | assert(Argument.getKind() == TemplateArgument::Declaration); |
527 | 0 | return LocInfo.getAsExpr(); |
528 | 0 | } |
529 | | |
530 | 0 | Expr *getSourceNullPtrExpression() const { |
531 | 0 | assert(Argument.getKind() == TemplateArgument::NullPtr); |
532 | 0 | return LocInfo.getAsExpr(); |
533 | 0 | } |
534 | | |
535 | 0 | Expr *getSourceIntegralExpression() const { |
536 | 0 | assert(Argument.getKind() == TemplateArgument::Integral); |
537 | 0 | return LocInfo.getAsExpr(); |
538 | 0 | } |
539 | | |
540 | 66.8k | NestedNameSpecifierLoc getTemplateQualifierLoc() const { |
541 | 66.8k | if (Argument.getKind() != TemplateArgument::Template && |
542 | 66.8k | Argument.getKind() != TemplateArgument::TemplateExpansion38 ) |
543 | 0 | return NestedNameSpecifierLoc(); |
544 | 66.8k | return LocInfo.getTemplateQualifierLoc(); |
545 | 66.8k | } |
546 | | |
547 | 171k | SourceLocation getTemplateNameLoc() const { |
548 | 171k | if (Argument.getKind() != TemplateArgument::Template && |
549 | 171k | Argument.getKind() != TemplateArgument::TemplateExpansion56 ) |
550 | 0 | return SourceLocation(); |
551 | 171k | return LocInfo.getTemplateNameLoc(); |
552 | 171k | } |
553 | | |
554 | 37 | SourceLocation getTemplateEllipsisLoc() const { |
555 | 37 | if (Argument.getKind() != TemplateArgument::TemplateExpansion) |
556 | 0 | return SourceLocation(); |
557 | 37 | return LocInfo.getTemplateEllipsisLoc(); |
558 | 37 | } |
559 | | }; |
560 | | |
561 | | /// A convenient class for passing around template argument |
562 | | /// information. Designed to be passed by reference. |
563 | | class TemplateArgumentListInfo { |
564 | | SmallVector<TemplateArgumentLoc, 8> Arguments; |
565 | | SourceLocation LAngleLoc; |
566 | | SourceLocation RAngleLoc; |
567 | | |
568 | | public: |
569 | 55.9M | TemplateArgumentListInfo() = default; |
570 | | |
571 | | TemplateArgumentListInfo(SourceLocation LAngleLoc, |
572 | | SourceLocation RAngleLoc) |
573 | 4.43M | : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} |
574 | | |
575 | | // This can leak if used in an AST node, use ASTTemplateArgumentListInfo |
576 | | // instead. |
577 | | void *operator new(size_t bytes, ASTContext &C) = delete; |
578 | | |
579 | 1.49M | SourceLocation getLAngleLoc() const { return LAngleLoc; } |
580 | 19.2M | SourceLocation getRAngleLoc() const { return RAngleLoc; } |
581 | | |
582 | 5.97M | void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } |
583 | 5.97M | void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } |
584 | | |
585 | 27.1M | unsigned size() const { return Arguments.size(); } |
586 | | |
587 | 0 | const TemplateArgumentLoc *getArgumentArray() const { |
588 | 0 | return Arguments.data(); |
589 | 0 | } |
590 | | |
591 | 15.5M | llvm::ArrayRef<TemplateArgumentLoc> arguments() const { |
592 | 15.5M | return Arguments; |
593 | 15.5M | } |
594 | | |
595 | 3.50M | const TemplateArgumentLoc &operator[](unsigned I) const { |
596 | 3.50M | return Arguments[I]; |
597 | 3.50M | } |
598 | | |
599 | 43.0M | TemplateArgumentLoc &operator[](unsigned I) { |
600 | 43.0M | return Arguments[I]; |
601 | 43.0M | } |
602 | | |
603 | 15.9M | void addArgument(const TemplateArgumentLoc &Loc) { |
604 | 15.9M | Arguments.push_back(Loc); |
605 | 15.9M | } |
606 | | }; |
607 | | |
608 | | /// Represents an explicit template argument list in C++, e.g., |
609 | | /// the "<int>" in "sort<int>". |
610 | | /// This is safe to be used inside an AST node, in contrast with |
611 | | /// TemplateArgumentListInfo. |
612 | | struct ASTTemplateArgumentListInfo final |
613 | | : private llvm::TrailingObjects<ASTTemplateArgumentListInfo, |
614 | | TemplateArgumentLoc> { |
615 | | private: |
616 | | friend class ASTNodeImporter; |
617 | | friend TrailingObjects; |
618 | | |
619 | | ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); |
620 | | |
621 | | // FIXME: Is it ever necessary to copy to another context? |
622 | | ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List); |
623 | | |
624 | | public: |
625 | | /// The source location of the left angle bracket ('<'). |
626 | | SourceLocation LAngleLoc; |
627 | | |
628 | | /// The source location of the right angle bracket ('>'). |
629 | | SourceLocation RAngleLoc; |
630 | | |
631 | | /// The number of template arguments in TemplateArgs. |
632 | | unsigned NumTemplateArgs; |
633 | | |
634 | 279 | SourceLocation getLAngleLoc() const { return LAngleLoc; } |
635 | 282 | SourceLocation getRAngleLoc() const { return RAngleLoc; } |
636 | | |
637 | | /// Retrieve the template arguments |
638 | 365k | const TemplateArgumentLoc *getTemplateArgs() const { |
639 | 365k | return getTrailingObjects<TemplateArgumentLoc>(); |
640 | 365k | } |
641 | 307k | unsigned getNumTemplateArgs() const { return NumTemplateArgs; } |
642 | | |
643 | 307k | llvm::ArrayRef<TemplateArgumentLoc> arguments() const { |
644 | 307k | return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs()); |
645 | 307k | } |
646 | | |
647 | 12.9k | const TemplateArgumentLoc &operator[](unsigned I) const { |
648 | 12.9k | return getTemplateArgs()[I]; |
649 | 12.9k | } |
650 | | |
651 | | static const ASTTemplateArgumentListInfo * |
652 | | Create(const ASTContext &C, const TemplateArgumentListInfo &List); |
653 | | |
654 | | // FIXME: Is it ever necessary to copy to another context? |
655 | | static const ASTTemplateArgumentListInfo * |
656 | | Create(const ASTContext &C, const ASTTemplateArgumentListInfo *List); |
657 | | }; |
658 | | |
659 | | /// Represents an explicit template argument list in C++, e.g., |
660 | | /// the "<int>" in "sort<int>". |
661 | | /// |
662 | | /// It is intended to be used as a trailing object on AST nodes, and |
663 | | /// as such, doesn't contain the array of TemplateArgumentLoc itself, |
664 | | /// but expects the containing object to also provide storage for |
665 | | /// that. |
666 | | struct alignas(void *) ASTTemplateKWAndArgsInfo { |
667 | | /// The source location of the left angle bracket ('<'). |
668 | | SourceLocation LAngleLoc; |
669 | | |
670 | | /// The source location of the right angle bracket ('>'). |
671 | | SourceLocation RAngleLoc; |
672 | | |
673 | | /// The source location of the template keyword; this is used |
674 | | /// as part of the representation of qualified identifiers, such as |
675 | | /// S<T>::template apply<T>. Will be empty if this expression does |
676 | | /// not have a template keyword. |
677 | | SourceLocation TemplateKWLoc; |
678 | | |
679 | | /// The number of template arguments in TemplateArgs. |
680 | | unsigned NumTemplateArgs; |
681 | | |
682 | | void initializeFrom(SourceLocation TemplateKWLoc, |
683 | | const TemplateArgumentListInfo &List, |
684 | | TemplateArgumentLoc *OutArgArray); |
685 | | // FIXME: The parameter Deps is the result populated by this method, the |
686 | | // caller doesn't need it since it is populated by computeDependence. remove |
687 | | // it. |
688 | | void initializeFrom(SourceLocation TemplateKWLoc, |
689 | | const TemplateArgumentListInfo &List, |
690 | | TemplateArgumentLoc *OutArgArray, |
691 | | TemplateArgumentDependence &Deps); |
692 | | void initializeFrom(SourceLocation TemplateKWLoc); |
693 | | |
694 | | void copyInto(const TemplateArgumentLoc *ArgArray, |
695 | | TemplateArgumentListInfo &List) const; |
696 | | }; |
697 | | |
698 | | const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
699 | | const TemplateArgument &Arg); |
700 | | |
701 | | inline TemplateSpecializationType::iterator |
702 | 698k | TemplateSpecializationType::end() const { |
703 | 698k | return getArgs() + getNumArgs(); |
704 | 698k | } |
705 | | |
706 | | inline DependentTemplateSpecializationType::iterator |
707 | 0 | DependentTemplateSpecializationType::end() const { |
708 | 0 | return getArgs() + getNumArgs(); |
709 | 0 | } |
710 | | |
711 | | inline const TemplateArgument & |
712 | 21.5M | TemplateSpecializationType::getArg(unsigned Idx) const { |
713 | 21.5M | assert(Idx < getNumArgs() && "Template argument out of range"); |
714 | 0 | return getArgs()[Idx]; |
715 | 21.5M | } |
716 | | |
717 | | inline const TemplateArgument & |
718 | 54.0k | DependentTemplateSpecializationType::getArg(unsigned Idx) const { |
719 | 54.0k | assert(Idx < getNumArgs() && "Template argument out of range"); |
720 | 0 | return getArgs()[Idx]; |
721 | 54.0k | } |
722 | | |
723 | 0 | inline const TemplateArgument &AutoType::getArg(unsigned Idx) const { |
724 | 0 | assert(Idx < getNumArgs() && "Template argument out of range"); |
725 | 0 | return getArgs()[Idx]; |
726 | 0 | } |
727 | | |
728 | | } // namespace clang |
729 | | |
730 | | #endif // LLVM_CLANG_AST_TEMPLATEBASE_H |