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 ExplodedNode *N = Engine.makeNodeWithBinding(Pred, BE, V, State,
219
220 // FIXME: Move all post/pre visits to ::Visit().
221 getCheckerManager().runCheckersForPostStmt(Dst, N, BE, *this);
222}
223
226 const StackFrame *SF, QualType T, QualType ExTy,
227 const CastExpr *CastE, ExplodedNodeSet &Dst,
228 ExplodedNode *Pred) {
229 if (T->isLValueReferenceType()) {
230 assert(!CastE->getType()->isLValueReferenceType());
231 ExTy = getContext().getLValueReferenceType(ExTy);
232 } else if (T->isRValueReferenceType()) {
233 assert(!CastE->getType()->isRValueReferenceType());
234 ExTy = getContext().getRValueReferenceType(ExTy);
235 }
236 // Delegate to SValBuilder to process.
237 SVal OrigV = state->getSVal(Ex, SF);
238 SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
239 SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);
240 // Negate the result if we're treating the boolean as a signed i1
241 if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
242 V = svalBuilder.evalMinus(V.castAs<NonLoc>());
243
244 state = state->BindExpr(CastE, SF, V);
245 if (V.isUnknown() && !OrigV.isUnknown()) {
246 state = escapeValues(state, OrigV, PSK_EscapeOther);
247 }
248 Dst.insert(Engine.makePostStmtNode(CastE, state, Pred));
249
250 return state;
251}
252
253void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
254 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
255
256 ExplodedNodeSet DstPreStmt;
257 getCheckerManager().runCheckersForPreStmt(DstPreStmt, Pred, CastE, *this);
258
259 if (CastE->getCastKind() == CK_LValueToRValue) {
260 for (ExplodedNode *Node : DstPreStmt) {
261 ProgramStateRef State = Node->getState();
262 const StackFrame *SF = Node->getStackFrame();
263 evalLoad(Dst, CastE, CastE, Node, State, State->getSVal(Ex, SF));
264 }
265 return;
266 }
267 if (CastE->getCastKind() == CK_LValueToRValueBitCast) {
268 // Handle `__builtin_bit_cast`:
269 ExplodedNodeSet DstEvalLoc;
270
271 // Simulate the lvalue-to-rvalue conversion on `Ex`:
272 for (ExplodedNode *Node : DstPreStmt) {
273 ProgramStateRef State = Node->getState();
274 const StackFrame *SF = Node->getStackFrame();
275 evalLocation(DstEvalLoc, CastE, Ex, Node, State, State->getSVal(Ex, SF),
276 true);
277 }
278 // Simulate the operation that actually casts the original value to a new
279 // value of the destination type :
280
281 for (ExplodedNode *Node : DstEvalLoc) {
282 ProgramStateRef State = Node->getState();
283 const StackFrame *SF = Node->getStackFrame();
284 // Although `Ex` is an lvalue, it could have `Loc::ConcreteInt` kind
285 // (e.g., `(int *)123456`). In such cases, there is no MemRegion
286 // available and we can't get the value to be casted.
287 SVal CastedV = UnknownVal();
288
289 if (const MemRegion *MR = State->getSVal(Ex, SF).getAsRegion()) {
290 SVal OrigV = State->getSVal(MR);
291 CastedV = svalBuilder.evalCast(svalBuilder.simplifySVal(State, OrigV),
292 CastE->getType(), Ex->getType());
293 }
294 Dst.insert(Engine.makeNodeWithBinding(Node, CastE, CastedV));
295 }
296 return;
297 }
298
299 // All other casts.
300 QualType T = CastE->getType();
301 QualType ExTy = Ex->getType();
302
303 if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
304 T = ExCast->getTypeAsWritten();
305
306 for (ExplodedNode *Pred : DstPreStmt) {
307 ProgramStateRef state = Pred->getState();
308 const StackFrame *SF = Pred->getStackFrame();
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 Dst.insert(Pred);
316 continue;
317 // The analyzer doesn't do anything special with these casts,
318 // since it understands retain/release semantics already.
319 case CK_ARCProduceObject:
320 case CK_ARCConsumeObject:
321 case CK_ARCReclaimReturnedObject:
322 case CK_ARCExtendBlockObject: // Fall-through.
323 case CK_CopyAndAutoreleaseBlockObject:
324 // The analyser can ignore atomic casts for now, although some future
325 // checkers may want to make certain that you're not modifying the same
326 // value through atomic and nonatomic pointers.
327 case CK_AtomicToNonAtomic:
328 case CK_NonAtomicToAtomic:
329 // True no-ops.
330 case CK_NoOp:
331 case CK_ConstructorConversion:
332 case CK_UserDefinedConversion:
333 case CK_FunctionToPointerDecay:
334 case CK_BuiltinFnToFnPtr:
335 case CK_HLSLArrayRValue: {
336 // Copy the SVal of Ex to CastE.
337 ProgramStateRef state = Pred->getState();
338 const StackFrame *SF = Pred->getStackFrame();
339 SVal V = state->getSVal(Ex, SF);
340 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
341 continue;
342 }
343 case CK_MemberPointerToBoolean:
344 case CK_PointerToBoolean: {
345 SVal V = state->getSVal(Ex, SF);
346 auto PTMSV = V.getAs<nonloc::PointerToMember>();
347 if (PTMSV)
348 V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy);
349 if (V.isUndef() || PTMSV) {
350 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
351 continue;
352 }
353 // Explicitly proceed with default handler for this case cascade.
354 state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Dst, Pred);
355 continue;
356 }
357 case CK_Dependent:
358 case CK_ArrayToPointerDecay:
359 case CK_BitCast:
360 case CK_AddressSpaceConversion:
361 case CK_BooleanToSignedIntegral:
362 case CK_IntegralToPointer:
363 case CK_PointerToIntegral: {
364 SVal V = state->getSVal(Ex, SF);
366 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, UnknownVal()));
367 continue;
368 }
369 // Explicitly proceed with default handler for this case cascade.
370 state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Dst, Pred);
371 continue;
372 }
373 case CK_IntegralToBoolean:
374 case CK_IntegralToFloating:
375 case CK_FloatingToIntegral:
376 case CK_FloatingToBoolean:
377 case CK_FloatingCast:
378 case CK_FloatingRealToComplex:
379 case CK_FloatingComplexToReal:
380 case CK_FloatingComplexToBoolean:
381 case CK_FloatingComplexCast:
382 case CK_FloatingComplexToIntegralComplex:
383 case CK_IntegralRealToComplex:
384 case CK_IntegralComplexToReal:
385 case CK_IntegralComplexToBoolean:
386 case CK_IntegralComplexCast:
387 case CK_IntegralComplexToFloatingComplex:
388 case CK_CPointerToObjCPointerCast:
389 case CK_BlockPointerToObjCPointerCast:
390 case CK_AnyPointerToBlockPointerCast:
391 case CK_ObjCObjectLValueCast:
392 case CK_ZeroToOCLOpaqueType:
393 case CK_IntToOCLSampler:
394 case CK_LValueBitCast:
395 case CK_FloatingToFixedPoint:
396 case CK_FixedPointToFloating:
397 case CK_FixedPointCast:
398 case CK_FixedPointToBoolean:
399 case CK_FixedPointToIntegral:
400 case CK_IntegralToFixedPoint: {
401 state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Dst, Pred);
402 continue;
403 }
404 case CK_IntegralCast: {
405 // Delegate to SValBuilder to process.
406 SVal V = state->getSVal(Ex, SF);
407 if (AMgr.options.analyzerSymbolicIntegerCasts())
408 V = svalBuilder.evalCast(V, T, ExTy);
409 else
410 V = svalBuilder.evalIntegralCast(state, V, T, ExTy);
411 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
412 continue;
413 }
414 case CK_DerivedToBase:
415 case CK_UncheckedDerivedToBase: {
416 // For DerivedToBase cast, delegate to the store manager.
417 SVal val = state->getSVal(Ex, SF);
418 val = getStoreManager().evalDerivedToBase(val, CastE);
419 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, val));
420 continue;
421 }
422 // Handle C++ dyn_cast.
423 case CK_Dynamic: {
424 SVal val = state->getSVal(Ex, SF);
425
426 // Compute the type of the result.
427 QualType resultType = CastE->getType();
428 if (CastE->isGLValue())
429 resultType = getContext().getPointerType(resultType);
430
431 bool Failed = true;
432
433 // Check if the value being cast does not evaluates to 0.
434 if (!val.isZeroConstant())
435 if (std::optional<SVal> V =
436 StateMgr.getStoreManager().evalBaseToDerived(val, T)) {
437 val = *V;
438 Failed = false;
439 }
440
441 if (Failed) {
442 if (T->isReferenceType()) {
443 // A bad_cast exception is thrown if input value is a reference.
444 // Currently, we model this, by generating a sink.
445 Engine.makePostStmtNode(CastE, state, Pred, /*MarkAsSink=*/true);
446 continue;
447 } else {
448 // If the cast fails on a pointer, bind to 0.
449 state = state->BindExpr(CastE, SF,
450 svalBuilder.makeNullWithType(resultType));
451 }
452 } else {
453 // If we don't know if the cast succeeded, conjure a new symbol.
454 if (val.isUnknown()) {
455 DefinedOrUnknownSVal NewSym = svalBuilder.conjureSymbolVal(
456 /*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
458 state = state->BindExpr(CastE, SF, NewSym);
459 } else
460 // Else, bind to the derived region value.
461 state = state->BindExpr(CastE, SF, val);
462 }
463 Dst.insert(Engine.makePostStmtNode(CastE, state, Pred));
464 continue;
465 }
466 case CK_BaseToDerived: {
467 SVal val = state->getSVal(Ex, SF);
468 QualType resultType = CastE->getType();
469 if (CastE->isGLValue())
470 resultType = getContext().getPointerType(resultType);
471
472 if (!val.isConstant()) {
473 std::optional<SVal> V = getStoreManager().evalBaseToDerived(val, T);
474 val = V ? *V : UnknownVal();
475 }
476
477 // Failed to cast or the result is unknown, fall back to conservative.
478 if (val.isUnknown()) {
479 val = svalBuilder.conjureSymbolVal(
480 /*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
482 }
483 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, val));
484 continue;
485 }
486 case CK_NullToPointer: {
487 SVal V = svalBuilder.makeNullWithType(CastE->getType());
488 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
489 continue;
490 }
491 case CK_NullToMemberPointer: {
492 SVal V = svalBuilder.getMemberPointer(nullptr);
493 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
494 continue;
495 }
496 case CK_DerivedToBaseMemberPointer:
497 case CK_BaseToDerivedMemberPointer:
498 case CK_ReinterpretMemberPointer: {
499 SVal V = state->getSVal(Ex, SF);
500 if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) {
501 SVal CastedPTMSV =
502 svalBuilder.makePointerToMember(getBasicVals().accumCXXBase(
503 CastE->path(), *PTMSV, CastE->getCastKind()));
504 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, CastedPTMSV));
505 continue;
506 }
507 // Explicitly proceed with default handler for this case cascade.
508 }
509 [[fallthrough]];
510 // Various C++ casts that are not handled yet.
511 case CK_ToUnion:
512 case CK_MatrixCast:
513 case CK_VectorSplat:
514 case CK_HLSLElementwiseCast:
515 case CK_HLSLAggregateSplatCast:
516 case CK_HLSLMatrixTruncation:
517 case CK_HLSLVectorTruncation: {
518 QualType resultType = CastE->getType();
519 if (CastE->isGLValue())
520 resultType = getContext().getPointerType(resultType);
521 SVal result = svalBuilder.conjureSymbolVal(
522 /*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
524 Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, result));
525 continue;
526 }
527 }
528 }
529}
530
532 ExplodedNode *Pred,
533 ExplodedNodeSet &Dst) {
534 ProgramStateRef State = Pred->getState();
535 const StackFrame *SF = Pred->getStackFrame();
536
537 const Expr *Init = CL->getInitializer();
538 SVal V = State->getSVal(CL->getInitializer(), SF);
539
541 // No work needed. Just pass the value up to this expression.
542 } else {
543 assert(isa<InitListExpr>(Init));
544 Loc CLLoc = State->getLValue(CL, SF);
545 State = State->bindLoc(CLLoc, V, SF);
546
547 if (CL->isGLValue())
548 V = CLLoc;
549 }
550
551 Dst.insert(Engine.makeNodeWithBinding(Pred, CL, V, State));
552}
553
555 ExplodedNodeSet &Dst) {
556 if (isa<TypedefNameDecl>(*DS->decl_begin())) {
557 // C99 6.7.7 "Any array size expressions associated with variable length
558 // array declarators are evaluated each time the declaration of the typedef
559 // name is reached in the order of execution."
560 // The checkers should know about typedef to be able to handle VLA size
561 // expressions.
562 ExplodedNodeSet DstPre;
563 getCheckerManager().runCheckersForPreStmt(DstPre, Pred, DS, *this);
564 getCheckerManager().runCheckersForPostStmt(Dst, DstPre, DS, *this);
565 return;
566 }
567
568 // Assumption: The CFG has one DeclStmt per Decl.
569 const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin());
570
571 if (!VD) {
572 //TODO:AZ: remove explicit insertion after refactoring is done.
573 Dst.insert(Pred);
574 return;
575 }
576
577 // Self-assignment initialization in variable declaration,
578 // i.e., `int x = x;`,
579 // is a C idiom to suppress warnings of unused variables.
580 // This filter will not match variables of C++ record types, but will match
581 // C++ references. Allow references continuing here to make the undefined
582 // value checker report self-assignments of C++ references.
583 if (const Expr *EI = VD->getInit()) {
584 // Ignore InitListExpr if exists.
585 if (const auto *IL = dyn_cast<InitListExpr>(EI);
586 IL && IL->getNumInits() == 1)
587 EI = IL->getInit(0);
588
589 // Ignore parentheses and implict casts.
590 if (const auto *DR = dyn_cast<DeclRefExpr>(EI->IgnoreParenImpCasts())) {
591 if (VD == DR->getDecl() && !VD->getType()->isReferenceType()) {
592 Dst.insert(Pred);
593 return;
594 }
595 }
596 }
597
598 // FIXME: all pre/post visits should eventually be handled by ::Visit().
599 ExplodedNodeSet dstPreVisit;
600 getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
601
602 ExplodedNodeSet dstEvaluated;
603 for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
604 I!=E; ++I) {
605 ExplodedNode *N = *I;
606 ProgramStateRef state = N->getState();
607 const StackFrame *SF = N->getStackFrame();
608
609 // Decls without InitExpr are not initialized explicitly.
610 if (const Expr *InitEx = VD->getInit()) {
611
612 // Note in the state that the initialization has occurred.
613 ExplodedNode *UpdatedN = N;
614 SVal InitVal = state->getSVal(InitEx, SF);
615
616 assert(DS->isSingleDecl());
617 if (getObjectUnderConstruction(state, DS, SF)) {
618 state = finishObjectConstruction(state, DS, SF);
619 // We constructed the object directly in the variable.
620 // No need to bind anything.
621 dstEvaluated.insert(Engine.makePostStmtNode(DS, state, UpdatedN));
622 } else {
623 // Recover some path-sensitivity if a scalar value evaluated to
624 // UnknownVal.
625 if (InitVal.isUnknown()) {
626 QualType Ty = InitEx->getType();
627 if (InitEx->isGLValue()) {
628 Ty = getContext().getPointerType(Ty);
629 }
630
631 InitVal = svalBuilder.conjureSymbolVal(
632 /*symbolTag=*/nullptr, getCFGElementRef(), SF, Ty,
634 }
635
636 evalBind(dstEvaluated, DS, UpdatedN, state->getLValue(VD, SF), InitVal,
637 true);
638 }
639 }
640 else {
641 dstEvaluated.insert(Engine.makePostStmtNode(DS, state, N));
642 }
643 }
644
645 getCheckerManager().runCheckersForPostStmt(Dst, dstEvaluated, DS, *this);
646}
647
649 ExplodedNodeSet &Dst) {
650 // This method acts upon CFG elements for logical operators && and ||
651 // and attaches the value (true or false) to them as expressions.
652 // It doesn't produce any state splits.
653 // If we made it that far, we're past the point when we modeled the short
654 // circuit. It means that we should have precise knowledge about whether
655 // we've short-circuited. If we did, we already know the value we need to
656 // bind. If we didn't, the value of the RHS (casted to the boolean type)
657 // is the answer.
658 // Currently this method tries to figure out whether we've short-circuited
659 // by looking at the ExplodedGraph. This method is imperfect because there
660 // could inevitably have been merges that would have resulted in multiple
661 // potential path traversal histories. We bail out when we fail.
662 // Due to this ambiguity, a more reliable solution would have been to
663 // track the short circuit operation history path-sensitively until
664 // we evaluate the respective logical operator.
665 assert(B->getOpcode() == BO_LAnd ||
666 B->getOpcode() == BO_LOr);
667
668 ProgramStateRef state = Pred->getState();
669
670 if (B->getType()->isVectorType()) {
671 // FIXME: We do not model vector arithmetic yet. When adding support for
672 // that, note that the CFG-based reasoning below does not apply, because
673 // logical operators on vectors are not short-circuit. Currently they are
674 // modeled as short-circuit in Clang CFG but this is incorrect.
675 // Do not set the value for the expression. It'd be UnknownVal by default.
676 Dst.insert(Engine.makePostStmtNode(B, state, Pred));
677 return;
678 }
679
680 ExplodedNode *N = Pred;
681 while (!N->getLocation().getAs<BlockEdge>()) {
682 ProgramPoint P = N->getLocation();
683 assert(P.getAs<PreStmt>() || P.getAs<PreStmtPurgeDeadSymbols>() ||
684 P.getAs<BlockEntrance>());
685 (void) P;
686 if (N->pred_size() != 1) {
687 // We failed to track back where we came from.
688 Dst.insert(Engine.makePostStmtNode(B, state, Pred));
689 return;
690 }
691 N = *N->pred_begin();
692 }
693
694 if (N->pred_size() != 1) {
695 // We failed to track back where we came from.
696 Dst.insert(Engine.makePostStmtNode(B, state, Pred));
697 return;
698 }
699
701 SVal X;
702
703 // Determine the value of the expression by introspecting how we
704 // got this location in the CFG. This requires looking at the previous
705 // block we were in and what kind of control-flow transfer was involved.
706 const CFGBlock *SrcBlock = BE.getSrc();
707 // The only terminator (if there is one) that makes sense is a logical op.
708 CFGTerminator T = SrcBlock->getTerminator();
709 if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) {
710 (void) Term;
711 assert(Term->isLogicalOp());
712 assert(SrcBlock->succ_size() == 2);
713 // Did we take the true or false branch?
714 unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0;
715 X = svalBuilder.makeIntVal(constant, B->getType());
716 }
717 else {
718 // If there is no terminator, by construction the last statement
719 // in SrcBlock is the value of the enclosing expression.
720 // However, we still need to constrain that value to be 0 or 1.
721 assert(!SrcBlock->empty());
722 CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>();
723 const Expr *RHS = cast<Expr>(Elem.getStmt());
724 SVal RHSVal = N->getState()->getSVal(RHS, Pred->getStackFrame());
725
726 if (RHSVal.isUndef()) {
727 X = RHSVal;
728 } else {
729 // We evaluate "RHSVal != 0" expression which result in 0 if the value is
730 // known to be false, 1 if the value is known to be true and a new symbol
731 // when the assumption is unknown.
732 X = evalBinOp(N->getState(), BO_NE, RHSVal,
733 svalBuilder.makeZeroVal(RHS->getType()), B->getType());
734 }
735 }
736 Dst.insert(Engine.makeNodeWithBinding(Pred, B, X));
737}
738
740 const Expr *L,
741 const Expr *R,
742 ExplodedNode *Pred,
743 ExplodedNodeSet &Dst) {
744 assert(L && R);
745
746 ProgramStateRef state = Pred->getState();
747 const StackFrame *SF = Pred->getStackFrame();
748 const CFGBlock *SrcBlock = nullptr;
749
750 // Find the predecessor block.
751 ProgramStateRef SrcState = state;
752 for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) {
753 auto Edge = N->getLocationAs<BlockEdge>();
754 if (!Edge.has_value()) {
755 // If the state N has multiple predecessors P, it means that successors
756 // of P are all equivalent.
757 // In turn, that means that all nodes at P are equivalent in terms
758 // of observable behavior at N, and we can follow any of them.
759 // FIXME: a more robust solution which does not walk up the tree.
760 continue;
761 }
762 SrcBlock = Edge->getSrc();
763 SrcState = N->getState();
764 break;
765 }
766
767 assert(SrcBlock && "missing function entry");
768
769 // Find the last expression in the predecessor block. That is the
770 // expression that is used for the value of the ternary expression.
771 bool hasValue = false;
772 SVal V;
773
774 for (CFGElement CE : llvm::reverse(*SrcBlock)) {
775 if (std::optional<CFGStmt> CS = CE.getAs<CFGStmt>()) {
776 const Expr *ValEx = cast<Expr>(CS->getStmt());
777 ValEx = ValEx->IgnoreParens();
778
779 // For GNU extension '?:' operator, the left hand side will be an
780 // OpaqueValueExpr, so get the underlying expression.
781 if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L))
782 L = OpaqueEx->getSourceExpr();
783
784 // If the last expression in the predecessor block matches true or false
785 // subexpression, get its the value.
786 if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) {
787 hasValue = true;
788 V = SrcState->getSVal(ValEx, SF);
789 }
790 break;
791 }
792 }
793
794 if (!hasValue)
795 V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), SF,
797
798 // Generate a new node with the binding from the appropriate path.
799 Dst.insert(Engine.makeNodeWithBinding(Pred, Ex, V));
800}
801
803 ExplodedNodeSet &Dst) {
805 if (OOE->EvaluateAsInt(Result, getContext())) {
806 APSInt IV = Result.Val.getInt();
807 assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
808 assert(OOE->getType()->castAs<BuiltinType>()->isInteger());
809 assert(IV.isSigned() == OOE->getType()->isSignedIntegerType());
810 SVal X = svalBuilder.makeIntVal(IV);
811 Dst.insert(Engine.makeNodeWithBinding(Pred, OOE, X));
812 } else {
813 // FIXME: Handle the case where __builtin_offsetof is not a constant.
814 Dst.insert(Pred);
815 }
816}
817
820 ExplodedNode *Pred,
821 ExplodedNodeSet &Dst) {
822 // FIXME: Prechecks eventually go in ::Visit().
823 ExplodedNodeSet CheckedSet;
824 getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this);
825
826 ExplodedNodeSet EvalSet;
828
829 for (ExplodedNode *N : CheckedSet) {
830 if (Ex->getKind() == UETT_SizeOf || Ex->getKind() == UETT_DataSizeOf ||
831 Ex->getKind() == UETT_CountOf) {
832 if (!T->isIncompleteType() && !T->isConstantSizeType()) {
833 assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
834
835 // FIXME: Add support for VLA type arguments and VLA expressions.
836 // When that happens, we should probably refactor VLASizeChecker's code.
837 EvalSet.insert(N);
838 continue;
839 } else if (T->getAs<ObjCObjectType>()) {
840 // Some code tries to take the sizeof an ObjCObjectType, relying that
841 // the compiler has laid out its representation. Just report Unknown
842 // for these.
843 EvalSet.insert(N);
844 continue;
845 }
846 }
847
848 APSInt Value = Ex->EvaluateKnownConstInt(getContext());
849 CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
850
851 SVal V = svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType());
852 EvalSet.insert(Engine.makeNodeWithBinding(N, Ex, V));
853 }
854
855 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);
856}
857
859 ExplodedNodeSet &Dst) {
860 // FIXME: Prechecks eventually go in ::Visit().
861 ExplodedNodeSet CheckedSet;
862 getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this);
863
864 ExplodedNodeSet EvalSet;
865
866 // Lambda for handling the case when the operand is returned unchanged.
867 auto MakeNodeForIdentityOp = [U, &Engine = Engine](ExplodedNode *N) {
868 const Expr *Ex = U->getSubExpr()->IgnoreParens();
869 SVal SV = N->getState()->getSVal(Ex, N->getStackFrame());
870 return Engine.makeNodeWithBinding(N, U, SV);
871 };
872
873 for (ExplodedNode *N : CheckedSet) {
874 switch (U->getOpcode()) {
875 default: {
876 ExplodedNodeSet Tmp;
878 EvalSet.insert(Tmp);
879 break;
880 }
881 case UO_Real: {
882 const Expr *Ex = U->getSubExpr()->IgnoreParens();
883
884 // FIXME: We don't have complex SValues yet.
885 if (Ex->getType()->isAnyComplexType()) {
886 // Just report "Unknown."
887 EvalSet.insert(N);
888 break;
889 }
890
891 // For all other types, UO_Real is an identity operation.
892 assert (U->getType() == Ex->getType());
893 EvalSet.insert(MakeNodeForIdentityOp(N));
894 break;
895 }
896
897 case UO_Imag: {
898 const Expr *Ex = U->getSubExpr()->IgnoreParens();
899 // FIXME: We don't have complex SValues yet.
900 if (Ex->getType()->isAnyComplexType()) {
901 // Just report "Unknown."
902 EvalSet.insert(N);
903 break;
904 }
905 // For all other types, UO_Imag returns 0.
906 SVal X = svalBuilder.makeZeroVal(Ex->getType());
907 EvalSet.insert(Engine.makeNodeWithBinding(N, U, X));
908 break;
909 }
910
911 case UO_AddrOf: {
912 // Process pointer-to-member address operation.
913 const Expr *Ex = U->getSubExpr()->IgnoreParens();
914 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex)) {
915 const ValueDecl *VD = DRE->getDecl();
916
918 SVal SV = svalBuilder.getMemberPointer(cast<NamedDecl>(VD));
919 EvalSet.insert(Engine.makeNodeWithBinding(N, U, SV));
920 break;
921 }
922 }
923 // Explicitly proceed with default handler for this case cascade.
924 EvalSet.insert(MakeNodeForIdentityOp(N));
925 break;
926 }
927 case UO_Plus:
928 assert(!U->isGLValue());
929 [[fallthrough]];
930 case UO_Deref:
931 case UO_Extension: {
932 EvalSet.insert(MakeNodeForIdentityOp(N));
933 break;
934 }
935
936 case UO_LNot:
937 case UO_Minus:
938 case UO_Not: {
939 assert (!U->isGLValue());
940 const Expr *Ex = U->getSubExpr()->IgnoreParens();
941 ProgramStateRef state = N->getState();
942 const StackFrame *SF = N->getStackFrame();
943
944 // Get the value of the subexpression.
945 SVal V = state->getSVal(Ex, SF);
946
947 if (V.isUnknownOrUndef()) {
948 EvalSet.insert(Engine.makeNodeWithBinding(N, U, V));
949 break;
950 }
951
952 switch (U->getOpcode()) {
953 default:
954 llvm_unreachable("Invalid Opcode.");
955 case UO_Not:
956 // FIXME: Do we need to handle promotions?
957 state = state->BindExpr(
958 U, SF, svalBuilder.evalComplement(V.castAs<NonLoc>()));
959 break;
960 case UO_Minus:
961 // FIXME: Do we need to handle promotions?
962 state =
963 state->BindExpr(U, SF, svalBuilder.evalMinus(V.castAs<NonLoc>()));
964 break;
965 case UO_LNot:
966 // C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
967 //
968 // Note: technically we do "E == 0", but this is the same in the
969 // transfer functions as "0 == E".
970 SVal Result;
971 if (std::optional<Loc> LV = V.getAs<Loc>()) {
972 Loc X = svalBuilder.makeNullWithType(Ex->getType());
973 Result = evalBinOp(state, BO_EQ, *LV, X, U->getType());
974 } else if (Ex->getType()->isFloatingType()) {
975 // FIXME: handle floating point types.
976 Result = UnknownVal();
977 } else {
978 nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
979 Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X, U->getType());
980 }
981
982 state = state->BindExpr(U, SF, Result);
983 break;
984 }
985 EvalSet.insert(Engine.makePostStmtNode(U, state, N));
986 break;
987 }
988 }
989 }
990
991 getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, U, *this);
992}
993
995 ExplodedNode *Pred,
996 ExplodedNodeSet &Dst) {
997 // Handle ++ and -- (both pre- and post-increment).
998 assert (U->isIncrementDecrementOp());
999 const Expr *Ex = U->getSubExpr()->IgnoreParens();
1000
1001 const StackFrame *SF = Pred->getStackFrame();
1002 ProgramStateRef state = Pred->getState();
1003 SVal loc = state->getSVal(Ex, SF);
1004
1005 // Perform a load.
1006 ExplodedNodeSet Tmp;
1007 evalLoad(Tmp, U, Ex, Pred, state, loc);
1008
1009 ExplodedNodeSet Dst2;
1010 for (ExplodedNode *N : Tmp) {
1011 state = N->getState();
1012 assert(SF == N->getStackFrame());
1013 SVal V2_untested = state->getSVal(Ex, SF);
1014
1015 // Propagate unknown and undefined values.
1016 if (V2_untested.isUnknownOrUndef()) {
1017 state = state->BindExpr(U, SF, V2_untested);
1018
1019 // Perform the store, so that the uninitialized value detection happens.
1020 evalStore(Dst2, U, Ex, N, state, loc, V2_untested);
1021 continue;
1022 }
1023 DefinedSVal V2 = V2_untested.castAs<DefinedSVal>();
1024
1025 // Handle all other values.
1026 BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub;
1027
1028 // If the UnaryOperator has non-location type, use its type to create the
1029 // constant value. If the UnaryOperator has location type, create the
1030 // constant with int type and pointer width.
1031 SVal RHS;
1032 SVal Result;
1033
1034 if (U->getType()->isAnyPointerType())
1035 RHS = svalBuilder.makeArrayIndex(1);
1036 else if (U->getType()->isIntegralOrEnumerationType())
1037 RHS = svalBuilder.makeIntVal(1, U->getType());
1038 else
1039 RHS = UnknownVal();
1040
1041 // The use of an operand of type bool with the ++ operators is deprecated
1042 // but valid until C++17. And if the operand of the ++ operator is of type
1043 // bool, it is set to true until C++17. Note that for '_Bool', it is also
1044 // set to true when it encounters ++ operator.
1045 if (U->getType()->isBooleanType() && U->isIncrementOp())
1046 Result = svalBuilder.makeTruthVal(true, U->getType());
1047 else
1048 Result = evalBinOp(state, Op, V2, RHS, U->getType());
1049
1050 // Conjure a new symbol if necessary to recover precision.
1051 if (Result.isUnknown()){
1052 DefinedOrUnknownSVal SymVal = svalBuilder.conjureSymbolVal(
1053 /*symbolTag=*/nullptr, getCFGElementRef(), SF,
1055 Result = SymVal;
1056
1057 // If the value is a location, ++/-- should always preserve
1058 // non-nullness. Check if the original value was non-null, and if so
1059 // propagate that constraint.
1060 if (Loc::isLocType(U->getType())) {
1061 DefinedOrUnknownSVal Constraint =
1062 svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType()));
1063
1064 if (!state->assume(Constraint, true)) {
1065 // It isn't feasible for the original value to be null.
1066 // Propagate this constraint.
1067 Constraint = svalBuilder.evalEQ(state, SymVal,
1068 svalBuilder.makeZeroVal(U->getType()));
1069
1070 state = state->assume(Constraint, false);
1071 assert(state);
1072 }
1073 }
1074 }
1075
1076 // Since the lvalue-to-rvalue conversion is explicit in the AST,
1077 // we bind an l-value if the operator is prefix and an lvalue (in C++).
1078 if (U->isGLValue())
1079 state = state->BindExpr(U, SF, loc);
1080 else
1081 state = state->BindExpr(U, SF, U->isPostfix() ? V2 : Result);
1082
1083 // Perform the store.
1084 evalStore(Dst2, U, Ex, N, state, loc, Result);
1085 }
1086 Dst.insert(Dst2);
1087}
#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:223
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:4049
Expr * getLHS() const
Definition Expr.h:4099
Expr * getRHS() const
Definition Expr.h:4101
static bool isAdditiveOp(Opcode Opc)
Definition Expr.h:4135
static bool isAssignmentOp(Opcode Opc)
Definition Expr.h:4185
static bool isCompoundAssignmentOp(Opcode Opc)
Definition Expr.h:4190
Opcode getOpcode() const
Definition Expr.h:4094
BinaryOperatorKind Opcode
Definition Expr.h:4054
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition Decl.h:4806
capture_const_iterator capture_begin() const
Definition Decl.h:4935
capture_const_iterator capture_end() const
Definition Decl.h:4936
const CFGBlock * getSrc() const
const CFGBlock * getDst() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6689
const BlockDecl * getBlockDecl() const
Definition Expr.h:6701
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:3687
CastKind getCastKind() const
Definition Expr.h:3731
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
Definition Expr.h:3774
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:3616
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1281
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1640
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition Stmt.h:1653
decl_iterator decl_begin()
Definition Stmt.h:1694
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3939
This represents one expression.
Definition Expr.h:112
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:287
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:3097
QualType getType() const
Definition Expr.h:144
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2538
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1189
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...
A (possibly-)qualified type.
Definition TypeBase.h:938
It represents a stack frame of the call stack.
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:8773
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9407
bool isReferenceType() const
Definition TypeBase.h:8765
bool isLValueReferenceType() const
Definition TypeBase.h:8769
bool isAnyComplexType() const
Definition TypeBase.h:8876
bool isVectorType() const
Definition TypeBase.h:8880
bool isFloatingType() const
Definition Type.cpp:2419
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition Expr.h:2636
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition Expr.h:2705
UnaryExprOrTypeTrait getKind() const
Definition Expr.h:2668
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2255
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
const Expr * getInit() const
Definition Decl.h:1391
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
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.
ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex, const StackFrame *SF, QualType T, QualType ExTy, const CastExpr *CastE, ExplodedNodeSet &Dst, ExplodedNode *Pred)
void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCast - Transfer function logic for all casts (implicit and explicit).
BasicValueFactory & getBasicVals()
Definition ExprEngine.h:493
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:686
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:214
StoreManager & getStoreManager()
Definition ExprEngine.h:480
ConstCFGElementRef getCFGElementRef() const
Definition ExprEngine.h:290
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:223
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:299
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.
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:1774
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:657