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