1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/AST/ExprCXX.h" |
14 | #include "clang/AST/DeclCXX.h" |
15 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
16 | #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" |
17 | |
18 | using namespace clang; |
19 | using namespace ento; |
20 | using llvm::APSInt; |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | static SVal conjureOffsetSymbolOnLocation( |
29 | SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder, |
30 | unsigned Count, const LocationContext *LCtx) { |
31 | QualType Ty = Expression->getType(); |
32 | if (Other.getAs<Loc>() && |
33 | Ty->isIntegralOrEnumerationType() && |
34 | Symbol.isUnknown()) { |
35 | return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count); |
36 | } |
37 | return Symbol; |
38 | } |
39 | |
40 | void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, |
41 | ExplodedNode *Pred, |
42 | ExplodedNodeSet &Dst) { |
43 | |
44 | Expr *LHS = B->getLHS()->IgnoreParens(); |
45 | Expr *RHS = B->getRHS()->IgnoreParens(); |
46 | |
47 | |
48 | ExplodedNodeSet CheckedSet; |
49 | ExplodedNodeSet Tmp2; |
50 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this); |
51 | |
52 | |
53 | for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end(); |
54 | it != ei; ++it) { |
55 | |
56 | ProgramStateRef state = (*it)->getState(); |
57 | const LocationContext *LCtx = (*it)->getLocationContext(); |
58 | SVal LeftV = state->getSVal(LHS, LCtx); |
59 | SVal RightV = state->getSVal(RHS, LCtx); |
60 | |
61 | BinaryOperator::Opcode Op = B->getOpcode(); |
62 | |
63 | if (Op == BO_Assign) { |
64 | |
65 | |
66 | if (RightV.isUnknown()) { |
67 | unsigned Count = currBldrCtx->blockCount(); |
68 | RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, |
69 | Count); |
70 | } |
71 | |
72 | |
73 | SVal ExprVal = B->isGLValue() ? LeftV : RightV; |
74 | evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal), |
75 | LeftV, RightV); |
76 | continue; |
77 | } |
78 | |
79 | if (!B->isAssignmentOp()) { |
80 | StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx); |
81 | |
82 | if (B->isAdditiveOp()) { |
83 | |
84 | |
85 | unsigned Count = currBldrCtx->blockCount(); |
86 | RightV = conjureOffsetSymbolOnLocation( |
87 | RightV, LeftV, RHS, svalBuilder, Count, LCtx); |
88 | LeftV = conjureOffsetSymbolOnLocation( |
89 | LeftV, RightV, LHS, svalBuilder, Count, LCtx); |
90 | } |
91 | |
92 | |
93 | |
94 | |
95 | if (B->getOpcode() == BO_PtrMemD) |
96 | state = createTemporaryRegionIfNeeded(state, LCtx, LHS); |
97 | |
98 | |
99 | |
100 | SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType()); |
101 | if (!Result.isUnknown()) { |
102 | state = state->BindExpr(B, LCtx, Result); |
103 | } |
104 | |
105 | Bldr.generateNode(B, *it, state); |
106 | continue; |
107 | } |
108 | |
109 | isCompoundAssignmentOp()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 109, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert (B->isCompoundAssignmentOp()); |
110 | |
111 | switch (Op) { |
112 | default: |
113 | llvm_unreachable("Invalid opcode for compound assignment."); |
114 | case BO_MulAssign: Op = BO_Mul; break; |
115 | case BO_DivAssign: Op = BO_Div; break; |
116 | case BO_RemAssign: Op = BO_Rem; break; |
117 | case BO_AddAssign: Op = BO_Add; break; |
118 | case BO_SubAssign: Op = BO_Sub; break; |
119 | case BO_ShlAssign: Op = BO_Shl; break; |
120 | case BO_ShrAssign: Op = BO_Shr; break; |
121 | case BO_AndAssign: Op = BO_And; break; |
122 | case BO_XorAssign: Op = BO_Xor; break; |
123 | case BO_OrAssign: Op = BO_Or; break; |
124 | } |
125 | |
126 | |
127 | |
128 | ExplodedNodeSet Tmp; |
129 | SVal location = LeftV; |
130 | evalLoad(Tmp, B, LHS, *it, state, location); |
131 | |
132 | for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; |
133 | ++I) { |
134 | |
135 | state = (*I)->getState(); |
136 | const LocationContext *LCtx = (*I)->getLocationContext(); |
137 | SVal V = state->getSVal(LHS, LCtx); |
138 | |
139 | |
140 | QualType CTy = |
141 | cast<CompoundAssignOperator>(B)->getComputationResultType(); |
142 | CTy = getContext().getCanonicalType(CTy); |
143 | |
144 | QualType CLHSTy = |
145 | cast<CompoundAssignOperator>(B)->getComputationLHSType(); |
146 | CLHSTy = getContext().getCanonicalType(CLHSTy); |
147 | |
148 | QualType LTy = getContext().getCanonicalType(LHS->getType()); |
149 | |
150 | |
151 | V = svalBuilder.evalCast(V, CLHSTy, LTy); |
152 | |
153 | |
154 | SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy), |
155 | B->getType(), CTy); |
156 | |
157 | |
158 | |
159 | |
160 | SVal LHSVal; |
161 | |
162 | if (Result.isUnknown()) { |
163 | |
164 | |
165 | |
166 | LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy, |
167 | currBldrCtx->blockCount()); |
168 | |
169 | Result = svalBuilder.evalCast(LHSVal, CTy, LTy); |
170 | } |
171 | else { |
172 | |
173 | |
174 | LHSVal = svalBuilder.evalCast(Result, LTy, CTy); |
175 | } |
176 | |
177 | |
178 | |
179 | if (B->isGLValue()) |
180 | state = state->BindExpr(B, LCtx, location); |
181 | else |
182 | state = state->BindExpr(B, LCtx, Result); |
183 | |
184 | evalStore(Tmp2, B, LHS, *I, state, location, LHSVal); |
185 | } |
186 | } |
187 | |
188 | |
189 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this); |
190 | } |
191 | |
192 | void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, |
193 | ExplodedNodeSet &Dst) { |
194 | |
195 | CanQualType T = getContext().getCanonicalType(BE->getType()); |
196 | |
197 | const BlockDecl *BD = BE->getBlockDecl(); |
198 | |
199 | SVal V = svalBuilder.getBlockPointer(BD, T, |
200 | Pred->getLocationContext(), |
201 | currBldrCtx->blockCount()); |
202 | |
203 | ProgramStateRef State = Pred->getState(); |
204 | |
205 | |
206 | |
207 | if (const BlockDataRegion *BDR = |
208 | dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { |
209 | |
210 | BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(), |
211 | E = BDR->referenced_vars_end(); |
212 | |
213 | auto CI = BD->capture_begin(); |
214 | auto CE = BD->capture_end(); |
215 | for (; I != E; ++I) { |
216 | const VarRegion *capturedR = I.getCapturedRegion(); |
217 | const VarRegion *originalR = I.getOriginalRegion(); |
218 | |
219 | |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | const Expr *copyExpr = nullptr; |
226 | if (CI != CE) { |
227 | getVariable() == capturedR->getDecl()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 227, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(CI->getVariable() == capturedR->getDecl()); |
228 | copyExpr = CI->getCopyExpr(); |
229 | CI++; |
230 | } |
231 | |
232 | if (capturedR != originalR) { |
233 | SVal originalV; |
234 | const LocationContext *LCtx = Pred->getLocationContext(); |
235 | if (copyExpr) { |
236 | originalV = State->getSVal(copyExpr, LCtx); |
237 | } else { |
238 | originalV = State->getSVal(loc::MemRegionVal(originalR)); |
239 | } |
240 | State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx); |
241 | } |
242 | } |
243 | } |
244 | |
245 | ExplodedNodeSet Tmp; |
246 | StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); |
247 | Bldr.generateNode(BE, Pred, |
248 | State->BindExpr(BE, Pred->getLocationContext(), V), |
249 | nullptr, ProgramPoint::PostLValueKind); |
250 | |
251 | |
252 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this); |
253 | } |
254 | |
255 | ProgramStateRef ExprEngine::handleLValueBitCast( |
256 | ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx, |
257 | QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr, |
258 | ExplodedNode* Pred) { |
259 | if (T->isLValueReferenceType()) { |
260 | getType()->isLValueReferenceType()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 260, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!CastE->getType()->isLValueReferenceType()); |
261 | ExTy = getContext().getLValueReferenceType(ExTy); |
262 | } else if (T->isRValueReferenceType()) { |
263 | getType()->isRValueReferenceType()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 263, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!CastE->getType()->isRValueReferenceType()); |
264 | ExTy = getContext().getRValueReferenceType(ExTy); |
265 | } |
266 | |
267 | SVal OrigV = state->getSVal(Ex, LCtx); |
268 | SVal V = svalBuilder.evalCast(OrigV, T, ExTy); |
269 | |
270 | if (CastE->getCastKind() == CK_BooleanToSignedIntegral) |
271 | V = evalMinus(V); |
272 | state = state->BindExpr(CastE, LCtx, V); |
273 | if (V.isUnknown() && !OrigV.isUnknown()) { |
274 | state = escapeValue(state, OrigV, PSK_EscapeOther); |
275 | } |
276 | Bldr.generateNode(CastE, Pred, state); |
277 | |
278 | return state; |
279 | } |
280 | |
281 | ProgramStateRef ExprEngine::handleLVectorSplat( |
282 | ProgramStateRef state, const LocationContext* LCtx, const CastExpr* CastE, |
283 | StmtNodeBuilder &Bldr, ExplodedNode* Pred) { |
284 | |
285 | QualType resultType = CastE->getType(); |
286 | if (CastE->isGLValue()) |
287 | resultType = getContext().getPointerType(resultType); |
288 | SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, |
289 | resultType, |
290 | currBldrCtx->blockCount()); |
291 | state = state->BindExpr(CastE, LCtx, result); |
292 | Bldr.generateNode(CastE, Pred, state); |
293 | |
294 | return state; |
295 | } |
296 | |
297 | void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, |
298 | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |
299 | |
300 | ExplodedNodeSet dstPreStmt; |
301 | getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this); |
302 | |
303 | if (CastE->getCastKind() == CK_LValueToRValue) { |
304 | for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end(); |
305 | I!=E; ++I) { |
306 | ExplodedNode *subExprNode = *I; |
307 | ProgramStateRef state = subExprNode->getState(); |
308 | const LocationContext *LCtx = subExprNode->getLocationContext(); |
309 | evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx)); |
310 | } |
311 | return; |
312 | } |
313 | |
314 | |
315 | QualType T = CastE->getType(); |
316 | QualType ExTy = Ex->getType(); |
317 | |
318 | if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE)) |
319 | T = ExCast->getTypeAsWritten(); |
320 | |
321 | StmtNodeBuilder Bldr(dstPreStmt, Dst, *currBldrCtx); |
322 | for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end(); |
323 | I != E; ++I) { |
324 | |
325 | Pred = *I; |
326 | ProgramStateRef state = Pred->getState(); |
327 | const LocationContext *LCtx = Pred->getLocationContext(); |
328 | |
329 | switch (CastE->getCastKind()) { |
330 | case CK_LValueToRValue: |
331 | llvm_unreachable("LValueToRValue casts handled earlier."); |
332 | case CK_ToVoid: |
333 | continue; |
334 | |
335 | |
336 | case CK_ARCProduceObject: |
337 | case CK_ARCConsumeObject: |
338 | case CK_ARCReclaimReturnedObject: |
339 | case CK_ARCExtendBlockObject: |
340 | case CK_CopyAndAutoreleaseBlockObject: |
341 | |
342 | |
343 | |
344 | case CK_AtomicToNonAtomic: |
345 | case CK_NonAtomicToAtomic: |
346 | |
347 | case CK_NoOp: |
348 | case CK_ConstructorConversion: |
349 | case CK_UserDefinedConversion: |
350 | case CK_FunctionToPointerDecay: |
351 | case CK_BuiltinFnToFnPtr: { |
352 | |
353 | ProgramStateRef state = Pred->getState(); |
354 | const LocationContext *LCtx = Pred->getLocationContext(); |
355 | SVal V = state->getSVal(Ex, LCtx); |
356 | state = state->BindExpr(CastE, LCtx, V); |
357 | Bldr.generateNode(CastE, Pred, state); |
358 | continue; |
359 | } |
360 | case CK_MemberPointerToBoolean: |
361 | case CK_PointerToBoolean: { |
362 | SVal V = state->getSVal(Ex, LCtx); |
363 | auto PTMSV = V.getAs<nonloc::PointerToMember>(); |
364 | if (PTMSV) |
365 | V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy); |
366 | if (V.isUndef() || PTMSV) { |
367 | state = state->BindExpr(CastE, LCtx, V); |
368 | Bldr.generateNode(CastE, Pred, state); |
369 | continue; |
370 | } |
371 | |
372 | state = |
373 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
374 | continue; |
375 | } |
376 | case CK_Dependent: |
377 | case CK_ArrayToPointerDecay: |
378 | case CK_BitCast: |
379 | case CK_AddressSpaceConversion: |
380 | case CK_BooleanToSignedIntegral: |
381 | case CK_NullToPointer: |
382 | case CK_IntegralToPointer: |
383 | case CK_PointerToIntegral: { |
384 | SVal V = state->getSVal(Ex, LCtx); |
385 | if (V.getAs<nonloc::PointerToMember>()) { |
386 | state = state->BindExpr(CastE, LCtx, UnknownVal()); |
387 | Bldr.generateNode(CastE, Pred, state); |
388 | continue; |
389 | } |
390 | |
391 | state = |
392 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
393 | continue; |
394 | } |
395 | case CK_IntegralToBoolean: |
396 | case CK_IntegralToFloating: |
397 | case CK_FloatingToIntegral: |
398 | case CK_FloatingToBoolean: |
399 | case CK_FloatingCast: |
400 | case CK_FloatingRealToComplex: |
401 | case CK_FloatingComplexToReal: |
402 | case CK_FloatingComplexToBoolean: |
403 | case CK_FloatingComplexCast: |
404 | case CK_FloatingComplexToIntegralComplex: |
405 | case CK_IntegralRealToComplex: |
406 | case CK_IntegralComplexToReal: |
407 | case CK_IntegralComplexToBoolean: |
408 | case CK_IntegralComplexCast: |
409 | case CK_IntegralComplexToFloatingComplex: |
410 | case CK_CPointerToObjCPointerCast: |
411 | case CK_BlockPointerToObjCPointerCast: |
412 | case CK_AnyPointerToBlockPointerCast: |
413 | case CK_ObjCObjectLValueCast: |
414 | case CK_ZeroToOCLOpaqueType: |
415 | case CK_IntToOCLSampler: |
416 | case CK_LValueBitCast: |
417 | case CK_FixedPointCast: |
418 | case CK_FixedPointToBoolean: |
419 | case CK_FixedPointToIntegral: |
420 | case CK_IntegralToFixedPoint: { |
421 | state = |
422 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
423 | continue; |
424 | } |
425 | case CK_IntegralCast: { |
426 | |
427 | SVal V = state->getSVal(Ex, LCtx); |
428 | V = svalBuilder.evalIntegralCast(state, V, T, ExTy); |
429 | state = state->BindExpr(CastE, LCtx, V); |
430 | Bldr.generateNode(CastE, Pred, state); |
431 | continue; |
432 | } |
433 | case CK_DerivedToBase: |
434 | case CK_UncheckedDerivedToBase: { |
435 | |
436 | SVal val = state->getSVal(Ex, LCtx); |
437 | val = getStoreManager().evalDerivedToBase(val, CastE); |
438 | state = state->BindExpr(CastE, LCtx, val); |
439 | Bldr.generateNode(CastE, Pred, state); |
440 | continue; |
441 | } |
442 | |
443 | case CK_Dynamic: { |
444 | SVal val = state->getSVal(Ex, LCtx); |
445 | |
446 | |
447 | QualType resultType = CastE->getType(); |
448 | if (CastE->isGLValue()) |
449 | resultType = getContext().getPointerType(resultType); |
450 | |
451 | bool Failed = false; |
452 | |
453 | |
454 | if (val.isZeroConstant()) |
455 | Failed = true; |
456 | |
457 | else |
458 | val = getStoreManager().attemptDownCast(val, T, Failed); |
459 | |
460 | if (Failed) { |
461 | if (T->isReferenceType()) { |
462 | |
463 | |
464 | Bldr.generateSink(CastE, Pred, state); |
465 | continue; |
466 | } else { |
467 | |
468 | state = state->BindExpr(CastE, LCtx, svalBuilder.makeNull()); |
469 | } |
470 | } else { |
471 | |
472 | if (val.isUnknown()) { |
473 | DefinedOrUnknownSVal NewSym = |
474 | svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, |
475 | currBldrCtx->blockCount()); |
476 | state = state->BindExpr(CastE, LCtx, NewSym); |
477 | } else |
478 | |
479 | state = state->BindExpr(CastE, LCtx, val); |
480 | } |
481 | Bldr.generateNode(CastE, Pred, state); |
482 | continue; |
483 | } |
484 | case CK_BaseToDerived: { |
485 | SVal val = state->getSVal(Ex, LCtx); |
486 | QualType resultType = CastE->getType(); |
487 | if (CastE->isGLValue()) |
488 | resultType = getContext().getPointerType(resultType); |
489 | |
490 | bool Failed = false; |
491 | |
492 | if (!val.isConstant()) { |
493 | val = getStoreManager().attemptDownCast(val, T, Failed); |
494 | } |
495 | |
496 | |
497 | if (Failed || val.isUnknown()) { |
498 | val = |
499 | svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, |
500 | currBldrCtx->blockCount()); |
501 | } |
502 | state = state->BindExpr(CastE, LCtx, val); |
503 | Bldr.generateNode(CastE, Pred, state); |
504 | continue; |
505 | } |
506 | case CK_NullToMemberPointer: { |
507 | SVal V = svalBuilder.getMemberPointer(nullptr); |
508 | state = state->BindExpr(CastE, LCtx, V); |
509 | Bldr.generateNode(CastE, Pred, state); |
510 | continue; |
511 | } |
512 | case CK_DerivedToBaseMemberPointer: |
513 | case CK_BaseToDerivedMemberPointer: |
514 | case CK_ReinterpretMemberPointer: { |
515 | SVal V = state->getSVal(Ex, LCtx); |
516 | if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) { |
517 | SVal CastedPTMSV = svalBuilder.makePointerToMember( |
518 | getBasicVals().accumCXXBase( |
519 | llvm::make_range<CastExpr::path_const_iterator>( |
520 | CastE->path_begin(), CastE->path_end()), *PTMSV)); |
521 | state = state->BindExpr(CastE, LCtx, CastedPTMSV); |
522 | Bldr.generateNode(CastE, Pred, state); |
523 | continue; |
524 | } |
525 | |
526 | state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred); |
527 | continue; |
528 | } |
529 | |
530 | case CK_ToUnion: |
531 | case CK_VectorSplat: { |
532 | state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred); |
533 | continue; |
534 | } |
535 | } |
536 | } |
537 | } |
538 | |
539 | void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, |
540 | ExplodedNode *Pred, |
541 | ExplodedNodeSet &Dst) { |
542 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
543 | |
544 | ProgramStateRef State = Pred->getState(); |
545 | const LocationContext *LCtx = Pred->getLocationContext(); |
546 | |
547 | const Expr *Init = CL->getInitializer(); |
548 | SVal V = State->getSVal(CL->getInitializer(), LCtx); |
549 | |
550 | if (isa<CXXConstructExpr>(Init) || isa<CXXStdInitializerListExpr>(Init)) { |
551 | |
552 | } else { |
553 | (Init)", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 553, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isa<InitListExpr>(Init)); |
554 | Loc CLLoc = State->getLValue(CL, LCtx); |
555 | State = State->bindLoc(CLLoc, V, LCtx); |
556 | |
557 | if (CL->isGLValue()) |
558 | V = CLLoc; |
559 | } |
560 | |
561 | B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V)); |
562 | } |
563 | |
564 | void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, |
565 | ExplodedNodeSet &Dst) { |
566 | |
567 | const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin()); |
568 | |
569 | if (!VD) { |
570 | |
571 | Dst.insert(Pred); |
572 | return; |
573 | } |
574 | |
575 | |
576 | ExplodedNodeSet dstPreVisit; |
577 | getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this); |
578 | |
579 | ExplodedNodeSet dstEvaluated; |
580 | StmtNodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx); |
581 | for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); |
582 | I!=E; ++I) { |
583 | ExplodedNode *N = *I; |
584 | ProgramStateRef state = N->getState(); |
585 | const LocationContext *LC = N->getLocationContext(); |
586 | |
587 | |
588 | if (const Expr *InitEx = VD->getInit()) { |
589 | |
590 | |
591 | ExplodedNode *UpdatedN = N; |
592 | SVal InitVal = state->getSVal(InitEx, LC); |
593 | |
594 | isSingleDecl()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 594, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(DS->isSingleDecl()); |
595 | if (getObjectUnderConstruction(state, DS, LC)) { |
596 | state = finishObjectConstruction(state, DS, LC); |
597 | |
598 | |
599 | B.generateNode(DS, UpdatedN, state); |
600 | } else { |
601 | |
602 | |
603 | if (InitVal.isUnknown()) { |
604 | QualType Ty = InitEx->getType(); |
605 | if (InitEx->isGLValue()) { |
606 | Ty = getContext().getPointerType(Ty); |
607 | } |
608 | |
609 | InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty, |
610 | currBldrCtx->blockCount()); |
611 | } |
612 | |
613 | |
614 | B.takeNodes(UpdatedN); |
615 | ExplodedNodeSet Dst2; |
616 | evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, LC), InitVal, true); |
617 | B.addNodes(Dst2); |
618 | } |
619 | } |
620 | else { |
621 | B.generateNode(DS, N, state); |
622 | } |
623 | } |
624 | |
625 | getCheckerManager().runCheckersForPostStmt(Dst, B.getResults(), DS, *this); |
626 | } |
627 | |
628 | void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, |
629 | ExplodedNodeSet &Dst) { |
630 | getOpcode() == BO_LAnd || B->getOpcode() == BO_LOr", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 631, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(B->getOpcode() == BO_LAnd || |
631 | getOpcode() == BO_LAnd || B->getOpcode() == BO_LOr", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 631, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> B->getOpcode() == BO_LOr); |
632 | |
633 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
634 | ProgramStateRef state = Pred->getState(); |
635 | |
636 | if (B->getType()->isVectorType()) { |
637 | |
638 | |
639 | |
640 | |
641 | |
642 | Bldr.generateNode(B, Pred, state); |
643 | return; |
644 | } |
645 | |
646 | ExplodedNode *N = Pred; |
647 | while (!N->getLocation().getAs<BlockEntrance>()) { |
648 | ProgramPoint P = N->getLocation(); |
649 | ()|| P.getAs()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 649, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>()); |
650 | (void) P; |
651 | pred_size() == 1", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 651, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(N->pred_size() == 1); |
652 | N = *N->pred_begin(); |
653 | } |
654 | pred_size() == 1", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 654, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(N->pred_size() == 1); |
655 | N = *N->pred_begin(); |
656 | BlockEdge BE = N->getLocation().castAs<BlockEdge>(); |
657 | SVal X; |
658 | |
659 | |
660 | |
661 | |
662 | const CFGBlock *SrcBlock = BE.getSrc(); |
663 | |
664 | CFGTerminator T = SrcBlock->getTerminator(); |
665 | if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) { |
666 | (void) Term; |
667 | isLogicalOp()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 667, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Term->isLogicalOp()); |
668 | succ_size() == 2", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 668, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(SrcBlock->succ_size() == 2); |
669 | |
670 | unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0; |
671 | X = svalBuilder.makeIntVal(constant, B->getType()); |
672 | } |
673 | else { |
674 | |
675 | |
676 | |
677 | empty()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 677, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!SrcBlock->empty()); |
678 | CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>(); |
679 | const Expr *RHS = cast<Expr>(Elem.getStmt()); |
680 | SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext()); |
681 | |
682 | if (RHSVal.isUndef()) { |
683 | X = RHSVal; |
684 | } else { |
685 | |
686 | |
687 | |
688 | nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); |
689 | X = evalBinOp(N->getState(), BO_NE, |
690 | svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()), |
691 | Zero, B->getType()); |
692 | } |
693 | } |
694 | Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); |
695 | } |
696 | |
697 | void ExprEngine::VisitInitListExpr(const InitListExpr *IE, |
698 | ExplodedNode *Pred, |
699 | ExplodedNodeSet &Dst) { |
700 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
701 | |
702 | ProgramStateRef state = Pred->getState(); |
703 | const LocationContext *LCtx = Pred->getLocationContext(); |
704 | QualType T = getContext().getCanonicalType(IE->getType()); |
705 | unsigned NumInitElements = IE->getNumInits(); |
706 | |
707 | if (!IE->isGLValue() && !IE->isTransparent() && |
708 | (T->isArrayType() || T->isRecordType() || T->isVectorType() || |
709 | T->isAnyComplexType())) { |
710 | llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); |
711 | |
712 | |
713 | |
714 | if (NumInitElements == 0) { |
715 | SVal V = svalBuilder.makeCompoundVal(T, vals); |
716 | B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); |
717 | return; |
718 | } |
719 | |
720 | for (InitListExpr::const_reverse_iterator it = IE->rbegin(), |
721 | ei = IE->rend(); it != ei; ++it) { |
722 | SVal V = state->getSVal(cast<Expr>(*it), LCtx); |
723 | vals = getBasicVals().prependSVal(V, vals); |
724 | } |
725 | |
726 | B.generateNode(IE, Pred, |
727 | state->BindExpr(IE, LCtx, |
728 | svalBuilder.makeCompoundVal(T, vals))); |
729 | return; |
730 | } |
731 | |
732 | |
733 | |
734 | |
735 | assert(NumInitElements <= 1); |
736 | |
737 | SVal V; |
738 | if (NumInitElements == 0) |
739 | V = getSValBuilder().makeZeroVal(T); |
740 | else |
741 | V = state->getSVal(IE->getInit(0), LCtx); |
742 | |
743 | B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); |
744 | } |
745 | |
746 | void ExprEngine::VisitGuardedExpr(const Expr *Ex, |
747 | const Expr *L, |
748 | const Expr *R, |
749 | ExplodedNode *Pred, |
750 | ExplodedNodeSet &Dst) { |
751 | assert(L && R); |
752 | |
753 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
754 | ProgramStateRef state = Pred->getState(); |
755 | const LocationContext *LCtx = Pred->getLocationContext(); |
756 | const CFGBlock *SrcBlock = nullptr; |
757 | |
758 | |
759 | ProgramStateRef SrcState = state; |
760 | for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) { |
761 | ProgramPoint PP = N->getLocation(); |
762 | if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) { |
763 | |
764 | |
765 | |
766 | |
767 | |
768 | continue; |
769 | } |
770 | SrcBlock = PP.castAs<BlockEdge>().getSrc(); |
771 | SrcState = N->getState(); |
772 | break; |
773 | } |
774 | |
775 | (0) . __assert_fail ("SrcBlock && \"missing function entry\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 775, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(SrcBlock && "missing function entry"); |
776 | |
777 | |
778 | |
779 | bool hasValue = false; |
780 | SVal V; |
781 | |
782 | for (CFGElement CE : llvm::reverse(*SrcBlock)) { |
783 | if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) { |
784 | const Expr *ValEx = cast<Expr>(CS->getStmt()); |
785 | ValEx = ValEx->IgnoreParens(); |
786 | |
787 | |
788 | |
789 | if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L)) |
790 | L = OpaqueEx->getSourceExpr(); |
791 | |
792 | |
793 | |
794 | if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) { |
795 | hasValue = true; |
796 | V = SrcState->getSVal(ValEx, LCtx); |
797 | } |
798 | break; |
799 | } |
800 | } |
801 | |
802 | if (!hasValue) |
803 | V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, |
804 | currBldrCtx->blockCount()); |
805 | |
806 | |
807 | B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); |
808 | } |
809 | |
810 | void ExprEngine:: |
811 | VisitOffsetOfExpr(const OffsetOfExpr *OOE, |
812 | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |
813 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
814 | Expr::EvalResult Result; |
815 | if (OOE->EvaluateAsInt(Result, getContext())) { |
816 | APSInt IV = Result.Val.getInt(); |
817 | getType())", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 817, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); |
818 | getType()->isBuiltinType()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 818, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(OOE->getType()->isBuiltinType()); |
819 | getType()->getAs()->isInteger()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 819, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(OOE->getType()->getAs<BuiltinType>()->isInteger()); |
820 | getType()->isSignedIntegerType()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 820, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(IV.isSigned() == OOE->getType()->isSignedIntegerType()); |
821 | SVal X = svalBuilder.makeIntVal(IV); |
822 | B.generateNode(OOE, Pred, |
823 | Pred->getState()->BindExpr(OOE, Pred->getLocationContext(), |
824 | X)); |
825 | } |
826 | |
827 | } |
828 | |
829 | |
830 | void ExprEngine:: |
831 | VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, |
832 | ExplodedNode *Pred, |
833 | ExplodedNodeSet &Dst) { |
834 | |
835 | ExplodedNodeSet CheckedSet; |
836 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); |
837 | |
838 | ExplodedNodeSet EvalSet; |
839 | StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); |
840 | |
841 | QualType T = Ex->getTypeOfArgument(); |
842 | |
843 | for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); |
844 | I != E; ++I) { |
845 | if (Ex->getKind() == UETT_SizeOf) { |
846 | if (!T->isIncompleteType() && !T->isConstantSizeType()) { |
847 | (0) . __assert_fail ("T->isVariableArrayType() && \"Unknown non-constant-sized type.\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 847, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); |
848 | |
849 | |
850 | |
851 | continue; |
852 | } else if (T->getAs<ObjCObjectType>()) { |
853 | |
854 | |
855 | |
856 | continue; |
857 | } |
858 | } |
859 | |
860 | APSInt Value = Ex->EvaluateKnownConstInt(getContext()); |
861 | CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); |
862 | |
863 | ProgramStateRef state = (*I)->getState(); |
864 | state = state->BindExpr(Ex, (*I)->getLocationContext(), |
865 | svalBuilder.makeIntVal(amt.getQuantity(), |
866 | Ex->getType())); |
867 | Bldr.generateNode(Ex, *I, state); |
868 | } |
869 | |
870 | getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this); |
871 | } |
872 | |
873 | void ExprEngine::handleUOExtension(ExplodedNodeSet::iterator I, |
874 | const UnaryOperator *U, |
875 | StmtNodeBuilder &Bldr) { |
876 | |
877 | |
878 | |
879 | |
880 | |
881 | |
882 | |
883 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
884 | ProgramStateRef state = (*I)->getState(); |
885 | const LocationContext *LCtx = (*I)->getLocationContext(); |
886 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, |
887 | state->getSVal(Ex, LCtx))); |
888 | } |
889 | |
890 | void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred, |
891 | ExplodedNodeSet &Dst) { |
892 | |
893 | ExplodedNodeSet CheckedSet; |
894 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this); |
895 | |
896 | ExplodedNodeSet EvalSet; |
897 | StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); |
898 | |
899 | for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); |
900 | I != E; ++I) { |
901 | switch (U->getOpcode()) { |
902 | default: { |
903 | Bldr.takeNodes(*I); |
904 | ExplodedNodeSet Tmp; |
905 | VisitIncrementDecrementOperator(U, *I, Tmp); |
906 | Bldr.addNodes(Tmp); |
907 | break; |
908 | } |
909 | case UO_Real: { |
910 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
911 | |
912 | |
913 | if (Ex->getType()->isAnyComplexType()) { |
914 | |
915 | break; |
916 | } |
917 | |
918 | |
919 | getType() == Ex->getType()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 919, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert (U->getType() == Ex->getType()); |
920 | ProgramStateRef state = (*I)->getState(); |
921 | const LocationContext *LCtx = (*I)->getLocationContext(); |
922 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, |
923 | state->getSVal(Ex, LCtx))); |
924 | break; |
925 | } |
926 | |
927 | case UO_Imag: { |
928 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
929 | |
930 | if (Ex->getType()->isAnyComplexType()) { |
931 | |
932 | break; |
933 | } |
934 | |
935 | ProgramStateRef state = (*I)->getState(); |
936 | const LocationContext *LCtx = (*I)->getLocationContext(); |
937 | SVal X = svalBuilder.makeZeroVal(Ex->getType()); |
938 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, X)); |
939 | break; |
940 | } |
941 | |
942 | case UO_AddrOf: { |
943 | |
944 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
945 | if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex)) { |
946 | const ValueDecl *VD = DRE->getDecl(); |
947 | |
948 | if (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD)) { |
949 | ProgramStateRef State = (*I)->getState(); |
950 | const LocationContext *LCtx = (*I)->getLocationContext(); |
951 | SVal SV = svalBuilder.getMemberPointer(cast<DeclaratorDecl>(VD)); |
952 | Bldr.generateNode(U, *I, State->BindExpr(U, LCtx, SV)); |
953 | break; |
954 | } |
955 | } |
956 | |
957 | handleUOExtension(I, U, Bldr); |
958 | break; |
959 | } |
960 | case UO_Plus: |
961 | isGLValue()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 961, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!U->isGLValue()); |
962 | LLVM_FALLTHROUGH; |
963 | case UO_Deref: |
964 | case UO_Extension: { |
965 | handleUOExtension(I, U, Bldr); |
966 | break; |
967 | } |
968 | |
969 | case UO_LNot: |
970 | case UO_Minus: |
971 | case UO_Not: { |
972 | isGLValue()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 972, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert (!U->isGLValue()); |
973 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
974 | ProgramStateRef state = (*I)->getState(); |
975 | const LocationContext *LCtx = (*I)->getLocationContext(); |
976 | |
977 | |
978 | SVal V = state->getSVal(Ex, LCtx); |
979 | |
980 | if (V.isUnknownOrUndef()) { |
981 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V)); |
982 | break; |
983 | } |
984 | |
985 | switch (U->getOpcode()) { |
986 | default: |
987 | llvm_unreachable("Invalid Opcode."); |
988 | case UO_Not: |
989 | |
990 | state = state->BindExpr(U, LCtx, evalComplement(V.castAs<NonLoc>())); |
991 | break; |
992 | case UO_Minus: |
993 | |
994 | state = state->BindExpr(U, LCtx, evalMinus(V.castAs<NonLoc>())); |
995 | break; |
996 | case UO_LNot: |
997 | |
998 | |
999 | |
1000 | |
1001 | SVal Result; |
1002 | if (Optional<Loc> LV = V.getAs<Loc>()) { |
1003 | Loc X = svalBuilder.makeNullWithType(Ex->getType()); |
1004 | Result = evalBinOp(state, BO_EQ, *LV, X, U->getType()); |
1005 | } else if (Ex->getType()->isFloatingType()) { |
1006 | |
1007 | Result = UnknownVal(); |
1008 | } else { |
1009 | nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType())); |
1010 | Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X, |
1011 | U->getType()); |
1012 | } |
1013 | |
1014 | state = state->BindExpr(U, LCtx, Result); |
1015 | break; |
1016 | } |
1017 | Bldr.generateNode(U, *I, state); |
1018 | break; |
1019 | } |
1020 | } |
1021 | } |
1022 | |
1023 | getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, U, *this); |
1024 | } |
1025 | |
1026 | void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, |
1027 | ExplodedNode *Pred, |
1028 | ExplodedNodeSet &Dst) { |
1029 | |
1030 | isIncrementDecrementOp()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 1030, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert (U->isIncrementDecrementOp()); |
1031 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
1032 | |
1033 | const LocationContext *LCtx = Pred->getLocationContext(); |
1034 | ProgramStateRef state = Pred->getState(); |
1035 | SVal loc = state->getSVal(Ex, LCtx); |
1036 | |
1037 | |
1038 | ExplodedNodeSet Tmp; |
1039 | evalLoad(Tmp, U, Ex, Pred, state, loc); |
1040 | |
1041 | ExplodedNodeSet Dst2; |
1042 | StmtNodeBuilder Bldr(Tmp, Dst2, *currBldrCtx); |
1043 | for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end();I!=E;++I) { |
1044 | |
1045 | state = (*I)->getState(); |
1046 | getLocationContext()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp", 1046, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(LCtx == (*I)->getLocationContext()); |
1047 | SVal V2_untested = state->getSVal(Ex, LCtx); |
1048 | |
1049 | |
1050 | if (V2_untested.isUnknownOrUndef()) { |
1051 | state = state->BindExpr(U, LCtx, V2_untested); |
1052 | |
1053 | |
1054 | Bldr.takeNodes(*I); |
1055 | ExplodedNodeSet Dst3; |
1056 | evalStore(Dst3, U, Ex, *I, state, loc, V2_untested); |
1057 | Bldr.addNodes(Dst3); |
1058 | |
1059 | continue; |
1060 | } |
1061 | DefinedSVal V2 = V2_untested.castAs<DefinedSVal>(); |
1062 | |
1063 | |
1064 | BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub; |
1065 | |
1066 | |
1067 | |
1068 | |
1069 | SVal RHS; |
1070 | SVal Result; |
1071 | |
1072 | if (U->getType()->isAnyPointerType()) |
1073 | RHS = svalBuilder.makeArrayIndex(1); |
1074 | else if (U->getType()->isIntegralOrEnumerationType()) |
1075 | RHS = svalBuilder.makeIntVal(1, U->getType()); |
1076 | else |
1077 | RHS = UnknownVal(); |
1078 | |
1079 | |
1080 | |
1081 | |
1082 | |
1083 | if (U->getType()->isBooleanType() && U->isIncrementOp()) |
1084 | Result = svalBuilder.makeTruthVal(true, U->getType()); |
1085 | else |
1086 | Result = evalBinOp(state, Op, V2, RHS, U->getType()); |
1087 | |
1088 | |
1089 | if (Result.isUnknown()){ |
1090 | DefinedOrUnknownSVal SymVal = |
1091 | svalBuilder.conjureSymbolVal(nullptr, U, LCtx, |
1092 | currBldrCtx->blockCount()); |
1093 | Result = SymVal; |
1094 | |
1095 | |
1096 | |
1097 | |
1098 | if (Loc::isLocType(U->getType())) { |
1099 | DefinedOrUnknownSVal Constraint = |
1100 | svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType())); |
1101 | |
1102 | if (!state->assume(Constraint, true)) { |
1103 | |
1104 | |
1105 | Constraint = svalBuilder.evalEQ(state, SymVal, |
1106 | svalBuilder.makeZeroVal(U->getType())); |
1107 | |
1108 | state = state->assume(Constraint, false); |
1109 | assert(state); |
1110 | } |
1111 | } |
1112 | } |
1113 | |
1114 | |
1115 | |
1116 | if (U->isGLValue()) |
1117 | state = state->BindExpr(U, LCtx, loc); |
1118 | else |
1119 | state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result); |
1120 | |
1121 | |
1122 | Bldr.takeNodes(*I); |
1123 | ExplodedNodeSet Dst3; |
1124 | evalStore(Dst3, U, Ex, *I, state, loc, Result); |
1125 | Bldr.addNodes(Dst3); |
1126 | } |
1127 | Dst.insert(Dst2); |
1128 | } |
1129 | |