diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/StaticAnalyzer/Core/ExprEngineC.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 123 |
1 files changed, 67 insertions, 56 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 00b2f4a..3a3c971 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/ExprCXX.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" @@ -66,12 +67,12 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, // TODO: This can be removed after we enable history tracking with // SymSymExpr. unsigned Count = currBldrCtx->blockCount(); - if (isa<Loc>(LeftV) && + if (LeftV.getAs<Loc>() && RHS->getType()->isIntegerType() && RightV.isUnknown()) { RightV = svalBuilder.conjureSymbolVal(RHS, LCtx, RHS->getType(), Count); } - if (isa<Loc>(RightV) && + if (RightV.getAs<Loc>() && LHS->getType()->isIntegerType() && LeftV.isUnknown()) { LeftV = svalBuilder.conjureSymbolVal(LHS, LCtx, LHS->getType(), Count); @@ -305,7 +306,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: - case CK_ObjCObjectLValueCast: { + case CK_ObjCObjectLValueCast: + case CK_ZeroToOCLEvent: { // Delegate to SValBuilder to process. SVal V = state->getSVal(Ex, LCtx); V = svalBuilder.evalCast(V, T, ExTy); @@ -423,15 +425,10 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - - // FIXME: static variables may have an initializer, but the second - // time a function is called those values may not be current. - // This may need to be reflected in the CFG. - // Assumption: The CFG has one DeclStmt per Decl. - const Decl *D = *DS->decl_begin(); - - if (!D || !isa<VarDecl>(D)) { + const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin()); + + if (!VD) { //TODO:AZ: remove explicit insertion after refactoring is done. Dst.insert(Pred); return; @@ -442,31 +439,33 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this); StmtNodeBuilder B(dstPreVisit, Dst, *currBldrCtx); - const VarDecl *VD = dyn_cast<VarDecl>(D); for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); I!=E; ++I) { ExplodedNode *N = *I; ProgramStateRef state = N->getState(); - - // Decls without InitExpr are not initialized explicitly. const LocationContext *LC = N->getLocationContext(); - + + // Decls without InitExpr are not initialized explicitly. if (const Expr *InitEx = VD->getInit()) { + + // Note in the state that the initialization has occurred. + ExplodedNode *UpdatedN = N; SVal InitVal = state->getSVal(InitEx, LC); - if (InitVal == state->getLValue(VD, LC) || - (VD->getType()->isArrayType() && - isa<CXXConstructExpr>(InitEx->IgnoreImplicit()))) { + if (isa<CXXConstructExpr>(InitEx->IgnoreImplicit())) { // We constructed the object directly in the variable. // No need to bind anything. - B.generateNode(DS, N, state); + B.generateNode(DS, UpdatedN, state); } else { // We bound the temp obj region to the CXXConstructExpr. Now recover // the lazy compound value when the variable is not a reference. - if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() && - !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){ - InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion()); - assert(isa<nonloc::LazyCompoundVal>(InitVal)); + if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() && + !VD->getType()->isReferenceType()) { + if (Optional<loc::MemRegionVal> M = + InitVal.getAs<loc::MemRegionVal>()) { + InitVal = state->getSVal(M->getRegion()); + assert(InitVal.getAs<nonloc::LazyCompoundVal>()); + } } // Recover some path-sensitivity if a scalar value evaluated to @@ -480,9 +479,11 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, InitVal = svalBuilder.conjureSymbolVal(0, InitEx, LC, Ty, currBldrCtx->blockCount()); } - B.takeNodes(N); + + + B.takeNodes(UpdatedN); ExplodedNodeSet Dst2; - evalBind(Dst2, DS, N, state->getLValue(VD, LC), InitVal, true); + evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, LC), InitVal, true); B.addNodes(Dst2); } } @@ -501,16 +502,16 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, ProgramStateRef state = Pred->getState(); ExplodedNode *N = Pred; - while (!isa<BlockEntrance>(N->getLocation())) { + while (!N->getLocation().getAs<BlockEntrance>()) { ProgramPoint P = N->getLocation(); - assert(isa<PreStmt>(P)|| isa<PreStmtPurgeDeadSymbols>(P)); + assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>()); (void) P; assert(N->pred_size() == 1); N = *N->pred_begin(); } assert(N->pred_size() == 1); N = *N->pred_begin(); - BlockEdge BE = cast<BlockEdge>(N->getLocation()); + BlockEdge BE = N->getLocation().castAs<BlockEdge>(); SVal X; // Determine the value of the expression by introspecting how we @@ -532,28 +533,32 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, // in SrcBlock is the value of the enclosing expression. // However, we still need to constrain that value to be 0 or 1. assert(!SrcBlock->empty()); - CFGStmt Elem = cast<CFGStmt>(*SrcBlock->rbegin()); + CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>(); const Expr *RHS = cast<Expr>(Elem.getStmt()); SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext()); - DefinedOrUnknownSVal DefinedRHS = cast<DefinedOrUnknownSVal>(RHSVal); - ProgramStateRef StTrue, StFalse; - llvm::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); - if (StTrue) { - if (StFalse) { - // We can't constrain the value to 0 or 1; the best we can do is a cast. - X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType()); + if (RHSVal.isUndef()) { + X = RHSVal; + } else { + DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs<DefinedOrUnknownSVal>(); + ProgramStateRef StTrue, StFalse; + llvm::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); + if (StTrue) { + if (StFalse) { + // We can't constrain the value to 0 or 1. + // The best we can do is a cast. + X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType()); + } else { + // The value is known to be true. + X = getSValBuilder().makeIntVal(1, B->getType()); + } } else { - // The value is known to be true. - X = getSValBuilder().makeIntVal(1, B->getType()); + // The value is known to be false. + assert(StFalse && "Infeasible path!"); + X = getSValBuilder().makeIntVal(0, B->getType()); } - } else { - // The value is known to be false. - assert(StFalse && "Infeasible path!"); - X = getSValBuilder().makeIntVal(0, B->getType()); } } - Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); } @@ -581,8 +586,10 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE, for (InitListExpr::const_reverse_iterator it = IE->rbegin(), ei = IE->rend(); it != ei; ++it) { - vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it), LCtx), - vals); + SVal V = state->getSVal(cast<Expr>(*it), LCtx); + if (dyn_cast_or_null<CXXTempObjectRegion>(V.getAsRegion())) + V = UnknownVal(); + vals = getBasicVals().consVals(V, vals); } B.generateNode(IE, Pred, @@ -615,14 +622,16 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) { ProgramPoint PP = N->getLocation(); - if (isa<PreStmtPurgeDeadSymbols>(PP) || isa<BlockEntrance>(PP)) { + if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) { assert(N->pred_size() == 1); continue; } - SrcBlock = cast<BlockEdge>(&PP)->getSrc(); + SrcBlock = PP.castAs<BlockEdge>().getSrc(); break; } + assert(SrcBlock && "missing function entry"); + // Find the last expression in the predecessor block. That is the // expression that is used for the value of the ternary expression. bool hasValue = false; @@ -631,7 +640,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, for (CFGBlock::const_reverse_iterator I = SrcBlock->rbegin(), E = SrcBlock->rend(); I != E; ++I) { CFGElement CE = *I; - if (CFGStmt *CS = dyn_cast<CFGStmt>(&CE)) { + if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) { const Expr *ValEx = cast<Expr>(CS->getStmt()); hasValue = true; V = state->getSVal(ValEx, LCtx); @@ -785,11 +794,11 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, llvm_unreachable("Invalid Opcode."); case UO_Not: // FIXME: Do we need to handle promotions? - state = state->BindExpr(U, LCtx, evalComplement(cast<NonLoc>(V))); + state = state->BindExpr(U, LCtx, evalComplement(V.castAs<NonLoc>())); break; case UO_Minus: // FIXME: Do we need to handle promotions? - state = state->BindExpr(U, LCtx, evalMinus(cast<NonLoc>(V))); + state = state->BindExpr(U, LCtx, evalMinus(V.castAs<NonLoc>())); break; case UO_LNot: // C99 6.5.3.3: "The expression !E is equivalent to (0==E)." @@ -797,14 +806,16 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, // Note: technically we do "E == 0", but this is the same in the // transfer functions as "0 == E". SVal Result; - if (isa<Loc>(V)) { + if (Optional<Loc> LV = V.getAs<Loc>()) { Loc X = svalBuilder.makeNull(); - Result = evalBinOp(state, BO_EQ, cast<Loc>(V), X, - U->getType()); + Result = evalBinOp(state, BO_EQ, *LV, X, U->getType()); } - else { + else if (Ex->getType()->isFloatingType()) { + // FIXME: handle floating point types. + Result = UnknownVal(); + } else { nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType())); - Result = evalBinOp(state, BO_EQ, cast<NonLoc>(V), X, + Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X, U->getType()); } @@ -846,7 +857,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V2_untested)); continue; } - DefinedSVal V2 = cast<DefinedSVal>(V2_untested); + DefinedSVal V2 = V2_untested.castAs<DefinedSVal>(); // Handle all other values. BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub; |