106f32e7eSjoerg //=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg //  This file defines ExprEngine's support for calls and returns.
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg 
1306f32e7eSjoerg #include "PrettyStackTraceLocationContext.h"
1406f32e7eSjoerg #include "clang/AST/CXXInheritance.h"
15*13fbcb42Sjoerg #include "clang/AST/Decl.h"
1606f32e7eSjoerg #include "clang/AST/DeclCXX.h"
1706f32e7eSjoerg #include "clang/Analysis/Analyses/LiveVariables.h"
1806f32e7eSjoerg #include "clang/Analysis/ConstructionContext.h"
1906f32e7eSjoerg #include "clang/StaticAnalyzer/Core/CheckerManager.h"
2006f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
21*13fbcb42Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
22*13fbcb42Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
2306f32e7eSjoerg #include "llvm/ADT/SmallSet.h"
2406f32e7eSjoerg #include "llvm/ADT/Statistic.h"
25*13fbcb42Sjoerg #include "llvm/Support/Casting.h"
26*13fbcb42Sjoerg #include "llvm/Support/Compiler.h"
2706f32e7eSjoerg #include "llvm/Support/SaveAndRestore.h"
2806f32e7eSjoerg 
2906f32e7eSjoerg using namespace clang;
3006f32e7eSjoerg using namespace ento;
3106f32e7eSjoerg 
3206f32e7eSjoerg #define DEBUG_TYPE "ExprEngine"
3306f32e7eSjoerg 
3406f32e7eSjoerg STATISTIC(NumOfDynamicDispatchPathSplits,
3506f32e7eSjoerg   "The # of times we split the path due to imprecise dynamic dispatch info");
3606f32e7eSjoerg 
3706f32e7eSjoerg STATISTIC(NumInlinedCalls,
3806f32e7eSjoerg   "The # of times we inlined a call");
3906f32e7eSjoerg 
4006f32e7eSjoerg STATISTIC(NumReachedInlineCountMax,
4106f32e7eSjoerg   "The # of times we reached inline count maximum");
4206f32e7eSjoerg 
processCallEnter(NodeBuilderContext & BC,CallEnter CE,ExplodedNode * Pred)4306f32e7eSjoerg void ExprEngine::processCallEnter(NodeBuilderContext& BC, CallEnter CE,
4406f32e7eSjoerg                                   ExplodedNode *Pred) {
4506f32e7eSjoerg   // Get the entry block in the CFG of the callee.
4606f32e7eSjoerg   const StackFrameContext *calleeCtx = CE.getCalleeContext();
4706f32e7eSjoerg   PrettyStackTraceLocationContext CrashInfo(calleeCtx);
4806f32e7eSjoerg   const CFGBlock *Entry = CE.getEntry();
4906f32e7eSjoerg 
5006f32e7eSjoerg   // Validate the CFG.
5106f32e7eSjoerg   assert(Entry->empty());
5206f32e7eSjoerg   assert(Entry->succ_size() == 1);
5306f32e7eSjoerg 
5406f32e7eSjoerg   // Get the solitary successor.
5506f32e7eSjoerg   const CFGBlock *Succ = *(Entry->succ_begin());
5606f32e7eSjoerg 
5706f32e7eSjoerg   // Construct an edge representing the starting location in the callee.
5806f32e7eSjoerg   BlockEdge Loc(Entry, Succ, calleeCtx);
5906f32e7eSjoerg 
6006f32e7eSjoerg   ProgramStateRef state = Pred->getState();
6106f32e7eSjoerg 
6206f32e7eSjoerg   // Construct a new node, notify checkers that analysis of the function has
6306f32e7eSjoerg   // begun, and add the resultant nodes to the worklist.
6406f32e7eSjoerg   bool isNew;
6506f32e7eSjoerg   ExplodedNode *Node = G.getNode(Loc, state, false, &isNew);
6606f32e7eSjoerg   Node->addPredecessor(Pred, G);
6706f32e7eSjoerg   if (isNew) {
6806f32e7eSjoerg     ExplodedNodeSet DstBegin;
6906f32e7eSjoerg     processBeginOfFunction(BC, Node, DstBegin, Loc);
7006f32e7eSjoerg     Engine.enqueue(DstBegin);
7106f32e7eSjoerg   }
7206f32e7eSjoerg }
7306f32e7eSjoerg 
7406f32e7eSjoerg // Find the last statement on the path to the exploded node and the
7506f32e7eSjoerg // corresponding Block.
7606f32e7eSjoerg static std::pair<const Stmt*,
getLastStmt(const ExplodedNode * Node)7706f32e7eSjoerg                  const CFGBlock*> getLastStmt(const ExplodedNode *Node) {
7806f32e7eSjoerg   const Stmt *S = nullptr;
7906f32e7eSjoerg   const CFGBlock *Blk = nullptr;
8006f32e7eSjoerg   const StackFrameContext *SF = Node->getStackFrame();
8106f32e7eSjoerg 
8206f32e7eSjoerg   // Back up through the ExplodedGraph until we reach a statement node in this
8306f32e7eSjoerg   // stack frame.
8406f32e7eSjoerg   while (Node) {
8506f32e7eSjoerg     const ProgramPoint &PP = Node->getLocation();
8606f32e7eSjoerg 
8706f32e7eSjoerg     if (PP.getStackFrame() == SF) {
8806f32e7eSjoerg       if (Optional<StmtPoint> SP = PP.getAs<StmtPoint>()) {
8906f32e7eSjoerg         S = SP->getStmt();
9006f32e7eSjoerg         break;
9106f32e7eSjoerg       } else if (Optional<CallExitEnd> CEE = PP.getAs<CallExitEnd>()) {
9206f32e7eSjoerg         S = CEE->getCalleeContext()->getCallSite();
9306f32e7eSjoerg         if (S)
9406f32e7eSjoerg           break;
9506f32e7eSjoerg 
9606f32e7eSjoerg         // If there is no statement, this is an implicitly-generated call.
9706f32e7eSjoerg         // We'll walk backwards over it and then continue the loop to find
9806f32e7eSjoerg         // an actual statement.
9906f32e7eSjoerg         Optional<CallEnter> CE;
10006f32e7eSjoerg         do {
10106f32e7eSjoerg           Node = Node->getFirstPred();
10206f32e7eSjoerg           CE = Node->getLocationAs<CallEnter>();
10306f32e7eSjoerg         } while (!CE || CE->getCalleeContext() != CEE->getCalleeContext());
10406f32e7eSjoerg 
10506f32e7eSjoerg         // Continue searching the graph.
10606f32e7eSjoerg       } else if (Optional<BlockEdge> BE = PP.getAs<BlockEdge>()) {
10706f32e7eSjoerg         Blk = BE->getSrc();
10806f32e7eSjoerg       }
10906f32e7eSjoerg     } else if (Optional<CallEnter> CE = PP.getAs<CallEnter>()) {
11006f32e7eSjoerg       // If we reached the CallEnter for this function, it has no statements.
11106f32e7eSjoerg       if (CE->getCalleeContext() == SF)
11206f32e7eSjoerg         break;
11306f32e7eSjoerg     }
11406f32e7eSjoerg 
11506f32e7eSjoerg     if (Node->pred_empty())
11606f32e7eSjoerg       return std::make_pair(nullptr, nullptr);
11706f32e7eSjoerg 
11806f32e7eSjoerg     Node = *Node->pred_begin();
11906f32e7eSjoerg   }
12006f32e7eSjoerg 
12106f32e7eSjoerg   return std::make_pair(S, Blk);
12206f32e7eSjoerg }
12306f32e7eSjoerg 
12406f32e7eSjoerg /// Adjusts a return value when the called function's return type does not
12506f32e7eSjoerg /// match the caller's expression type. This can happen when a dynamic call
12606f32e7eSjoerg /// is devirtualized, and the overriding method has a covariant (more specific)
12706f32e7eSjoerg /// return type than the parent's method. For C++ objects, this means we need
12806f32e7eSjoerg /// to add base casts.
adjustReturnValue(SVal V,QualType ExpectedTy,QualType ActualTy,StoreManager & StoreMgr)12906f32e7eSjoerg static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy,
13006f32e7eSjoerg                               StoreManager &StoreMgr) {
13106f32e7eSjoerg   // For now, the only adjustments we handle apply only to locations.
13206f32e7eSjoerg   if (!V.getAs<Loc>())
13306f32e7eSjoerg     return V;
13406f32e7eSjoerg 
13506f32e7eSjoerg   // If the types already match, don't do any unnecessary work.
13606f32e7eSjoerg   ExpectedTy = ExpectedTy.getCanonicalType();
13706f32e7eSjoerg   ActualTy = ActualTy.getCanonicalType();
13806f32e7eSjoerg   if (ExpectedTy == ActualTy)
13906f32e7eSjoerg     return V;
14006f32e7eSjoerg 
14106f32e7eSjoerg   // No adjustment is needed between Objective-C pointer types.
14206f32e7eSjoerg   if (ExpectedTy->isObjCObjectPointerType() &&
14306f32e7eSjoerg       ActualTy->isObjCObjectPointerType())
14406f32e7eSjoerg     return V;
14506f32e7eSjoerg 
14606f32e7eSjoerg   // C++ object pointers may need "derived-to-base" casts.
14706f32e7eSjoerg   const CXXRecordDecl *ExpectedClass = ExpectedTy->getPointeeCXXRecordDecl();
14806f32e7eSjoerg   const CXXRecordDecl *ActualClass = ActualTy->getPointeeCXXRecordDecl();
14906f32e7eSjoerg   if (ExpectedClass && ActualClass) {
15006f32e7eSjoerg     CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
15106f32e7eSjoerg                        /*DetectVirtual=*/false);
15206f32e7eSjoerg     if (ActualClass->isDerivedFrom(ExpectedClass, Paths) &&
15306f32e7eSjoerg         !Paths.isAmbiguous(ActualTy->getCanonicalTypeUnqualified())) {
15406f32e7eSjoerg       return StoreMgr.evalDerivedToBase(V, Paths.front());
15506f32e7eSjoerg     }
15606f32e7eSjoerg   }
15706f32e7eSjoerg 
15806f32e7eSjoerg   // Unfortunately, Objective-C does not enforce that overridden methods have
15906f32e7eSjoerg   // covariant return types, so we can't assert that that never happens.
16006f32e7eSjoerg   // Be safe and return UnknownVal().
16106f32e7eSjoerg   return UnknownVal();
16206f32e7eSjoerg }
16306f32e7eSjoerg 
removeDeadOnEndOfFunction(NodeBuilderContext & BC,ExplodedNode * Pred,ExplodedNodeSet & Dst)16406f32e7eSjoerg void ExprEngine::removeDeadOnEndOfFunction(NodeBuilderContext& BC,
16506f32e7eSjoerg                                            ExplodedNode *Pred,
16606f32e7eSjoerg                                            ExplodedNodeSet &Dst) {
16706f32e7eSjoerg   // Find the last statement in the function and the corresponding basic block.
16806f32e7eSjoerg   const Stmt *LastSt = nullptr;
16906f32e7eSjoerg   const CFGBlock *Blk = nullptr;
17006f32e7eSjoerg   std::tie(LastSt, Blk) = getLastStmt(Pred);
17106f32e7eSjoerg   if (!Blk || !LastSt) {
17206f32e7eSjoerg     Dst.Add(Pred);
17306f32e7eSjoerg     return;
17406f32e7eSjoerg   }
17506f32e7eSjoerg 
17606f32e7eSjoerg   // Here, we destroy the current location context. We use the current
17706f32e7eSjoerg   // function's entire body as a diagnostic statement, with which the program
17806f32e7eSjoerg   // point will be associated. However, we only want to use LastStmt as a
17906f32e7eSjoerg   // reference for what to clean up if it's a ReturnStmt; otherwise, everything
18006f32e7eSjoerg   // is dead.
18106f32e7eSjoerg   SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);
18206f32e7eSjoerg   const LocationContext *LCtx = Pred->getLocationContext();
18306f32e7eSjoerg   removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt), LCtx,
18406f32e7eSjoerg              LCtx->getAnalysisDeclContext()->getBody(),
18506f32e7eSjoerg              ProgramPoint::PostStmtPurgeDeadSymbolsKind);
18606f32e7eSjoerg }
18706f32e7eSjoerg 
wasDifferentDeclUsedForInlining(CallEventRef<> Call,const StackFrameContext * calleeCtx)18806f32e7eSjoerg static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call,
18906f32e7eSjoerg     const StackFrameContext *calleeCtx) {
19006f32e7eSjoerg   const Decl *RuntimeCallee = calleeCtx->getDecl();
19106f32e7eSjoerg   const Decl *StaticDecl = Call->getDecl();
19206f32e7eSjoerg   assert(RuntimeCallee);
19306f32e7eSjoerg   if (!StaticDecl)
19406f32e7eSjoerg     return true;
19506f32e7eSjoerg   return RuntimeCallee->getCanonicalDecl() != StaticDecl->getCanonicalDecl();
19606f32e7eSjoerg }
19706f32e7eSjoerg 
19806f32e7eSjoerg /// The call exit is simulated with a sequence of nodes, which occur between
19906f32e7eSjoerg /// CallExitBegin and CallExitEnd. The following operations occur between the
20006f32e7eSjoerg /// two program points:
20106f32e7eSjoerg /// 1. CallExitBegin (triggers the start of call exit sequence)
20206f32e7eSjoerg /// 2. Bind the return value
20306f32e7eSjoerg /// 3. Run Remove dead bindings to clean up the dead symbols from the callee.
20406f32e7eSjoerg /// 4. CallExitEnd (switch to the caller context)
20506f32e7eSjoerg /// 5. PostStmt<CallExpr>
processCallExit(ExplodedNode * CEBNode)20606f32e7eSjoerg void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
20706f32e7eSjoerg   // Step 1 CEBNode was generated before the call.
20806f32e7eSjoerg   PrettyStackTraceLocationContext CrashInfo(CEBNode->getLocationContext());
20906f32e7eSjoerg   const StackFrameContext *calleeCtx = CEBNode->getStackFrame();
21006f32e7eSjoerg 
21106f32e7eSjoerg   // The parent context might not be a stack frame, so make sure we
21206f32e7eSjoerg   // look up the first enclosing stack frame.
21306f32e7eSjoerg   const StackFrameContext *callerCtx =
21406f32e7eSjoerg     calleeCtx->getParent()->getStackFrame();
21506f32e7eSjoerg 
21606f32e7eSjoerg   const Stmt *CE = calleeCtx->getCallSite();
21706f32e7eSjoerg   ProgramStateRef state = CEBNode->getState();
21806f32e7eSjoerg   // Find the last statement in the function and the corresponding basic block.
21906f32e7eSjoerg   const Stmt *LastSt = nullptr;
22006f32e7eSjoerg   const CFGBlock *Blk = nullptr;
22106f32e7eSjoerg   std::tie(LastSt, Blk) = getLastStmt(CEBNode);
22206f32e7eSjoerg 
22306f32e7eSjoerg   // Generate a CallEvent /before/ cleaning the state, so that we can get the
22406f32e7eSjoerg   // correct value for 'this' (if necessary).
22506f32e7eSjoerg   CallEventManager &CEMgr = getStateManager().getCallEventManager();
22606f32e7eSjoerg   CallEventRef<> Call = CEMgr.getCaller(calleeCtx, state);
22706f32e7eSjoerg 
22806f32e7eSjoerg   // Step 2: generate node with bound return value: CEBNode -> BindedRetNode.
22906f32e7eSjoerg 
23006f32e7eSjoerg   // If the callee returns an expression, bind its value to CallExpr.
23106f32e7eSjoerg   if (CE) {
23206f32e7eSjoerg     if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
23306f32e7eSjoerg       const LocationContext *LCtx = CEBNode->getLocationContext();
23406f32e7eSjoerg       SVal V = state->getSVal(RS, LCtx);
23506f32e7eSjoerg 
23606f32e7eSjoerg       // Ensure that the return type matches the type of the returned Expr.
23706f32e7eSjoerg       if (wasDifferentDeclUsedForInlining(Call, calleeCtx)) {
23806f32e7eSjoerg         QualType ReturnedTy =
23906f32e7eSjoerg           CallEvent::getDeclaredResultType(calleeCtx->getDecl());
24006f32e7eSjoerg         if (!ReturnedTy.isNull()) {
24106f32e7eSjoerg           if (const Expr *Ex = dyn_cast<Expr>(CE)) {
24206f32e7eSjoerg             V = adjustReturnValue(V, Ex->getType(), ReturnedTy,
24306f32e7eSjoerg                                   getStoreManager());
24406f32e7eSjoerg           }
24506f32e7eSjoerg         }
24606f32e7eSjoerg       }
24706f32e7eSjoerg 
24806f32e7eSjoerg       state = state->BindExpr(CE, callerCtx, V);
24906f32e7eSjoerg     }
25006f32e7eSjoerg 
25106f32e7eSjoerg     // Bind the constructed object value to CXXConstructExpr.
25206f32e7eSjoerg     if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
25306f32e7eSjoerg       loc::MemRegionVal This =
25406f32e7eSjoerg         svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);
25506f32e7eSjoerg       SVal ThisV = state->getSVal(This);
25606f32e7eSjoerg       ThisV = state->getSVal(ThisV.castAs<Loc>());
25706f32e7eSjoerg       state = state->BindExpr(CCE, callerCtx, ThisV);
25806f32e7eSjoerg     }
25906f32e7eSjoerg 
26006f32e7eSjoerg     if (const auto *CNE = dyn_cast<CXXNewExpr>(CE)) {
26106f32e7eSjoerg       // We are currently evaluating a CXXNewAllocator CFGElement. It takes a
26206f32e7eSjoerg       // while to reach the actual CXXNewExpr element from here, so keep the
26306f32e7eSjoerg       // region for later use.
26406f32e7eSjoerg       // Additionally cast the return value of the inlined operator new
26506f32e7eSjoerg       // (which is of type 'void *') to the correct object type.
26606f32e7eSjoerg       SVal AllocV = state->getSVal(CNE, callerCtx);
26706f32e7eSjoerg       AllocV = svalBuilder.evalCast(
26806f32e7eSjoerg           AllocV, CNE->getType(),
26906f32e7eSjoerg           getContext().getPointerType(getContext().VoidTy));
27006f32e7eSjoerg 
27106f32e7eSjoerg       state = addObjectUnderConstruction(state, CNE, calleeCtx->getParent(),
27206f32e7eSjoerg                                          AllocV);
27306f32e7eSjoerg     }
27406f32e7eSjoerg   }
27506f32e7eSjoerg 
27606f32e7eSjoerg   // Step 3: BindedRetNode -> CleanedNodes
27706f32e7eSjoerg   // If we can find a statement and a block in the inlined function, run remove
27806f32e7eSjoerg   // dead bindings before returning from the call. This is important to ensure
27906f32e7eSjoerg   // that we report the issues such as leaks in the stack contexts in which
28006f32e7eSjoerg   // they occurred.
28106f32e7eSjoerg   ExplodedNodeSet CleanedNodes;
28206f32e7eSjoerg   if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
28306f32e7eSjoerg     static SimpleProgramPointTag retValBind("ExprEngine", "Bind Return Value");
28406f32e7eSjoerg     PostStmt Loc(LastSt, calleeCtx, &retValBind);
28506f32e7eSjoerg     bool isNew;
28606f32e7eSjoerg     ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
28706f32e7eSjoerg     BindedRetNode->addPredecessor(CEBNode, G);
28806f32e7eSjoerg     if (!isNew)
28906f32e7eSjoerg       return;
29006f32e7eSjoerg 
29106f32e7eSjoerg     NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
29206f32e7eSjoerg     currBldrCtx = &Ctx;
29306f32e7eSjoerg     // Here, we call the Symbol Reaper with 0 statement and callee location
29406f32e7eSjoerg     // context, telling it to clean up everything in the callee's context
29506f32e7eSjoerg     // (and its children). We use the callee's function body as a diagnostic
29606f32e7eSjoerg     // statement, with which the program point will be associated.
29706f32e7eSjoerg     removeDead(BindedRetNode, CleanedNodes, nullptr, calleeCtx,
29806f32e7eSjoerg                calleeCtx->getAnalysisDeclContext()->getBody(),
29906f32e7eSjoerg                ProgramPoint::PostStmtPurgeDeadSymbolsKind);
30006f32e7eSjoerg     currBldrCtx = nullptr;
30106f32e7eSjoerg   } else {
30206f32e7eSjoerg     CleanedNodes.Add(CEBNode);
30306f32e7eSjoerg   }
30406f32e7eSjoerg 
30506f32e7eSjoerg   for (ExplodedNodeSet::iterator I = CleanedNodes.begin(),
30606f32e7eSjoerg                                  E = CleanedNodes.end(); I != E; ++I) {
30706f32e7eSjoerg 
30806f32e7eSjoerg     // Step 4: Generate the CallExit and leave the callee's context.
30906f32e7eSjoerg     // CleanedNodes -> CEENode
31006f32e7eSjoerg     CallExitEnd Loc(calleeCtx, callerCtx);
31106f32e7eSjoerg     bool isNew;
31206f32e7eSjoerg     ProgramStateRef CEEState = (*I == CEBNode) ? state : (*I)->getState();
31306f32e7eSjoerg 
31406f32e7eSjoerg     ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew);
31506f32e7eSjoerg     CEENode->addPredecessor(*I, G);
31606f32e7eSjoerg     if (!isNew)
31706f32e7eSjoerg       return;
31806f32e7eSjoerg 
31906f32e7eSjoerg     // Step 5: Perform the post-condition check of the CallExpr and enqueue the
32006f32e7eSjoerg     // result onto the work list.
32106f32e7eSjoerg     // CEENode -> Dst -> WorkList
32206f32e7eSjoerg     NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), CEENode);
32306f32e7eSjoerg     SaveAndRestore<const NodeBuilderContext*> NBCSave(currBldrCtx,
32406f32e7eSjoerg         &Ctx);
32506f32e7eSjoerg     SaveAndRestore<unsigned> CBISave(currStmtIdx, calleeCtx->getIndex());
32606f32e7eSjoerg 
32706f32e7eSjoerg     CallEventRef<> UpdatedCall = Call.cloneWithState(CEEState);
32806f32e7eSjoerg 
32906f32e7eSjoerg     ExplodedNodeSet DstPostCall;
330*13fbcb42Sjoerg     if (llvm::isa_and_nonnull<CXXNewExpr>(CE)) {
33106f32e7eSjoerg       ExplodedNodeSet DstPostPostCallCallback;
33206f32e7eSjoerg       getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback,
33306f32e7eSjoerg                                                  CEENode, *UpdatedCall, *this,
33406f32e7eSjoerg                                                  /*wasInlined=*/true);
335*13fbcb42Sjoerg       for (ExplodedNode *I : DstPostPostCallCallback) {
33606f32e7eSjoerg         getCheckerManager().runCheckersForNewAllocator(
337*13fbcb42Sjoerg             cast<CXXAllocatorCall>(*UpdatedCall), DstPostCall, I, *this,
33806f32e7eSjoerg             /*wasInlined=*/true);
33906f32e7eSjoerg       }
34006f32e7eSjoerg     } else {
34106f32e7eSjoerg       getCheckerManager().runCheckersForPostCall(DstPostCall, CEENode,
34206f32e7eSjoerg                                                  *UpdatedCall, *this,
34306f32e7eSjoerg                                                  /*wasInlined=*/true);
34406f32e7eSjoerg     }
34506f32e7eSjoerg     ExplodedNodeSet Dst;
34606f32e7eSjoerg     if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
34706f32e7eSjoerg       getCheckerManager().runCheckersForPostObjCMessage(Dst, DstPostCall, *Msg,
34806f32e7eSjoerg                                                         *this,
34906f32e7eSjoerg                                                         /*wasInlined=*/true);
35006f32e7eSjoerg     } else if (CE &&
35106f32e7eSjoerg                !(isa<CXXNewExpr>(CE) && // Called when visiting CXXNewExpr.
35206f32e7eSjoerg                  AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {
35306f32e7eSjoerg       getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
35406f32e7eSjoerg                                                  *this, /*wasInlined=*/true);
35506f32e7eSjoerg     } else {
35606f32e7eSjoerg       Dst.insert(DstPostCall);
35706f32e7eSjoerg     }
35806f32e7eSjoerg 
35906f32e7eSjoerg     // Enqueue the next element in the block.
36006f32e7eSjoerg     for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end();
36106f32e7eSjoerg                                    PSI != PSE; ++PSI) {
36206f32e7eSjoerg       Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(),
36306f32e7eSjoerg                                     calleeCtx->getIndex()+1);
36406f32e7eSjoerg     }
36506f32e7eSjoerg   }
36606f32e7eSjoerg }
36706f32e7eSjoerg 
isSmall(AnalysisDeclContext * ADC) const36806f32e7eSjoerg bool ExprEngine::isSmall(AnalysisDeclContext *ADC) const {
36906f32e7eSjoerg   // When there are no branches in the function, it means that there's no
37006f32e7eSjoerg   // exponential complexity introduced by inlining such function.
37106f32e7eSjoerg   // Such functions also don't trigger various fundamental problems
37206f32e7eSjoerg   // with our inlining mechanism, such as the problem of
37306f32e7eSjoerg   // inlined defensive checks. Hence isLinear().
37406f32e7eSjoerg   const CFG *Cfg = ADC->getCFG();
37506f32e7eSjoerg   return Cfg->isLinear() || Cfg->size() <= AMgr.options.AlwaysInlineSize;
37606f32e7eSjoerg }
37706f32e7eSjoerg 
isLarge(AnalysisDeclContext * ADC) const37806f32e7eSjoerg bool ExprEngine::isLarge(AnalysisDeclContext *ADC) const {
37906f32e7eSjoerg   const CFG *Cfg = ADC->getCFG();
38006f32e7eSjoerg   return Cfg->size() >= AMgr.options.MinCFGSizeTreatFunctionsAsLarge;
38106f32e7eSjoerg }
38206f32e7eSjoerg 
isHuge(AnalysisDeclContext * ADC) const38306f32e7eSjoerg bool ExprEngine::isHuge(AnalysisDeclContext *ADC) const {
38406f32e7eSjoerg   const CFG *Cfg = ADC->getCFG();
38506f32e7eSjoerg   return Cfg->getNumBlockIDs() > AMgr.options.MaxInlinableSize;
38606f32e7eSjoerg }
38706f32e7eSjoerg 
examineStackFrames(const Decl * D,const LocationContext * LCtx,bool & IsRecursive,unsigned & StackDepth)38806f32e7eSjoerg void ExprEngine::examineStackFrames(const Decl *D, const LocationContext *LCtx,
38906f32e7eSjoerg                                bool &IsRecursive, unsigned &StackDepth) {
39006f32e7eSjoerg   IsRecursive = false;
39106f32e7eSjoerg   StackDepth = 0;
39206f32e7eSjoerg 
39306f32e7eSjoerg   while (LCtx) {
39406f32e7eSjoerg     if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LCtx)) {
39506f32e7eSjoerg       const Decl *DI = SFC->getDecl();
39606f32e7eSjoerg 
39706f32e7eSjoerg       // Mark recursive (and mutually recursive) functions and always count
39806f32e7eSjoerg       // them when measuring the stack depth.
39906f32e7eSjoerg       if (DI == D) {
40006f32e7eSjoerg         IsRecursive = true;
40106f32e7eSjoerg         ++StackDepth;
40206f32e7eSjoerg         LCtx = LCtx->getParent();
40306f32e7eSjoerg         continue;
40406f32e7eSjoerg       }
40506f32e7eSjoerg 
40606f32e7eSjoerg       // Do not count the small functions when determining the stack depth.
40706f32e7eSjoerg       AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
40806f32e7eSjoerg       if (!isSmall(CalleeADC))
40906f32e7eSjoerg         ++StackDepth;
41006f32e7eSjoerg     }
41106f32e7eSjoerg     LCtx = LCtx->getParent();
41206f32e7eSjoerg   }
41306f32e7eSjoerg }
41406f32e7eSjoerg 
41506f32e7eSjoerg // The GDM component containing the dynamic dispatch bifurcation info. When
41606f32e7eSjoerg // the exact type of the receiver is not known, we want to explore both paths -
41706f32e7eSjoerg // one on which we do inline it and the other one on which we don't. This is
41806f32e7eSjoerg // done to ensure we do not drop coverage.
41906f32e7eSjoerg // This is the map from the receiver region to a bool, specifying either we
42006f32e7eSjoerg // consider this region's information precise or not along the given path.
42106f32e7eSjoerg namespace {
42206f32e7eSjoerg   enum DynamicDispatchMode {
42306f32e7eSjoerg     DynamicDispatchModeInlined = 1,
42406f32e7eSjoerg     DynamicDispatchModeConservative
42506f32e7eSjoerg   };
42606f32e7eSjoerg } // end anonymous namespace
42706f32e7eSjoerg 
REGISTER_MAP_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap,const MemRegion *,unsigned)42806f32e7eSjoerg REGISTER_MAP_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap,
42906f32e7eSjoerg                                const MemRegion *, unsigned)
43006f32e7eSjoerg 
43106f32e7eSjoerg bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
43206f32e7eSjoerg                             NodeBuilder &Bldr, ExplodedNode *Pred,
43306f32e7eSjoerg                             ProgramStateRef State) {
43406f32e7eSjoerg   assert(D);
43506f32e7eSjoerg 
43606f32e7eSjoerg   const LocationContext *CurLC = Pred->getLocationContext();
43706f32e7eSjoerg   const StackFrameContext *CallerSFC = CurLC->getStackFrame();
43806f32e7eSjoerg   const LocationContext *ParentOfCallee = CallerSFC;
43906f32e7eSjoerg   if (Call.getKind() == CE_Block &&
44006f32e7eSjoerg       !cast<BlockCall>(Call).isConversionFromLambda()) {
44106f32e7eSjoerg     const BlockDataRegion *BR = cast<BlockCall>(Call).getBlockRegion();
44206f32e7eSjoerg     assert(BR && "If we have the block definition we should have its region");
44306f32e7eSjoerg     AnalysisDeclContext *BlockCtx = AMgr.getAnalysisDeclContext(D);
44406f32e7eSjoerg     ParentOfCallee = BlockCtx->getBlockInvocationContext(CallerSFC,
44506f32e7eSjoerg                                                          cast<BlockDecl>(D),
44606f32e7eSjoerg                                                          BR);
44706f32e7eSjoerg   }
44806f32e7eSjoerg 
44906f32e7eSjoerg   // This may be NULL, but that's fine.
45006f32e7eSjoerg   const Expr *CallE = Call.getOriginExpr();
45106f32e7eSjoerg 
45206f32e7eSjoerg   // Construct a new stack frame for the callee.
45306f32e7eSjoerg   AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
45406f32e7eSjoerg   const StackFrameContext *CalleeSFC =
45506f32e7eSjoerg       CalleeADC->getStackFrame(ParentOfCallee, CallE, currBldrCtx->getBlock(),
45606f32e7eSjoerg                                currBldrCtx->blockCount(), currStmtIdx);
45706f32e7eSjoerg 
45806f32e7eSjoerg   CallEnter Loc(CallE, CalleeSFC, CurLC);
45906f32e7eSjoerg 
46006f32e7eSjoerg   // Construct a new state which contains the mapping from actual to
46106f32e7eSjoerg   // formal arguments.
46206f32e7eSjoerg   State = State->enterStackFrame(Call, CalleeSFC);
46306f32e7eSjoerg 
46406f32e7eSjoerg   bool isNew;
46506f32e7eSjoerg   if (ExplodedNode *N = G.getNode(Loc, State, false, &isNew)) {
46606f32e7eSjoerg     N->addPredecessor(Pred, G);
46706f32e7eSjoerg     if (isNew)
46806f32e7eSjoerg       Engine.getWorkList()->enqueue(N);
46906f32e7eSjoerg   }
47006f32e7eSjoerg 
47106f32e7eSjoerg   // If we decided to inline the call, the successor has been manually
47206f32e7eSjoerg   // added onto the work list so remove it from the node builder.
47306f32e7eSjoerg   Bldr.takeNodes(Pred);
47406f32e7eSjoerg 
47506f32e7eSjoerg   NumInlinedCalls++;
47606f32e7eSjoerg   Engine.FunctionSummaries->bumpNumTimesInlined(D);
47706f32e7eSjoerg 
47806f32e7eSjoerg   // Mark the decl as visited.
47906f32e7eSjoerg   if (VisitedCallees)
48006f32e7eSjoerg     VisitedCallees->insert(D);
48106f32e7eSjoerg 
48206f32e7eSjoerg   return true;
48306f32e7eSjoerg }
48406f32e7eSjoerg 
getInlineFailedState(ProgramStateRef State,const Stmt * CallE)48506f32e7eSjoerg static ProgramStateRef getInlineFailedState(ProgramStateRef State,
48606f32e7eSjoerg                                             const Stmt *CallE) {
48706f32e7eSjoerg   const void *ReplayState = State->get<ReplayWithoutInlining>();
48806f32e7eSjoerg   if (!ReplayState)
48906f32e7eSjoerg     return nullptr;
49006f32e7eSjoerg 
49106f32e7eSjoerg   assert(ReplayState == CallE && "Backtracked to the wrong call.");
49206f32e7eSjoerg   (void)CallE;
49306f32e7eSjoerg 
49406f32e7eSjoerg   return State->remove<ReplayWithoutInlining>();
49506f32e7eSjoerg }
49606f32e7eSjoerg 
VisitCallExpr(const CallExpr * CE,ExplodedNode * Pred,ExplodedNodeSet & dst)49706f32e7eSjoerg void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
49806f32e7eSjoerg                                ExplodedNodeSet &dst) {
49906f32e7eSjoerg   // Perform the previsit of the CallExpr.
50006f32e7eSjoerg   ExplodedNodeSet dstPreVisit;
50106f32e7eSjoerg   getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this);
50206f32e7eSjoerg 
50306f32e7eSjoerg   // Get the call in its initial state. We use this as a template to perform
50406f32e7eSjoerg   // all the checks.
50506f32e7eSjoerg   CallEventManager &CEMgr = getStateManager().getCallEventManager();
50606f32e7eSjoerg   CallEventRef<> CallTemplate
50706f32e7eSjoerg     = CEMgr.getSimpleCall(CE, Pred->getState(), Pred->getLocationContext());
50806f32e7eSjoerg 
50906f32e7eSjoerg   // Evaluate the function call.  We try each of the checkers
51006f32e7eSjoerg   // to see if the can evaluate the function call.
51106f32e7eSjoerg   ExplodedNodeSet dstCallEvaluated;
51206f32e7eSjoerg   for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
51306f32e7eSjoerg        I != E; ++I) {
51406f32e7eSjoerg     evalCall(dstCallEvaluated, *I, *CallTemplate);
51506f32e7eSjoerg   }
51606f32e7eSjoerg 
51706f32e7eSjoerg   // Finally, perform the post-condition check of the CallExpr and store
51806f32e7eSjoerg   // the created nodes in 'Dst'.
51906f32e7eSjoerg   // Note that if the call was inlined, dstCallEvaluated will be empty.
52006f32e7eSjoerg   // The post-CallExpr check will occur in processCallExit.
52106f32e7eSjoerg   getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE,
52206f32e7eSjoerg                                              *this);
52306f32e7eSjoerg }
52406f32e7eSjoerg 
finishArgumentConstruction(ProgramStateRef State,const CallEvent & Call)52506f32e7eSjoerg ProgramStateRef ExprEngine::finishArgumentConstruction(ProgramStateRef State,
52606f32e7eSjoerg                                                        const CallEvent &Call) {
52706f32e7eSjoerg   const Expr *E = Call.getOriginExpr();
52806f32e7eSjoerg   // FIXME: Constructors to placement arguments of operator new
52906f32e7eSjoerg   // are not supported yet.
53006f32e7eSjoerg   if (!E || isa<CXXNewExpr>(E))
53106f32e7eSjoerg     return State;
53206f32e7eSjoerg 
53306f32e7eSjoerg   const LocationContext *LC = Call.getLocationContext();
53406f32e7eSjoerg   for (unsigned CallI = 0, CallN = Call.getNumArgs(); CallI != CallN; ++CallI) {
53506f32e7eSjoerg     unsigned I = Call.getASTArgumentIndex(CallI);
53606f32e7eSjoerg     if (Optional<SVal> V =
53706f32e7eSjoerg             getObjectUnderConstruction(State, {E, I}, LC)) {
53806f32e7eSjoerg       SVal VV = *V;
53906f32e7eSjoerg       (void)VV;
54006f32e7eSjoerg       assert(cast<VarRegion>(VV.castAs<loc::MemRegionVal>().getRegion())
54106f32e7eSjoerg                  ->getStackFrame()->getParent()
54206f32e7eSjoerg                  ->getStackFrame() == LC->getStackFrame());
54306f32e7eSjoerg       State = finishObjectConstruction(State, {E, I}, LC);
54406f32e7eSjoerg     }
54506f32e7eSjoerg   }
54606f32e7eSjoerg 
54706f32e7eSjoerg   return State;
54806f32e7eSjoerg }
54906f32e7eSjoerg 
finishArgumentConstruction(ExplodedNodeSet & Dst,ExplodedNode * Pred,const CallEvent & Call)55006f32e7eSjoerg void ExprEngine::finishArgumentConstruction(ExplodedNodeSet &Dst,
55106f32e7eSjoerg                                             ExplodedNode *Pred,
55206f32e7eSjoerg                                             const CallEvent &Call) {
55306f32e7eSjoerg   ProgramStateRef State = Pred->getState();
55406f32e7eSjoerg   ProgramStateRef CleanedState = finishArgumentConstruction(State, Call);
55506f32e7eSjoerg   if (CleanedState == State) {
55606f32e7eSjoerg     Dst.insert(Pred);
55706f32e7eSjoerg     return;
55806f32e7eSjoerg   }
55906f32e7eSjoerg 
56006f32e7eSjoerg   const Expr *E = Call.getOriginExpr();
56106f32e7eSjoerg   const LocationContext *LC = Call.getLocationContext();
56206f32e7eSjoerg   NodeBuilder B(Pred, Dst, *currBldrCtx);
56306f32e7eSjoerg   static SimpleProgramPointTag Tag("ExprEngine",
56406f32e7eSjoerg                                    "Finish argument construction");
56506f32e7eSjoerg   PreStmt PP(E, LC, &Tag);
56606f32e7eSjoerg   B.generateNode(PP, CleanedState, Pred);
56706f32e7eSjoerg }
56806f32e7eSjoerg 
evalCall(ExplodedNodeSet & Dst,ExplodedNode * Pred,const CallEvent & Call)56906f32e7eSjoerg void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
57006f32e7eSjoerg                           const CallEvent &Call) {
57106f32e7eSjoerg   // WARNING: At this time, the state attached to 'Call' may be older than the
57206f32e7eSjoerg   // state in 'Pred'. This is a minor optimization since CheckerManager will
57306f32e7eSjoerg   // use an updated CallEvent instance when calling checkers, but if 'Call' is
57406f32e7eSjoerg   // ever used directly in this function all callers should be updated to pass
57506f32e7eSjoerg   // the most recent state. (It is probably not worth doing the work here since
57606f32e7eSjoerg   // for some callers this will not be necessary.)
57706f32e7eSjoerg 
57806f32e7eSjoerg   // Run any pre-call checks using the generic call interface.
57906f32e7eSjoerg   ExplodedNodeSet dstPreVisit;
58006f32e7eSjoerg   getCheckerManager().runCheckersForPreCall(dstPreVisit, Pred,
58106f32e7eSjoerg                                             Call, *this);
58206f32e7eSjoerg 
58306f32e7eSjoerg   // Actually evaluate the function call.  We try each of the checkers
58406f32e7eSjoerg   // to see if the can evaluate the function call, and get a callback at
58506f32e7eSjoerg   // defaultEvalCall if all of them fail.
58606f32e7eSjoerg   ExplodedNodeSet dstCallEvaluated;
58706f32e7eSjoerg   getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, dstPreVisit,
588*13fbcb42Sjoerg                                              Call, *this, EvalCallOptions());
58906f32e7eSjoerg 
59006f32e7eSjoerg   // If there were other constructors called for object-type arguments
59106f32e7eSjoerg   // of this call, clean them up.
59206f32e7eSjoerg   ExplodedNodeSet dstArgumentCleanup;
593*13fbcb42Sjoerg   for (ExplodedNode *I : dstCallEvaluated)
59406f32e7eSjoerg     finishArgumentConstruction(dstArgumentCleanup, I, Call);
59506f32e7eSjoerg 
596*13fbcb42Sjoerg   ExplodedNodeSet dstPostCall;
597*13fbcb42Sjoerg   getCheckerManager().runCheckersForPostCall(dstPostCall, dstArgumentCleanup,
59806f32e7eSjoerg                                              Call, *this);
599*13fbcb42Sjoerg 
600*13fbcb42Sjoerg   // Escaping symbols conjured during invalidating the regions above.
601*13fbcb42Sjoerg   // Note that, for inlined calls the nodes were put back into the worklist,
602*13fbcb42Sjoerg   // so we can assume that every node belongs to a conservative call at this
603*13fbcb42Sjoerg   // point.
604*13fbcb42Sjoerg 
605*13fbcb42Sjoerg   // Run pointerEscape callback with the newly conjured symbols.
606*13fbcb42Sjoerg   SmallVector<std::pair<SVal, SVal>, 8> Escaped;
607*13fbcb42Sjoerg   for (ExplodedNode *I : dstPostCall) {
608*13fbcb42Sjoerg     NodeBuilder B(I, Dst, *currBldrCtx);
609*13fbcb42Sjoerg     ProgramStateRef State = I->getState();
610*13fbcb42Sjoerg     Escaped.clear();
611*13fbcb42Sjoerg     {
612*13fbcb42Sjoerg       unsigned Arg = -1;
613*13fbcb42Sjoerg       for (const ParmVarDecl *PVD : Call.parameters()) {
614*13fbcb42Sjoerg         ++Arg;
615*13fbcb42Sjoerg         QualType ParamTy = PVD->getType();
616*13fbcb42Sjoerg         if (ParamTy.isNull() ||
617*13fbcb42Sjoerg             (!ParamTy->isPointerType() && !ParamTy->isReferenceType()))
618*13fbcb42Sjoerg           continue;
619*13fbcb42Sjoerg         QualType Pointee = ParamTy->getPointeeType();
620*13fbcb42Sjoerg         if (Pointee.isConstQualified() || Pointee->isVoidType())
621*13fbcb42Sjoerg           continue;
622*13fbcb42Sjoerg         if (const MemRegion *MR = Call.getArgSVal(Arg).getAsRegion())
623*13fbcb42Sjoerg           Escaped.emplace_back(loc::MemRegionVal(MR), State->getSVal(MR, Pointee));
624*13fbcb42Sjoerg       }
625*13fbcb42Sjoerg     }
626*13fbcb42Sjoerg 
627*13fbcb42Sjoerg     State = processPointerEscapedOnBind(State, Escaped, I->getLocationContext(),
628*13fbcb42Sjoerg                                         PSK_EscapeOutParameters, &Call);
629*13fbcb42Sjoerg 
630*13fbcb42Sjoerg     if (State == I->getState())
631*13fbcb42Sjoerg       Dst.insert(I);
632*13fbcb42Sjoerg     else
633*13fbcb42Sjoerg       B.generateNode(I->getLocation(), State, I);
634*13fbcb42Sjoerg   }
63506f32e7eSjoerg }
63606f32e7eSjoerg 
bindReturnValue(const CallEvent & Call,const LocationContext * LCtx,ProgramStateRef State)63706f32e7eSjoerg ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
63806f32e7eSjoerg                                             const LocationContext *LCtx,
63906f32e7eSjoerg                                             ProgramStateRef State) {
64006f32e7eSjoerg   const Expr *E = Call.getOriginExpr();
64106f32e7eSjoerg   if (!E)
64206f32e7eSjoerg     return State;
64306f32e7eSjoerg 
64406f32e7eSjoerg   // Some method families have known return values.
64506f32e7eSjoerg   if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
64606f32e7eSjoerg     switch (Msg->getMethodFamily()) {
64706f32e7eSjoerg     default:
64806f32e7eSjoerg       break;
64906f32e7eSjoerg     case OMF_autorelease:
65006f32e7eSjoerg     case OMF_retain:
65106f32e7eSjoerg     case OMF_self: {
65206f32e7eSjoerg       // These methods return their receivers.
65306f32e7eSjoerg       return State->BindExpr(E, LCtx, Msg->getReceiverSVal());
65406f32e7eSjoerg     }
65506f32e7eSjoerg     }
65606f32e7eSjoerg   } else if (const CXXConstructorCall *C = dyn_cast<CXXConstructorCall>(&Call)){
65706f32e7eSjoerg     SVal ThisV = C->getCXXThisVal();
65806f32e7eSjoerg     ThisV = State->getSVal(ThisV.castAs<Loc>());
65906f32e7eSjoerg     return State->BindExpr(E, LCtx, ThisV);
66006f32e7eSjoerg   }
66106f32e7eSjoerg 
66206f32e7eSjoerg   SVal R;
66306f32e7eSjoerg   QualType ResultTy = Call.getResultType();
66406f32e7eSjoerg   unsigned Count = currBldrCtx->blockCount();
66506f32e7eSjoerg   if (auto RTC = getCurrentCFGElement().getAs<CFGCXXRecordTypedCall>()) {
66606f32e7eSjoerg     // Conjure a temporary if the function returns an object by value.
66706f32e7eSjoerg     SVal Target;
66806f32e7eSjoerg     assert(RTC->getStmt() == Call.getOriginExpr());
66906f32e7eSjoerg     EvalCallOptions CallOpts; // FIXME: We won't really need those.
67006f32e7eSjoerg     std::tie(State, Target) =
671*13fbcb42Sjoerg         handleConstructionContext(Call.getOriginExpr(), State, LCtx,
67206f32e7eSjoerg                                   RTC->getConstructionContext(), CallOpts);
67306f32e7eSjoerg     const MemRegion *TargetR = Target.getAsRegion();
67406f32e7eSjoerg     assert(TargetR);
67506f32e7eSjoerg     // Invalidate the region so that it didn't look uninitialized. If this is
67606f32e7eSjoerg     // a field or element constructor, we do not want to invalidate
67706f32e7eSjoerg     // the whole structure. Pointer escape is meaningless because
67806f32e7eSjoerg     // the structure is a product of conservative evaluation
67906f32e7eSjoerg     // and therefore contains nothing interesting at this point.
68006f32e7eSjoerg     RegionAndSymbolInvalidationTraits ITraits;
68106f32e7eSjoerg     ITraits.setTrait(TargetR,
68206f32e7eSjoerg         RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
68306f32e7eSjoerg     State = State->invalidateRegions(TargetR, E, Count, LCtx,
68406f32e7eSjoerg                                      /* CausesPointerEscape=*/false, nullptr,
68506f32e7eSjoerg                                      &Call, &ITraits);
68606f32e7eSjoerg 
68706f32e7eSjoerg     R = State->getSVal(Target.castAs<Loc>(), E->getType());
68806f32e7eSjoerg   } else {
68906f32e7eSjoerg     // Conjure a symbol if the return value is unknown.
69006f32e7eSjoerg 
69106f32e7eSjoerg     // See if we need to conjure a heap pointer instead of
69206f32e7eSjoerg     // a regular unknown pointer.
693*13fbcb42Sjoerg     const auto *CNE = dyn_cast<CXXNewExpr>(E);
694*13fbcb42Sjoerg     if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
695*13fbcb42Sjoerg       R = svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count);
696*13fbcb42Sjoerg       const MemRegion *MR = R.getAsRegion()->StripCasts();
697*13fbcb42Sjoerg 
698*13fbcb42Sjoerg       // Store the extent of the allocated object(s).
699*13fbcb42Sjoerg       SVal ElementCount;
700*13fbcb42Sjoerg       if (const Expr *SizeExpr = CNE->getArraySize().getValueOr(nullptr)) {
701*13fbcb42Sjoerg         ElementCount = State->getSVal(SizeExpr, LCtx);
702*13fbcb42Sjoerg       } else {
703*13fbcb42Sjoerg         ElementCount = svalBuilder.makeIntVal(1, /*IsUnsigned=*/true);
70406f32e7eSjoerg       }
70506f32e7eSjoerg 
706*13fbcb42Sjoerg       SVal ElementSize = getElementExtent(CNE->getAllocatedType(), svalBuilder);
707*13fbcb42Sjoerg 
708*13fbcb42Sjoerg       SVal Size =
709*13fbcb42Sjoerg           svalBuilder.evalBinOp(State, BO_Mul, ElementCount, ElementSize,
710*13fbcb42Sjoerg                                 svalBuilder.getArrayIndexType());
711*13fbcb42Sjoerg 
712*13fbcb42Sjoerg       State = setDynamicExtent(State, MR, Size.castAs<DefinedOrUnknownSVal>(),
713*13fbcb42Sjoerg                                svalBuilder);
714*13fbcb42Sjoerg     } else {
715*13fbcb42Sjoerg       R = svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
716*13fbcb42Sjoerg     }
71706f32e7eSjoerg   }
71806f32e7eSjoerg   return State->BindExpr(E, LCtx, R);
71906f32e7eSjoerg }
72006f32e7eSjoerg 
72106f32e7eSjoerg // Conservatively evaluate call by invalidating regions and binding
72206f32e7eSjoerg // a conjured return value.
conservativeEvalCall(const CallEvent & Call,NodeBuilder & Bldr,ExplodedNode * Pred,ProgramStateRef State)72306f32e7eSjoerg void ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
724*13fbcb42Sjoerg                                       ExplodedNode *Pred, ProgramStateRef State) {
72506f32e7eSjoerg   State = Call.invalidateRegions(currBldrCtx->blockCount(), State);
72606f32e7eSjoerg   State = bindReturnValue(Call, Pred->getLocationContext(), State);
72706f32e7eSjoerg 
72806f32e7eSjoerg   // And make the result node.
72906f32e7eSjoerg   Bldr.generateNode(Call.getProgramPoint(), State, Pred);
73006f32e7eSjoerg }
73106f32e7eSjoerg 
73206f32e7eSjoerg ExprEngine::CallInlinePolicy
mayInlineCallKind(const CallEvent & Call,const ExplodedNode * Pred,AnalyzerOptions & Opts,const EvalCallOptions & CallOpts)73306f32e7eSjoerg ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
73406f32e7eSjoerg                               AnalyzerOptions &Opts,
735*13fbcb42Sjoerg                               const EvalCallOptions &CallOpts) {
73606f32e7eSjoerg   const LocationContext *CurLC = Pred->getLocationContext();
73706f32e7eSjoerg   const StackFrameContext *CallerSFC = CurLC->getStackFrame();
73806f32e7eSjoerg   switch (Call.getKind()) {
73906f32e7eSjoerg   case CE_Function:
74006f32e7eSjoerg   case CE_Block:
74106f32e7eSjoerg     break;
74206f32e7eSjoerg   case CE_CXXMember:
74306f32e7eSjoerg   case CE_CXXMemberOperator:
74406f32e7eSjoerg     if (!Opts.mayInlineCXXMemberFunction(CIMK_MemberFunctions))
74506f32e7eSjoerg       return CIP_DisallowedAlways;
74606f32e7eSjoerg     break;
74706f32e7eSjoerg   case CE_CXXConstructor: {
74806f32e7eSjoerg     if (!Opts.mayInlineCXXMemberFunction(CIMK_Constructors))
74906f32e7eSjoerg       return CIP_DisallowedAlways;
75006f32e7eSjoerg 
75106f32e7eSjoerg     const CXXConstructorCall &Ctor = cast<CXXConstructorCall>(Call);
75206f32e7eSjoerg 
75306f32e7eSjoerg     const CXXConstructExpr *CtorExpr = Ctor.getOriginExpr();
75406f32e7eSjoerg 
75506f32e7eSjoerg     auto CCE = getCurrentCFGElement().getAs<CFGConstructor>();
75606f32e7eSjoerg     const ConstructionContext *CC = CCE ? CCE->getConstructionContext()
75706f32e7eSjoerg                                         : nullptr;
75806f32e7eSjoerg 
759*13fbcb42Sjoerg     if (llvm::isa_and_nonnull<NewAllocatedObjectConstructionContext>(CC) &&
76006f32e7eSjoerg         !Opts.MayInlineCXXAllocator)
76106f32e7eSjoerg       return CIP_DisallowedOnce;
76206f32e7eSjoerg 
76306f32e7eSjoerg     // FIXME: We don't handle constructors or destructors for arrays properly.
76406f32e7eSjoerg     // Even once we do, we still need to be careful about implicitly-generated
76506f32e7eSjoerg     // initializers for array fields in default move/copy constructors.
76606f32e7eSjoerg     // We still allow construction into ElementRegion targets when they don't
76706f32e7eSjoerg     // represent array elements.
76806f32e7eSjoerg     if (CallOpts.IsArrayCtorOrDtor)
76906f32e7eSjoerg       return CIP_DisallowedOnce;
77006f32e7eSjoerg 
77106f32e7eSjoerg     // Inlining constructors requires including initializers in the CFG.
77206f32e7eSjoerg     const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
77306f32e7eSjoerg     assert(ADC->getCFGBuildOptions().AddInitializers && "No CFG initializers");
77406f32e7eSjoerg     (void)ADC;
77506f32e7eSjoerg 
77606f32e7eSjoerg     // If the destructor is trivial, it's always safe to inline the constructor.
77706f32e7eSjoerg     if (Ctor.getDecl()->getParent()->hasTrivialDestructor())
77806f32e7eSjoerg       break;
77906f32e7eSjoerg 
78006f32e7eSjoerg     // For other types, only inline constructors if destructor inlining is
78106f32e7eSjoerg     // also enabled.
78206f32e7eSjoerg     if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
78306f32e7eSjoerg       return CIP_DisallowedAlways;
78406f32e7eSjoerg 
78506f32e7eSjoerg     if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete) {
78606f32e7eSjoerg       // If we don't handle temporary destructors, we shouldn't inline
78706f32e7eSjoerg       // their constructors.
78806f32e7eSjoerg       if (CallOpts.IsTemporaryCtorOrDtor &&
78906f32e7eSjoerg           !Opts.ShouldIncludeTemporaryDtorsInCFG)
79006f32e7eSjoerg         return CIP_DisallowedOnce;
79106f32e7eSjoerg 
79206f32e7eSjoerg       // If we did not find the correct this-region, it would be pointless
79306f32e7eSjoerg       // to inline the constructor. Instead we will simply invalidate
79406f32e7eSjoerg       // the fake temporary target.
79506f32e7eSjoerg       if (CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion)
79606f32e7eSjoerg         return CIP_DisallowedOnce;
79706f32e7eSjoerg 
79806f32e7eSjoerg       // If the temporary is lifetime-extended by binding it to a reference-type
79906f32e7eSjoerg       // field within an aggregate, automatic destructors don't work properly.
80006f32e7eSjoerg       if (CallOpts.IsTemporaryLifetimeExtendedViaAggregate)
80106f32e7eSjoerg         return CIP_DisallowedOnce;
80206f32e7eSjoerg     }
80306f32e7eSjoerg 
80406f32e7eSjoerg     break;
80506f32e7eSjoerg   }
806*13fbcb42Sjoerg   case CE_CXXInheritedConstructor: {
807*13fbcb42Sjoerg     // This doesn't really increase the cost of inlining ever, because
808*13fbcb42Sjoerg     // the stack frame of the inherited constructor is trivial.
809*13fbcb42Sjoerg     return CIP_Allowed;
810*13fbcb42Sjoerg   }
81106f32e7eSjoerg   case CE_CXXDestructor: {
81206f32e7eSjoerg     if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
81306f32e7eSjoerg       return CIP_DisallowedAlways;
81406f32e7eSjoerg 
81506f32e7eSjoerg     // Inlining destructors requires building the CFG correctly.
81606f32e7eSjoerg     const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
81706f32e7eSjoerg     assert(ADC->getCFGBuildOptions().AddImplicitDtors && "No CFG destructors");
81806f32e7eSjoerg     (void)ADC;
81906f32e7eSjoerg 
82006f32e7eSjoerg     // FIXME: We don't handle constructors or destructors for arrays properly.
82106f32e7eSjoerg     if (CallOpts.IsArrayCtorOrDtor)
82206f32e7eSjoerg       return CIP_DisallowedOnce;
82306f32e7eSjoerg 
82406f32e7eSjoerg     // Allow disabling temporary destructor inlining with a separate option.
82506f32e7eSjoerg     if (CallOpts.IsTemporaryCtorOrDtor &&
82606f32e7eSjoerg         !Opts.MayInlineCXXTemporaryDtors)
82706f32e7eSjoerg       return CIP_DisallowedOnce;
82806f32e7eSjoerg 
82906f32e7eSjoerg     // If we did not find the correct this-region, it would be pointless
83006f32e7eSjoerg     // to inline the destructor. Instead we will simply invalidate
83106f32e7eSjoerg     // the fake temporary target.
83206f32e7eSjoerg     if (CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion)
83306f32e7eSjoerg       return CIP_DisallowedOnce;
83406f32e7eSjoerg     break;
83506f32e7eSjoerg   }
836*13fbcb42Sjoerg   case CE_CXXDeallocator:
837*13fbcb42Sjoerg     LLVM_FALLTHROUGH;
83806f32e7eSjoerg   case CE_CXXAllocator:
83906f32e7eSjoerg     if (Opts.MayInlineCXXAllocator)
84006f32e7eSjoerg       break;
84106f32e7eSjoerg     // Do not inline allocators until we model deallocators.
84206f32e7eSjoerg     // This is unfortunate, but basically necessary for smart pointers and such.
84306f32e7eSjoerg     return CIP_DisallowedAlways;
84406f32e7eSjoerg   case CE_ObjCMessage:
84506f32e7eSjoerg     if (!Opts.MayInlineObjCMethod)
84606f32e7eSjoerg       return CIP_DisallowedAlways;
84706f32e7eSjoerg     if (!(Opts.getIPAMode() == IPAK_DynamicDispatch ||
84806f32e7eSjoerg           Opts.getIPAMode() == IPAK_DynamicDispatchBifurcate))
84906f32e7eSjoerg       return CIP_DisallowedAlways;
85006f32e7eSjoerg     break;
85106f32e7eSjoerg   }
85206f32e7eSjoerg 
85306f32e7eSjoerg   return CIP_Allowed;
85406f32e7eSjoerg }
85506f32e7eSjoerg 
85606f32e7eSjoerg /// Returns true if the given C++ class contains a member with the given name.
hasMember(const ASTContext & Ctx,const CXXRecordDecl * RD,StringRef Name)85706f32e7eSjoerg static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD,
85806f32e7eSjoerg                       StringRef Name) {
85906f32e7eSjoerg   const IdentifierInfo &II = Ctx.Idents.get(Name);
860*13fbcb42Sjoerg   return RD->hasMemberName(Ctx.DeclarationNames.getIdentifier(&II));
86106f32e7eSjoerg }
86206f32e7eSjoerg 
86306f32e7eSjoerg /// Returns true if the given C++ class is a container or iterator.
86406f32e7eSjoerg ///
86506f32e7eSjoerg /// Our heuristic for this is whether it contains a method named 'begin()' or a
86606f32e7eSjoerg /// nested type named 'iterator' or 'iterator_category'.
isContainerClass(const ASTContext & Ctx,const CXXRecordDecl * RD)86706f32e7eSjoerg static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD) {
86806f32e7eSjoerg   return hasMember(Ctx, RD, "begin") ||
86906f32e7eSjoerg          hasMember(Ctx, RD, "iterator") ||
87006f32e7eSjoerg          hasMember(Ctx, RD, "iterator_category");
87106f32e7eSjoerg }
87206f32e7eSjoerg 
87306f32e7eSjoerg /// Returns true if the given function refers to a method of a C++ container
87406f32e7eSjoerg /// or iterator.
87506f32e7eSjoerg ///
87606f32e7eSjoerg /// We generally do a poor job modeling most containers right now, and might
87706f32e7eSjoerg /// prefer not to inline their methods.
isContainerMethod(const ASTContext & Ctx,const FunctionDecl * FD)87806f32e7eSjoerg static bool isContainerMethod(const ASTContext &Ctx,
87906f32e7eSjoerg                               const FunctionDecl *FD) {
88006f32e7eSjoerg   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
88106f32e7eSjoerg     return isContainerClass(Ctx, MD->getParent());
88206f32e7eSjoerg   return false;
88306f32e7eSjoerg }
88406f32e7eSjoerg 
88506f32e7eSjoerg /// Returns true if the given function is the destructor of a class named
88606f32e7eSjoerg /// "shared_ptr".
isCXXSharedPtrDtor(const FunctionDecl * FD)88706f32e7eSjoerg static bool isCXXSharedPtrDtor(const FunctionDecl *FD) {
88806f32e7eSjoerg   const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(FD);
88906f32e7eSjoerg   if (!Dtor)
89006f32e7eSjoerg     return false;
89106f32e7eSjoerg 
89206f32e7eSjoerg   const CXXRecordDecl *RD = Dtor->getParent();
89306f32e7eSjoerg   if (const IdentifierInfo *II = RD->getDeclName().getAsIdentifierInfo())
89406f32e7eSjoerg     if (II->isStr("shared_ptr"))
89506f32e7eSjoerg         return true;
89606f32e7eSjoerg 
89706f32e7eSjoerg   return false;
89806f32e7eSjoerg }
89906f32e7eSjoerg 
90006f32e7eSjoerg /// Returns true if the function in \p CalleeADC may be inlined in general.
90106f32e7eSjoerg ///
90206f32e7eSjoerg /// This checks static properties of the function, such as its signature and
90306f32e7eSjoerg /// CFG, to determine whether the analyzer should ever consider inlining it,
90406f32e7eSjoerg /// in any context.
mayInlineDecl(AnalysisDeclContext * CalleeADC) const90506f32e7eSjoerg bool ExprEngine::mayInlineDecl(AnalysisDeclContext *CalleeADC) const {
90606f32e7eSjoerg   AnalyzerOptions &Opts = AMgr.getAnalyzerOptions();
90706f32e7eSjoerg   // FIXME: Do not inline variadic calls.
90806f32e7eSjoerg   if (CallEvent::isVariadic(CalleeADC->getDecl()))
90906f32e7eSjoerg     return false;
91006f32e7eSjoerg 
91106f32e7eSjoerg   // Check certain C++-related inlining policies.
91206f32e7eSjoerg   ASTContext &Ctx = CalleeADC->getASTContext();
91306f32e7eSjoerg   if (Ctx.getLangOpts().CPlusPlus) {
91406f32e7eSjoerg     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->getDecl())) {
91506f32e7eSjoerg       // Conditionally control the inlining of template functions.
91606f32e7eSjoerg       if (!Opts.MayInlineTemplateFunctions)
91706f32e7eSjoerg         if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
91806f32e7eSjoerg           return false;
91906f32e7eSjoerg 
92006f32e7eSjoerg       // Conditionally control the inlining of C++ standard library functions.
92106f32e7eSjoerg       if (!Opts.MayInlineCXXStandardLibrary)
92206f32e7eSjoerg         if (Ctx.getSourceManager().isInSystemHeader(FD->getLocation()))
92306f32e7eSjoerg           if (AnalysisDeclContext::isInStdNamespace(FD))
92406f32e7eSjoerg             return false;
92506f32e7eSjoerg 
92606f32e7eSjoerg       // Conditionally control the inlining of methods on objects that look
92706f32e7eSjoerg       // like C++ containers.
92806f32e7eSjoerg       if (!Opts.MayInlineCXXContainerMethods)
92906f32e7eSjoerg         if (!AMgr.isInCodeFile(FD->getLocation()))
93006f32e7eSjoerg           if (isContainerMethod(Ctx, FD))
93106f32e7eSjoerg             return false;
93206f32e7eSjoerg 
93306f32e7eSjoerg       // Conditionally control the inlining of the destructor of C++ shared_ptr.
93406f32e7eSjoerg       // We don't currently do a good job modeling shared_ptr because we can't
93506f32e7eSjoerg       // see the reference count, so treating as opaque is probably the best
93606f32e7eSjoerg       // idea.
93706f32e7eSjoerg       if (!Opts.MayInlineCXXSharedPtrDtor)
93806f32e7eSjoerg         if (isCXXSharedPtrDtor(FD))
93906f32e7eSjoerg           return false;
94006f32e7eSjoerg     }
94106f32e7eSjoerg   }
94206f32e7eSjoerg 
94306f32e7eSjoerg   // It is possible that the CFG cannot be constructed.
94406f32e7eSjoerg   // Be safe, and check if the CalleeCFG is valid.
94506f32e7eSjoerg   const CFG *CalleeCFG = CalleeADC->getCFG();
94606f32e7eSjoerg   if (!CalleeCFG)
94706f32e7eSjoerg     return false;
94806f32e7eSjoerg 
94906f32e7eSjoerg   // Do not inline large functions.
95006f32e7eSjoerg   if (isHuge(CalleeADC))
95106f32e7eSjoerg     return false;
95206f32e7eSjoerg 
95306f32e7eSjoerg   // It is possible that the live variables analysis cannot be
95406f32e7eSjoerg   // run.  If so, bail out.
95506f32e7eSjoerg   if (!CalleeADC->getAnalysis<RelaxedLiveVariables>())
95606f32e7eSjoerg     return false;
95706f32e7eSjoerg 
95806f32e7eSjoerg   return true;
95906f32e7eSjoerg }
96006f32e7eSjoerg 
shouldInlineCall(const CallEvent & Call,const Decl * D,const ExplodedNode * Pred,const EvalCallOptions & CallOpts)96106f32e7eSjoerg bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
96206f32e7eSjoerg                                   const ExplodedNode *Pred,
96306f32e7eSjoerg                                   const EvalCallOptions &CallOpts) {
96406f32e7eSjoerg   if (!D)
96506f32e7eSjoerg     return false;
96606f32e7eSjoerg 
96706f32e7eSjoerg   AnalysisManager &AMgr = getAnalysisManager();
96806f32e7eSjoerg   AnalyzerOptions &Opts = AMgr.options;
96906f32e7eSjoerg   AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
97006f32e7eSjoerg   AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);
97106f32e7eSjoerg 
97206f32e7eSjoerg   // The auto-synthesized bodies are essential to inline as they are
97306f32e7eSjoerg   // usually small and commonly used. Note: we should do this check early on to
97406f32e7eSjoerg   // ensure we always inline these calls.
97506f32e7eSjoerg   if (CalleeADC->isBodyAutosynthesized())
97606f32e7eSjoerg     return true;
97706f32e7eSjoerg 
97806f32e7eSjoerg   if (!AMgr.shouldInlineCall())
97906f32e7eSjoerg     return false;
98006f32e7eSjoerg 
98106f32e7eSjoerg   // Check if this function has been marked as non-inlinable.
98206f32e7eSjoerg   Optional<bool> MayInline = Engine.FunctionSummaries->mayInline(D);
98306f32e7eSjoerg   if (MayInline.hasValue()) {
98406f32e7eSjoerg     if (!MayInline.getValue())
98506f32e7eSjoerg       return false;
98606f32e7eSjoerg 
98706f32e7eSjoerg   } else {
98806f32e7eSjoerg     // We haven't actually checked the static properties of this function yet.
98906f32e7eSjoerg     // Do that now, and record our decision in the function summaries.
99006f32e7eSjoerg     if (mayInlineDecl(CalleeADC)) {
99106f32e7eSjoerg       Engine.FunctionSummaries->markMayInline(D);
99206f32e7eSjoerg     } else {
99306f32e7eSjoerg       Engine.FunctionSummaries->markShouldNotInline(D);
99406f32e7eSjoerg       return false;
99506f32e7eSjoerg     }
99606f32e7eSjoerg   }
99706f32e7eSjoerg 
99806f32e7eSjoerg   // Check if we should inline a call based on its kind.
99906f32e7eSjoerg   // FIXME: this checks both static and dynamic properties of the call, which
100006f32e7eSjoerg   // means we're redoing a bit of work that could be cached in the function
100106f32e7eSjoerg   // summary.
100206f32e7eSjoerg   CallInlinePolicy CIP = mayInlineCallKind(Call, Pred, Opts, CallOpts);
100306f32e7eSjoerg   if (CIP != CIP_Allowed) {
100406f32e7eSjoerg     if (CIP == CIP_DisallowedAlways) {
100506f32e7eSjoerg       assert(!MayInline.hasValue() || MayInline.getValue());
100606f32e7eSjoerg       Engine.FunctionSummaries->markShouldNotInline(D);
100706f32e7eSjoerg     }
100806f32e7eSjoerg     return false;
100906f32e7eSjoerg   }
101006f32e7eSjoerg 
101106f32e7eSjoerg   // Do not inline if recursive or we've reached max stack frame count.
101206f32e7eSjoerg   bool IsRecursive = false;
101306f32e7eSjoerg   unsigned StackDepth = 0;
101406f32e7eSjoerg   examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
101506f32e7eSjoerg   if ((StackDepth >= Opts.InlineMaxStackDepth) &&
101606f32e7eSjoerg       (!isSmall(CalleeADC) || IsRecursive))
101706f32e7eSjoerg     return false;
101806f32e7eSjoerg 
101906f32e7eSjoerg   // Do not inline large functions too many times.
102006f32e7eSjoerg   if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
102106f32e7eSjoerg        Opts.MaxTimesInlineLarge) &&
102206f32e7eSjoerg       isLarge(CalleeADC)) {
102306f32e7eSjoerg     NumReachedInlineCountMax++;
102406f32e7eSjoerg     return false;
102506f32e7eSjoerg   }
102606f32e7eSjoerg 
102706f32e7eSjoerg   if (HowToInline == Inline_Minimal && (!isSmall(CalleeADC) || IsRecursive))
102806f32e7eSjoerg     return false;
102906f32e7eSjoerg 
103006f32e7eSjoerg   return true;
103106f32e7eSjoerg }
103206f32e7eSjoerg 
isTrivialObjectAssignment(const CallEvent & Call)103306f32e7eSjoerg static bool isTrivialObjectAssignment(const CallEvent &Call) {
103406f32e7eSjoerg   const CXXInstanceCall *ICall = dyn_cast<CXXInstanceCall>(&Call);
103506f32e7eSjoerg   if (!ICall)
103606f32e7eSjoerg     return false;
103706f32e7eSjoerg 
103806f32e7eSjoerg   const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(ICall->getDecl());
103906f32e7eSjoerg   if (!MD)
104006f32e7eSjoerg     return false;
104106f32e7eSjoerg   if (!(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()))
104206f32e7eSjoerg     return false;
104306f32e7eSjoerg 
104406f32e7eSjoerg   return MD->isTrivial();
104506f32e7eSjoerg }
104606f32e7eSjoerg 
defaultEvalCall(NodeBuilder & Bldr,ExplodedNode * Pred,const CallEvent & CallTemplate,const EvalCallOptions & CallOpts)104706f32e7eSjoerg void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred,
104806f32e7eSjoerg                                  const CallEvent &CallTemplate,
104906f32e7eSjoerg                                  const EvalCallOptions &CallOpts) {
105006f32e7eSjoerg   // Make sure we have the most recent state attached to the call.
105106f32e7eSjoerg   ProgramStateRef State = Pred->getState();
105206f32e7eSjoerg   CallEventRef<> Call = CallTemplate.cloneWithState(State);
105306f32e7eSjoerg 
105406f32e7eSjoerg   // Special-case trivial assignment operators.
105506f32e7eSjoerg   if (isTrivialObjectAssignment(*Call)) {
105606f32e7eSjoerg     performTrivialCopy(Bldr, Pred, *Call);
105706f32e7eSjoerg     return;
105806f32e7eSjoerg   }
105906f32e7eSjoerg 
106006f32e7eSjoerg   // Try to inline the call.
106106f32e7eSjoerg   // The origin expression here is just used as a kind of checksum;
106206f32e7eSjoerg   // this should still be safe even for CallEvents that don't come from exprs.
106306f32e7eSjoerg   const Expr *E = Call->getOriginExpr();
106406f32e7eSjoerg 
106506f32e7eSjoerg   ProgramStateRef InlinedFailedState = getInlineFailedState(State, E);
106606f32e7eSjoerg   if (InlinedFailedState) {
106706f32e7eSjoerg     // If we already tried once and failed, make sure we don't retry later.
106806f32e7eSjoerg     State = InlinedFailedState;
106906f32e7eSjoerg   } else {
107006f32e7eSjoerg     RuntimeDefinition RD = Call->getRuntimeDefinition();
107106f32e7eSjoerg     const Decl *D = RD.getDecl();
107206f32e7eSjoerg     if (shouldInlineCall(*Call, D, Pred, CallOpts)) {
107306f32e7eSjoerg       if (RD.mayHaveOtherDefinitions()) {
107406f32e7eSjoerg         AnalyzerOptions &Options = getAnalysisManager().options;
107506f32e7eSjoerg 
107606f32e7eSjoerg         // Explore with and without inlining the call.
107706f32e7eSjoerg         if (Options.getIPAMode() == IPAK_DynamicDispatchBifurcate) {
107806f32e7eSjoerg           BifurcateCall(RD.getDispatchRegion(), *Call, D, Bldr, Pred);
107906f32e7eSjoerg           return;
108006f32e7eSjoerg         }
108106f32e7eSjoerg 
108206f32e7eSjoerg         // Don't inline if we're not in any dynamic dispatch mode.
108306f32e7eSjoerg         if (Options.getIPAMode() != IPAK_DynamicDispatch) {
108406f32e7eSjoerg           conservativeEvalCall(*Call, Bldr, Pred, State);
108506f32e7eSjoerg           return;
108606f32e7eSjoerg         }
108706f32e7eSjoerg       }
108806f32e7eSjoerg 
108906f32e7eSjoerg       // We are not bifurcating and we do have a Decl, so just inline.
109006f32e7eSjoerg       if (inlineCall(*Call, D, Bldr, Pred, State))
109106f32e7eSjoerg         return;
109206f32e7eSjoerg     }
109306f32e7eSjoerg   }
109406f32e7eSjoerg 
109506f32e7eSjoerg   // If we can't inline it, handle the return value and invalidate the regions.
109606f32e7eSjoerg   conservativeEvalCall(*Call, Bldr, Pred, State);
109706f32e7eSjoerg }
109806f32e7eSjoerg 
BifurcateCall(const MemRegion * BifurReg,const CallEvent & Call,const Decl * D,NodeBuilder & Bldr,ExplodedNode * Pred)109906f32e7eSjoerg void ExprEngine::BifurcateCall(const MemRegion *BifurReg,
110006f32e7eSjoerg                                const CallEvent &Call, const Decl *D,
110106f32e7eSjoerg                                NodeBuilder &Bldr, ExplodedNode *Pred) {
110206f32e7eSjoerg   assert(BifurReg);
110306f32e7eSjoerg   BifurReg = BifurReg->StripCasts();
110406f32e7eSjoerg 
110506f32e7eSjoerg   // Check if we've performed the split already - note, we only want
110606f32e7eSjoerg   // to split the path once per memory region.
110706f32e7eSjoerg   ProgramStateRef State = Pred->getState();
110806f32e7eSjoerg   const unsigned *BState =
110906f32e7eSjoerg                         State->get<DynamicDispatchBifurcationMap>(BifurReg);
111006f32e7eSjoerg   if (BState) {
111106f32e7eSjoerg     // If we are on "inline path", keep inlining if possible.
111206f32e7eSjoerg     if (*BState == DynamicDispatchModeInlined)
111306f32e7eSjoerg       if (inlineCall(Call, D, Bldr, Pred, State))
111406f32e7eSjoerg         return;
111506f32e7eSjoerg     // If inline failed, or we are on the path where we assume we
111606f32e7eSjoerg     // don't have enough info about the receiver to inline, conjure the
111706f32e7eSjoerg     // return value and invalidate the regions.
111806f32e7eSjoerg     conservativeEvalCall(Call, Bldr, Pred, State);
111906f32e7eSjoerg     return;
112006f32e7eSjoerg   }
112106f32e7eSjoerg 
112206f32e7eSjoerg   // If we got here, this is the first time we process a message to this
112306f32e7eSjoerg   // region, so split the path.
112406f32e7eSjoerg   ProgramStateRef IState =
112506f32e7eSjoerg       State->set<DynamicDispatchBifurcationMap>(BifurReg,
112606f32e7eSjoerg                                                DynamicDispatchModeInlined);
112706f32e7eSjoerg   inlineCall(Call, D, Bldr, Pred, IState);
112806f32e7eSjoerg 
112906f32e7eSjoerg   ProgramStateRef NoIState =
113006f32e7eSjoerg       State->set<DynamicDispatchBifurcationMap>(BifurReg,
113106f32e7eSjoerg                                                DynamicDispatchModeConservative);
113206f32e7eSjoerg   conservativeEvalCall(Call, Bldr, Pred, NoIState);
113306f32e7eSjoerg 
113406f32e7eSjoerg   NumOfDynamicDispatchPathSplits++;
113506f32e7eSjoerg }
113606f32e7eSjoerg 
VisitReturnStmt(const ReturnStmt * RS,ExplodedNode * Pred,ExplodedNodeSet & Dst)113706f32e7eSjoerg void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
113806f32e7eSjoerg                                  ExplodedNodeSet &Dst) {
113906f32e7eSjoerg   ExplodedNodeSet dstPreVisit;
114006f32e7eSjoerg   getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this);
114106f32e7eSjoerg 
114206f32e7eSjoerg   StmtNodeBuilder B(dstPreVisit, Dst, *currBldrCtx);
114306f32e7eSjoerg 
114406f32e7eSjoerg   if (RS->getRetValue()) {
114506f32e7eSjoerg     for (ExplodedNodeSet::iterator it = dstPreVisit.begin(),
114606f32e7eSjoerg                                   ei = dstPreVisit.end(); it != ei; ++it) {
114706f32e7eSjoerg       B.generateNode(RS, *it, (*it)->getState());
114806f32e7eSjoerg     }
114906f32e7eSjoerg   }
115006f32e7eSjoerg }
1151