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/SimpleConstraintManager.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/SimpleConstraintManager.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp | 101 |
1 files changed, 58 insertions, 43 deletions
diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp index 4236ee4..9b759df 100644 --- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp @@ -24,7 +24,7 @@ namespace ento { SimpleConstraintManager::~SimpleConstraintManager() {} bool SimpleConstraintManager::canReasonAbout(SVal X) const { - nonloc::SymbolVal *SymVal = dyn_cast<nonloc::SymbolVal>(&X); + Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>(); if (SymVal && SymVal->isExpression()) { const SymExpr *SE = SymVal->getSymbol(); @@ -49,6 +49,16 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const { } } + if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) { + if (BinaryOperator::isComparisonOp(SSE->getOpcode())) { + // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc. + if (Loc::isLocType(SSE->getLHS()->getType())) { + assert(Loc::isLocType(SSE->getRHS()->getType())); + return true; + } + } + } + return false; } @@ -58,10 +68,9 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const { ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, DefinedSVal Cond, bool Assumption) { - if (isa<NonLoc>(Cond)) - return assume(state, cast<NonLoc>(Cond), Assumption); - else - return assume(state, cast<Loc>(Cond), Assumption); + if (Optional<NonLoc> NV = Cond.getAs<NonLoc>()) + return assume(state, *NV, Assumption); + return assume(state, Cond.castAs<Loc>(), Assumption); } ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, Loc cond, @@ -82,7 +91,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, case loc::MemRegionKind: { // FIXME: Should this go into the storemanager? - const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion(); + const MemRegion *R = Cond.castAs<loc::MemRegionVal>().getRegion(); const SubRegion *SubR = dyn_cast<SubRegion>(R); while (SubR) { @@ -104,7 +113,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, return Assumption ? state : NULL; case loc::ConcreteIntKind: { - bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0; + bool b = Cond.castAs<loc::ConcreteInt>().getValue() != 0; bool isFeasible = b ? Assumption : !Assumption; return isFeasible ? state : NULL; } @@ -120,21 +129,6 @@ ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, return state; } -static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) { - // FIXME: This should probably be part of BinaryOperator, since this isn't - // the only place it's used. (This code was copied from SimpleSValBuilder.cpp.) - switch (op) { - default: - llvm_unreachable("Invalid opcode."); - case BO_LT: return BO_GE; - case BO_GT: return BO_LE; - case BO_LE: return BO_GT; - case BO_GE: return BO_LT; - case BO_EQ: return BO_NE; - case BO_NE: return BO_EQ; - } -} - ProgramStateRef SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State, @@ -165,14 +159,12 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, return assumeAuxForSymbol(state, sym, Assumption); } - BasicValueFactory &BasicVals = getBasicVals(); - switch (Cond.getSubKind()) { default: llvm_unreachable("'Assume' not implemented for this NonLoc"); case nonloc::SymbolValKind: { - nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond); + nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>(); SymbolRef sym = SV.getSymbol(); assert(sym); @@ -181,36 +173,55 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, return assumeAuxForSymbol(state, sym, Assumption); // Handle symbolic expression. - } else { + } else if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym)) { // We can only simplify expressions whose RHS is an integer. - const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym); - if (!SE) - return assumeAuxForSymbol(state, sym, Assumption); BinaryOperator::Opcode op = SE->getOpcode(); - // Implicitly compare non-comparison expressions to 0. - if (!BinaryOperator::isComparisonOp(op)) { - QualType T = SE->getType(); - const llvm::APSInt &zero = BasicVals.getValue(0, T); - op = (Assumption ? BO_NE : BO_EQ); - return assumeSymRel(state, SE, op, zero); + if (BinaryOperator::isComparisonOp(op)) { + if (!Assumption) + op = BinaryOperator::negateComparisonOp(op); + + return assumeSymRel(state, SE->getLHS(), op, SE->getRHS()); } - // From here on out, op is the real comparison we'll be testing. - if (!Assumption) - op = NegateComparison(op); - return assumeSymRel(state, SE->getLHS(), op, SE->getRHS()); + } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(sym)) { + // Translate "a != b" to "(b - a) != 0". + // We invert the order of the operands as a heuristic for how loop + // conditions are usually written ("begin != end") as compared to length + // calculations ("end - begin"). The more correct thing to do would be to + // canonicalize "a - b" and "b - a", which would allow us to treat + // "a != b" and "b != a" the same. + SymbolManager &SymMgr = getSymbolManager(); + BinaryOperator::Opcode Op = SSE->getOpcode(); + assert(BinaryOperator::isComparisonOp(Op)); + + // For now, we only support comparing pointers. + assert(Loc::isLocType(SSE->getLHS()->getType())); + assert(Loc::isLocType(SSE->getRHS()->getType())); + QualType DiffTy = SymMgr.getContext().getPointerDiffType(); + SymbolRef Subtraction = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, + SSE->getLHS(), DiffTy); + + const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy); + Op = BinaryOperator::reverseComparisonOp(Op); + if (!Assumption) + Op = BinaryOperator::negateComparisonOp(Op); + return assumeSymRel(state, Subtraction, Op, Zero); } + + // If we get here, there's nothing else we can do but treat the symbol as + // opaque. + return assumeAuxForSymbol(state, sym, Assumption); } case nonloc::ConcreteIntKind: { - bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0; + bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0; bool isFeasible = b ? Assumption : !Assumption; return isFeasible ? state : NULL; } case nonloc::LocAsIntegerKind: - return assumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(), + return assumeAux(state, Cond.castAs<nonloc::LocAsInteger>().getLoc(), Assumption); } // end switch } @@ -258,10 +269,14 @@ ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state, APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int)); llvm::APSInt ConvertedInt = ComparisonType.convert(Int); + // Prefer unsigned comparisons. + if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() && + ComparisonType.isUnsigned() && !WraparoundType.isUnsigned()) + Adjustment.setIsSigned(false); + switch (op) { default: - // No logic yet for other operators. assume the constraint is feasible. - return state; + llvm_unreachable("invalid operation not caught by assertion above"); case BO_EQ: return assumeSymEQ(state, Sym, ConvertedInt, Adjustment); |