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"
17742920c8SJordan Rose #include "clang/StaticAnalyzer/Core/PathSensitive/Calls.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 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
2510e25031STed Kremenek                                           ExplodedNode *Pred,
2610e25031STed Kremenek                                           ExplodedNodeSet &Dst) {
27e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
282a14c695STed Kremenek   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
2949b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
30632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
3110e25031STed Kremenek 
3210e25031STed Kremenek   // Bind the temporary object to the value of the expression. Then bind
3310e25031STed Kremenek   // the expression to the location of the object.
34632e3b7eSTed Kremenek   SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
3510e25031STed Kremenek 
3610e25031STed Kremenek   const MemRegion *R =
37632e3b7eSTed Kremenek     svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
3810e25031STed Kremenek 
3910e25031STed Kremenek   state = state->bindLoc(loc::MemRegionVal(R), V);
40632e3b7eSTed Kremenek   Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
4110e25031STed Kremenek }
4210e25031STed Kremenek 
4311764ab4SBenjamin Kramer void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
4411764ab4SBenjamin Kramer                                              ExplodedNode *Pred,
4511764ab4SBenjamin Kramer                                              ExplodedNodeSet &Dst) {
4611764ab4SBenjamin Kramer   VisitCXXConstructExpr(expr, 0, Pred, Dst);
4711764ab4SBenjamin Kramer }
4811764ab4SBenjamin Kramer 
49f3c12ac3SJordan Rose void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
5010e25031STed Kremenek                                        const MemRegion *Dest,
5110e25031STed Kremenek                                        ExplodedNode *Pred,
5210e25031STed Kremenek                                        ExplodedNodeSet &destNodes) {
53f3c12ac3SJordan Rose   CXXConstructorCall Call(CE, Dest, Pred->getState(),
5410e25031STed Kremenek                           Pred->getLocationContext());
5510e25031STed Kremenek 
56f3c12ac3SJordan Rose   ExplodedNodeSet DstPreVisit;
57f3c12ac3SJordan Rose   getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
58afe7c2c2SJordan Rose   ExplodedNodeSet DstPreCall;
59afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
60afe7c2c2SJordan Rose                                             Call, *this);
6110e25031STed Kremenek 
62f3c12ac3SJordan Rose   ExplodedNodeSet DstInvalidated;
63afe7c2c2SJordan Rose   for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
64f3c12ac3SJordan Rose        I != E; ++I)
65f3c12ac3SJordan Rose     defaultEvalCall(DstInvalidated, *I, Call);
6610e25031STed Kremenek 
67afe7c2c2SJordan Rose   ExplodedNodeSet DstPostCall;
68afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
69afe7c2c2SJordan Rose                                              Call, *this);
70afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
7110e25031STed Kremenek }
7210e25031STed Kremenek 
7310e25031STed Kremenek void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
7410e25031STed Kremenek                                       const MemRegion *Dest,
7510e25031STed Kremenek                                       const Stmt *S,
7610e25031STed Kremenek                                       ExplodedNode *Pred,
7710e25031STed Kremenek                                       ExplodedNodeSet &Dst) {
78e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
7910e25031STed Kremenek   if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
8010e25031STed Kremenek     return;
81142adc49STed Kremenek 
8210e25031STed Kremenek   // Create the context for 'this' region.
83142adc49STed Kremenek   const StackFrameContext *SFC =
8481ce1c8aSTed Kremenek     AnalysisDeclContexts.getContext(DD)->
85142adc49STed Kremenek       getStackFrame(Pred->getLocationContext(), S,
86e594034fSAnna Zaks       currentBuilderContext->getBlock(), currentStmtIdx);
8710e25031STed Kremenek 
8810e25031STed Kremenek   CallEnter PP(S, SFC, Pred->getLocationContext());
8949b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
9072b3452cSTed Kremenek   state = state->bindLoc(svalBuilder.getCXXThis(DD->getParent(), SFC),
9172b3452cSTed Kremenek                          loc::MemRegionVal(Dest));
92e594034fSAnna Zaks   Bldr.generateNode(PP, Pred, state);
9310e25031STed Kremenek }
9410e25031STed Kremenek 
9510e25031STed Kremenek void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
9610e25031STed Kremenek                                    ExplodedNodeSet &Dst) {
97*a4ee064cSJordan Rose   // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
98*a4ee064cSJordan Rose   // Also, we need to decide how allocators actually work -- they're not
99*a4ee064cSJordan Rose   // really part of the CXXNewExpr because they happen BEFORE the
100*a4ee064cSJordan Rose   // CXXConstructExpr subexpression. See PR12014 for some discussion.
101e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
10210e25031STed Kremenek 
103e594034fSAnna Zaks   unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
104d519cae8STed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
10510e25031STed Kremenek   DefinedOrUnknownSVal symVal =
106*a4ee064cSJordan Rose     svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount);
10744320367SJordan Rose   ProgramStateRef State = Pred->getState();
10810e25031STed Kremenek 
109*a4ee064cSJordan Rose   // Invalidate placement args.
110*a4ee064cSJordan Rose   CXXAllocatorCall Call(CNE, State, LCtx);
111*a4ee064cSJordan Rose   State = Call.invalidateRegions(blockCount);
112*a4ee064cSJordan Rose 
11310e25031STed Kremenek   if (CNE->isArray()) {
11410e25031STed Kremenek     // FIXME: allocating an array requires simulating the constructors.
11510e25031STed Kremenek     // For now, just return a symbolicated region.
116*a4ee064cSJordan Rose     const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
117*a4ee064cSJordan Rose     QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
118*a4ee064cSJordan Rose     const ElementRegion *EleReg =
119*a4ee064cSJordan Rose       getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
12044320367SJordan Rose     State = State->BindExpr(CNE, Pred->getLocationContext(),
121632e3b7eSTed Kremenek                             loc::MemRegionVal(EleReg));
12244320367SJordan Rose     Bldr.generateNode(CNE, Pred, State);
12310e25031STed Kremenek     return;
12410e25031STed Kremenek   }
12510e25031STed Kremenek 
126*a4ee064cSJordan Rose   // FIXME: Once we have proper support for CXXConstructExprs inside
127*a4ee064cSJordan Rose   // CXXNewExpr, we need to make sure that the constructed object is not
128*a4ee064cSJordan Rose   // immediately invalidated here. (The placement call should happen before
129*a4ee064cSJordan Rose   // the constructor call anyway.)
13044320367SJordan Rose   FunctionDecl *FD = CNE->getOperatorNew();
13144320367SJordan Rose   if (FD && FD->isReservedGlobalPlacementOperator()) {
13244320367SJordan Rose     // Non-array placement new should always return the placement location.
13344320367SJordan Rose     SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
13444320367SJordan Rose     State = State->BindExpr(CNE, LCtx, PlacementLoc);
13544320367SJordan Rose   } else {
136*a4ee064cSJordan Rose     State = State->BindExpr(CNE, LCtx, symVal);
13744320367SJordan Rose   }
13844320367SJordan Rose 
13944320367SJordan Rose   Bldr.generateNode(CNE, Pred, State);
14010e25031STed Kremenek }
14110e25031STed Kremenek 
14210e25031STed Kremenek void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
14310e25031STed Kremenek                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
14464aea652SErik Verbruggen   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
14564aea652SErik Verbruggen   ProgramStateRef state = Pred->getState();
14664aea652SErik Verbruggen   Bldr.generateNode(CDE, Pred, state);
14710e25031STed Kremenek }
14810e25031STed Kremenek 
1498fdb59f9STed Kremenek void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
1508fdb59f9STed Kremenek                                    ExplodedNode *Pred,
1518fdb59f9STed Kremenek                                    ExplodedNodeSet &Dst) {
1528fdb59f9STed Kremenek   const VarDecl *VD = CS->getExceptionDecl();
153b1279b5cSTed Kremenek   if (!VD) {
154b1279b5cSTed Kremenek     Dst.Add(Pred);
155b1279b5cSTed Kremenek     return;
156b1279b5cSTed Kremenek   }
157b1279b5cSTed Kremenek 
1588fdb59f9STed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
1598fdb59f9STed Kremenek   SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
1608fdb59f9STed Kremenek                                  currentBuilderContext->getCurrentBlockCount());
1618fdb59f9STed Kremenek   ProgramStateRef state = Pred->getState();
1628fdb59f9STed Kremenek   state = state->bindLoc(state->getLValue(VD, LCtx), V);
1638fdb59f9STed Kremenek 
1648fdb59f9STed Kremenek   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
1658fdb59f9STed Kremenek   Bldr.generateNode(CS, Pred, state);
1668fdb59f9STed Kremenek }
1678fdb59f9STed Kremenek 
16810e25031STed Kremenek void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
16910e25031STed Kremenek                                     ExplodedNodeSet &Dst) {
170e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
171e594034fSAnna Zaks 
17210e25031STed Kremenek   // Get the this object region from StoreManager.
173632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
17410e25031STed Kremenek   const MemRegion *R =
17510e25031STed Kremenek     svalBuilder.getRegionManager().getCXXThisRegion(
17610e25031STed Kremenek                                   getContext().getCanonicalType(TE->getType()),
177632e3b7eSTed Kremenek                                                     LCtx);
17810e25031STed Kremenek 
17949b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
18010e25031STed Kremenek   SVal V = state->getSVal(loc::MemRegionVal(R));
181632e3b7eSTed Kremenek   Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
18210e25031STed Kremenek }
183