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