SimpleConstraintManager.cpp revision 1eb4433ac451dc16f4133a88af2d002ac26c58ef
1//== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines SimpleConstraintManager, a class that holds code shared 11// between BasicConstraintManager and RangeConstraintManager. 12// 13//===----------------------------------------------------------------------===// 14 15#include "SimpleConstraintManager.h" 16#include "clang/Analysis/PathSensitive/GRExprEngine.h" 17#include "clang/Analysis/PathSensitive/GRState.h" 18 19namespace clang { 20 21SimpleConstraintManager::~SimpleConstraintManager() {} 22 23bool SimpleConstraintManager::canReasonAbout(SVal X) const { 24 if (nonloc::SymExprVal *SymVal = dyn_cast<nonloc::SymExprVal>(&X)) { 25 const SymExpr *SE = SymVal->getSymbolicExpression(); 26 27 if (isa<SymbolData>(SE)) 28 return true; 29 30 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) { 31 switch (SIE->getOpcode()) { 32 // We don't reason yet about bitwise-constraints on symbolic values. 33 case BinaryOperator::And: 34 case BinaryOperator::Or: 35 case BinaryOperator::Xor: 36 return false; 37 // We don't reason yet about arithmetic constraints on symbolic values. 38 case BinaryOperator::Mul: 39 case BinaryOperator::Div: 40 case BinaryOperator::Rem: 41 case BinaryOperator::Add: 42 case BinaryOperator::Sub: 43 case BinaryOperator::Shl: 44 case BinaryOperator::Shr: 45 return false; 46 // All other cases. 47 default: 48 return true; 49 } 50 } 51 52 return false; 53 } 54 55 return true; 56} 57 58const GRState *SimpleConstraintManager::Assume(const GRState *state, 59 SVal Cond, bool Assumption) { 60 if (Cond.isUnknown()) { 61 return state; 62 } 63 64 if (isa<NonLoc>(Cond)) 65 return Assume(state, cast<NonLoc>(Cond), Assumption); 66 else 67 return Assume(state, cast<Loc>(Cond), Assumption); 68} 69 70const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond, 71 bool Assumption) { 72 73 state = AssumeAux(state, Cond, Assumption); 74 75 // EvalAssume is used to call into the GRTransferFunction object to perform 76 // any checker-specific update of the state based on this assumption being 77 // true or false. 78 return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption) 79 : NULL; 80} 81 82const GRState *SimpleConstraintManager::AssumeAux(const GRState *state, 83 Loc Cond, bool Assumption) { 84 85 BasicValueFactory &BasicVals = state->getBasicVals(); 86 87 switch (Cond.getSubKind()) { 88 default: 89 assert (false && "'Assume' not implemented for this Loc."); 90 return state; 91 92 case loc::MemRegionKind: { 93 // FIXME: Should this go into the storemanager? 94 95 const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion(); 96 const SubRegion *SubR = dyn_cast<SubRegion>(R); 97 98 while (SubR) { 99 // FIXME: now we only find the first symbolic region. 100 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) { 101 if (Assumption) 102 return AssumeSymNE(state, SymR->getSymbol(), 103 BasicVals.getZeroWithPtrWidth()); 104 else 105 return AssumeSymEQ(state, SymR->getSymbol(), 106 BasicVals.getZeroWithPtrWidth()); 107 } 108 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion()); 109 } 110 111 // FALL-THROUGH. 112 } 113 114 case loc::GotoLabelKind: 115 return Assumption ? state : NULL; 116 117 case loc::ConcreteIntKind: { 118 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0; 119 bool isFeasible = b ? Assumption : !Assumption; 120 return isFeasible ? state : NULL; 121 } 122 } // end switch 123} 124 125const GRState *SimpleConstraintManager::Assume(const GRState *state, 126 NonLoc Cond, 127 bool Assumption) { 128 129 state = AssumeAux(state, Cond, Assumption); 130 131 // EvalAssume is used to call into the GRTransferFunction object to perform 132 // any checker-specific update of the state based on this assumption being 133 // true or false. 134 return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption) 135 : NULL; 136} 137 138const GRState *SimpleConstraintManager::AssumeAux(const GRState *state, 139 NonLoc Cond, 140 bool Assumption) { 141 142 // We cannot reason about SymIntExpr and SymSymExpr. 143 if (!canReasonAbout(Cond)) { 144 // Just return the current state indicating that the path is feasible. 145 // This may be an over-approximation of what is possible. 146 return state; 147 } 148 149 BasicValueFactory &BasicVals = state->getBasicVals(); 150 SymbolManager &SymMgr = state->getSymbolManager(); 151 152 switch (Cond.getSubKind()) { 153 default: 154 assert(false && "'Assume' not implemented for this NonLoc"); 155 156 case nonloc::SymbolValKind: { 157 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond); 158 SymbolRef sym = SV.getSymbol(); 159 QualType T = SymMgr.getType(sym); 160 const llvm::APSInt &zero = BasicVals.getValue(0, T); 161 162 return Assumption ? AssumeSymNE(state, sym, zero) 163 : AssumeSymEQ(state, sym, zero); 164 } 165 166 case nonloc::SymExprValKind: { 167 nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond); 168 if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression())) 169 return AssumeSymInt(state, Assumption, SE); 170 171 // For all other symbolic expressions, over-approximate and consider 172 // the constraint feasible. 173 return state; 174 } 175 176 case nonloc::ConcreteIntKind: { 177 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0; 178 bool isFeasible = b ? Assumption : !Assumption; 179 return isFeasible ? state : NULL; 180 } 181 182 case nonloc::LocAsIntegerKind: 183 return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(), 184 Assumption); 185 } // end switch 186} 187 188const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state, 189 bool Assumption, 190 const SymIntExpr *SE) { 191 192 193 // Here we assume that LHS is a symbol. This is consistent with the 194 // rest of the constraint manager logic. 195 SymbolRef Sym = cast<SymbolData>(SE->getLHS()); 196 const llvm::APSInt &Int = SE->getRHS(); 197 198 switch (SE->getOpcode()) { 199 default: 200 // No logic yet for other operators. Assume the constraint is feasible. 201 return state; 202 203 case BinaryOperator::EQ: 204 return Assumption ? AssumeSymEQ(state, Sym, Int) 205 : AssumeSymNE(state, Sym, Int); 206 207 case BinaryOperator::NE: 208 return Assumption ? AssumeSymNE(state, Sym, Int) 209 : AssumeSymEQ(state, Sym, Int); 210 case BinaryOperator::GT: 211 return Assumption ? AssumeSymGT(state, Sym, Int) 212 : AssumeSymLE(state, Sym, Int); 213 214 case BinaryOperator::GE: 215 return Assumption ? AssumeSymGE(state, Sym, Int) 216 : AssumeSymLT(state, Sym, Int); 217 218 case BinaryOperator::LT: 219 return Assumption ? AssumeSymLT(state, Sym, Int) 220 : AssumeSymGE(state, Sym, Int); 221 222 case BinaryOperator::LE: 223 return Assumption ? AssumeSymLE(state, Sym, Int) 224 : AssumeSymGT(state, Sym, Int); 225 } // end switch 226} 227 228const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state, 229 SVal Idx, 230 SVal UpperBound, 231 bool Assumption) { 232 233 // Only support ConcreteInt for now. 234 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))) 235 return state; 236 237 const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false); 238 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue(); 239 // IdxV might be too narrow. 240 if (IdxV.getBitWidth() < Zero.getBitWidth()) 241 IdxV.extend(Zero.getBitWidth()); 242 // UBV might be too narrow, too. 243 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue(); 244 if (UBV.getBitWidth() < Zero.getBitWidth()) 245 UBV.extend(Zero.getBitWidth()); 246 247 bool InBound = (Zero <= IdxV) && (IdxV < UBV); 248 bool isFeasible = Assumption ? InBound : !InBound; 249 return isFeasible ? state : NULL; 250} 251 252} // end of namespace clang 253