diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 89 |
1 files changed, 54 insertions, 35 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 983fda00a2ff..ffda52709dc2 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -47,7 +47,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, // FIXME: Handle structs. if (RightV.isUnknown()) { unsigned Count = currBldrCtx->blockCount(); - RightV = svalBuilder.conjureSymbolVal(0, B->getRHS(), LCtx, Count); + RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, + Count); } // Simulate the effects of a "store": bind the value of the RHS // to the L-Value represented by the LHS. @@ -81,6 +82,12 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, } } + // Although we don't yet model pointers-to-members, we do need to make + // sure that the members of temporaries have a valid 'this' pointer for + // other checks. + if (B->getOpcode() == BO_PtrMemD) + state = createTemporaryRegionIfNeeded(state, LCtx, LHS); + // Process non-assignments except commas or short-circuited // logical expressions (LAnd and LOr). SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType()); @@ -151,7 +158,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, // The symbolic value is actually for the type of the left-hand side // expression, not the computation type, as this is the value the // LValue on the LHS will bind to. - LHSVal = svalBuilder.conjureSymbolVal(0, B->getRHS(), LCtx, LTy, + LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy, currBldrCtx->blockCount()); // However, we need to convert the symbol to the computation type. Result = svalBuilder.evalCast(LHSVal, CTy, LTy); @@ -211,8 +218,8 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); Bldr.generateNode(BE, Pred, State->BindExpr(BE, Pred->getLocationContext(), V), - 0, ProgramPoint::PostLValueKind); - + nullptr, ProgramPoint::PostLValueKind); + // FIXME: Move all post/pre visits to ::Visit(). getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this); } @@ -286,6 +293,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_Dependent: case CK_ArrayToPointerDecay: case CK_BitCast: + case CK_AddressSpaceConversion: case CK_IntegralCast: case CK_NullToPointer: case CK_IntegralToPointer: @@ -360,7 +368,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, // If we don't know if the cast succeeded, conjure a new symbol. if (val.isUnknown()) { DefinedOrUnknownSVal NewSym = - svalBuilder.conjureSymbolVal(0, CastE, LCtx, resultType, + svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, currBldrCtx->blockCount()); state = state->BindExpr(CastE, LCtx, NewSym); } else @@ -388,7 +396,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, QualType resultType = CastE->getType(); if (CastE->isGLValue()) resultType = getContext().getPointerType(resultType); - SVal result = svalBuilder.conjureSymbolVal(0, CastE, LCtx, + SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, currBldrCtx->blockCount()); state = state->BindExpr(CastE, LCtx, result); @@ -486,7 +494,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, Ty = getContext().getPointerType(Ty); } - InitVal = svalBuilder.conjureSymbolVal(0, InitEx, LC, Ty, + InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty, currBldrCtx->blockCount()); } @@ -554,7 +562,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, } else { DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs<DefinedOrUnknownSVal>(); ProgramStateRef StTrue, StFalse; - llvm::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); + std::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); if (StTrue) { if (StFalse) { // We can't constrain the value to 0 or 1. @@ -633,7 +641,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, StmtNodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); - const CFGBlock *SrcBlock = 0; + const CFGBlock *SrcBlock = nullptr; // Find the predecessor block. ProgramStateRef SrcState = state; @@ -678,7 +686,8 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, } if (!hasValue) - V = svalBuilder.conjureSymbolVal(0, Ex, LCtx, currBldrCtx->blockCount()); + V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, + currBldrCtx->blockCount()); // Generate a new node with the binding from the appropriate path. B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); @@ -707,34 +716,43 @@ void ExprEngine:: VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + // FIXME: Prechecks eventually go in ::Visit(). + ExplodedNodeSet CheckedSet; + getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); + + ExplodedNodeSet EvalSet; + StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); QualType T = Ex->getTypeOfArgument(); - - if (Ex->getKind() == UETT_SizeOf) { - if (!T->isIncompleteType() && !T->isConstantSizeType()) { - assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); - - // FIXME: Add support for VLA type arguments and VLA expressions. - // When that happens, we should probably refactor VLASizeChecker's code. - return; - } - else if (T->getAs<ObjCObjectType>()) { - // Some code tries to take the sizeof an ObjCObjectType, relying that - // the compiler has laid out its representation. Just report Unknown - // for these. - return; + + for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); + I != E; ++I) { + if (Ex->getKind() == UETT_SizeOf) { + if (!T->isIncompleteType() && !T->isConstantSizeType()) { + assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); + + // FIXME: Add support for VLA type arguments and VLA expressions. + // When that happens, we should probably refactor VLASizeChecker's code. + continue; + } else if (T->getAs<ObjCObjectType>()) { + // Some code tries to take the sizeof an ObjCObjectType, relying that + // the compiler has laid out its representation. Just report Unknown + // for these. + continue; + } } + + APSInt Value = Ex->EvaluateKnownConstInt(getContext()); + CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); + + ProgramStateRef state = (*I)->getState(); + state = state->BindExpr(Ex, (*I)->getLocationContext(), + svalBuilder.makeIntVal(amt.getQuantity(), + Ex->getType())); + Bldr.generateNode(Ex, *I, state); } - - APSInt Value = Ex->EvaluateKnownConstInt(getContext()); - CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); - - ProgramStateRef state = Pred->getState(); - state = state->BindExpr(Ex, Pred->getLocationContext(), - svalBuilder.makeIntVal(amt.getQuantity(), - Ex->getType())); - Bldr.generateNode(Ex, Pred, state); + + getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this); } void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, @@ -919,7 +937,8 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, // Conjure a new symbol if necessary to recover precision. if (Result.isUnknown()){ DefinedOrUnknownSVal SymVal = - svalBuilder.conjureSymbolVal(0, Ex, LCtx, currBldrCtx->blockCount()); + svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, + currBldrCtx->blockCount()); Result = SymVal; // If the value is a location, ++/-- should always preserve |