clang 24.0.0git
ExprEngineCallAndReturn.cpp
Go to the documentation of this file.
1//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- 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 ExprEngine's support for calls and returns.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclCXX.h"
23#include "llvm/Support/Casting.h"
24#include "llvm/Support/Compiler.h"
25#include "llvm/Support/SaveAndRestore.h"
26#include <optional>
27
28using namespace clang;
29using namespace ento;
30
31#define DEBUG_TYPE "ExprEngine"
32
34 NumOfDynamicDispatchPathSplits,
35 "The # of times we split the path due to imprecise dynamic dispatch info");
36
37STAT_COUNTER(NumInlinedCalls, "The # of times we inlined a call");
38
39STAT_COUNTER(NumReachedInlineCountMax,
40 "The # of times we reached inline count maximum");
41
43 // Get the entry block in the CFG of the callee.
44 const CFGBlock *Entry = CE.getEntry();
45
46 // Validate the CFG.
47 assert(Entry->empty());
48 assert(Entry->succ_size() == 1);
49
50 // Get the solitary successor.
51 const CFGBlock *Succ = *(Entry->succ_begin());
52
53 // Construct an edge representing the starting location in the callee.
54 BlockEdge Loc(Entry, Succ, CE.getCalleeStackFrame());
55
56 // Construct a new node, notify checkers that analysis of the function has
57 // begun, and add the resultant nodes to the worklist.
58 ExplodedNode *Node = Engine.makeNode(Loc, Pred->getState(), Pred);
59 if (Node) {
60 // FIXME: In the `processBeginOfFunction` callback
61 // `ExprEngine::getCurrStackFrame()` can be different from the
62 // `StackFrame` queried from e.g. the `ExplodedNode`s. I'm not
63 // touching this now because this commit is NFC; but in the future it would
64 // be nice to avoid this inconsistency.
65 ExplodedNodeSet DstBegin;
66 processBeginOfFunction(Node, DstBegin, Loc);
67 Engine.enqueue(DstBegin);
68 }
69}
70
71// Find the last statement on the path to the exploded node and the
72// corresponding Block.
73static std::pair<const Stmt*,
74 const CFGBlock*> getLastStmt(const ExplodedNode *Node) {
75 const Stmt *S = nullptr;
76 const CFGBlock *Blk = nullptr;
77 const StackFrame *SF = Node->getStackFrame();
78
79 // Back up through the ExplodedGraph until we reach a statement node in this
80 // stack frame.
81 while (Node) {
82 const ProgramPoint &PP = Node->getLocation();
83
84 if (PP.getStackFrame() == SF) {
85 if (std::optional<StmtPoint> SP = PP.getAs<StmtPoint>()) {
86 S = SP->getStmt();
87 break;
88 } else if (std::optional<CallExitEnd> CEE = PP.getAs<CallExitEnd>()) {
89 S = CEE->getCalleeStackFrame()->getCallSite();
90 if (S)
91 break;
92
93 // If there is no statement, this is an implicitly-generated call.
94 // We'll walk backwards over it and then continue the loop to find
95 // an actual statement.
96 std::optional<CallEnter> CE;
97 do {
98 Node = Node->getFirstPred();
99 CE = Node->getLocationAs<CallEnter>();
100 } while (!CE ||
101 CE->getCalleeStackFrame() != CEE->getCalleeStackFrame());
102
103 // Continue searching the graph.
104 } else if (std::optional<BlockEdge> BE = PP.getAs<BlockEdge>()) {
105 Blk = BE->getSrc();
106 }
107 } else if (std::optional<CallEnter> CE = PP.getAs<CallEnter>()) {
108 // If we reached the CallEnter for this function, it has no statements.
109 if (CE->getCalleeStackFrame() == SF)
110 break;
111 }
112
113 if (Node->pred_empty())
114 return std::make_pair(nullptr, nullptr);
115
116 Node = *Node->pred_begin();
117 }
118
119 return std::make_pair(S, Blk);
120}
121
122/// Adjusts a return value when the called function's return type does not
123/// match the caller's expression type. This can happen when a dynamic call
124/// is devirtualized, and the overriding method has a covariant (more specific)
125/// return type than the parent's method. For C++ objects, this means we need
126/// to add base casts.
127static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy,
128 StoreManager &StoreMgr) {
129 // For now, the only adjustments we handle apply only to locations.
130 if (!isa<Loc>(V))
131 return V;
132
133 // If the types already match, don't do any unnecessary work.
134 ExpectedTy = ExpectedTy.getCanonicalType();
135 ActualTy = ActualTy.getCanonicalType();
136 if (ExpectedTy == ActualTy)
137 return V;
138
139 // No adjustment is needed between Objective-C pointer types.
140 if (ExpectedTy->isObjCObjectPointerType() &&
141 ActualTy->isObjCObjectPointerType())
142 return V;
143
144 // C++ object pointers may need "derived-to-base" casts.
146 const CXXRecordDecl *ActualClass = ActualTy->getPointeeCXXRecordDecl();
147 if (ExpectedClass && ActualClass) {
148 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
149 /*DetectVirtual=*/false);
150 if (ActualClass->isDerivedFrom(ExpectedClass, Paths) &&
151 !Paths.isAmbiguous(ActualTy->getCanonicalTypeUnqualified())) {
152 return StoreMgr.evalDerivedToBase(V, Paths.front());
153 }
154 }
155
156 // Unfortunately, Objective-C does not enforce that overridden methods have
157 // covariant return types, so we can't assert that that never happens.
158 // Be safe and return UnknownVal().
159 return UnknownVal();
160}
161
163 ExplodedNodeSet &Dst) {
164 // Find the last statement in the function and the corresponding basic block.
165 const Stmt *LastSt = nullptr;
166 const CFGBlock *Blk = nullptr;
167 std::tie(LastSt, Blk) = getLastStmt(Pred);
168 if (!Blk || !LastSt) {
169 Dst.insert(Pred);
170 return;
171 }
172
173 // Here, we destroy the current stack frame. We use the current function's
174 // entire body as a diagnostic statement, with which the program point
175 // will be associated. However, we only want to use LastStmt as a reference
176 // for what to clean up if it's a ReturnStmt; otherwise, everything is dead.
177 const StackFrame *SF = Pred->getStackFrame();
178 removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt), SF,
181}
182
184 const StackFrame *calleeCtx) {
185 const Decl *RuntimeCallee = calleeCtx->getDecl();
186 const Decl *StaticDecl = Call->getDecl();
187 assert(RuntimeCallee);
188 if (!StaticDecl)
189 return true;
190 return RuntimeCallee->getCanonicalDecl() != StaticDecl->getCanonicalDecl();
191}
192
193// Returns the number of elements in the array currently being destructed.
194// If the element count is not found 0 will be returned.
196 const CallEvent &Call, const ProgramStateRef State, SValBuilder &SVB) {
198 "The call event is not a destructor call!");
199
200 const auto &DtorCall = cast<CXXDestructorCall>(Call);
201
202 auto ThisVal = DtorCall.getCXXThisVal();
203
204 if (auto ThisElementRegion = dyn_cast<ElementRegion>(ThisVal.getAsRegion())) {
205 auto ArrayRegion = ThisElementRegion->getAsArrayOffset().getRegion();
206 auto ElementType = ThisElementRegion->getElementType();
207
208 auto ElementCount =
209 getDynamicElementCount(State, ArrayRegion, SVB, ElementType);
210
211 if (!ElementCount.isConstant())
212 return 0;
213
214 return ElementCount.getAsInteger()->getLimitedValue();
215 }
216
217 return 0;
218}
219
220ProgramStateRef ExprEngine::removeStateTraitsUsedForArrayEvaluation(
221 ProgramStateRef State, const CXXConstructExpr *E, const StackFrame *SF) {
222
223 assert(SF && "Stack frame must be provided!");
224
225 if (E) {
226 if (getPendingInitLoop(State, E, SF))
227 State = removePendingInitLoop(State, E, SF);
228
229 if (getIndexOfElementToConstruct(State, E, SF))
230 State = removeIndexOfElementToConstruct(State, E, SF);
231 }
232
233 if (getPendingArrayDestruction(State, SF))
234 State = removePendingArrayDestruction(State, SF);
235
236 return State;
237}
238
239/// The call exit is simulated with a sequence of nodes, which occur between
240/// CallExitBegin and CallExitEnd. The following operations occur between the
241/// two program points:
242/// 1. CallExitBegin (triggers the start of call exit sequence)
243/// 2. Bind the return value
244/// 3. Run Remove dead bindings to clean up the dead symbols from the callee.
245/// 4. CallExitEnd
246/// 5. PostStmt<CallExpr>
247/// Steps 1-3. happen in the callee stack frame; but there is a stack frame
248/// switch and steps 4-5. happen in the caller stack frame.
250 // Step 1 CEBNode was generated before the call.
251 const StackFrame *CalleeSF = CEBNode->getStackFrame();
252
253 const StackFrame *CallerSF = CalleeSF->getParent();
254
255 const Expr *CE = CalleeSF->getCallSite();
256 ProgramStateRef State = CEBNode->getState();
257 // Find the last statement in the function and the corresponding basic block.
258 auto [LastSt, Blk] = getLastStmt(CEBNode);
259
260 const CFGBlock *PrePurgeBlock =
261 isa_and_nonnull<ReturnStmt>(LastSt) ? Blk : &CEBNode->getCFG().getExit();
262 // The first half of this process happens in the callee stack frame:
263 setCurrStackFrameAndBlock(CalleeSF, PrePurgeBlock);
264
265 // Generate a CallEvent /before/ cleaning the State, so that we can get the
266 // correct value for 'this' (if necessary).
268 CallEventRef<> Call = CEMgr.getCaller(CalleeSF, State);
269
270 // Step 2: generate node with bound return value: CEBNode -> BoundRetNode.
271
272 // If this variable is set to 'true' the analyzer will evaluate the call
273 // statement we are about to exit again, instead of continuing the execution
274 // from the statement after the call. This is useful for non-POD type array
275 // construction where the CXXConstructExpr is referenced only once in the CFG,
276 // but we want to evaluate it as many times as many elements the array has.
277 bool ShouldRepeatCall = false;
278
279 if (const auto *DtorDecl =
280 dyn_cast_or_null<CXXDestructorDecl>(Call->getDecl())) {
281 if (auto Idx = getPendingArrayDestruction(State, CallerSF)) {
282 ShouldRepeatCall = *Idx > 0;
283
284 auto ThisVal = svalBuilder.getCXXThis(DtorDecl->getParent(), CalleeSF);
285 State = State->killBinding(ThisVal);
286 }
287 }
288
289 // If the callee returns an expression, bind its value to CallExpr.
290 if (CE) {
291 if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
292 const StackFrame *SF = CEBNode->getStackFrame();
293
294 SVal V = UndefinedVal();
295 if (RS->getRetValue())
296 V = State->getSVal(RS->getRetValue(), SF);
297
298 // Ensure that the return type matches the type of the returned Expr.
299 if (wasDifferentDeclUsedForInlining(Call, CalleeSF)) {
300 QualType ReturnedTy =
302 if (!ReturnedTy.isNull()) {
303 V = adjustReturnValue(V, CE->getType(), ReturnedTy,
305 }
306 }
307
308 State = State->BindExpr(CE, CallerSF, V);
309 }
310
311 // Bind the constructed object value to CXXConstructExpr.
312 if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
314 svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), CalleeSF);
315 SVal ThisV = State->getSVal(This);
316 ThisV = State->getSVal(ThisV.castAs<Loc>());
317 State = State->BindExpr(CCE, CallerSF, ThisV);
318
319 ShouldRepeatCall = shouldRepeatCtorCall(State, CCE, CallerSF);
320 }
321
322 if (const auto *CNE = dyn_cast<CXXNewExpr>(CE)) {
323 // We are currently evaluating a CXXNewAllocator CFGElement. It takes a
324 // while to reach the actual CXXNewExpr element from here, so keep the
325 // region for later use.
326 // Additionally cast the return value of the inlined operator new
327 // (which is of type 'void *') to the correct object type.
328 SVal AllocV = State->getSVal(CNE, CallerSF);
329 AllocV = svalBuilder.evalCast(
330 AllocV, CNE->getType(),
331 getContext().getPointerType(getContext().VoidTy));
332
333 State =
334 addObjectUnderConstruction(State, CNE, CalleeSF->getParent(), AllocV);
335 }
336 }
337
338 if (!ShouldRepeatCall) {
339 State = removeStateTraitsUsedForArrayEvaluation(
340 State, dyn_cast_or_null<CXXConstructExpr>(CE), CallerSF);
341 }
342
343 // Step 3: BoundRetNode -> CleanedNodes
344 // If we can find a statement and a block in the inlined function, run remove
345 // dead bindings before returning from the call. This is important to ensure
346 // that we report the issues such as leaks in the stack frames in which
347 // they occurred.
348 ExplodedNodeSet CleanedNodes;
349 if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
350 static SimpleProgramPointTag RetValBind("ExprEngine", "Bind Return Value");
351 auto Loc = isa<ReturnStmt>(LastSt)
352 ? ProgramPoint{PostStmt(LastSt, CalleeSF, &RetValBind)}
353 : ProgramPoint{EpsilonPoint(CalleeSF, /*Data1=*/nullptr,
354 /*Data2=*/nullptr, &RetValBind)};
355
356 ExplodedNode *BoundRetNode = Engine.makeNode(Loc, State, CEBNode);
357 if (!BoundRetNode)
358 return;
359
360 // We call removeDead in the stack frame of the callee.
361 removeDead(BoundRetNode, CleanedNodes, /*ReferenceStmt=*/nullptr, CalleeSF,
362 /*DiagnosticStmt=*/CalleeSF->getAnalysisDeclContext()->getBody(),
364 } else {
365 CleanedNodes.insert(CEBNode);
366 }
367
368 // The second half of this process happens in the caller stack frame. This is
369 // an exception to the general rule that the current StackFrame and Block
370 // stay the same within a single call to dispatchWorkItem.
372 setCurrStackFrameAndBlock(CallerSF, CalleeSF->getCallSiteBlock());
373 SaveAndRestore CBISave(currStmtIdx, CalleeSF->getIndex());
374
375 for (ExplodedNode *N : CleanedNodes) {
376 // Step 4: Generate the CallExitEnd node.
377 // CleanedNodes -> CEENode
378 CallExitEnd Loc(CalleeSF, CallerSF);
379 ProgramStateRef CEEState = (N == CEBNode) ? State : N->getState();
380
381 ExplodedNode *CEENode = Engine.makeNode(Loc, CEEState, N);
382 if (!CEENode)
383 continue;
384
385 // Step 5: Perform the post-condition check of the CallExpr and enqueue the
386 // result onto the work list.
387 // CEENode -> Dst -> WorkList
388
389 CallEventRef<> UpdatedCall = Call.cloneWithState(CEEState);
390
391 ExplodedNodeSet DstPostPostCallCallback;
392 getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback, CEENode,
393 *UpdatedCall, *this,
394 /*wasInlined=*/true);
395 ExplodedNodeSet DstPostCall;
396 if (llvm::isa_and_nonnull<CXXNewExpr>(CE)) {
397 for (ExplodedNode *I : DstPostPostCallCallback) {
399 cast<CXXAllocatorCall>(*UpdatedCall), DstPostCall, I, *this,
400 /*wasInlined=*/true);
401 }
402 } else {
403 DstPostCall.insert(DstPostPostCallCallback);
404 }
405
406 ExplodedNodeSet Dst;
407 if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
408 getCheckerManager().runCheckersForPostObjCMessage(Dst, DstPostCall, *Msg,
409 *this,
410 /*wasInlined=*/true);
411 } else if (CE &&
412 !(isa<CXXNewExpr>(CE) && // Called when visiting CXXNewExpr.
413 AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {
414 getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
415 *this, /*wasInlined=*/true);
416 } else {
417 Dst.insert(DstPostCall);
418 }
419
420 // Enqueue the next element in the block.
421 for (ExplodedNode *DstNode : Dst) {
422 unsigned Idx = CalleeSF->getIndex() + (ShouldRepeatCall ? 0 : 1);
423
424 Engine.getWorkList()->enqueue(DstNode, CalleeSF->getCallSiteBlock(), Idx);
425 }
426 }
427}
428
429bool ExprEngine::isSmall(AnalysisDeclContext *ADC) const {
430 // When there are no branches in the function, it means that there's no
431 // exponential complexity introduced by inlining such function.
432 // Such functions also don't trigger various fundamental problems
433 // with our inlining mechanism, such as the problem of
434 // inlined defensive checks. Hence isLinear().
435 const CFG *Cfg = ADC->getCFG();
436 return Cfg->isLinear() || Cfg->size() <= AMgr.options.AlwaysInlineSize;
437}
438
439bool ExprEngine::isLarge(AnalysisDeclContext *ADC) const {
440 const CFG *Cfg = ADC->getCFG();
441 return Cfg->size() >= AMgr.options.MinCFGSizeTreatFunctionsAsLarge;
442}
443
444bool ExprEngine::isHuge(AnalysisDeclContext *ADC) const {
445 const CFG *Cfg = ADC->getCFG();
446 return Cfg->getNumBlockIDs() > AMgr.options.MaxInlinableSize;
447}
448
449void ExprEngine::examineStackFrames(
450 const Decl *D, llvm::iterator_range<StackFrame::parent_iterator> Frames,
451 bool &IsRecursive, unsigned &StackDepth) {
452 IsRecursive = false;
453 StackDepth = 0;
454
455 for (const StackFrame &Frame : Frames) {
456 const Decl *DI = Frame.getDecl();
457
458 // Mark recursive (and mutually recursive) functions and always count
459 // them when measuring the stack depth.
460 if (DI == D) {
461 IsRecursive = true;
462 ++StackDepth;
463 continue;
464 }
465
466 // Do not count the small functions when determining the stack depth.
467 AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
468 if (!isSmall(CalleeADC))
469 ++StackDepth;
470 }
471}
472
473// The GDM component containing the dynamic dispatch bifurcation info. When
474// the exact type of the receiver is not known, we want to explore both paths -
475// one on which we do inline it and the other one on which we don't. This is
476// done to ensure we do not drop coverage.
477// This is the map from the receiver region to a bool, specifying either we
478// consider this region's information precise or not along the given path.
479namespace {
480 enum DynamicDispatchMode {
481 DynamicDispatchModeInlined = 1,
482 DynamicDispatchModeConservative
483 };
484} // end anonymous namespace
485
486REGISTER_MAP_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap,
487 const MemRegion *, unsigned)
488REGISTER_TRAIT_WITH_PROGRAMSTATE(CTUDispatchBifurcation, bool)
489
490void ExprEngine::ctuBifurcate(const CallEvent &Call, const Decl *D,
491 ExplodedNodeSet &Dst, ExplodedNode *Pred,
492 ProgramStateRef State) {
493 if (Call.isForeign() && !isSecondPhaseCTU()) {
494 const auto IK = AMgr.options.getCTUPhase1Inlining();
495 const bool DoInline = IK == CTUPhase1InliningKind::All ||
497 isSmall(AMgr.getAnalysisDeclContext(D)));
498 if (DoInline) {
499 inlineCall(Engine.getWorkList(), Call, D, Pred, State);
500 return;
501 }
502 const bool BState = State->get<CTUDispatchBifurcation>();
503 if (!BState) { // This is the first time we see this foreign function.
504 // Enqueue it to be analyzed in the second (ctu) phase.
505 inlineCall(Engine.getCTUWorkList(), Call, D, Pred, State);
506 // Conservatively evaluate in the first phase.
507 State = State->set<CTUDispatchBifurcation>(true);
508 }
509 Dst.insert(conservativeEvalCall(Call, Pred, State));
510 return;
511 }
512 inlineCall(Engine.getWorkList(), Call, D, Pred, State);
513}
514
515void ExprEngine::inlineCall(WorkList *WList, const CallEvent &Call,
516 const Decl *D, ExplodedNode *Pred,
517 ProgramStateRef State) {
518 assert(D);
519
520 const StackFrame *CallerSF = Pred->getStackFrame();
521 const BlockDataRegion *BlockInvocationData = nullptr;
522 if (Call.getKind() == CE_Block &&
523 !cast<BlockCall>(Call).isConversionFromLambda()) {
524 BlockInvocationData = cast<BlockCall>(Call).getBlockRegion();
525 assert(BlockInvocationData &&
526 "If we have the block definition we should have its region");
527 }
528
529 // This may be NULL, but that's fine.
530 const Expr *CallE = Call.getOriginExpr();
531
532 // Construct a new stack frame for the callee.
533 AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
534 const StackFrame *CalleeSF = CalleeADC->getStackFrame(
535 CallerSF, BlockInvocationData, CallE, getCurrBlock(),
536 getNumVisitedCurrent(), currStmtIdx);
537
538 CallEnter Loc(CallE, CalleeSF, CallerSF);
539
540 // Construct a new state which contains the mapping from actual to
541 // formal arguments.
542 State = State->enterStackFrame(Call, CalleeSF);
543
544 if (ExplodedNode *N = Engine.makeNode(Loc, State, Pred))
545 WList->enqueue(N);
546
547 NumInlinedCalls++;
548 Engine.FunctionSummaries->bumpNumTimesInlined(D);
549
550 // Do not mark as visited in the 2nd run (CTUWList), so the function will
551 // be visited as top-level, this way we won't loose reports in non-ctu
552 // mode. Considering the case when a function in a foreign TU calls back
553 // into the main TU.
554 // Note, during the 1st run, it doesn't matter if we mark the foreign
555 // functions as visited (or not) because they can never appear as a top level
556 // function in the main TU.
557 if (!isSecondPhaseCTU())
558 // Mark the decl as visited.
559 if (VisitedCallees)
560 VisitedCallees->insert(D);
561}
562
564 const Expr *CallE) {
565 const void *ReplayState = State->get<ReplayWithoutInlining>();
566 if (!ReplayState)
567 return nullptr;
568
569 assert(ReplayState == CallE && "Backtracked to the wrong call.");
570 (void)CallE;
571
572 return State->remove<ReplayWithoutInlining>();
573}
574
576 ExplodedNodeSet &dst) {
577 if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
578 // For instance method operators, make sure the 'this' argument has a
579 // valid region.
580 // FIXME: Why is this only applied for operator calls and not other calls?
581 const Decl *Callee = OCE->getCalleeDecl();
582 if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
583 if (MD->isImplicitObjectMemberFunction()) {
584 ProgramStateRef State = Pred->getState();
585 const StackFrame *SF = Pred->getStackFrame();
586 ProgramStateRef NewState =
587 createTemporaryRegionIfNeeded(State, SF, OCE->getArg(0));
588 if (NewState != State) {
589 PreStmt PS(OCE, SF, /*tag=*/nullptr);
590 Pred = Engine.makeNode(PS, NewState, Pred);
591 if (!Pred)
592 return; // Cached out.
593 }
594 }
595 }
596 }
597 // Perform the previsit of the CallExpr.
598 ExplodedNodeSet dstPreVisit;
599 getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this);
600
601 // Get the call in its initial state. We use this as a template to perform
602 // all the checks.
604 CallEventRef<> CallTemplate = CEMgr.getSimpleCall(
605 CE, Pred->getState(), Pred->getStackFrame(), getCFGElementRef());
606
607 // Evaluate the function call. We try each of the checkers
608 // to see if the can evaluate the function call.
609 ExplodedNodeSet dstCallEvaluated;
610 for (ExplodedNode *N : dstPreVisit) {
611 evalCall(dstCallEvaluated, N, *CallTemplate);
612 }
613
614 // Finally, perform the post-condition check of the CallExpr and store
615 // the created nodes in 'Dst'.
616 // Note that if the call was inlined, dstCallEvaluated will be empty.
617 // The post-CallExpr check will occur in processCallExit.
618 getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE,
619 *this);
620}
621
622ProgramStateRef ExprEngine::finishArgumentConstruction(ProgramStateRef State,
623 const CallEvent &Call) {
624 // WARNING: The state attached to 'Call' may be obsolete, do not call any
625 // methods that rely on it!
626 const Expr *E = Call.getOriginExpr();
627 // FIXME: Constructors to placement arguments of operator new
628 // are not supported yet.
629 if (!E || isa<CXXNewExpr>(E))
630 return State;
631
632 const StackFrame *SF = Call.getStackFrame();
633 for (unsigned CallI = 0, CallN = Call.getNumArgs(); CallI != CallN; ++CallI) {
634 unsigned I = Call.getASTArgumentIndex(CallI);
635 if (std::optional<SVal> V = getObjectUnderConstruction(State, {E, I}, SF)) {
636 SVal VV = *V;
637 (void)VV;
639 ->getStackFrame()
640 ->getParent() == SF);
641 State = finishObjectConstruction(State, {E, I}, SF);
642 }
643 }
644
645 return State;
646}
647
648void ExprEngine::finishArgumentConstruction(ExplodedNodeSet &Dst,
649 ExplodedNode *Pred,
650 const CallEvent &Call) {
651 // WARNING: The state attached to 'Call' may be obsolete, do not call any
652 // methods that rely on it!
653 ProgramStateRef State = Pred->getState();
654 ProgramStateRef CleanedState = finishArgumentConstruction(State, Call);
655 if (CleanedState == State) {
656 Dst.insert(Pred);
657 return;
658 }
659
660 const Expr *E = Call.getOriginExpr();
661 const StackFrame *SF = Call.getStackFrame();
662 static SimpleProgramPointTag Tag("ExprEngine",
663 "Finish argument construction");
664 Dst.insert(Engine.makeNode(PreStmt(E, SF, &Tag), CleanedState, Pred));
665}
666
668 const CallEvent &CallTemplate) {
669 // NOTE: CallTemplate is called a "template" because its attached state may
670 // be obsolete (compared to the state of Pred). The state-dependent methods
671 // of CallEvent should be used only after a `cloneWithState` call that
672 // attaches the up-to-date state to this template object.
673
674 // Run any pre-call checks using the generic call interface.
675 ExplodedNodeSet dstPreVisit;
676 getCheckerManager().runCheckersForPreCall(dstPreVisit, Pred, CallTemplate,
677 *this);
678
679 // Actually evaluate the function call. We try each of the checkers
680 // to see if the can evaluate the function call, and get a callback at
681 // defaultEvalCall if all of them fail.
682 ExplodedNodeSet dstCallEvaluated;
684 dstCallEvaluated, dstPreVisit, CallTemplate, *this, EvalCallOptions());
685
686 // If there were other constructors called for object-type arguments
687 // of this call, clean them up.
688 ExplodedNodeSet dstArgumentCleanup;
689 for (ExplodedNode *I : dstCallEvaluated)
690 finishArgumentConstruction(dstArgumentCleanup, I, CallTemplate);
691
692 ExplodedNodeSet dstPostCall;
693 getCheckerManager().runCheckersForPostCall(dstPostCall, dstArgumentCleanup,
694 CallTemplate, *this);
695
696 // Escaping symbols conjured during invalidating the regions above.
697 // Note that, for inlined calls the nodes were put back into the worklist,
698 // so we can assume that every node belongs to a conservative call at this
699 // point.
700
701 // Run pointerEscape callback with the newly conjured symbols.
703 for (ExplodedNode *I : dstPostCall) {
704 ProgramStateRef State = I->getState();
705 CallEventRef<> Call = CallTemplate.cloneWithState(State);
706 Escaped.clear();
707 {
708 unsigned Arg = -1;
709 for (const ParmVarDecl *PVD : Call->parameters()) {
710 ++Arg;
711 QualType ParamTy = PVD->getType();
712 if (ParamTy.isNull() ||
713 (!ParamTy->isPointerType() && !ParamTy->isReferenceType()))
714 continue;
715 QualType Pointee = ParamTy->getPointeeType();
716 if (Pointee.isConstQualified() || Pointee->isVoidType())
717 continue;
718 if (const MemRegion *MR = Call->getArgSVal(Arg).getAsRegion())
719 Escaped.emplace_back(loc::MemRegionVal(MR), State->getSVal(MR, Pointee));
720 }
721 }
722
723 State = processPointerEscapedOnBind(State, Escaped, I->getStackFrame(),
725
726 if (State != I->getState())
727 I = Engine.makeNode(I->getLocation(), State, I);
728
729 Dst.insert(I);
730 }
731}
732
734 const StackFrame *SF,
735 ProgramStateRef State) {
736 const Expr *E = Call.getOriginExpr();
737 const ConstCFGElementRef &Elem = Call.getCFGElementRef();
738 if (!E)
739 return State;
740
741 // Some method families have known return values.
742 if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
743 switch (Msg->getMethodFamily()) {
744 default:
745 break;
746 case OMF_autorelease:
747 case OMF_retain:
748 case OMF_self: {
749 // These methods return their receivers.
750 return State->BindExpr(E, SF, Msg->getReceiverSVal());
751 }
752 }
753 } else if (const CXXConstructorCall *C = dyn_cast<CXXConstructorCall>(&Call)){
754 SVal ThisV = C->getCXXThisVal();
755 ThisV = State->getSVal(ThisV.castAs<Loc>());
756 return State->BindExpr(E, SF, ThisV);
757 }
758
759 SVal R;
760 QualType ResultTy = Call.getResultType();
761 unsigned Count = getNumVisitedCurrent();
762 if (auto RTC = getCurrentCFGElement().getAs<CFGCXXRecordTypedCall>()) {
763 // Conjure a temporary if the function returns an object by value.
764 SVal Target;
765 assert(RTC->getStmt() == Call.getOriginExpr());
766 EvalCallOptions CallOpts; // FIXME: We won't really need those.
767 std::tie(State, Target) =
768 handleConstructionContext(Call.getOriginExpr(), State, SF,
769 RTC->getConstructionContext(), CallOpts);
770 const MemRegion *TargetR = Target.getAsRegion();
771 assert(TargetR);
772 // Invalidate the region so that it didn't look uninitialized. If this is
773 // a field or element constructor, we do not want to invalidate
774 // the whole structure. Pointer escape is meaningless because
775 // the structure is a product of conservative evaluation
776 // and therefore contains nothing interesting at this point.
778 ITraits.setTrait(TargetR,
780 State = State->invalidateRegions(TargetR, Elem, Count, SF,
781 /* CausesPointerEscape=*/false, nullptr,
782 &Call, &ITraits);
783
784 R = State->getSVal(Target.castAs<Loc>(), E->getType());
785 } else {
786 // Conjure a symbol if the return value is unknown.
787
788 // See if we need to conjure a heap pointer instead of
789 // a regular unknown pointer.
790 const auto *CNE = dyn_cast<CXXNewExpr>(E);
791 if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
792 R = svalBuilder.getConjuredHeapSymbolVal(Elem, SF, E->getType(), Count);
793 const MemRegion *MR = R.getAsRegion()->StripCasts();
794
795 // Store the extent of the allocated object(s).
796 SVal ElementCount;
797 if (const Expr *SizeExpr = CNE->getArraySize().value_or(nullptr)) {
798 ElementCount = State->getSVal(SizeExpr, SF);
799 } else {
800 ElementCount = svalBuilder.makeIntVal(1, /*IsUnsigned=*/true);
801 }
802
803 SVal ElementSize = getElementExtent(CNE->getAllocatedType(), svalBuilder);
804
805 SVal Size =
806 svalBuilder.evalBinOp(State, BO_Mul, ElementCount, ElementSize,
807 svalBuilder.getArrayIndexType());
808
809 // FIXME: This line is to prevent a crash. For more details please check
810 // issue #56264.
811 if (Size.isUndef())
812 Size = UnknownVal();
813
814 State = setDynamicExtent(State, MR, Size.castAs<DefinedOrUnknownSVal>());
815 } else {
816 R = svalBuilder.conjureSymbolVal(Elem, SF, ResultTy, Count);
817 }
818 }
819 return State->BindExpr(E, SF, R);
820}
821
822// Conservatively evaluate call by invalidating regions and binding
823// a conjured return value.
824ExplodedNode *ExprEngine::conservativeEvalCall(const CallEvent &Call,
825 ExplodedNode *Pred,
826 ProgramStateRef State) {
827 State = Call.invalidateRegions(getNumVisitedCurrent(), State);
828 State = bindReturnValue(Call, Pred->getStackFrame(), State);
829
830 // And make the result node.
831 static SimpleProgramPointTag PT("ExprEngine", "Conservative eval call");
832 return Engine.makeNode(Call.getProgramPoint(false, &PT), State, Pred);
833}
834
835ExprEngine::CallInlinePolicy
836ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
837 AnalyzerOptions &Opts,
838 const EvalCallOptions &CallOpts) {
839 const StackFrame *CallerSF = Pred->getStackFrame();
840 switch (Call.getKind()) {
841 case CE_Function:
843 case CE_Block:
844 break;
845 case CE_CXXMember:
848 return CIP_DisallowedAlways;
849 break;
850 case CE_CXXConstructor: {
852 return CIP_DisallowedAlways;
853
855
856 const CXXConstructExpr *CtorExpr = Ctor.getOriginExpr();
857
859 const ConstructionContext *CC = CCE ? CCE->getConstructionContext()
860 : nullptr;
861
862 if (llvm::isa_and_nonnull<NewAllocatedObjectConstructionContext>(CC) &&
863 !Opts.MayInlineCXXAllocator)
864 return CIP_DisallowedOnce;
865
866 if (CallOpts.IsArrayCtorOrDtor) {
867 if (!shouldInlineArrayConstruction(Pred->getState(), CtorExpr, CallerSF))
868 return CIP_DisallowedOnce;
869 }
870
871 // Inlining constructors requires including initializers in the CFG.
872 const AnalysisDeclContext *ADC = CallerSF->getAnalysisDeclContext();
873 assert(ADC->getCFGBuildOptions().AddInitializers && "No CFG initializers");
874 (void)ADC;
875
876 // If the destructor is trivial, it's always safe to inline the constructor.
877 if (Ctor.getDecl()->getParent()->hasTrivialDestructor())
878 break;
879
880 // For other types, only inline constructors if destructor inlining is
881 // also enabled.
883 return CIP_DisallowedAlways;
884
886 // If we don't handle temporary destructors, we shouldn't inline
887 // their constructors.
888 if (CallOpts.IsTemporaryCtorOrDtor &&
889 !Opts.ShouldIncludeTemporaryDtorsInCFG)
890 return CIP_DisallowedOnce;
891
892 // If we did not find the correct this-region, it would be pointless
893 // to inline the constructor. Instead we will simply invalidate
894 // the fake temporary target.
896 return CIP_DisallowedOnce;
897
898 // If the temporary is lifetime-extended by binding it to a reference-type
899 // field within an aggregate, automatic destructors don't work properly.
901 return CIP_DisallowedOnce;
902 }
903
904 break;
905 }
907 // This doesn't really increase the cost of inlining ever, because
908 // the stack frame of the inherited constructor is trivial.
909 return CIP_Allowed;
910 }
911 case CE_CXXDestructor: {
913 return CIP_DisallowedAlways;
914
915 // Inlining destructors requires building the CFG correctly.
916 const AnalysisDeclContext *ADC = CallerSF->getAnalysisDeclContext();
917 assert(ADC->getCFGBuildOptions().AddImplicitDtors && "No CFG destructors");
918 (void)ADC;
919
920 if (CallOpts.IsArrayCtorOrDtor) {
921 if (!shouldInlineArrayDestruction(getElementCountOfArrayBeingDestructed(
922 Call, Pred->getState(), svalBuilder))) {
923 return CIP_DisallowedOnce;
924 }
925 }
926
927 // Allow disabling temporary destructor inlining with a separate option.
928 if (CallOpts.IsTemporaryCtorOrDtor &&
929 !Opts.MayInlineCXXTemporaryDtors)
930 return CIP_DisallowedOnce;
931
932 // If we did not find the correct this-region, it would be pointless
933 // to inline the destructor. Instead we will simply invalidate
934 // the fake temporary target.
936 return CIP_DisallowedOnce;
937 break;
938 }
940 [[fallthrough]];
941 case CE_CXXAllocator:
942 if (Opts.MayInlineCXXAllocator)
943 break;
944 // Do not inline allocators until we model deallocators.
945 // This is unfortunate, but basically necessary for smart pointers and such.
946 return CIP_DisallowedAlways;
947 case CE_ObjCMessage:
948 if (!Opts.MayInlineObjCMethod)
949 return CIP_DisallowedAlways;
950 if (!(Opts.getIPAMode() == IPAK_DynamicDispatch ||
952 return CIP_DisallowedAlways;
953 break;
954 }
955
956 return CIP_Allowed;
957}
958
959/// Returns true if the given C++ class contains a member with the given name.
960static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD,
961 StringRef Name) {
962 const IdentifierInfo &II = Ctx.Idents.get(Name);
963 return RD->hasMemberName(Ctx.DeclarationNames.getIdentifier(&II));
964}
965
966/// Returns true if the given C++ class is a container or iterator.
967///
968/// Our heuristic for this is whether it contains a method named 'begin()' or a
969/// nested type named 'iterator' or 'iterator_category'.
970static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD) {
971 return hasMember(Ctx, RD, "begin") ||
972 hasMember(Ctx, RD, "iterator") ||
973 hasMember(Ctx, RD, "iterator_category");
974}
975
976/// Returns true if the given function refers to a method of a C++ container
977/// or iterator.
978///
979/// We generally do a poor job modeling most containers right now, and might
980/// prefer not to inline their methods.
981static bool isContainerMethod(const ASTContext &Ctx,
982 const FunctionDecl *FD) {
983 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
984 return isContainerClass(Ctx, MD->getParent());
985 return false;
986}
987
988/// Returns true if the given function is the destructor of a class named
989/// "shared_ptr".
990static bool isCXXSharedPtrDtor(const FunctionDecl *FD) {
991 const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(FD);
992 if (!Dtor)
993 return false;
994
995 const CXXRecordDecl *RD = Dtor->getParent();
996 if (const IdentifierInfo *II = RD->getDeclName().getAsIdentifierInfo())
997 if (II->isStr("shared_ptr"))
998 return true;
999
1000 return false;
1001}
1002
1003/// Returns true if the function in \p CalleeADC may be inlined in general.
1004///
1005/// This checks static properties of the function, such as its signature and
1006/// CFG, to determine whether the analyzer should ever consider inlining it,
1007/// in any context.
1008bool ExprEngine::mayInlineDecl(AnalysisDeclContext *CalleeADC) const {
1009 AnalyzerOptions &Opts = AMgr.getAnalyzerOptions();
1010 // FIXME: Do not inline variadic calls.
1011 if (CallEvent::isVariadic(CalleeADC->getDecl()))
1012 return false;
1013
1014 // Check certain C++-related inlining policies.
1015 ASTContext &Ctx = CalleeADC->getASTContext();
1016 if (Ctx.getLangOpts().CPlusPlus) {
1017 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->getDecl())) {
1018 // Conditionally control the inlining of template functions.
1019 if (!Opts.MayInlineTemplateFunctions)
1020 if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
1021 return false;
1022
1023 // Conditionally control the inlining of C++ standard library functions.
1024 if (!Opts.MayInlineCXXStandardLibrary)
1025 if (Ctx.getSourceManager().isInSystemHeader(FD->getLocation()))
1027 return false;
1028
1029 // Conditionally control the inlining of methods on objects that look
1030 // like C++ containers.
1031 if (!Opts.MayInlineCXXContainerMethods)
1032 if (!AMgr.isInCodeFile(FD->getLocation()))
1033 if (isContainerMethod(Ctx, FD))
1034 return false;
1035
1036 // Conditionally control the inlining of the destructor of C++ shared_ptr.
1037 // We don't currently do a good job modeling shared_ptr because we can't
1038 // see the reference count, so treating as opaque is probably the best
1039 // idea.
1040 if (!Opts.MayInlineCXXSharedPtrDtor)
1041 if (isCXXSharedPtrDtor(FD))
1042 return false;
1043 }
1044 }
1045
1046 // It is possible that the CFG cannot be constructed.
1047 // Be safe, and check if the CalleeCFG is valid.
1048 const CFG *CalleeCFG = CalleeADC->getCFG();
1049 if (!CalleeCFG)
1050 return false;
1051
1052 // Do not inline large functions.
1053 if (isHuge(CalleeADC))
1054 return false;
1055
1056 // It is possible that the live variables analysis cannot be
1057 // run. If so, bail out.
1058 if (!CalleeADC->getAnalysis<RelaxedLiveVariables>())
1059 return false;
1060
1061 return true;
1062}
1063
1064bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
1065 const ExplodedNode *Pred,
1066 const EvalCallOptions &CallOpts) {
1067 if (!D)
1068 return false;
1069
1070 AnalysisManager &AMgr = getAnalysisManager();
1071 AnalyzerOptions &Opts = AMgr.options;
1072 AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
1073 AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);
1074
1075 // The auto-synthesized bodies are essential to inline as they are
1076 // usually small and commonly used. Note: we should do this check early on to
1077 // ensure we always inline these calls.
1078 if (CalleeADC->isBodyAutosynthesized())
1079 return true;
1080
1081 if (!AMgr.shouldInlineCall())
1082 return false;
1083
1084 // Check if this function has been marked as non-inlinable.
1085 std::optional<bool> MayInline = Engine.FunctionSummaries->mayInline(D);
1086 if (MayInline) {
1087 if (!*MayInline)
1088 return false;
1089
1090 } else {
1091 // We haven't actually checked the static properties of this function yet.
1092 // Do that now, and record our decision in the function summaries.
1093 if (mayInlineDecl(CalleeADC)) {
1094 Engine.FunctionSummaries->markMayInline(D);
1095 } else {
1096 Engine.FunctionSummaries->markShouldNotInline(D);
1097 return false;
1098 }
1099 }
1100
1101 // Check if we should inline a call based on its kind.
1102 // FIXME: this checks both static and dynamic properties of the call, which
1103 // means we're redoing a bit of work that could be cached in the function
1104 // summary.
1105 CallInlinePolicy CIP = mayInlineCallKind(Call, Pred, Opts, CallOpts);
1106 if (CIP != CIP_Allowed) {
1107 if (CIP == CIP_DisallowedAlways) {
1108 assert(!MayInline || *MayInline);
1109 Engine.FunctionSummaries->markShouldNotInline(D);
1110 }
1111 return false;
1112 }
1113
1114 // Do not inline if recursive or we've reached max stack frame count.
1115 bool IsRecursive = false;
1116 unsigned StackDepth = 0;
1117 examineStackFrames(D, Pred->stackframes(), IsRecursive, StackDepth);
1118 if ((StackDepth >= Opts.InlineMaxStackDepth) &&
1119 (!isSmall(CalleeADC) || IsRecursive))
1120 return false;
1121
1122 // Do not inline large functions too many times.
1123 if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
1124 Opts.MaxTimesInlineLarge) &&
1125 isLarge(CalleeADC)) {
1126 NumReachedInlineCountMax++;
1127 return false;
1128 }
1129
1130 if (HowToInline == Inline_Minimal && (!isSmall(CalleeADC) || IsRecursive))
1131 return false;
1132
1133 return true;
1134}
1135
1136bool ExprEngine::shouldInlineArrayConstruction(const ProgramStateRef State,
1137 const CXXConstructExpr *CE,
1138 const StackFrame *SF) {
1139 if (!CE)
1140 return false;
1141
1142 // FIXME: Handle other arrays types.
1143 if (const auto *CAT = dyn_cast<ConstantArrayType>(CE->getType())) {
1144 unsigned ArrSize = getContext().getConstantArrayElementCount(CAT);
1145
1146 // This might seem conter-intuitive at first glance, but the functions are
1147 // closely related. Reasoning about destructors depends only on the type
1148 // of the expression that initialized the memory region, which is the
1149 // CXXConstructExpr. So to avoid code repetition, the work is delegated
1150 // to the function that reasons about destructor inlining. Also note that
1151 // if the constructors of the array elements are inlined, the destructors
1152 // can also be inlined and if the destructors can be inline, it's safe to
1153 // inline the constructors.
1154 return shouldInlineArrayDestruction(ArrSize);
1155 }
1156
1157 // Check if we're inside an ArrayInitLoopExpr, and it's sufficiently small.
1158 if (auto Size = getPendingInitLoop(State, CE, SF))
1159 return shouldInlineArrayDestruction(*Size);
1160
1161 return false;
1162}
1163
1164bool ExprEngine::shouldInlineArrayDestruction(uint64_t Size) {
1165
1166 uint64_t maxAllowedSize = AMgr.options.maxBlockVisitOnPath;
1167
1168 // Declaring a 0 element array is also possible.
1169 return Size <= maxAllowedSize && Size > 0;
1170}
1171
1172bool ExprEngine::shouldRepeatCtorCall(ProgramStateRef State,
1173 const CXXConstructExpr *E,
1174 const StackFrame *SF) {
1175
1176 if (!E)
1177 return false;
1178
1179 auto Ty = E->getType();
1180
1181 // FIXME: Handle non constant array types
1182 if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
1184 return Size > getIndexOfElementToConstruct(State, E, SF);
1185 }
1186
1187 if (auto Size = getPendingInitLoop(State, E, SF))
1188 return Size > getIndexOfElementToConstruct(State, E, SF);
1189
1190 return false;
1191}
1192
1194 const CXXInstanceCall *ICall = dyn_cast<CXXInstanceCall>(&Call);
1195 if (!ICall)
1196 return false;
1197
1198 const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(ICall->getDecl());
1199 if (!MD)
1200 return false;
1202 return false;
1203
1204 return MD->isTrivial();
1205}
1206
1208 const CallEvent &Call,
1209 const EvalCallOptions &CallOpts) {
1210 // Make sure we have the most recent state attached to the call.
1211 ProgramStateRef State = Pred->getState();
1212
1213 // Special-case trivial assignment operators.
1215 performTrivialCopy(Dst, Pred, Call);
1216 return;
1217 }
1218
1219 const Expr *E = Call.getOriginExpr();
1220
1221 ProgramStateRef InlinedFailedState = getInlineFailedState(State, E);
1222 if (InlinedFailedState) {
1223 // If we already tried once and failed, make sure we don't retry later.
1224 State = InlinedFailedState;
1225 } else {
1226 RuntimeDefinition RD = Call.getRuntimeDefinition();
1227 Call.setForeign(RD.isForeign());
1228 const Decl *D = RD.getDecl();
1229 if (shouldInlineCall(Call, D, Pred, CallOpts)) {
1230 if (RD.mayHaveOtherDefinitions()) {
1232
1233 // Explore with and without inlining the call.
1234 if (Options.getIPAMode() == IPAK_DynamicDispatchBifurcate) {
1235 dynDispatchBifurcate(RD.getDispatchRegion(), Call, D, Dst, Pred);
1236 return;
1237 }
1238
1239 // Don't inline if we're not in any dynamic dispatch mode.
1240 if (Options.getIPAMode() != IPAK_DynamicDispatch) {
1241 Dst.insert(conservativeEvalCall(Call, Pred, State));
1242 return;
1243 }
1244 }
1245 ctuBifurcate(Call, D, Dst, Pred, State);
1246 return;
1247 }
1248 }
1249
1250 // If we can't inline it, clean up the state traits used only if the function
1251 // is inlined.
1252 State = removeStateTraitsUsedForArrayEvaluation(
1253 State, dyn_cast_or_null<CXXConstructExpr>(E), Call.getStackFrame());
1254
1255 // Also handle the return value and invalidate the regions.
1256 Dst.insert(conservativeEvalCall(Call, Pred, State));
1257}
1258
1259void ExprEngine::dynDispatchBifurcate(const MemRegion *BifurReg,
1260 const CallEvent &Call, const Decl *D,
1261 ExplodedNodeSet &Dst,
1262 ExplodedNode *Pred) {
1263 assert(BifurReg);
1264 BifurReg = BifurReg->StripCasts();
1265
1266 // Check if we've performed the split already - note, we only want
1267 // to split the path once per memory region.
1268 ProgramStateRef State = Pred->getState();
1269 const unsigned *BState =
1270 State->get<DynamicDispatchBifurcationMap>(BifurReg);
1271 if (BState) {
1272 // If we are on "inline path", keep inlining if possible.
1273 if (*BState == DynamicDispatchModeInlined)
1274 ctuBifurcate(Call, D, Dst, Pred, State);
1275 // If inline failed, or we are on the path where we assume we
1276 // don't have enough info about the receiver to inline, conjure the
1277 // return value and invalidate the regions.
1278 Dst.insert(conservativeEvalCall(Call, Pred, State));
1279 return;
1280 }
1281
1282 // If we got here, this is the first time we process a message to this
1283 // region, so split the path.
1284 ProgramStateRef IState =
1285 State->set<DynamicDispatchBifurcationMap>(BifurReg,
1286 DynamicDispatchModeInlined);
1287 ctuBifurcate(Call, D, Dst, Pred, IState);
1288
1289 ProgramStateRef NoIState =
1290 State->set<DynamicDispatchBifurcationMap>(BifurReg,
1291 DynamicDispatchModeConservative);
1292 Dst.insert(conservativeEvalCall(Call, Pred, NoIState));
1293
1294 NumOfDynamicDispatchPathSplits++;
1295}
1296
1298 ExplodedNodeSet &Dst) {
1299 if (RS->getRetValue()) {
1300 Dst.insert(Engine.makePostStmtNode(RS, Pred->getState(), Pred));
1301 } else {
1302 Dst.insert(Pred);
1303 }
1304}
#define V(N, I)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
#define STAT_COUNTER(VARNAME, DESC)
static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD)
Returns true if the given C++ class is a container or iterator.
static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call, const StackFrame *calleeCtx)
static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)
static bool isTrivialObjectAssignment(const CallEvent &Call)
static bool isCXXSharedPtrDtor(const FunctionDecl *FD)
Returns true if the given function is the destructor of a class named "shared_ptr".
static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD, StringRef Name)
Returns true if the given C++ class contains a member with the given name.
static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy, StoreManager &StoreMgr)
Adjusts a return value when the called function's return type does not match the caller's expression ...
static bool isContainerMethod(const ASTContext &Ctx, const FunctionDecl *FD)
Returns true if the given function refers to a method of a C++ container or iterator.
static unsigned getElementCountOfArrayBeingDestructed(const CallEvent &Call, const ProgramStateRef State, SValBuilder &SVB)
static ProgramStateRef getInlineFailedState(ProgramStateRef State, const Expr *CallE)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
a trap message and trap category.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
SourceManager & getSourceManager()
Definition ASTContext.h:907
DeclarationNameTable DeclarationNames
Definition ASTContext.h:850
IdentifierTable & Idents
Definition ASTContext.h:846
const LangOptions & getLangOpts() const
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
AnalysisDeclContext * getContext(const Decl *D)
AnalysisDeclContext contains the context data for the function, method or block under analysis.
static bool isInStdNamespace(const Decl *D)
ASTContext & getASTContext() const
const StackFrame * getStackFrame(const StackFrame *ParentSF, const void *Data, const Expr *E, const CFGBlock *Blk, unsigned BlockCount, unsigned Index)
Obtain a context of the call stack using its parent context.
CFG::BuildOptions & getCFGBuildOptions()
Stores options for the analyzer from the command line.
bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const
Returns the option controlling which C++ member functions will be considered for inlining.
IPAKind getIPAMode() const
Returns the inter-procedural analysis mode.
CTUPhase1InliningKind getCTUPhase1Inlining() const
unsigned InlineMaxStackDepth
The inlining stack depth limit.
Represents a single basic block in a source-level CFG.
Definition CFG.h:652
bool empty() const
Definition CFG.h:1000
succ_iterator succ_begin()
Definition CFG.h:1037
unsigned succ_size() const
Definition CFG.h:1055
Represents C++ constructor call.
Definition CFG.h:161
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:113
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1271
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
Definition CFG.h:1469
bool isLinear() const
Returns true if the CFG has no branches.
Definition CFG.cpp:5469
CFGBlock & getExit()
Definition CFG.h:1387
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition CFG.h:1464
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
CXXBasePath & front()
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Represents a call to a C++ constructor.
Definition ExprCXX.h:1552
CXXConstructionKind getConstructionKind() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
Definition ExprCXX.h:1663
Represents a C++ destructor within a class.
Definition DeclCXX.h:2906
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2149
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2292
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
Definition DeclCXX.cpp:2751
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Definition DeclCXX.cpp:2730
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1381
bool hasMemberName(DeclarationName N) const
Determine whether this class has a member with the given name, possibly in a non-dependent base class...
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
Represents a point when we begin processing an inlined call.
const StackFrame * getCalleeStackFrame() const
const CFGBlock * getEntry() const
Returns the entry block in the CFG for the entered function.
Represents a point when we finish the call exit sequence (for inlined call).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
ConstructionContext's subclasses describe different ways of constructing an object in C++.
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:995
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
This is a meta program point, which should be skipped by all the diagnostic reasoning etc.
This represents one expression.
Definition Expr.h:113
QualType getType() const
Definition Expr.h:145
Represents a function declaration or definition.
Definition Decl.h:2059
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2504
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:341
Represents a parameter to a function.
Definition Decl.h:1820
const StackFrame * getStackFrame() const
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
QualType getCanonicalType() const
Definition TypeBase.h:8480
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8501
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition Stmt.h:3172
Expr * getRetValue()
Definition Stmt.h:3199
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
It represents a stack frame of the call stack.
unsigned getIndex() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getCallSite() const
const Decl * getDecl() const
const StackFrame * getParent() const
It might return null.
const CFGBlock * getCallSiteBlock() const
Stmt - This represents one statement.
Definition Stmt.h:85
bool isVoidType() const
Definition TypeBase.h:9037
bool isPointerType() const
Definition TypeBase.h:8665
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
Definition TypeBase.h:8689
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
Definition Type.cpp:1993
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:798
bool isObjCObjectPointerType() const
Definition TypeBase.h:8844
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
Represents a call to a C++ constructor.
Definition CallEvent.h:990
const CXXConstructorDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
Definition CallEvent.h:1021
const CXXConstructExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
Definition CallEvent.h:1017
Represents a non-static C++ member function call, no matter how it is written.
Definition CallEvent.h:686
const FunctionDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
Manages the lifetime of CallEvent objects.
Definition CallEvent.h:1363
CallEventRef getCaller(const StackFrame *CalleeSF, ProgramStateRef State)
Gets an outside caller given a callee context.
CallEventRef getSimpleCall(const CallExpr *E, ProgramStateRef State, const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef)
Represents an abstract call to a function or method along a particular path.
Definition CallEvent.h:152
CallEventRef< T > cloneWithState(ProgramStateRef NewState) const
Returns a copy of this CallEvent, but using the given state.
Definition CallEvent.h:1479
static QualType getDeclaredResultType(const Decl *D)
Returns the result type of a function or method declaration.
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 runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting obj-c messages.
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.
WorkList * getCTUWorkList() const
Definition CoreEngine.h:166
WorkList * getWorkList() const
Definition CoreEngine.h:165
ExplodedNode * makeNode(const ProgramPoint &Loc, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false) const
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.
std::optional< T > getLocationAs() const &
llvm::iterator_range< StackFrame::parent_iterator > stackframes() const
Iterates over the current stack frame and all of its ancestors.
ExplodedNode * getFirstPred()
const StackFrame * getStackFrame() const
ProgramStateManager & getStateManager()
Definition ExprEngine.h:441
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const StackFrame *SF, const Stmt *DiagnosticStmt=nullptr, ProgramPoint::Kind K=ProgramPoint::PreStmtPurgeDeadSymbolsKind)
Run the analyzer's garbage collection - remove dead symbols and bindings from the state.
void removeDeadOnEndOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst)
Remove dead bindings/symbols before exiting a function.
void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitReturnStmt - Transfer function logic for return statements.
void processCallEnter(CallEnter CE, ExplodedNode *Pred)
Generate the entry node of the callee.
void processCallExit(ExplodedNode *Pred)
Generate the sequence of nodes that simulate the call exit and the post visit for CallExpr.
CFGElement getCurrentCFGElement()
Return the CFG element corresponding to the worklist element that is currently being processed by Exp...
Definition ExprEngine.h:747
static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const StackFrame *SF)
Retrieves which element is being constructed in a non-POD type array.
@ Inline_Minimal
Do minimal inlining of callees.
Definition ExprEngine.h:129
ProgramStateRef bindReturnValue(const CallEvent &Call, const StackFrame *SF, ProgramStateRef State)
Create a new state in which the call return value is binded to the call origin expression.
static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const StackFrame *SF)
Retrieves the size of the array in the pending ArrayInitLoopExpr.
void setCurrStackFrameAndBlock(const StackFrame *SF, const CFGBlock *B)
Definition ExprEngine.h:216
void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCall - Transfer function for function calls.
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
Definition ExprEngine.h:192
StoreManager & getStoreManager()
Definition ExprEngine.h:444
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call)
Evaluate a call, running pre- and post-call checkers and allowing checkers to be responsible for hand...
void defaultEvalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call, const EvalCallOptions &CallOpts={})
Default implementation of call evaluation.
ConstCFGElementRef getCFGElementRef() const
Definition ExprEngine.h:254
static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const StackFrame *SF)
Retrieves which element is being destructed in a non-POD type array.
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, ArrayRef< std::pair< SVal, SVal > > LocAndVals, const StackFrame *SF, PointerEscapeKind Kind, const CallEvent *Call)
Call PointerEscape callback when a value escapes as a result of bind.
std::pair< ProgramStateRef, SVal > handleConstructionContext(const Expr *E, ProgramStateRef State, const StackFrame *SF, const ConstructionContext *CC, EvalCallOptions &CallOpts, unsigned Idx=0)
A convenient wrapper around computeObjectUnderConstruction and updateObjectsUnderConstruction.
Definition ExprEngine.h:796
CheckerManager & getCheckerManager() const
Definition ExprEngine.h:201
static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const StackFrame *SF)
By looking at a certain item that may be potentially part of an object's ConstructionContext,...
void processBeginOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L)
Called by CoreEngine.
unsigned getNumVisitedCurrent() const
Definition ExprEngine.h:263
AnalysisManager & getAnalysisManager()
Definition ExprEngine.h:194
const CFGBlock * getCurrBlock() const
Get the 'current' CFGBlock corresponding to the current work item (elementary analysis step handled b...
Definition ExprEngine.h:252
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:97
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
Represents any expression that calls an Objective-C method.
Definition CallEvent.h:1251
CallEventManager & getCallEventManager()
Information about invalidation for a particular region/symbol.
Definition MemRegion.h:1663
void setTrait(SymbolRef Sym, InvalidationKinds IK)
Defines the runtime definition of the called function.
Definition CallEvent.h:109
const MemRegion * getDispatchRegion()
When other definitions are possible, returns the region whose runtime type determines the method defi...
Definition CallEvent.h:140
bool mayHaveOtherDefinitions()
Check if the definition we have is precise.
Definition CallEvent.h:136
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:57
QualType getType(const ASTContext &) const
Try to get a reasonable type for the given value.
Definition SVals.cpp:180
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition SVals.h:84
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
virtual void enqueue(const WorkListUnit &U)=0
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getRegion() const
Get the underlining region.
Definition SVals.h:499
@ PSK_EscapeOutParameters
Escape for a new symbol that was generated into a region that the analyzer cannot follow during a con...
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, DefinedOrUnknownSVal Extent)
Set the dynamic extent Extent of the region MR.
@ CE_CXXInheritedConstructor
Definition CallEvent.h:68
@ CE_CXXStaticOperator
Definition CallEvent.h:61
@ CE_CXXDestructor
Definition CallEvent.h:64
@ CE_CXXDeallocator
Definition CallEvent.h:72
@ CE_CXXAllocator
Definition CallEvent.h:71
@ CE_CXXConstructor
Definition CallEvent.h:67
@ CE_CXXMemberOperator
Definition CallEvent.h:63
DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CFGBlock::ConstCFGElementRef ConstCFGElementRef
Definition CFG.h:1248
@ ExpectedClass
@ IPAK_DynamicDispatch
Enable inlining of dynamically dispatched methods.
@ IPAK_DynamicDispatchBifurcate
Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailabl...
@ CIMK_Destructors
Refers to destructors (implicit or explicit).
@ CIMK_MemberFunctions
Refers to regular member function and operator calls.
@ CIMK_Constructors
Refers to constructors (implicit or explicit).
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t
Hints for figuring out if a call should be inlined during evalCall().
Definition ExprEngine.h:92
bool IsTemporaryLifetimeExtendedViaAggregate
This call is a constructor for a temporary that is lifetime-extended by binding it to a reference-typ...
Definition ExprEngine.h:107
bool IsTemporaryCtorOrDtor
This call is a constructor or a destructor of a temporary value.
Definition ExprEngine.h:102
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:99
bool IsCtorOrDtorWithImproperlyModeledTargetRegion
This call is a constructor or a destructor for which we do not currently compute the this-region corr...
Definition ExprEngine.h:95
Traits for storing the call processing policy inside GDM.