SimpleConstraintManager.cpp revision 234353
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/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 17#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 18 19namespace clang { 20 21namespace ento { 22 23SimpleConstraintManager::~SimpleConstraintManager() {} 24 25bool SimpleConstraintManager::canReasonAbout(SVal X) const { 26 nonloc::SymbolVal *SymVal = dyn_cast<nonloc::SymbolVal>(&X); 27 if (SymVal && SymVal->isExpression()) { 28 const SymExpr *SE = SymVal->getSymbol(); 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 BO_And: 34 case BO_Or: 35 case BO_Xor: 36 return false; 37 // We don't reason yet about these arithmetic constraints on 38 // symbolic values. 39 case BO_Mul: 40 case BO_Div: 41 case BO_Rem: 42 case BO_Shl: 43 case BO_Shr: 44 return false; 45 // All other cases. 46 default: 47 return true; 48 } 49 } 50 51 return false; 52 } 53 54 return true; 55} 56 57ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, 58 DefinedSVal Cond, 59 bool Assumption) { 60 if (isa<NonLoc>(Cond)) 61 return assume(state, cast<NonLoc>(Cond), Assumption); 62 else 63 return assume(state, cast<Loc>(Cond), Assumption); 64} 65 66ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, Loc cond, 67 bool assumption) { 68 state = assumeAux(state, cond, assumption); 69 return SU.processAssume(state, cond, assumption); 70} 71 72ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, 73 Loc Cond, bool Assumption) { 74 75 BasicValueFactory &BasicVals = state->getBasicVals(); 76 77 switch (Cond.getSubKind()) { 78 default: 79 assert (false && "'Assume' not implemented for this Loc."); 80 return state; 81 82 case loc::MemRegionKind: { 83 // FIXME: Should this go into the storemanager? 84 85 const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion(); 86 const SubRegion *SubR = dyn_cast<SubRegion>(R); 87 88 while (SubR) { 89 // FIXME: now we only find the first symbolic region. 90 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) { 91 const llvm::APSInt &zero = BasicVals.getZeroWithPtrWidth(); 92 if (Assumption) 93 return assumeSymNE(state, SymR->getSymbol(), zero, zero); 94 else 95 return assumeSymEQ(state, SymR->getSymbol(), zero, zero); 96 } 97 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion()); 98 } 99 100 // FALL-THROUGH. 101 } 102 103 case loc::GotoLabelKind: 104 return Assumption ? state : NULL; 105 106 case loc::ConcreteIntKind: { 107 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0; 108 bool isFeasible = b ? Assumption : !Assumption; 109 return isFeasible ? state : NULL; 110 } 111 } // end switch 112} 113 114ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, 115 NonLoc cond, 116 bool assumption) { 117 state = assumeAux(state, cond, assumption); 118 return SU.processAssume(state, cond, assumption); 119} 120 121static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) { 122 // FIXME: This should probably be part of BinaryOperator, since this isn't 123 // the only place it's used. (This code was copied from SimpleSValBuilder.cpp.) 124 switch (op) { 125 default: 126 llvm_unreachable("Invalid opcode."); 127 case BO_LT: return BO_GE; 128 case BO_GT: return BO_LE; 129 case BO_LE: return BO_GT; 130 case BO_GE: return BO_LT; 131 case BO_EQ: return BO_NE; 132 case BO_NE: return BO_EQ; 133 } 134} 135 136 137ProgramStateRef SimpleConstraintManager::assumeAuxForSymbol( 138 ProgramStateRef State, 139 SymbolRef Sym, 140 bool Assumption) { 141 QualType T = State->getSymbolManager().getType(Sym); 142 const llvm::APSInt &zero = State->getBasicVals().getValue(0, T); 143 if (Assumption) 144 return assumeSymNE(State, Sym, zero, zero); 145 else 146 return assumeSymEQ(State, Sym, zero, zero); 147} 148 149ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, 150 NonLoc Cond, 151 bool Assumption) { 152 153 // We cannot reason about SymSymExprs, and can only reason about some 154 // SymIntExprs. 155 if (!canReasonAbout(Cond)) { 156 // Just add the constraint to the expression without trying to simplify. 157 SymbolRef sym = Cond.getAsSymExpr(); 158 return assumeAuxForSymbol(state, sym, Assumption); 159 } 160 161 BasicValueFactory &BasicVals = state->getBasicVals(); 162 SymbolManager &SymMgr = state->getSymbolManager(); 163 164 switch (Cond.getSubKind()) { 165 default: 166 llvm_unreachable("'Assume' not implemented for this NonLoc"); 167 168 case nonloc::SymbolValKind: { 169 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond); 170 SymbolRef sym = SV.getSymbol(); 171 assert(sym); 172 173 // Handle SymbolData. 174 if (!SV.isExpression()) { 175 return assumeAuxForSymbol(state, sym, Assumption); 176 177 // Handle symbolic expression. 178 } else { 179 // We can only simplify expressions whose RHS is an integer. 180 const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym); 181 if (!SE) 182 return assumeAuxForSymbol(state, sym, Assumption); 183 184 BinaryOperator::Opcode op = SE->getOpcode(); 185 // Implicitly compare non-comparison expressions to 0. 186 if (!BinaryOperator::isComparisonOp(op)) { 187 QualType T = SymMgr.getType(SE); 188 const llvm::APSInt &zero = BasicVals.getValue(0, T); 189 op = (Assumption ? BO_NE : BO_EQ); 190 return assumeSymRel(state, SE, op, zero); 191 } 192 // From here on out, op is the real comparison we'll be testing. 193 if (!Assumption) 194 op = NegateComparison(op); 195 196 return assumeSymRel(state, SE->getLHS(), op, SE->getRHS()); 197 } 198 } 199 200 case nonloc::ConcreteIntKind: { 201 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0; 202 bool isFeasible = b ? Assumption : !Assumption; 203 return isFeasible ? state : NULL; 204 } 205 206 case nonloc::LocAsIntegerKind: 207 return assumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(), 208 Assumption); 209 } // end switch 210} 211 212static llvm::APSInt computeAdjustment(const SymExpr *LHS, 213 SymbolRef &Sym) { 214 llvm::APSInt DefaultAdjustment; 215 DefaultAdjustment = 0; 216 217 // First check if the LHS is a simple symbol reference. 218 if (isa<SymbolData>(LHS)) 219 return DefaultAdjustment; 220 221 // Next, see if it's a "($sym+constant1)" expression. 222 const SymIntExpr *SE = dyn_cast<SymIntExpr>(LHS); 223 224 // We cannot simplify "($sym1+$sym2)". 225 if (!SE) 226 return DefaultAdjustment; 227 228 // Get the constant out of the expression "($sym+constant1)" or 229 // "<expr>+constant1". 230 Sym = SE->getLHS(); 231 switch (SE->getOpcode()) { 232 case BO_Add: 233 return SE->getRHS(); 234 case BO_Sub: 235 return -SE->getRHS(); 236 default: 237 // We cannot simplify non-additive operators. 238 return DefaultAdjustment; 239 } 240} 241 242ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state, 243 const SymExpr *LHS, 244 BinaryOperator::Opcode op, 245 const llvm::APSInt& Int) { 246 assert(BinaryOperator::isComparisonOp(op) && 247 "Non-comparison ops should be rewritten as comparisons to zero."); 248 249 // We only handle simple comparisons of the form "$sym == constant" 250 // or "($sym+constant1) == constant2". 251 // The adjustment is "constant1" in the above expression. It's used to 252 // "slide" the solution range around for modular arithmetic. For example, 253 // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which 254 // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to 255 // the subclasses of SimpleConstraintManager to handle the adjustment. 256 SymbolRef Sym = LHS; 257 llvm::APSInt Adjustment = computeAdjustment(LHS, Sym); 258 259 // FIXME: This next section is a hack. It silently converts the integers to 260 // be of the same type as the symbol, which is not always correct. Really the 261 // comparisons should be performed using the Int's type, then mapped back to 262 // the symbol's range of values. 263 ProgramStateManager &StateMgr = state->getStateManager(); 264 ASTContext &Ctx = StateMgr.getContext(); 265 266 QualType T = Sym->getType(Ctx); 267 assert(T->isIntegerType() || Loc::isLocType(T)); 268 unsigned bitwidth = Ctx.getTypeSize(T); 269 bool isSymUnsigned 270 = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T); 271 272 // Convert the adjustment. 273 Adjustment.setIsUnsigned(isSymUnsigned); 274 Adjustment = Adjustment.extOrTrunc(bitwidth); 275 276 // Convert the right-hand side integer. 277 llvm::APSInt ConvertedInt(Int, isSymUnsigned); 278 ConvertedInt = ConvertedInt.extOrTrunc(bitwidth); 279 280 switch (op) { 281 default: 282 // No logic yet for other operators. assume the constraint is feasible. 283 return state; 284 285 case BO_EQ: 286 return assumeSymEQ(state, Sym, ConvertedInt, Adjustment); 287 288 case BO_NE: 289 return assumeSymNE(state, Sym, ConvertedInt, Adjustment); 290 291 case BO_GT: 292 return assumeSymGT(state, Sym, ConvertedInt, Adjustment); 293 294 case BO_GE: 295 return assumeSymGE(state, Sym, ConvertedInt, Adjustment); 296 297 case BO_LT: 298 return assumeSymLT(state, Sym, ConvertedInt, Adjustment); 299 300 case BO_LE: 301 return assumeSymLE(state, Sym, ConvertedInt, Adjustment); 302 } // end switch 303} 304 305} // end of namespace ento 306 307} // end of namespace clang 308