File: | clang/lib/AST/TemplateBase.cpp |
Warning: | line 548, column 5 Storage provided to placement new is only 0 bytes, whereas the allocated type requires 32 bytes |
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/DependenceFlags.h" | |||
20 | #include "clang/AST/Expr.h" | |||
21 | #include "clang/AST/ExprCXX.h" | |||
22 | #include "clang/AST/PrettyPrinter.h" | |||
23 | #include "clang/AST/TemplateName.h" | |||
24 | #include "clang/AST/Type.h" | |||
25 | #include "clang/AST/TypeLoc.h" | |||
26 | #include "clang/Basic/Diagnostic.h" | |||
27 | #include "clang/Basic/LLVM.h" | |||
28 | #include "clang/Basic/LangOptions.h" | |||
29 | #include "clang/Basic/SourceLocation.h" | |||
30 | #include "llvm/ADT/APSInt.h" | |||
31 | #include "llvm/ADT/FoldingSet.h" | |||
32 | #include "llvm/ADT/None.h" | |||
33 | #include "llvm/ADT/SmallString.h" | |||
34 | #include "llvm/ADT/StringRef.h" | |||
35 | #include "llvm/Support/Casting.h" | |||
36 | #include "llvm/Support/Compiler.h" | |||
37 | #include "llvm/Support/ErrorHandling.h" | |||
38 | #include "llvm/Support/raw_ostream.h" | |||
39 | #include <cassert> | |||
40 | #include <cstddef> | |||
41 | #include <cstdint> | |||
42 | #include <cstring> | |||
43 | ||||
44 | using namespace clang; | |||
45 | ||||
46 | /// Print a template integral argument value. | |||
47 | /// | |||
48 | /// \param TemplArg the TemplateArgument instance to print. | |||
49 | /// | |||
50 | /// \param Out the raw_ostream instance to use for printing. | |||
51 | /// | |||
52 | /// \param Policy the printing policy for EnumConstantDecl printing. | |||
53 | static void printIntegral(const TemplateArgument &TemplArg, | |||
54 | raw_ostream &Out, const PrintingPolicy& Policy) { | |||
55 | const Type *T = TemplArg.getIntegralType().getTypePtr(); | |||
56 | const llvm::APSInt &Val = TemplArg.getAsIntegral(); | |||
57 | ||||
58 | if (const EnumType *ET = T->getAs<EnumType>()) { | |||
59 | for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) { | |||
60 | // In Sema::CheckTemplateArugment, enum template arguments value are | |||
61 | // extended to the size of the integer underlying the enum type. This | |||
62 | // may create a size difference between the enum value and template | |||
63 | // argument value, requiring isSameValue here instead of operator==. | |||
64 | if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) { | |||
65 | ECD->printQualifiedName(Out, Policy); | |||
66 | return; | |||
67 | } | |||
68 | } | |||
69 | } | |||
70 | ||||
71 | if (T->isBooleanType() && !Policy.MSVCFormatting) { | |||
72 | Out << (Val.getBoolValue() ? "true" : "false"); | |||
73 | } else if (T->isCharType()) { | |||
74 | const char Ch = Val.getZExtValue(); | |||
75 | Out << ((Ch == '\'') ? "'\\" : "'"); | |||
76 | Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); | |||
77 | Out << "'"; | |||
78 | } else { | |||
79 | Out << Val; | |||
80 | } | |||
81 | } | |||
82 | ||||
83 | //===----------------------------------------------------------------------===// | |||
84 | // TemplateArgument Implementation | |||
85 | //===----------------------------------------------------------------------===// | |||
86 | ||||
87 | TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, | |||
88 | QualType Type) { | |||
89 | Integer.Kind = Integral; | |||
90 | // Copy the APSInt value into our decomposed form. | |||
91 | Integer.BitWidth = Value.getBitWidth(); | |||
92 | Integer.IsUnsigned = Value.isUnsigned(); | |||
93 | // If the value is large, we have to get additional memory from the ASTContext | |||
94 | unsigned NumWords = Value.getNumWords(); | |||
95 | if (NumWords > 1) { | |||
96 | void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t)); | |||
97 | std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t)); | |||
98 | Integer.pVal = static_cast<uint64_t *>(Mem); | |||
99 | } else { | |||
100 | Integer.VAL = Value.getZExtValue(); | |||
101 | } | |||
102 | ||||
103 | Integer.Type = Type.getAsOpaquePtr(); | |||
104 | } | |||
105 | ||||
106 | TemplateArgument | |||
107 | TemplateArgument::CreatePackCopy(ASTContext &Context, | |||
108 | ArrayRef<TemplateArgument> Args) { | |||
109 | if (Args.empty()) | |||
110 | return getEmptyPack(); | |||
111 | ||||
112 | return TemplateArgument(Args.copy(Context)); | |||
113 | } | |||
114 | ||||
115 | TemplateArgumentDependence TemplateArgument::getDependence() const { | |||
116 | auto Deps = TemplateArgumentDependence::None; | |||
117 | switch (getKind()) { | |||
118 | case Null: | |||
119 | llvm_unreachable("Should not have a NULL template argument")::llvm::llvm_unreachable_internal("Should not have a NULL template argument" , "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 119); | |||
120 | ||||
121 | case Type: | |||
122 | Deps = toTemplateArgumentDependence(getAsType()->getDependence()); | |||
123 | if (isa<PackExpansionType>(getAsType())) | |||
124 | Deps |= TemplateArgumentDependence::Dependent; | |||
125 | return Deps; | |||
126 | ||||
127 | case Template: | |||
128 | return toTemplateArgumentDependence(getAsTemplate().getDependence()); | |||
129 | ||||
130 | case TemplateExpansion: | |||
131 | return TemplateArgumentDependence::Dependent | | |||
132 | TemplateArgumentDependence::Instantiation; | |||
133 | ||||
134 | case Declaration: { | |||
135 | auto *DC = dyn_cast<DeclContext>(getAsDecl()); | |||
136 | if (!DC) | |||
137 | DC = getAsDecl()->getDeclContext(); | |||
138 | if (DC->isDependentContext()) | |||
139 | Deps = TemplateArgumentDependence::Dependent | | |||
140 | TemplateArgumentDependence::Instantiation; | |||
141 | return Deps; | |||
142 | } | |||
143 | ||||
144 | case NullPtr: | |||
145 | case Integral: | |||
146 | return TemplateArgumentDependence::None; | |||
147 | ||||
148 | case Expression: | |||
149 | Deps = toTemplateArgumentDependence(getAsExpr()->getDependence()); | |||
150 | if (isa<PackExpansionExpr>(getAsExpr())) | |||
151 | Deps |= TemplateArgumentDependence::Dependent | | |||
152 | TemplateArgumentDependence::Instantiation; | |||
153 | return Deps; | |||
154 | ||||
155 | case Pack: | |||
156 | for (const auto &P : pack_elements()) | |||
157 | Deps |= P.getDependence(); | |||
158 | return Deps; | |||
159 | } | |||
160 | llvm_unreachable("unhandled ArgKind")::llvm::llvm_unreachable_internal("unhandled ArgKind", "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 160); | |||
161 | } | |||
162 | ||||
163 | bool TemplateArgument::isDependent() const { | |||
164 | return getDependence() & TemplateArgumentDependence::Dependent; | |||
165 | } | |||
166 | ||||
167 | bool TemplateArgument::isInstantiationDependent() const { | |||
168 | return getDependence() & TemplateArgumentDependence::Instantiation; | |||
169 | } | |||
170 | ||||
171 | bool TemplateArgument::isPackExpansion() const { | |||
172 | switch (getKind()) { | |||
173 | case Null: | |||
174 | case Declaration: | |||
175 | case Integral: | |||
176 | case Pack: | |||
177 | case Template: | |||
178 | case NullPtr: | |||
179 | return false; | |||
180 | ||||
181 | case TemplateExpansion: | |||
182 | return true; | |||
183 | ||||
184 | case Type: | |||
185 | return isa<PackExpansionType>(getAsType()); | |||
186 | ||||
187 | case Expression: | |||
188 | return isa<PackExpansionExpr>(getAsExpr()); | |||
189 | } | |||
190 | ||||
191 | llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!" , "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 191); | |||
192 | } | |||
193 | ||||
194 | bool TemplateArgument::containsUnexpandedParameterPack() const { | |||
195 | return getDependence() & TemplateArgumentDependence::UnexpandedPack; | |||
196 | } | |||
197 | ||||
198 | Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { | |||
199 | assert(getKind() == TemplateExpansion)((getKind() == TemplateExpansion) ? static_cast<void> ( 0) : __assert_fail ("getKind() == TemplateExpansion", "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 199, __PRETTY_FUNCTION__)); | |||
200 | if (TemplateArg.NumExpansions) | |||
201 | return TemplateArg.NumExpansions - 1; | |||
202 | ||||
203 | return None; | |||
204 | } | |||
205 | ||||
206 | QualType TemplateArgument::getNonTypeTemplateArgumentType() const { | |||
207 | switch (getKind()) { | |||
208 | case TemplateArgument::Null: | |||
209 | case TemplateArgument::Type: | |||
210 | case TemplateArgument::Template: | |||
211 | case TemplateArgument::TemplateExpansion: | |||
212 | case TemplateArgument::Pack: | |||
213 | return QualType(); | |||
214 | ||||
215 | case TemplateArgument::Integral: | |||
216 | return getIntegralType(); | |||
217 | ||||
218 | case TemplateArgument::Expression: | |||
219 | return getAsExpr()->getType(); | |||
220 | ||||
221 | case TemplateArgument::Declaration: | |||
222 | return getParamTypeForDecl(); | |||
223 | ||||
224 | case TemplateArgument::NullPtr: | |||
225 | return getNullPtrType(); | |||
226 | } | |||
227 | ||||
228 | llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!" , "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 228); | |||
229 | } | |||
230 | ||||
231 | void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, | |||
232 | const ASTContext &Context) const { | |||
233 | ID.AddInteger(getKind()); | |||
234 | switch (getKind()) { | |||
235 | case Null: | |||
236 | break; | |||
237 | ||||
238 | case Type: | |||
239 | getAsType().Profile(ID); | |||
240 | break; | |||
241 | ||||
242 | case NullPtr: | |||
243 | getNullPtrType().Profile(ID); | |||
244 | break; | |||
245 | ||||
246 | case Declaration: | |||
247 | getParamTypeForDecl().Profile(ID); | |||
248 | ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr); | |||
249 | break; | |||
250 | ||||
251 | case Template: | |||
252 | case TemplateExpansion: { | |||
253 | TemplateName Template = getAsTemplateOrTemplatePattern(); | |||
254 | if (TemplateTemplateParmDecl *TTP | |||
255 | = dyn_cast_or_null<TemplateTemplateParmDecl>( | |||
256 | Template.getAsTemplateDecl())) { | |||
257 | ID.AddBoolean(true); | |||
258 | ID.AddInteger(TTP->getDepth()); | |||
259 | ID.AddInteger(TTP->getPosition()); | |||
260 | ID.AddBoolean(TTP->isParameterPack()); | |||
261 | } else { | |||
262 | ID.AddBoolean(false); | |||
263 | ID.AddPointer(Context.getCanonicalTemplateName(Template) | |||
264 | .getAsVoidPointer()); | |||
265 | } | |||
266 | break; | |||
267 | } | |||
268 | ||||
269 | case Integral: | |||
270 | getAsIntegral().Profile(ID); | |||
271 | getIntegralType().Profile(ID); | |||
272 | break; | |||
273 | ||||
274 | case Expression: | |||
275 | getAsExpr()->Profile(ID, Context, true); | |||
276 | break; | |||
277 | ||||
278 | case Pack: | |||
279 | ID.AddInteger(Args.NumArgs); | |||
280 | for (unsigned I = 0; I != Args.NumArgs; ++I) | |||
281 | Args.Args[I].Profile(ID, Context); | |||
282 | } | |||
283 | } | |||
284 | ||||
285 | bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { | |||
286 | if (getKind() != Other.getKind()) return false; | |||
287 | ||||
288 | switch (getKind()) { | |||
289 | case Null: | |||
290 | case Type: | |||
291 | case Expression: | |||
292 | case NullPtr: | |||
293 | return TypeOrValue.V == Other.TypeOrValue.V; | |||
294 | ||||
295 | case Template: | |||
296 | case TemplateExpansion: | |||
297 | return TemplateArg.Name == Other.TemplateArg.Name && | |||
298 | TemplateArg.NumExpansions == Other.TemplateArg.NumExpansions; | |||
299 | ||||
300 | case Declaration: | |||
301 | return getAsDecl() == Other.getAsDecl(); | |||
302 | ||||
303 | case Integral: | |||
304 | return getIntegralType() == Other.getIntegralType() && | |||
305 | getAsIntegral() == Other.getAsIntegral(); | |||
306 | ||||
307 | case Pack: | |||
308 | if (Args.NumArgs != Other.Args.NumArgs) return false; | |||
309 | for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) | |||
310 | if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) | |||
311 | return false; | |||
312 | return true; | |||
313 | } | |||
314 | ||||
315 | llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!" , "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 315); | |||
316 | } | |||
317 | ||||
318 | TemplateArgument TemplateArgument::getPackExpansionPattern() const { | |||
319 | assert(isPackExpansion())((isPackExpansion()) ? static_cast<void> (0) : __assert_fail ("isPackExpansion()", "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 319, __PRETTY_FUNCTION__)); | |||
320 | ||||
321 | switch (getKind()) { | |||
322 | case Type: | |||
323 | return getAsType()->castAs<PackExpansionType>()->getPattern(); | |||
324 | ||||
325 | case Expression: | |||
326 | return cast<PackExpansionExpr>(getAsExpr())->getPattern(); | |||
327 | ||||
328 | case TemplateExpansion: | |||
329 | return TemplateArgument(getAsTemplateOrTemplatePattern()); | |||
330 | ||||
331 | case Declaration: | |||
332 | case Integral: | |||
333 | case Pack: | |||
334 | case Null: | |||
335 | case Template: | |||
336 | case NullPtr: | |||
337 | return TemplateArgument(); | |||
338 | } | |||
339 | ||||
340 | llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!" , "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 340); | |||
341 | } | |||
342 | ||||
343 | void TemplateArgument::print(const PrintingPolicy &Policy, | |||
344 | raw_ostream &Out) const { | |||
345 | switch (getKind()) { | |||
346 | case Null: | |||
347 | Out << "(no value)"; | |||
348 | break; | |||
349 | ||||
350 | case Type: { | |||
351 | PrintingPolicy SubPolicy(Policy); | |||
352 | SubPolicy.SuppressStrongLifetime = true; | |||
353 | getAsType().print(Out, SubPolicy); | |||
354 | break; | |||
355 | } | |||
356 | ||||
357 | case Declaration: { | |||
358 | NamedDecl *ND = getAsDecl(); | |||
359 | if (getParamTypeForDecl()->isRecordType()) { | |||
360 | if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) { | |||
361 | // FIXME: Include the type if it's not obvious from the context. | |||
362 | TPO->printAsInit(Out); | |||
363 | break; | |||
364 | } | |||
365 | } | |||
366 | if (!getParamTypeForDecl()->isReferenceType()) | |||
367 | Out << '&'; | |||
368 | ND->printQualifiedName(Out); | |||
369 | break; | |||
370 | } | |||
371 | ||||
372 | case NullPtr: | |||
373 | Out << "nullptr"; | |||
374 | break; | |||
375 | ||||
376 | case Template: | |||
377 | getAsTemplate().print(Out, Policy); | |||
378 | break; | |||
379 | ||||
380 | case TemplateExpansion: | |||
381 | getAsTemplateOrTemplatePattern().print(Out, Policy); | |||
382 | Out << "..."; | |||
383 | break; | |||
384 | ||||
385 | case Integral: | |||
386 | printIntegral(*this, Out, Policy); | |||
387 | break; | |||
388 | ||||
389 | case Expression: | |||
390 | getAsExpr()->printPretty(Out, nullptr, Policy); | |||
391 | break; | |||
392 | ||||
393 | case Pack: | |||
394 | Out << "<"; | |||
395 | bool First = true; | |||
396 | for (const auto &P : pack_elements()) { | |||
397 | if (First) | |||
398 | First = false; | |||
399 | else | |||
400 | Out << ", "; | |||
401 | ||||
402 | P.print(Policy, Out); | |||
403 | } | |||
404 | Out << ">"; | |||
405 | break; | |||
406 | } | |||
407 | } | |||
408 | ||||
409 | void TemplateArgument::dump(raw_ostream &Out) const { | |||
410 | LangOptions LO; // FIXME! see also TemplateName::dump(). | |||
411 | LO.CPlusPlus = true; | |||
412 | LO.Bool = true; | |||
413 | print(PrintingPolicy(LO), Out); | |||
414 | } | |||
415 | ||||
416 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void TemplateArgument::dump() const { dump(llvm::errs()); } | |||
417 | ||||
418 | //===----------------------------------------------------------------------===// | |||
419 | // TemplateArgumentLoc Implementation | |||
420 | //===----------------------------------------------------------------------===// | |||
421 | ||||
422 | SourceRange TemplateArgumentLoc::getSourceRange() const { | |||
423 | switch (Argument.getKind()) { | |||
424 | case TemplateArgument::Expression: | |||
425 | return getSourceExpression()->getSourceRange(); | |||
426 | ||||
427 | case TemplateArgument::Declaration: | |||
428 | return getSourceDeclExpression()->getSourceRange(); | |||
429 | ||||
430 | case TemplateArgument::NullPtr: | |||
431 | return getSourceNullPtrExpression()->getSourceRange(); | |||
432 | ||||
433 | case TemplateArgument::Type: | |||
434 | if (TypeSourceInfo *TSI = getTypeSourceInfo()) | |||
435 | return TSI->getTypeLoc().getSourceRange(); | |||
436 | else | |||
437 | return SourceRange(); | |||
438 | ||||
439 | case TemplateArgument::Template: | |||
440 | if (getTemplateQualifierLoc()) | |||
441 | return SourceRange(getTemplateQualifierLoc().getBeginLoc(), | |||
442 | getTemplateNameLoc()); | |||
443 | return SourceRange(getTemplateNameLoc()); | |||
444 | ||||
445 | case TemplateArgument::TemplateExpansion: | |||
446 | if (getTemplateQualifierLoc()) | |||
447 | return SourceRange(getTemplateQualifierLoc().getBeginLoc(), | |||
448 | getTemplateEllipsisLoc()); | |||
449 | return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); | |||
450 | ||||
451 | case TemplateArgument::Integral: | |||
452 | return getSourceIntegralExpression()->getSourceRange(); | |||
453 | ||||
454 | case TemplateArgument::Pack: | |||
455 | case TemplateArgument::Null: | |||
456 | return SourceRange(); | |||
457 | } | |||
458 | ||||
459 | llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!" , "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 459); | |||
460 | } | |||
461 | ||||
462 | template <typename T> | |||
463 | static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) { | |||
464 | switch (Arg.getKind()) { | |||
465 | case TemplateArgument::Null: | |||
466 | // This is bad, but not as bad as crashing because of argument | |||
467 | // count mismatches. | |||
468 | return DB << "(null template argument)"; | |||
469 | ||||
470 | case TemplateArgument::Type: | |||
471 | return DB << Arg.getAsType(); | |||
472 | ||||
473 | case TemplateArgument::Declaration: | |||
474 | return DB << Arg.getAsDecl(); | |||
475 | ||||
476 | case TemplateArgument::NullPtr: | |||
477 | return DB << "nullptr"; | |||
478 | ||||
479 | case TemplateArgument::Integral: | |||
480 | return DB << Arg.getAsIntegral().toString(10); | |||
481 | ||||
482 | case TemplateArgument::Template: | |||
483 | return DB << Arg.getAsTemplate(); | |||
484 | ||||
485 | case TemplateArgument::TemplateExpansion: | |||
486 | return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; | |||
487 | ||||
488 | case TemplateArgument::Expression: { | |||
489 | // This shouldn't actually ever happen, so it's okay that we're | |||
490 | // regurgitating an expression here. | |||
491 | // FIXME: We're guessing at LangOptions! | |||
492 | SmallString<32> Str; | |||
493 | llvm::raw_svector_ostream OS(Str); | |||
494 | LangOptions LangOpts; | |||
495 | LangOpts.CPlusPlus = true; | |||
496 | PrintingPolicy Policy(LangOpts); | |||
497 | Arg.getAsExpr()->printPretty(OS, nullptr, Policy); | |||
498 | return DB << OS.str(); | |||
499 | } | |||
500 | ||||
501 | case TemplateArgument::Pack: { | |||
502 | // FIXME: We're guessing at LangOptions! | |||
503 | SmallString<32> Str; | |||
504 | llvm::raw_svector_ostream OS(Str); | |||
505 | LangOptions LangOpts; | |||
506 | LangOpts.CPlusPlus = true; | |||
507 | PrintingPolicy Policy(LangOpts); | |||
508 | Arg.print(Policy, OS); | |||
509 | return DB << OS.str(); | |||
510 | } | |||
511 | } | |||
512 | ||||
513 | llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!" , "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 513); | |||
514 | } | |||
515 | ||||
516 | const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, | |||
517 | const TemplateArgument &Arg) { | |||
518 | return DiagTemplateArg(DB, Arg); | |||
519 | } | |||
520 | ||||
521 | clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo( | |||
522 | ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, | |||
523 | SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) { | |||
524 | TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo; | |||
525 | Template->Qualifier = QualifierLoc.getNestedNameSpecifier(); | |||
526 | Template->QualifierLocData = QualifierLoc.getOpaqueData(); | |||
527 | Template->TemplateNameLoc = TemplateNameLoc; | |||
528 | Template->EllipsisLoc = EllipsisLoc; | |||
529 | Pointer = Template; | |||
530 | } | |||
531 | ||||
532 | const ASTTemplateArgumentListInfo * | |||
533 | ASTTemplateArgumentListInfo::Create(const ASTContext &C, | |||
534 | const TemplateArgumentListInfo &List) { | |||
535 | std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size()); | |||
536 | void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo)); | |||
537 | return new (Mem) ASTTemplateArgumentListInfo(List); | |||
| ||||
538 | } | |||
539 | ||||
540 | ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( | |||
541 | const TemplateArgumentListInfo &Info) { | |||
542 | LAngleLoc = Info.getLAngleLoc(); | |||
543 | RAngleLoc = Info.getRAngleLoc(); | |||
544 | NumTemplateArgs = Info.size(); | |||
545 | ||||
546 | TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>(); | |||
547 | for (unsigned i = 0; i != NumTemplateArgs; ++i) | |||
548 | new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); | |||
| ||||
549 | } | |||
550 | ||||
551 | void ASTTemplateKWAndArgsInfo::initializeFrom( | |||
552 | SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, | |||
553 | TemplateArgumentLoc *OutArgArray) { | |||
554 | this->TemplateKWLoc = TemplateKWLoc; | |||
555 | LAngleLoc = Info.getLAngleLoc(); | |||
556 | RAngleLoc = Info.getRAngleLoc(); | |||
557 | NumTemplateArgs = Info.size(); | |||
558 | ||||
559 | for (unsigned i = 0; i != NumTemplateArgs; ++i) | |||
560 | new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); | |||
561 | } | |||
562 | ||||
563 | void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { | |||
564 | assert(TemplateKWLoc.isValid())((TemplateKWLoc.isValid()) ? static_cast<void> (0) : __assert_fail ("TemplateKWLoc.isValid()", "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/clang/lib/AST/TemplateBase.cpp" , 564, __PRETTY_FUNCTION__)); | |||
565 | LAngleLoc = SourceLocation(); | |||
566 | RAngleLoc = SourceLocation(); | |||
567 | this->TemplateKWLoc = TemplateKWLoc; | |||
568 | NumTemplateArgs = 0; | |||
569 | } | |||
570 | ||||
571 | void ASTTemplateKWAndArgsInfo::initializeFrom( | |||
572 | SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, | |||
573 | TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) { | |||
574 | this->TemplateKWLoc = TemplateKWLoc; | |||
575 | LAngleLoc = Info.getLAngleLoc(); | |||
576 | RAngleLoc = Info.getRAngleLoc(); | |||
577 | NumTemplateArgs = Info.size(); | |||
578 | ||||
579 | for (unsigned i = 0; i != NumTemplateArgs; ++i) { | |||
580 | Deps |= Info[i].getArgument().getDependence(); | |||
581 | ||||
582 | new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); | |||
583 | } | |||
584 | } | |||
585 | ||||
586 | void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray, | |||
587 | TemplateArgumentListInfo &Info) const { | |||
588 | Info.setLAngleLoc(LAngleLoc); | |||
589 | Info.setRAngleLoc(RAngleLoc); | |||
590 | for (unsigned I = 0; I != NumTemplateArgs; ++I) | |||
591 | Info.addArgument(ArgArray[I]); | |||
592 | } |
1 | //===--- TrailingObjects.h - Variable-length classes ------------*- 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 | /// \file |
10 | /// This header defines support for implementing classes that have |
11 | /// some trailing object (or arrays of objects) appended to them. The |
12 | /// main purpose is to make it obvious where this idiom is being used, |
13 | /// and to make the usage more idiomatic and more difficult to get |
14 | /// wrong. |
15 | /// |
16 | /// The TrailingObject template abstracts away the reinterpret_cast, |
17 | /// pointer arithmetic, and size calculations used for the allocation |
18 | /// and access of appended arrays of objects, and takes care that they |
19 | /// are all allocated at their required alignment. Additionally, it |
20 | /// ensures that the base type is final -- deriving from a class that |
21 | /// expects data appended immediately after it is typically not safe. |
22 | /// |
23 | /// Users are expected to derive from this template, and provide |
24 | /// numTrailingObjects implementations for each trailing type except |
25 | /// the last, e.g. like this sample: |
26 | /// |
27 | /// \code |
28 | /// class VarLengthObj : private TrailingObjects<VarLengthObj, int, double> { |
29 | /// friend TrailingObjects; |
30 | /// |
31 | /// unsigned NumInts, NumDoubles; |
32 | /// size_t numTrailingObjects(OverloadToken<int>) const { return NumInts; } |
33 | /// }; |
34 | /// \endcode |
35 | /// |
36 | /// You can access the appended arrays via 'getTrailingObjects', and |
37 | /// determine the size needed for allocation via |
38 | /// 'additionalSizeToAlloc' and 'totalSizeToAlloc'. |
39 | /// |
40 | /// All the methods implemented by this class are are intended for use |
41 | /// by the implementation of the class, not as part of its interface |
42 | /// (thus, private inheritance is suggested). |
43 | /// |
44 | //===----------------------------------------------------------------------===// |
45 | |
46 | #ifndef LLVM_SUPPORT_TRAILINGOBJECTS_H |
47 | #define LLVM_SUPPORT_TRAILINGOBJECTS_H |
48 | |
49 | #include "llvm/Support/AlignOf.h" |
50 | #include "llvm/Support/Alignment.h" |
51 | #include "llvm/Support/Compiler.h" |
52 | #include "llvm/Support/MathExtras.h" |
53 | #include "llvm/Support/type_traits.h" |
54 | #include <new> |
55 | #include <type_traits> |
56 | |
57 | namespace llvm { |
58 | |
59 | namespace trailing_objects_internal { |
60 | /// Helper template to calculate the max alignment requirement for a set of |
61 | /// objects. |
62 | template <typename First, typename... Rest> class AlignmentCalcHelper { |
63 | private: |
64 | enum { |
65 | FirstAlignment = alignof(First), |
66 | RestAlignment = AlignmentCalcHelper<Rest...>::Alignment, |
67 | }; |
68 | |
69 | public: |
70 | enum { |
71 | Alignment = FirstAlignment > RestAlignment ? FirstAlignment : RestAlignment |
72 | }; |
73 | }; |
74 | |
75 | template <typename First> class AlignmentCalcHelper<First> { |
76 | public: |
77 | enum { Alignment = alignof(First) }; |
78 | }; |
79 | |
80 | /// The base class for TrailingObjects* classes. |
81 | class TrailingObjectsBase { |
82 | protected: |
83 | /// OverloadToken's purpose is to allow specifying function overloads |
84 | /// for different types, without actually taking the types as |
85 | /// parameters. (Necessary because member function templates cannot |
86 | /// be specialized, so overloads must be used instead of |
87 | /// specialization.) |
88 | template <typename T> struct OverloadToken {}; |
89 | }; |
90 | |
91 | template <int Align> |
92 | class TrailingObjectsAligner : public TrailingObjectsBase {}; |
93 | template <> |
94 | class alignas(1) TrailingObjectsAligner<1> : public TrailingObjectsBase {}; |
95 | template <> |
96 | class alignas(2) TrailingObjectsAligner<2> : public TrailingObjectsBase {}; |
97 | template <> |
98 | class alignas(4) TrailingObjectsAligner<4> : public TrailingObjectsBase {}; |
99 | template <> |
100 | class alignas(8) TrailingObjectsAligner<8> : public TrailingObjectsBase {}; |
101 | template <> |
102 | class alignas(16) TrailingObjectsAligner<16> : public TrailingObjectsBase { |
103 | }; |
104 | template <> |
105 | class alignas(32) TrailingObjectsAligner<32> : public TrailingObjectsBase { |
106 | }; |
107 | |
108 | // Just a little helper for transforming a type pack into the same |
109 | // number of a different type. e.g.: |
110 | // ExtractSecondType<Foo..., int>::type |
111 | template <typename Ty1, typename Ty2> struct ExtractSecondType { |
112 | typedef Ty2 type; |
113 | }; |
114 | |
115 | // TrailingObjectsImpl is somewhat complicated, because it is a |
116 | // recursively inheriting template, in order to handle the template |
117 | // varargs. Each level of inheritance picks off a single trailing type |
118 | // then recurses on the rest. The "Align", "BaseTy", and |
119 | // "TopTrailingObj" arguments are passed through unchanged through the |
120 | // recursion. "PrevTy" is, at each level, the type handled by the |
121 | // level right above it. |
122 | |
123 | template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy, |
124 | typename... MoreTys> |
125 | class TrailingObjectsImpl { |
126 | // The main template definition is never used -- the two |
127 | // specializations cover all possibilities. |
128 | }; |
129 | |
130 | template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy, |
131 | typename NextTy, typename... MoreTys> |
132 | class TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy, NextTy, |
133 | MoreTys...> |
134 | : public TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, NextTy, |
135 | MoreTys...> { |
136 | |
137 | typedef TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, NextTy, MoreTys...> |
138 | ParentType; |
139 | |
140 | struct RequiresRealignment { |
141 | static const bool value = alignof(PrevTy) < alignof(NextTy); |
142 | }; |
143 | |
144 | static constexpr bool requiresRealignment() { |
145 | return RequiresRealignment::value; |
146 | } |
147 | |
148 | protected: |
149 | // Ensure the inherited getTrailingObjectsImpl is not hidden. |
150 | using ParentType::getTrailingObjectsImpl; |
151 | |
152 | // These two functions are helper functions for |
153 | // TrailingObjects::getTrailingObjects. They recurse to the left -- |
154 | // the result for each type in the list of trailing types depends on |
155 | // the result of calling the function on the type to the |
156 | // left. However, the function for the type to the left is |
157 | // implemented by a *subclass* of this class, so we invoke it via |
158 | // the TopTrailingObj, which is, via the |
159 | // curiously-recurring-template-pattern, the most-derived type in |
160 | // this recursion, and thus, contains all the overloads. |
161 | static const NextTy * |
162 | getTrailingObjectsImpl(const BaseTy *Obj, |
163 | TrailingObjectsBase::OverloadToken<NextTy>) { |
164 | auto *Ptr = TopTrailingObj::getTrailingObjectsImpl( |
165 | Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) + |
166 | TopTrailingObj::callNumTrailingObjects( |
167 | Obj, TrailingObjectsBase::OverloadToken<PrevTy>()); |
168 | |
169 | if (requiresRealignment()) |
170 | return reinterpret_cast<const NextTy *>( |
171 | alignAddr(Ptr, Align::Of<NextTy>())); |
172 | else |
173 | return reinterpret_cast<const NextTy *>(Ptr); |
174 | } |
175 | |
176 | static NextTy * |
177 | getTrailingObjectsImpl(BaseTy *Obj, |
178 | TrailingObjectsBase::OverloadToken<NextTy>) { |
179 | auto *Ptr = TopTrailingObj::getTrailingObjectsImpl( |
180 | Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) + |
181 | TopTrailingObj::callNumTrailingObjects( |
182 | Obj, TrailingObjectsBase::OverloadToken<PrevTy>()); |
183 | |
184 | if (requiresRealignment()) |
185 | return reinterpret_cast<NextTy *>(alignAddr(Ptr, Align::Of<NextTy>())); |
186 | else |
187 | return reinterpret_cast<NextTy *>(Ptr); |
188 | } |
189 | |
190 | // Helper function for TrailingObjects::additionalSizeToAlloc: this |
191 | // function recurses to superclasses, each of which requires one |
192 | // fewer size_t argument, and adds its own size. |
193 | static constexpr size_t additionalSizeToAllocImpl( |
194 | size_t SizeSoFar, size_t Count1, |
195 | typename ExtractSecondType<MoreTys, size_t>::type... MoreCounts) { |
196 | return ParentType::additionalSizeToAllocImpl( |
197 | (requiresRealignment() ? llvm::alignTo<alignof(NextTy)>(SizeSoFar) |
198 | : SizeSoFar) + |
199 | sizeof(NextTy) * Count1, |
200 | MoreCounts...); |
201 | } |
202 | }; |
203 | |
204 | // The base case of the TrailingObjectsImpl inheritance recursion, |
205 | // when there's no more trailing types. |
206 | template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy> |
207 | class TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy> |
208 | : public TrailingObjectsAligner<Align> { |
209 | protected: |
210 | // This is a dummy method, only here so the "using" doesn't fail -- |
211 | // it will never be called, because this function recurses backwards |
212 | // up the inheritance chain to subclasses. |
213 | static void getTrailingObjectsImpl(); |
214 | |
215 | static constexpr size_t additionalSizeToAllocImpl(size_t SizeSoFar) { |
216 | return SizeSoFar; |
217 | } |
218 | |
219 | template <bool CheckAlignment> static void verifyTrailingObjectsAlignment() {} |
220 | }; |
221 | |
222 | } // end namespace trailing_objects_internal |
223 | |
224 | // Finally, the main type defined in this file, the one intended for users... |
225 | |
226 | /// See the file comment for details on the usage of the |
227 | /// TrailingObjects type. |
228 | template <typename BaseTy, typename... TrailingTys> |
229 | class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl< |
230 | trailing_objects_internal::AlignmentCalcHelper< |
231 | TrailingTys...>::Alignment, |
232 | BaseTy, TrailingObjects<BaseTy, TrailingTys...>, |
233 | BaseTy, TrailingTys...> { |
234 | |
235 | template <int A, typename B, typename T, typename P, typename... M> |
236 | friend class trailing_objects_internal::TrailingObjectsImpl; |
237 | |
238 | template <typename... Tys> class Foo {}; |
239 | |
240 | typedef trailing_objects_internal::TrailingObjectsImpl< |
241 | trailing_objects_internal::AlignmentCalcHelper<TrailingTys...>::Alignment, |
242 | BaseTy, TrailingObjects<BaseTy, TrailingTys...>, BaseTy, TrailingTys...> |
243 | ParentType; |
244 | using TrailingObjectsBase = trailing_objects_internal::TrailingObjectsBase; |
245 | |
246 | using ParentType::getTrailingObjectsImpl; |
247 | |
248 | // This function contains only a static_assert BaseTy is final. The |
249 | // static_assert must be in a function, and not at class-level |
250 | // because BaseTy isn't complete at class instantiation time, but |
251 | // will be by the time this function is instantiated. |
252 | static void verifyTrailingObjectsAssertions() { |
253 | static_assert(std::is_final<BaseTy>(), "BaseTy must be final."); |
254 | } |
255 | |
256 | // These two methods are the base of the recursion for this method. |
257 | static const BaseTy * |
258 | getTrailingObjectsImpl(const BaseTy *Obj, |
259 | TrailingObjectsBase::OverloadToken<BaseTy>) { |
260 | return Obj; |
261 | } |
262 | |
263 | static BaseTy * |
264 | getTrailingObjectsImpl(BaseTy *Obj, |
265 | TrailingObjectsBase::OverloadToken<BaseTy>) { |
266 | return Obj; |
267 | } |
268 | |
269 | // callNumTrailingObjects simply calls numTrailingObjects on the |
270 | // provided Obj -- except when the type being queried is BaseTy |
271 | // itself. There is always only one of the base object, so that case |
272 | // is handled here. (An additional benefit of indirecting through |
273 | // this function is that consumers only say "friend |
274 | // TrailingObjects", and thus, only this class itself can call the |
275 | // numTrailingObjects function.) |
276 | static size_t |
277 | callNumTrailingObjects(const BaseTy *Obj, |
278 | TrailingObjectsBase::OverloadToken<BaseTy>) { |
279 | return 1; |
280 | } |
281 | |
282 | template <typename T> |
283 | static size_t callNumTrailingObjects(const BaseTy *Obj, |
284 | TrailingObjectsBase::OverloadToken<T>) { |
285 | return Obj->numTrailingObjects(TrailingObjectsBase::OverloadToken<T>()); |
286 | } |
287 | |
288 | public: |
289 | // Make this (privately inherited) member public. |
290 | #ifndef _MSC_VER |
291 | using ParentType::OverloadToken; |
292 | #else |
293 | // MSVC bug prevents the above from working, at least up through CL |
294 | // 19.10.24629. |
295 | template <typename T> |
296 | using OverloadToken = typename ParentType::template OverloadToken<T>; |
297 | #endif |
298 | |
299 | /// Returns a pointer to the trailing object array of the given type |
300 | /// (which must be one of those specified in the class template). The |
301 | /// array may have zero or more elements in it. |
302 | template <typename T> const T *getTrailingObjects() const { |
303 | verifyTrailingObjectsAssertions(); |
304 | // Forwards to an impl function with overloads, since member |
305 | // function templates can't be specialized. |
306 | return this->getTrailingObjectsImpl( |
307 | static_cast<const BaseTy *>(this), |
308 | TrailingObjectsBase::OverloadToken<T>()); |
309 | } |
310 | |
311 | /// Returns a pointer to the trailing object array of the given type |
312 | /// (which must be one of those specified in the class template). The |
313 | /// array may have zero or more elements in it. |
314 | template <typename T> T *getTrailingObjects() { |
315 | verifyTrailingObjectsAssertions(); |
316 | // Forwards to an impl function with overloads, since member |
317 | // function templates can't be specialized. |
318 | return this->getTrailingObjectsImpl( |
319 | static_cast<BaseTy *>(this), TrailingObjectsBase::OverloadToken<T>()); |
320 | } |
321 | |
322 | /// Returns the size of the trailing data, if an object were |
323 | /// allocated with the given counts (The counts are in the same order |
324 | /// as the template arguments). This does not include the size of the |
325 | /// base object. The template arguments must be the same as those |
326 | /// used in the class; they are supplied here redundantly only so |
327 | /// that it's clear what the counts are counting in callers. |
328 | template <typename... Tys> |
329 | static constexpr std::enable_if_t< |
330 | std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t> |
331 | additionalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType< |
332 | TrailingTys, size_t>::type... Counts) { |
333 | return ParentType::additionalSizeToAllocImpl(0, Counts...); |
334 | } |
335 | |
336 | /// Returns the total size of an object if it were allocated with the |
337 | /// given trailing object counts. This is the same as |
338 | /// additionalSizeToAlloc, except it *does* include the size of the base |
339 | /// object. |
340 | template <typename... Tys> |
341 | static constexpr std::enable_if_t< |
342 | std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t> |
343 | totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType< |
344 | TrailingTys, size_t>::type... Counts) { |
345 | return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...); |
346 | } |
347 | |
348 | /// A type where its ::with_counts template member has a ::type member |
349 | /// suitable for use as uninitialized storage for an object with the given |
350 | /// trailing object counts. The template arguments are similar to those |
351 | /// of additionalSizeToAlloc. |
352 | /// |
353 | /// Use with FixedSizeStorageOwner, e.g.: |
354 | /// |
355 | /// \code{.cpp} |
356 | /// |
357 | /// MyObj::FixedSizeStorage<void *>::with_counts<1u>::type myStackObjStorage; |
358 | /// MyObj::FixedSizeStorageOwner |
359 | /// myStackObjOwner(new ((void *)&myStackObjStorage) MyObj); |
360 | /// MyObj *const myStackObjPtr = myStackObjOwner.get(); |
361 | /// |
362 | /// \endcode |
363 | template <typename... Tys> struct FixedSizeStorage { |
364 | template <size_t... Counts> struct with_counts { |
365 | enum { Size = totalSizeToAlloc<Tys...>(Counts...) }; |
366 | struct type { |
367 | alignas(BaseTy) char buffer[Size]; |
368 | }; |
369 | }; |
370 | }; |
371 | |
372 | /// A type that acts as the owner for an object placed into fixed storage. |
373 | class FixedSizeStorageOwner { |
374 | public: |
375 | FixedSizeStorageOwner(BaseTy *p) : p(p) {} |
376 | ~FixedSizeStorageOwner() { |
377 | assert(p && "FixedSizeStorageOwner owns null?")((p && "FixedSizeStorageOwner owns null?") ? static_cast <void> (0) : __assert_fail ("p && \"FixedSizeStorageOwner owns null?\"" , "/build/llvm-toolchain-snapshot-12~++20210115100614+a14c36fe27f5/llvm/include/llvm/Support/TrailingObjects.h" , 377, __PRETTY_FUNCTION__)); |
378 | p->~BaseTy(); |
379 | } |
380 | |
381 | BaseTy *get() { return p; } |
382 | const BaseTy *get() const { return p; } |
383 | |
384 | private: |
385 | FixedSizeStorageOwner(const FixedSizeStorageOwner &) = delete; |
386 | FixedSizeStorageOwner(FixedSizeStorageOwner &&) = delete; |
387 | FixedSizeStorageOwner &operator=(const FixedSizeStorageOwner &) = delete; |
388 | FixedSizeStorageOwner &operator=(FixedSizeStorageOwner &&) = delete; |
389 | |
390 | BaseTy *const p; |
391 | }; |
392 | }; |
393 | |
394 | } // end namespace llvm |
395 | |
396 | #endif |