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"
20*b970505dSJordan Rose #include "clang/AST/ParentMap.h"
2110e25031STed Kremenek 
2210e25031STed Kremenek using namespace clang;
2310e25031STed Kremenek using namespace ento;
2410e25031STed Kremenek 
2510e25031STed Kremenek void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
2610e25031STed Kremenek                                           ExplodedNode *Pred,
2710e25031STed Kremenek                                           ExplodedNodeSet &Dst) {
28e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
292a14c695STed Kremenek   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
3049b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
31632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
3210e25031STed Kremenek 
3310e25031STed Kremenek   // Bind the temporary object to the value of the expression. Then bind
3410e25031STed Kremenek   // the expression to the location of the object.
35632e3b7eSTed Kremenek   SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
3610e25031STed Kremenek 
3710e25031STed Kremenek   const MemRegion *R =
38632e3b7eSTed Kremenek     svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
3910e25031STed Kremenek 
4010e25031STed Kremenek   state = state->bindLoc(loc::MemRegionVal(R), V);
41632e3b7eSTed Kremenek   Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
4210e25031STed Kremenek }
4310e25031STed Kremenek 
44*b970505dSJordan Rose static const VarDecl *findDirectConstruction(const DeclStmt *DS,
45*b970505dSJordan Rose                                              const Expr *Init) {
46*b970505dSJordan Rose   for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
47*b970505dSJordan Rose        I != E; ++I) {
48*b970505dSJordan Rose     const VarDecl *Var = dyn_cast<VarDecl>(*I);
49*b970505dSJordan Rose     if (!Var)
50*b970505dSJordan Rose       continue;
51*b970505dSJordan Rose     if (Var->getInit() != Init)
52*b970505dSJordan Rose       continue;
53*b970505dSJordan Rose     // FIXME: We need to decide how copy-elision should work here.
54*b970505dSJordan Rose     if (!Var->isDirectInit())
55*b970505dSJordan Rose       break;
56*b970505dSJordan Rose     if (Var->getType()->isReferenceType())
57*b970505dSJordan Rose       break;
58*b970505dSJordan Rose     return Var;
59*b970505dSJordan Rose   }
60*b970505dSJordan Rose 
61*b970505dSJordan Rose   return 0;
62*b970505dSJordan Rose }
63*b970505dSJordan Rose 
64f3c12ac3SJordan Rose void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
6510e25031STed Kremenek                                        ExplodedNode *Pred,
6610e25031STed Kremenek                                        ExplodedNodeSet &destNodes) {
67*b970505dSJordan Rose   const LocationContext *LCtx = Pred->getLocationContext();
68*b970505dSJordan Rose   const MemRegion *Target = 0;
69*b970505dSJordan Rose 
70*b970505dSJordan Rose   switch (CE->getConstructionKind()) {
71*b970505dSJordan Rose   case CXXConstructExpr::CK_Complete: {
72*b970505dSJordan Rose     // See if we're constructing an existing region.
73*b970505dSJordan Rose     // FIXME: This is inefficient. Not only are we getting the parent of the
74*b970505dSJordan Rose     // CXXConstructExpr, but we also then have to crawl through it if it's a
75*b970505dSJordan Rose     // DeclStmt to find out which variable is being constructed. (The CFG has
76*b970505dSJordan Rose     // one (fake) DeclStmt per Decl, but ParentMap uses the original AST.)
77*b970505dSJordan Rose     const ParentMap &PM = LCtx->getParentMap();
78*b970505dSJordan Rose     if (const DeclStmt *DS = dyn_cast_or_null<DeclStmt>(PM.getParent(CE)))
79*b970505dSJordan Rose       if (const VarDecl *Var = findDirectConstruction(DS, CE))
80*b970505dSJordan Rose         Target = Pred->getState()->getLValue(Var, LCtx).getAsRegion();
81*b970505dSJordan Rose     // If we can't find an existing region to construct into, we'll just
82*b970505dSJordan Rose     // generate a symbolic region, which is fine.
83*b970505dSJordan Rose     break;
84*b970505dSJordan Rose   }
85*b970505dSJordan Rose   case CXXConstructExpr::CK_NonVirtualBase:
86*b970505dSJordan Rose   case CXXConstructExpr::CK_VirtualBase:
87*b970505dSJordan Rose   case CXXConstructExpr::CK_Delegating: {
88*b970505dSJordan Rose     const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
89*b970505dSJordan Rose     Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
90*b970505dSJordan Rose                                               LCtx->getCurrentStackFrame());
91*b970505dSJordan Rose     SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
92*b970505dSJordan Rose 
93*b970505dSJordan Rose     if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) {
94*b970505dSJordan Rose       Target = ThisVal.getAsRegion();
95*b970505dSJordan Rose     } else {
96*b970505dSJordan Rose       // Cast to the base type.
97*b970505dSJordan Rose       QualType BaseTy = CE->getType();
98*b970505dSJordan Rose       SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
99*b970505dSJordan Rose       Target = cast<loc::MemRegionVal>(BaseVal).getRegion();
100*b970505dSJordan Rose     }
101*b970505dSJordan Rose     break;
102*b970505dSJordan Rose   }
103*b970505dSJordan Rose   }
104*b970505dSJordan Rose 
105*b970505dSJordan Rose   CXXConstructorCall Call(CE, Target, Pred->getState(),
10610e25031STed Kremenek                           Pred->getLocationContext());
10710e25031STed Kremenek 
108f3c12ac3SJordan Rose   ExplodedNodeSet DstPreVisit;
109f3c12ac3SJordan Rose   getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
110afe7c2c2SJordan Rose   ExplodedNodeSet DstPreCall;
111afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
112afe7c2c2SJordan Rose                                             Call, *this);
11310e25031STed Kremenek 
114f3c12ac3SJordan Rose   ExplodedNodeSet DstInvalidated;
1153136cf9dSAnna Zaks   StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
116afe7c2c2SJordan Rose   for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
117f3c12ac3SJordan Rose        I != E; ++I)
1183136cf9dSAnna Zaks     defaultEvalCall(Bldr, *I, Call);
11910e25031STed Kremenek 
120afe7c2c2SJordan Rose   ExplodedNodeSet DstPostCall;
121afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
122afe7c2c2SJordan Rose                                              Call, *this);
123afe7c2c2SJordan Rose   getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
12410e25031STed Kremenek }
12510e25031STed Kremenek 
126*b970505dSJordan Rose void ExprEngine::VisitCXXDestructor(QualType ObjectType,
12710e25031STed Kremenek                                     const MemRegion *Dest,
12810e25031STed Kremenek                                     const Stmt *S,
12910e25031STed Kremenek                                     ExplodedNode *Pred,
13010e25031STed Kremenek                                     ExplodedNodeSet &Dst) {
131*b970505dSJordan Rose   const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
132*b970505dSJordan Rose   assert(RecordDecl && "Only CXXRecordDecls should have destructors");
133*b970505dSJordan Rose   const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();
134*b970505dSJordan Rose 
135*b970505dSJordan Rose   CXXDestructorCall Call(DtorDecl, S, Dest, Pred->getState(),
1364ee71b8aSJordan Rose                          Pred->getLocationContext());
137142adc49STed Kremenek 
1384ee71b8aSJordan Rose   ExplodedNodeSet DstPreCall;
1394ee71b8aSJordan Rose   getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
1404ee71b8aSJordan Rose                                             Call, *this);
14110e25031STed Kremenek 
1424ee71b8aSJordan Rose   ExplodedNodeSet DstInvalidated;
1433136cf9dSAnna Zaks   StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
1444ee71b8aSJordan Rose   for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
1454ee71b8aSJordan Rose        I != E; ++I)
1463136cf9dSAnna Zaks     defaultEvalCall(Bldr, *I, Call);
1474ee71b8aSJordan Rose 
1484ee71b8aSJordan Rose   ExplodedNodeSet DstPostCall;
1494ee71b8aSJordan Rose   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
1504ee71b8aSJordan Rose                                              Call, *this);
15110e25031STed Kremenek }
15210e25031STed Kremenek 
15310e25031STed Kremenek void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
15410e25031STed Kremenek                                    ExplodedNodeSet &Dst) {
155a4ee064cSJordan Rose   // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
156a4ee064cSJordan Rose   // Also, we need to decide how allocators actually work -- they're not
157a4ee064cSJordan Rose   // really part of the CXXNewExpr because they happen BEFORE the
158a4ee064cSJordan Rose   // CXXConstructExpr subexpression. See PR12014 for some discussion.
159e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
16010e25031STed Kremenek 
161e594034fSAnna Zaks   unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
162d519cae8STed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
16310e25031STed Kremenek   DefinedOrUnknownSVal symVal =
164a4ee064cSJordan Rose     svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount);
16544320367SJordan Rose   ProgramStateRef State = Pred->getState();
16610e25031STed Kremenek 
167a4ee064cSJordan Rose   // Invalidate placement args.
168a4ee064cSJordan Rose   CXXAllocatorCall Call(CNE, State, LCtx);
169a4ee064cSJordan Rose   State = Call.invalidateRegions(blockCount);
170a4ee064cSJordan Rose 
17110e25031STed Kremenek   if (CNE->isArray()) {
17210e25031STed Kremenek     // FIXME: allocating an array requires simulating the constructors.
17310e25031STed Kremenek     // For now, just return a symbolicated region.
174a4ee064cSJordan Rose     const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
175a4ee064cSJordan Rose     QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
176a4ee064cSJordan Rose     const ElementRegion *EleReg =
177a4ee064cSJordan Rose       getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
17844320367SJordan Rose     State = State->BindExpr(CNE, Pred->getLocationContext(),
179632e3b7eSTed Kremenek                             loc::MemRegionVal(EleReg));
18044320367SJordan Rose     Bldr.generateNode(CNE, Pred, State);
18110e25031STed Kremenek     return;
18210e25031STed Kremenek   }
18310e25031STed Kremenek 
184a4ee064cSJordan Rose   // FIXME: Once we have proper support for CXXConstructExprs inside
185a4ee064cSJordan Rose   // CXXNewExpr, we need to make sure that the constructed object is not
186a4ee064cSJordan Rose   // immediately invalidated here. (The placement call should happen before
187a4ee064cSJordan Rose   // the constructor call anyway.)
18844320367SJordan Rose   FunctionDecl *FD = CNE->getOperatorNew();
18944320367SJordan Rose   if (FD && FD->isReservedGlobalPlacementOperator()) {
19044320367SJordan Rose     // Non-array placement new should always return the placement location.
19144320367SJordan Rose     SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
19244320367SJordan Rose     State = State->BindExpr(CNE, LCtx, PlacementLoc);
19344320367SJordan Rose   } else {
194a4ee064cSJordan Rose     State = State->BindExpr(CNE, LCtx, symVal);
19544320367SJordan Rose   }
19644320367SJordan Rose 
1975089f3b3SJordan Rose   // If the type is not a record, we won't have a CXXConstructExpr as an
1985089f3b3SJordan Rose   // initializer. Copy the value over.
1995089f3b3SJordan Rose   if (const Expr *Init = CNE->getInitializer()) {
2005089f3b3SJordan Rose     if (!isa<CXXConstructExpr>(Init)) {
2015089f3b3SJordan Rose       QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
2025089f3b3SJordan Rose       (void)ObjTy;
2035089f3b3SJordan Rose       assert(!ObjTy->isRecordType());
2045089f3b3SJordan Rose       SVal Location = State->getSVal(CNE, LCtx);
2055089f3b3SJordan Rose       if (isa<Loc>(Location))
2065089f3b3SJordan Rose         State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx));
2075089f3b3SJordan Rose     }
2085089f3b3SJordan Rose   }
2095089f3b3SJordan Rose 
21044320367SJordan Rose   Bldr.generateNode(CNE, Pred, State);
21110e25031STed Kremenek }
21210e25031STed Kremenek 
21310e25031STed Kremenek void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
21410e25031STed Kremenek                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
21564aea652SErik Verbruggen   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
21664aea652SErik Verbruggen   ProgramStateRef state = Pred->getState();
21764aea652SErik Verbruggen   Bldr.generateNode(CDE, Pred, state);
21810e25031STed Kremenek }
21910e25031STed Kremenek 
2208fdb59f9STed Kremenek void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
2218fdb59f9STed Kremenek                                    ExplodedNode *Pred,
2228fdb59f9STed Kremenek                                    ExplodedNodeSet &Dst) {
2238fdb59f9STed Kremenek   const VarDecl *VD = CS->getExceptionDecl();
224b1279b5cSTed Kremenek   if (!VD) {
225b1279b5cSTed Kremenek     Dst.Add(Pred);
226b1279b5cSTed Kremenek     return;
227b1279b5cSTed Kremenek   }
228b1279b5cSTed Kremenek 
2298fdb59f9STed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
2308fdb59f9STed Kremenek   SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
2318fdb59f9STed Kremenek                                  currentBuilderContext->getCurrentBlockCount());
2328fdb59f9STed Kremenek   ProgramStateRef state = Pred->getState();
2338fdb59f9STed Kremenek   state = state->bindLoc(state->getLValue(VD, LCtx), V);
2348fdb59f9STed Kremenek 
2358fdb59f9STed Kremenek   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
2368fdb59f9STed Kremenek   Bldr.generateNode(CS, Pred, state);
2378fdb59f9STed Kremenek }
2388fdb59f9STed Kremenek 
23910e25031STed Kremenek void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
24010e25031STed Kremenek                                     ExplodedNodeSet &Dst) {
241e4e5712cSAnna Zaks   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
242e594034fSAnna Zaks 
24310e25031STed Kremenek   // Get the this object region from StoreManager.
244632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
24510e25031STed Kremenek   const MemRegion *R =
24610e25031STed Kremenek     svalBuilder.getRegionManager().getCXXThisRegion(
24710e25031STed Kremenek                                   getContext().getCanonicalType(TE->getType()),
248632e3b7eSTed Kremenek                                                     LCtx);
24910e25031STed Kremenek 
25049b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
25110e25031STed Kremenek   SVal V = state->getSVal(loc::MemRegionVal(R));
252632e3b7eSTed Kremenek   Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
25310e25031STed Kremenek }
254