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