ExprEngineCXX.cpp revision 075f6fbcb4d858c09e9b138f8dc10d8d3d43d935
1//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the C++ expression evaluation engine. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 16#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 17#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" 18#include "clang/AST/DeclCXX.h" 19#include "clang/AST/StmtCXX.h" 20 21using namespace clang; 22using namespace ento; 23 24void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 25 ExplodedNode *Pred, 26 ExplodedNodeSet &Dst) { 27 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 28 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 29 ProgramStateRef state = Pred->getState(); 30 const LocationContext *LCtx = Pred->getLocationContext(); 31 32 // Bind the temporary object to the value of the expression. Then bind 33 // the expression to the location of the object. 34 SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); 35 36 const MemRegion *R = 37 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); 38 39 state = state->bindLoc(loc::MemRegionVal(R), V); 40 Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); 41} 42 43void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 44 ExplodedNode *Pred, 45 ExplodedNodeSet &destNodes) { 46 const LocationContext *LCtx = Pred->getLocationContext(); 47 ProgramStateRef State = Pred->getState(); 48 49 const MemRegion *Target = 0; 50 51 switch (CE->getConstructionKind()) { 52 case CXXConstructExpr::CK_Complete: { 53 // See if we're constructing an existing region by looking at the next 54 // element in the CFG. 55 const CFGBlock *B = currentBuilderContext->getBlock(); 56 if (currentStmtIdx + 1 < B->size()) { 57 CFGElement Next = (*B)[currentStmtIdx+1]; 58 59 // Is this a constructor for a local variable? 60 if (const CFGStmt *StmtElem = dyn_cast<CFGStmt>(&Next)) 61 if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) 62 if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) 63 if (Var->getInit() == CE) 64 Target = State->getLValue(Var, LCtx).getAsRegion(); 65 66 // FIXME: This will eventually need to handle new-expressions as well. 67 } 68 69 // If we couldn't find an existing region to construct into, we'll just 70 // generate a symbolic region, which is fine. 71 72 break; 73 } 74 case CXXConstructExpr::CK_NonVirtualBase: 75 case CXXConstructExpr::CK_VirtualBase: 76 case CXXConstructExpr::CK_Delegating: { 77 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 78 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 79 LCtx->getCurrentStackFrame()); 80 SVal ThisVal = State->getSVal(ThisPtr); 81 82 if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { 83 Target = ThisVal.getAsRegion(); 84 } else { 85 // Cast to the base type. 86 QualType BaseTy = CE->getType(); 87 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy); 88 Target = cast<loc::MemRegionVal>(BaseVal).getRegion(); 89 } 90 break; 91 } 92 } 93 94 CXXConstructorCall Call(CE, Target, State, LCtx); 95 96 ExplodedNodeSet DstPreVisit; 97 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); 98 ExplodedNodeSet DstPreCall; 99 getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit, 100 Call, *this); 101 102 ExplodedNodeSet DstInvalidated; 103 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext); 104 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 105 I != E; ++I) 106 defaultEvalCall(Bldr, *I, Call); 107 108 ExplodedNodeSet DstPostCall; 109 getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated, 110 Call, *this); 111 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); 112} 113 114void ExprEngine::VisitCXXDestructor(QualType ObjectType, 115 const MemRegion *Dest, 116 const Stmt *S, 117 ExplodedNode *Pred, 118 ExplodedNodeSet &Dst) { 119 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl(); 120 assert(RecordDecl && "Only CXXRecordDecls should have destructors"); 121 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); 122 123 CXXDestructorCall Call(DtorDecl, S, Dest, Pred->getState(), 124 Pred->getLocationContext()); 125 126 ExplodedNodeSet DstPreCall; 127 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 128 Call, *this); 129 130 ExplodedNodeSet DstInvalidated; 131 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext); 132 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 133 I != E; ++I) 134 defaultEvalCall(Bldr, *I, Call); 135 136 ExplodedNodeSet DstPostCall; 137 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 138 Call, *this); 139} 140 141void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 142 ExplodedNodeSet &Dst) { 143 // FIXME: Much of this should eventually migrate to CXXAllocatorCall. 144 // Also, we need to decide how allocators actually work -- they're not 145 // really part of the CXXNewExpr because they happen BEFORE the 146 // CXXConstructExpr subexpression. See PR12014 for some discussion. 147 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 148 149 unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 150 const LocationContext *LCtx = Pred->getLocationContext(); 151 DefinedOrUnknownSVal symVal = 152 svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount); 153 ProgramStateRef State = Pred->getState(); 154 155 // Invalidate placement args. 156 CXXAllocatorCall Call(CNE, State, LCtx); 157 State = Call.invalidateRegions(blockCount); 158 159 if (CNE->isArray()) { 160 // FIXME: allocating an array requires simulating the constructors. 161 // For now, just return a symbolicated region. 162 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 163 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 164 const ElementRegion *EleReg = 165 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 166 State = State->BindExpr(CNE, Pred->getLocationContext(), 167 loc::MemRegionVal(EleReg)); 168 Bldr.generateNode(CNE, Pred, State); 169 return; 170 } 171 172 // FIXME: Once we have proper support for CXXConstructExprs inside 173 // CXXNewExpr, we need to make sure that the constructed object is not 174 // immediately invalidated here. (The placement call should happen before 175 // the constructor call anyway.) 176 FunctionDecl *FD = CNE->getOperatorNew(); 177 if (FD && FD->isReservedGlobalPlacementOperator()) { 178 // Non-array placement new should always return the placement location. 179 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 180 State = State->BindExpr(CNE, LCtx, PlacementLoc); 181 } else { 182 State = State->BindExpr(CNE, LCtx, symVal); 183 } 184 185 // If the type is not a record, we won't have a CXXConstructExpr as an 186 // initializer. Copy the value over. 187 if (const Expr *Init = CNE->getInitializer()) { 188 if (!isa<CXXConstructExpr>(Init)) { 189 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 190 (void)ObjTy; 191 assert(!ObjTy->isRecordType()); 192 SVal Location = State->getSVal(CNE, LCtx); 193 if (isa<Loc>(Location)) 194 State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx)); 195 } 196 } 197 198 Bldr.generateNode(CNE, Pred, State); 199} 200 201void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 202 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 203 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 204 ProgramStateRef state = Pred->getState(); 205 Bldr.generateNode(CDE, Pred, state); 206} 207 208void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 209 ExplodedNode *Pred, 210 ExplodedNodeSet &Dst) { 211 const VarDecl *VD = CS->getExceptionDecl(); 212 if (!VD) { 213 Dst.Add(Pred); 214 return; 215 } 216 217 const LocationContext *LCtx = Pred->getLocationContext(); 218 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 219 currentBuilderContext->getCurrentBlockCount()); 220 ProgramStateRef state = Pred->getState(); 221 state = state->bindLoc(state->getLValue(VD, LCtx), V); 222 223 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 224 Bldr.generateNode(CS, Pred, state); 225} 226 227void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 228 ExplodedNodeSet &Dst) { 229 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 230 231 // Get the this object region from StoreManager. 232 const LocationContext *LCtx = Pred->getLocationContext(); 233 const MemRegion *R = 234 svalBuilder.getRegionManager().getCXXThisRegion( 235 getContext().getCanonicalType(TE->getType()), 236 LCtx); 237 238 ProgramStateRef state = Pred->getState(); 239 SVal V = state->getSVal(loc::MemRegionVal(R)); 240 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 241} 242