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