clang 24.0.0git
ExprEngineC.cpp
Go to the documentation of this file.
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"
17#include <optional>
18
19using namespace clang;
20using namespace ento;
21using llvm::APSInt;
22
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(CheckedSet, Pred, B, *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(LHS, SF);
40 SVal RightV = State->getSVal(RHS, SF);
41
43
44 if (Op == BO_Assign) {
45 if (RightV.isUnknown()) {
46 unsigned Count = getNumVisitedCurrent();
47 RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), SF,
48 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(Tmp2, B, LHS, N, State->BindExpr(B, SF, ExprVal), LeftV,
54 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>(Other) && VTy->isIntegralOrEnumerationType() &&
65 V.isUnknown()) {
66 V = svalBuilder.conjureSymbolVal(getCFGElementRef(), SF, VTy,
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, LHS);
79
80 // Process non-assignments except commas or short-circuited
81 // logical expressions (LAnd and LOr).
82 SVal Result = evalBinOp(State, Op, LeftV, RightV, B->getType());
83 if (!Result.isUnknown()) {
84 State = State->BindExpr(B, SF, Result);
85 } else {
86 // If we cannot evaluate the operation escape the operands.
87 State = escapeValues(State, LeftV, PSK_EscapeOther);
88 State = escapeValues(State, RightV, PSK_EscapeOther);
89 }
90
91 Tmp2.insert(Engine.makePostStmtNode(B, State, 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(Tmp, B, LHS, N, State, LeftV);
116
117 for (ExplodedNode *N : Tmp) {
118 State = N->getState();
119 SVal V = State->getSVal(LHS, SF);
120
121 // Determine the relevant types.
122 const ASTContext &ACtx = getContext();
123 const auto *CAOpB = cast<CompoundAssignOperator>(B);
124 QualType CTy = ACtx.getCanonicalType(CAOpB->getComputationResultType());
125 QualType CLHSTy = ACtx.getCanonicalType(CAOpB->getComputationLHSType());
126 QualType LTy = ACtx.getCanonicalType(LHS->getType());
127
128 // Promote LHS.
129 V = svalBuilder.evalCast(V, CLHSTy, LTy);
130
131 // Compute the result of the operation.
132 SVal Result = svalBuilder.evalCast(evalBinOp(State, Op, V, RightV, CTy),
133 B->getType(), 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, getCFGElementRef(), SF, LTy,
144 // However, we need to convert the symbol to the computation type.
145 Result = svalBuilder.evalCast(StoredInLeftV, CTy, LTy);
146 } else {
147 // The left-hand side may bind to a different value then the
148 // computation type.
149 StoredInLeftV = svalBuilder.evalCast(Result, LTy, CTy);
150 }
151
152 // In C++, assignment and compound assignment operators return an
153 // lvalue.
154 if (B->isGLValue())
155 State = State->BindExpr(B, SF, LeftV);
156 else
157 State = State->BindExpr(B, SF, Result);
158
159 evalStore(Tmp2, B, LHS, N, State, LeftV, StoredInLeftV);
160 }
161 }
162
163 // FIXME: postvisits eventually go in ::Visit()
164 getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this);
165}
166
168 ExplodedNodeSet &Dst) {
169
171
172 const BlockDecl *BD = BE->getBlockDecl();
173 // Get the value of the block itself.
174 SVal V = svalBuilder.getBlockPointer(BD, T, Pred->getStackFrame(),
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>(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(copyExpr, SF);
209 } else {
210 originalV = State->getSVal(loc::MemRegionVal(originalR));
211 }
212 State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, SF);
213 }
214 }
215 }
216
217 Dst.insert(Engine.makeNodeWithBinding(Pred, BE, V, State,
219}
220
222 const StackFrame *SF, QualType T,
223 QualType ExTy, const CastExpr *CastE,
224 ExplodedNodeSet &Dst, ExplodedNode *Pred) {
225 if (T->isLValueReferenceType()) {
226 assert(!CastE->getType()->isLValueReferenceType());
227 ExTy = getContext().getLValueReferenceType(ExTy);
228 } else if (T->isRValueReferenceType()) {
229 assert(!CastE->getType()->isRValueReferenceType());
230 ExTy = getContext().getRValueReferenceType(ExTy);
231 }
232 // Delegate to SValBuilder to process.
233 SVal OrigV = state->getSVal(Ex, SF);
234 SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
235 SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);
236 // Negate the result if we're treating the boolean as a signed i1
237 if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
238 V = svalBuilder.evalMinus(V.castAs<NonLoc>());
239
240 state = state->BindExpr(CastE, SF, V);
241 if (V.isUnknown() && !OrigV.isUnknown()) {
242 state = escapeValues(state, OrigV, PSK_EscapeOther);
243 }
244 Dst.insert(Engine.makePostStmtNode(CastE, state, Pred));
245}
246
248 ExplodedNodeSet &Dst) {
249 const Expr *Ex = CastE->getSubExpr();
250 ProgramStateRef State = Pred->getState();
251 const StackFrame *SF = Pred->getStackFrame();
252
253 if (CastE->getCastKind() == CK_LValueToRValue) {
254 evalLoad(Dst, CastE, CastE, Pred, State, State->getSVal(Ex, SF));
255 return;
256 }
257 if (CastE->getCastKind() == CK_LValueToRValueBitCast) {
258 // Handle `__builtin_bit_cast`:
259 ExplodedNodeSet DstEvalLoc;
260
261 // Simulate the lvalue-to-rvalue conversion on `Ex`:
262 evalLocation(DstEvalLoc, CastE, Ex, Pred, State, State->getSVal(Ex, SF),
263 true);
264 // Simulate the operation that actually casts the original value to a new
265 // value of the destination type :
266
267 for (ExplodedNode *Node : DstEvalLoc) {
268 ProgramStateRef State = Node->getState();
269 const StackFrame *SF = Node->getStackFrame();
270 // Although `Ex` is an lvalue, it could have `Loc::ConcreteInt` kind
271 // (e.g., `(int *)123456`). In such cases, there is no MemRegion
272 // available and we can't get the value to be casted.
273 SVal CastedV = UnknownVal();
274
275 if (const MemRegion *MR = State->getSVal(Ex, SF).getAsRegion()) {
276 SVal OrigV = State->getSVal(MR);
277 CastedV = svalBuilder.evalCast(svalBuilder.simplifySVal(State, OrigV),
278 CastE->getType(), Ex->getType());
279 }
280 Dst.insert(Engine.makeNodeWithBinding(Node, CastE, CastedV));
281 }
282 return;
283 }
284
285 // All other casts.
286 QualType T = CastE->getType();
287 QualType ExTy = Ex->getType();
288
289 if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
290 T = ExCast->getTypeAsWritten();
291
292 switch (CastE->getCastKind()) {
293 case CK_LValueToRValue:
294 case CK_LValueToRValueBitCast:
295 llvm_unreachable("LValueToRValue casts handled earlier.");
296 case CK_ToVoid:
297 Dst.insert(Pred);
298 return;
299 // The analyzer doesn't do anything special with these casts,
300 // since it understands retain/release semantics already.
301 case CK_ARCProduceObject:
302 case CK_ARCConsumeObject:
303 case CK_ARCReclaimReturnedObject:
304 case CK_ARCExtendBlockObject: // Fall-through.
305 case CK_CopyAndAutoreleaseBlockObject:
306 // The analyser can ignore atomic casts for now, although some future
307 // checkers may want to make certain that you're not modifying the same
308 // value through atomic and nonatomic pointers.
309 case CK_AtomicToNonAtomic:
310 case CK_NonAtomicToAtomic:
311 // True no-ops.
312 case CK_NoOp:
313 case CK_ConstructorConversion:
314 case CK_UserDefinedConversion:
315 case CK_FunctionToPointerDecay:
316 case CK_BuiltinFnToFnPtr:
317 case CK_HLSLArrayRValue: {
318 // Copy the SVal of Ex to CastE.
319 SVal V = State->getSVal(Ex, SF);
320 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
321 return;
322 }
323 case CK_MemberPointerToBoolean:
324 case CK_PointerToBoolean: {
325 SVal V = State->getSVal(Ex, SF);
326 auto PTMSV = V.getAs<nonloc::PointerToMember>();
327 if (PTMSV)
328 V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy);
329 if (V.isUndef() || PTMSV) {
330 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
331 return;
332 }
333 handleLValueBitCast(State, Ex, SF, T, ExTy, CastE, Dst, Pred);
334 return;
335 }
336 case CK_Dependent:
337 case CK_ArrayToPointerDecay:
338 case CK_BitCast:
339 case CK_AddressSpaceConversion:
340 case CK_BooleanToSignedIntegral:
341 case CK_IntegralToPointer:
342 case CK_PointerToIntegral: {
343 SVal V = State->getSVal(Ex, SF);
345 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, UnknownVal()));
346 return;
347 }
348 handleLValueBitCast(State, Ex, SF, T, ExTy, CastE, Dst, Pred);
349 return;
350 }
351 case CK_IntegralToBoolean:
352 case CK_IntegralToFloating:
353 case CK_FloatingToIntegral:
354 case CK_FloatingToBoolean:
355 case CK_FloatingCast:
356 case CK_FloatingRealToComplex:
357 case CK_FloatingComplexToReal:
358 case CK_FloatingComplexToBoolean:
359 case CK_FloatingComplexCast:
360 case CK_FloatingComplexToIntegralComplex:
361 case CK_IntegralRealToComplex:
362 case CK_IntegralComplexToReal:
363 case CK_IntegralComplexToBoolean:
364 case CK_IntegralComplexCast:
365 case CK_IntegralComplexToFloatingComplex:
366 case CK_CPointerToObjCPointerCast:
367 case CK_BlockPointerToObjCPointerCast:
368 case CK_AnyPointerToBlockPointerCast:
369 case CK_ObjCObjectLValueCast:
370 case CK_ZeroToOCLOpaqueType:
371 case CK_IntToOCLSampler:
372 case CK_LValueBitCast:
373 case CK_FloatingToFixedPoint:
374 case CK_FixedPointToFloating:
375 case CK_FixedPointCast:
376 case CK_FixedPointToBoolean:
377 case CK_FixedPointToIntegral:
378 case CK_IntegralToFixedPoint: {
379 handleLValueBitCast(State, Ex, SF, T, ExTy, CastE, Dst, Pred);
380 return;
381 }
382 case CK_IntegralCast: {
383 // Delegate to SValBuilder to process.
384 SVal V = State->getSVal(Ex, SF);
385 if (AMgr.options.analyzerSymbolicIntegerCasts())
386 V = svalBuilder.evalCast(V, T, ExTy);
387 else
388 V = svalBuilder.evalIntegralCast(State, V, T, ExTy);
389 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
390 return;
391 }
392 case CK_DerivedToBase:
393 case CK_UncheckedDerivedToBase: {
394 // For DerivedToBase cast, delegate to the store manager.
395 SVal val = State->getSVal(Ex, SF);
396 val = getStoreManager().evalDerivedToBase(val, CastE);
397 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, val));
398 return;
399 }
400 // Handle C++ dyn_cast.
401 case CK_Dynamic: {
402 SVal val = State->getSVal(Ex, SF);
403
404 // Compute the type of the result.
405 QualType resultType = CastE->getType();
406 if (CastE->isGLValue())
407 resultType = getContext().getPointerType(resultType);
408
409 bool Failed = true;
410
411 // Check if the value being cast does not evaluates to 0.
412 if (!val.isZeroConstant())
413 if (std::optional<SVal> V =
414 StateMgr.getStoreManager().evalBaseToDerived(val, T)) {
415 val = *V;
416 Failed = false;
417 }
418
419 if (Failed) {
420 if (T->isReferenceType()) {
421 // A bad_cast exception is thrown if input value is a reference.
422 // Currently, we model this, by generating a sink.
423 Engine.makePostStmtNode(CastE, State, Pred, /*MarkAsSink=*/true);
424 return;
425 } else {
426 // If the cast fails on a pointer, bind to 0.
427 State = State->BindExpr(CastE, SF,
428 svalBuilder.makeNullWithType(resultType));
429 }
430 } else {
431 // If we don't know if the cast succeeded, conjure a new symbol.
432 if (val.isUnknown()) {
433 DefinedOrUnknownSVal NewSym = svalBuilder.conjureSymbolVal(
434 /*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
436 State = State->BindExpr(CastE, SF, NewSym);
437 } else
438 // Else, bind to the derived region value.
439 State = State->BindExpr(CastE, SF, val);
440 }
441 Dst.insert(Engine.makePostStmtNode(CastE, State, Pred));
442 return;
443 }
444 case CK_BaseToDerived: {
445 SVal val = State->getSVal(Ex, SF);
446 QualType resultType = CastE->getType();
447 if (CastE->isGLValue())
448 resultType = getContext().getPointerType(resultType);
449
450 if (!val.isConstant()) {
451 std::optional<SVal> V = getStoreManager().evalBaseToDerived(val, T);
452 val = V ? *V : UnknownVal();
453 }
454
455 // Failed to cast or the result is unknown, fall back to conservative.
456 if (val.isUnknown()) {
457 val = svalBuilder.conjureSymbolVal(
458 /*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
460 }
461 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, val));
462 return;
463 }
464 case CK_NullToPointer: {
465 SVal V = svalBuilder.makeNullWithType(CastE->getType());
466 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
467 return;
468 }
469 case CK_NullToMemberPointer: {
470 SVal V = svalBuilder.getMemberPointer(nullptr);
471 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
472 return;
473 }
474 case CK_DerivedToBaseMemberPointer:
475 case CK_BaseToDerivedMemberPointer:
476 case CK_ReinterpretMemberPointer: {
477 SVal V = State->getSVal(Ex, SF);
478 if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) {
479 SVal CastedPTMSV =
480 svalBuilder.makePointerToMember(getBasicVals().accumCXXBase(
481 CastE->path(), *PTMSV, CastE->getCastKind()));
482 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, CastedPTMSV));
483 return;
484 }
485 // Explicitly proceed with default handler for this case cascade.
486 }
487 [[fallthrough]];
488 // Various C++ casts that are not handled yet.
489 case CK_ToUnion:
490 case CK_MatrixCast:
491 case CK_VectorSplat:
492 case CK_HLSLElementwiseCast:
493 case CK_HLSLAggregateSplatCast:
494 case CK_HLSLMatrixTruncation:
495 case CK_HLSLVectorTruncation: {
496 QualType resultType = CastE->getType();
497 if (CastE->isGLValue())
498 resultType = getContext().getPointerType(resultType);
499 SVal result = svalBuilder.conjureSymbolVal(
500 /*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
502 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, result));
503 return;
504 }
505 }
506}
507
509 ExplodedNode *Pred,
510 ExplodedNodeSet &Dst) {
511 ProgramStateRef State = Pred->getState();
512 const StackFrame *SF = Pred->getStackFrame();
513
514 const Expr *Init = CL->getInitializer();
515 SVal V = State->getSVal(CL->getInitializer(), SF);
516
518 // No work needed. Just pass the value up to this expression.
519 } else {
520 assert(isa<InitListExpr>(Init));
521 Loc CLLoc = State->getLValue(CL, SF);
522 State = State->bindLoc(CLLoc, V, SF);
523
524 if (CL->isGLValue())
525 V = CLLoc;
526 }
527
528 Dst.insert(Engine.makeNodeWithBinding(Pred, CL, V, State));
529}
530
532 ExplodedNodeSet &Dst) {
533 if (isa<TypedefNameDecl>(*DS->decl_begin())) {
534 // C99 6.7.7 "Any array size expressions associated with variable length
535 // array declarators are evaluated each time the declaration of the typedef
536 // name is reached in the order of execution."
537 // The checkers should know about typedef to be able to handle VLA size
538 // expressions.
539 ExplodedNodeSet DstPre;
540 getCheckerManager().runCheckersForPreStmt(DstPre, Pred, DS, *this);
541 getCheckerManager().runCheckersForPostStmt(Dst, DstPre, DS, *this);
542 return;
543 }
544
545 // Assumption: The CFG has one DeclStmt per Decl.
546 const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin());
547
548 if (!VD) {
549 //TODO:AZ: remove explicit insertion after refactoring is done.
550 Dst.insert(Pred);
551 return;
552 }
553
554 // Self-assignment initialization in variable declaration,
555 // i.e., `int x = x;`,
556 // is a C idiom to suppress warnings of unused variables.
557 // This filter will not match variables of C++ record types, but will match
558 // C++ references. Allow references continuing here to make the undefined
559 // value checker report self-assignments of C++ references.
560 if (const Expr *EI = VD->getInit()) {
561 // Ignore InitListExpr if exists.
562 if (const auto *IL = dyn_cast<InitListExpr>(EI);
563 IL && IL->getNumInits() == 1)
564 EI = IL->getInit(0);
565
566 // Ignore parentheses and implict casts.
567 if (const auto *DR = dyn_cast<DeclRefExpr>(EI->IgnoreParenImpCasts())) {
568 if (VD == DR->getDecl() && !VD->getType()->isReferenceType()) {
569 Dst.insert(Pred);
570 return;
571 }
572 }
573 }
574
575 // FIXME: all pre/post visits should eventually be handled by ::Visit().
576 ExplodedNodeSet dstPreVisit;
577 getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
578
579 ExplodedNodeSet dstEvaluated;
580 for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
581 I!=E; ++I) {
582 ExplodedNode *N = *I;
583 ProgramStateRef state = N->getState();
584 const StackFrame *SF = N->getStackFrame();
585
586 // Decls without InitExpr are not initialized explicitly.
587 if (const Expr *InitEx = VD->getInit()) {
588
589 // Note in the state that the initialization has occurred.
590 ExplodedNode *UpdatedN = N;
591 SVal InitVal = state->getSVal(InitEx, SF);
592
593 assert(DS->isSingleDecl());
594 if (getObjectUnderConstruction(state, DS, SF)) {
595 state = finishObjectConstruction(state, DS, SF);
596 // We constructed the object directly in the variable.
597 // No need to bind anything.
598 dstEvaluated.insert(Engine.makePostStmtNode(DS, state, UpdatedN));
599 } else {
600 // Recover some path-sensitivity if a scalar value evaluated to
601 // UnknownVal.
602 if (InitVal.isUnknown()) {
603 QualType Ty = InitEx->getType();
604 if (InitEx->isGLValue()) {
605 Ty = getContext().getPointerType(Ty);
606 }
607
608 InitVal = svalBuilder.conjureSymbolVal(
609 /*symbolTag=*/nullptr, getCFGElementRef(), SF, Ty,
611 }
612
613 evalBind(dstEvaluated, DS, UpdatedN, state->getLValue(VD, SF), InitVal,
614 true);
615 }
616 }
617 else {
618 dstEvaluated.insert(Engine.makePostStmtNode(DS, state, N));
619 }
620 }
621
622 getCheckerManager().runCheckersForPostStmt(Dst, dstEvaluated, DS, *this);
623}
624
626 ExplodedNodeSet &Dst) {
627 // This method acts upon CFG elements for logical operators && and ||
628 // and attaches the value (true or false) to them as expressions.
629 // It doesn't produce any state splits.
630 // If we made it that far, we're past the point when we modeled the short
631 // circuit. It means that we should have precise knowledge about whether
632 // we've short-circuited. If we did, we already know the value we need to
633 // bind. If we didn't, the value of the RHS (casted to the boolean type)
634 // is the answer.
635 // Currently this method tries to figure out whether we've short-circuited
636 // by looking at the ExplodedGraph. This method is imperfect because there
637 // could inevitably have been merges that would have resulted in multiple
638 // potential path traversal histories. We bail out when we fail.
639 // Due to this ambiguity, a more reliable solution would have been to
640 // track the short circuit operation history path-sensitively until
641 // we evaluate the respective logical operator.
642 assert(B->getOpcode() == BO_LAnd ||
643 B->getOpcode() == BO_LOr);
644
645 ProgramStateRef state = Pred->getState();
646
647 if (B->getType()->isVectorType()) {
648 // FIXME: We do not model vector arithmetic yet. When adding support for
649 // that, note that the CFG-based reasoning below does not apply, because
650 // logical operators on vectors are not short-circuit. Currently they are
651 // modeled as short-circuit in Clang CFG but this is incorrect.
652 // Do not set the value for the expression. It'd be UnknownVal by default.
653 Dst.insert(Engine.makePostStmtNode(B, state, Pred));
654 return;
655 }
656
657 ExplodedNode *N = Pred;
658 while (!N->getLocation().getAs<BlockEdge>()) {
659 ProgramPoint P = N->getLocation();
660 assert(P.getAs<PreStmt>() || P.getAs<PreStmtPurgeDeadSymbols>() ||
661 P.getAs<BlockEntrance>());
662 (void) P;
663 if (N->pred_size() != 1) {
664 // We failed to track back where we came from.
665 Dst.insert(Engine.makePostStmtNode(B, state, Pred));
666 return;
667 }
668 N = *N->pred_begin();
669 }
670
671 if (N->pred_size() != 1) {
672 // We failed to track back where we came from.
673 Dst.insert(Engine.makePostStmtNode(B, state, Pred));
674 return;
675 }
676
678 SVal X;
679
680 // Determine the value of the expression by introspecting how we
681 // got this location in the CFG. This requires looking at the previous
682 // block we were in and what kind of control-flow transfer was involved.
683 const CFGBlock *SrcBlock = BE.getSrc();
684 // The only terminator (if there is one) that makes sense is a logical op.
685 CFGTerminator T = SrcBlock->getTerminator();
686 if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) {
687 (void) Term;
688 assert(Term->isLogicalOp());
689 assert(SrcBlock->succ_size() == 2);
690 // Did we take the true or false branch?
691 unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0;
692 X = svalBuilder.makeIntVal(constant, B->getType());
693 }
694 else {
695 // If there is no terminator, by construction the last statement
696 // in SrcBlock is the value of the enclosing expression.
697 // However, we still need to constrain that value to be 0 or 1.
698 assert(!SrcBlock->empty());
699 CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>();
700 const Expr *RHS = cast<Expr>(Elem.getStmt());
701 SVal RHSVal = N->getState()->getSVal(RHS, Pred->getStackFrame());
702
703 if (RHSVal.isUndef()) {
704 X = RHSVal;
705 } else {
706 // We evaluate "RHSVal != 0" expression which result in 0 if the value is
707 // known to be false, 1 if the value is known to be true and a new symbol
708 // when the assumption is unknown.
709 X = evalBinOp(N->getState(), BO_NE, RHSVal,
710 svalBuilder.makeZeroVal(RHS->getType()), B->getType());
711 }
712 }
713 Dst.insert(Engine.makeNodeWithBinding(Pred, B, X));
714}
715
717 const Expr *L,
718 const Expr *R,
719 ExplodedNode *Pred,
720 ExplodedNodeSet &Dst) {
721 assert(L && R);
722
723 ProgramStateRef state = Pred->getState();
724 const StackFrame *SF = Pred->getStackFrame();
725 const CFGBlock *SrcBlock = nullptr;
726
727 // Find the predecessor block.
728 ProgramStateRef SrcState = state;
729 for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) {
730 auto Edge = N->getLocationAs<BlockEdge>();
731 if (!Edge.has_value()) {
732 // If the state N has multiple predecessors P, it means that successors
733 // of P are all equivalent.
734 // In turn, that means that all nodes at P are equivalent in terms
735 // of observable behavior at N, and we can follow any of them.
736 // FIXME: a more robust solution which does not walk up the tree.
737 continue;
738 }
739 SrcBlock = Edge->getSrc();
740 SrcState = N->getState();
741 break;
742 }
743
744 assert(SrcBlock && "missing function entry");
745
746 // Find the last expression in the predecessor block. That is the
747 // expression that is used for the value of the ternary expression.
748 bool hasValue = false;
749 SVal V;
750
751 for (CFGElement CE : llvm::reverse(*SrcBlock)) {
752 if (std::optional<CFGStmt> CS = CE.getAs<CFGStmt>()) {
753 const Expr *ValEx = cast<Expr>(CS->getStmt());
754 ValEx = ValEx->IgnoreParens();
755
756 // For GNU extension '?:' operator, the left hand side will be an
757 // OpaqueValueExpr, so get the underlying expression.
758 if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L))
759 L = OpaqueEx->getSourceExpr();
760
761 // If the last expression in the predecessor block matches true or false
762 // subexpression, get its the value.
763 if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) {
764 hasValue = true;
765 V = SrcState->getSVal(ValEx, SF);
766 }
767 break;
768 }
769 }
770
771 if (!hasValue)
772 V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), SF,
774
775 // Generate a new node with the binding from the appropriate path.
776 Dst.insert(Engine.makeNodeWithBinding(Pred, Ex, V));
777}
778
780 ExplodedNodeSet &Dst) {
782 if (OOE->EvaluateAsInt(Result, getContext())) {
783 APSInt IV = Result.Val.getInt();
784 assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
785 assert(OOE->getType()->castAs<BuiltinType>()->isInteger());
786 assert(IV.isSigned() == OOE->getType()->isSignedIntegerType());
787 SVal X = svalBuilder.makeIntVal(IV);
788 Dst.insert(Engine.makeNodeWithBinding(Pred, OOE, X));
789 } else {
790 // FIXME: Handle the case where __builtin_offsetof is not a constant.
791 Dst.insert(Pred);
792 }
793}
794
796 const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred,
797 ExplodedNodeSet &Dst) {
799
800 if (Ex->getKind() == UETT_SizeOf || Ex->getKind() == UETT_DataSizeOf ||
801 Ex->getKind() == UETT_CountOf) {
802 if (!T->isIncompleteType() && !T->isConstantSizeType()) {
803 assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
804
805 // FIXME: Add support for VLA type arguments and VLA expressions.
806 // When that happens, we should probably refactor VLASizeChecker's code.
807 Dst.insert(Pred);
808 return;
809 } else if (T->getAs<ObjCObjectType>()) {
810 // Some code tries to take the sizeof an ObjCObjectType, relying that
811 // the compiler has laid out its representation. Just report Unknown
812 // for these.
813 Dst.insert(Pred);
814 return;
815 }
816 }
817
818 APSInt Value = Ex->EvaluateKnownConstInt(getContext());
819 CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
820
821 SVal V = svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType());
822 Dst.insert(Engine.makeNodeWithBinding(Pred, Ex, V));
823}
824
826 ExplodedNodeSet &Dst) {
827 if (SE->getSubStmt()->body_empty()) {
828 // Empty statement expression.
829 assert(SE->getType() == getContext().VoidTy &&
830 "Empty statement expression must have void type.");
831 } else if (const auto *LastExpr =
832 dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
833 SVal Val = Pred->getState()->getSVal(LastExpr, Pred->getStackFrame());
834 Pred = Engine.makeNodeWithBinding(Pred, SE, Val);
835 }
836 Dst.insert(Pred);
837}
838
840 ExplodedNodeSet &Dst) {
841 // FIXME: Prechecks eventually go in ::Visit().
842 ExplodedNodeSet CheckedSet;
843 getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this);
844
845 ExplodedNodeSet EvalSet;
846
847 // Lambda for handling the case when the operand is returned unchanged.
848 auto MakeNodeForIdentityOp = [U, &Engine = Engine](ExplodedNode *N) {
849 const Expr *Ex = U->getSubExpr()->IgnoreParens();
850 SVal SV = N->getState()->getSVal(Ex, N->getStackFrame());
851 return Engine.makeNodeWithBinding(N, U, SV);
852 };
853
854 for (ExplodedNode *N : CheckedSet) {
855 switch (U->getOpcode()) {
856 default: {
857 ExplodedNodeSet Tmp;
859 EvalSet.insert(Tmp);
860 break;
861 }
862 case UO_Real: {
863 const Expr *Ex = U->getSubExpr()->IgnoreParens();
864
865 // FIXME: We don't have complex SValues yet.
866 if (Ex->getType()->isAnyComplexType()) {
867 // Just report "Unknown."
868 EvalSet.insert(N);
869 break;
870 }
871
872 // For all other types, UO_Real is an identity operation.
873 assert (U->getType() == Ex->getType());
874 EvalSet.insert(MakeNodeForIdentityOp(N));
875 break;
876 }
877
878 case UO_Imag: {
879 const Expr *Ex = U->getSubExpr()->IgnoreParens();
880 // FIXME: We don't have complex SValues yet.
881 if (Ex->getType()->isAnyComplexType()) {
882 // Just report "Unknown."
883 EvalSet.insert(N);
884 break;
885 }
886 // For all other types, UO_Imag returns 0.
887 SVal X = svalBuilder.makeZeroVal(Ex->getType());
888 EvalSet.insert(Engine.makeNodeWithBinding(N, U, X));
889 break;
890 }
891
892 case UO_AddrOf: {
893 // Process pointer-to-member address operation.
894 const Expr *Ex = U->getSubExpr()->IgnoreParens();
895 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex)) {
896 const ValueDecl *VD = DRE->getDecl();
897
899 SVal SV = svalBuilder.getMemberPointer(cast<NamedDecl>(VD));
900 EvalSet.insert(Engine.makeNodeWithBinding(N, U, SV));
901 break;
902 }
903 }
904 // Explicitly proceed with default handler for this case cascade.
905 EvalSet.insert(MakeNodeForIdentityOp(N));
906 break;
907 }
908 case UO_Plus:
909 assert(!U->isGLValue());
910 [[fallthrough]];
911 case UO_Deref:
912 case UO_Extension: {
913 EvalSet.insert(MakeNodeForIdentityOp(N));
914 break;
915 }
916
917 case UO_LNot:
918 case UO_Minus:
919 case UO_Not: {
920 assert (!U->isGLValue());
921 const Expr *Ex = U->getSubExpr()->IgnoreParens();
922 ProgramStateRef state = N->getState();
923 const StackFrame *SF = N->getStackFrame();
924
925 // Get the value of the subexpression.
926 SVal V = state->getSVal(Ex, SF);
927
928 if (V.isUnknownOrUndef()) {
929 EvalSet.insert(Engine.makeNodeWithBinding(N, U, V));
930 break;
931 }
932
933 switch (U->getOpcode()) {
934 default:
935 llvm_unreachable("Invalid Opcode.");
936 case UO_Not:
937 // FIXME: Do we need to handle promotions?
938 state = state->BindExpr(
939 U, SF, svalBuilder.evalComplement(V.castAs<NonLoc>()));
940 break;
941 case UO_Minus:
942 // FIXME: Do we need to handle promotions?
943 state =
944 state->BindExpr(U, SF, svalBuilder.evalMinus(V.castAs<NonLoc>()));
945 break;
946 case UO_LNot:
947 // C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
948 //
949 // Note: technically we do "E == 0", but this is the same in the
950 // transfer functions as "0 == E".
951 SVal Result;
952 if (std::optional<Loc> LV = V.getAs<Loc>()) {
953 Loc X = svalBuilder.makeNullWithType(Ex->getType());
954 Result = evalBinOp(state, BO_EQ, *LV, X, U->getType());
955 } else if (Ex->getType()->isFloatingType()) {
956 // FIXME: handle floating point types.
957 Result = UnknownVal();
958 } else {
959 nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
960 Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X, U->getType());
961 }
962
963 state = state->BindExpr(U, SF, Result);
964 break;
965 }
966 EvalSet.insert(Engine.makePostStmtNode(U, state, N));
967 break;
968 }
969 }
970 }
971
972 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, U, *this);
973}
974
976 ExplodedNode *Pred,
977 ExplodedNodeSet &Dst) {
978 SVal V = UnknownVal();
979 if (const Expr *Result = PE->getResultExpr())
980 V = Pred->getState()->getSVal(Result, Pred->getStackFrame());
981 Dst.insert(Engine.makeNodeWithBinding(Pred, PE, V));
982}
983
986 ExplodedNodeSet &Dst) {
987 // ObjCIndirectCopyRestoreExpr implies passing a temporary for
988 // correctness of lifetime management. Due to limited analysis
989 // of ARC, this is implemented as direct arg passing.
990 const Expr *E = OIE->getSubExpr();
991 SVal V = Pred->getState()->getSVal(E, Pred->getStackFrame());
992 Dst.insert(Engine.makeNodeWithBinding(Pred, OIE, V));
993}
994
996 ExplodedNode *Pred,
997 ExplodedNodeSet &Dst) {
998 // Handle ++ and -- (both pre- and post-increment).
999 assert (U->isIncrementDecrementOp());
1000 const Expr *Ex = U->getSubExpr()->IgnoreParens();
1001
1002 const StackFrame *SF = Pred->getStackFrame();
1003 ProgramStateRef state = Pred->getState();
1004 SVal loc = state->getSVal(Ex, SF);
1005
1006 // Perform a load.
1007 ExplodedNodeSet Tmp;
1008 evalLoad(Tmp, U, Ex, Pred, state, loc);
1009
1010 ExplodedNodeSet Dst2;
1011 for (ExplodedNode *N : Tmp) {
1012 state = N->getState();
1013 assert(SF == N->getStackFrame());
1014 SVal V2_untested = state->getSVal(Ex, SF);
1015
1016 // Propagate unknown and undefined values.
1017 if (V2_untested.isUnknownOrUndef()) {
1018 state = state->BindExpr(U, SF, V2_untested);
1019
1020 // Perform the store, so that the uninitialized value detection happens.
1021 evalStore(Dst2, U, Ex, N, state, loc, V2_untested);
1022 continue;
1023 }
1024 DefinedSVal V2 = V2_untested.castAs<DefinedSVal>();
1025
1026 // Handle all other values.
1027 BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub;
1028
1029 // If the UnaryOperator has non-location type, use its type to create the
1030 // constant value. If the UnaryOperator has location type, create the
1031 // constant with int type and pointer width.
1032 SVal RHS;
1033 SVal Result;
1034
1035 if (U->getType()->isAnyPointerType())
1036 RHS = svalBuilder.makeArrayIndex(1);
1037 else if (U->getType()->isIntegralOrEnumerationType())
1038 RHS = svalBuilder.makeIntVal(1, U->getType());
1039 else
1040 RHS = UnknownVal();
1041
1042 // The use of an operand of type bool with the ++ operators is deprecated
1043 // but valid until C++17. And if the operand of the ++ operator is of type
1044 // bool, it is set to true until C++17. Note that for '_Bool', it is also
1045 // set to true when it encounters ++ operator.
1046 if (U->getType()->isBooleanType() && U->isIncrementOp())
1047 Result = svalBuilder.makeTruthVal(true, U->getType());
1048 else
1049 Result = evalBinOp(state, Op, V2, RHS, U->getType());
1050
1051 // Conjure a new symbol if necessary to recover precision.
1052 if (Result.isUnknown()){
1053 DefinedOrUnknownSVal SymVal = svalBuilder.conjureSymbolVal(
1054 /*symbolTag=*/nullptr, getCFGElementRef(), SF,
1056 Result = SymVal;
1057
1058 // If the value is a location, ++/-- should always preserve
1059 // non-nullness. Check if the original value was non-null, and if so
1060 // propagate that constraint.
1061 if (Loc::isLocType(U->getType())) {
1062 DefinedOrUnknownSVal Constraint =
1063 svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType()));
1064
1065 if (!state->assume(Constraint, true)) {
1066 // It isn't feasible for the original value to be null.
1067 // Propagate this constraint.
1068 Constraint = svalBuilder.evalEQ(state, SymVal,
1069 svalBuilder.makeZeroVal(U->getType()));
1070
1071 state = state->assume(Constraint, false);
1072 assert(state);
1073 }
1074 }
1075 }
1076
1077 // Since the lvalue-to-rvalue conversion is explicit in the AST,
1078 // we bind an l-value if the operator is prefix and an lvalue (in C++).
1079 if (U->isGLValue())
1080 state = state->BindExpr(U, SF, loc);
1081 else
1082 state = state->BindExpr(U, SF, U->isPostfix() ? V2 : Result);
1083
1084 // Perform the store.
1085 evalStore(Dst2, U, Ex, N, state, loc, Result);
1086 }
1087 Dst.insert(Dst2);
1088}
#define V(N, I)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
#define X(type, name)
Definition Value.h:97
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4082
Expr * getLHS() const
Definition Expr.h:4132
Expr * getRHS() const
Definition Expr.h:4134
static bool isAdditiveOp(Opcode Opc)
Definition Expr.h:4168
static bool isAssignmentOp(Opcode Opc)
Definition Expr.h:4218
static bool isCompoundAssignmentOp(Opcode Opc)
Definition Expr.h:4223
Opcode getOpcode() const
Definition Expr.h:4127
BinaryOperatorKind Opcode
Definition Expr.h:4087
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition Decl.h:4807
capture_const_iterator capture_begin() const
Definition Decl.h:4936
capture_const_iterator capture_end() const
Definition Decl.h:4937
const CFGBlock * getSrc() const
const CFGBlock * getDst() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6722
const BlockDecl * getBlockDecl() const
Definition Expr.h:6734
This class is used for builtin types like 'int'.
Definition TypeBase.h:3241
bool isInteger() const
Definition TypeBase.h:3305
Represents a single basic block in a source-level CFG.
Definition CFG.h:652
reverse_iterator rbegin()
Definition CFG.h:962
bool empty() const
Definition CFG.h:1000
CFGTerminator getTerminator() const
Definition CFG.h:1132
succ_iterator succ_begin()
Definition CFG.h:1037
unsigned succ_size() const
Definition CFG.h:1055
Represents a top-level expression in a basic block.
Definition CFG.h:55
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Definition CFG.h:103
const Stmt * getStmt() const
Definition CFG.h:143
Represents CFGBlock terminator statement.
Definition CFG.h:579
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3720
CastKind getCastKind() const
Definition Expr.h:3764
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
Definition Expr.h:3807
Expr * getSubExpr()
Definition Expr.h:3770
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3649
bool body_empty() const
Definition Stmt.h:1796
reverse_body_iterator body_rbegin()
Definition Stmt.h:1847
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1290
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1643
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition Stmt.h:1656
decl_iterator decl_begin()
Definition Stmt.h:1697
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3972
This represents one expression.
Definition Expr.h:113
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isGLValue() const
Definition Expr.h:288
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3119
QualType getType() const
Definition Expr.h:145
ObjCIndirectCopyRestoreExpr - Represents the passing of a function argument by indirect copy-restore ...
Definition ExprObjC.h:1614
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2571
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1198
Represents a point after we ran remove dead bindings BEFORE processing the given statement.
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type.
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition Expr.h:6854
Expr * getResultExpr()
Return the result-bearing expression, or null if there is none.
Definition Expr.h:6902
A (possibly-)qualified type.
Definition TypeBase.h:938
It represents a stack frame of the call stack.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
Definition Expr.h:4639
CompoundStmt * getSubStmt()
Definition Expr.h:4656
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition Type.cpp:2296
bool isRValueReferenceType() const
Definition TypeBase.h:8687
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9321
bool isReferenceType() const
Definition TypeBase.h:8679
bool isLValueReferenceType() const
Definition TypeBase.h:8683
bool isAnyComplexType() const
Definition TypeBase.h:8790
bool isVectorType() const
Definition TypeBase.h:8794
bool isFloatingType() const
Definition Type.cpp:2421
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition Expr.h:2669
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition Expr.h:2738
UnaryExprOrTypeTrait getKind() const
Definition Expr.h:2701
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2288
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
const Expr * getInit() const
Definition Decl.h:1392
BlockDataRegion - A region that represents a block instance.
Definition MemRegion.h:712
void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting Stmts.
void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)
Run checkers for pre-visiting Stmts.
ExplodedNodeSet is a set of ExplodedNode * elements with the invariant that its elements cannot be nu...
void insert(ExplodedNode *N)
const ProgramStateRef & getState() const
SVal getSVal(const Expr *E) const
Get the value of an arbitrary expression at this node.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
unsigned pred_size() const
const StackFrame * getStackFrame() const
void VisitBinaryOperator(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBinaryOperator - Transfer function logic for binary operators.
void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGuardedExpr - Transfer function logic for ?, __builtin_choose.
BasicValueFactory & getBasicVals()
Definition ExprEngine.h:457
void VisitLogicalExpr(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitLogicalExpr - Transfer function logic for '&&', '||'.
SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, SVal LHS, SVal RHS, QualType T)
Definition ExprEngine.h:658
void VisitObjCIndirectCopyRestoreExpr(const ObjCIndirectCopyRestoreExpr *OIE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitUnaryOperator(const UnaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryOperator - Transfer function logic for unary operators.
void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBlockExpr - Transfer function logic for BlockExprs.
void VisitIncrementDecrementOperator(const UnaryOperator *U, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Handle ++ and – (both pre- and post-increment).
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
Definition ExprEngine.h:192
StoreManager & getStoreManager()
Definition ExprEngine.h:444
ConstCFGElementRef getCFGElementRef() const
Definition ExprEngine.h:254
void VisitStmtExpr(const StmtExpr *SE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
ProgramStateRef escapeValues(ProgramStateRef State, ArrayRef< SVal > Vs, PointerEscapeKind K, const CallEvent *Call=nullptr) const
A simple wrapper when you only need to notify checkers of pointer-escape of some values.
CheckerManager & getCheckerManager() const
Definition ExprEngine.h:201
static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const StackFrame *SF)
By looking at a certain item that may be potentially part of an object's ConstructionContext,...
unsigned getNumVisitedCurrent() const
Definition ExprEngine.h:263
void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitOffsetOfExpr - Transfer function for offsetof.
void evalLoad(ExplodedNodeSet &Dst, const Expr *NodeEx, const Expr *BoundExpr, ExplodedNode *Pred, ProgramStateRef St, SVal location, const ProgramPointTag *tag=nullptr, QualType LoadTy=QualType())
Simulate a read of the result of Ex.
void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, const ProgramPointTag *tag=nullptr)
evalStore - Handle the semantics of a store via an assignment.
void VisitCastExpr(const CastExpr *CastE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCastExpr - Transfer function logic for all casts (implicit and explicit).
void VisitPseudoObjectExpr(const PseudoObjectExpr *PE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void handleLValueBitCast(ProgramStateRef state, const Expr *Ex, const StackFrame *SF, QualType T, QualType ExTy, const CastExpr *CastE, ExplodedNodeSet &Dst, ExplodedNode *Pred)
static bool isLocType(QualType T)
Definition SVals.h:268
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:97
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:57
bool isUndef() const
Definition SVals.h:113
bool isZeroConstant() const
Definition SVals.cpp:257
bool isUnknownOrUndef() const
Definition SVals.h:115
bool isConstant() const
Definition SVals.cpp:245
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition SVals.h:84
bool isUnknown() const
Definition SVals.h:111
SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)
Evaluates a chain of derived-to-base casts through the path specified in Cast.
Definition Store.cpp:254
std::optional< SVal > evalBaseToDerived(SVal Base, QualType DerivedPtrType)
Attempts to do a down cast.
Definition Store.cpp:318
TypedValueRegion - An abstract class representing regions having a typed value.
Definition MemRegion.h:569
const VarDecl * getDecl() const override=0
Value representing integer constant.
Definition SVals.h:306
Value representing pointer-to-member.
Definition SVals.h:440
Definition SPIR.cpp:35
@ PSK_EscapeOther
The reason for pointer escape is unknown.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Other
Other implicit parameter.
Definition Decl.h:1775
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:666