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