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 
43f3c12ac3SJordan Rose void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
4410e25031STed Kremenek                                        const MemRegion *Dest,
4510e25031STed Kremenek                                        ExplodedNode *Pred,
4610e25031STed Kremenek                                        ExplodedNodeSet &destNodes) {
47f3c12ac3SJordan Rose   CXXConstructorCall Call(CE, Dest, Pred->getState(),
4810e25031STed Kremenek                           Pred->getLocationContext());
4910e25031STed Kremenek 
50f3c12ac3SJordan Rose   ExplodedNodeSet DstPreVisit;
51f3c12ac3SJordan Rose   getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
52afe7c2c2SJordan Rose   ExplodedNodeSet DstPreCall;
53afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
54afe7c2c2SJordan Rose                                             Call, *this);
5510e25031STed Kremenek 
56f3c12ac3SJordan Rose   ExplodedNodeSet DstInvalidated;
57*3136cf9dSAnna Zaks   StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
58afe7c2c2SJordan Rose   for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
59f3c12ac3SJordan Rose        I != E; ++I)
60*3136cf9dSAnna Zaks     defaultEvalCall(Bldr, *I, Call);
6110e25031STed Kremenek 
62afe7c2c2SJordan Rose   ExplodedNodeSet DstPostCall;
63afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
64afe7c2c2SJordan Rose                                              Call, *this);
65afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
6610e25031STed Kremenek }
6710e25031STed Kremenek 
6810e25031STed Kremenek void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
6910e25031STed Kremenek                                       const MemRegion *Dest,
7010e25031STed Kremenek                                       const Stmt *S,
7110e25031STed Kremenek                                       ExplodedNode *Pred,
7210e25031STed Kremenek                                       ExplodedNodeSet &Dst) {
734ee71b8aSJordan Rose   CXXDestructorCall Call(DD, S, Dest, Pred->getState(),
744ee71b8aSJordan Rose                          Pred->getLocationContext());
75142adc49STed Kremenek 
764ee71b8aSJordan Rose   ExplodedNodeSet DstPreCall;
774ee71b8aSJordan Rose   getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
784ee71b8aSJordan Rose                                             Call, *this);
7910e25031STed Kremenek 
804ee71b8aSJordan Rose   ExplodedNodeSet DstInvalidated;
81*3136cf9dSAnna Zaks   StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
824ee71b8aSJordan Rose   for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
834ee71b8aSJordan Rose        I != E; ++I)
84*3136cf9dSAnna Zaks     defaultEvalCall(Bldr, *I, Call);
854ee71b8aSJordan Rose 
864ee71b8aSJordan Rose   ExplodedNodeSet DstPostCall;
874ee71b8aSJordan Rose   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
884ee71b8aSJordan Rose                                              Call, *this);
8910e25031STed Kremenek }
9010e25031STed Kremenek 
9110e25031STed Kremenek void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
9210e25031STed Kremenek                                    ExplodedNodeSet &Dst) {
93a4ee064cSJordan Rose   // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
94a4ee064cSJordan Rose   // Also, we need to decide how allocators actually work -- they're not
95a4ee064cSJordan Rose   // really part of the CXXNewExpr because they happen BEFORE the
96a4ee064cSJordan Rose   // CXXConstructExpr subexpression. See PR12014 for some discussion.
97e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
9810e25031STed Kremenek 
99e594034fSAnna Zaks   unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
100d519cae8STed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
10110e25031STed Kremenek   DefinedOrUnknownSVal symVal =
102a4ee064cSJordan Rose     svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount);
10344320367SJordan Rose   ProgramStateRef State = Pred->getState();
10410e25031STed Kremenek 
105a4ee064cSJordan Rose   // Invalidate placement args.
106a4ee064cSJordan Rose   CXXAllocatorCall Call(CNE, State, LCtx);
107a4ee064cSJordan Rose   State = Call.invalidateRegions(blockCount);
108a4ee064cSJordan Rose 
10910e25031STed Kremenek   if (CNE->isArray()) {
11010e25031STed Kremenek     // FIXME: allocating an array requires simulating the constructors.
11110e25031STed Kremenek     // For now, just return a symbolicated region.
112a4ee064cSJordan Rose     const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
113a4ee064cSJordan Rose     QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
114a4ee064cSJordan Rose     const ElementRegion *EleReg =
115a4ee064cSJordan Rose       getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
11644320367SJordan Rose     State = State->BindExpr(CNE, Pred->getLocationContext(),
117632e3b7eSTed Kremenek                             loc::MemRegionVal(EleReg));
11844320367SJordan Rose     Bldr.generateNode(CNE, Pred, State);
11910e25031STed Kremenek     return;
12010e25031STed Kremenek   }
12110e25031STed Kremenek 
122a4ee064cSJordan Rose   // FIXME: Once we have proper support for CXXConstructExprs inside
123a4ee064cSJordan Rose   // CXXNewExpr, we need to make sure that the constructed object is not
124a4ee064cSJordan Rose   // immediately invalidated here. (The placement call should happen before
125a4ee064cSJordan Rose   // the constructor call anyway.)
12644320367SJordan Rose   FunctionDecl *FD = CNE->getOperatorNew();
12744320367SJordan Rose   if (FD && FD->isReservedGlobalPlacementOperator()) {
12844320367SJordan Rose     // Non-array placement new should always return the placement location.
12944320367SJordan Rose     SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
13044320367SJordan Rose     State = State->BindExpr(CNE, LCtx, PlacementLoc);
13144320367SJordan Rose   } else {
132a4ee064cSJordan Rose     State = State->BindExpr(CNE, LCtx, symVal);
13344320367SJordan Rose   }
13444320367SJordan Rose 
1355089f3b3SJordan Rose   // If the type is not a record, we won't have a CXXConstructExpr as an
1365089f3b3SJordan Rose   // initializer. Copy the value over.
1375089f3b3SJordan Rose   if (const Expr *Init = CNE->getInitializer()) {
1385089f3b3SJordan Rose     if (!isa<CXXConstructExpr>(Init)) {
1395089f3b3SJordan Rose       QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
1405089f3b3SJordan Rose       (void)ObjTy;
1415089f3b3SJordan Rose       assert(!ObjTy->isRecordType());
1425089f3b3SJordan Rose       SVal Location = State->getSVal(CNE, LCtx);
1435089f3b3SJordan Rose       if (isa<Loc>(Location))
1445089f3b3SJordan Rose         State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx));
1455089f3b3SJordan Rose     }
1465089f3b3SJordan Rose   }
1475089f3b3SJordan Rose 
14844320367SJordan Rose   Bldr.generateNode(CNE, Pred, State);
14910e25031STed Kremenek }
15010e25031STed Kremenek 
15110e25031STed Kremenek void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
15210e25031STed Kremenek                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
15364aea652SErik Verbruggen   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
15464aea652SErik Verbruggen   ProgramStateRef state = Pred->getState();
15564aea652SErik Verbruggen   Bldr.generateNode(CDE, Pred, state);
15610e25031STed Kremenek }
15710e25031STed Kremenek 
1588fdb59f9STed Kremenek void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
1598fdb59f9STed Kremenek                                    ExplodedNode *Pred,
1608fdb59f9STed Kremenek                                    ExplodedNodeSet &Dst) {
1618fdb59f9STed Kremenek   const VarDecl *VD = CS->getExceptionDecl();
162b1279b5cSTed Kremenek   if (!VD) {
163b1279b5cSTed Kremenek     Dst.Add(Pred);
164b1279b5cSTed Kremenek     return;
165b1279b5cSTed Kremenek   }
166b1279b5cSTed Kremenek 
1678fdb59f9STed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
1688fdb59f9STed Kremenek   SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
1698fdb59f9STed Kremenek                                  currentBuilderContext->getCurrentBlockCount());
1708fdb59f9STed Kremenek   ProgramStateRef state = Pred->getState();
1718fdb59f9STed Kremenek   state = state->bindLoc(state->getLValue(VD, LCtx), V);
1728fdb59f9STed Kremenek 
1738fdb59f9STed Kremenek   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
1748fdb59f9STed Kremenek   Bldr.generateNode(CS, Pred, state);
1758fdb59f9STed Kremenek }
1768fdb59f9STed Kremenek 
17710e25031STed Kremenek void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
17810e25031STed Kremenek                                     ExplodedNodeSet &Dst) {
179e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
180e594034fSAnna Zaks 
18110e25031STed Kremenek   // Get the this object region from StoreManager.
182632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
18310e25031STed Kremenek   const MemRegion *R =
18410e25031STed Kremenek     svalBuilder.getRegionManager().getCXXThisRegion(
18510e25031STed Kremenek                                   getContext().getCanonicalType(TE->getType()),
186632e3b7eSTed Kremenek                                                     LCtx);
18710e25031STed Kremenek 
18849b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
18910e25031STed Kremenek   SVal V = state->getSVal(loc::MemRegionVal(R));
190632e3b7eSTed Kremenek   Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
19110e25031STed Kremenek }
192