110e25031STed Kremenek //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
210e25031STed Kremenek //
310e25031STed Kremenek //                     The LLVM Compiler Infrastructure
410e25031STed Kremenek //
510e25031STed Kremenek // This file is distributed under the University of Illinois Open Source
610e25031STed Kremenek // License. See LICENSE.TXT for details.
710e25031STed Kremenek //
810e25031STed Kremenek //===----------------------------------------------------------------------===//
910e25031STed Kremenek //
1010e25031STed Kremenek //  This file defines the C++ expression evaluation engine.
1110e25031STed Kremenek //
1210e25031STed Kremenek //===----------------------------------------------------------------------===//
1310e25031STed Kremenek 
1410e25031STed Kremenek #include "clang/StaticAnalyzer/Core/CheckerManager.h"
1510e25031STed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
1610e25031STed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17087611edSJordy Rose #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
1810e25031STed Kremenek #include "clang/AST/DeclCXX.h"
198fdb59f9STed Kremenek #include "clang/AST/StmtCXX.h"
2010e25031STed Kremenek 
2110e25031STed Kremenek using namespace clang;
2210e25031STed Kremenek using namespace ento;
2310e25031STed Kremenek 
2410e25031STed Kremenek const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
2510e25031STed Kremenek                                                  const StackFrameContext *SFC) {
2610e25031STed Kremenek   const Type *T = D->getTypeForDecl();
2710e25031STed Kremenek   QualType PT = getContext().getPointerType(QualType(T, 0));
2810e25031STed Kremenek   return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
2910e25031STed Kremenek }
3010e25031STed Kremenek 
3110e25031STed Kremenek const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
3210e25031STed Kremenek                                             const StackFrameContext *frameCtx) {
3310e25031STed Kremenek   return svalBuilder.getRegionManager().
3410e25031STed Kremenek                     getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
3510e25031STed Kremenek }
3610e25031STed Kremenek 
3710e25031STed Kremenek void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
3810e25031STed Kremenek                                           ExplodedNode *Pred,
3910e25031STed Kremenek                                           ExplodedNodeSet &Dst) {
40e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
412a14c695STed Kremenek   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
4249b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
43632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
4410e25031STed Kremenek 
4510e25031STed Kremenek   // Bind the temporary object to the value of the expression. Then bind
4610e25031STed Kremenek   // the expression to the location of the object.
47632e3b7eSTed Kremenek   SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
4810e25031STed Kremenek 
4910e25031STed Kremenek   const MemRegion *R =
50632e3b7eSTed Kremenek     svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
5110e25031STed Kremenek 
5210e25031STed Kremenek   state = state->bindLoc(loc::MemRegionVal(R), V);
53632e3b7eSTed Kremenek   Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
5410e25031STed Kremenek }
5510e25031STed Kremenek 
5611764ab4SBenjamin Kramer void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
5711764ab4SBenjamin Kramer                                              ExplodedNode *Pred,
5811764ab4SBenjamin Kramer                                              ExplodedNodeSet &Dst) {
5911764ab4SBenjamin Kramer   VisitCXXConstructExpr(expr, 0, Pred, Dst);
6011764ab4SBenjamin Kramer }
6111764ab4SBenjamin Kramer 
6210e25031STed Kremenek void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
6310e25031STed Kremenek                                        const MemRegion *Dest,
6410e25031STed Kremenek                                        ExplodedNode *Pred,
6510e25031STed Kremenek                                        ExplodedNodeSet &destNodes) {
6610e25031STed Kremenek 
67be84d859SMatt Beaumont-Gay #if 0
6810e25031STed Kremenek   const CXXConstructorDecl *CD = E->getConstructor();
6910e25031STed Kremenek   assert(CD);
70be84d859SMatt Beaumont-Gay #endif
7110e25031STed Kremenek 
7210e25031STed Kremenek #if 0
7310e25031STed Kremenek   if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
7410e25031STed Kremenek     // FIXME: invalidate the object.
7510e25031STed Kremenek     return;
7610e25031STed Kremenek #endif
7710e25031STed Kremenek 
7810e25031STed Kremenek #if 0
7910e25031STed Kremenek   // Is the constructor elidable?
8010e25031STed Kremenek   if (E->isElidable()) {
8110e25031STed Kremenek     destNodes.Add(Pred);
8210e25031STed Kremenek     return;
8310e25031STed Kremenek   }
8410e25031STed Kremenek #endif
8510e25031STed Kremenek 
8610e25031STed Kremenek   // Perform the previsit of the constructor.
87fe66dd62SErik Verbruggen   ExplodedNodeSet SrcNodes;
88fe66dd62SErik Verbruggen   SrcNodes.Add(Pred);
89fe66dd62SErik Verbruggen   ExplodedNodeSet TmpNodes;
90fe66dd62SErik Verbruggen   getCheckerManager().runCheckersForPreStmt(TmpNodes, SrcNodes, E, *this);
9110e25031STed Kremenek 
9210e25031STed Kremenek   // Evaluate the constructor.  Currently we don't now allow checker-specific
9310e25031STed Kremenek   // implementations of specific constructors (as we do with ordinary
9410e25031STed Kremenek   // function calls.  We can re-evaluate this in the future.
9510e25031STed Kremenek 
9610e25031STed Kremenek #if 0
9710e25031STed Kremenek   // Inlining currently isn't fully implemented.
9810e25031STed Kremenek 
9910e25031STed Kremenek   if (AMgr.shouldInlineCall()) {
10010e25031STed Kremenek     if (!Dest)
10110e25031STed Kremenek       Dest =
10210e25031STed Kremenek         svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
10310e25031STed Kremenek                                                   Pred->getLocationContext());
10410e25031STed Kremenek 
10510e25031STed Kremenek     // The callee stack frame context used to create the 'this'
10610e25031STed Kremenek     // parameter region.
10710e25031STed Kremenek     const StackFrameContext *SFC =
10810e25031STed Kremenek       AMgr.getStackFrame(CD, Pred->getLocationContext(),
109e594034fSAnna Zaks                          E, currentBuilderContext->getBlock(),
110e594034fSAnna Zaks                          currentStmtIdx);
11110e25031STed Kremenek 
11210e25031STed Kremenek     // Create the 'this' region.
11310e25031STed Kremenek     const CXXThisRegion *ThisR =
11410e25031STed Kremenek       getCXXThisRegion(E->getConstructor()->getParent(), SFC);
11510e25031STed Kremenek 
11610e25031STed Kremenek     CallEnter Loc(E, SFC, Pred->getLocationContext());
11710e25031STed Kremenek 
118fe66dd62SErik Verbruggen     StmtNodeBuilder Bldr(SrcNodes, TmpNodes, *currentBuilderContext);
119fe66dd62SErik Verbruggen     for (ExplodedNodeSet::iterator NI = SrcNodes.begin(),
120fe66dd62SErik Verbruggen                                    NE = SrcNodes.end(); NI != NE; ++NI) {
12149b1e38eSTed Kremenek       ProgramStateRef state = (*NI)->getState();
12210e25031STed Kremenek       // Setup 'this' region, so that the ctor is evaluated on the object pointed
12310e25031STed Kremenek       // by 'Dest'.
12410e25031STed Kremenek       state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
125e594034fSAnna Zaks       Bldr.generateNode(Loc, *NI, state);
12610e25031STed Kremenek     }
12710e25031STed Kremenek   }
12810e25031STed Kremenek #endif
12910e25031STed Kremenek 
13010e25031STed Kremenek   // Default semantics: invalidate all regions passed as arguments.
13110e25031STed Kremenek   ExplodedNodeSet destCall;
132e594034fSAnna Zaks   {
133fe66dd62SErik Verbruggen     StmtNodeBuilder Bldr(TmpNodes, destCall, *currentBuilderContext);
134fe66dd62SErik Verbruggen     for (ExplodedNodeSet::iterator i = TmpNodes.begin(), e = TmpNodes.end();
13510e25031STed Kremenek          i != e; ++i)
13610e25031STed Kremenek     {
13710e25031STed Kremenek       ExplodedNode *Pred = *i;
138d188d66eSJordy Rose       const LocationContext *LC = Pred->getLocationContext();
13949b1e38eSTed Kremenek       ProgramStateRef state = Pred->getState();
14010e25031STed Kremenek 
141632e3b7eSTed Kremenek       state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
142e594034fSAnna Zaks       Bldr.generateNode(E, Pred, state);
14310e25031STed Kremenek     }
144e594034fSAnna Zaks   }
14510e25031STed Kremenek   // Do the post visit.
14610e25031STed Kremenek   getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
14710e25031STed Kremenek }
14810e25031STed Kremenek 
14910e25031STed Kremenek void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
15010e25031STed Kremenek                                       const MemRegion *Dest,
15110e25031STed Kremenek                                       const Stmt *S,
15210e25031STed Kremenek                                       ExplodedNode *Pred,
15310e25031STed Kremenek                                       ExplodedNodeSet &Dst) {
154e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
15510e25031STed Kremenek   if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
15610e25031STed Kremenek     return;
157142adc49STed Kremenek 
15810e25031STed Kremenek   // Create the context for 'this' region.
159142adc49STed Kremenek   const StackFrameContext *SFC =
16081ce1c8aSTed Kremenek     AnalysisDeclContexts.getContext(DD)->
161142adc49STed Kremenek       getStackFrame(Pred->getLocationContext(), S,
162e594034fSAnna Zaks       currentBuilderContext->getBlock(), currentStmtIdx);
16310e25031STed Kremenek 
16410e25031STed Kremenek   const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
16510e25031STed Kremenek 
16610e25031STed Kremenek   CallEnter PP(S, SFC, Pred->getLocationContext());
16710e25031STed Kremenek 
16849b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
16910e25031STed Kremenek   state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
170e594034fSAnna Zaks   Bldr.generateNode(PP, Pred, state);
17110e25031STed Kremenek }
17210e25031STed Kremenek 
17310e25031STed Kremenek void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
17410e25031STed Kremenek                                    ExplodedNodeSet &Dst) {
175e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
17610e25031STed Kremenek 
177e594034fSAnna Zaks   unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
178d519cae8STed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
17910e25031STed Kremenek   DefinedOrUnknownSVal symVal =
180d519cae8STed Kremenek     svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount);
18110e25031STed Kremenek   const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
18210e25031STed Kremenek   QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
18310e25031STed Kremenek   const ElementRegion *EleReg =
18410e25031STed Kremenek     getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
18510e25031STed Kremenek 
18610e25031STed Kremenek   if (CNE->isArray()) {
18710e25031STed Kremenek     // FIXME: allocating an array requires simulating the constructors.
18810e25031STed Kremenek     // For now, just return a symbolicated region.
18949b1e38eSTed Kremenek     ProgramStateRef state = Pred->getState();
190632e3b7eSTed Kremenek     state = state->BindExpr(CNE, Pred->getLocationContext(),
191632e3b7eSTed Kremenek                             loc::MemRegionVal(EleReg));
192e594034fSAnna Zaks     Bldr.generateNode(CNE, Pred, state);
19310e25031STed Kremenek     return;
19410e25031STed Kremenek   }
19510e25031STed Kremenek 
1966047f07eSSebastian Redl   // FIXME: Update for AST changes.
1976047f07eSSebastian Redl #if 0
19810e25031STed Kremenek   // Evaluate constructor arguments.
19910e25031STed Kremenek   const FunctionProtoType *FnType = NULL;
20010e25031STed Kremenek   const CXXConstructorDecl *CD = CNE->getConstructor();
20110e25031STed Kremenek   if (CD)
20210e25031STed Kremenek     FnType = CD->getType()->getAs<FunctionProtoType>();
20310e25031STed Kremenek   ExplodedNodeSet argsEvaluated;
204e594034fSAnna Zaks   Bldr.takeNodes(Pred);
20510e25031STed Kremenek   evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
20610e25031STed Kremenek                 FnType, Pred, argsEvaluated);
207e594034fSAnna Zaks   Bldr.addNodes(argsEvaluated);
20810e25031STed Kremenek 
20910e25031STed Kremenek   // Initialize the object region and bind the 'new' expression.
21010e25031STed Kremenek   for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
21110e25031STed Kremenek                                  E = argsEvaluated.end(); I != E; ++I) {
21210e25031STed Kremenek 
21349b1e38eSTed Kremenek     ProgramStateRef state = (*I)->getState();
21410e25031STed Kremenek 
21510e25031STed Kremenek     // Accumulate list of regions that are invalidated.
21610e25031STed Kremenek     // FIXME: Eventually we should unify the logic for constructor
21710e25031STed Kremenek     // processing in one place.
21810e25031STed Kremenek     SmallVector<const MemRegion*, 10> regionsToInvalidate;
21910e25031STed Kremenek     for (CXXNewExpr::const_arg_iterator
22010e25031STed Kremenek           ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
22110e25031STed Kremenek           ai != ae; ++ai)
22210e25031STed Kremenek     {
223632e3b7eSTed Kremenek       SVal val = state->getSVal(*ai, (*I)->getLocationContext());
22410e25031STed Kremenek       if (const MemRegion *region = val.getAsRegion())
22510e25031STed Kremenek         regionsToInvalidate.push_back(region);
22610e25031STed Kremenek     }
22710e25031STed Kremenek 
22810e25031STed Kremenek     if (ObjTy->isRecordType()) {
22910e25031STed Kremenek       regionsToInvalidate.push_back(EleReg);
23010e25031STed Kremenek       // Invalidate the regions.
2318158ef0dSAnna Zaks       // TODO: Pass the call to new information as the last argument, to limit
2328158ef0dSAnna Zaks       // the globals which will get invalidated.
2331fad6631SJordy Rose       state = state->invalidateRegions(regionsToInvalidate,
2348158ef0dSAnna Zaks                                        CNE, blockCount, 0, 0);
23510e25031STed Kremenek 
23610e25031STed Kremenek     } else {
23710e25031STed Kremenek       // Invalidate the regions.
2388158ef0dSAnna Zaks       // TODO: Pass the call to new information as the last argument, to limit
2398158ef0dSAnna Zaks       // the globals which will get invalidated.
2401fad6631SJordy Rose       state = state->invalidateRegions(regionsToInvalidate,
2418158ef0dSAnna Zaks                                        CNE, blockCount, 0, 0);
24210e25031STed Kremenek 
24310e25031STed Kremenek       if (CNE->hasInitializer()) {
244632e3b7eSTed Kremenek         SVal V = state->getSVal(*CNE->constructor_arg_begin(),
245632e3b7eSTed Kremenek                                 (*I)->getLocationContext());
24610e25031STed Kremenek         state = state->bindLoc(loc::MemRegionVal(EleReg), V);
24710e25031STed Kremenek       } else {
24810e25031STed Kremenek         // Explicitly set to undefined, because currently we retrieve symbolic
24910e25031STed Kremenek         // value from symbolic region.
25010e25031STed Kremenek         state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
25110e25031STed Kremenek       }
25210e25031STed Kremenek     }
253632e3b7eSTed Kremenek     state = state->BindExpr(CNE, (*I)->getLocationContext(),
254632e3b7eSTed Kremenek                             loc::MemRegionVal(EleReg));
255e594034fSAnna Zaks     Bldr.generateNode(CNE, *I, state);
25610e25031STed Kremenek   }
2576047f07eSSebastian Redl #endif
25810e25031STed Kremenek }
25910e25031STed Kremenek 
26010e25031STed Kremenek void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
26110e25031STed Kremenek                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
26264aea652SErik Verbruggen   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
26364aea652SErik Verbruggen   ProgramStateRef state = Pred->getState();
26464aea652SErik Verbruggen   Bldr.generateNode(CDE, Pred, state);
26510e25031STed Kremenek }
26610e25031STed Kremenek 
2678fdb59f9STed Kremenek void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
2688fdb59f9STed Kremenek                                    ExplodedNode *Pred,
2698fdb59f9STed Kremenek                                    ExplodedNodeSet &Dst) {
2708fdb59f9STed Kremenek   const VarDecl *VD = CS->getExceptionDecl();
271*b1279b5cSTed Kremenek   if (!VD) {
272*b1279b5cSTed Kremenek     Dst.Add(Pred);
273*b1279b5cSTed Kremenek     return;
274*b1279b5cSTed Kremenek   }
275*b1279b5cSTed Kremenek 
2768fdb59f9STed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
2778fdb59f9STed Kremenek   SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
2788fdb59f9STed Kremenek                                  currentBuilderContext->getCurrentBlockCount());
2798fdb59f9STed Kremenek   ProgramStateRef state = Pred->getState();
2808fdb59f9STed Kremenek   state = state->bindLoc(state->getLValue(VD, LCtx), V);
2818fdb59f9STed Kremenek 
2828fdb59f9STed Kremenek   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
2838fdb59f9STed Kremenek   Bldr.generateNode(CS, Pred, state);
2848fdb59f9STed Kremenek }
2858fdb59f9STed Kremenek 
28610e25031STed Kremenek void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
28710e25031STed Kremenek                                     ExplodedNodeSet &Dst) {
288e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
289e594034fSAnna Zaks 
29010e25031STed Kremenek   // Get the this object region from StoreManager.
291632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
29210e25031STed Kremenek   const MemRegion *R =
29310e25031STed Kremenek     svalBuilder.getRegionManager().getCXXThisRegion(
29410e25031STed Kremenek                                   getContext().getCanonicalType(TE->getType()),
295632e3b7eSTed Kremenek                                                     LCtx);
29610e25031STed Kremenek 
29749b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
29810e25031STed Kremenek   SVal V = state->getSVal(loc::MemRegionVal(R));
299632e3b7eSTed Kremenek   Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
30010e25031STed Kremenek }
301