diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 | 
| commit | 56d91b49b13fe55c918afbda19f6165b5fbff87a (patch) | |
| tree | 9abb1a658a297776086f4e0dfa6ca533de02104e /lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp | |
| parent | 41e20f564abdb05101d6b2b29c59459a966c22cc (diff) | |
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp')
| -rw-r--r-- | lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp | 103 | 
1 files changed, 41 insertions, 62 deletions
diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp index a76a2da001b5..5568f1ca555d 100644 --- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp @@ -13,6 +13,7 @@  //===----------------------------------------------------------------------===//  #include "SimpleConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"  #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"  #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" @@ -71,9 +72,6 @@ ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, Loc cond,  ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,                                                    Loc Cond, bool Assumption) { - -  BasicValueFactory &BasicVals = state->getBasicVals(); -    switch (Cond.getSubKind()) {    default:      assert (false && "'Assume' not implemented for this Loc."); @@ -88,7 +86,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,      while (SubR) {        // FIXME: now we only find the first symbolic region.        if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) { -        const llvm::APSInt &zero = BasicVals.getZeroWithPtrWidth(); +        const llvm::APSInt &zero = getBasicVals().getZeroWithPtrWidth();          if (Assumption)            return assumeSymNE(state, SymR->getSymbol(), zero, zero);          else @@ -134,12 +132,17 @@ static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {  } -ProgramStateRef SimpleConstraintManager::assumeAuxForSymbol( -                                              ProgramStateRef State, -                                              SymbolRef Sym, -                                              bool Assumption) { -  QualType T =  State->getSymbolManager().getType(Sym); -  const llvm::APSInt &zero = State->getBasicVals().getValue(0, T); +ProgramStateRef +SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State, +                                            SymbolRef Sym, bool Assumption) { +  BasicValueFactory &BVF = getBasicVals(); +  QualType T = Sym->getType(BVF.getContext()); + +  // None of the constraint solvers currently support non-integer types. +  if (!T->isIntegerType()) +    return State; + +  const llvm::APSInt &zero = BVF.getValue(0, T);    if (Assumption)      return assumeSymNE(State, Sym, zero, zero);    else @@ -158,8 +161,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,      return assumeAuxForSymbol(state, sym, Assumption);    } -  BasicValueFactory &BasicVals = state->getBasicVals(); -  SymbolManager &SymMgr = state->getSymbolManager(); +  BasicValueFactory &BasicVals = getBasicVals();    switch (Cond.getSubKind()) {    default: @@ -184,7 +186,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,        BinaryOperator::Opcode op = SE->getOpcode();        // Implicitly compare non-comparison expressions to 0.        if (!BinaryOperator::isComparisonOp(op)) { -        QualType T = SymMgr.getType(SE); +        QualType T = SE->getType(BasicVals.getContext());          const llvm::APSInt &zero = BasicVals.getValue(0, T);          op = (Assumption ? BO_NE : BO_EQ);          return assumeSymRel(state, SE, op, zero); @@ -209,33 +211,20 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,    } // end switch  } -static llvm::APSInt computeAdjustment(const SymExpr *LHS, -                                      SymbolRef &Sym) { -  llvm::APSInt DefaultAdjustment; -  DefaultAdjustment = 0; - -  // First check if the LHS is a simple symbol reference. -  if (isa<SymbolData>(LHS)) -    return DefaultAdjustment; - -  // Next, see if it's a "($sym+constant1)" expression. -  const SymIntExpr *SE = dyn_cast<SymIntExpr>(LHS); - -  // We cannot simplify "($sym1+$sym2)". -  if (!SE) -    return DefaultAdjustment; - -  // Get the constant out of the expression "($sym+constant1)" or -  // "<expr>+constant1". -  Sym = SE->getLHS(); -  switch (SE->getOpcode()) { -  case BO_Add: -    return SE->getRHS(); -  case BO_Sub: -    return -SE->getRHS(); -  default: -    // We cannot simplify non-additive operators. -    return DefaultAdjustment; +static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) { +  // Is it a "($sym+constant1)" expression? +  if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) { +    BinaryOperator::Opcode Op = SE->getOpcode(); +    if (Op == BO_Add || Op == BO_Sub) { +      Sym = SE->getLHS(); +      Adjustment = APSIntType(Adjustment).convert(SE->getRHS()); + +      // Don't forget to negate the adjustment if it's being subtracted. +      // This should happen /after/ promotion, in case the value being +      // subtracted is, say, CHAR_MIN, and the promoted type is 'int'. +      if (Op == BO_Sub) +        Adjustment = -Adjustment; +    }    }  } @@ -246,6 +235,12 @@ ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,    assert(BinaryOperator::isComparisonOp(op) &&           "Non-comparison ops should be rewritten as comparisons to zero."); +  BasicValueFactory &BVF = getBasicVals(); +  ASTContext &Ctx = BVF.getContext(); + +  // Get the type used for calculating wraparound. +  APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType(Ctx)); +    // We only handle simple comparisons of the form "$sym == constant"    // or "($sym+constant1) == constant2".    // The adjustment is "constant1" in the above expression. It's used to @@ -254,28 +249,12 @@ ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,    // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to    // the subclasses of SimpleConstraintManager to handle the adjustment.    SymbolRef Sym = LHS; -  llvm::APSInt Adjustment = computeAdjustment(LHS, Sym); - -  // FIXME: This next section is a hack. It silently converts the integers to -  // be of the same type as the symbol, which is not always correct. Really the -  // comparisons should be performed using the Int's type, then mapped back to -  // the symbol's range of values. -  ProgramStateManager &StateMgr = state->getStateManager(); -  ASTContext &Ctx = StateMgr.getContext(); - -  QualType T = Sym->getType(Ctx); -  assert(T->isIntegerType() || Loc::isLocType(T)); -  unsigned bitwidth = Ctx.getTypeSize(T); -  bool isSymUnsigned  -    = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T); - -  // Convert the adjustment. -  Adjustment.setIsUnsigned(isSymUnsigned); -  Adjustment = Adjustment.extOrTrunc(bitwidth); - -  // Convert the right-hand side integer. -  llvm::APSInt ConvertedInt(Int, isSymUnsigned); -  ConvertedInt = ConvertedInt.extOrTrunc(bitwidth); +  llvm::APSInt Adjustment = WraparoundType.getZeroValue(); +  computeAdjustment(Sym, Adjustment); + +  // Convert the right-hand side integer as necessary. +  APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int)); +  llvm::APSInt ConvertedInt = ComparisonType.convert(Int);    switch (op) {    default:  | 
