10b57cec5SDimitry Andric //=-- ExprEngineC.cpp - ExprEngine support for C expressions ----*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines ExprEngine's support for C expressions. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 1406c3fb27SDimitry Andric #include "clang/AST/ExprCXX.h" 150b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h" 160b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 17bdd1243dSDimitry Andric #include <optional> 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace clang; 200b57cec5SDimitry Andric using namespace ento; 210b57cec5SDimitry Andric using llvm::APSInt; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric /// Optionally conjure and return a symbol for offset when processing 240b57cec5SDimitry Andric /// an expression \p Expression. 250b57cec5SDimitry Andric /// If \p Other is a location, conjure a symbol for \p Symbol 260b57cec5SDimitry Andric /// (offset) if it is unknown so that memory arithmetic always 270b57cec5SDimitry Andric /// results in an ElementRegion. 280b57cec5SDimitry Andric /// \p Count The number of times the current basic block was visited. 290b57cec5SDimitry Andric static SVal conjureOffsetSymbolOnLocation( 300b57cec5SDimitry Andric SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder, 310b57cec5SDimitry Andric unsigned Count, const LocationContext *LCtx) { 320b57cec5SDimitry Andric QualType Ty = Expression->getType(); 3381ad6265SDimitry Andric if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() && 340b57cec5SDimitry Andric Symbol.isUnknown()) { 350b57cec5SDimitry Andric return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count); 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric return Symbol; 380b57cec5SDimitry Andric } 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, 410b57cec5SDimitry Andric ExplodedNode *Pred, 420b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric Expr *LHS = B->getLHS()->IgnoreParens(); 450b57cec5SDimitry Andric Expr *RHS = B->getRHS()->IgnoreParens(); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric // FIXME: Prechecks eventually go in ::Visit(). 480b57cec5SDimitry Andric ExplodedNodeSet CheckedSet; 490b57cec5SDimitry Andric ExplodedNodeSet Tmp2; 500b57cec5SDimitry Andric getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this); 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric // With both the LHS and RHS evaluated, process the operation itself. 530b57cec5SDimitry Andric for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end(); 540b57cec5SDimitry Andric it != ei; ++it) { 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric ProgramStateRef state = (*it)->getState(); 570b57cec5SDimitry Andric const LocationContext *LCtx = (*it)->getLocationContext(); 580b57cec5SDimitry Andric SVal LeftV = state->getSVal(LHS, LCtx); 590b57cec5SDimitry Andric SVal RightV = state->getSVal(RHS, LCtx); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric BinaryOperator::Opcode Op = B->getOpcode(); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric if (Op == BO_Assign) { 640b57cec5SDimitry Andric // EXPERIMENTAL: "Conjured" symbols. 650b57cec5SDimitry Andric // FIXME: Handle structs. 660b57cec5SDimitry Andric if (RightV.isUnknown()) { 670b57cec5SDimitry Andric unsigned Count = currBldrCtx->blockCount(); 680b57cec5SDimitry Andric RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, 690b57cec5SDimitry Andric Count); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric // Simulate the effects of a "store": bind the value of the RHS 720b57cec5SDimitry Andric // to the L-Value represented by the LHS. 730b57cec5SDimitry Andric SVal ExprVal = B->isGLValue() ? LeftV : RightV; 740b57cec5SDimitry Andric evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal), 750b57cec5SDimitry Andric LeftV, RightV); 760b57cec5SDimitry Andric continue; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric if (!B->isAssignmentOp()) { 800b57cec5SDimitry Andric StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric if (B->isAdditiveOp()) { 830b57cec5SDimitry Andric // TODO: This can be removed after we enable history tracking with 840b57cec5SDimitry Andric // SymSymExpr. 850b57cec5SDimitry Andric unsigned Count = currBldrCtx->blockCount(); 860b57cec5SDimitry Andric RightV = conjureOffsetSymbolOnLocation( 870b57cec5SDimitry Andric RightV, LeftV, RHS, svalBuilder, Count, LCtx); 880b57cec5SDimitry Andric LeftV = conjureOffsetSymbolOnLocation( 890b57cec5SDimitry Andric LeftV, RightV, LHS, svalBuilder, Count, LCtx); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // Although we don't yet model pointers-to-members, we do need to make 930b57cec5SDimitry Andric // sure that the members of temporaries have a valid 'this' pointer for 940b57cec5SDimitry Andric // other checks. 950b57cec5SDimitry Andric if (B->getOpcode() == BO_PtrMemD) 960b57cec5SDimitry Andric state = createTemporaryRegionIfNeeded(state, LCtx, LHS); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric // Process non-assignments except commas or short-circuited 990b57cec5SDimitry Andric // logical expressions (LAnd and LOr). 1000b57cec5SDimitry Andric SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType()); 1010b57cec5SDimitry Andric if (!Result.isUnknown()) { 1020b57cec5SDimitry Andric state = state->BindExpr(B, LCtx, Result); 1030b57cec5SDimitry Andric } else { 1040b57cec5SDimitry Andric // If we cannot evaluate the operation escape the operands. 105480093f4SDimitry Andric state = escapeValues(state, LeftV, PSK_EscapeOther); 106480093f4SDimitry Andric state = escapeValues(state, RightV, PSK_EscapeOther); 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric Bldr.generateNode(B, *it, state); 1100b57cec5SDimitry Andric continue; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric assert (B->isCompoundAssignmentOp()); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric switch (Op) { 1160b57cec5SDimitry Andric default: 1170b57cec5SDimitry Andric llvm_unreachable("Invalid opcode for compound assignment."); 1180b57cec5SDimitry Andric case BO_MulAssign: Op = BO_Mul; break; 1190b57cec5SDimitry Andric case BO_DivAssign: Op = BO_Div; break; 1200b57cec5SDimitry Andric case BO_RemAssign: Op = BO_Rem; break; 1210b57cec5SDimitry Andric case BO_AddAssign: Op = BO_Add; break; 1220b57cec5SDimitry Andric case BO_SubAssign: Op = BO_Sub; break; 1230b57cec5SDimitry Andric case BO_ShlAssign: Op = BO_Shl; break; 1240b57cec5SDimitry Andric case BO_ShrAssign: Op = BO_Shr; break; 1250b57cec5SDimitry Andric case BO_AndAssign: Op = BO_And; break; 1260b57cec5SDimitry Andric case BO_XorAssign: Op = BO_Xor; break; 1270b57cec5SDimitry Andric case BO_OrAssign: Op = BO_Or; break; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // Perform a load (the LHS). This performs the checks for 1310b57cec5SDimitry Andric // null dereferences, and so on. 1320b57cec5SDimitry Andric ExplodedNodeSet Tmp; 1330b57cec5SDimitry Andric SVal location = LeftV; 1340b57cec5SDimitry Andric evalLoad(Tmp, B, LHS, *it, state, location); 1350b57cec5SDimitry Andric 13606c3fb27SDimitry Andric for (ExplodedNode *N : Tmp) { 13706c3fb27SDimitry Andric state = N->getState(); 13806c3fb27SDimitry Andric const LocationContext *LCtx = N->getLocationContext(); 1390b57cec5SDimitry Andric SVal V = state->getSVal(LHS, LCtx); 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric // Get the computation type. 1420b57cec5SDimitry Andric QualType CTy = 1430b57cec5SDimitry Andric cast<CompoundAssignOperator>(B)->getComputationResultType(); 1440b57cec5SDimitry Andric CTy = getContext().getCanonicalType(CTy); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric QualType CLHSTy = 1470b57cec5SDimitry Andric cast<CompoundAssignOperator>(B)->getComputationLHSType(); 1480b57cec5SDimitry Andric CLHSTy = getContext().getCanonicalType(CLHSTy); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric QualType LTy = getContext().getCanonicalType(LHS->getType()); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // Promote LHS. 1530b57cec5SDimitry Andric V = svalBuilder.evalCast(V, CLHSTy, LTy); 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric // Compute the result of the operation. 1560b57cec5SDimitry Andric SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy), 1570b57cec5SDimitry Andric B->getType(), CTy); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric // EXPERIMENTAL: "Conjured" symbols. 1600b57cec5SDimitry Andric // FIXME: Handle structs. 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric SVal LHSVal; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric if (Result.isUnknown()) { 1650b57cec5SDimitry Andric // The symbolic value is actually for the type of the left-hand side 1660b57cec5SDimitry Andric // expression, not the computation type, as this is the value the 1670b57cec5SDimitry Andric // LValue on the LHS will bind to. 1680b57cec5SDimitry Andric LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy, 1690b57cec5SDimitry Andric currBldrCtx->blockCount()); 1700b57cec5SDimitry Andric // However, we need to convert the symbol to the computation type. 1710b57cec5SDimitry Andric Result = svalBuilder.evalCast(LHSVal, CTy, LTy); 17206c3fb27SDimitry Andric } else { 1730b57cec5SDimitry Andric // The left-hand side may bind to a different value then the 1740b57cec5SDimitry Andric // computation type. 1750b57cec5SDimitry Andric LHSVal = svalBuilder.evalCast(Result, LTy, CTy); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric // In C++, assignment and compound assignment operators return an 1790b57cec5SDimitry Andric // lvalue. 1800b57cec5SDimitry Andric if (B->isGLValue()) 1810b57cec5SDimitry Andric state = state->BindExpr(B, LCtx, location); 1820b57cec5SDimitry Andric else 1830b57cec5SDimitry Andric state = state->BindExpr(B, LCtx, Result); 1840b57cec5SDimitry Andric 18506c3fb27SDimitry Andric evalStore(Tmp2, B, LHS, N, state, location, LHSVal); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric // FIXME: postvisits eventually go in ::Visit() 1900b57cec5SDimitry Andric getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, 1940b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric CanQualType T = getContext().getCanonicalType(BE->getType()); 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric const BlockDecl *BD = BE->getBlockDecl(); 1990b57cec5SDimitry Andric // Get the value of the block itself. 2000b57cec5SDimitry Andric SVal V = svalBuilder.getBlockPointer(BD, T, 2010b57cec5SDimitry Andric Pred->getLocationContext(), 2020b57cec5SDimitry Andric currBldrCtx->blockCount()); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric ProgramStateRef State = Pred->getState(); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // If we created a new MemRegion for the block, we should explicitly bind 2070b57cec5SDimitry Andric // the captured variables. 2080b57cec5SDimitry Andric if (const BlockDataRegion *BDR = 2090b57cec5SDimitry Andric dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { 2100b57cec5SDimitry Andric 21106c3fb27SDimitry Andric auto ReferencedVars = BDR->referenced_vars(); 2120b57cec5SDimitry Andric auto CI = BD->capture_begin(); 2130b57cec5SDimitry Andric auto CE = BD->capture_end(); 21406c3fb27SDimitry Andric for (auto Var : ReferencedVars) { 21506c3fb27SDimitry Andric const VarRegion *capturedR = Var.getCapturedRegion(); 21606c3fb27SDimitry Andric const TypedValueRegion *originalR = Var.getOriginalRegion(); 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric // If the capture had a copy expression, use the result of evaluating 2190b57cec5SDimitry Andric // that expression, otherwise use the original value. 2200b57cec5SDimitry Andric // We rely on the invariant that the block declaration's capture variables 2210b57cec5SDimitry Andric // are a prefix of the BlockDataRegion's referenced vars (which may include 2220b57cec5SDimitry Andric // referenced globals, etc.) to enable fast lookup of the capture for a 2230b57cec5SDimitry Andric // given referenced var. 2240b57cec5SDimitry Andric const Expr *copyExpr = nullptr; 2250b57cec5SDimitry Andric if (CI != CE) { 2260b57cec5SDimitry Andric assert(CI->getVariable() == capturedR->getDecl()); 2270b57cec5SDimitry Andric copyExpr = CI->getCopyExpr(); 2280b57cec5SDimitry Andric CI++; 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric if (capturedR != originalR) { 2320b57cec5SDimitry Andric SVal originalV; 2330b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 2340b57cec5SDimitry Andric if (copyExpr) { 2350b57cec5SDimitry Andric originalV = State->getSVal(copyExpr, LCtx); 2360b57cec5SDimitry Andric } else { 2370b57cec5SDimitry Andric originalV = State->getSVal(loc::MemRegionVal(originalR)); 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric ExplodedNodeSet Tmp; 2450b57cec5SDimitry Andric StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); 2460b57cec5SDimitry Andric Bldr.generateNode(BE, Pred, 2470b57cec5SDimitry Andric State->BindExpr(BE, Pred->getLocationContext(), V), 2480b57cec5SDimitry Andric nullptr, ProgramPoint::PostLValueKind); 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric // FIXME: Move all post/pre visits to ::Visit(). 2510b57cec5SDimitry Andric getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric ProgramStateRef ExprEngine::handleLValueBitCast( 2550b57cec5SDimitry Andric ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx, 2560b57cec5SDimitry Andric QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr, 2570b57cec5SDimitry Andric ExplodedNode* Pred) { 2580b57cec5SDimitry Andric if (T->isLValueReferenceType()) { 2590b57cec5SDimitry Andric assert(!CastE->getType()->isLValueReferenceType()); 2600b57cec5SDimitry Andric ExTy = getContext().getLValueReferenceType(ExTy); 2610b57cec5SDimitry Andric } else if (T->isRValueReferenceType()) { 2620b57cec5SDimitry Andric assert(!CastE->getType()->isRValueReferenceType()); 2630b57cec5SDimitry Andric ExTy = getContext().getRValueReferenceType(ExTy); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric // Delegate to SValBuilder to process. 2660b57cec5SDimitry Andric SVal OrigV = state->getSVal(Ex, LCtx); 2675f757f3fSDimitry Andric SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV); 2685f757f3fSDimitry Andric SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy); 2690b57cec5SDimitry Andric // Negate the result if we're treating the boolean as a signed i1 27081ad6265SDimitry Andric if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid()) 27181ad6265SDimitry Andric V = svalBuilder.evalMinus(V.castAs<NonLoc>()); 27281ad6265SDimitry Andric 2730b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, V); 2740b57cec5SDimitry Andric if (V.isUnknown() && !OrigV.isUnknown()) { 275480093f4SDimitry Andric state = escapeValues(state, OrigV, PSK_EscapeOther); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric return state; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, 2830b57cec5SDimitry Andric ExplodedNode *Pred, ExplodedNodeSet &Dst) { 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric ExplodedNodeSet dstPreStmt; 2860b57cec5SDimitry Andric getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this); 2870b57cec5SDimitry Andric 288fe6060f1SDimitry Andric if (CastE->getCastKind() == CK_LValueToRValue || 289fe6060f1SDimitry Andric CastE->getCastKind() == CK_LValueToRValueBitCast) { 29006c3fb27SDimitry Andric for (ExplodedNode *subExprNode : dstPreStmt) { 2910b57cec5SDimitry Andric ProgramStateRef state = subExprNode->getState(); 2920b57cec5SDimitry Andric const LocationContext *LCtx = subExprNode->getLocationContext(); 2930b57cec5SDimitry Andric evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx)); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric return; 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric // All other casts. 2990b57cec5SDimitry Andric QualType T = CastE->getType(); 3000b57cec5SDimitry Andric QualType ExTy = Ex->getType(); 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE)) 3030b57cec5SDimitry Andric T = ExCast->getTypeAsWritten(); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric StmtNodeBuilder Bldr(dstPreStmt, Dst, *currBldrCtx); 30606c3fb27SDimitry Andric for (ExplodedNode *Pred : dstPreStmt) { 3070b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 3080b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric switch (CastE->getCastKind()) { 3110b57cec5SDimitry Andric case CK_LValueToRValue: 312fe6060f1SDimitry Andric case CK_LValueToRValueBitCast: 3130b57cec5SDimitry Andric llvm_unreachable("LValueToRValue casts handled earlier."); 3140b57cec5SDimitry Andric case CK_ToVoid: 3150b57cec5SDimitry Andric continue; 3160b57cec5SDimitry Andric // The analyzer doesn't do anything special with these casts, 3170b57cec5SDimitry Andric // since it understands retain/release semantics already. 3180b57cec5SDimitry Andric case CK_ARCProduceObject: 3190b57cec5SDimitry Andric case CK_ARCConsumeObject: 3200b57cec5SDimitry Andric case CK_ARCReclaimReturnedObject: 3210b57cec5SDimitry Andric case CK_ARCExtendBlockObject: // Fall-through. 3220b57cec5SDimitry Andric case CK_CopyAndAutoreleaseBlockObject: 3230b57cec5SDimitry Andric // The analyser can ignore atomic casts for now, although some future 3240b57cec5SDimitry Andric // checkers may want to make certain that you're not modifying the same 3250b57cec5SDimitry Andric // value through atomic and nonatomic pointers. 3260b57cec5SDimitry Andric case CK_AtomicToNonAtomic: 3270b57cec5SDimitry Andric case CK_NonAtomicToAtomic: 3280b57cec5SDimitry Andric // True no-ops. 3290b57cec5SDimitry Andric case CK_NoOp: 3300b57cec5SDimitry Andric case CK_ConstructorConversion: 3310b57cec5SDimitry Andric case CK_UserDefinedConversion: 3320b57cec5SDimitry Andric case CK_FunctionToPointerDecay: 333*0fca6ea1SDimitry Andric case CK_BuiltinFnToFnPtr: 334*0fca6ea1SDimitry Andric case CK_HLSLArrayRValue: { 3350b57cec5SDimitry Andric // Copy the SVal of Ex to CastE. 3360b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 3370b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 3380b57cec5SDimitry Andric SVal V = state->getSVal(Ex, LCtx); 3390b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, V); 3400b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 3410b57cec5SDimitry Andric continue; 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric case CK_MemberPointerToBoolean: 3440b57cec5SDimitry Andric case CK_PointerToBoolean: { 3450b57cec5SDimitry Andric SVal V = state->getSVal(Ex, LCtx); 3460b57cec5SDimitry Andric auto PTMSV = V.getAs<nonloc::PointerToMember>(); 3470b57cec5SDimitry Andric if (PTMSV) 3480b57cec5SDimitry Andric V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy); 3490b57cec5SDimitry Andric if (V.isUndef() || PTMSV) { 3500b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, V); 3510b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 3520b57cec5SDimitry Andric continue; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric // Explicitly proceed with default handler for this case cascade. 3550b57cec5SDimitry Andric state = 3560b57cec5SDimitry Andric handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); 3570b57cec5SDimitry Andric continue; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric case CK_Dependent: 3600b57cec5SDimitry Andric case CK_ArrayToPointerDecay: 3610b57cec5SDimitry Andric case CK_BitCast: 3620b57cec5SDimitry Andric case CK_AddressSpaceConversion: 3630b57cec5SDimitry Andric case CK_BooleanToSignedIntegral: 3640b57cec5SDimitry Andric case CK_IntegralToPointer: 3650b57cec5SDimitry Andric case CK_PointerToIntegral: { 3660b57cec5SDimitry Andric SVal V = state->getSVal(Ex, LCtx); 36781ad6265SDimitry Andric if (isa<nonloc::PointerToMember>(V)) { 3680b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, UnknownVal()); 3690b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 3700b57cec5SDimitry Andric continue; 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric // Explicitly proceed with default handler for this case cascade. 3730b57cec5SDimitry Andric state = 3740b57cec5SDimitry Andric handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); 3750b57cec5SDimitry Andric continue; 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric case CK_IntegralToBoolean: 3780b57cec5SDimitry Andric case CK_IntegralToFloating: 3790b57cec5SDimitry Andric case CK_FloatingToIntegral: 3800b57cec5SDimitry Andric case CK_FloatingToBoolean: 3810b57cec5SDimitry Andric case CK_FloatingCast: 3820b57cec5SDimitry Andric case CK_FloatingRealToComplex: 3830b57cec5SDimitry Andric case CK_FloatingComplexToReal: 3840b57cec5SDimitry Andric case CK_FloatingComplexToBoolean: 3850b57cec5SDimitry Andric case CK_FloatingComplexCast: 3860b57cec5SDimitry Andric case CK_FloatingComplexToIntegralComplex: 3870b57cec5SDimitry Andric case CK_IntegralRealToComplex: 3880b57cec5SDimitry Andric case CK_IntegralComplexToReal: 3890b57cec5SDimitry Andric case CK_IntegralComplexToBoolean: 3900b57cec5SDimitry Andric case CK_IntegralComplexCast: 3910b57cec5SDimitry Andric case CK_IntegralComplexToFloatingComplex: 3920b57cec5SDimitry Andric case CK_CPointerToObjCPointerCast: 3930b57cec5SDimitry Andric case CK_BlockPointerToObjCPointerCast: 3940b57cec5SDimitry Andric case CK_AnyPointerToBlockPointerCast: 3950b57cec5SDimitry Andric case CK_ObjCObjectLValueCast: 3960b57cec5SDimitry Andric case CK_ZeroToOCLOpaqueType: 3970b57cec5SDimitry Andric case CK_IntToOCLSampler: 3980b57cec5SDimitry Andric case CK_LValueBitCast: 399e8d8bef9SDimitry Andric case CK_FloatingToFixedPoint: 400e8d8bef9SDimitry Andric case CK_FixedPointToFloating: 4010b57cec5SDimitry Andric case CK_FixedPointCast: 4020b57cec5SDimitry Andric case CK_FixedPointToBoolean: 4030b57cec5SDimitry Andric case CK_FixedPointToIntegral: 4040b57cec5SDimitry Andric case CK_IntegralToFixedPoint: { 4050b57cec5SDimitry Andric state = 4060b57cec5SDimitry Andric handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); 4070b57cec5SDimitry Andric continue; 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric case CK_IntegralCast: { 4100b57cec5SDimitry Andric // Delegate to SValBuilder to process. 4110b57cec5SDimitry Andric SVal V = state->getSVal(Ex, LCtx); 41204eeddc0SDimitry Andric if (AMgr.options.ShouldSupportSymbolicIntegerCasts) 41304eeddc0SDimitry Andric V = svalBuilder.evalCast(V, T, ExTy); 41404eeddc0SDimitry Andric else 4150b57cec5SDimitry Andric V = svalBuilder.evalIntegralCast(state, V, T, ExTy); 4160b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, V); 4170b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 4180b57cec5SDimitry Andric continue; 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric case CK_DerivedToBase: 4210b57cec5SDimitry Andric case CK_UncheckedDerivedToBase: { 4220b57cec5SDimitry Andric // For DerivedToBase cast, delegate to the store manager. 4230b57cec5SDimitry Andric SVal val = state->getSVal(Ex, LCtx); 4240b57cec5SDimitry Andric val = getStoreManager().evalDerivedToBase(val, CastE); 4250b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, val); 4260b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 4270b57cec5SDimitry Andric continue; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric // Handle C++ dyn_cast. 4300b57cec5SDimitry Andric case CK_Dynamic: { 4310b57cec5SDimitry Andric SVal val = state->getSVal(Ex, LCtx); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric // Compute the type of the result. 4340b57cec5SDimitry Andric QualType resultType = CastE->getType(); 4350b57cec5SDimitry Andric if (CastE->isGLValue()) 4360b57cec5SDimitry Andric resultType = getContext().getPointerType(resultType); 4370b57cec5SDimitry Andric 4380eae32dcSDimitry Andric bool Failed = true; 4390b57cec5SDimitry Andric 4400eae32dcSDimitry Andric // Check if the value being cast does not evaluates to 0. 4410eae32dcSDimitry Andric if (!val.isZeroConstant()) 442bdd1243dSDimitry Andric if (std::optional<SVal> V = 4430eae32dcSDimitry Andric StateMgr.getStoreManager().evalBaseToDerived(val, T)) { 4440eae32dcSDimitry Andric val = *V; 4450eae32dcSDimitry Andric Failed = false; 4460eae32dcSDimitry Andric } 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric if (Failed) { 4490b57cec5SDimitry Andric if (T->isReferenceType()) { 4500b57cec5SDimitry Andric // A bad_cast exception is thrown if input value is a reference. 4510b57cec5SDimitry Andric // Currently, we model this, by generating a sink. 4520b57cec5SDimitry Andric Bldr.generateSink(CastE, Pred, state); 4530b57cec5SDimitry Andric continue; 4540b57cec5SDimitry Andric } else { 4550b57cec5SDimitry Andric // If the cast fails on a pointer, bind to 0. 45681ad6265SDimitry Andric state = state->BindExpr(CastE, LCtx, 45781ad6265SDimitry Andric svalBuilder.makeNullWithType(resultType)); 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric } else { 4600b57cec5SDimitry Andric // If we don't know if the cast succeeded, conjure a new symbol. 4610b57cec5SDimitry Andric if (val.isUnknown()) { 4620b57cec5SDimitry Andric DefinedOrUnknownSVal NewSym = 4630b57cec5SDimitry Andric svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, 4640b57cec5SDimitry Andric currBldrCtx->blockCount()); 4650b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, NewSym); 4660b57cec5SDimitry Andric } else 4670b57cec5SDimitry Andric // Else, bind to the derived region value. 4680b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, val); 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 4710b57cec5SDimitry Andric continue; 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric case CK_BaseToDerived: { 4740b57cec5SDimitry Andric SVal val = state->getSVal(Ex, LCtx); 4750b57cec5SDimitry Andric QualType resultType = CastE->getType(); 4760b57cec5SDimitry Andric if (CastE->isGLValue()) 4770b57cec5SDimitry Andric resultType = getContext().getPointerType(resultType); 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric if (!val.isConstant()) { 480bdd1243dSDimitry Andric std::optional<SVal> V = getStoreManager().evalBaseToDerived(val, T); 4810eae32dcSDimitry Andric val = V ? *V : UnknownVal(); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric // Failed to cast or the result is unknown, fall back to conservative. 4850eae32dcSDimitry Andric if (val.isUnknown()) { 4860b57cec5SDimitry Andric val = 4870b57cec5SDimitry Andric svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, 4880b57cec5SDimitry Andric currBldrCtx->blockCount()); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, val); 4910b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 4920b57cec5SDimitry Andric continue; 4930b57cec5SDimitry Andric } 4940b57cec5SDimitry Andric case CK_NullToPointer: { 49581ad6265SDimitry Andric SVal V = svalBuilder.makeNullWithType(CastE->getType()); 4960b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, V); 4970b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 4980b57cec5SDimitry Andric continue; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric case CK_NullToMemberPointer: { 5010b57cec5SDimitry Andric SVal V = svalBuilder.getMemberPointer(nullptr); 5020b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, V); 5030b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 5040b57cec5SDimitry Andric continue; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric case CK_DerivedToBaseMemberPointer: 5070b57cec5SDimitry Andric case CK_BaseToDerivedMemberPointer: 5080b57cec5SDimitry Andric case CK_ReinterpretMemberPointer: { 5090b57cec5SDimitry Andric SVal V = state->getSVal(Ex, LCtx); 5100b57cec5SDimitry Andric if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) { 511fe6060f1SDimitry Andric SVal CastedPTMSV = 512fe6060f1SDimitry Andric svalBuilder.makePointerToMember(getBasicVals().accumCXXBase( 513fe6060f1SDimitry Andric CastE->path(), *PTMSV, CastE->getCastKind())); 5140b57cec5SDimitry Andric state = state->BindExpr(CastE, LCtx, CastedPTMSV); 5150b57cec5SDimitry Andric Bldr.generateNode(CastE, Pred, state); 5160b57cec5SDimitry Andric continue; 5170b57cec5SDimitry Andric } 5180b57cec5SDimitry Andric // Explicitly proceed with default handler for this case cascade. 5190b57cec5SDimitry Andric } 520bdd1243dSDimitry Andric [[fallthrough]]; 5210b57cec5SDimitry Andric // Various C++ casts that are not handled yet. 5220b57cec5SDimitry Andric case CK_ToUnion: 523fe6060f1SDimitry Andric case CK_MatrixCast: 524*0fca6ea1SDimitry Andric case CK_VectorSplat: 525*0fca6ea1SDimitry Andric case CK_HLSLVectorTruncation: { 526fe6060f1SDimitry Andric QualType resultType = CastE->getType(); 527fe6060f1SDimitry Andric if (CastE->isGLValue()) 528fe6060f1SDimitry Andric resultType = getContext().getPointerType(resultType); 529fe6060f1SDimitry Andric SVal result = svalBuilder.conjureSymbolVal( 530fe6060f1SDimitry Andric /*symbolTag=*/nullptr, CastE, LCtx, resultType, 531fe6060f1SDimitry Andric currBldrCtx->blockCount()); 532fe6060f1SDimitry Andric state = state->BindExpr(CastE, LCtx, result); 533fe6060f1SDimitry Andric Bldr.generateNode(CastE, Pred, state); 5340b57cec5SDimitry Andric continue; 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, 5410b57cec5SDimitry Andric ExplodedNode *Pred, 5420b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 5430b57cec5SDimitry Andric StmtNodeBuilder B(Pred, Dst, *currBldrCtx); 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric ProgramStateRef State = Pred->getState(); 5460b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric const Expr *Init = CL->getInitializer(); 5490b57cec5SDimitry Andric SVal V = State->getSVal(CL->getInitializer(), LCtx); 5500b57cec5SDimitry Andric 551349cc55cSDimitry Andric if (isa<CXXConstructExpr, CXXStdInitializerListExpr>(Init)) { 5520b57cec5SDimitry Andric // No work needed. Just pass the value up to this expression. 5530b57cec5SDimitry Andric } else { 5540b57cec5SDimitry Andric assert(isa<InitListExpr>(Init)); 5550b57cec5SDimitry Andric Loc CLLoc = State->getLValue(CL, LCtx); 5560b57cec5SDimitry Andric State = State->bindLoc(CLLoc, V, LCtx); 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric if (CL->isGLValue()) 5590b57cec5SDimitry Andric V = CLLoc; 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V)); 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, 5660b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 5675ffd83dbSDimitry Andric if (isa<TypedefNameDecl>(*DS->decl_begin())) { 5685ffd83dbSDimitry Andric // C99 6.7.7 "Any array size expressions associated with variable length 5695ffd83dbSDimitry Andric // array declarators are evaluated each time the declaration of the typedef 5705ffd83dbSDimitry Andric // name is reached in the order of execution." 5715ffd83dbSDimitry Andric // The checkers should know about typedef to be able to handle VLA size 5725ffd83dbSDimitry Andric // expressions. 5735ffd83dbSDimitry Andric ExplodedNodeSet DstPre; 5745ffd83dbSDimitry Andric getCheckerManager().runCheckersForPreStmt(DstPre, Pred, DS, *this); 5755ffd83dbSDimitry Andric getCheckerManager().runCheckersForPostStmt(Dst, DstPre, DS, *this); 5765ffd83dbSDimitry Andric return; 5775ffd83dbSDimitry Andric } 5785ffd83dbSDimitry Andric 5790b57cec5SDimitry Andric // Assumption: The CFG has one DeclStmt per Decl. 5800b57cec5SDimitry Andric const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin()); 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric if (!VD) { 5830b57cec5SDimitry Andric //TODO:AZ: remove explicit insertion after refactoring is done. 5840b57cec5SDimitry Andric Dst.insert(Pred); 5850b57cec5SDimitry Andric return; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric // FIXME: all pre/post visits should eventually be handled by ::Visit(). 5890b57cec5SDimitry Andric ExplodedNodeSet dstPreVisit; 5900b57cec5SDimitry Andric getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this); 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric ExplodedNodeSet dstEvaluated; 5930b57cec5SDimitry Andric StmtNodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx); 5940b57cec5SDimitry Andric for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); 5950b57cec5SDimitry Andric I!=E; ++I) { 5960b57cec5SDimitry Andric ExplodedNode *N = *I; 5970b57cec5SDimitry Andric ProgramStateRef state = N->getState(); 5980b57cec5SDimitry Andric const LocationContext *LC = N->getLocationContext(); 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric // Decls without InitExpr are not initialized explicitly. 6010b57cec5SDimitry Andric if (const Expr *InitEx = VD->getInit()) { 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric // Note in the state that the initialization has occurred. 6040b57cec5SDimitry Andric ExplodedNode *UpdatedN = N; 6050b57cec5SDimitry Andric SVal InitVal = state->getSVal(InitEx, LC); 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric assert(DS->isSingleDecl()); 6080b57cec5SDimitry Andric if (getObjectUnderConstruction(state, DS, LC)) { 6090b57cec5SDimitry Andric state = finishObjectConstruction(state, DS, LC); 6100b57cec5SDimitry Andric // We constructed the object directly in the variable. 6110b57cec5SDimitry Andric // No need to bind anything. 6120b57cec5SDimitry Andric B.generateNode(DS, UpdatedN, state); 6130b57cec5SDimitry Andric } else { 6140b57cec5SDimitry Andric // Recover some path-sensitivity if a scalar value evaluated to 6150b57cec5SDimitry Andric // UnknownVal. 6160b57cec5SDimitry Andric if (InitVal.isUnknown()) { 6170b57cec5SDimitry Andric QualType Ty = InitEx->getType(); 6180b57cec5SDimitry Andric if (InitEx->isGLValue()) { 6190b57cec5SDimitry Andric Ty = getContext().getPointerType(Ty); 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty, 6230b57cec5SDimitry Andric currBldrCtx->blockCount()); 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric B.takeNodes(UpdatedN); 6280b57cec5SDimitry Andric ExplodedNodeSet Dst2; 6290b57cec5SDimitry Andric evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, LC), InitVal, true); 6300b57cec5SDimitry Andric B.addNodes(Dst2); 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric else { 6340b57cec5SDimitry Andric B.generateNode(DS, N, state); 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric getCheckerManager().runCheckersForPostStmt(Dst, B.getResults(), DS, *this); 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, 6420b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 6430b57cec5SDimitry Andric // This method acts upon CFG elements for logical operators && and || 6440b57cec5SDimitry Andric // and attaches the value (true or false) to them as expressions. 6450b57cec5SDimitry Andric // It doesn't produce any state splits. 6460b57cec5SDimitry Andric // If we made it that far, we're past the point when we modeled the short 6470b57cec5SDimitry Andric // circuit. It means that we should have precise knowledge about whether 6480b57cec5SDimitry Andric // we've short-circuited. If we did, we already know the value we need to 6490b57cec5SDimitry Andric // bind. If we didn't, the value of the RHS (casted to the boolean type) 6500b57cec5SDimitry Andric // is the answer. 6510b57cec5SDimitry Andric // Currently this method tries to figure out whether we've short-circuited 6520b57cec5SDimitry Andric // by looking at the ExplodedGraph. This method is imperfect because there 6530b57cec5SDimitry Andric // could inevitably have been merges that would have resulted in multiple 6540b57cec5SDimitry Andric // potential path traversal histories. We bail out when we fail. 6550b57cec5SDimitry Andric // Due to this ambiguity, a more reliable solution would have been to 6560b57cec5SDimitry Andric // track the short circuit operation history path-sensitively until 6570b57cec5SDimitry Andric // we evaluate the respective logical operator. 6580b57cec5SDimitry Andric assert(B->getOpcode() == BO_LAnd || 6590b57cec5SDimitry Andric B->getOpcode() == BO_LOr); 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 6620b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric if (B->getType()->isVectorType()) { 6650b57cec5SDimitry Andric // FIXME: We do not model vector arithmetic yet. When adding support for 6660b57cec5SDimitry Andric // that, note that the CFG-based reasoning below does not apply, because 6670b57cec5SDimitry Andric // logical operators on vectors are not short-circuit. Currently they are 6680b57cec5SDimitry Andric // modeled as short-circuit in Clang CFG but this is incorrect. 6690b57cec5SDimitry Andric // Do not set the value for the expression. It'd be UnknownVal by default. 6700b57cec5SDimitry Andric Bldr.generateNode(B, Pred, state); 6710b57cec5SDimitry Andric return; 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric ExplodedNode *N = Pred; 6750b57cec5SDimitry Andric while (!N->getLocation().getAs<BlockEntrance>()) { 6760b57cec5SDimitry Andric ProgramPoint P = N->getLocation(); 6770b57cec5SDimitry Andric assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>()); 6780b57cec5SDimitry Andric (void) P; 6790b57cec5SDimitry Andric if (N->pred_size() != 1) { 6800b57cec5SDimitry Andric // We failed to track back where we came from. 6810b57cec5SDimitry Andric Bldr.generateNode(B, Pred, state); 6820b57cec5SDimitry Andric return; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric N = *N->pred_begin(); 6850b57cec5SDimitry Andric } 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric if (N->pred_size() != 1) { 6880b57cec5SDimitry Andric // We failed to track back where we came from. 6890b57cec5SDimitry Andric Bldr.generateNode(B, Pred, state); 6900b57cec5SDimitry Andric return; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric N = *N->pred_begin(); 6940b57cec5SDimitry Andric BlockEdge BE = N->getLocation().castAs<BlockEdge>(); 6950b57cec5SDimitry Andric SVal X; 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric // Determine the value of the expression by introspecting how we 6980b57cec5SDimitry Andric // got this location in the CFG. This requires looking at the previous 6990b57cec5SDimitry Andric // block we were in and what kind of control-flow transfer was involved. 7000b57cec5SDimitry Andric const CFGBlock *SrcBlock = BE.getSrc(); 7010b57cec5SDimitry Andric // The only terminator (if there is one) that makes sense is a logical op. 7020b57cec5SDimitry Andric CFGTerminator T = SrcBlock->getTerminator(); 7030b57cec5SDimitry Andric if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) { 7040b57cec5SDimitry Andric (void) Term; 7050b57cec5SDimitry Andric assert(Term->isLogicalOp()); 7060b57cec5SDimitry Andric assert(SrcBlock->succ_size() == 2); 7070b57cec5SDimitry Andric // Did we take the true or false branch? 7080b57cec5SDimitry Andric unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0; 7090b57cec5SDimitry Andric X = svalBuilder.makeIntVal(constant, B->getType()); 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric else { 7120b57cec5SDimitry Andric // If there is no terminator, by construction the last statement 7130b57cec5SDimitry Andric // in SrcBlock is the value of the enclosing expression. 7140b57cec5SDimitry Andric // However, we still need to constrain that value to be 0 or 1. 7150b57cec5SDimitry Andric assert(!SrcBlock->empty()); 7160b57cec5SDimitry Andric CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>(); 7170b57cec5SDimitry Andric const Expr *RHS = cast<Expr>(Elem.getStmt()); 7180b57cec5SDimitry Andric SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext()); 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric if (RHSVal.isUndef()) { 7210b57cec5SDimitry Andric X = RHSVal; 7220b57cec5SDimitry Andric } else { 7230b57cec5SDimitry Andric // We evaluate "RHSVal != 0" expression which result in 0 if the value is 7240b57cec5SDimitry Andric // known to be false, 1 if the value is known to be true and a new symbol 7250b57cec5SDimitry Andric // when the assumption is unknown. 7260b57cec5SDimitry Andric nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); 7270b57cec5SDimitry Andric X = evalBinOp(N->getState(), BO_NE, 7280b57cec5SDimitry Andric svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()), 7290b57cec5SDimitry Andric Zero, B->getType()); 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric void ExprEngine::VisitInitListExpr(const InitListExpr *IE, 7360b57cec5SDimitry Andric ExplodedNode *Pred, 7370b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 7380b57cec5SDimitry Andric StmtNodeBuilder B(Pred, Dst, *currBldrCtx); 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 7410b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 7420b57cec5SDimitry Andric QualType T = getContext().getCanonicalType(IE->getType()); 7430b57cec5SDimitry Andric unsigned NumInitElements = IE->getNumInits(); 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric if (!IE->isGLValue() && !IE->isTransparent() && 7460b57cec5SDimitry Andric (T->isArrayType() || T->isRecordType() || T->isVectorType() || 7470b57cec5SDimitry Andric T->isAnyComplexType())) { 7480b57cec5SDimitry Andric llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric // Handle base case where the initializer has no elements. 7510b57cec5SDimitry Andric // e.g: static int* myArray[] = {}; 7520b57cec5SDimitry Andric if (NumInitElements == 0) { 7530b57cec5SDimitry Andric SVal V = svalBuilder.makeCompoundVal(T, vals); 7540b57cec5SDimitry Andric B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); 7550b57cec5SDimitry Andric return; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 758349cc55cSDimitry Andric for (const Stmt *S : llvm::reverse(*IE)) { 759349cc55cSDimitry Andric SVal V = state->getSVal(cast<Expr>(S), LCtx); 7600b57cec5SDimitry Andric vals = getBasicVals().prependSVal(V, vals); 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric B.generateNode(IE, Pred, 7640b57cec5SDimitry Andric state->BindExpr(IE, LCtx, 7650b57cec5SDimitry Andric svalBuilder.makeCompoundVal(T, vals))); 7660b57cec5SDimitry Andric return; 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric // Handle scalars: int{5} and int{} and GLvalues. 7700b57cec5SDimitry Andric // Note, if the InitListExpr is a GLvalue, it means that there is an address 7710b57cec5SDimitry Andric // representing it, so it must have a single init element. 7720b57cec5SDimitry Andric assert(NumInitElements <= 1); 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric SVal V; 7750b57cec5SDimitry Andric if (NumInitElements == 0) 7760b57cec5SDimitry Andric V = getSValBuilder().makeZeroVal(T); 7770b57cec5SDimitry Andric else 7780b57cec5SDimitry Andric V = state->getSVal(IE->getInit(0), LCtx); 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); 7810b57cec5SDimitry Andric } 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric void ExprEngine::VisitGuardedExpr(const Expr *Ex, 7840b57cec5SDimitry Andric const Expr *L, 7850b57cec5SDimitry Andric const Expr *R, 7860b57cec5SDimitry Andric ExplodedNode *Pred, 7870b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 7880b57cec5SDimitry Andric assert(L && R); 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric StmtNodeBuilder B(Pred, Dst, *currBldrCtx); 7910b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 7920b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 7930b57cec5SDimitry Andric const CFGBlock *SrcBlock = nullptr; 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric // Find the predecessor block. 7960b57cec5SDimitry Andric ProgramStateRef SrcState = state; 7970b57cec5SDimitry Andric for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) { 7980b57cec5SDimitry Andric ProgramPoint PP = N->getLocation(); 7990b57cec5SDimitry Andric if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) { 8000b57cec5SDimitry Andric // If the state N has multiple predecessors P, it means that successors 8010b57cec5SDimitry Andric // of P are all equivalent. 8020b57cec5SDimitry Andric // In turn, that means that all nodes at P are equivalent in terms 8030b57cec5SDimitry Andric // of observable behavior at N, and we can follow any of them. 8040b57cec5SDimitry Andric // FIXME: a more robust solution which does not walk up the tree. 8050b57cec5SDimitry Andric continue; 8060b57cec5SDimitry Andric } 8070b57cec5SDimitry Andric SrcBlock = PP.castAs<BlockEdge>().getSrc(); 8080b57cec5SDimitry Andric SrcState = N->getState(); 8090b57cec5SDimitry Andric break; 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric assert(SrcBlock && "missing function entry"); 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric // Find the last expression in the predecessor block. That is the 8150b57cec5SDimitry Andric // expression that is used for the value of the ternary expression. 8160b57cec5SDimitry Andric bool hasValue = false; 8170b57cec5SDimitry Andric SVal V; 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric for (CFGElement CE : llvm::reverse(*SrcBlock)) { 820bdd1243dSDimitry Andric if (std::optional<CFGStmt> CS = CE.getAs<CFGStmt>()) { 8210b57cec5SDimitry Andric const Expr *ValEx = cast<Expr>(CS->getStmt()); 8220b57cec5SDimitry Andric ValEx = ValEx->IgnoreParens(); 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric // For GNU extension '?:' operator, the left hand side will be an 8250b57cec5SDimitry Andric // OpaqueValueExpr, so get the underlying expression. 8260b57cec5SDimitry Andric if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L)) 8270b57cec5SDimitry Andric L = OpaqueEx->getSourceExpr(); 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric // If the last expression in the predecessor block matches true or false 8300b57cec5SDimitry Andric // subexpression, get its the value. 8310b57cec5SDimitry Andric if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) { 8320b57cec5SDimitry Andric hasValue = true; 8330b57cec5SDimitry Andric V = SrcState->getSVal(ValEx, LCtx); 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric break; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric if (!hasValue) 8400b57cec5SDimitry Andric V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, 8410b57cec5SDimitry Andric currBldrCtx->blockCount()); 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric // Generate a new node with the binding from the appropriate path. 8440b57cec5SDimitry Andric B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric void ExprEngine:: 8480b57cec5SDimitry Andric VisitOffsetOfExpr(const OffsetOfExpr *OOE, 8490b57cec5SDimitry Andric ExplodedNode *Pred, ExplodedNodeSet &Dst) { 8500b57cec5SDimitry Andric StmtNodeBuilder B(Pred, Dst, *currBldrCtx); 8510b57cec5SDimitry Andric Expr::EvalResult Result; 8520b57cec5SDimitry Andric if (OOE->EvaluateAsInt(Result, getContext())) { 8530b57cec5SDimitry Andric APSInt IV = Result.Val.getInt(); 8540b57cec5SDimitry Andric assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); 855a7dea167SDimitry Andric assert(OOE->getType()->castAs<BuiltinType>()->isInteger()); 8560b57cec5SDimitry Andric assert(IV.isSigned() == OOE->getType()->isSignedIntegerType()); 8570b57cec5SDimitry Andric SVal X = svalBuilder.makeIntVal(IV); 8580b57cec5SDimitry Andric B.generateNode(OOE, Pred, 8590b57cec5SDimitry Andric Pred->getState()->BindExpr(OOE, Pred->getLocationContext(), 8600b57cec5SDimitry Andric X)); 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric // FIXME: Handle the case where __builtin_offsetof is not a constant. 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric void ExprEngine:: 8670b57cec5SDimitry Andric VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, 8680b57cec5SDimitry Andric ExplodedNode *Pred, 8690b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 8700b57cec5SDimitry Andric // FIXME: Prechecks eventually go in ::Visit(). 8710b57cec5SDimitry Andric ExplodedNodeSet CheckedSet; 8720b57cec5SDimitry Andric getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric ExplodedNodeSet EvalSet; 8750b57cec5SDimitry Andric StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric QualType T = Ex->getTypeOfArgument(); 8780b57cec5SDimitry Andric 87906c3fb27SDimitry Andric for (ExplodedNode *N : CheckedSet) { 8800b57cec5SDimitry Andric if (Ex->getKind() == UETT_SizeOf) { 8810b57cec5SDimitry Andric if (!T->isIncompleteType() && !T->isConstantSizeType()) { 8820b57cec5SDimitry Andric assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric // FIXME: Add support for VLA type arguments and VLA expressions. 8850b57cec5SDimitry Andric // When that happens, we should probably refactor VLASizeChecker's code. 8860b57cec5SDimitry Andric continue; 8870b57cec5SDimitry Andric } else if (T->getAs<ObjCObjectType>()) { 8880b57cec5SDimitry Andric // Some code tries to take the sizeof an ObjCObjectType, relying that 8890b57cec5SDimitry Andric // the compiler has laid out its representation. Just report Unknown 8900b57cec5SDimitry Andric // for these. 8910b57cec5SDimitry Andric continue; 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric APSInt Value = Ex->EvaluateKnownConstInt(getContext()); 8960b57cec5SDimitry Andric CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); 8970b57cec5SDimitry Andric 89806c3fb27SDimitry Andric ProgramStateRef state = N->getState(); 89906c3fb27SDimitry Andric state = state->BindExpr( 90006c3fb27SDimitry Andric Ex, N->getLocationContext(), 90106c3fb27SDimitry Andric svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())); 90206c3fb27SDimitry Andric Bldr.generateNode(Ex, N, state); 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this); 9060b57cec5SDimitry Andric } 9070b57cec5SDimitry Andric 90806c3fb27SDimitry Andric void ExprEngine::handleUOExtension(ExplodedNode *N, const UnaryOperator *U, 9090b57cec5SDimitry Andric StmtNodeBuilder &Bldr) { 9100b57cec5SDimitry Andric // FIXME: We can probably just have some magic in Environment::getSVal() 9110b57cec5SDimitry Andric // that propagates values, instead of creating a new node here. 9120b57cec5SDimitry Andric // 9130b57cec5SDimitry Andric // Unary "+" is a no-op, similar to a parentheses. We still have places 9140b57cec5SDimitry Andric // where it may be a block-level expression, so we need to 9150b57cec5SDimitry Andric // generate an extra node that just propagates the value of the 9160b57cec5SDimitry Andric // subexpression. 9170b57cec5SDimitry Andric const Expr *Ex = U->getSubExpr()->IgnoreParens(); 91806c3fb27SDimitry Andric ProgramStateRef state = N->getState(); 91906c3fb27SDimitry Andric const LocationContext *LCtx = N->getLocationContext(); 92006c3fb27SDimitry Andric Bldr.generateNode(U, N, state->BindExpr(U, LCtx, state->getSVal(Ex, LCtx))); 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred, 9240b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 9250b57cec5SDimitry Andric // FIXME: Prechecks eventually go in ::Visit(). 9260b57cec5SDimitry Andric ExplodedNodeSet CheckedSet; 9270b57cec5SDimitry Andric getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this); 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric ExplodedNodeSet EvalSet; 9300b57cec5SDimitry Andric StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); 9310b57cec5SDimitry Andric 93206c3fb27SDimitry Andric for (ExplodedNode *N : CheckedSet) { 9330b57cec5SDimitry Andric switch (U->getOpcode()) { 9340b57cec5SDimitry Andric default: { 93506c3fb27SDimitry Andric Bldr.takeNodes(N); 9360b57cec5SDimitry Andric ExplodedNodeSet Tmp; 93706c3fb27SDimitry Andric VisitIncrementDecrementOperator(U, N, Tmp); 9380b57cec5SDimitry Andric Bldr.addNodes(Tmp); 9390b57cec5SDimitry Andric break; 9400b57cec5SDimitry Andric } 9410b57cec5SDimitry Andric case UO_Real: { 9420b57cec5SDimitry Andric const Expr *Ex = U->getSubExpr()->IgnoreParens(); 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric // FIXME: We don't have complex SValues yet. 9450b57cec5SDimitry Andric if (Ex->getType()->isAnyComplexType()) { 9460b57cec5SDimitry Andric // Just report "Unknown." 9470b57cec5SDimitry Andric break; 9480b57cec5SDimitry Andric } 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric // For all other types, UO_Real is an identity operation. 9510b57cec5SDimitry Andric assert (U->getType() == Ex->getType()); 95206c3fb27SDimitry Andric ProgramStateRef state = N->getState(); 95306c3fb27SDimitry Andric const LocationContext *LCtx = N->getLocationContext(); 95406c3fb27SDimitry Andric Bldr.generateNode(U, N, 95506c3fb27SDimitry Andric state->BindExpr(U, LCtx, state->getSVal(Ex, LCtx))); 9560b57cec5SDimitry Andric break; 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric 9590b57cec5SDimitry Andric case UO_Imag: { 9600b57cec5SDimitry Andric const Expr *Ex = U->getSubExpr()->IgnoreParens(); 9610b57cec5SDimitry Andric // FIXME: We don't have complex SValues yet. 9620b57cec5SDimitry Andric if (Ex->getType()->isAnyComplexType()) { 9630b57cec5SDimitry Andric // Just report "Unknown." 9640b57cec5SDimitry Andric break; 9650b57cec5SDimitry Andric } 9660b57cec5SDimitry Andric // For all other types, UO_Imag returns 0. 96706c3fb27SDimitry Andric ProgramStateRef state = N->getState(); 96806c3fb27SDimitry Andric const LocationContext *LCtx = N->getLocationContext(); 9690b57cec5SDimitry Andric SVal X = svalBuilder.makeZeroVal(Ex->getType()); 97006c3fb27SDimitry Andric Bldr.generateNode(U, N, state->BindExpr(U, LCtx, X)); 9710b57cec5SDimitry Andric break; 9720b57cec5SDimitry Andric } 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric case UO_AddrOf: { 9750b57cec5SDimitry Andric // Process pointer-to-member address operation. 9760b57cec5SDimitry Andric const Expr *Ex = U->getSubExpr()->IgnoreParens(); 9770b57cec5SDimitry Andric if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex)) { 9780b57cec5SDimitry Andric const ValueDecl *VD = DRE->getDecl(); 9790b57cec5SDimitry Andric 980349cc55cSDimitry Andric if (isa<CXXMethodDecl, FieldDecl, IndirectFieldDecl>(VD)) { 98106c3fb27SDimitry Andric ProgramStateRef State = N->getState(); 98206c3fb27SDimitry Andric const LocationContext *LCtx = N->getLocationContext(); 983e8d8bef9SDimitry Andric SVal SV = svalBuilder.getMemberPointer(cast<NamedDecl>(VD)); 98406c3fb27SDimitry Andric Bldr.generateNode(U, N, State->BindExpr(U, LCtx, SV)); 9850b57cec5SDimitry Andric break; 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric // Explicitly proceed with default handler for this case cascade. 98906c3fb27SDimitry Andric handleUOExtension(N, U, Bldr); 9900b57cec5SDimitry Andric break; 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric case UO_Plus: 9930b57cec5SDimitry Andric assert(!U->isGLValue()); 994bdd1243dSDimitry Andric [[fallthrough]]; 9950b57cec5SDimitry Andric case UO_Deref: 9960b57cec5SDimitry Andric case UO_Extension: { 99706c3fb27SDimitry Andric handleUOExtension(N, U, Bldr); 9980b57cec5SDimitry Andric break; 9990b57cec5SDimitry Andric } 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric case UO_LNot: 10020b57cec5SDimitry Andric case UO_Minus: 10030b57cec5SDimitry Andric case UO_Not: { 10040b57cec5SDimitry Andric assert (!U->isGLValue()); 10050b57cec5SDimitry Andric const Expr *Ex = U->getSubExpr()->IgnoreParens(); 100606c3fb27SDimitry Andric ProgramStateRef state = N->getState(); 100706c3fb27SDimitry Andric const LocationContext *LCtx = N->getLocationContext(); 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric // Get the value of the subexpression. 10100b57cec5SDimitry Andric SVal V = state->getSVal(Ex, LCtx); 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric if (V.isUnknownOrUndef()) { 101306c3fb27SDimitry Andric Bldr.generateNode(U, N, state->BindExpr(U, LCtx, V)); 10140b57cec5SDimitry Andric break; 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric switch (U->getOpcode()) { 10180b57cec5SDimitry Andric default: 10190b57cec5SDimitry Andric llvm_unreachable("Invalid Opcode."); 10200b57cec5SDimitry Andric case UO_Not: 10210b57cec5SDimitry Andric // FIXME: Do we need to handle promotions? 102281ad6265SDimitry Andric state = state->BindExpr( 102381ad6265SDimitry Andric U, LCtx, svalBuilder.evalComplement(V.castAs<NonLoc>())); 10240b57cec5SDimitry Andric break; 10250b57cec5SDimitry Andric case UO_Minus: 10260b57cec5SDimitry Andric // FIXME: Do we need to handle promotions? 102781ad6265SDimitry Andric state = state->BindExpr(U, LCtx, 102881ad6265SDimitry Andric svalBuilder.evalMinus(V.castAs<NonLoc>())); 10290b57cec5SDimitry Andric break; 10300b57cec5SDimitry Andric case UO_LNot: 10310b57cec5SDimitry Andric // C99 6.5.3.3: "The expression !E is equivalent to (0==E)." 10320b57cec5SDimitry Andric // 10330b57cec5SDimitry Andric // Note: technically we do "E == 0", but this is the same in the 10340b57cec5SDimitry Andric // transfer functions as "0 == E". 10350b57cec5SDimitry Andric SVal Result; 1036bdd1243dSDimitry Andric if (std::optional<Loc> LV = V.getAs<Loc>()) { 10370b57cec5SDimitry Andric Loc X = svalBuilder.makeNullWithType(Ex->getType()); 10380b57cec5SDimitry Andric Result = evalBinOp(state, BO_EQ, *LV, X, U->getType()); 10390b57cec5SDimitry Andric } else if (Ex->getType()->isFloatingType()) { 10400b57cec5SDimitry Andric // FIXME: handle floating point types. 10410b57cec5SDimitry Andric Result = UnknownVal(); 10420b57cec5SDimitry Andric } else { 10430b57cec5SDimitry Andric nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType())); 1044bdd1243dSDimitry Andric Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X, U->getType()); 10450b57cec5SDimitry Andric } 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric state = state->BindExpr(U, LCtx, Result); 10480b57cec5SDimitry Andric break; 10490b57cec5SDimitry Andric } 105006c3fb27SDimitry Andric Bldr.generateNode(U, N, state); 10510b57cec5SDimitry Andric break; 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric } 10540b57cec5SDimitry Andric } 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, U, *this); 10570b57cec5SDimitry Andric } 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, 10600b57cec5SDimitry Andric ExplodedNode *Pred, 10610b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 10620b57cec5SDimitry Andric // Handle ++ and -- (both pre- and post-increment). 10630b57cec5SDimitry Andric assert (U->isIncrementDecrementOp()); 10640b57cec5SDimitry Andric const Expr *Ex = U->getSubExpr()->IgnoreParens(); 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 10670b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 10680b57cec5SDimitry Andric SVal loc = state->getSVal(Ex, LCtx); 10690b57cec5SDimitry Andric 10700b57cec5SDimitry Andric // Perform a load. 10710b57cec5SDimitry Andric ExplodedNodeSet Tmp; 10720b57cec5SDimitry Andric evalLoad(Tmp, U, Ex, Pred, state, loc); 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric ExplodedNodeSet Dst2; 10750b57cec5SDimitry Andric StmtNodeBuilder Bldr(Tmp, Dst2, *currBldrCtx); 107606c3fb27SDimitry Andric for (ExplodedNode *N : Tmp) { 107706c3fb27SDimitry Andric state = N->getState(); 107806c3fb27SDimitry Andric assert(LCtx == N->getLocationContext()); 10790b57cec5SDimitry Andric SVal V2_untested = state->getSVal(Ex, LCtx); 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric // Propagate unknown and undefined values. 10820b57cec5SDimitry Andric if (V2_untested.isUnknownOrUndef()) { 10830b57cec5SDimitry Andric state = state->BindExpr(U, LCtx, V2_untested); 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric // Perform the store, so that the uninitialized value detection happens. 108606c3fb27SDimitry Andric Bldr.takeNodes(N); 10870b57cec5SDimitry Andric ExplodedNodeSet Dst3; 108806c3fb27SDimitry Andric evalStore(Dst3, U, Ex, N, state, loc, V2_untested); 10890b57cec5SDimitry Andric Bldr.addNodes(Dst3); 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andric continue; 10920b57cec5SDimitry Andric } 10930b57cec5SDimitry Andric DefinedSVal V2 = V2_untested.castAs<DefinedSVal>(); 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric // Handle all other values. 10960b57cec5SDimitry Andric BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub; 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric // If the UnaryOperator has non-location type, use its type to create the 10990b57cec5SDimitry Andric // constant value. If the UnaryOperator has location type, create the 11000b57cec5SDimitry Andric // constant with int type and pointer width. 11010b57cec5SDimitry Andric SVal RHS; 11020b57cec5SDimitry Andric SVal Result; 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric if (U->getType()->isAnyPointerType()) 11050b57cec5SDimitry Andric RHS = svalBuilder.makeArrayIndex(1); 11060b57cec5SDimitry Andric else if (U->getType()->isIntegralOrEnumerationType()) 11070b57cec5SDimitry Andric RHS = svalBuilder.makeIntVal(1, U->getType()); 11080b57cec5SDimitry Andric else 11090b57cec5SDimitry Andric RHS = UnknownVal(); 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric // The use of an operand of type bool with the ++ operators is deprecated 11120b57cec5SDimitry Andric // but valid until C++17. And if the operand of the ++ operator is of type 11130b57cec5SDimitry Andric // bool, it is set to true until C++17. Note that for '_Bool', it is also 11140b57cec5SDimitry Andric // set to true when it encounters ++ operator. 11150b57cec5SDimitry Andric if (U->getType()->isBooleanType() && U->isIncrementOp()) 11160b57cec5SDimitry Andric Result = svalBuilder.makeTruthVal(true, U->getType()); 11170b57cec5SDimitry Andric else 11180b57cec5SDimitry Andric Result = evalBinOp(state, Op, V2, RHS, U->getType()); 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric // Conjure a new symbol if necessary to recover precision. 11210b57cec5SDimitry Andric if (Result.isUnknown()){ 11220b57cec5SDimitry Andric DefinedOrUnknownSVal SymVal = 11230b57cec5SDimitry Andric svalBuilder.conjureSymbolVal(nullptr, U, LCtx, 11240b57cec5SDimitry Andric currBldrCtx->blockCount()); 11250b57cec5SDimitry Andric Result = SymVal; 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric // If the value is a location, ++/-- should always preserve 11280b57cec5SDimitry Andric // non-nullness. Check if the original value was non-null, and if so 11290b57cec5SDimitry Andric // propagate that constraint. 11300b57cec5SDimitry Andric if (Loc::isLocType(U->getType())) { 11310b57cec5SDimitry Andric DefinedOrUnknownSVal Constraint = 11320b57cec5SDimitry Andric svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType())); 11330b57cec5SDimitry Andric 11340b57cec5SDimitry Andric if (!state->assume(Constraint, true)) { 11350b57cec5SDimitry Andric // It isn't feasible for the original value to be null. 11360b57cec5SDimitry Andric // Propagate this constraint. 11370b57cec5SDimitry Andric Constraint = svalBuilder.evalEQ(state, SymVal, 11380b57cec5SDimitry Andric svalBuilder.makeZeroVal(U->getType())); 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric state = state->assume(Constraint, false); 11410b57cec5SDimitry Andric assert(state); 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric } 11440b57cec5SDimitry Andric } 11450b57cec5SDimitry Andric 11460b57cec5SDimitry Andric // Since the lvalue-to-rvalue conversion is explicit in the AST, 11470b57cec5SDimitry Andric // we bind an l-value if the operator is prefix and an lvalue (in C++). 11480b57cec5SDimitry Andric if (U->isGLValue()) 11490b57cec5SDimitry Andric state = state->BindExpr(U, LCtx, loc); 11500b57cec5SDimitry Andric else 11510b57cec5SDimitry Andric state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result); 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric // Perform the store. 115406c3fb27SDimitry Andric Bldr.takeNodes(N); 11550b57cec5SDimitry Andric ExplodedNodeSet Dst3; 115606c3fb27SDimitry Andric evalStore(Dst3, U, Ex, N, state, loc, Result); 11570b57cec5SDimitry Andric Bldr.addNodes(Dst3); 11580b57cec5SDimitry Andric } 11590b57cec5SDimitry Andric Dst.insert(Dst2); 11600b57cec5SDimitry Andric } 1161