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