clang 23.0.0git
ExprEngineCXX.cpp
Go to the documentation of this file.
1//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- 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// This file defines the C++ expression evaluation engine.
10//
11//===----------------------------------------------------------------------===//
12
15#include "clang/AST/DeclCXX.h"
16#include "clang/AST/ParentMap.h"
17#include "clang/AST/StmtCXX.h"
25#include "llvm/ADT/STLExtras.h"
26#include "llvm/ADT/Sequence.h"
27#include "llvm/Support/Casting.h"
28#include <optional>
29
30using namespace clang;
31using namespace ento;
32
34 ExplodedNode *Pred,
35 ExplodedNodeSet &Dst) {
36 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
37 const Expr *tempExpr = ME->getSubExpr()->IgnoreParens();
38 ProgramStateRef state = Pred->getState();
39 const LocationContext *LCtx = Pred->getLocationContext();
40
41 state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME);
42 Bldr.generateNode(ME, Pred, state);
43}
44
45// FIXME: This is the sort of code that should eventually live in a Core
46// checker rather than as a special case in ExprEngine.
47void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
48 const CallEvent &Call) {
49 SVal ThisVal;
50 bool AlwaysReturnsLValue;
51 [[maybe_unused]] const CXXRecordDecl *ThisRD = nullptr;
52 if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
53 assert(Ctor->getDecl()->isTrivial());
54 assert(Ctor->getDecl()->isCopyOrMoveConstructor());
55 ThisVal = Ctor->getCXXThisVal();
56 ThisRD = Ctor->getDecl()->getParent();
57 AlwaysReturnsLValue = false;
58 } else {
59 assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial());
60 assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() ==
61 OO_Equal);
62 ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal();
63 ThisRD = cast<CXXMethodDecl>(Call.getDecl())->getParent();
64 AlwaysReturnsLValue = true;
65 }
66
67 const LocationContext *LCtx = Pred->getLocationContext();
68 const Expr *CallExpr = Call.getOriginExpr();
69
71 Bldr.takeNodes(Pred);
72
73 assert(ThisRD);
74
75 if (!ThisRD->isEmpty()) {
76 SVal V = Call.getArgSVal(0);
77 const Expr *VExpr = Call.getArgExpr(0);
78
79 // If the value being copied is not unknown, load from its location to get
80 // an aggregate rvalue.
81 if (std::optional<Loc> L = V.getAs<Loc>())
82 V = Pred->getState()->getSVal(*L);
83 else
84 assert(V.isUnknownOrUndef());
85
87 evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V,
88 /*isLoad=*/true);
89 for (ExplodedNode *N : Tmp)
90 evalBind(Dst, CallExpr, N, ThisVal, V, !AlwaysReturnsLValue);
91 } else {
92 // We can't copy empty classes because of empty base class optimization.
93 // In that case, copying the empty base class subobject would overwrite the
94 // object that it overlaps with - so let's not do that.
95 // See issue-157467.cpp for an example.
96 Dst.insert(Pred);
97 }
98
99 PostStmt PS(CallExpr, LCtx);
100 for (ExplodedNode *N : Dst) {
101 ProgramStateRef State = N->getState();
102 if (AlwaysReturnsLValue)
103 State = State->BindExpr(CallExpr, LCtx, ThisVal);
104 else
105 State = bindReturnValue(Call, LCtx, State);
106 Bldr.generateNode(PS, State, N);
107 }
108}
109
110SVal ExprEngine::makeElementRegion(ProgramStateRef State, SVal LValue,
111 QualType &Ty, bool &IsArray, unsigned Idx) {
112 SValBuilder &SVB = State->getStateManager().getSValBuilder();
113 ASTContext &Ctx = SVB.getContext();
114
115 if (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
116 while (AT) {
117 Ty = AT->getElementType();
118 AT = dyn_cast<ArrayType>(AT->getElementType());
119 }
120 LValue = State->getLValue(Ty, SVB.makeArrayIndex(Idx), LValue);
121 IsArray = true;
122 }
123
124 return LValue;
125}
126
127// In case when the prvalue is returned from the function (kind is one of
128// SimpleReturnedValueKind, CXX17ElidedCopyReturnedValueKind), then
129// it's materialization happens in context of the caller.
131 const Expr *E, ProgramStateRef State, unsigned NumVisitedCaller,
132 const LocationContext *LCtx, const ConstructionContext *CC,
133 EvalCallOptions &CallOpts, unsigned Idx) {
134
136 MemRegionManager &MRMgr = SVB.getRegionManager();
137 ASTContext &ACtx = SVB.getContext();
138
139 // Compute the target region by exploring the construction context.
140 if (CC) {
141 switch (CC->getKind()) {
144 const auto *DSCC = cast<VariableConstructionContext>(CC);
145 const auto *DS = DSCC->getDeclStmt();
146 const auto *Var = cast<VarDecl>(DS->getSingleDecl());
147 QualType Ty = Var->getType();
148 return makeElementRegion(State, State->getLValue(Var, LCtx), Ty,
149 CallOpts.IsArrayCtorOrDtor, Idx);
150 }
154 const auto *Init = ICC->getCXXCtorInitializer();
155 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
156 Loc ThisPtr = SVB.getCXXThis(CurCtor, LCtx->getStackFrame());
157 SVal ThisVal = State->getSVal(ThisPtr);
158 if (Init->isBaseInitializer()) {
159 const auto *ThisReg = cast<SubRegion>(ThisVal.getAsRegion());
160 const CXXRecordDecl *BaseClass =
161 Init->getBaseClass()->getAsCXXRecordDecl();
162 const auto *BaseReg =
163 MRMgr.getCXXBaseObjectRegion(BaseClass, ThisReg,
164 Init->isBaseVirtual());
165 return SVB.makeLoc(BaseReg);
166 }
167 if (Init->isDelegatingInitializer())
168 return ThisVal;
169
170 const ValueDecl *Field;
171 SVal FieldVal;
172 if (Init->isIndirectMemberInitializer()) {
173 Field = Init->getIndirectMember();
174 FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal);
175 } else {
176 Field = Init->getMember();
177 FieldVal = State->getLValue(Init->getMember(), ThisVal);
178 }
179
180 QualType Ty = Field->getType();
181 return makeElementRegion(State, FieldVal, Ty, CallOpts.IsArrayCtorOrDtor,
182 Idx);
183 }
185 if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
186 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
187 const auto *NE = NECC->getCXXNewExpr();
188 SVal V = *getObjectUnderConstruction(State, NE, LCtx);
189 if (const SubRegion *MR =
190 dyn_cast_or_null<SubRegion>(V.getAsRegion())) {
191 if (NE->isArray()) {
192 CallOpts.IsArrayCtorOrDtor = true;
193
194 auto Ty = NE->getType()->getPointeeType();
195 while (const auto *AT = getContext().getAsArrayType(Ty))
196 Ty = AT->getElementType();
197
198 auto R = MRMgr.getElementRegion(Ty, svalBuilder.makeArrayIndex(Idx),
199 MR, SVB.getContext());
200
201 return loc::MemRegionVal(R);
202 }
203 return V;
204 }
205 // TODO: Detect when the allocator returns a null pointer.
206 // Constructor shall not be called in this case.
207 }
208 break;
209 }
212 // The temporary is to be managed by the parent stack frame.
213 // So build it in the parent stack frame if we're not in the
214 // top frame of the analysis.
215 const StackFrameContext *SFC = LCtx->getStackFrame();
216 if (const LocationContext *CallerLCtx = SFC->getParent()) {
217 auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
218 .getAs<CFGCXXRecordTypedCall>();
219 if (!RTC) {
220 // We were unable to find the correct construction context for the
221 // call in the parent stack frame. This is equivalent to not being
222 // able to find construction context at all.
223 break;
224 }
225 if (isa<BlockInvocationContext>(CallerLCtx)) {
226 // Unwrap block invocation contexts. They're mostly part of
227 // the current stack frame.
228 CallerLCtx = CallerLCtx->getParent();
229 assert(!isa<BlockInvocationContext>(CallerLCtx));
230 }
231
232 unsigned NVCaller = getNumVisited(CallerLCtx, SFC->getCallSiteBlock());
234 cast<Expr>(SFC->getCallSite()), State, NVCaller, CallerLCtx,
235 RTC->getConstructionContext(), CallOpts);
236 } else {
237 // We are on the top frame of the analysis. We do not know where is the
238 // object returned to. Conjure a symbolic region for the return value.
239 // TODO: We probably need a new MemRegion kind to represent the storage
240 // of that SymbolicRegion, so that we could produce a fancy symbol
241 // instead of an anonymous conjured symbol.
242 // TODO: Do we need to track the region to avoid having it dead
243 // too early? It does die too early, at least in C++17, but because
244 // putting anything into a SymbolicRegion causes an immediate escape,
245 // it doesn't cause any leak false positives.
246 const auto *RCC = cast<ReturnedValueConstructionContext>(CC);
247 // Make sure that this doesn't coincide with any other symbol
248 // conjured for the returned expression.
249 static const int TopLevelSymRegionTag = 0;
250 const Expr *RetE = RCC->getReturnStmt()->getRetValue();
251 assert(RetE && "Void returns should not have a construction context");
252 QualType ReturnTy = RetE->getType();
253 QualType RegionTy = ACtx.getPointerType(ReturnTy);
254 return SVB.conjureSymbolVal(&TopLevelSymRegionTag, getCFGElementRef(),
255 SFC, RegionTy, getNumVisitedCurrent());
256 }
257 llvm_unreachable("Unhandled return value construction context!");
258 }
260 assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
262
263 // Support pre-C++17 copy elision. We'll have the elidable copy
264 // constructor in the AST and in the CFG, but we'll skip it
265 // and construct directly into the final object. This call
266 // also sets the CallOpts flags for us.
267 // If the elided copy/move constructor is not supported, there's still
268 // benefit in trying to model the non-elided constructor.
269 // Stash our state before trying to elide, as it'll get overwritten.
270 ProgramStateRef PreElideState = State;
271 EvalCallOptions PreElideCallOpts = CallOpts;
272
274 TCC->getConstructorAfterElision(), State, NumVisitedCaller, LCtx,
275 TCC->getConstructionContextAfterElision(), CallOpts);
276
277 // FIXME: This definition of "copy elision has not failed" is unreliable.
278 // It doesn't indicate that the constructor will actually be inlined
279 // later; this is still up to evalCall() to decide.
281 return V;
282
283 // Copy elision failed. Revert the changes and proceed as if we have
284 // a simple temporary.
285 CallOpts = PreElideCallOpts;
287 [[fallthrough]];
288 }
290 const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
291 const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
292
293 CallOpts.IsTemporaryCtorOrDtor = true;
294 if (MTE) {
295 if (const ValueDecl *VD = MTE->getExtendingDecl()) {
297 assert(SD != SD_FullExpression);
298 if (!VD->getType()->isReferenceType()) {
299 // We're lifetime-extended by a surrounding aggregate.
300 // Automatic destructors aren't quite working in this case
301 // on the CFG side. We should warn the caller about that.
302 // FIXME: Is there a better way to retrieve this information from
303 // the MaterializeTemporaryExpr?
305 }
306
307 if (SD == SD_Static || SD == SD_Thread)
308 return loc::MemRegionVal(
309 MRMgr.getCXXStaticLifetimeExtendedObjectRegion(E, VD));
310
311 return loc::MemRegionVal(
312 MRMgr.getCXXLifetimeExtendedObjectRegion(E, VD, LCtx));
313 }
314 assert(MTE->getStorageDuration() == SD_FullExpression);
315 }
316
317 return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
318 }
320 CallOpts.IsTemporaryCtorOrDtor = true;
321
322 const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
323
325 MRMgr.getCXXTempObjectRegion(LCC->getInitializer(), LCtx));
326
327 const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E);
328 if (getIndexOfElementToConstruct(State, CE, LCtx)) {
329 CallOpts.IsArrayCtorOrDtor = true;
330 Base = State->getLValue(E->getType(), svalBuilder.makeArrayIndex(Idx),
331 Base);
332 }
333
334 return Base;
335 }
337 // Arguments are technically temporaries.
338 CallOpts.IsTemporaryCtorOrDtor = true;
339
340 const auto *ACC = cast<ArgumentConstructionContext>(CC);
341 const Expr *E = ACC->getCallLikeExpr();
342 unsigned Idx = ACC->getIndex();
343
345 auto getArgLoc = [&](CallEventRef<> Caller) -> std::optional<SVal> {
346 const LocationContext *FutureSFC =
347 Caller->getCalleeStackFrame(NumVisitedCaller);
348 // Return early if we are unable to reliably foresee
349 // the future stack frame.
350 if (!FutureSFC)
351 return std::nullopt;
352
353 // This should be equivalent to Caller->getDecl() for now, but
354 // FutureSFC->getDecl() is likely to support better stuff (like
355 // virtual functions) earlier.
356 const Decl *CalleeD = FutureSFC->getDecl();
357
358 // FIXME: Support for variadic arguments is not implemented here yet.
359 if (CallEvent::isVariadic(CalleeD))
360 return std::nullopt;
361
362 // Operator arguments do not correspond to operator parameters
363 // because this-argument is implemented as a normal argument in
364 // operator call expressions but not in operator declarations.
365 const TypedValueRegion *TVR = Caller->getParameterLocation(
366 *Caller->getAdjustedParameterIndex(Idx), NumVisitedCaller);
367 if (!TVR)
368 return std::nullopt;
369
370 return loc::MemRegionVal(TVR);
371 };
372
373 if (const auto *CE = dyn_cast<CallExpr>(E)) {
374 CallEventRef<> Caller =
375 CEMgr.getSimpleCall(CE, State, LCtx, getCFGElementRef());
376 if (std::optional<SVal> V = getArgLoc(Caller))
377 return *V;
378 else
379 break;
380 } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) {
381 // Don't bother figuring out the target region for the future
382 // constructor because we won't need it.
384 CCE, /*Target=*/nullptr, State, LCtx, getCFGElementRef());
385 if (std::optional<SVal> V = getArgLoc(Caller))
386 return *V;
387 else
388 break;
389 } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
390 CallEventRef<> Caller =
391 CEMgr.getObjCMethodCall(ME, State, LCtx, getCFGElementRef());
392 if (std::optional<SVal> V = getArgLoc(Caller))
393 return *V;
394 else
395 break;
396 }
397 }
398 } // switch (CC->getKind())
399 }
400
401 // If we couldn't find an existing region to construct into, assume we're
402 // constructing a temporary. Notify the caller of our failure.
404 return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
405}
406
408 SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
409 const ConstructionContext *CC, const EvalCallOptions &CallOpts) {
411 // Sounds like we failed to find the target region and therefore
412 // copy elision failed. There's nothing we can do about it here.
413 return State;
414 }
415
416 // See if we're constructing an existing region by looking at the
417 // current construction context.
418 assert(CC && "Computed target region without construction context?");
419 switch (CC->getKind()) {
422 const auto *DSCC = cast<VariableConstructionContext>(CC);
423 return addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, V);
424 }
428 const auto *Init = ICC->getCXXCtorInitializer();
429 // Base and delegating initializers handled above
430 assert(Init->isAnyMemberInitializer() &&
431 "Base and delegating initializers should have been handled by"
432 "computeObjectUnderConstruction()");
433 return addObjectUnderConstruction(State, Init, LCtx, V);
434 }
436 return State;
437 }
440 const StackFrameContext *SFC = LCtx->getStackFrame();
441 const LocationContext *CallerLCtx = SFC->getParent();
442 if (!CallerLCtx) {
443 // No extra work is necessary in top frame.
444 return State;
445 }
446
447 auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
448 .getAs<CFGCXXRecordTypedCall>();
449 assert(RTC && "Could not have had a target region without it");
450 if (isa<BlockInvocationContext>(CallerLCtx)) {
451 // Unwrap block invocation contexts. They're mostly part of
452 // the current stack frame.
453 CallerLCtx = CallerLCtx->getParent();
454 assert(!isa<BlockInvocationContext>(CallerLCtx));
455 }
456
458 cast<Expr>(SFC->getCallSite()), State, CallerLCtx,
459 RTC->getConstructionContext(), CallOpts);
460 }
462 assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
466 V, TCC->getConstructorAfterElision(), State, LCtx,
467 TCC->getConstructionContextAfterElision(), CallOpts);
468
469 // Remember that we've elided the constructor.
470 State = addObjectUnderConstruction(
471 State, TCC->getConstructorAfterElision(), LCtx, V);
472
473 // Remember that we've elided the destructor.
474 if (const auto *BTE = TCC->getCXXBindTemporaryExpr())
475 State = elideDestructor(State, BTE, LCtx);
476
477 // Instead of materialization, shamelessly return
478 // the final object destination.
479 if (const auto *MTE = TCC->getMaterializedTemporaryExpr())
480 State = addObjectUnderConstruction(State, MTE, LCtx, V);
481
482 return State;
483 }
484 // If we decided not to elide the constructor, proceed as if
485 // it's a simple temporary.
486 [[fallthrough]];
487 }
489 const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
490 if (const auto *BTE = TCC->getCXXBindTemporaryExpr())
491 State = addObjectUnderConstruction(State, BTE, LCtx, V);
492
493 if (const auto *MTE = TCC->getMaterializedTemporaryExpr())
494 State = addObjectUnderConstruction(State, MTE, LCtx, V);
495
496 return State;
497 }
499 const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
500
501 // If we capture and array, we want to store the super region, not a
502 // sub-region.
503 if (const auto *EL = dyn_cast_or_null<ElementRegion>(V.getAsRegion()))
504 V = loc::MemRegionVal(EL->getSuperRegion());
505
506 return addObjectUnderConstruction(
507 State, {LCC->getLambdaExpr(), LCC->getIndex()}, LCtx, V);
508 }
510 const auto *ACC = cast<ArgumentConstructionContext>(CC);
511 if (const auto *BTE = ACC->getCXXBindTemporaryExpr())
512 State = addObjectUnderConstruction(State, BTE, LCtx, V);
513
514 return addObjectUnderConstruction(
515 State, {ACC->getCallLikeExpr(), ACC->getIndex()}, LCtx, V);
516 }
517 }
518 llvm_unreachable("Unhandled construction context!");
519}
520
521static ProgramStateRef
523 const ArrayInitLoopExpr *AILE,
524 const LocationContext *LCtx, NonLoc Idx) {
526 MemRegionManager &MRMgr = SVB.getRegionManager();
527 ASTContext &Ctx = SVB.getContext();
528
529 // HACK: There is no way we can put the index of the array element into the
530 // CFG unless we unroll the loop, so we manually select and bind the required
531 // parameter to the environment.
532 const Expr *SourceArray = AILE->getCommonExpr()->getSourceExpr();
533 const auto *Ctor =
535
536 const auto *SourceArrayRegion =
537 cast<SubRegion>(State->getSVal(SourceArray, LCtx).getAsRegion());
539 MRMgr.getElementRegion(Ctor->getType(), Idx, SourceArrayRegion, Ctx);
540
541 return State->BindExpr(Ctor->getArg(0), LCtx,
543}
544
545void ExprEngine::handleConstructor(const Expr *E,
546 ExplodedNode *Pred,
547 ExplodedNodeSet &destNodes) {
548 const auto *CE = dyn_cast<CXXConstructExpr>(E);
549 const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(E);
550 assert(CE || CIE);
551
552 const LocationContext *LCtx = Pred->getLocationContext();
553 ProgramStateRef State = Pred->getState();
554
555 SVal Target = UnknownVal();
556
557 if (CE) {
558 if (std::optional<SVal> ElidedTarget =
559 getObjectUnderConstruction(State, CE, LCtx)) {
560 // We've previously modeled an elidable constructor by pretending that
561 // it in fact constructs into the correct target. This constructor can
562 // therefore be skipped.
563 Target = *ElidedTarget;
564 NodeBuilder Bldr(Pred, destNodes, *currBldrCtx);
565 State = finishObjectConstruction(State, CE, LCtx);
566 if (auto L = Target.getAs<Loc>())
567 State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType()));
568 Bldr.generateNode(CE, Pred, State);
569 return;
570 }
571 }
572
573 EvalCallOptions CallOpts;
574 auto C = getCurrentCFGElement().getAs<CFGConstructor>();
575 assert(C || getCurrentCFGElement().getAs<CFGStmt>());
576 const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr;
577
578 const CXXConstructionKind CK =
579 CE ? CE->getConstructionKind() : CIE->getConstructionKind();
580 switch (CK) {
582 // Inherited constructors are always base class constructors.
583 assert(CE && !CIE && "A complete constructor is inherited?!");
584
585 // If the ctor is part of an ArrayInitLoopExpr, we want to handle it
586 // differently.
587 auto *AILE = CC ? CC->getArrayInitLoop() : nullptr;
588
589 unsigned Idx = 0;
590 if (CE->getType()->isArrayType() || AILE) {
591
592 auto isZeroSizeArray = [&] {
593 uint64_t Size = 1;
594
595 if (const auto *CAT = dyn_cast<ConstantArrayType>(CE->getType()))
597 else if (AILE)
599
600 return Size == 0;
601 };
602
603 // No element construction will happen in a 0 size array.
604 if (isZeroSizeArray()) {
605 NodeBuilder Bldr(Pred, destNodes, *currBldrCtx);
606 static SimpleProgramPointTag T{"ExprEngine",
607 "Skipping 0 size array construction"};
608 Bldr.generateNode(CE, Pred, State, &T);
609 return;
610 }
611
612 Idx = getIndexOfElementToConstruct(State, CE, LCtx).value_or(0u);
613 State = setIndexOfElementToConstruct(State, CE, LCtx, Idx + 1);
614 }
615
616 if (AILE) {
617 // Only set this once even though we loop through it multiple times.
618 if (!getPendingInitLoop(State, CE, LCtx))
619 State = setPendingInitLoop(
620 State, CE, LCtx,
621 getContext().getArrayInitLoopExprElementCount(AILE));
622
624 State, AILE, LCtx, svalBuilder.makeArrayIndex(Idx));
625 }
626
627 // The target region is found from construction context.
628 std::tie(State, Target) = handleConstructionContext(
629 CE, State, currBldrCtx, LCtx, CC, CallOpts, Idx);
630 break;
631 }
633 // Make sure we are not calling virtual base class initializers twice.
634 // Only the most-derived object should initialize virtual base classes.
635 const auto *OuterCtor = dyn_cast_or_null<CXXConstructExpr>(
636 LCtx->getStackFrame()->getCallSite());
637 assert(
638 (!OuterCtor ||
639 OuterCtor->getConstructionKind() == CXXConstructionKind::Complete ||
640 OuterCtor->getConstructionKind() == CXXConstructionKind::Delegating) &&
641 ("This virtual base should have already been initialized by "
642 "the most derived class!"));
643 (void)OuterCtor;
644 [[fallthrough]];
645 }
647 // In C++17, classes with non-virtual bases may be aggregates, so they would
648 // be initialized as aggregates without a constructor call, so we may have
649 // a base class constructed directly into an initializer list without
650 // having the derived-class constructor call on the previous stack frame.
651 // Initializer lists may be nested into more initializer lists that
652 // correspond to surrounding aggregate initializations.
653 // FIXME: For now this code essentially bails out. We need to find the
654 // correct target region and set it.
655 // FIXME: Instead of relying on the ParentMap, we should have the
656 // trigger-statement (InitListExpr or CXXParenListInitExpr in this case)
657 // passed down from CFG or otherwise always available during construction.
658 if (isa_and_nonnull<InitListExpr, CXXParenListInitExpr>(
659 LCtx->getParentMap().getParent(E))) {
660 MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
661 Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
663 break;
664 }
665 [[fallthrough]];
667 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
668 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
669 LCtx->getStackFrame());
670 SVal ThisVal = State->getSVal(ThisPtr);
671
673 Target = ThisVal;
674 } else {
675 // Cast to the base type.
676 bool IsVirtual = (CK == CXXConstructionKind::VirtualBase);
677 SVal BaseVal =
678 getStoreManager().evalDerivedToBase(ThisVal, E->getType(), IsVirtual);
679 Target = BaseVal;
680 }
681 break;
682 }
683 }
684
685 if (State != Pred->getState()) {
686 static SimpleProgramPointTag T("ExprEngine",
687 "Prepare for object construction");
688 ExplodedNodeSet DstPrepare;
689 NodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx);
690 Pred =
691 BldrPrepare.generateNode(E, Pred, State, &T, ProgramPoint::PreStmtKind);
692 if (!Pred)
693 return;
694 }
695
696 const MemRegion *TargetRegion = Target.getAsRegion();
697 CallEventManager &CEMgr = getStateManager().getCallEventManager();
698 CallEventRef<> Call =
699 CIE ? (CallEventRef<>)CEMgr.getCXXInheritedConstructorCall(
700 CIE, TargetRegion, State, LCtx, getCFGElementRef())
701 : (CallEventRef<>)CEMgr.getCXXConstructorCall(
702 CE, TargetRegion, State, LCtx, getCFGElementRef());
703
704 ExplodedNodeSet DstPreVisit;
705 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, E, *this);
706
707 ExplodedNodeSet PreInitialized;
708 if (CE) {
709 // FIXME: Is it possible and/or useful to do this before PreStmt?
710 NodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx);
711 for (ExplodedNode *N : DstPreVisit) {
712 ProgramStateRef State = N->getState();
713 if (CE->requiresZeroInitialization()) {
714 // FIXME: Once we properly handle constructors in new-expressions, we'll
715 // need to invalidate the region before setting a default value, to make
716 // sure there aren't any lingering bindings around. This probably needs
717 // to happen regardless of whether or not the object is zero-initialized
718 // to handle random fields of a placement-initialized object picking up
719 // old bindings. We might only want to do it when we need to, though.
720 // FIXME: This isn't actually correct for arrays -- we need to zero-
721 // initialize the entire array, not just the first element -- but our
722 // handling of arrays everywhere else is weak as well, so this shouldn't
723 // actually make things worse. Placement new makes this tricky as well,
724 // since it's then possible to be initializing one part of a multi-
725 // dimensional array.
726 const CXXRecordDecl *TargetHeldRecord =
727 dyn_cast_or_null<CXXRecordDecl>(CE->getType()->getAsRecordDecl());
728
729 if (!TargetHeldRecord || !TargetHeldRecord->isEmpty())
730 State = State->bindDefaultZero(Target, LCtx);
731 }
732
733 Bldr.generateNode(CE, N, State, /*tag=*/nullptr,
735 }
736 } else {
737 PreInitialized = DstPreVisit;
738 }
739
740 ExplodedNodeSet DstPreCall;
741 getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized,
742 *Call, *this);
743
744 ExplodedNodeSet DstEvaluated;
745
746 if (CE && CE->getConstructor()->isTrivial() &&
747 CE->getConstructor()->isCopyOrMoveConstructor() &&
748 !CallOpts.IsArrayCtorOrDtor) {
749 NodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx);
750 // FIXME: Handle other kinds of trivial constructors as well.
751 for (ExplodedNode *N : DstPreCall)
752 performTrivialCopy(Bldr, N, *Call);
753
754 } else {
755 for (ExplodedNode *N : DstPreCall)
756 getCheckerManager().runCheckersForEvalCall(DstEvaluated, N, *Call, *this,
757 CallOpts);
758 }
759
760 // If the CFG was constructed without elements for temporary destructors
761 // and the just-called constructor created a temporary object then
762 // stop exploration if the temporary object has a noreturn constructor.
763 // This can lose coverage because the destructor, if it were present
764 // in the CFG, would be called at the end of the full expression or
765 // later (for life-time extended temporaries) -- but avoids infeasible
766 // paths when no-return temporary destructors are used for assertions.
767 ExplodedNodeSet DstEvaluatedPostProcessed;
768 NodeBuilder Bldr(DstEvaluated, DstEvaluatedPostProcessed, *currBldrCtx);
769 const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext();
771 if (llvm::isa_and_nonnull<CXXTempObjectRegion,
772 CXXLifetimeExtendedObjectRegion>(TargetRegion) &&
774 ->getParent()
775 ->isAnyDestructorNoReturn()) {
776
777 // If we've inlined the constructor, then DstEvaluated would be empty.
778 // In this case we still want a sink, which could be implemented
779 // in processCallExit. But we don't have that implemented at the moment,
780 // so if you hit this assertion, see if you can avoid inlining
781 // the respective constructor when analyzer-config cfg-temporary-dtors
782 // is set to false.
783 // Otherwise there's nothing wrong with inlining such constructor.
784 assert(!DstEvaluated.empty() &&
785 "We should not have inlined this constructor!");
786
787 for (ExplodedNode *N : DstEvaluated) {
788 Bldr.generateSink(E, N, N->getState());
789 }
790
791 // There is no need to run the PostCall and PostStmt checker
792 // callbacks because we just generated sinks on all nodes in th
793 // frontier.
794 return;
795 }
796 }
797
798 ExplodedNodeSet DstPostArgumentCleanup;
799 for (ExplodedNode *I : DstEvaluatedPostProcessed)
800 finishArgumentConstruction(DstPostArgumentCleanup, I, *Call);
801
802 // If there were other constructors called for object-type arguments
803 // of this constructor, clean them up.
804 ExplodedNodeSet DstPostCall;
806 DstPostArgumentCleanup,
807 *Call, *this);
808 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, E, *this);
809}
810
812 ExplodedNode *Pred,
813 ExplodedNodeSet &Dst) {
814 handleConstructor(CE, Pred, Dst);
815}
816
818 const CXXInheritedCtorInitExpr *CE, ExplodedNode *Pred,
819 ExplodedNodeSet &Dst) {
820 handleConstructor(CE, Pred, Dst);
821}
822
824 const MemRegion *Dest,
825 const Stmt *S,
826 bool IsBaseDtor,
827 ExplodedNode *Pred,
828 ExplodedNodeSet &Dst,
829 EvalCallOptions &CallOpts) {
830 assert(S && "A destructor without a trigger!");
831 const LocationContext *LCtx = Pred->getLocationContext();
832 ProgramStateRef State = Pred->getState();
833
834 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
835 assert(RecordDecl && "Only CXXRecordDecls should have destructors");
836 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();
837 // FIXME: There should always be a Decl, otherwise the destructor call
838 // shouldn't have been added to the CFG in the first place.
839 if (!DtorDecl) {
840 // Skip the invalid destructor. We cannot simply return because
841 // it would interrupt the analysis instead.
842 static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor");
843 // FIXME: PostImplicitCall with a null decl may crash elsewhere anyway.
844 PostImplicitCall PP(/*Decl=*/nullptr, S->getEndLoc(), LCtx,
845 getCFGElementRef(), &T);
846 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
847 Bldr.generateNode(PP, Pred->getState(), Pred);
848 return;
849 }
850
851 if (!Dest) {
852 // We're trying to destroy something that is not a region. This may happen
853 // for a variety of reasons (unknown target region, concrete integer instead
854 // of target region, etc.). The current code makes an attempt to recover.
855 // FIXME: We probably don't really need to recover when we're dealing
856 // with concrete integers specifically.
858 if (const Expr *E = dyn_cast_or_null<Expr>(S)) {
859 Dest = MRMgr.getCXXTempObjectRegion(E, Pred->getLocationContext());
860 } else {
861 static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor");
862 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
863 Bldr.generateSink(Pred->getLocation().withTag(&T),
864 Pred->getState(), Pred);
865 return;
866 }
867 }
868
871 DtorDecl, S, Dest, IsBaseDtor, State, LCtx, getCFGElementRef());
872
873 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
874 Call->getSourceRange().getBegin(),
875 "Error evaluating destructor");
876
877 ExplodedNodeSet DstPreCall;
878 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
879 *Call, *this);
880
881 ExplodedNodeSet DstInvalidated;
882 NodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
883 for (ExplodedNode *N : DstPreCall)
884 defaultEvalCall(Bldr, N, *Call, CallOpts);
885
886 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
887 *Call, *this);
888}
889
891 ExplodedNode *Pred,
892 ExplodedNodeSet &Dst) {
893 ProgramStateRef State = Pred->getState();
894 const LocationContext *LCtx = Pred->getLocationContext();
895 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
896 CNE->getBeginLoc(),
897 "Error evaluating New Allocator Call");
900 CEMgr.getCXXAllocatorCall(CNE, State, LCtx, getCFGElementRef());
901
902 ExplodedNodeSet DstPreCall;
903 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
904 *Call, *this);
905
906 ExplodedNodeSet DstPostCall;
907 NodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx);
908 for (ExplodedNode *I : DstPreCall) {
909 // Operator new calls (CXXNewExpr) are intentionally not eval-called,
910 // because it does not make sense to eval-call user-provided functions.
911 // 1) If the new operator can be inlined, then don't prevent it from
912 // inlining by having an eval-call of that operator.
913 // 2) If it can't be inlined, then the default conservative modeling
914 // is what we want anyway.
915 // So the best is to not allow eval-calling CXXNewExprs from checkers.
916 // Checkers can provide their pre/post-call callbacks if needed.
917 defaultEvalCall(CallBldr, I, *Call);
918 }
919 // If the call is inlined, DstPostCall will be empty and we bail out now.
920
921 // Store return value of operator new() for future use, until the actual
922 // CXXNewExpr gets processed.
923 ExplodedNodeSet DstPostValue;
924 NodeBuilder ValueBldr(DstPostCall, DstPostValue, *currBldrCtx);
925 for (ExplodedNode *I : DstPostCall) {
926 // FIXME: Because CNE serves as the "call site" for the allocator (due to
927 // lack of a better expression in the AST), the conjured return value symbol
928 // is going to be of the same type (C++ object pointer type). Technically
929 // this is not correct because the operator new's prototype always says that
930 // it returns a 'void *'. So we should change the type of the symbol,
931 // and then evaluate the cast over the symbolic pointer from 'void *' to
932 // the object pointer type. But without changing the symbol's type it
933 // is breaking too much to evaluate the no-op symbolic cast over it, so we
934 // skip it for now.
935 ProgramStateRef State = I->getState();
936 SVal RetVal = State->getSVal(CNE, LCtx);
937 // [basic.stc.dynamic.allocation] (on the return value of an allocation
938 // function):
939 // "The order, contiguity, and initial value of storage allocated by
940 // successive calls to an allocation function are unspecified."
941 State = State->bindDefaultInitial(RetVal, UndefinedVal{}, LCtx);
942
943 // If this allocation function is not declared as non-throwing, failures
944 // /must/ be signalled by exceptions, and thus the return value will never
945 // be NULL. -fno-exceptions does not influence this semantics.
946 // FIXME: GCC has a -fcheck-new option, which forces it to consider the case
947 // where new can return NULL. If we end up supporting that option, we can
948 // consider adding a check for it here.
949 // C++11 [basic.stc.dynamic.allocation]p3.
950 if (const FunctionDecl *FD = CNE->getOperatorNew()) {
951 QualType Ty = FD->getType();
952 if (const auto *ProtoType = Ty->getAs<FunctionProtoType>())
953 if (!ProtoType->isNothrow())
954 State = State->assume(RetVal.castAs<DefinedOrUnknownSVal>(), true);
955 }
956
957 ValueBldr.generateNode(
958 CNE, I, addObjectUnderConstruction(State, CNE, LCtx, RetVal));
959 }
960
961 ExplodedNodeSet DstPostPostCallCallback;
962 getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback,
963 DstPostValue, *Call, *this);
964 for (ExplodedNode *I : DstPostPostCallCallback) {
966 }
967}
968
970 ExplodedNodeSet &Dst) {
971 // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
972 // Also, we need to decide how allocators actually work -- they're not
973 // really part of the CXXNewExpr because they happen BEFORE the
974 // CXXConstructExpr subexpression. See PR12014 for some discussion.
975
976 unsigned blockCount = getNumVisitedCurrent();
977 const LocationContext *LCtx = Pred->getLocationContext();
978 SVal symVal = UnknownVal();
979 FunctionDecl *FD = CNE->getOperatorNew();
980
981 bool IsStandardGlobalOpNewFunction =
983
984 ProgramStateRef State = Pred->getState();
985
986 // Retrieve the stored operator new() return value.
987 if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
988 symVal = *getObjectUnderConstruction(State, CNE, LCtx);
989 State = finishObjectConstruction(State, CNE, LCtx);
990 }
991
992 // We assume all standard global 'operator new' functions allocate memory in
993 // heap. We realize this is an approximation that might not correctly model
994 // a custom global allocator.
995 if (symVal.isUnknown()) {
996 if (IsStandardGlobalOpNewFunction)
997 symVal = svalBuilder.getConjuredHeapSymbolVal(getCFGElementRef(), LCtx,
998 CNE->getType(), blockCount);
999 else
1000 symVal = svalBuilder.conjureSymbolVal(
1001 /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, blockCount);
1002 }
1003
1006 CEMgr.getCXXAllocatorCall(CNE, State, LCtx, getCFGElementRef());
1007
1008 if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
1009 // Invalidate placement args.
1010 // FIXME: Once we figure out how we want allocators to work,
1011 // we should be using the usual pre-/(default-)eval-/post-call checkers
1012 // here.
1013 State = Call->invalidateRegions(blockCount, State);
1014 if (!State)
1015 return;
1016
1017 // If this allocation function is not declared as non-throwing, failures
1018 // /must/ be signalled by exceptions, and thus the return value will never
1019 // be NULL. -fno-exceptions does not influence this semantics.
1020 // FIXME: GCC has a -fcheck-new option, which forces it to consider the case
1021 // where new can return NULL. If we end up supporting that option, we can
1022 // consider adding a check for it here.
1023 // C++11 [basic.stc.dynamic.allocation]p3.
1024 if (const auto *ProtoType = FD->getType()->getAs<FunctionProtoType>())
1025 if (!ProtoType->isNothrow())
1026 if (auto dSymVal = symVal.getAs<DefinedOrUnknownSVal>())
1027 State = State->assume(*dSymVal, true);
1028 }
1029
1030 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1031
1032 SVal Result = symVal;
1033
1034 if (CNE->isArray()) {
1035
1036 if (const auto *NewReg = cast_or_null<SubRegion>(symVal.getAsRegion())) {
1037 // If each element is initialized by their default constructor, the field
1038 // values are properly placed inside the required region, however if an
1039 // initializer list is used, this doesn't happen automatically.
1040 auto *Init = CNE->getInitializer();
1041 bool isInitList =
1042 isa_and_nonnull<InitListExpr, CXXParenListInitExpr>(Init);
1043
1044 QualType ObjTy =
1045 isInitList ? Init->getType() : CNE->getType()->getPointeeType();
1046 const ElementRegion *EleReg =
1047 MRMgr.getElementRegion(ObjTy, svalBuilder.makeArrayIndex(0), NewReg,
1048 svalBuilder.getContext());
1049 Result = loc::MemRegionVal(EleReg);
1050
1051 // If the array is list initialized, we bind the initializer list to the
1052 // memory region here, otherwise we would lose it.
1053 if (isInitList) {
1054 Bldr.takeNodes(Pred);
1055 Pred = Bldr.generateNode(CNE, Pred, State);
1056
1057 SVal V = State->getSVal(Init, LCtx);
1058 ExplodedNodeSet evaluated;
1059 evalBind(evaluated, CNE, Pred, Result, V, true);
1060
1061 Bldr.takeNodes(Pred);
1062 Bldr.addNodes(evaluated);
1063
1064 Pred = *evaluated.begin();
1065 State = Pred->getState();
1066 }
1067 }
1068
1069 State = State->BindExpr(CNE, Pred->getLocationContext(), Result);
1070 Bldr.generateNode(CNE, Pred, State);
1071 return;
1072 }
1073
1074 // FIXME: Once we have proper support for CXXConstructExprs inside
1075 // CXXNewExpr, we need to make sure that the constructed object is not
1076 // immediately invalidated here. (The placement call should happen before
1077 // the constructor call anyway.)
1079 // Non-array placement new should always return the placement location.
1080 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
1081 Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(),
1082 CNE->getPlacementArg(0)->getType());
1083 }
1084
1085 // Bind the address of the object, then check to see if we cached out.
1086 State = State->BindExpr(CNE, LCtx, Result);
1087 ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State);
1088 if (!NewN)
1089 return;
1090
1091 // If the type is not a record, we won't have a CXXConstructExpr as an
1092 // initializer. Copy the value over.
1093 if (const Expr *Init = CNE->getInitializer()) {
1095 assert(Bldr.getResults().size() == 1);
1096 Bldr.takeNodes(NewN);
1097 evalBind(Dst, CNE, NewN, Result, State->getSVal(Init, LCtx),
1098 /*FirstInit=*/IsStandardGlobalOpNewFunction);
1099 }
1100 }
1101}
1102
1104 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
1105
1108 CDE, Pred->getState(), Pred->getLocationContext(), getCFGElementRef());
1109
1110 ExplodedNodeSet DstPreCall;
1111 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, *Call, *this);
1112 ExplodedNodeSet DstPostCall;
1113
1114 if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
1115 NodeBuilder Bldr(DstPreCall, DstPostCall, *currBldrCtx);
1116 for (ExplodedNode *I : DstPreCall) {
1117 // Intentionally either inline or conservative eval-call the operator
1118 // delete, but avoid triggering an eval-call event for checkers.
1119 // As detailed at handling CXXNewExprs, in short, because it does not
1120 // really make sense to eval-call user-provided functions.
1121 defaultEvalCall(Bldr, I, *Call);
1122 }
1123 } else {
1124 DstPostCall = std::move(DstPreCall);
1125 }
1126 getCheckerManager().runCheckersForPostCall(Dst, DstPostCall, *Call, *this);
1127}
1128
1130 ExplodedNodeSet &Dst) {
1131 const VarDecl *VD = CS->getExceptionDecl();
1132 if (!VD) {
1133 Dst.insert(Pred);
1134 return;
1135 }
1136
1137 const LocationContext *LCtx = Pred->getLocationContext();
1138 SVal V = svalBuilder.conjureSymbolVal(getCFGElementRef(), LCtx, VD->getType(),
1140 ProgramStateRef state = Pred->getState();
1141 state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx);
1142
1143 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1144 Bldr.generateNode(CS, Pred, state);
1145}
1146
1148 ExplodedNodeSet &Dst) {
1149 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1150
1151 // Get the this object region from StoreManager.
1152 const LocationContext *LCtx = Pred->getLocationContext();
1153 const MemRegion *R =
1154 svalBuilder.getRegionManager().getCXXThisRegion(
1155 getContext().getCanonicalType(TE->getType()),
1156 LCtx);
1157
1158 ProgramStateRef state = Pred->getState();
1159 SVal V = state->getSVal(loc::MemRegionVal(R));
1160 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
1161}
1162
1164 ExplodedNodeSet &Dst) {
1165 const LocationContext *LocCtxt = Pred->getLocationContext();
1166
1167 // Get the region of the lambda itself.
1168 const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(
1169 LE, LocCtxt);
1171
1172 ProgramStateRef State = Pred->getState();
1173
1174 // If we created a new MemRegion for the lambda, we should explicitly bind
1175 // the captures.
1176 for (auto const [Idx, FieldForCapture, InitExpr] :
1177 llvm::zip(llvm::seq<unsigned>(0, -1), LE->getLambdaClass()->fields(),
1178 LE->capture_inits())) {
1179 SVal FieldLoc = State->getLValue(FieldForCapture, V);
1180
1181 SVal InitVal;
1182 if (!FieldForCapture->hasCapturedVLAType()) {
1183 assert(InitExpr && "Capture missing initialization expression");
1184
1185 // Capturing a 0 length array is a no-op, so we ignore it to get a more
1186 // accurate analysis. If it's not ignored, it would set the default
1187 // binding of the lambda to 'Unknown', which can lead to falsely detecting
1188 // 'Uninitialized' values as 'Unknown' and not reporting a warning.
1189 const auto FTy = FieldForCapture->getType();
1190 if (FTy->isConstantArrayType() &&
1191 getContext().getConstantArrayElementCount(
1192 getContext().getAsConstantArrayType(FTy)) == 0)
1193 continue;
1194
1195 // With C++17 copy elision the InitExpr can be anything, so instead of
1196 // pattern matching all cases, we simple check if the current field is
1197 // under construction or not, regardless what it's InitExpr is.
1198 if (const auto OUC =
1199 getObjectUnderConstruction(State, {LE, Idx}, LocCtxt)) {
1200 InitVal = State->getSVal(OUC->getAsRegion());
1201
1202 State = finishObjectConstruction(State, {LE, Idx}, LocCtxt);
1203 } else
1204 InitVal = State->getSVal(InitExpr, LocCtxt);
1205
1206 } else {
1207
1208 assert(!getObjectUnderConstruction(State, {LE, Idx}, LocCtxt) &&
1209 "VLA capture by value is a compile time error!");
1210
1211 // The field stores the length of a captured variable-length array.
1212 // These captures don't have initialization expressions; instead we
1213 // get the length from the VLAType size expression.
1214 Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr();
1215 InitVal = State->getSVal(SizeExpr, LocCtxt);
1216 }
1217
1218 State = State->bindLoc(FieldLoc, InitVal, LocCtxt);
1219 }
1220
1221 // Decay the Loc into an RValue, because there might be a
1222 // MaterializeTemporaryExpr node above this one which expects the bound value
1223 // to be an RValue.
1224 SVal LambdaRVal = State->getSVal(R);
1225
1226 ExplodedNodeSet Tmp;
1227 NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
1228 // FIXME: is this the right program point kind?
1229 Bldr.generateNode(LE, Pred,
1230 State->BindExpr(LE, LocCtxt, LambdaRVal),
1232
1233 // FIXME: Move all post/pre visits to ::Visit().
1234 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this);
1235}
1236
1238 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
1239 ExplodedNodeSet CheckerPreStmt;
1240 getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);
1241
1242 ExplodedNodeSet EvalSet;
1243 NodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
1244
1245 for (const auto *Attr : getSpecificAttrs<CXXAssumeAttr>(A->getAttrs())) {
1246 for (ExplodedNode *N : CheckerPreStmt) {
1247 Visit(Attr->getAssumption()->IgnoreParens(), N, EvalSet);
1248 }
1249 }
1250
1251 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
1252}
Defines the clang::ASTContext interface.
#define V(N, I)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static ProgramStateRef bindRequiredArrayElementToEnvironment(ProgramStateRef State, const ArrayInitLoopExpr *AILE, const LocationContext *LCtx, NonLoc Idx)
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
uint64_t getArrayInitLoopExprElementCount(const ArrayInitLoopExpr *AILE) const
Return number of elements initialized in an ArrayInitLoopExpr.
CFG::BuildOptions & getCFGBuildOptions()
Represents a loop initializing the elements of an array.
Definition Expr.h:5971
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition Expr.h:5986
Attr - This represents one attribute.
Definition Attr.h:46
Represents an attribute applied to a statement.
Definition Stmt.h:2204
ArrayRef< const Attr * > getAttrs() const
Definition Stmt.h:2236
Represents a function call that returns a C++ object by value.
Definition CFG.h:187
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Definition CFG.h:110
CXXCatchStmt - This represents a C++ catch block.
Definition StmtCXX.h:28
VarDecl * getExceptionDecl() const
Definition StmtCXX.h:49
Represents a call to a C++ constructor.
Definition ExprCXX.h:1549
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2627
Represents a C++ destructor within a class.
Definition DeclCXX.h:2876
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1752
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2356
bool isArray() const
Definition ExprCXX.h:2465
Expr * getPlacementArg(unsigned I)
Definition ExprCXX.h:2504
SourceLocation getBeginLoc() const
Definition ExprCXX.h:2607
FunctionDecl * getOperatorNew() const
Definition ExprCXX.h:2460
Expr * getInitializer()
The initializer of this new-expression.
Definition ExprCXX.h:2534
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Definition DeclCXX.h:1186
Represents the this expression in C++.
Definition ExprCXX.h:1155
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2946
ConstructionContext's subclasses describe different ways of constructing an object in C++.
virtual const ArrayInitLoopExpr * getArrayInitLoop() const
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
This represents one expression.
Definition Expr.h:112
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3086
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2015
bool isReplaceableGlobalAllocationFunction(UnsignedOrNone *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const
Determines whether this function is one of the replaceable global allocation functions: void *operato...
Definition Decl.h:2609
bool isReservedGlobalPlacementOperator() const
Determines whether this operator new or delete is one of the reserved global placement operators: voi...
Definition Decl.cpp:3404
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5357
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Definition ExprCXX.h:1969
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
const ParentMap & getParentMap() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const LocationContext * getParent() const
It might return null.
const StackFrameContext * getStackFrame() const
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4921
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4946
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4938
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition ExprCXX.h:4971
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1231
Stmt * getParent(Stmt *) const
Represents a program point just after an implicit call event.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
ProgramPoint withTag(const ProgramPointTag *tag) const
Create a new ProgramPoint object that is the same as the original except for using the specified tag ...
A (possibly-)qualified type.
Definition TypeBase.h:937
Represents a struct/union/class.
Definition Decl.h:4342
It represents a stack frame of the call stack (based on CallEvent).
const Stmt * getCallSite() const
const CFGBlock * getCallSiteBlock() const
Stmt - This represents one statement.
Definition Stmt.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:754
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9261
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
Represents a call to a C++ constructor.
Definition CallEvent.h:997
Manages the lifetime of CallEvent objects.
Definition CallEvent.h:1374
CallEventRef< CXXDestructorCall > getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, const MemRegion *Target, bool IsBase, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)
Definition CallEvent.h:1467
CallEventRef< CXXDeallocatorCall > getCXXDeallocatorCall(const CXXDeleteExpr *E, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)
Definition CallEvent.h:1483
CallEventRef getSimpleCall(const CallExpr *E, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)
CallEventRef< ObjCMethodCall > getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)
Definition CallEvent.h:1445
CallEventRef< CXXAllocatorCall > getCXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)
Definition CallEvent.h:1476
CallEventRef< CXXConstructorCall > getCXXConstructorCall(const CXXConstructExpr *E, const MemRegion *Target, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)
Definition CallEvent.h:1452
CallEventRef< CXXInheritedConstructorCall > getCXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *E, const MemRegion *Target, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)
Definition CallEvent.h:1459
Represents an abstract call to a function or method along a particular path.
Definition CallEvent.h:153
static bool isVariadic(const Decl *D)
Returns true if the given decl is known to be variadic.
void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng)
Run checkers for pre-visiting function calls (including methods, constructors, destructors etc.
void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng, const EvalCallOptions &CallOpts)
Run checkers for evaluating a call.
void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting Stmts.
void runCheckersForNewAllocator(const CXXAllocatorCall &Call, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, bool wasInlined=false)
Run checkers between C++ operator new and constructor calls.
void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)
Run checkers for pre-visiting Stmts.
void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting function calls (including methods, constructors, destructors etc.
ElementRegion is used to represent both array elements and casts.
Definition MemRegion.h:1227
ExplodedNodeSet is a set of ExplodedNode * elements with the invariant that its elements cannot be nu...
void insert(ExplodedNode *N)
const ProgramStateRef & getState() const
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
const LocationContext * getLocationContext() const
ProgramStateManager & getStateManager()
Definition ExprEngine.h:481
std::pair< ProgramStateRef, SVal > handleConstructionContext(const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx, const LocationContext *LCtx, const ConstructionContext *CC, EvalCallOptions &CallOpts, unsigned Idx=0)
A convenient wrapper around computeObjectUnderConstruction and updateObjectsUnderConstruction.
Definition ExprEngine.h:820
void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst, EvalCallOptions &Options)
void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitLambdaExpr - Transfer function logic for LambdaExprs.
static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const LocationContext *LC)
By looking at a certain item that may be potentially part of an object's ConstructionContext,...
CFGElement getCurrentCFGElement()
Return the CFG element corresponding to the worklist element that is currently being processed by Exp...
Definition ExprEngine.h:771
unsigned getNumVisited(const LocationContext *LC, const CFGBlock *Block) const
Definition ExprEngine.h:297
SVal computeObjectUnderConstruction(const Expr *E, ProgramStateRef State, unsigned NumVisitedCaller, const LocationContext *LCtx, const ConstructionContext *CC, EvalCallOptions &CallOpts, unsigned Idx=0)
Find location of the object that is being constructed by a given constructor.
static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives which element is being constructed in a non-POD type array.
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
Definition ExprEngine.h:216
StoreManager & getStoreManager()
Definition ExprEngine.h:484
void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Create a C++ temporary object for an rvalue.
ConstCFGElementRef getCFGElementRef() const
Definition ExprEngine.h:293
CheckerManager & getCheckerManager() const
Definition ExprEngine.h:225
ProgramStateRef bindReturnValue(const CallEvent &Call, const LocationContext *LCtx, ProgramStateRef State)
Create a new state in which the call return value is binded to the call origin expression.
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
unsigned getNumVisitedCurrent() const
Definition ExprEngine.h:303
void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Visit - Transfer function logic for all statements.
void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, const CallEvent &Call, const EvalCallOptions &CallOpts={})
Default implementation of call evaluation.
void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
SValBuilder & getSValBuilder()
Definition ExprEngine.h:229
ProgramStateRef updateObjectsUnderConstruction(SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx, const ConstructionContext *CC, const EvalCallOptions &CallOpts)
Update the program state with all the path-sensitive information that's necessary to perform construc...
void VisitAttributedStmt(const AttributedStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAttributedStmt - Transfer function logic for AttributedStmt.
static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives the size of the array in the pending ArrayInitLoopExpr.
const ElementRegion * getElementRegion(QualType elementType, NonLoc Idx, const SubRegion *superRegion, const ASTContext &Ctx)
getElementRegion - Retrieve the memory region associated with the associated element type,...
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:98
This is the simplest builder which generates nodes in the ExplodedGraph.
Definition CoreEngine.h:245
void takeNodes(const ExplodedNodeSet &S)
Definition CoreEngine.h:310
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false)
Generates a node in the ExplodedGraph.
ExplodedNode * generateSink(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a sink in the ExplodedGraph.
Definition CoreEngine.h:280
void addNodes(const ExplodedNodeSet &S)
Definition CoreEngine.h:316
const ExplodedNodeSet & getResults() const
Definition CoreEngine.h:306
CallEventManager & getCallEventManager()
MemRegionManager & getRegionManager()
ProgramStateManager & getStateManager()
NonLoc makeArrayIndex(uint64_t idx)
ASTContext & getContext()
loc::MemRegionVal makeLoc(SymbolRef sym)
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the 'this' object reference.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:56
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition SVals.h:87
const MemRegion * getAsRegion() const
Definition SVals.cpp:119
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition SVals.h:83
bool isUnknown() const
Definition SVals.h:105
SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)
Evaluates a chain of derived-to-base casts through the path specified in Cast.
Definition Store.cpp:254
SubRegion - A region that subsets another larger region.
Definition MemRegion.h:474
TypedValueRegion - An abstract class representing regions having a typed value.
Definition MemRegion.h:563
Definition ARM.cpp:1102
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CXXConstructionKind
Definition ExprCXX.h:1541
StorageDuration
The storage duration for an object (per C++ [basic.stc]).
Definition Specifiers.h:339
@ SD_Thread
Thread storage duration.
Definition Specifiers.h:342
@ SD_Static
Static storage duration.
Definition Specifiers.h:343
@ SD_FullExpression
Full-expression storage duration (for temporaries).
Definition Specifiers.h:340
@ Result
The result type of a method or function.
Definition TypeBase.h:905
auto getSpecificAttrs(const Container &container)
U cast(CodeGen::Address addr)
Definition Address.h:327
Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)
Definition CFG.cpp:1460
unsigned long uint64_t
Hints for figuring out of a call should be inlined during evalCall().
Definition ExprEngine.h:95
bool IsTemporaryLifetimeExtendedViaAggregate
This call is a constructor for a temporary that is lifetime-extended by binding it to a reference-typ...
Definition ExprEngine.h:110
bool IsTemporaryCtorOrDtor
This call is a constructor or a destructor of a temporary value.
Definition ExprEngine.h:105
bool IsArrayCtorOrDtor
This call is a constructor or a destructor for a single element within an array, a part of array cons...
Definition ExprEngine.h:102
bool IsElidableCtorThatHasNotBeenElided
This call is a pre-C++17 elidable constructor that we failed to elide because we failed to compute th...
Definition ExprEngine.h:117
bool IsCtorOrDtorWithImproperlyModeledTargetRegion
This call is a constructor or a destructor for which we do not currently compute the this-region corr...
Definition ExprEngine.h:98