xref: /freebsd-src/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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