1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
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 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
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 | |
60 | |
61 | |
62 | |
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), true); |
76 | Out << "'"; |
77 | } else { |
78 | Out << Val; |
79 | } |
80 | } |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, |
87 | QualType Type) { |
88 | Integer.Kind = Integral; |
89 | |
90 | Integer.BitWidth = Value.getBitWidth(); |
91 | Integer.IsUnsigned = Value.isUnsigned(); |
92 | |
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"); |
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 | |
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!"); |
153 | } |
154 | |
155 | bool TemplateArgument::isInstantiationDependent() const { |
156 | switch (getKind()) { |
157 | case Null: |
158 | llvm_unreachable("Should not have a NULL template argument"); |
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 | |
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!"); |
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!"); |
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); |
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!"); |
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!"); |
366 | } |
367 | |
368 | TemplateArgument TemplateArgument::getPackExpansionPattern() const { |
369 | assert(isPackExpansion()); |
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!"); |
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 | |
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; |
458 | LO.CPlusPlus = true; |
459 | LO.Bool = true; |
460 | print(PrintingPolicy(LO), Out); |
461 | } |
462 | |
463 | LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); } |
464 | |
465 | |
466 | |
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!"); |
507 | } |
508 | |
509 | const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, |
510 | const TemplateArgument &Arg) { |
511 | switch (Arg.getKind()) { |
512 | case TemplateArgument::Null: |
513 | |
514 | |
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 | |
537 | |
538 | |
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 | |
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!"); |
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()); |
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 | } |
630 | |