ExprEngineCXX.cpp revision 226586
119304Speter//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
219304Speter//
319304Speter//                     The LLVM Compiler Infrastructure
419304Speter//
519304Speter// This file is distributed under the University of Illinois Open Source
619304Speter// License. See LICENSE.TXT for details.
719304Speter//
819304Speter//===----------------------------------------------------------------------===//
919304Speter//
1019304Speter//  This file defines the C++ expression evaluation engine.
1119304Speter//
1219304Speter//===----------------------------------------------------------------------===//
13254225Speter
1419304Speter#include "clang/StaticAnalyzer/Core/CheckerManager.h"
1519304Speter#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
1619304Speter#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
1719304Speter#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
1819304Speter#include "clang/AST/DeclCXX.h"
1919304Speter
2019304Speterusing namespace clang;
2119304Speterusing namespace ento;
2219304Speter
2319304Speternamespace {
2419304Speterclass CallExprWLItem {
2519304Speterpublic:
2619304Speter  CallExpr::const_arg_iterator I;
2719304Speter  ExplodedNode *N;
2819304Speter
2919304Speter  CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
3019304Speter    : I(i), N(n) {}
3119304Speter};
3219304Speter}
3319304Speter
3419304Spetervoid ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
3519304Speter                                 const FunctionProtoType *FnType,
3619304Speter                                 ExplodedNode *Pred, ExplodedNodeSet &Dst,
3719304Speter                                 bool FstArgAsLValue) {
3819304Speter
3919304Speter
4019304Speter  SmallVector<CallExprWLItem, 20> WorkList;
4119304Speter  WorkList.reserve(AE - AI);
4219304Speter  WorkList.push_back(CallExprWLItem(AI, Pred));
43254225Speter
4419304Speter  while (!WorkList.empty()) {
4519304Speter    CallExprWLItem Item = WorkList.back();
4619304Speter    WorkList.pop_back();
47254225Speter
48254225Speter    if (Item.I == AE) {
4919304Speter      Dst.insert(Item.N);
5019304Speter      continue;
5119304Speter    }
5219304Speter
5319304Speter    // Evaluate the argument.
5419304Speter    ExplodedNodeSet Tmp;
5519304Speter    if (FstArgAsLValue) {
5619304Speter      FstArgAsLValue = false;
5719304Speter    }
5819304Speter
59254225Speter    Visit(*Item.I, Item.N, Tmp);
6019304Speter    ++(Item.I);
6119304Speter    for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
6219304Speter      WorkList.push_back(CallExprWLItem(Item.I, *NI));
6319304Speter  }
6419304Speter}
6519304Speter
6619304Spetervoid ExprEngine::evalCallee(const CallExpr *callExpr,
6719304Speter                            const ExplodedNodeSet &src,
6819304Speter                            ExplodedNodeSet &dest) {
6919304Speter
7019304Speter  const Expr *callee = 0;
7119304Speter
7219304Speter  switch (callExpr->getStmtClass()) {
7319304Speter    case Stmt::CXXMemberCallExprClass: {
7419304Speter      // Evaluate the implicit object argument that is the recipient of the
7519304Speter      // call.
7619304Speter      callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument();
7719304Speter
7819304Speter      // FIXME: handle member pointers.
7919304Speter      if (!callee)
8019304Speter        return;
8119304Speter
8219304Speter      break;
8319304Speter    }
8419304Speter    default: {
8519304Speter      callee = callExpr->getCallee()->IgnoreParens();
8619304Speter      break;
8719304Speter    }
8819304Speter  }
8919304Speter
9019304Speter  for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i)
9119304Speter    Visit(callee, *i, dest);
9219304Speter}
9319304Speter
9419304Speterconst CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
95254225Speter                                                 const StackFrameContext *SFC) {
9619304Speter  const Type *T = D->getTypeForDecl();
9719304Speter  QualType PT = getContext().getPointerType(QualType(T, 0));
9819304Speter  return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
9919304Speter}
10019304Speter
10119304Speterconst CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
10219304Speter                                            const StackFrameContext *frameCtx) {
10319304Speter  return svalBuilder.getRegionManager().
10419304Speter                    getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
10519304Speter}
10619304Speter
10719304Spetervoid ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
10819304Speter                                          ExplodedNode *Pred,
10919304Speter                                          ExplodedNodeSet &Dst) {
11019304Speter  const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
11119304Speter  const ProgramState *state = Pred->getState();
11219304Speter
113254225Speter  // Bind the temporary object to the value of the expression. Then bind
11419304Speter  // the expression to the location of the object.
11519304Speter  SVal V = state->getSVal(tempExpr);
11619304Speter
11719304Speter  const MemRegion *R =
11819304Speter    svalBuilder.getRegionManager().getCXXTempObjectRegion(ME,
11919304Speter                                                 Pred->getLocationContext());
12019304Speter
12119304Speter  state = state->bindLoc(loc::MemRegionVal(R), V);
12219304Speter  MakeNode(Dst, ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
12319304Speter}
124254225Speter
12519304Spetervoid ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
12619304Speter                                       const MemRegion *Dest,
12719304Speter                                       ExplodedNode *Pred,
128254225Speter                                       ExplodedNodeSet &destNodes) {
129254225Speter
13019304Speter  const CXXConstructorDecl *CD = E->getConstructor();
13119304Speter  assert(CD);
13219304Speter
13319304Speter#if 0
13419304Speter  if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
13519304Speter    // FIXME: invalidate the object.
13619304Speter    return;
13719304Speter#endif
13819304Speter
13919304Speter  // Evaluate other arguments.
140254225Speter  ExplodedNodeSet argsEvaluated;
14119304Speter  const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
14219304Speter  evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
14319304Speter
144254225Speter#if 0
145254225Speter  // Is the constructor elidable?
14619304Speter  if (E->isElidable()) {
14719304Speter    VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
14819304Speter    // FIXME: this is here to force propagation if VisitAggExpr doesn't
14919304Speter    if (destNodes.empty())
15019304Speter      destNodes.Add(Pred);
15119304Speter    return;
15219304Speter  }
15319304Speter#endif
15419304Speter
15519304Speter  // Perform the previsit of the constructor.
156254225Speter  ExplodedNodeSet destPreVisit;
15719304Speter  getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
15819304Speter                                            *this);
15919304Speter
160254225Speter  // Evaluate the constructor.  Currently we don't now allow checker-specific
161254225Speter  // implementations of specific constructors (as we do with ordinary
16219304Speter  // function calls.  We can re-evaluate this in the future.
16319304Speter
16419304Speter#if 0
16519304Speter  // Inlining currently isn't fully implemented.
16619304Speter
16719304Speter  if (AMgr.shouldInlineCall()) {
16819304Speter    if (!Dest)
16919304Speter      Dest =
17019304Speter        svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
17119304Speter                                                  Pred->getLocationContext());
172254225Speter
17319304Speter    // The callee stack frame context used to create the 'this'
17419304Speter    // parameter region.
17519304Speter    const StackFrameContext *SFC =
176254225Speter      AMgr.getStackFrame(CD, Pred->getLocationContext(),
177254225Speter                         E, Builder->getBlock(), Builder->getIndex());
17819304Speter
17919304Speter    // Create the 'this' region.
18019304Speter    const CXXThisRegion *ThisR =
18119304Speter      getCXXThisRegion(E->getConstructor()->getParent(), SFC);
18219304Speter
18319304Speter    CallEnter Loc(E, SFC, Pred->getLocationContext());
18419304Speter
18519304Speter
18619304Speter    for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
18719304Speter                                  NE = argsEvaluated.end(); NI != NE; ++NI) {
18819304Speter      const ProgramState *state = (*NI)->getState();
18919304Speter      // Setup 'this' region, so that the ctor is evaluated on the object pointed
19019304Speter      // by 'Dest'.
19119304Speter      state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
192254225Speter      if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI))
193254225Speter        destNodes.Add(N);
194254225Speter    }
19519304Speter  }
19619304Speter#endif
19719304Speter
19819304Speter  // Default semantics: invalidate all regions passed as arguments.
19919304Speter  ExplodedNodeSet destCall;
20019304Speter
20119304Speter  for (ExplodedNodeSet::iterator
20219304Speter        i = destPreVisit.begin(), e = destPreVisit.end();
20319304Speter       i != e; ++i)
20419304Speter  {
205254225Speter    ExplodedNode *Pred = *i;
20619304Speter    const LocationContext *LC = Pred->getLocationContext();
20719304Speter    const ProgramState *state = Pred->getState();
20819304Speter
209254225Speter    state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
210254225Speter    Builder->MakeNode(destCall, E, Pred, state);
21119304Speter  }
21219304Speter
21319304Speter  // Do the post visit.
21419304Speter  getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
21519304Speter}
21619304Speter
21719304Spetervoid ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
21819304Speter                                      const MemRegion *Dest,
21919304Speter                                      const Stmt *S,
22019304Speter                                      ExplodedNode *Pred,
221254225Speter                                      ExplodedNodeSet &Dst) {
22219304Speter  if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
22319304Speter    return;
22419304Speter  // Create the context for 'this' region.
225254225Speter  const StackFrameContext *SFC = AMgr.getStackFrame(DD,
22619304Speter                                                    Pred->getLocationContext(),
22719304Speter                                                    S, Builder->getBlock(),
22819304Speter                                                    Builder->getIndex());
22919304Speter
23019304Speter  const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
23119304Speter
23219304Speter  CallEnter PP(S, SFC, Pred->getLocationContext());
23319304Speter
23419304Speter  const ProgramState *state = Pred->getState();
23519304Speter  state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
236254225Speter  ExplodedNode *N = Builder->generateNode(PP, state, Pred);
23719304Speter  if (N)
23819304Speter    Dst.Add(N);
23919304Speter}
24019304Speter
24119304Spetervoid ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
24219304Speter                                   ExplodedNodeSet &Dst) {
24319304Speter
24419304Speter  unsigned blockCount = Builder->getCurrentBlockCount();
24519304Speter  DefinedOrUnknownSVal symVal =
24619304Speter    svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount);
24719304Speter  const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
24819304Speter  QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
24919304Speter  const ElementRegion *EleReg =
25019304Speter    getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
25119304Speter
25219304Speter  if (CNE->isArray()) {
25319304Speter    // FIXME: allocating an array requires simulating the constructors.
25419304Speter    // For now, just return a symbolicated region.
25519304Speter    const ProgramState *state = Pred->getState();
25619304Speter    state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
25719304Speter    MakeNode(Dst, CNE, Pred, state);
25819304Speter    return;
25919304Speter  }
26019304Speter
26119304Speter  // Evaluate constructor arguments.
262254225Speter  const FunctionProtoType *FnType = NULL;
263254225Speter  const CXXConstructorDecl *CD = CNE->getConstructor();
26419304Speter  if (CD)
26519304Speter    FnType = CD->getType()->getAs<FunctionProtoType>();
266254225Speter  ExplodedNodeSet argsEvaluated;
26719304Speter  evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
26819304Speter                FnType, Pred, argsEvaluated);
26919304Speter
27019304Speter  // Initialize the object region and bind the 'new' expression.
27119304Speter  for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
27219304Speter                                 E = argsEvaluated.end(); I != E; ++I) {
27319304Speter
27419304Speter    const ProgramState *state = (*I)->getState();
27519304Speter
27619304Speter    // Accumulate list of regions that are invalidated.
27719304Speter    // FIXME: Eventually we should unify the logic for constructor
27819304Speter    // processing in one place.
27919304Speter    SmallVector<const MemRegion*, 10> regionsToInvalidate;
28019304Speter    for (CXXNewExpr::const_arg_iterator
28119304Speter          ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
28219304Speter          ai != ae; ++ai)
28319304Speter    {
28419304Speter      SVal val = state->getSVal(*ai);
285254225Speter      if (const MemRegion *region = val.getAsRegion())
28619304Speter        regionsToInvalidate.push_back(region);
28719304Speter    }
28819304Speter
28919304Speter    if (ObjTy->isRecordType()) {
29019304Speter      regionsToInvalidate.push_back(EleReg);
29119304Speter      // Invalidate the regions.
29219304Speter      state = state->invalidateRegions(regionsToInvalidate,
29319304Speter                                       CNE, blockCount, 0,
29419304Speter                                       /* invalidateGlobals = */ true);
295254225Speter
29619304Speter    } else {
29719304Speter      // Invalidate the regions.
29819304Speter      state = state->invalidateRegions(regionsToInvalidate,
29919304Speter                                       CNE, blockCount, 0,
30019304Speter                                       /* invalidateGlobals = */ true);
30119304Speter
30219304Speter      if (CNE->hasInitializer()) {
30319304Speter        SVal V = state->getSVal(*CNE->constructor_arg_begin());
30419304Speter        state = state->bindLoc(loc::MemRegionVal(EleReg), V);
30519304Speter      } else {
30619304Speter        // Explicitly set to undefined, because currently we retrieve symbolic
30719304Speter        // value from symbolic region.
30819304Speter        state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
30919304Speter      }
310254225Speter    }
31119304Speter    state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
31219304Speter    MakeNode(Dst, CNE, *I, state);
31319304Speter  }
31419304Speter}
31519304Speter
31619304Spetervoid ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
31719304Speter                                      ExplodedNode *Pred,ExplodedNodeSet &Dst) {
31819304Speter  // Should do more checking.
31919304Speter  ExplodedNodeSet Argevaluated;
32019304Speter  Visit(CDE->getArgument(), Pred, Argevaluated);
32119304Speter  for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
32219304Speter                                 E = Argevaluated.end(); I != E; ++I) {
32319304Speter    const ProgramState *state = (*I)->getState();
32419304Speter    MakeNode(Dst, CDE, *I, state);
325254225Speter  }
32619304Speter}
32719304Speter
32819304Spetervoid ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
32919304Speter                                    ExplodedNodeSet &Dst) {
33019304Speter  // Get the this object region from StoreManager.
33119304Speter  const MemRegion *R =
33219304Speter    svalBuilder.getRegionManager().getCXXThisRegion(
33319304Speter                                  getContext().getCanonicalType(TE->getType()),
33419304Speter                                               Pred->getLocationContext());
33519304Speter
33619304Speter  const ProgramState *state = Pred->getState();
33719304Speter  SVal V = state->getSVal(loc::MemRegionVal(R));
33819304Speter  MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
33919304Speter}
34019304Speter