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