Bug Summary

File:clang/lib/AST/TemplateBase.cpp
Warning:line 525, column 5
Storage provided to placement new is only 0 bytes, whereas the allocated type requires 48 bytes

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name TemplateBase.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -mthread-model posix -mframe-pointer=none -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-11/lib/clang/11.0.0 -D CLANG_VENDOR="Debian " -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/tools/clang/lib/AST -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/include -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/include -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/tools/clang/lib/AST -fdebug-prefix-map=/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2020-03-09-184146-41876-1 -x c++ /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp

/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/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/DependencyFlags.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
44using 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.
53static 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
87TemplateArgument::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
106TemplateArgument
107TemplateArgument::CreatePackCopy(ASTContext &Context,
108 ArrayRef<TemplateArgument> Args) {
109 if (Args.empty())
110 return getEmptyPack();
111
112 return TemplateArgument(Args.copy(Context));
113}
114
115TemplateArgumentDependence 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-11~++20200309111110+2c36c23f347/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-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 160)
;
161}
162
163bool TemplateArgument::isDependent() const {
164 return getDependence() & TemplateArgumentDependence::Dependent;
165}
166
167bool TemplateArgument::isInstantiationDependent() const {
168 return getDependence() & TemplateArgumentDependence::Instantiation;
169}
170
171bool 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-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 191)
;
192}
193
194bool TemplateArgument::containsUnexpandedParameterPack() const {
195 return getDependence() & TemplateArgumentDependence::UnexpandedPack;
196}
197
198Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
199 assert(getKind() == TemplateExpansion)((getKind() == TemplateExpansion) ? static_cast<void> (
0) : __assert_fail ("getKind() == TemplateExpansion", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 199, __PRETTY_FUNCTION__))
;
200 if (TemplateArg.NumExpansions)
201 return TemplateArg.NumExpansions - 1;
202
203 return None;
204}
205
206QualType 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-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 228)
;
229}
230
231void 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 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
248 break;
249
250 case Template:
251 case TemplateExpansion: {
252 TemplateName Template = getAsTemplateOrTemplatePattern();
253 if (TemplateTemplateParmDecl *TTP
254 = dyn_cast_or_null<TemplateTemplateParmDecl>(
255 Template.getAsTemplateDecl())) {
256 ID.AddBoolean(true);
257 ID.AddInteger(TTP->getDepth());
258 ID.AddInteger(TTP->getPosition());
259 ID.AddBoolean(TTP->isParameterPack());
260 } else {
261 ID.AddBoolean(false);
262 ID.AddPointer(Context.getCanonicalTemplateName(Template)
263 .getAsVoidPointer());
264 }
265 break;
266 }
267
268 case Integral:
269 getAsIntegral().Profile(ID);
270 getIntegralType().Profile(ID);
271 break;
272
273 case Expression:
274 getAsExpr()->Profile(ID, Context, true);
275 break;
276
277 case Pack:
278 ID.AddInteger(Args.NumArgs);
279 for (unsigned I = 0; I != Args.NumArgs; ++I)
280 Args.Args[I].Profile(ID, Context);
281 }
282}
283
284bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
285 if (getKind() != Other.getKind()) return false;
286
287 switch (getKind()) {
288 case Null:
289 case Type:
290 case Expression:
291 case Template:
292 case TemplateExpansion:
293 case NullPtr:
294 return TypeOrValue.V == Other.TypeOrValue.V;
295
296 case Declaration:
297 return getAsDecl() == Other.getAsDecl();
298
299 case Integral:
300 return getIntegralType() == Other.getIntegralType() &&
301 getAsIntegral() == Other.getAsIntegral();
302
303 case Pack:
304 if (Args.NumArgs != Other.Args.NumArgs) return false;
305 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
306 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
307 return false;
308 return true;
309 }
310
311 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 311)
;
312}
313
314TemplateArgument TemplateArgument::getPackExpansionPattern() const {
315 assert(isPackExpansion())((isPackExpansion()) ? static_cast<void> (0) : __assert_fail
("isPackExpansion()", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 315, __PRETTY_FUNCTION__))
;
316
317 switch (getKind()) {
318 case Type:
319 return getAsType()->castAs<PackExpansionType>()->getPattern();
320
321 case Expression:
322 return cast<PackExpansionExpr>(getAsExpr())->getPattern();
323
324 case TemplateExpansion:
325 return TemplateArgument(getAsTemplateOrTemplatePattern());
326
327 case Declaration:
328 case Integral:
329 case Pack:
330 case Null:
331 case Template:
332 case NullPtr:
333 return TemplateArgument();
334 }
335
336 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 336)
;
337}
338
339void TemplateArgument::print(const PrintingPolicy &Policy,
340 raw_ostream &Out) const {
341 switch (getKind()) {
342 case Null:
343 Out << "(no value)";
344 break;
345
346 case Type: {
347 PrintingPolicy SubPolicy(Policy);
348 SubPolicy.SuppressStrongLifetime = true;
349 getAsType().print(Out, SubPolicy);
350 break;
351 }
352
353 case Declaration: {
354 NamedDecl *ND = getAsDecl();
355 Out << '&';
356 if (ND->getDeclName()) {
357 // FIXME: distinguish between pointer and reference args?
358 ND->printQualifiedName(Out);
359 } else {
360 Out << "(anonymous)";
361 }
362 break;
363 }
364
365 case NullPtr:
366 Out << "nullptr";
367 break;
368
369 case Template:
370 getAsTemplate().print(Out, Policy);
371 break;
372
373 case TemplateExpansion:
374 getAsTemplateOrTemplatePattern().print(Out, Policy);
375 Out << "...";
376 break;
377
378 case Integral:
379 printIntegral(*this, Out, Policy);
380 break;
381
382 case Expression:
383 getAsExpr()->printPretty(Out, nullptr, Policy);
384 break;
385
386 case Pack:
387 Out << "<";
388 bool First = true;
389 for (const auto &P : pack_elements()) {
390 if (First)
391 First = false;
392 else
393 Out << ", ";
394
395 P.print(Policy, Out);
396 }
397 Out << ">";
398 break;
399 }
400}
401
402void TemplateArgument::dump(raw_ostream &Out) const {
403 LangOptions LO; // FIXME! see also TemplateName::dump().
404 LO.CPlusPlus = true;
405 LO.Bool = true;
406 print(PrintingPolicy(LO), Out);
407}
408
409LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void TemplateArgument::dump() const { dump(llvm::errs()); }
410
411//===----------------------------------------------------------------------===//
412// TemplateArgumentLoc Implementation
413//===----------------------------------------------------------------------===//
414
415SourceRange TemplateArgumentLoc::getSourceRange() const {
416 switch (Argument.getKind()) {
417 case TemplateArgument::Expression:
418 return getSourceExpression()->getSourceRange();
419
420 case TemplateArgument::Declaration:
421 return getSourceDeclExpression()->getSourceRange();
422
423 case TemplateArgument::NullPtr:
424 return getSourceNullPtrExpression()->getSourceRange();
425
426 case TemplateArgument::Type:
427 if (TypeSourceInfo *TSI = getTypeSourceInfo())
428 return TSI->getTypeLoc().getSourceRange();
429 else
430 return SourceRange();
431
432 case TemplateArgument::Template:
433 if (getTemplateQualifierLoc())
434 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
435 getTemplateNameLoc());
436 return SourceRange(getTemplateNameLoc());
437
438 case TemplateArgument::TemplateExpansion:
439 if (getTemplateQualifierLoc())
440 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
441 getTemplateEllipsisLoc());
442 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
443
444 case TemplateArgument::Integral:
445 return getSourceIntegralExpression()->getSourceRange();
446
447 case TemplateArgument::Pack:
448 case TemplateArgument::Null:
449 return SourceRange();
450 }
451
452 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 452)
;
453}
454
455const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
456 const TemplateArgument &Arg) {
457 switch (Arg.getKind()) {
458 case TemplateArgument::Null:
459 // This is bad, but not as bad as crashing because of argument
460 // count mismatches.
461 return DB << "(null template argument)";
462
463 case TemplateArgument::Type:
464 return DB << Arg.getAsType();
465
466 case TemplateArgument::Declaration:
467 return DB << Arg.getAsDecl();
468
469 case TemplateArgument::NullPtr:
470 return DB << "nullptr";
471
472 case TemplateArgument::Integral:
473 return DB << Arg.getAsIntegral().toString(10);
474
475 case TemplateArgument::Template:
476 return DB << Arg.getAsTemplate();
477
478 case TemplateArgument::TemplateExpansion:
479 return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
480
481 case TemplateArgument::Expression: {
482 // This shouldn't actually ever happen, so it's okay that we're
483 // regurgitating an expression here.
484 // FIXME: We're guessing at LangOptions!
485 SmallString<32> Str;
486 llvm::raw_svector_ostream OS(Str);
487 LangOptions LangOpts;
488 LangOpts.CPlusPlus = true;
489 PrintingPolicy Policy(LangOpts);
490 Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
491 return DB << OS.str();
492 }
493
494 case TemplateArgument::Pack: {
495 // FIXME: We're guessing at LangOptions!
496 SmallString<32> Str;
497 llvm::raw_svector_ostream OS(Str);
498 LangOptions LangOpts;
499 LangOpts.CPlusPlus = true;
500 PrintingPolicy Policy(LangOpts);
501 Arg.print(Policy, OS);
502 return DB << OS.str();
503 }
504 }
505
506 llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 506)
;
507}
508
509const ASTTemplateArgumentListInfo *
510ASTTemplateArgumentListInfo::Create(const ASTContext &C,
511 const TemplateArgumentListInfo &List) {
512 std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
513 void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
514 return new (Mem) ASTTemplateArgumentListInfo(List);
1
Calling constructor for 'ASTTemplateArgumentListInfo'
515}
516
517ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
518 const TemplateArgumentListInfo &Info) {
519 LAngleLoc = Info.getLAngleLoc();
520 RAngleLoc = Info.getRAngleLoc();
521 NumTemplateArgs = Info.size();
522
523 TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
2
Calling 'TrailingObjects::getTrailingObjects'
11
Returning from 'TrailingObjects::getTrailingObjects'
12
'ArgBuffer' initialized here
524 for (unsigned i = 0; i != NumTemplateArgs; ++i)
13
Assuming 'i' is not equal to field 'NumTemplateArgs'
14
Loop condition is true. Entering loop body
525 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
15
Storage provided to placement new is only 0 bytes, whereas the allocated type requires 48 bytes
526}
527
528void ASTTemplateKWAndArgsInfo::initializeFrom(
529 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
530 TemplateArgumentLoc *OutArgArray) {
531 this->TemplateKWLoc = TemplateKWLoc;
532 LAngleLoc = Info.getLAngleLoc();
533 RAngleLoc = Info.getRAngleLoc();
534 NumTemplateArgs = Info.size();
535
536 for (unsigned i = 0; i != NumTemplateArgs; ++i)
537 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
538}
539
540void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
541 assert(TemplateKWLoc.isValid())((TemplateKWLoc.isValid()) ? static_cast<void> (0) : __assert_fail
("TemplateKWLoc.isValid()", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/AST/TemplateBase.cpp"
, 541, __PRETTY_FUNCTION__))
;
542 LAngleLoc = SourceLocation();
543 RAngleLoc = SourceLocation();
544 this->TemplateKWLoc = TemplateKWLoc;
545 NumTemplateArgs = 0;
546}
547
548void ASTTemplateKWAndArgsInfo::initializeFrom(
549 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
550 TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) {
551 this->TemplateKWLoc = TemplateKWLoc;
552 LAngleLoc = Info.getLAngleLoc();
553 RAngleLoc = Info.getRAngleLoc();
554 NumTemplateArgs = Info.size();
555
556 for (unsigned i = 0; i != NumTemplateArgs; ++i) {
557 Deps |= Info[i].getArgument().getDependence();
558
559 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
560 }
561}
562
563void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
564 TemplateArgumentListInfo &Info) const {
565 Info.setLAngleLoc(LAngleLoc);
566 Info.setRAngleLoc(RAngleLoc);
567 for (unsigned I = 0; I != NumTemplateArgs; ++I)
568 Info.addArgument(ArgArray[I]);
569}

/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/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
91template <int Align>
92class TrailingObjectsAligner : public TrailingObjectsBase {};
93template <>
94class alignas(1) TrailingObjectsAligner<1> : public TrailingObjectsBase {};
95template <>
96class alignas(2) TrailingObjectsAligner<2> : public TrailingObjectsBase {};
97template <>
98class alignas(4) TrailingObjectsAligner<4> : public TrailingObjectsBase {};
99template <>
100class alignas(8) TrailingObjectsAligner<8> : public TrailingObjectsBase {};
101template <>
102class alignas(16) TrailingObjectsAligner<16> : public TrailingObjectsBase {
103};
104template <>
105class 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
111template <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
123template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy,
124 typename... MoreTys>
125class TrailingObjectsImpl {
126 // The main template definition is never used -- the two
127 // specializations cover all possibilities.
128};
129
130template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy,
131 typename NextTy, typename... MoreTys>
132class 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
148protected:
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(
6
'Ptr' initialized here
180 Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) +
5
Passing value via 1st parameter 'Obj'
181 TopTrailingObj::callNumTrailingObjects(
182 Obj, TrailingObjectsBase::OverloadToken<PrevTy>());
183
184 if (requiresRealignment())
7
Taking false branch
185 return reinterpret_cast<NextTy *>(alignAddr(Ptr, Align::Of<NextTy>()));
186 else
187 return reinterpret_cast<NextTy *>(Ptr);
8
Returning pointer (loaded from '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.
206template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy>
207class TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy>
208 : public TrailingObjectsAligner<Align> {
209protected:
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.
228template <typename BaseTy, typename... TrailingTys>
229class 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
288public:
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(
4
Calling 'TrailingObjectsImpl::getTrailingObjectsImpl'
9
Returning from 'TrailingObjectsImpl::getTrailingObjectsImpl'
10
Returning pointer
319 static_cast<BaseTy *>(this), TrailingObjectsBase::OverloadToken<T>());
3
Passing value via 1st parameter 'Obj'
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-11~++20200309111110+2c36c23f347/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