Bug Summary

File:build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/clang/lib/AST/TemplateBase.cpp
Warning:line 639, column 5
Storage provided to placement new is only 0 bytes, whereas the allocated type requires 32 bytes

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name TemplateBase.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/build-llvm -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/lib/AST -I /build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/clang/lib/AST -I /build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/clang/include -I tools/clang/include -I include -I /build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-10-03-140002-15933-1 -x c++ /build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/clang/lib/AST/TemplateBase.cpp

/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/clang/lib/AST/TemplateBase.cpp

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
45using 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.
57static 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 (Policy.UseEnumerators) {
63 if (const EnumType *ET = T->getAs<EnumType>()) {
64 for (const EnumConstantDecl *ECD : ET->getDecl()->enumerators()) {
65 // In Sema::CheckTemplateArugment, enum template arguments value are
66 // extended to the size of the integer underlying the enum type. This
67 // may create a size difference between the enum value and template
68 // argument value, requiring isSameValue here instead of operator==.
69 if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
70 ECD->printQualifiedName(Out, Policy);
71 return;
72 }
73 }
74 }
75 }
76
77 if (Policy.MSVCFormatting)
78 IncludeType = false;
79
80 if (T->isBooleanType()) {
81 if (!Policy.MSVCFormatting)
82 Out << (Val.getBoolValue() ? "true" : "false");
83 else
84 Out << Val;
85 } else if (T->isCharType()) {
86 if (IncludeType) {
87 if (T->isSpecificBuiltinType(BuiltinType::SChar))
88 Out << "(signed char)";
89 else if (T->isSpecificBuiltinType(BuiltinType::UChar))
90 Out << "(unsigned char)";
91 }
92 CharacterLiteral::print(Val.getZExtValue(), CharacterLiteral::Ascii, Out);
93 } else if (T->isAnyCharacterType() && !Policy.MSVCFormatting) {
94 CharacterLiteral::CharacterKind Kind;
95 if (T->isWideCharType())
96 Kind = CharacterLiteral::Wide;
97 else if (T->isChar8Type())
98 Kind = CharacterLiteral::UTF8;
99 else if (T->isChar16Type())
100 Kind = CharacterLiteral::UTF16;
101 else if (T->isChar32Type())
102 Kind = CharacterLiteral::UTF32;
103 else
104 Kind = CharacterLiteral::Ascii;
105 CharacterLiteral::print(Val.getExtValue(), Kind, Out);
106 } else if (IncludeType) {
107 if (const auto *BT = T->getAs<BuiltinType>()) {
108 switch (BT->getKind()) {
109 case BuiltinType::ULongLong:
110 Out << Val << "ULL";
111 break;
112 case BuiltinType::LongLong:
113 Out << Val << "LL";
114 break;
115 case BuiltinType::ULong:
116 Out << Val << "UL";
117 break;
118 case BuiltinType::Long:
119 Out << Val << "L";
120 break;
121 case BuiltinType::UInt:
122 Out << Val << "U";
123 break;
124 case BuiltinType::Int:
125 Out << Val;
126 break;
127 default:
128 Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
129 << Val;
130 break;
131 }
132 } else
133 Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
134 << Val;
135 } else
136 Out << Val;
137}
138
139static unsigned getArrayDepth(QualType type) {
140 unsigned count = 0;
141 while (const auto *arrayType = type->getAsArrayTypeUnsafe()) {
142 count++;
143 type = arrayType->getElementType();
144 }
145 return count;
146}
147
148static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) {
149 // Generally, if the parameter type is a pointer, we must be taking the
150 // address of something and need a &. However, if the argument is an array,
151 // this could be implicit via array-to-pointer decay.
152 if (!paramType->isPointerType())
153 return paramType->isMemberPointerType();
154 if (argType->isArrayType())
155 return getArrayDepth(argType) == getArrayDepth(paramType->getPointeeType());
156 return true;
157}
158
159//===----------------------------------------------------------------------===//
160// TemplateArgument Implementation
161//===----------------------------------------------------------------------===//
162
163TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
164 QualType Type) {
165 Integer.Kind = Integral;
166 // Copy the APSInt value into our decomposed form.
167 Integer.BitWidth = Value.getBitWidth();
168 Integer.IsUnsigned = Value.isUnsigned();
169 // If the value is large, we have to get additional memory from the ASTContext
170 unsigned NumWords = Value.getNumWords();
171 if (NumWords > 1) {
172 void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t));
173 std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t));
174 Integer.pVal = static_cast<uint64_t *>(Mem);
175 } else {
176 Integer.VAL = Value.getZExtValue();
177 }
178
179 Integer.Type = Type.getAsOpaquePtr();
180}
181
182TemplateArgument
183TemplateArgument::CreatePackCopy(ASTContext &Context,
184 ArrayRef<TemplateArgument> Args) {
185 if (Args.empty())
186 return getEmptyPack();
187
188 return TemplateArgument(Args.copy(Context));
189}
190
191TemplateArgumentDependence TemplateArgument::getDependence() const {
192 auto Deps = TemplateArgumentDependence::None;
193 switch (getKind()) {
194 case Null:
195 llvm_unreachable("Should not have a NULL template argument")::llvm::llvm_unreachable_internal("Should not have a NULL template argument"
, "clang/lib/AST/TemplateBase.cpp", 195)
;
196
197 case Type:
198 Deps = toTemplateArgumentDependence(getAsType()->getDependence());
199 if (isa<PackExpansionType>(getAsType()))
200 Deps |= TemplateArgumentDependence::Dependent;
201 return Deps;
202
203 case Template:
204 return toTemplateArgumentDependence(getAsTemplate().getDependence());
205
206 case TemplateExpansion:
207 return TemplateArgumentDependence::Dependent |
208 TemplateArgumentDependence::Instantiation;
209
210 case Declaration: {
211 auto *DC = dyn_cast<DeclContext>(getAsDecl());
212 if (!DC)
213 DC = getAsDecl()->getDeclContext();
214 if (DC->isDependentContext())
215 Deps = TemplateArgumentDependence::Dependent |
216 TemplateArgumentDependence::Instantiation;
217 return Deps;
218 }
219
220 case NullPtr:
221 case Integral:
222 return TemplateArgumentDependence::None;
223
224 case Expression:
225 Deps = toTemplateArgumentDependence(getAsExpr()->getDependence());
226 if (isa<PackExpansionExpr>(getAsExpr()))
227 Deps |= TemplateArgumentDependence::Dependent |
228 TemplateArgumentDependence::Instantiation;
229 return Deps;
230
231 case Pack:
232 for (const auto &P : pack_elements())
233 Deps |= P.getDependence();
234 return Deps;
235 }
236 llvm_unreachable("unhandled ArgKind")::llvm::llvm_unreachable_internal("unhandled ArgKind", "clang/lib/AST/TemplateBase.cpp"
, 236)
;
237}
238
239bool TemplateArgument::isDependent() const {
240 return getDependence() & TemplateArgumentDependence::Dependent;
241}
242
243bool TemplateArgument::isInstantiationDependent() const {
244 return getDependence() & TemplateArgumentDependence::Instantiation;
245}
246
247bool TemplateArgument::isPackExpansion() const {
248 switch (getKind()) {
249 case Null:
250 case Declaration:
251 case Integral:
252 case Pack:
253 case Template:
254 case NullPtr:
255 return false;
256
257 case TemplateExpansion:
258 return true;
259
260 case Type:
261 return isa<PackExpansionType>(getAsType());
262
263 case Expression:
264 return isa<PackExpansionExpr>(getAsExpr());
265 }
266
267 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "clang/lib/AST/TemplateBase.cpp", 267)
;
268}
269
270bool TemplateArgument::containsUnexpandedParameterPack() const {
271 return getDependence() & TemplateArgumentDependence::UnexpandedPack;
272}
273
274Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
275 assert(getKind() == TemplateExpansion)(static_cast <bool> (getKind() == TemplateExpansion) ? void
(0) : __assert_fail ("getKind() == TemplateExpansion", "clang/lib/AST/TemplateBase.cpp"
, 275, __extension__ __PRETTY_FUNCTION__))
;
276 if (TemplateArg.NumExpansions)
277 return TemplateArg.NumExpansions - 1;
278
279 return None;
280}
281
282QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
283 switch (getKind()) {
284 case TemplateArgument::Null:
285 case TemplateArgument::Type:
286 case TemplateArgument::Template:
287 case TemplateArgument::TemplateExpansion:
288 case TemplateArgument::Pack:
289 return QualType();
290
291 case TemplateArgument::Integral:
292 return getIntegralType();
293
294 case TemplateArgument::Expression:
295 return getAsExpr()->getType();
296
297 case TemplateArgument::Declaration:
298 return getParamTypeForDecl();
299
300 case TemplateArgument::NullPtr:
301 return getNullPtrType();
302 }
303
304 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "clang/lib/AST/TemplateBase.cpp", 304)
;
305}
306
307void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
308 const ASTContext &Context) const {
309 ID.AddInteger(getKind());
310 switch (getKind()) {
311 case Null:
312 break;
313
314 case Type:
315 getAsType().Profile(ID);
316 break;
317
318 case NullPtr:
319 getNullPtrType().Profile(ID);
320 break;
321
322 case Declaration:
323 getParamTypeForDecl().Profile(ID);
324 ID.AddPointer(getAsDecl());
325 break;
326
327 case TemplateExpansion:
328 ID.AddInteger(TemplateArg.NumExpansions);
329 LLVM_FALLTHROUGH[[fallthrough]];
330 case Template:
331 getAsTemplateOrTemplatePattern().Profile(ID);
332 break;
333
334 case Integral:
335 getAsIntegral().Profile(ID);
336 getIntegralType().Profile(ID);
337 break;
338
339 case Expression:
340 getAsExpr()->Profile(ID, Context, true);
341 break;
342
343 case Pack:
344 ID.AddInteger(Args.NumArgs);
345 for (unsigned I = 0; I != Args.NumArgs; ++I)
346 Args.Args[I].Profile(ID, Context);
347 }
348}
349
350bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
351 if (getKind() != Other.getKind()) return false;
352
353 switch (getKind()) {
354 case Null:
355 case Type:
356 case Expression:
357 case NullPtr:
358 return TypeOrValue.V == Other.TypeOrValue.V;
359
360 case Template:
361 case TemplateExpansion:
362 return TemplateArg.Name == Other.TemplateArg.Name &&
363 TemplateArg.NumExpansions == Other.TemplateArg.NumExpansions;
364
365 case Declaration:
366 return getAsDecl() == Other.getAsDecl();
367
368 case Integral:
369 return getIntegralType() == Other.getIntegralType() &&
370 getAsIntegral() == Other.getAsIntegral();
371
372 case Pack:
373 if (Args.NumArgs != Other.Args.NumArgs) return false;
374 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
375 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
376 return false;
377 return true;
378 }
379
380 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "clang/lib/AST/TemplateBase.cpp", 380)
;
381}
382
383TemplateArgument TemplateArgument::getPackExpansionPattern() const {
384 assert(isPackExpansion())(static_cast <bool> (isPackExpansion()) ? void (0) : __assert_fail
("isPackExpansion()", "clang/lib/AST/TemplateBase.cpp", 384,
__extension__ __PRETTY_FUNCTION__))
;
385
386 switch (getKind()) {
387 case Type:
388 return getAsType()->castAs<PackExpansionType>()->getPattern();
389
390 case Expression:
391 return cast<PackExpansionExpr>(getAsExpr())->getPattern();
392
393 case TemplateExpansion:
394 return TemplateArgument(getAsTemplateOrTemplatePattern());
395
396 case Declaration:
397 case Integral:
398 case Pack:
399 case Null:
400 case Template:
401 case NullPtr:
402 return TemplateArgument();
403 }
404
405 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "clang/lib/AST/TemplateBase.cpp", 405)
;
406}
407
408void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
409 bool IncludeType) const {
410
411 switch (getKind()) {
412 case Null:
413 Out << "(no value)";
414 break;
415
416 case Type: {
417 PrintingPolicy SubPolicy(Policy);
418 SubPolicy.SuppressStrongLifetime = true;
419 getAsType().print(Out, SubPolicy);
420 break;
421 }
422
423 case Declaration: {
424 // FIXME: Include the type if it's not obvious from the context.
425 NamedDecl *ND = getAsDecl();
426 if (getParamTypeForDecl()->isRecordType()) {
427 if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
428 TPO->printAsInit(Out, Policy);
429 break;
430 }
431 }
432 if (auto *VD = dyn_cast<ValueDecl>(ND)) {
433 if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType()))
434 Out << "&";
435 }
436 ND->printQualifiedName(Out);
437 break;
438 }
439
440 case NullPtr:
441 // FIXME: Include the type if it's not obvious from the context.
442 Out << "nullptr";
443 break;
444
445 case Template:
446 getAsTemplate().print(Out, Policy, TemplateName::Qualified::Fully);
447 break;
448
449 case TemplateExpansion:
450 getAsTemplateOrTemplatePattern().print(Out, Policy);
451 Out << "...";
452 break;
453
454 case Integral:
455 printIntegral(*this, Out, Policy, IncludeType);
456 break;
457
458 case Expression:
459 getAsExpr()->printPretty(Out, nullptr, Policy);
460 break;
461
462 case Pack:
463 Out << "<";
464 bool First = true;
465 for (const auto &P : pack_elements()) {
466 if (First)
467 First = false;
468 else
469 Out << ", ";
470
471 P.print(Policy, Out, IncludeType);
472 }
473 Out << ">";
474 break;
475 }
476}
477
478void TemplateArgument::dump(raw_ostream &Out) const {
479 LangOptions LO; // FIXME! see also TemplateName::dump().
480 LO.CPlusPlus = true;
481 LO.Bool = true;
482 print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
483}
484
485LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void TemplateArgument::dump() const { dump(llvm::errs()); }
486
487//===----------------------------------------------------------------------===//
488// TemplateArgumentLoc Implementation
489//===----------------------------------------------------------------------===//
490
491SourceRange TemplateArgumentLoc::getSourceRange() const {
492 switch (Argument.getKind()) {
493 case TemplateArgument::Expression:
494 return getSourceExpression()->getSourceRange();
495
496 case TemplateArgument::Declaration:
497 return getSourceDeclExpression()->getSourceRange();
498
499 case TemplateArgument::NullPtr:
500 return getSourceNullPtrExpression()->getSourceRange();
501
502 case TemplateArgument::Type:
503 if (TypeSourceInfo *TSI = getTypeSourceInfo())
504 return TSI->getTypeLoc().getSourceRange();
505 else
506 return SourceRange();
507
508 case TemplateArgument::Template:
509 if (getTemplateQualifierLoc())
510 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
511 getTemplateNameLoc());
512 return SourceRange(getTemplateNameLoc());
513
514 case TemplateArgument::TemplateExpansion:
515 if (getTemplateQualifierLoc())
516 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
517 getTemplateEllipsisLoc());
518 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
519
520 case TemplateArgument::Integral:
521 return getSourceIntegralExpression()->getSourceRange();
522
523 case TemplateArgument::Pack:
524 case TemplateArgument::Null:
525 return SourceRange();
526 }
527
528 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "clang/lib/AST/TemplateBase.cpp", 528)
;
529}
530
531template <typename T>
532static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
533 switch (Arg.getKind()) {
534 case TemplateArgument::Null:
535 // This is bad, but not as bad as crashing because of argument
536 // count mismatches.
537 return DB << "(null template argument)";
538
539 case TemplateArgument::Type:
540 return DB << Arg.getAsType();
541
542 case TemplateArgument::Declaration:
543 return DB << Arg.getAsDecl();
544
545 case TemplateArgument::NullPtr:
546 return DB << "nullptr";
547
548 case TemplateArgument::Integral:
549 return DB << toString(Arg.getAsIntegral(), 10);
550
551 case TemplateArgument::Template:
552 return DB << Arg.getAsTemplate();
553
554 case TemplateArgument::TemplateExpansion:
555 return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
556
557 case TemplateArgument::Expression: {
558 // This shouldn't actually ever happen, so it's okay that we're
559 // regurgitating an expression here.
560 // FIXME: We're guessing at LangOptions!
561 SmallString<32> Str;
562 llvm::raw_svector_ostream OS(Str);
563 LangOptions LangOpts;
564 LangOpts.CPlusPlus = true;
565 PrintingPolicy Policy(LangOpts);
566 Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
567 return DB << OS.str();
568 }
569
570 case TemplateArgument::Pack: {
571 // FIXME: We're guessing at LangOptions!
572 SmallString<32> Str;
573 llvm::raw_svector_ostream OS(Str);
574 LangOptions LangOpts;
575 LangOpts.CPlusPlus = true;
576 PrintingPolicy Policy(LangOpts);
577 Arg.print(Policy, OS, /*IncludeType*/ true);
578 return DB << OS.str();
579 }
580 }
581
582 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "clang/lib/AST/TemplateBase.cpp", 582)
;
583}
584
585const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
586 const TemplateArgument &Arg) {
587 return DiagTemplateArg(DB, Arg);
588}
589
590clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo(
591 ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
592 SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) {
593 TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo;
594 Template->Qualifier = QualifierLoc.getNestedNameSpecifier();
595 Template->QualifierLocData = QualifierLoc.getOpaqueData();
596 Template->TemplateNameLoc = TemplateNameLoc;
597 Template->EllipsisLoc = EllipsisLoc;
598 Pointer = Template;
599}
600
601const ASTTemplateArgumentListInfo *
602ASTTemplateArgumentListInfo::Create(const ASTContext &C,
603 const TemplateArgumentListInfo &List) {
604 std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
605 void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
606 return new (Mem) ASTTemplateArgumentListInfo(List);
607}
608
609const ASTTemplateArgumentListInfo *
610ASTTemplateArgumentListInfo::Create(const ASTContext &C,
611 const ASTTemplateArgumentListInfo *List) {
612 if (!List)
1
Assuming 'List' is non-null
2
Taking false branch
613 return nullptr;
614 std::size_t size =
615 totalSizeToAlloc<TemplateArgumentLoc>(List->getNumTemplateArgs());
616 void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
617 return new (Mem) ASTTemplateArgumentListInfo(List);
3
Calling constructor for 'ASTTemplateArgumentListInfo'
618}
619
620ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
621 const TemplateArgumentListInfo &Info) {
622 LAngleLoc = Info.getLAngleLoc();
623 RAngleLoc = Info.getRAngleLoc();
624 NumTemplateArgs = Info.size();
625
626 TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
627 for (unsigned i = 0; i != NumTemplateArgs; ++i)
628 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
629}
630
631ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
632 const ASTTemplateArgumentListInfo *Info) {
633 LAngleLoc = Info->getLAngleLoc();
634 RAngleLoc = Info->getRAngleLoc();
635 NumTemplateArgs = Info->getNumTemplateArgs();
636
637 TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
4
Calling 'TrailingObjects::getTrailingObjects'
13
Returning from 'TrailingObjects::getTrailingObjects'
14
'ArgBuffer' initialized here
638 for (unsigned i = 0; i != NumTemplateArgs; ++i)
15
Assuming 'i' is not equal to field 'NumTemplateArgs'
16
Loop condition is true. Entering loop body
639 new (&ArgBuffer[i]) TemplateArgumentLoc((*Info)[i]);
17
Storage provided to placement new is only 0 bytes, whereas the allocated type requires 32 bytes
640}
641
642void ASTTemplateKWAndArgsInfo::initializeFrom(
643 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
644 TemplateArgumentLoc *OutArgArray) {
645 this->TemplateKWLoc = TemplateKWLoc;
646 LAngleLoc = Info.getLAngleLoc();
647 RAngleLoc = Info.getRAngleLoc();
648 NumTemplateArgs = Info.size();
649
650 for (unsigned i = 0; i != NumTemplateArgs; ++i)
651 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
652}
653
654void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
655 assert(TemplateKWLoc.isValid())(static_cast <bool> (TemplateKWLoc.isValid()) ? void (0
) : __assert_fail ("TemplateKWLoc.isValid()", "clang/lib/AST/TemplateBase.cpp"
, 655, __extension__ __PRETTY_FUNCTION__))
;
656 LAngleLoc = SourceLocation();
657 RAngleLoc = SourceLocation();
658 this->TemplateKWLoc = TemplateKWLoc;
659 NumTemplateArgs = 0;
660}
661
662void ASTTemplateKWAndArgsInfo::initializeFrom(
663 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
664 TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) {
665 this->TemplateKWLoc = TemplateKWLoc;
666 LAngleLoc = Info.getLAngleLoc();
667 RAngleLoc = Info.getRAngleLoc();
668 NumTemplateArgs = Info.size();
669
670 for (unsigned i = 0; i != NumTemplateArgs; ++i) {
671 Deps |= Info[i].getArgument().getDependence();
672
673 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
674 }
675}
676
677void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
678 TemplateArgumentListInfo &Info) const {
679 Info.setLAngleLoc(LAngleLoc);
680 Info.setRAngleLoc(RAngleLoc);
681 for (unsigned I = 0; I != NumTemplateArgs; ++I)
682 Info.addArgument(ArgArray[I]);
683}

/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/llvm/include/llvm/Support/TrailingObjects.h

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
57namespace llvm {
58
59namespace trailing_objects_internal {
60/// Helper template to calculate the max alignment requirement for a set of
61/// objects.
62template <typename First, typename... Rest> class AlignmentCalcHelper {
63private:
64 enum {
65 FirstAlignment = alignof(First),
66 RestAlignment = AlignmentCalcHelper<Rest...>::Alignment,
67 };
68
69public:
70 enum {
71 Alignment = FirstAlignment > RestAlignment ? FirstAlignment : RestAlignment
72 };
73};
74
75template <typename First> class AlignmentCalcHelper<First> {
76public:
77 enum { Alignment = alignof(First) };
78};
79
80/// The base class for TrailingObjects* classes.
81class TrailingObjectsBase {
82protected:
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
94template <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
106template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy,
107 typename... MoreTys>
108class TrailingObjectsImpl {
109 // The main template definition is never used -- the two
110 // specializations cover all possibilities.
111};
112
113template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy,
114 typename NextTy, typename... MoreTys>
115class 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
131protected:
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(
8
'Ptr' initialized here
163 Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) +
7
Passing value via 1st parameter 'Obj'
164 TopTrailingObj::callNumTrailingObjects(
165 Obj, TrailingObjectsBase::OverloadToken<PrevTy>());
166
167 if (requiresRealignment())
9
Taking false branch
168 return reinterpret_cast<NextTy *>(alignAddr(Ptr, Align::Of<NextTy>()));
169 else
170 return reinterpret_cast<NextTy *>(Ptr);
10
Returning pointer (loaded from '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.
189template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy>
190class alignas(Align) TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy>
191 : public TrailingObjectsBase {
192protected:
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.
211template <typename BaseTy, typename... TrailingTys>
212class 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
271public:
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(
6
Calling 'TrailingObjectsImpl::getTrailingObjectsImpl'
11
Returning from 'TrailingObjectsImpl::getTrailingObjectsImpl'
12
Returning pointer
302 static_cast<BaseTy *>(this), TrailingObjectsBase::OverloadToken<T>());
5
Passing value via 1st parameter 'Obj'
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?\""
, "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