blob: 38b5d7f90c007038cf16ca06dc82dc40d85f22a5 [file] [log] [blame]
Ted Kremenek5f764312011-08-20 05:59:58 +00001//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
Zhongxing Xucb7464a2010-04-19 12:51:02 +00002//
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
Argyrios Kyrtzidiseb48bd12011-03-01 01:16:03 +000014#include "clang/StaticAnalyzer/Core/CheckerManager.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000015#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
16#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
Jordan Rose740d4902012-07-02 19:27:35 +000017#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
Zhongxing Xucb7464a2010-04-19 12:51:02 +000018#include "clang/AST/DeclCXX.h"
Ted Kremenek337e4db2012-03-10 01:34:17 +000019#include "clang/AST/StmtCXX.h"
Jordan Rose888c90a2012-07-26 20:04:13 +000020#include "clang/AST/ParentMap.h"
Zhongxing Xucb7464a2010-04-19 12:51:02 +000021
22using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000023using namespace ento;
Zhongxing Xucb7464a2010-04-19 12:51:02 +000024
Ted Kremenekeea72a92011-07-28 23:07:36 +000025void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
26 ExplodedNode *Pred,
27 ExplodedNodeSet &Dst) {
Anna Zaksaa0aeb12011-10-24 21:19:59 +000028 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
Ted Kremenek6a835dd2011-10-02 00:54:48 +000029 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
Ted Kremenek8bef8232012-01-26 21:29:00 +000030 ProgramStateRef state = Pred->getState();
Ted Kremenek5eca4822012-01-06 22:09:28 +000031 const LocationContext *LCtx = Pred->getLocationContext();
Zhongxing Xucb7464a2010-04-19 12:51:02 +000032
Ted Kremenek6a835dd2011-10-02 00:54:48 +000033 // Bind the temporary object to the value of the expression. Then bind
34 // the expression to the location of the object.
Ted Kremenek5eca4822012-01-06 22:09:28 +000035 SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
Zhongxing Xucb7464a2010-04-19 12:51:02 +000036
Ted Kremenek6a835dd2011-10-02 00:54:48 +000037 const MemRegion *R =
Ted Kremenek5eca4822012-01-06 22:09:28 +000038 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
Zhongxing Xucb7464a2010-04-19 12:51:02 +000039
Ted Kremenek6a835dd2011-10-02 00:54:48 +000040 state = state->bindLoc(loc::MemRegionVal(R), V);
Ted Kremenek5eca4822012-01-06 22:09:28 +000041 Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
Zhongxing Xucb7464a2010-04-19 12:51:02 +000042}
43
Jordan Rose888c90a2012-07-26 20:04:13 +000044static const VarDecl *findDirectConstruction(const DeclStmt *DS,
45 const Expr *Init) {
46 for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
47 I != E; ++I) {
48 const VarDecl *Var = dyn_cast<VarDecl>(*I);
49 if (!Var)
50 continue;
51 if (Var->getInit() != Init)
52 continue;
53 // FIXME: We need to decide how copy-elision should work here.
54 if (!Var->isDirectInit())
55 break;
56 if (Var->getType()->isReferenceType())
57 break;
58 return Var;
59 }
60
61 return 0;
62}
63
Jordan Rose362a31c2012-07-02 19:28:12 +000064void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
Ted Kremenek5fe98722011-04-08 22:42:35 +000065 ExplodedNode *Pred,
66 ExplodedNodeSet &destNodes) {
Jordan Rose888c90a2012-07-26 20:04:13 +000067 const LocationContext *LCtx = Pred->getLocationContext();
68 const MemRegion *Target = 0;
69
70 switch (CE->getConstructionKind()) {
71 case CXXConstructExpr::CK_Complete: {
72 // See if we're constructing an existing region.
73 // FIXME: This is inefficient. Not only are we getting the parent of the
74 // CXXConstructExpr, but we also then have to crawl through it if it's a
75 // DeclStmt to find out which variable is being constructed. (The CFG has
76 // one (fake) DeclStmt per Decl, but ParentMap uses the original AST.)
77 const ParentMap &PM = LCtx->getParentMap();
78 if (const DeclStmt *DS = dyn_cast_or_null<DeclStmt>(PM.getParent(CE)))
79 if (const VarDecl *Var = findDirectConstruction(DS, CE))
80 Target = Pred->getState()->getLValue(Var, LCtx).getAsRegion();
81 // If we can't find an existing region to construct into, we'll just
82 // generate a symbolic region, which is fine.
83 break;
84 }
85 case CXXConstructExpr::CK_NonVirtualBase:
86 case CXXConstructExpr::CK_VirtualBase:
87 case CXXConstructExpr::CK_Delegating: {
88 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
89 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
90 LCtx->getCurrentStackFrame());
91 SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
92
93 if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) {
94 Target = ThisVal.getAsRegion();
95 } else {
96 // Cast to the base type.
97 QualType BaseTy = CE->getType();
98 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
99 Target = cast<loc::MemRegionVal>(BaseVal).getRegion();
100 }
101 break;
102 }
103 }
104
105 CXXConstructorCall Call(CE, Target, Pred->getState(),
Jordan Rose362a31c2012-07-02 19:28:12 +0000106 Pred->getLocationContext());
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000107
Jordan Rose362a31c2012-07-02 19:28:12 +0000108 ExplodedNodeSet DstPreVisit;
109 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
Jordan Rose96479da2012-07-02 19:28:16 +0000110 ExplodedNodeSet DstPreCall;
111 getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
112 Call, *this);
Ted Kremenek5fe98722011-04-08 22:42:35 +0000113
Jordan Rose362a31c2012-07-02 19:28:12 +0000114 ExplodedNodeSet DstInvalidated;
Anna Zakse81ce252012-07-19 23:38:13 +0000115 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
Jordan Rose96479da2012-07-02 19:28:16 +0000116 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
Jordan Rose362a31c2012-07-02 19:28:12 +0000117 I != E; ++I)
Anna Zakse81ce252012-07-19 23:38:13 +0000118 defaultEvalCall(Bldr, *I, Call);
Ted Kremenek5fe98722011-04-08 22:42:35 +0000119
Jordan Rose96479da2012-07-02 19:28:16 +0000120 ExplodedNodeSet DstPostCall;
121 getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
122 Call, *this);
123 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000124}
125
Jordan Rose888c90a2012-07-26 20:04:13 +0000126void ExprEngine::VisitCXXDestructor(QualType ObjectType,
127 const MemRegion *Dest,
128 const Stmt *S,
129 ExplodedNode *Pred,
130 ExplodedNodeSet &Dst) {
131 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
132 assert(RecordDecl && "Only CXXRecordDecls should have destructors");
133 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();
134
135 CXXDestructorCall Call(DtorDecl, S, Dest, Pred->getState(),
Jordan Rose8d276d32012-07-10 22:07:47 +0000136 Pred->getLocationContext());
Ted Kremenekb1b5daf2011-10-23 02:31:52 +0000137
Jordan Rose8d276d32012-07-10 22:07:47 +0000138 ExplodedNodeSet DstPreCall;
139 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
140 Call, *this);
Zhongxing Xub13453b2010-11-20 06:53:12 +0000141
Jordan Rose8d276d32012-07-10 22:07:47 +0000142 ExplodedNodeSet DstInvalidated;
Anna Zakse81ce252012-07-19 23:38:13 +0000143 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
Jordan Rose8d276d32012-07-10 22:07:47 +0000144 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
145 I != E; ++I)
Anna Zakse81ce252012-07-19 23:38:13 +0000146 defaultEvalCall(Bldr, *I, Call);
Jordan Rose8d276d32012-07-10 22:07:47 +0000147
148 ExplodedNodeSet DstPostCall;
149 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
150 Call, *this);
Zhongxing Xub13453b2010-11-20 06:53:12 +0000151}
152
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000153void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000154 ExplodedNodeSet &Dst) {
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000155 // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
156 // Also, we need to decide how allocators actually work -- they're not
157 // really part of the CXXNewExpr because they happen BEFORE the
158 // CXXConstructExpr subexpression. See PR12014 for some discussion.
Anna Zaksaa0aeb12011-10-24 21:19:59 +0000159 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
Ted Kremenek41c5f492011-03-31 04:04:48 +0000160
Anna Zaksebae6d02011-10-24 18:26:19 +0000161 unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
Ted Kremenek3133f792012-02-17 23:13:45 +0000162 const LocationContext *LCtx = Pred->getLocationContext();
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000163 DefinedOrUnknownSVal symVal =
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000164 svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount);
Jordan Rosee38c1c22012-06-20 01:32:01 +0000165 ProgramStateRef State = Pred->getState();
Ted Kremenek41c5f492011-03-31 04:04:48 +0000166
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000167 // Invalidate placement args.
168 CXXAllocatorCall Call(CNE, State, LCtx);
169 State = Call.invalidateRegions(blockCount);
170
Ted Kremenek41c5f492011-03-31 04:04:48 +0000171 if (CNE->isArray()) {
172 // FIXME: allocating an array requires simulating the constructors.
173 // For now, just return a symbolicated region.
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000174 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
175 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
176 const ElementRegion *EleReg =
177 getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
Jordan Rosee38c1c22012-06-20 01:32:01 +0000178 State = State->BindExpr(CNE, Pred->getLocationContext(),
Ted Kremenek5eca4822012-01-06 22:09:28 +0000179 loc::MemRegionVal(EleReg));
Jordan Rosee38c1c22012-06-20 01:32:01 +0000180 Bldr.generateNode(CNE, Pred, State);
Ted Kremenek41c5f492011-03-31 04:04:48 +0000181 return;
182 }
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000183
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000184 // FIXME: Once we have proper support for CXXConstructExprs inside
185 // CXXNewExpr, we need to make sure that the constructed object is not
186 // immediately invalidated here. (The placement call should happen before
187 // the constructor call anyway.)
Jordan Rosee38c1c22012-06-20 01:32:01 +0000188 FunctionDecl *FD = CNE->getOperatorNew();
189 if (FD && FD->isReservedGlobalPlacementOperator()) {
190 // Non-array placement new should always return the placement location.
191 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
192 State = State->BindExpr(CNE, LCtx, PlacementLoc);
Jordan Rose70cbf3c2012-07-02 22:21:47 +0000193 } else {
194 State = State->BindExpr(CNE, LCtx, symVal);
Jordan Rosee38c1c22012-06-20 01:32:01 +0000195 }
196
Jordan Rose89e5aaf2012-07-16 23:38:09 +0000197 // If the type is not a record, we won't have a CXXConstructExpr as an
198 // initializer. Copy the value over.
199 if (const Expr *Init = CNE->getInitializer()) {
200 if (!isa<CXXConstructExpr>(Init)) {
201 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
202 (void)ObjTy;
203 assert(!ObjTy->isRecordType());
204 SVal Location = State->getSVal(CNE, LCtx);
205 if (isa<Loc>(Location))
206 State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx));
207 }
208 }
209
Jordan Rosee38c1c22012-06-20 01:32:01 +0000210 Bldr.generateNode(CNE, Pred, State);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000211}
212
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000213void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
Anna Zaksebae6d02011-10-24 18:26:19 +0000214 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
Erik Verbruggen4fafeb62012-02-29 08:42:57 +0000215 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
216 ProgramStateRef state = Pred->getState();
217 Bldr.generateNode(CDE, Pred, state);
Zhongxing Xu6b851382010-04-21 02:17:31 +0000218}
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000219
Ted Kremenek337e4db2012-03-10 01:34:17 +0000220void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
221 ExplodedNode *Pred,
222 ExplodedNodeSet &Dst) {
223 const VarDecl *VD = CS->getExceptionDecl();
Ted Kremenekce612f52012-03-16 05:58:15 +0000224 if (!VD) {
225 Dst.Add(Pred);
226 return;
227 }
228
Ted Kremenek337e4db2012-03-10 01:34:17 +0000229 const LocationContext *LCtx = Pred->getLocationContext();
230 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
231 currentBuilderContext->getCurrentBlockCount());
232 ProgramStateRef state = Pred->getState();
233 state = state->bindLoc(state->getLValue(VD, LCtx), V);
234
235 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
236 Bldr.generateNode(CS, Pred, state);
237}
238
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000239void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
Zhongxing Xu6b851382010-04-21 02:17:31 +0000240 ExplodedNodeSet &Dst) {
Anna Zaksaa0aeb12011-10-24 21:19:59 +0000241 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
Anna Zaksebae6d02011-10-24 18:26:19 +0000242
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000243 // Get the this object region from StoreManager.
Ted Kremenek5eca4822012-01-06 22:09:28 +0000244 const LocationContext *LCtx = Pred->getLocationContext();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000245 const MemRegion *R =
Ted Kremenekc8413fd2010-12-02 07:49:45 +0000246 svalBuilder.getRegionManager().getCXXThisRegion(
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000247 getContext().getCanonicalType(TE->getType()),
Ted Kremenek5eca4822012-01-06 22:09:28 +0000248 LCtx);
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000249
Ted Kremenek8bef8232012-01-26 21:29:00 +0000250 ProgramStateRef state = Pred->getState();
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000251 SVal V = state->getSVal(loc::MemRegionVal(R));
Ted Kremenek5eca4822012-01-06 22:09:28 +0000252 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
Zhongxing Xucb7464a2010-04-19 12:51:02 +0000253}