1 | //=-- ExprEngineC.cpp - ExprEngine support for C expressions ----*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines ExprEngine's support for C expressions. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "clang/AST/DeclCXX.h" |
14 | #include "clang/AST/ExprCXX.h" |
15 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
16 | #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" |
17 | #include <optional> |
18 | |
19 | using namespace clang; |
20 | using namespace ento; |
21 | using llvm::APSInt; |
22 | |
23 | /// Optionally conjure and return a symbol for offset when processing |
24 | /// an expression \p Expression. |
25 | /// If \p Other is a location, conjure a symbol for \p Symbol |
26 | /// (offset) if it is unknown so that memory arithmetic always |
27 | /// results in an ElementRegion. |
28 | /// \p Count The number of times the current basic block was visited. |
29 | static SVal conjureOffsetSymbolOnLocation( |
30 | SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder, |
31 | unsigned Count, const LocationContext *LCtx) { |
32 | QualType Ty = Expression->getType(); |
33 | if (isa<Loc>(Val: Other) && 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 | // FIXME: Prechecks eventually go in ::Visit(). |
48 | ExplodedNodeSet CheckedSet; |
49 | ExplodedNodeSet Tmp2; |
50 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this); |
51 | |
52 | // With both the LHS and RHS evaluated, process the operation itself. |
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 | // EXPERIMENTAL: "Conjured" symbols. |
65 | // FIXME: Handle structs. |
66 | if (RightV.isUnknown()) { |
67 | unsigned Count = currBldrCtx->blockCount(); |
68 | RightV = svalBuilder.conjureSymbolVal(symbolTag: nullptr, expr: B->getRHS(), LCtx, |
69 | count: Count); |
70 | } |
71 | // Simulate the effects of a "store": bind the value of the RHS |
72 | // to the L-Value represented by the LHS. |
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 | // TODO: This can be removed after we enable history tracking with |
84 | // SymSymExpr. |
85 | unsigned Count = currBldrCtx->blockCount(); |
86 | RightV = conjureOffsetSymbolOnLocation( |
87 | Symbol: RightV, Other: LeftV, Expression: RHS, svalBuilder, Count, LCtx); |
88 | LeftV = conjureOffsetSymbolOnLocation( |
89 | Symbol: LeftV, Other: RightV, Expression: LHS, svalBuilder, Count, LCtx); |
90 | } |
91 | |
92 | // Although we don't yet model pointers-to-members, we do need to make |
93 | // sure that the members of temporaries have a valid 'this' pointer for |
94 | // other checks. |
95 | if (B->getOpcode() == BO_PtrMemD) |
96 | state = createTemporaryRegionIfNeeded(State: state, LC: LCtx, InitWithAdjustments: LHS); |
97 | |
98 | // Process non-assignments except commas or short-circuited |
99 | // logical expressions (LAnd and LOr). |
100 | SVal Result = evalBinOp(ST: state, Op, LHS: LeftV, RHS: RightV, T: B->getType()); |
101 | if (!Result.isUnknown()) { |
102 | state = state->BindExpr(B, LCtx, Result); |
103 | } else { |
104 | // If we cannot evaluate the operation escape the operands. |
105 | state = escapeValues(State: state, Vs: LeftV, K: PSK_EscapeOther); |
106 | state = escapeValues(State: state, Vs: RightV, K: 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 | // Perform a load (the LHS). This performs the checks for |
131 | // null dereferences, and so on. |
132 | ExplodedNodeSet Tmp; |
133 | SVal location = LeftV; |
134 | evalLoad(Tmp, B, LHS, *it, state, location); |
135 | |
136 | for (ExplodedNode *N : Tmp) { |
137 | state = N->getState(); |
138 | const LocationContext *LCtx = N->getLocationContext(); |
139 | SVal V = state->getSVal(LHS, LCtx); |
140 | |
141 | // Get the computation type. |
142 | QualType CTy = |
143 | cast<CompoundAssignOperator>(Val: B)->getComputationResultType(); |
144 | CTy = getContext().getCanonicalType(T: CTy); |
145 | |
146 | QualType CLHSTy = |
147 | cast<CompoundAssignOperator>(Val: B)->getComputationLHSType(); |
148 | CLHSTy = getContext().getCanonicalType(T: CLHSTy); |
149 | |
150 | QualType LTy = getContext().getCanonicalType(T: LHS->getType()); |
151 | |
152 | // Promote LHS. |
153 | V = svalBuilder.evalCast(V, CastTy: CLHSTy, OriginalTy: LTy); |
154 | |
155 | // Compute the result of the operation. |
156 | SVal Result = svalBuilder.evalCast(V: evalBinOp(ST: state, Op, LHS: V, RHS: RightV, T: CTy), |
157 | CastTy: B->getType(), OriginalTy: CTy); |
158 | |
159 | // EXPERIMENTAL: "Conjured" symbols. |
160 | // FIXME: Handle structs. |
161 | |
162 | SVal LHSVal; |
163 | |
164 | if (Result.isUnknown()) { |
165 | // The symbolic value is actually for the type of the left-hand side |
166 | // expression, not the computation type, as this is the value the |
167 | // LValue on the LHS will bind to. |
168 | LHSVal = svalBuilder.conjureSymbolVal(symbolTag: nullptr, expr: B->getRHS(), LCtx, type: LTy, |
169 | count: currBldrCtx->blockCount()); |
170 | // However, we need to convert the symbol to the computation type. |
171 | Result = svalBuilder.evalCast(V: LHSVal, CastTy: CTy, OriginalTy: LTy); |
172 | } else { |
173 | // The left-hand side may bind to a different value then the |
174 | // computation type. |
175 | LHSVal = svalBuilder.evalCast(V: Result, CastTy: LTy, OriginalTy: CTy); |
176 | } |
177 | |
178 | // In C++, assignment and compound assignment operators return an |
179 | // lvalue. |
180 | if (B->isGLValue()) |
181 | state = state->BindExpr(B, LCtx, location); |
182 | else |
183 | state = state->BindExpr(B, LCtx, Result); |
184 | |
185 | evalStore(Tmp2, B, LHS, N, state, location, LHSVal); |
186 | } |
187 | } |
188 | |
189 | // FIXME: postvisits eventually go in ::Visit() |
190 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this); |
191 | } |
192 | |
193 | void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, |
194 | ExplodedNodeSet &Dst) { |
195 | |
196 | CanQualType T = getContext().getCanonicalType(BE->getType()); |
197 | |
198 | const BlockDecl *BD = BE->getBlockDecl(); |
199 | // Get the value of the block itself. |
200 | SVal V = svalBuilder.getBlockPointer(block: BD, locTy: T, |
201 | locContext: Pred->getLocationContext(), |
202 | blockCount: currBldrCtx->blockCount()); |
203 | |
204 | ProgramStateRef State = Pred->getState(); |
205 | |
206 | // If we created a new MemRegion for the block, we should explicitly bind |
207 | // the captured variables. |
208 | if (const BlockDataRegion *BDR = |
209 | dyn_cast_or_null<BlockDataRegion>(Val: V.getAsRegion())) { |
210 | |
211 | auto ReferencedVars = BDR->referenced_vars(); |
212 | auto CI = BD->capture_begin(); |
213 | auto CE = BD->capture_end(); |
214 | for (auto Var : ReferencedVars) { |
215 | const VarRegion *capturedR = Var.getCapturedRegion(); |
216 | const TypedValueRegion *originalR = Var.getOriginalRegion(); |
217 | |
218 | // If the capture had a copy expression, use the result of evaluating |
219 | // that expression, otherwise use the original value. |
220 | // We rely on the invariant that the block declaration's capture variables |
221 | // are a prefix of the BlockDataRegion's referenced vars (which may include |
222 | // referenced globals, etc.) to enable fast lookup of the capture for a |
223 | // given referenced var. |
224 | const Expr *copyExpr = nullptr; |
225 | if (CI != CE) { |
226 | assert(CI->getVariable() == capturedR->getDecl()); |
227 | copyExpr = CI->getCopyExpr(); |
228 | CI++; |
229 | } |
230 | |
231 | if (capturedR != originalR) { |
232 | SVal originalV; |
233 | const LocationContext *LCtx = Pred->getLocationContext(); |
234 | if (copyExpr) { |
235 | originalV = State->getSVal(copyExpr, LCtx); |
236 | } else { |
237 | originalV = State->getSVal(loc::MemRegionVal(originalR)); |
238 | } |
239 | State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx); |
240 | } |
241 | } |
242 | } |
243 | |
244 | ExplodedNodeSet Tmp; |
245 | StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); |
246 | Bldr.generateNode(BE, Pred, |
247 | State->BindExpr(BE, Pred->getLocationContext(), V), |
248 | nullptr, ProgramPoint::PostLValueKind); |
249 | |
250 | // FIXME: Move all post/pre visits to ::Visit(). |
251 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this); |
252 | } |
253 | |
254 | ProgramStateRef ExprEngine::handleLValueBitCast( |
255 | ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx, |
256 | QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr, |
257 | ExplodedNode* Pred) { |
258 | if (T->isLValueReferenceType()) { |
259 | assert(!CastE->getType()->isLValueReferenceType()); |
260 | ExTy = getContext().getLValueReferenceType(T: ExTy); |
261 | } else if (T->isRValueReferenceType()) { |
262 | assert(!CastE->getType()->isRValueReferenceType()); |
263 | ExTy = getContext().getRValueReferenceType(T: ExTy); |
264 | } |
265 | // Delegate to SValBuilder to process. |
266 | SVal OrigV = state->getSVal(Ex, LCtx); |
267 | SVal SimplifiedOrigV = svalBuilder.simplifySVal(State: state, Val: OrigV); |
268 | SVal V = svalBuilder.evalCast(V: SimplifiedOrigV, CastTy: T, OriginalTy: ExTy); |
269 | // Negate the result if we're treating the boolean as a signed i1 |
270 | if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid()) |
271 | V = svalBuilder.evalMinus(val: V.castAs<NonLoc>()); |
272 | |
273 | state = state->BindExpr(CastE, LCtx, V); |
274 | if (V.isUnknown() && !OrigV.isUnknown()) { |
275 | state = escapeValues(State: state, Vs: OrigV, K: PSK_EscapeOther); |
276 | } |
277 | Bldr.generateNode(CastE, Pred, state); |
278 | |
279 | return state; |
280 | } |
281 | |
282 | void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, |
283 | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |
284 | |
285 | ExplodedNodeSet dstPreStmt; |
286 | getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this); |
287 | |
288 | if (CastE->getCastKind() == CK_LValueToRValue || |
289 | CastE->getCastKind() == CK_LValueToRValueBitCast) { |
290 | for (ExplodedNode *subExprNode : dstPreStmt) { |
291 | ProgramStateRef state = subExprNode->getState(); |
292 | const LocationContext *LCtx = subExprNode->getLocationContext(); |
293 | evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx)); |
294 | } |
295 | return; |
296 | } |
297 | |
298 | // All other casts. |
299 | QualType T = CastE->getType(); |
300 | QualType ExTy = Ex->getType(); |
301 | |
302 | if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(Val: CastE)) |
303 | T = ExCast->getTypeAsWritten(); |
304 | |
305 | StmtNodeBuilder Bldr(dstPreStmt, Dst, *currBldrCtx); |
306 | for (ExplodedNode *Pred : dstPreStmt) { |
307 | ProgramStateRef state = Pred->getState(); |
308 | const LocationContext *LCtx = Pred->getLocationContext(); |
309 | |
310 | switch (CastE->getCastKind()) { |
311 | case CK_LValueToRValue: |
312 | case CK_LValueToRValueBitCast: |
313 | llvm_unreachable("LValueToRValue casts handled earlier." ); |
314 | case CK_ToVoid: |
315 | continue; |
316 | // The analyzer doesn't do anything special with these casts, |
317 | // since it understands retain/release semantics already. |
318 | case CK_ARCProduceObject: |
319 | case CK_ARCConsumeObject: |
320 | case CK_ARCReclaimReturnedObject: |
321 | case CK_ARCExtendBlockObject: // Fall-through. |
322 | case CK_CopyAndAutoreleaseBlockObject: |
323 | // The analyser can ignore atomic casts for now, although some future |
324 | // checkers may want to make certain that you're not modifying the same |
325 | // value through atomic and nonatomic pointers. |
326 | case CK_AtomicToNonAtomic: |
327 | case CK_NonAtomicToAtomic: |
328 | // True no-ops. |
329 | case CK_NoOp: |
330 | case CK_ConstructorConversion: |
331 | case CK_UserDefinedConversion: |
332 | case CK_FunctionToPointerDecay: |
333 | case CK_BuiltinFnToFnPtr: { |
334 | // Copy the SVal of Ex to CastE. |
335 | ProgramStateRef state = Pred->getState(); |
336 | const LocationContext *LCtx = Pred->getLocationContext(); |
337 | SVal V = state->getSVal(Ex, LCtx); |
338 | state = state->BindExpr(CastE, LCtx, V); |
339 | Bldr.generateNode(CastE, Pred, state); |
340 | continue; |
341 | } |
342 | case CK_MemberPointerToBoolean: |
343 | case CK_PointerToBoolean: { |
344 | SVal V = state->getSVal(Ex, LCtx); |
345 | auto PTMSV = V.getAs<nonloc::PointerToMember>(); |
346 | if (PTMSV) |
347 | V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy); |
348 | if (V.isUndef() || PTMSV) { |
349 | state = state->BindExpr(CastE, LCtx, V); |
350 | Bldr.generateNode(CastE, Pred, state); |
351 | continue; |
352 | } |
353 | // Explicitly proceed with default handler for this case cascade. |
354 | state = |
355 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
356 | continue; |
357 | } |
358 | case CK_Dependent: |
359 | case CK_ArrayToPointerDecay: |
360 | case CK_BitCast: |
361 | case CK_AddressSpaceConversion: |
362 | case CK_BooleanToSignedIntegral: |
363 | case CK_IntegralToPointer: |
364 | case CK_PointerToIntegral: { |
365 | SVal V = state->getSVal(Ex, LCtx); |
366 | if (isa<nonloc::PointerToMember>(Val: V)) { |
367 | state = state->BindExpr(CastE, LCtx, UnknownVal()); |
368 | Bldr.generateNode(CastE, Pred, state); |
369 | continue; |
370 | } |
371 | // Explicitly proceed with default handler for this case cascade. |
372 | state = |
373 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
374 | continue; |
375 | } |
376 | case CK_IntegralToBoolean: |
377 | case CK_IntegralToFloating: |
378 | case CK_FloatingToIntegral: |
379 | case CK_FloatingToBoolean: |
380 | case CK_FloatingCast: |
381 | case CK_FloatingRealToComplex: |
382 | case CK_FloatingComplexToReal: |
383 | case CK_FloatingComplexToBoolean: |
384 | case CK_FloatingComplexCast: |
385 | case CK_FloatingComplexToIntegralComplex: |
386 | case CK_IntegralRealToComplex: |
387 | case CK_IntegralComplexToReal: |
388 | case CK_IntegralComplexToBoolean: |
389 | case CK_IntegralComplexCast: |
390 | case CK_IntegralComplexToFloatingComplex: |
391 | case CK_CPointerToObjCPointerCast: |
392 | case CK_BlockPointerToObjCPointerCast: |
393 | case CK_AnyPointerToBlockPointerCast: |
394 | case CK_ObjCObjectLValueCast: |
395 | case CK_ZeroToOCLOpaqueType: |
396 | case CK_IntToOCLSampler: |
397 | case CK_LValueBitCast: |
398 | case CK_FloatingToFixedPoint: |
399 | case CK_FixedPointToFloating: |
400 | case CK_FixedPointCast: |
401 | case CK_FixedPointToBoolean: |
402 | case CK_FixedPointToIntegral: |
403 | case CK_IntegralToFixedPoint: { |
404 | state = |
405 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
406 | continue; |
407 | } |
408 | case CK_IntegralCast: { |
409 | // Delegate to SValBuilder to process. |
410 | SVal V = state->getSVal(Ex, LCtx); |
411 | if (AMgr.options.ShouldSupportSymbolicIntegerCasts) |
412 | V = svalBuilder.evalCast(V, CastTy: T, OriginalTy: ExTy); |
413 | else |
414 | V = svalBuilder.evalIntegralCast(state, val: V, castTy: T, originalType: ExTy); |
415 | state = state->BindExpr(CastE, LCtx, V); |
416 | Bldr.generateNode(CastE, Pred, state); |
417 | continue; |
418 | } |
419 | case CK_DerivedToBase: |
420 | case CK_UncheckedDerivedToBase: { |
421 | // For DerivedToBase cast, delegate to the store manager. |
422 | SVal val = state->getSVal(Ex, LCtx); |
423 | val = getStoreManager().evalDerivedToBase(Derived: val, Cast: CastE); |
424 | state = state->BindExpr(CastE, LCtx, val); |
425 | Bldr.generateNode(CastE, Pred, state); |
426 | continue; |
427 | } |
428 | // Handle C++ dyn_cast. |
429 | case CK_Dynamic: { |
430 | SVal val = state->getSVal(Ex, LCtx); |
431 | |
432 | // Compute the type of the result. |
433 | QualType resultType = CastE->getType(); |
434 | if (CastE->isGLValue()) |
435 | resultType = getContext().getPointerType(T: resultType); |
436 | |
437 | bool Failed = true; |
438 | |
439 | // Check if the value being cast does not evaluates to 0. |
440 | if (!val.isZeroConstant()) |
441 | if (std::optional<SVal> V = |
442 | StateMgr.getStoreManager().evalBaseToDerived(Base: val, DerivedPtrType: T)) { |
443 | val = *V; |
444 | Failed = false; |
445 | } |
446 | |
447 | if (Failed) { |
448 | if (T->isReferenceType()) { |
449 | // A bad_cast exception is thrown if input value is a reference. |
450 | // Currently, we model this, by generating a sink. |
451 | Bldr.generateSink(CastE, Pred, state); |
452 | continue; |
453 | } else { |
454 | // If the cast fails on a pointer, bind to 0. |
455 | state = state->BindExpr(CastE, LCtx, |
456 | svalBuilder.makeNullWithType(type: resultType)); |
457 | } |
458 | } else { |
459 | // If we don't know if the cast succeeded, conjure a new symbol. |
460 | if (val.isUnknown()) { |
461 | DefinedOrUnknownSVal NewSym = |
462 | svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, |
463 | currBldrCtx->blockCount()); |
464 | state = state->BindExpr(CastE, LCtx, NewSym); |
465 | } else |
466 | // Else, bind to the derived region value. |
467 | state = state->BindExpr(CastE, LCtx, val); |
468 | } |
469 | Bldr.generateNode(CastE, Pred, state); |
470 | continue; |
471 | } |
472 | case CK_BaseToDerived: { |
473 | SVal val = state->getSVal(Ex, LCtx); |
474 | QualType resultType = CastE->getType(); |
475 | if (CastE->isGLValue()) |
476 | resultType = getContext().getPointerType(T: resultType); |
477 | |
478 | if (!val.isConstant()) { |
479 | std::optional<SVal> V = getStoreManager().evalBaseToDerived(Base: val, DerivedPtrType: T); |
480 | val = V ? *V : UnknownVal(); |
481 | } |
482 | |
483 | // Failed to cast or the result is unknown, fall back to conservative. |
484 | if (val.isUnknown()) { |
485 | val = |
486 | svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, |
487 | currBldrCtx->blockCount()); |
488 | } |
489 | state = state->BindExpr(CastE, LCtx, val); |
490 | Bldr.generateNode(CastE, Pred, state); |
491 | continue; |
492 | } |
493 | case CK_NullToPointer: { |
494 | SVal V = svalBuilder.makeNullWithType(type: CastE->getType()); |
495 | state = state->BindExpr(CastE, LCtx, V); |
496 | Bldr.generateNode(CastE, Pred, state); |
497 | continue; |
498 | } |
499 | case CK_NullToMemberPointer: { |
500 | SVal V = svalBuilder.getMemberPointer(ND: nullptr); |
501 | state = state->BindExpr(CastE, LCtx, V); |
502 | Bldr.generateNode(CastE, Pred, state); |
503 | continue; |
504 | } |
505 | case CK_DerivedToBaseMemberPointer: |
506 | case CK_BaseToDerivedMemberPointer: |
507 | case CK_ReinterpretMemberPointer: { |
508 | SVal V = state->getSVal(Ex, LCtx); |
509 | if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) { |
510 | SVal CastedPTMSV = |
511 | svalBuilder.makePointerToMember(getBasicVals().accumCXXBase( |
512 | PathRange: CastE->path(), PTM: *PTMSV, kind: CastE->getCastKind())); |
513 | state = state->BindExpr(CastE, LCtx, CastedPTMSV); |
514 | Bldr.generateNode(CastE, Pred, state); |
515 | continue; |
516 | } |
517 | // Explicitly proceed with default handler for this case cascade. |
518 | } |
519 | [[fallthrough]]; |
520 | // Various C++ casts that are not handled yet. |
521 | case CK_ToUnion: |
522 | case CK_MatrixCast: |
523 | case CK_VectorSplat: { |
524 | QualType resultType = CastE->getType(); |
525 | if (CastE->isGLValue()) |
526 | resultType = getContext().getPointerType(T: resultType); |
527 | SVal result = svalBuilder.conjureSymbolVal( |
528 | /*symbolTag=*/nullptr, CastE, LCtx, resultType, |
529 | currBldrCtx->blockCount()); |
530 | state = state->BindExpr(CastE, LCtx, result); |
531 | Bldr.generateNode(CastE, Pred, state); |
532 | continue; |
533 | } |
534 | } |
535 | } |
536 | } |
537 | |
538 | void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, |
539 | ExplodedNode *Pred, |
540 | ExplodedNodeSet &Dst) { |
541 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
542 | |
543 | ProgramStateRef State = Pred->getState(); |
544 | const LocationContext *LCtx = Pred->getLocationContext(); |
545 | |
546 | const Expr *Init = CL->getInitializer(); |
547 | SVal V = State->getSVal(CL->getInitializer(), LCtx); |
548 | |
549 | if (isa<CXXConstructExpr, CXXStdInitializerListExpr>(Val: Init)) { |
550 | // No work needed. Just pass the value up to this expression. |
551 | } else { |
552 | assert(isa<InitListExpr>(Init)); |
553 | Loc CLLoc = State->getLValue(literal: CL, LC: LCtx); |
554 | State = State->bindLoc(location: CLLoc, V, LCtx); |
555 | |
556 | if (CL->isGLValue()) |
557 | V = CLLoc; |
558 | } |
559 | |
560 | B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V)); |
561 | } |
562 | |
563 | void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, |
564 | ExplodedNodeSet &Dst) { |
565 | if (isa<TypedefNameDecl>(Val: *DS->decl_begin())) { |
566 | // C99 6.7.7 "Any array size expressions associated with variable length |
567 | // array declarators are evaluated each time the declaration of the typedef |
568 | // name is reached in the order of execution." |
569 | // The checkers should know about typedef to be able to handle VLA size |
570 | // expressions. |
571 | ExplodedNodeSet DstPre; |
572 | getCheckerManager().runCheckersForPreStmt(Dst&: DstPre, Src: Pred, S: DS, Eng&: *this); |
573 | getCheckerManager().runCheckersForPostStmt(Dst, Src: DstPre, S: DS, Eng&: *this); |
574 | return; |
575 | } |
576 | |
577 | // Assumption: The CFG has one DeclStmt per Decl. |
578 | const VarDecl *VD = dyn_cast_or_null<VarDecl>(Val: *DS->decl_begin()); |
579 | |
580 | if (!VD) { |
581 | //TODO:AZ: remove explicit insertion after refactoring is done. |
582 | Dst.insert(S: Pred); |
583 | return; |
584 | } |
585 | |
586 | // FIXME: all pre/post visits should eventually be handled by ::Visit(). |
587 | ExplodedNodeSet dstPreVisit; |
588 | getCheckerManager().runCheckersForPreStmt(Dst&: dstPreVisit, Src: Pred, S: DS, Eng&: *this); |
589 | |
590 | ExplodedNodeSet dstEvaluated; |
591 | StmtNodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx); |
592 | for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); |
593 | I!=E; ++I) { |
594 | ExplodedNode *N = *I; |
595 | ProgramStateRef state = N->getState(); |
596 | const LocationContext *LC = N->getLocationContext(); |
597 | |
598 | // Decls without InitExpr are not initialized explicitly. |
599 | if (const Expr *InitEx = VD->getInit()) { |
600 | |
601 | // Note in the state that the initialization has occurred. |
602 | ExplodedNode *UpdatedN = N; |
603 | SVal InitVal = state->getSVal(InitEx, LC); |
604 | |
605 | assert(DS->isSingleDecl()); |
606 | if (getObjectUnderConstruction(State: state, Item: DS, LC)) { |
607 | state = finishObjectConstruction(State: state, Item: DS, LC); |
608 | // We constructed the object directly in the variable. |
609 | // No need to bind anything. |
610 | B.generateNode(S: DS, Pred: UpdatedN, St: state); |
611 | } else { |
612 | // Recover some path-sensitivity if a scalar value evaluated to |
613 | // UnknownVal. |
614 | if (InitVal.isUnknown()) { |
615 | QualType Ty = InitEx->getType(); |
616 | if (InitEx->isGLValue()) { |
617 | Ty = getContext().getPointerType(T: Ty); |
618 | } |
619 | |
620 | InitVal = svalBuilder.conjureSymbolVal(symbolTag: nullptr, expr: InitEx, LCtx: LC, type: Ty, |
621 | count: currBldrCtx->blockCount()); |
622 | } |
623 | |
624 | |
625 | B.takeNodes(N: UpdatedN); |
626 | ExplodedNodeSet Dst2; |
627 | evalBind(Dst&: Dst2, StoreE: DS, Pred: UpdatedN, location: state->getLValue(VD, LC), Val: InitVal, atDeclInit: true); |
628 | B.addNodes(S: Dst2); |
629 | } |
630 | } |
631 | else { |
632 | B.generateNode(S: DS, Pred: N, St: state); |
633 | } |
634 | } |
635 | |
636 | getCheckerManager().runCheckersForPostStmt(Dst, Src: B.getResults(), S: DS, Eng&: *this); |
637 | } |
638 | |
639 | void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, |
640 | ExplodedNodeSet &Dst) { |
641 | // This method acts upon CFG elements for logical operators && and || |
642 | // and attaches the value (true or false) to them as expressions. |
643 | // It doesn't produce any state splits. |
644 | // If we made it that far, we're past the point when we modeled the short |
645 | // circuit. It means that we should have precise knowledge about whether |
646 | // we've short-circuited. If we did, we already know the value we need to |
647 | // bind. If we didn't, the value of the RHS (casted to the boolean type) |
648 | // is the answer. |
649 | // Currently this method tries to figure out whether we've short-circuited |
650 | // by looking at the ExplodedGraph. This method is imperfect because there |
651 | // could inevitably have been merges that would have resulted in multiple |
652 | // potential path traversal histories. We bail out when we fail. |
653 | // Due to this ambiguity, a more reliable solution would have been to |
654 | // track the short circuit operation history path-sensitively until |
655 | // we evaluate the respective logical operator. |
656 | assert(B->getOpcode() == BO_LAnd || |
657 | B->getOpcode() == BO_LOr); |
658 | |
659 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
660 | ProgramStateRef state = Pred->getState(); |
661 | |
662 | if (B->getType()->isVectorType()) { |
663 | // FIXME: We do not model vector arithmetic yet. When adding support for |
664 | // that, note that the CFG-based reasoning below does not apply, because |
665 | // logical operators on vectors are not short-circuit. Currently they are |
666 | // modeled as short-circuit in Clang CFG but this is incorrect. |
667 | // Do not set the value for the expression. It'd be UnknownVal by default. |
668 | Bldr.generateNode(B, Pred, state); |
669 | return; |
670 | } |
671 | |
672 | ExplodedNode *N = Pred; |
673 | while (!N->getLocation().getAs<BlockEntrance>()) { |
674 | ProgramPoint P = N->getLocation(); |
675 | assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>()); |
676 | (void) P; |
677 | if (N->pred_size() != 1) { |
678 | // We failed to track back where we came from. |
679 | Bldr.generateNode(B, Pred, state); |
680 | return; |
681 | } |
682 | N = *N->pred_begin(); |
683 | } |
684 | |
685 | if (N->pred_size() != 1) { |
686 | // We failed to track back where we came from. |
687 | Bldr.generateNode(B, Pred, state); |
688 | return; |
689 | } |
690 | |
691 | N = *N->pred_begin(); |
692 | BlockEdge BE = N->getLocation().castAs<BlockEdge>(); |
693 | SVal X; |
694 | |
695 | // Determine the value of the expression by introspecting how we |
696 | // got this location in the CFG. This requires looking at the previous |
697 | // block we were in and what kind of control-flow transfer was involved. |
698 | const CFGBlock *SrcBlock = BE.getSrc(); |
699 | // The only terminator (if there is one) that makes sense is a logical op. |
700 | CFGTerminator T = SrcBlock->getTerminator(); |
701 | if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(Val: T.getStmt())) { |
702 | (void) Term; |
703 | assert(Term->isLogicalOp()); |
704 | assert(SrcBlock->succ_size() == 2); |
705 | // Did we take the true or false branch? |
706 | unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0; |
707 | X = svalBuilder.makeIntVal(constant, B->getType()); |
708 | } |
709 | else { |
710 | // If there is no terminator, by construction the last statement |
711 | // in SrcBlock is the value of the enclosing expression. |
712 | // However, we still need to constrain that value to be 0 or 1. |
713 | assert(!SrcBlock->empty()); |
714 | CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>(); |
715 | const Expr *RHS = cast<Expr>(Val: Elem.getStmt()); |
716 | SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext()); |
717 | |
718 | if (RHSVal.isUndef()) { |
719 | X = RHSVal; |
720 | } else { |
721 | // We evaluate "RHSVal != 0" expression which result in 0 if the value is |
722 | // known to be false, 1 if the value is known to be true and a new symbol |
723 | // when the assumption is unknown. |
724 | nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); |
725 | X = evalBinOp(ST: N->getState(), Op: BO_NE, |
726 | LHS: svalBuilder.evalCast(V: RHSVal, CastTy: B->getType(), OriginalTy: RHS->getType()), |
727 | RHS: Zero, T: B->getType()); |
728 | } |
729 | } |
730 | Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); |
731 | } |
732 | |
733 | void ExprEngine::VisitInitListExpr(const InitListExpr *IE, |
734 | ExplodedNode *Pred, |
735 | ExplodedNodeSet &Dst) { |
736 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
737 | |
738 | ProgramStateRef state = Pred->getState(); |
739 | const LocationContext *LCtx = Pred->getLocationContext(); |
740 | QualType T = getContext().getCanonicalType(IE->getType()); |
741 | unsigned NumInitElements = IE->getNumInits(); |
742 | |
743 | if (!IE->isGLValue() && !IE->isTransparent() && |
744 | (T->isArrayType() || T->isRecordType() || T->isVectorType() || |
745 | T->isAnyComplexType())) { |
746 | llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); |
747 | |
748 | // Handle base case where the initializer has no elements. |
749 | // e.g: static int* myArray[] = {}; |
750 | if (NumInitElements == 0) { |
751 | SVal V = svalBuilder.makeCompoundVal(type: T, vals); |
752 | B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); |
753 | return; |
754 | } |
755 | |
756 | for (const Stmt *S : llvm::reverse(C: *IE)) { |
757 | SVal V = state->getSVal(cast<Expr>(Val: S), LCtx); |
758 | vals = getBasicVals().prependSVal(X: V, L: vals); |
759 | } |
760 | |
761 | B.generateNode(IE, Pred, |
762 | state->BindExpr(IE, LCtx, |
763 | svalBuilder.makeCompoundVal(type: T, vals))); |
764 | return; |
765 | } |
766 | |
767 | // Handle scalars: int{5} and int{} and GLvalues. |
768 | // Note, if the InitListExpr is a GLvalue, it means that there is an address |
769 | // representing it, so it must have a single init element. |
770 | assert(NumInitElements <= 1); |
771 | |
772 | SVal V; |
773 | if (NumInitElements == 0) |
774 | V = getSValBuilder().makeZeroVal(type: T); |
775 | else |
776 | V = state->getSVal(IE->getInit(Init: 0), LCtx); |
777 | |
778 | B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); |
779 | } |
780 | |
781 | void ExprEngine::VisitGuardedExpr(const Expr *Ex, |
782 | const Expr *L, |
783 | const Expr *R, |
784 | ExplodedNode *Pred, |
785 | ExplodedNodeSet &Dst) { |
786 | assert(L && R); |
787 | |
788 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
789 | ProgramStateRef state = Pred->getState(); |
790 | const LocationContext *LCtx = Pred->getLocationContext(); |
791 | const CFGBlock *SrcBlock = nullptr; |
792 | |
793 | // Find the predecessor block. |
794 | ProgramStateRef SrcState = state; |
795 | for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) { |
796 | ProgramPoint PP = N->getLocation(); |
797 | if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) { |
798 | // If the state N has multiple predecessors P, it means that successors |
799 | // of P are all equivalent. |
800 | // In turn, that means that all nodes at P are equivalent in terms |
801 | // of observable behavior at N, and we can follow any of them. |
802 | // FIXME: a more robust solution which does not walk up the tree. |
803 | continue; |
804 | } |
805 | SrcBlock = PP.castAs<BlockEdge>().getSrc(); |
806 | SrcState = N->getState(); |
807 | break; |
808 | } |
809 | |
810 | assert(SrcBlock && "missing function entry" ); |
811 | |
812 | // Find the last expression in the predecessor block. That is the |
813 | // expression that is used for the value of the ternary expression. |
814 | bool hasValue = false; |
815 | SVal V; |
816 | |
817 | for (CFGElement CE : llvm::reverse(C: *SrcBlock)) { |
818 | if (std::optional<CFGStmt> CS = CE.getAs<CFGStmt>()) { |
819 | const Expr *ValEx = cast<Expr>(Val: CS->getStmt()); |
820 | ValEx = ValEx->IgnoreParens(); |
821 | |
822 | // For GNU extension '?:' operator, the left hand side will be an |
823 | // OpaqueValueExpr, so get the underlying expression. |
824 | if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(Val: L)) |
825 | L = OpaqueEx->getSourceExpr(); |
826 | |
827 | // If the last expression in the predecessor block matches true or false |
828 | // subexpression, get its the value. |
829 | if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) { |
830 | hasValue = true; |
831 | V = SrcState->getSVal(ValEx, LCtx); |
832 | } |
833 | break; |
834 | } |
835 | } |
836 | |
837 | if (!hasValue) |
838 | V = svalBuilder.conjureSymbolVal(symbolTag: nullptr, expr: Ex, LCtx, |
839 | count: currBldrCtx->blockCount()); |
840 | |
841 | // Generate a new node with the binding from the appropriate path. |
842 | B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); |
843 | } |
844 | |
845 | void ExprEngine:: |
846 | VisitOffsetOfExpr(const OffsetOfExpr *OOE, |
847 | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |
848 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
849 | Expr::EvalResult Result; |
850 | if (OOE->EvaluateAsInt(Result, getContext())) { |
851 | APSInt IV = Result.Val.getInt(); |
852 | assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); |
853 | assert(OOE->getType()->castAs<BuiltinType>()->isInteger()); |
854 | assert(IV.isSigned() == OOE->getType()->isSignedIntegerType()); |
855 | SVal X = svalBuilder.makeIntVal(integer: IV); |
856 | B.generateNode(OOE, Pred, |
857 | Pred->getState()->BindExpr(OOE, Pred->getLocationContext(), |
858 | X)); |
859 | } |
860 | // FIXME: Handle the case where __builtin_offsetof is not a constant. |
861 | } |
862 | |
863 | |
864 | void ExprEngine:: |
865 | VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, |
866 | ExplodedNode *Pred, |
867 | ExplodedNodeSet &Dst) { |
868 | // FIXME: Prechecks eventually go in ::Visit(). |
869 | ExplodedNodeSet CheckedSet; |
870 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); |
871 | |
872 | ExplodedNodeSet EvalSet; |
873 | StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); |
874 | |
875 | QualType T = Ex->getTypeOfArgument(); |
876 | |
877 | for (ExplodedNode *N : CheckedSet) { |
878 | if (Ex->getKind() == UETT_SizeOf) { |
879 | if (!T->isIncompleteType() && !T->isConstantSizeType()) { |
880 | assert(T->isVariableArrayType() && "Unknown non-constant-sized type." ); |
881 | |
882 | // FIXME: Add support for VLA type arguments and VLA expressions. |
883 | // When that happens, we should probably refactor VLASizeChecker's code. |
884 | continue; |
885 | } else if (T->getAs<ObjCObjectType>()) { |
886 | // Some code tries to take the sizeof an ObjCObjectType, relying that |
887 | // the compiler has laid out its representation. Just report Unknown |
888 | // for these. |
889 | continue; |
890 | } |
891 | } |
892 | |
893 | APSInt Value = Ex->EvaluateKnownConstInt(getContext()); |
894 | CharUnits amt = CharUnits::fromQuantity(Quantity: Value.getZExtValue()); |
895 | |
896 | ProgramStateRef state = N->getState(); |
897 | state = state->BindExpr( |
898 | S: Ex, LCtx: N->getLocationContext(), |
899 | V: svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())); |
900 | Bldr.generateNode(Ex, N, state); |
901 | } |
902 | |
903 | getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this); |
904 | } |
905 | |
906 | void ExprEngine::handleUOExtension(ExplodedNode *N, const UnaryOperator *U, |
907 | StmtNodeBuilder &Bldr) { |
908 | // FIXME: We can probably just have some magic in Environment::getSVal() |
909 | // that propagates values, instead of creating a new node here. |
910 | // |
911 | // Unary "+" is a no-op, similar to a parentheses. We still have places |
912 | // where it may be a block-level expression, so we need to |
913 | // generate an extra node that just propagates the value of the |
914 | // subexpression. |
915 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
916 | ProgramStateRef state = N->getState(); |
917 | const LocationContext *LCtx = N->getLocationContext(); |
918 | Bldr.generateNode(U, N, state->BindExpr(U, LCtx, state->getSVal(Ex, LCtx))); |
919 | } |
920 | |
921 | void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred, |
922 | ExplodedNodeSet &Dst) { |
923 | // FIXME: Prechecks eventually go in ::Visit(). |
924 | ExplodedNodeSet CheckedSet; |
925 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this); |
926 | |
927 | ExplodedNodeSet EvalSet; |
928 | StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); |
929 | |
930 | for (ExplodedNode *N : CheckedSet) { |
931 | switch (U->getOpcode()) { |
932 | default: { |
933 | Bldr.takeNodes(N); |
934 | ExplodedNodeSet Tmp; |
935 | VisitIncrementDecrementOperator(U, Pred: N, Dst&: Tmp); |
936 | Bldr.addNodes(S: Tmp); |
937 | break; |
938 | } |
939 | case UO_Real: { |
940 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
941 | |
942 | // FIXME: We don't have complex SValues yet. |
943 | if (Ex->getType()->isAnyComplexType()) { |
944 | // Just report "Unknown." |
945 | break; |
946 | } |
947 | |
948 | // For all other types, UO_Real is an identity operation. |
949 | assert (U->getType() == Ex->getType()); |
950 | ProgramStateRef state = N->getState(); |
951 | const LocationContext *LCtx = N->getLocationContext(); |
952 | Bldr.generateNode(U, N, |
953 | state->BindExpr(U, LCtx, state->getSVal(Ex, LCtx))); |
954 | break; |
955 | } |
956 | |
957 | case UO_Imag: { |
958 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
959 | // FIXME: We don't have complex SValues yet. |
960 | if (Ex->getType()->isAnyComplexType()) { |
961 | // Just report "Unknown." |
962 | break; |
963 | } |
964 | // For all other types, UO_Imag returns 0. |
965 | ProgramStateRef state = N->getState(); |
966 | const LocationContext *LCtx = N->getLocationContext(); |
967 | SVal X = svalBuilder.makeZeroVal(type: Ex->getType()); |
968 | Bldr.generateNode(U, N, state->BindExpr(U, LCtx, X)); |
969 | break; |
970 | } |
971 | |
972 | case UO_AddrOf: { |
973 | // Process pointer-to-member address operation. |
974 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
975 | if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: Ex)) { |
976 | const ValueDecl *VD = DRE->getDecl(); |
977 | |
978 | if (isa<CXXMethodDecl, FieldDecl, IndirectFieldDecl>(Val: VD)) { |
979 | ProgramStateRef State = N->getState(); |
980 | const LocationContext *LCtx = N->getLocationContext(); |
981 | SVal SV = svalBuilder.getMemberPointer(ND: cast<NamedDecl>(Val: VD)); |
982 | Bldr.generateNode(U, N, State->BindExpr(U, LCtx, SV)); |
983 | break; |
984 | } |
985 | } |
986 | // Explicitly proceed with default handler for this case cascade. |
987 | handleUOExtension(N, U, Bldr); |
988 | break; |
989 | } |
990 | case UO_Plus: |
991 | assert(!U->isGLValue()); |
992 | [[fallthrough]]; |
993 | case UO_Deref: |
994 | case UO_Extension: { |
995 | handleUOExtension(N, U, Bldr); |
996 | break; |
997 | } |
998 | |
999 | case UO_LNot: |
1000 | case UO_Minus: |
1001 | case UO_Not: { |
1002 | assert (!U->isGLValue()); |
1003 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
1004 | ProgramStateRef state = N->getState(); |
1005 | const LocationContext *LCtx = N->getLocationContext(); |
1006 | |
1007 | // Get the value of the subexpression. |
1008 | SVal V = state->getSVal(Ex, LCtx); |
1009 | |
1010 | if (V.isUnknownOrUndef()) { |
1011 | Bldr.generateNode(U, N, state->BindExpr(U, LCtx, V)); |
1012 | break; |
1013 | } |
1014 | |
1015 | switch (U->getOpcode()) { |
1016 | default: |
1017 | llvm_unreachable("Invalid Opcode." ); |
1018 | case UO_Not: |
1019 | // FIXME: Do we need to handle promotions? |
1020 | state = state->BindExpr( |
1021 | U, LCtx, svalBuilder.evalComplement(val: V.castAs<NonLoc>())); |
1022 | break; |
1023 | case UO_Minus: |
1024 | // FIXME: Do we need to handle promotions? |
1025 | state = state->BindExpr(U, LCtx, |
1026 | svalBuilder.evalMinus(val: V.castAs<NonLoc>())); |
1027 | break; |
1028 | case UO_LNot: |
1029 | // C99 6.5.3.3: "The expression !E is equivalent to (0==E)." |
1030 | // |
1031 | // Note: technically we do "E == 0", but this is the same in the |
1032 | // transfer functions as "0 == E". |
1033 | SVal Result; |
1034 | if (std::optional<Loc> LV = V.getAs<Loc>()) { |
1035 | Loc X = svalBuilder.makeNullWithType(type: Ex->getType()); |
1036 | Result = evalBinOp(ST: state, Op: BO_EQ, LHS: *LV, RHS: X, T: U->getType()); |
1037 | } else if (Ex->getType()->isFloatingType()) { |
1038 | // FIXME: handle floating point types. |
1039 | Result = UnknownVal(); |
1040 | } else { |
1041 | nonloc::ConcreteInt X(getBasicVals().getValue(X: 0, T: Ex->getType())); |
1042 | Result = evalBinOp(ST: state, Op: BO_EQ, LHS: V.castAs<NonLoc>(), RHS: X, T: U->getType()); |
1043 | } |
1044 | |
1045 | state = state->BindExpr(U, LCtx, Result); |
1046 | break; |
1047 | } |
1048 | Bldr.generateNode(U, N, state); |
1049 | break; |
1050 | } |
1051 | } |
1052 | } |
1053 | |
1054 | getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, U, *this); |
1055 | } |
1056 | |
1057 | void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, |
1058 | ExplodedNode *Pred, |
1059 | ExplodedNodeSet &Dst) { |
1060 | // Handle ++ and -- (both pre- and post-increment). |
1061 | assert (U->isIncrementDecrementOp()); |
1062 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
1063 | |
1064 | const LocationContext *LCtx = Pred->getLocationContext(); |
1065 | ProgramStateRef state = Pred->getState(); |
1066 | SVal loc = state->getSVal(Ex, LCtx); |
1067 | |
1068 | // Perform a load. |
1069 | ExplodedNodeSet Tmp; |
1070 | evalLoad(Tmp, U, Ex, Pred, state, loc); |
1071 | |
1072 | ExplodedNodeSet Dst2; |
1073 | StmtNodeBuilder Bldr(Tmp, Dst2, *currBldrCtx); |
1074 | for (ExplodedNode *N : Tmp) { |
1075 | state = N->getState(); |
1076 | assert(LCtx == N->getLocationContext()); |
1077 | SVal V2_untested = state->getSVal(Ex, LCtx); |
1078 | |
1079 | // Propagate unknown and undefined values. |
1080 | if (V2_untested.isUnknownOrUndef()) { |
1081 | state = state->BindExpr(U, LCtx, V2_untested); |
1082 | |
1083 | // Perform the store, so that the uninitialized value detection happens. |
1084 | Bldr.takeNodes(N); |
1085 | ExplodedNodeSet Dst3; |
1086 | evalStore(Dst3, U, Ex, N, state, loc, V2_untested); |
1087 | Bldr.addNodes(S: Dst3); |
1088 | |
1089 | continue; |
1090 | } |
1091 | DefinedSVal V2 = V2_untested.castAs<DefinedSVal>(); |
1092 | |
1093 | // Handle all other values. |
1094 | BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub; |
1095 | |
1096 | // If the UnaryOperator has non-location type, use its type to create the |
1097 | // constant value. If the UnaryOperator has location type, create the |
1098 | // constant with int type and pointer width. |
1099 | SVal RHS; |
1100 | SVal Result; |
1101 | |
1102 | if (U->getType()->isAnyPointerType()) |
1103 | RHS = svalBuilder.makeArrayIndex(idx: 1); |
1104 | else if (U->getType()->isIntegralOrEnumerationType()) |
1105 | RHS = svalBuilder.makeIntVal(1, U->getType()); |
1106 | else |
1107 | RHS = UnknownVal(); |
1108 | |
1109 | // The use of an operand of type bool with the ++ operators is deprecated |
1110 | // but valid until C++17. And if the operand of the ++ operator is of type |
1111 | // bool, it is set to true until C++17. Note that for '_Bool', it is also |
1112 | // set to true when it encounters ++ operator. |
1113 | if (U->getType()->isBooleanType() && U->isIncrementOp()) |
1114 | Result = svalBuilder.makeTruthVal(true, U->getType()); |
1115 | else |
1116 | Result = evalBinOp(ST: state, Op, LHS: V2, RHS, T: U->getType()); |
1117 | |
1118 | // Conjure a new symbol if necessary to recover precision. |
1119 | if (Result.isUnknown()){ |
1120 | DefinedOrUnknownSVal SymVal = |
1121 | svalBuilder.conjureSymbolVal(nullptr, U, LCtx, |
1122 | currBldrCtx->blockCount()); |
1123 | Result = SymVal; |
1124 | |
1125 | // If the value is a location, ++/-- should always preserve |
1126 | // non-nullness. Check if the original value was non-null, and if so |
1127 | // propagate that constraint. |
1128 | if (Loc::isLocType(T: U->getType())) { |
1129 | DefinedOrUnknownSVal Constraint = |
1130 | svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(type: U->getType())); |
1131 | |
1132 | if (!state->assume(Cond: Constraint, Assumption: true)) { |
1133 | // It isn't feasible for the original value to be null. |
1134 | // Propagate this constraint. |
1135 | Constraint = svalBuilder.evalEQ(state, SymVal, |
1136 | svalBuilder.makeZeroVal(type: U->getType())); |
1137 | |
1138 | state = state->assume(Cond: Constraint, Assumption: false); |
1139 | assert(state); |
1140 | } |
1141 | } |
1142 | } |
1143 | |
1144 | // Since the lvalue-to-rvalue conversion is explicit in the AST, |
1145 | // we bind an l-value if the operator is prefix and an lvalue (in C++). |
1146 | if (U->isGLValue()) |
1147 | state = state->BindExpr(U, LCtx, loc); |
1148 | else |
1149 | state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result); |
1150 | |
1151 | // Perform the store. |
1152 | Bldr.takeNodes(N); |
1153 | ExplodedNodeSet Dst3; |
1154 | evalStore(Dst3, U, Ex, N, state, loc, Result); |
1155 | Bldr.addNodes(S: Dst3); |
1156 | } |
1157 | Dst.insert(S: Dst2); |
1158 | } |
1159 | |