================
@@ -303,228 +292,221 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const
Expr *Ex,
if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
T = ExCast->getTypeAsWritten();
- for (ExplodedNode *Pred : DstPreStmt) {
- ProgramStateRef state = Pred->getState();
- const StackFrame *SF = Pred->getStackFrame();
-
- switch (CastE->getCastKind()) {
- case CK_LValueToRValue:
- case CK_LValueToRValueBitCast:
- llvm_unreachable("LValueToRValue casts handled earlier.");
- case CK_ToVoid:
- Dst.insert(Pred);
- continue;
- // The analyzer doesn't do anything special with these casts,
- // since it understands retain/release semantics already.
- case CK_ARCProduceObject:
- case CK_ARCConsumeObject:
- case CK_ARCReclaimReturnedObject:
- case CK_ARCExtendBlockObject: // Fall-through.
- case CK_CopyAndAutoreleaseBlockObject:
- // The analyser can ignore atomic casts for now, although some future
- // checkers may want to make certain that you're not modifying the same
- // value through atomic and nonatomic pointers.
- case CK_AtomicToNonAtomic:
- case CK_NonAtomicToAtomic:
- // True no-ops.
- case CK_NoOp:
- case CK_ConstructorConversion:
- case CK_UserDefinedConversion:
- case CK_FunctionToPointerDecay:
- case CK_BuiltinFnToFnPtr:
- case CK_HLSLArrayRValue: {
- // Copy the SVal of Ex to CastE.
- ProgramStateRef state = Pred->getState();
- const StackFrame *SF = Pred->getStackFrame();
- SVal V = state->getSVal(Ex, SF);
- Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
- continue;
- }
- case CK_MemberPointerToBoolean:
- case CK_PointerToBoolean: {
- SVal V = state->getSVal(Ex, SF);
- auto PTMSV = V.getAs<nonloc::PointerToMember>();
- if (PTMSV)
- V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy);
- if (V.isUndef() || PTMSV) {
- Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
- continue;
- }
- // Explicitly proceed with default handler for this case cascade.
- state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Dst, Pred);
- continue;
- }
- case CK_Dependent:
- case CK_ArrayToPointerDecay:
- case CK_BitCast:
- case CK_AddressSpaceConversion:
- case CK_BooleanToSignedIntegral:
- case CK_IntegralToPointer:
- case CK_PointerToIntegral: {
- SVal V = state->getSVal(Ex, SF);
- if (isa<nonloc::PointerToMember>(V)) {
- Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, UnknownVal()));
- continue;
- }
- // Explicitly proceed with default handler for this case cascade.
- state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Dst, Pred);
- continue;
- }
- case CK_IntegralToBoolean:
- case CK_IntegralToFloating:
- case CK_FloatingToIntegral:
- case CK_FloatingToBoolean:
- case CK_FloatingCast:
- case CK_FloatingRealToComplex:
- case CK_FloatingComplexToReal:
- case CK_FloatingComplexToBoolean:
- case CK_FloatingComplexCast:
- case CK_FloatingComplexToIntegralComplex:
- case CK_IntegralRealToComplex:
- case CK_IntegralComplexToReal:
- case CK_IntegralComplexToBoolean:
- case CK_IntegralComplexCast:
- case CK_IntegralComplexToFloatingComplex:
- case CK_CPointerToObjCPointerCast:
- case CK_BlockPointerToObjCPointerCast:
- case CK_AnyPointerToBlockPointerCast:
- case CK_ObjCObjectLValueCast:
- case CK_ZeroToOCLOpaqueType:
- case CK_IntToOCLSampler:
- case CK_LValueBitCast:
- case CK_FloatingToFixedPoint:
- case CK_FixedPointToFloating:
- case CK_FixedPointCast:
- case CK_FixedPointToBoolean:
- case CK_FixedPointToIntegral:
- case CK_IntegralToFixedPoint: {
- state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Dst, Pred);
- continue;
- }
- case CK_IntegralCast: {
- // Delegate to SValBuilder to process.
- SVal V = state->getSVal(Ex, SF);
- if (AMgr.options.analyzerSymbolicIntegerCasts())
- V = svalBuilder.evalCast(V, T, ExTy);
- else
- V = svalBuilder.evalIntegralCast(state, V, T, ExTy);
- Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
- continue;
- }
- case CK_DerivedToBase:
- case CK_UncheckedDerivedToBase: {
- // For DerivedToBase cast, delegate to the store manager.
- SVal val = state->getSVal(Ex, SF);
- val = getStoreManager().evalDerivedToBase(val, CastE);
- Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, val));
- continue;
- }
- // Handle C++ dyn_cast.
- case CK_Dynamic: {
- SVal val = state->getSVal(Ex, SF);
-
- // Compute the type of the result.
- QualType resultType = CastE->getType();
- if (CastE->isGLValue())
- resultType = getContext().getPointerType(resultType);
-
- bool Failed = true;
-
- // Check if the value being cast does not evaluates to 0.
- if (!val.isZeroConstant())
- if (std::optional<SVal> V =
- StateMgr.getStoreManager().evalBaseToDerived(val, T)) {
- val = *V;
- Failed = false;
- }
-
- if (Failed) {
- if (T->isReferenceType()) {
- // A bad_cast exception is thrown if input value is a reference.
- // Currently, we model this, by generating a sink.
- Engine.makePostStmtNode(CastE, state, Pred, /*MarkAsSink=*/true);
- continue;
- } else {
- // If the cast fails on a pointer, bind to 0.
- state = state->BindExpr(CastE, SF,
- svalBuilder.makeNullWithType(resultType));
- }
- } else {
- // If we don't know if the cast succeeded, conjure a new symbol.
- if (val.isUnknown()) {
- DefinedOrUnknownSVal NewSym = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
- getNumVisitedCurrent());
- state = state->BindExpr(CastE, SF, NewSym);
- } else
- // Else, bind to the derived region value.
- state = state->BindExpr(CastE, SF, val);
- }
- Dst.insert(Engine.makePostStmtNode(CastE, state, Pred));
- continue;
+ switch (CastE->getCastKind()) {
+ case CK_LValueToRValue:
+ case CK_LValueToRValueBitCast:
+ llvm_unreachable("LValueToRValue casts handled earlier.");
+ case CK_ToVoid:
+ Dst.insert(Pred);
+ return;
+ // The analyzer doesn't do anything special with these casts,
+ // since it understands retain/release semantics already.
+ case CK_ARCProduceObject:
+ case CK_ARCConsumeObject:
+ case CK_ARCReclaimReturnedObject:
+ case CK_ARCExtendBlockObject: // Fall-through.
+ case CK_CopyAndAutoreleaseBlockObject:
+ // The analyser can ignore atomic casts for now, although some future
+ // checkers may want to make certain that you're not modifying the same
+ // value through atomic and nonatomic pointers.
+ case CK_AtomicToNonAtomic:
+ case CK_NonAtomicToAtomic:
+ // True no-ops.
+ case CK_NoOp:
+ case CK_ConstructorConversion:
+ case CK_UserDefinedConversion:
+ case CK_FunctionToPointerDecay:
+ case CK_BuiltinFnToFnPtr:
+ case CK_HLSLArrayRValue: {
+ // Copy the SVal of Ex to CastE.
+ SVal V = State->getSVal(Ex, SF);
+ Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
+ return;
+ }
+ case CK_MemberPointerToBoolean:
+ case CK_PointerToBoolean: {
+ SVal V = State->getSVal(Ex, SF);
+ auto PTMSV = V.getAs<nonloc::PointerToMember>();
+ if (PTMSV)
+ V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy);
+ if (V.isUndef() || PTMSV) {
+ Dst.insert(Engine.makeNodeWithBinding(Pred, CastE, V));
+ return;
+ }
+ // Explicitly proceed with default handler for this case cascade.
----------------
NagyDonat wrote:
This comment appears twice, but in my opinion adds no information; consider
removing it (if you also think that it is useless).
https://github.com/llvm/llvm-project/pull/218691
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits