ExprEngineCallAndReturn.cpp revision 580cd17f256259f39a382e967173f34d68e73859
1659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===//
243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//                     The LLVM Compiler Infrastructure
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This file is distributed under the University of Illinois Open Source
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// License. See LICENSE.TXT for details.
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//===----------------------------------------------------------------------===//
943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//  This file defines ExprEngine's support for calls and returns.
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//===----------------------------------------------------------------------===//
1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define DEBUG_TYPE "ExprEngine"
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/Analysis/Analyses/LiveVariables.h"
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/StaticAnalyzer/Core/CheckerManager.h"
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/AST/DeclCXX.h"
2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/AST/ParentMap.h"
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "llvm/ADT/SmallSet.h"
2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "llvm/ADT/Statistic.h"
2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "llvm/Support/SaveAndRestore.h"
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenusing namespace clang;
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenusing namespace ento;
2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenSTATISTIC(NumOfDynamicDispatchPathSplits,
3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  "The # of times we split the path due to imprecise dynamic dispatch info");
311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
32c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comSTATISTIC(NumInlinedCalls,
33ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  "The # of times we inlined a call");
349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
3571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgvoid ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
3671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Get the entry block in the CFG of the callee.
3743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const StackFrameContext *calleeCtx = CE.getCalleeContext();
38659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  const CFG *CalleeCFG = calleeCtx->getCFG();
39659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  const CFGBlock *Entry = &(CalleeCFG->getEntry());
40a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
41659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  // Validate the CFG.
42659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  assert(Entry->empty());
43ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  assert(Entry->succ_size() == 1);
44a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Get the solitary sucessor.
4643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const CFGBlock *Succ = *(Entry->succ_begin());
4768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
4868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // Construct an edge representing the starting location in the callee.
49c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  BlockEdge Loc(Entry, Succ, calleeCtx);
5068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
51c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  ProgramStateRef state = Pred->getState();
52c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
53bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Construct a new node and add it to the worklist.
54bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  bool isNew;
5568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  ExplodedNode *Node = G.getNode(Loc, state, false, &isNew);
5643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Node->addPredecessor(Pred, G);
5743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (isNew)
582ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org    Engine.getWorkList()->enqueue(Node);
592ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org}
602ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org
612ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org// Find the last statement on the path to the exploded node and the
6243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// corresponding Block.
6343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic std::pair<const Stmt*,
6443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                 const CFGBlock*> getLastStmt(const ExplodedNode *Node) {
6543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const Stmt *S = 0;
6643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const StackFrameContext *SF =
6743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          Node->getLocation().getLocationContext()->getCurrentStackFrame();
688bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org
698bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  // Back up through the ExplodedGraph until we reach a statement node in this
708bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  // stack frame.
717be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  while (Node) {
7241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    const ProgramPoint &PP = Node->getLocation();
7341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
741510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    if (PP.getLocationContext()->getCurrentStackFrame() == SF) {
7543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) {
7643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        S = SP->getStmt();
7743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
7841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org      } else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&PP)) {
7941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org        S = CEE->getCalleeContext()->getCallSite();
807be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        if (S)
815a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org          break;
8243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
838bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org        // If there is no statement, this is an implicitly-generated call.
84cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        // We'll walk backwards over it and then continue the loop to find
85cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        // an actual statement.
86cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        const CallEnter *CE;
87cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        do {
88a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          Node = Node->getFirstPred();
89a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          CE = Node->getLocationAs<CallEnter>();
907be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        } while (!CE || CE->getCalleeContext() != CEE->getCalleeContext());
917be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
927be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        // Continue searching the graph.
937be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org      }
947be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    } else if (const CallEnter *CE = dyn_cast<CallEnter>(&PP)) {
95355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      // If we reached the CallEnter for this function, it has no statements.
96355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      if (CE->getCalleeContext() == SF)
97355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        break;
98355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    }
99355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
100355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    Node = *Node->pred_begin();
101355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  }
102355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
10341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  const CFGBlock *Blk = 0;
10441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org  if (S) {
1057be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    // Now, get the enclosing basic block.
1067be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    while (Node && Node->pred_size() >=1 ) {
10741044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org      const ProgramPoint &PP = Node->getLocation();
108cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      if (isa<BlockEdge>(PP) &&
109cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org          (PP.getLocationContext()->getCurrentStackFrame() == SF)) {
110cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        BlockEdge &EPP = cast<BlockEdge>(PP);
111cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        Blk = EPP.getDst();
112cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        break;
113cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      }
114cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      Node = *Node->pred_begin();
115355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    }
116cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  }
117cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
1185a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  return std::pair<const Stmt*, const CFGBlock*>(S, Blk);
119cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org}
12015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
12115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// The call exit is simulated with a sequence of nodes, which occur between
12215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// CallExitBegin and CallExitEnd. The following operations occur between the
12315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// two program points:
124cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// 1. CallExitBegin (triggers the start of call exit sequence)
125cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// 2. Bind the return value
12615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// 3. Run Remove dead bindings to clean up the dead symbols from the callee.
12715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// 4. CallExitEnd (switch to the caller context)
12815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org/// 5. PostStmt<CallExpr>
129355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.orgvoid ExprEngine::processCallExit(ExplodedNode *CEBNode) {
130355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // Step 1 CEBNode was generated before the call.
131cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
132a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const StackFrameContext *calleeCtx =
13341826e77311db718135ef6517b846933dfd275f3ager@chromium.org      CEBNode->getLocationContext()->getCurrentStackFrame();
134355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
13541826e77311db718135ef6517b846933dfd275f3ager@chromium.org  // The parent context might not be a stack frame, so make sure we
136a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // look up the first enclosing stack frame.
137a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const StackFrameContext *callerCtx =
1387be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    calleeCtx->getParent()->getCurrentStackFrame();
1395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const Stmt *CE = calleeCtx->getCallSite();
141355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  ProgramStateRef state = CEBNode->getState();
142355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // Find the last statement in the function and the corresponding basic block.
143355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  const Stmt *LastSt = 0;
144355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  const CFGBlock *Blk = 0;
145355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  llvm::tie(LastSt, Blk) = getLastStmt(CEBNode);
146355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
147355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // Step 2: generate node with bound return value: CEBNode -> BindedRetNode.
148355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
149355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // If the callee returns an expression, bind its value to CallExpr.
150355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  if (CE) {
151355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
152355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      const LocationContext *LCtx = CEBNode->getLocationContext();
153355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      SVal V = state->getSVal(RS, LCtx);
154355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      state = state->BindExpr(CE, callerCtx, V);
1552f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    }
156355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
157355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    // Bind the constructed object value to CXXConstructExpr.
158355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
159355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      loc::MemRegionVal This =
160355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);
1612f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      SVal ThisV = state->getSVal(This);
162355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
1632f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // If the constructed object is a prvalue, get its bindings.
164355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      // Note that we have to be careful here because constructors embedded
1652f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // in DeclStmts are not marked as lvalues.
166355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      if (!CCE->isGLValue())
167355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        if (const MemRegion *MR = ThisV.getAsRegion())
168355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org          if (isa<CXXTempObjectRegion>(MR))
169355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org            ThisV = state->getSVal(cast<Loc>(ThisV));
170355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
171355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      state = state->BindExpr(CCE, callerCtx, ThisV);
172355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    }
173355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  }
174355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
175355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // Generate a CallEvent /before/ cleaning the state, so that we can get the
176355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // correct value for 'this' (if necessary).
177355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  CallEventManager &CEMgr = getStateManager().getCallEventManager();
178355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  CallEventRef<> Call = CEMgr.getCaller(calleeCtx, state);
179355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
1800c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // Step 3: BindedRetNode -> CleanedNodes
1817be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  // If we can find a statement and a block in the inlined function, run remove
1827be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  // dead bindings before returning from the call. This is important to ensure
1837be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  // that we report the issues such as leaks in the stack contexts in which
184bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // they occurred.
1857be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  ExplodedNodeSet CleanedNodes;
1867be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
1870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    static SimpleProgramPointTag retValBind("ExprEngine : Bind Return Value");
1880c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    PostStmt Loc(LastSt, calleeCtx, &retValBind);
1890c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    bool isNew;
1900c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
1910c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    BindedRetNode->addPredecessor(CEBNode, G);
1920c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    if (!isNew)
1930c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      return;
1940c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
1950c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
1960c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    currBldrCtx = &Ctx;
197bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // Here, we call the Symbol Reaper with 0 statement and caller location
1987be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    // context, telling it to clean up everything in the callee's context
1997be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    // (and it's children). We use LastStmt as a diagnostic statement, which
2007be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    // which the PreStmtPurge Dead point will be associated.
2017be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    removeDead(BindedRetNode, CleanedNodes, 0, callerCtx, LastSt,
2027be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org               ProgramPoint::PostStmtPurgeDeadSymbolsKind);
2037be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    currBldrCtx = 0;
2047be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  } else {
2057be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    CleanedNodes.Add(CEBNode);
2067be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  }
207bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
2087be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  for (ExplodedNodeSet::iterator I = CleanedNodes.begin(),
2097be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                                 E = CleanedNodes.end(); I != E; ++I) {
2107be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
211bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // Step 4: Generate the CallExit and leave the callee's context.
2127be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    // CleanedNodes -> CEENode
2137be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    CallExitEnd Loc(calleeCtx, callerCtx);
2147be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    bool isNew;
2157be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    ProgramStateRef CEEState = (*I == CEBNode) ? state : (*I)->getState();
2167be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew);
217a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    CEENode->addPredecessor(*I, G);
218bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    if (!isNew)
219bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org      return;
220bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
2217be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    // Step 5: Perform the post-condition check of the CallExpr and enqueue the
222bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // result onto the work list.
2237be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    // CEENode -> Dst -> WorkList
2247be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), CEENode);
2257be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    SaveAndRestore<const NodeBuilderContext*> NBCSave(currBldrCtx,
2267be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        &Ctx);
2277be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    SaveAndRestore<unsigned> CBISave(currStmtIdx, calleeCtx->getIndex());
2287be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
22943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    CallEventRef<> UpdatedCall = Call.cloneWithState(CEEState);
23083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
23183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ExplodedNodeSet DstPostCall;
23283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    getCheckerManager().runCheckersForPostCall(DstPostCall, CEENode,
23383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                               *UpdatedCall, *this,
23483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                               /*WasInlined=*/true);
23583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
23683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ExplodedNodeSet Dst;
23783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
238bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org      getCheckerManager().runCheckersForPostObjCMessage(Dst, DstPostCall, *Msg,
2397d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org                                                        *this,
2405a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                                                        /*WasInlined=*/true);
2417d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    } else if (CE) {
2425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
24343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                                 *this, /*WasInlined=*/true);
24443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
24543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Dst.insert(DstPostCall);
2460c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    }
2470c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2480c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    // Enqueue the next element in the block.
2490c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end();
2500c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                   PSI != PSE; ++PSI) {
2510c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(),
2520c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                    calleeCtx->getIndex()+1);
2530c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    }
2540c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
2550c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2561044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org
2571044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.orgvoid ExprEngine::examineStackFrames(const Decl *D, const LocationContext *LCtx,
258a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                               bool &IsRecursive, unsigned &StackDepth) {
259a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  IsRecursive = false;
260a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  StackDepth = 0;
261a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
262a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (LCtx) {
263a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LCtx)) {
2647028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      const Decl *DI = SFC->getDecl();
2657028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
266ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      // Mark recursive (and mutually recursive) functions and always count
267a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // them when measuring the stack depth.
268a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (DI == D) {
269a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        IsRecursive = true;
270a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        ++StackDepth;
271a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        LCtx = LCtx->getParent();
272a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        continue;
273a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
274a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
275a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // Do not count the small functions when determining the stack depth.
276a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
277a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      const CFG *CalleeCFG = CalleeADC->getCFG();
278a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize())
279a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        ++StackDepth;
280a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
281a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    LCtx = LCtx->getParent();
282a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
2838bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org
284a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
2857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
2867028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.orgstatic bool IsInStdNamespace(const FunctionDecl *FD) {
287a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const DeclContext *DC = FD->getEnclosingNamespaceContext();
288ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
289a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!ND)
2907028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    return false;
2917028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
2920c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  while (const DeclContext *Parent = ND->getParent()) {
2930c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    if (!isa<NamespaceDecl>(Parent))
2940c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      break;
2950c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    ND = cast<NamespaceDecl>(Parent);
2960c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
2970c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2980c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  return ND->getName() == "std";
2990c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
3000c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
3010c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org// Determine if we should inline the call.
3027028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.orgbool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) {
3037028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
304a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const CFG *CalleeCFG = CalleeADC->getCFG();
305a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
306a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // It is possible that the CFG cannot be constructed.
307a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Be safe, and check if the CalleeCFG is valid.
308a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!CalleeCFG)
309a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
310a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
311a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  bool IsRecursive = false;
312a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  unsigned StackDepth = 0;
313a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
314a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if ((StackDepth >= AMgr.options.InlineMaxStackDepth) &&
315a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org       ((CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize())
316a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org         || IsRecursive))
317a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
3187028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
319a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (Engine.FunctionSummaries->hasReachedMaxBlockCount(D))
320a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
321a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
322a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (CalleeCFG->getNumBlockIDs() > AMgr.options.InlineMaxFunctionSize)
323a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
324a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
325a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Do not inline variadic calls (for now).
3267028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
327a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (BD->isVariadic())
328a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
329a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
330a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
3317028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (FD->isVariadic())
332a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
333a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
334a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
335a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (getContext().getLangOpts().CPlusPlus) {
336a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
337a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // Conditionally allow the inlining of template functions.
3383291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      if (!getAnalysisManager().options.mayInlineTemplateFunctions())
339a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
340a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          return false;
341a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
342a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // Conditionally allow the inlining of C++ standard library functions.
343a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (!getAnalysisManager().options.mayInlineCXXStandardLibrary())
344a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (getContext().getSourceManager().isInSystemHeader(FD->getLocation()))
345a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          if (IsInStdNamespace(FD))
3467028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org            return false;
3477028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    }
348a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
349a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
350a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // It is possible that the live variables analysis cannot be
351a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // run.  If so, bail out.
352a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!CalleeADC->getAnalysis<RelaxedLiveVariables>())
353a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
354a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
355a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
3567028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org}
3577028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
3587028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org/// The GDM component containing the dynamic dispatch bifurcation info. When
359a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// the exact type of the receiver is not known, we want to explore both paths -
360a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// one on which we do inline it and the other one on which we don't. This is
361a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// done to ensure we do not drop coverage.
362a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// This is the map from the receiver region to a bool, specifying either we
363a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/// consider this region's information precise or not along the given path.
364a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgnamespace clang {
365a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgnamespace ento {
366a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgenum DynamicDispatchMode { DynamicDispatchModeInlined = 1,
367a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                           DynamicDispatchModeConservative };
368a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
369a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstruct DynamicDispatchBifurcationMap {};
370a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgtypedef llvm::ImmutableMap<const MemRegion*,
371a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org                           unsigned int> DynamicDispatchBifur;
372a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgtemplate<> struct ProgramStateTrait<DynamicDispatchBifurcationMap>
373a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    :  public ProgramStatePartialTrait<DynamicDispatchBifur> {
374a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  static void *GDMIndex() { static int index; return &index; }
375a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org};
376a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
377a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}}
378a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
379a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
380a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                            NodeBuilder &Bldr, ExplodedNode *Pred,
381a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                            ProgramStateRef State) {
3827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  assert(D);
383a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
384a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const LocationContext *CurLC = Pred->getLocationContext();
385a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame();
386a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const LocationContext *ParentOfCallee = 0;
3877028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
3887028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  const AnalyzerOptions &Opts = getAnalysisManager().options;
3897028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
39083e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  // FIXME: Refactor this check into a hypothetical CallEvent::canInline.
391a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  switch (Call.getKind()) {
392a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  case CE_Function:
393a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    break;
394a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  case CE_CXXMember:
395a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  case CE_CXXMemberOperator:
396a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (!Opts.mayInlineCXXMemberFunction(CIMK_MemberFunctions))
397a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
398a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    break;
399a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  case CE_CXXConstructor: {
400a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (!Opts.mayInlineCXXMemberFunction(CIMK_Constructors))
401a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
402a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
403a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    const CXXConstructorCall &Ctor = cast<CXXConstructorCall>(Call);
404a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
405a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // FIXME: We don't handle constructors or destructors for arrays properly.
406ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    const MemRegion *Target = Ctor.getCXXThisVal().getAsRegion();
407a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (Target && isa<ElementRegion>(Target))
408a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
409a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
410a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // FIXME: This is a hack. We don't use the correct region for a new
411a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // expression, so if we inline the constructor its result will just be
412a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // thrown away. This short-term hack is tracked in <rdar://problem/12180598>
413a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // and the longer-term possible fix is discussed in PR12014.
414a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    const CXXConstructExpr *CtorExpr = Ctor.getOriginExpr();
415a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (const Stmt *Parent = CurLC->getParentMap().getParent(CtorExpr))
416a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (isa<CXXNewExpr>(Parent))
417a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return false;
418a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
419a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // Inlining constructors requires including initializers in the CFG.
420a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
421a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    assert(ADC->getCFGBuildOptions().AddInitializers && "No CFG initializers");
422a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    (void)ADC;
423a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
424a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // If the destructor is trivial, it's always safe to inline the constructor.
425a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (Ctor.getDecl()->getParent()->hasTrivialDestructor())
426a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
427a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
428a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // For other types, only inline constructors if destructor inlining is
4299259716434187c932704601f700375e53d865de8rossberg@chromium.org    // also enabled.
430a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
4319259716434187c932704601f700375e53d865de8rossberg@chromium.org      return false;
4329259716434187c932704601f700375e53d865de8rossberg@chromium.org
4339259716434187c932704601f700375e53d865de8rossberg@chromium.org    // FIXME: This is a hack. We don't handle temporary destructors
4349259716434187c932704601f700375e53d865de8rossberg@chromium.org    // right now, so we shouldn't inline their constructors.
4359259716434187c932704601f700375e53d865de8rossberg@chromium.org    if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete)
436a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (!Target || !isa<DeclRegion>(Target))
437a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return false;
4389259716434187c932704601f700375e53d865de8rossberg@chromium.org
4399259716434187c932704601f700375e53d865de8rossberg@chromium.org    break;
4409259716434187c932704601f700375e53d865de8rossberg@chromium.org  }
4419259716434187c932704601f700375e53d865de8rossberg@chromium.org  case CE_CXXDestructor: {
4429259716434187c932704601f700375e53d865de8rossberg@chromium.org    if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
4439259716434187c932704601f700375e53d865de8rossberg@chromium.org      return false;
4449259716434187c932704601f700375e53d865de8rossberg@chromium.org
4459259716434187c932704601f700375e53d865de8rossberg@chromium.org    // Inlining destructors requires building the CFG correctly.
4469259716434187c932704601f700375e53d865de8rossberg@chromium.org    const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
4479259716434187c932704601f700375e53d865de8rossberg@chromium.org    assert(ADC->getCFGBuildOptions().AddImplicitDtors && "No CFG destructors");
4489259716434187c932704601f700375e53d865de8rossberg@chromium.org    (void)ADC;
4499259716434187c932704601f700375e53d865de8rossberg@chromium.org
4509259716434187c932704601f700375e53d865de8rossberg@chromium.org    const CXXDestructorCall &Dtor = cast<CXXDestructorCall>(Call);
4519259716434187c932704601f700375e53d865de8rossberg@chromium.org
4529259716434187c932704601f700375e53d865de8rossberg@chromium.org    // FIXME: We don't handle constructors or destructors for arrays properly.
4539259716434187c932704601f700375e53d865de8rossberg@chromium.org    const MemRegion *Target = Dtor.getCXXThisVal().getAsRegion();
4549259716434187c932704601f700375e53d865de8rossberg@chromium.org    if (Target && isa<ElementRegion>(Target))
4559259716434187c932704601f700375e53d865de8rossberg@chromium.org      return false;
4569259716434187c932704601f700375e53d865de8rossberg@chromium.org
4579259716434187c932704601f700375e53d865de8rossberg@chromium.org    break;
4589259716434187c932704601f700375e53d865de8rossberg@chromium.org  }
4599259716434187c932704601f700375e53d865de8rossberg@chromium.org  case CE_CXXAllocator:
4609259716434187c932704601f700375e53d865de8rossberg@chromium.org    // Do not inline allocators until we model deallocators.
4619259716434187c932704601f700375e53d865de8rossberg@chromium.org    // This is unfortunate, but basically necessary for smart pointers and such.
4629259716434187c932704601f700375e53d865de8rossberg@chromium.org    return false;
4639259716434187c932704601f700375e53d865de8rossberg@chromium.org  case CE_Block: {
464a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    const BlockDataRegion *BR = cast<BlockCall>(Call).getBlockRegion();
465a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    assert(BR && "If we have the block definition we should have its region");
466a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    AnalysisDeclContext *BlockCtx = AMgr.getAnalysisDeclContext(D);
4673291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    ParentOfCallee = BlockCtx->getBlockInvocationContext(CallerSFC,
4688bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                                                         cast<BlockDecl>(D),
4698bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                                                         BR);
470a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    break;
471a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
472a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  case CE_ObjCMessage:
473a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (!Opts.mayInlineObjCMethod())
474a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
475a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (!(getAnalysisManager().options.IPAMode == DynamicDispatch ||
476a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          getAnalysisManager().options.IPAMode == DynamicDispatchBifurcate))
477a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
4781044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org    break;
4791044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org  }
480a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
481a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!shouldInlineDecl(D, Pred))
482a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
483a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
484a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!ParentOfCallee)
485a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ParentOfCallee = CallerSFC;
486a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
48737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // This may be NULL, but that's fine.
488a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const Expr *CallE = Call.getOriginExpr();
489a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
490a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Construct a new stack frame for the callee.
491a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
492a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  const StackFrameContext *CalleeSFC =
493a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    CalleeADC->getStackFrame(ParentOfCallee, CallE,
494a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                             currBldrCtx->getBlock(),
495a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                             currStmtIdx);
496a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
497a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  CallEnter Loc(CallE, CalleeSFC, CurLC);
498a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4998bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  // Construct a new state which contains the mapping from actual to
5008bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  // formal arguments.
5018bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  State = State->enterStackFrame(Call, CalleeSFC);
5028bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org
5038bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  bool isNew;
5048bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  if (ExplodedNode *N = G.getNode(Loc, State, false, &isNew)) {
505a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    N->addPredecessor(Pred, G);
506a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (isNew)
507a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Engine.getWorkList()->enqueue(N);
508a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
509a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
510a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // If we decided to inline the call, the successor has been manually
511a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // added onto the work list so remove it from the node builder.
512a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Bldr.takeNodes(Pred);
513a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
514a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  NumInlinedCalls++;
515a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
516a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Mark the decl as visited.
517a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (VisitedCallees)
518a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    VisitedCallees->insert(D);
519a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
520a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
521a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
522a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
523a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatic ProgramStateRef getInlineFailedState(ProgramStateRef State,
524a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                            const Stmt *CallE) {
525a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  void *ReplayState = State->get<ReplayWithoutInlining>();
526a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!ReplayState)
527a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return 0;
528a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5291044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org  assert(ReplayState == (const void*)CallE && "Backtracked to the wrong call.");
530a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  (void)CallE;
531a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
532a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return State->remove<ReplayWithoutInlining>();
53337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
53437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
53537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
53637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                               ExplodedNodeSet &dst) {
53737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Perform the previsit of the CallExpr.
53837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  ExplodedNodeSet dstPreVisit;
53937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this);
540245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org
541245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  // Get the call in its initial state. We use this as a template to perform
54237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // all the checks.
54337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  CallEventManager &CEMgr = getStateManager().getCallEventManager();
54437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  CallEventRef<> CallTemplate
545245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    = CEMgr.getSimpleCall(CE, Pred->getState(), Pred->getLocationContext());
546245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org
54737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Evaluate the function call.  We try each of the checkers
54837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // to see if the can evaluate the function call.
54937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  ExplodedNodeSet dstCallEvaluated;
55037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
55137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com       I != E; ++I) {
55237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    evalCall(dstCallEvaluated, *I, *CallTemplate);
553245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  }
554245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org
55537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Finally, perform the post-condition check of the CallExpr and store
55637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // the created nodes in 'Dst'.
55737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Note that if the call was inlined, dstCallEvaluated will be empty.
55837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // The post-CallExpr check will occur in processCallExit.
55937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE,
56037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                             *this);
56137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
56237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
56337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
56437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                          const CallEvent &Call) {
56537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // WARNING: At this time, the state attached to 'Call' may be older than the
56637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // state in 'Pred'. This is a minor optimization since CheckerManager will
56737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // use an updated CallEvent instance when calling checkers, but if 'Call' is
56837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // ever used directly in this function all callers should be updated to pass
56937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // the most recent state. (It is probably not worth doing the work here since
57037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // for some callers this will not be necessary.)
57137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
57237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Run any pre-call checks using the generic call interface.
57337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  ExplodedNodeSet dstPreVisit;
57437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  getCheckerManager().runCheckersForPreCall(dstPreVisit, Pred, Call, *this);
57537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
57637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Actually evaluate the function call.  We try each of the checkers
57737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // to see if the can evaluate the function call, and get a callback at
57837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // defaultEvalCall if all of them fail.
579245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  ExplodedNodeSet dstCallEvaluated;
580245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, dstPreVisit,
581245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                                             Call, *this);
58237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
58337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Finally, run any post-call checks.
58437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  getCheckerManager().runCheckersForPostCall(Dst, dstCallEvaluated,
5851044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org                                             Call, *this);
5861044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org}
5871044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org
588a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
589a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                            const LocationContext *LCtx,
590400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org                                            ProgramStateRef State) {
591400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org  const Expr *E = Call.getOriginExpr();
592ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  if (!E)
593ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    return State;
59437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
595a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Some method families have known return values.
596a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
597ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    switch (Msg->getMethodFamily()) {
59837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    default:
599ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org      break;
600ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    case OMF_autorelease:
601a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    case OMF_retain:
602a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    case OMF_self: {
603a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      // These methods return their receivers.
604a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      return State->BindExpr(E, LCtx, Msg->getReceiverSVal());
6054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    }
60637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    }
60737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  } else if (const CXXConstructorCall *C = dyn_cast<CXXConstructorCall>(&Call)){
60837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return State->BindExpr(E, LCtx, C->getCXXThisVal());
60937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
6103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
61137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Conjure a symbol if the return value is unknown.
61237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  QualType ResultTy = Call.getResultType();
61337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  SValBuilder &SVB = getSValBuilder();
61437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  unsigned Count = currBldrCtx->blockCount();
61537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  SVal R = SVB.conjureSymbolVal(0, E, LCtx, ResultTy, Count);
61637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  return State->BindExpr(E, LCtx, R);
61737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
61837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
61937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// Conservatively evaluate call by invalidating regions and binding
62037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// a conjured return value.
621245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.orgvoid ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
622245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                                      ExplodedNode *Pred, ProgramStateRef State) {
6238bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  State = Call.invalidateRegions(currBldrCtx->blockCount(), State);
6248bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  State = bindReturnValue(Call, Pred->getLocationContext(), State);
6257d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
6267d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  // And make the result node.
6277d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  Bldr.generateNode(Call.getProgramPoint(), State, Pred);
6287d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org}
6297d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
6307d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgvoid ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred,
6317d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org                                 const CallEvent &CallTemplate) {
6327d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  // Make sure we have the most recent state attached to the call.
6337d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  ProgramStateRef State = Pred->getState();
6347d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  CallEventRef<> Call = CallTemplate.cloneWithState(State);
635400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org
636400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org  if (!getAnalysisManager().shouldInlineCall()) {
6374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    conservativeEvalCall(*Call, Bldr, Pred, State);
63837141398d9125c021d47ceb91e2b19efd35c89ddverwaest@chromium.org    return;
639400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org  }
64037141398d9125c021d47ceb91e2b19efd35c89ddverwaest@chromium.org  // Try to inline the call.
64137141398d9125c021d47ceb91e2b19efd35c89ddverwaest@chromium.org  // The origin expression here is just used as a kind of checksum;
6427d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  // this should still be safe even for CallEvents that don't come from exprs.
6437d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  const Expr *E = Call->getOriginExpr();
6441044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org  ProgramStateRef InlinedFailedState = getInlineFailedState(State, E);
6451044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org
6461044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org  if (InlinedFailedState) {
6471044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org    // If we already tried once and failed, make sure we don't retry later.
64859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    State = InlinedFailedState;
6491044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org  } else {
6501044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org    RuntimeDefinition RD = Call->getRuntimeDefinition();
6511044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org    const Decl *D = RD.getDecl();
6521044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org    if (D) {
6531044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org      if (RD.mayHaveOtherDefinitions()) {
6541044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org        // Explore with and without inlining the call.
6551044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org        if (getAnalysisManager().options.IPAMode == DynamicDispatchBifurcate) {
6561044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org          BifurcateCall(RD.getDispatchRegion(), *Call, D, Bldr, Pred);
6571044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org          return;
6581044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org        }
6591044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org
660ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        // Don't inline if we're not in any dynamic dispatch mode.
661ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        if (getAnalysisManager().options.IPAMode != DynamicDispatch) {
662ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com          conservativeEvalCall(*Call, Bldr, Pred, State);
663ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com          return;
664ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        }
665ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      }
666ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
6677d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org      // We are not bifurcating and we do have a Decl, so just inline.
6688bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org      if (inlineCall(*Call, D, Bldr, Pred, State))
6692efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org        return;
6703291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    }
6713291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  }
6723291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
6733291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // If we can't inline it, handle the return value and invalidate the regions.
6743291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  conservativeEvalCall(*Call, Bldr, Pred, State);
675a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
676a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
677a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid ExprEngine::BifurcateCall(const MemRegion *BifurReg,
678ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                               const CallEvent &Call, const Decl *D,
679ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                               NodeBuilder &Bldr, ExplodedNode *Pred) {
680ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  assert(BifurReg);
6810c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  BifurReg = BifurReg->StripCasts();
6827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
683400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org  // Check if we've performed the split already - note, we only want
684a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // to split the path once per memory region.
685ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  ProgramStateRef State = Pred->getState();
6861044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org  const unsigned int *BState =
6870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                        State->get<DynamicDispatchBifurcationMap>(BifurReg);
6883291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  if (BState) {
689a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // If we are on "inline path", keep inlining if possible.
690ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    if (*BState == DynamicDispatchModeInlined)
691ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      if (inlineCall(Call, D, Bldr, Pred, State))
692ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        return;
693ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    // If inline failed, or we are on the path where we assume we
694a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // don't have enough info about the receiver to inline, conjure the
6950c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    // return value and invalidate the regions.
696a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    conservativeEvalCall(Call, Bldr, Pred, State);
697a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
6983291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  }
6993291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7003291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // If we got here, this is the first time we process a message to this
7013291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // region, so split the path.
7023291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  ProgramStateRef IState =
7033291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      State->set<DynamicDispatchBifurcationMap>(BifurReg,
704ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                                               DynamicDispatchModeInlined);
705400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org  inlineCall(Call, D, Bldr, Pred, IState);
706400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org
7073291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  ProgramStateRef NoIState =
7083291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      State->set<DynamicDispatchBifurcationMap>(BifurReg,
7093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                                               DynamicDispatchModeConservative);
7103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  conservativeEvalCall(Call, Bldr, Pred, NoIState);
7113291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7123291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  NumOfDynamicDispatchPathSplits++;
7133291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  return;
7143291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
7153291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7163291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7173291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
7183291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                                 ExplodedNodeSet &Dst) {
7193291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7203291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  ExplodedNodeSet dstPreVisit;
7213291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this);
7223291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7233291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  StmtNodeBuilder B(dstPreVisit, Dst, *currBldrCtx);
7243291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7253291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  if (RS->getRetValue()) {
7263291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    for (ExplodedNodeSet::iterator it = dstPreVisit.begin(),
727ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                                  ei = dstPreVisit.end(); it != ei; ++it) {
728ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      B.generateNode(RS, *it, (*it)->getState());
7293291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    }
7303291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  }
7313291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
7323291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org