clang API Documentation
00001 //== BasicConstraintManager.cpp - Manage basic constraints.------*- C++ -*--==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines BasicConstraintManager, a class that tracks simple 00011 // equality and inequality constraints on symbolic values of ProgramState. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "SimpleConstraintManager.h" 00016 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" 00017 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 00018 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 00019 #include "llvm/Support/raw_ostream.h" 00020 00021 using namespace clang; 00022 using namespace ento; 00023 00024 00025 namespace { class ConstNotEq {}; } 00026 namespace { class ConstEq {}; } 00027 00028 typedef llvm::ImmutableMap<SymbolRef,ProgramState::IntSetTy> ConstNotEqTy; 00029 typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy; 00030 00031 static int ConstEqIndex = 0; 00032 static int ConstNotEqIndex = 0; 00033 00034 namespace clang { 00035 namespace ento { 00036 template<> 00037 struct ProgramStateTrait<ConstNotEq> : 00038 public ProgramStatePartialTrait<ConstNotEqTy> { 00039 static inline void *GDMIndex() { return &ConstNotEqIndex; } 00040 }; 00041 00042 template<> 00043 struct ProgramStateTrait<ConstEq> : public ProgramStatePartialTrait<ConstEqTy> { 00044 static inline void *GDMIndex() { return &ConstEqIndex; } 00045 }; 00046 } 00047 } 00048 00049 namespace { 00050 // BasicConstraintManager only tracks equality and inequality constraints of 00051 // constants and integer variables. 00052 class BasicConstraintManager 00053 : public SimpleConstraintManager { 00054 ProgramState::IntSetTy::Factory ISetFactory; 00055 public: 00056 BasicConstraintManager(ProgramStateManager &statemgr, SubEngine &subengine) 00057 : SimpleConstraintManager(subengine, statemgr.getBasicVals()), 00058 ISetFactory(statemgr.getAllocator()) {} 00059 00060 ProgramStateRef assumeSymEquality(ProgramStateRef State, SymbolRef Sym, 00061 const llvm::APSInt &V, 00062 const llvm::APSInt &Adjustment, 00063 bool Assumption); 00064 00065 ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym, 00066 const llvm::APSInt &V, 00067 const llvm::APSInt &Adjustment) { 00068 return assumeSymEquality(State, Sym, V, Adjustment, false); 00069 } 00070 00071 ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym, 00072 const llvm::APSInt &V, 00073 const llvm::APSInt &Adjustment) { 00074 return assumeSymEquality(State, Sym, V, Adjustment, true); 00075 } 00076 00077 ProgramStateRef assumeSymLT(ProgramStateRef state, 00078 SymbolRef sym, 00079 const llvm::APSInt& V, 00080 const llvm::APSInt& Adjustment); 00081 00082 ProgramStateRef assumeSymGT(ProgramStateRef state, 00083 SymbolRef sym, 00084 const llvm::APSInt& V, 00085 const llvm::APSInt& Adjustment); 00086 00087 ProgramStateRef assumeSymGE(ProgramStateRef state, 00088 SymbolRef sym, 00089 const llvm::APSInt& V, 00090 const llvm::APSInt& Adjustment); 00091 00092 ProgramStateRef assumeSymLE(ProgramStateRef state, 00093 SymbolRef sym, 00094 const llvm::APSInt& V, 00095 const llvm::APSInt& Adjustment); 00096 00097 ProgramStateRef AddEQ(ProgramStateRef state, 00098 SymbolRef sym, 00099 const llvm::APSInt& V); 00100 00101 ProgramStateRef AddNE(ProgramStateRef state, 00102 SymbolRef sym, 00103 const llvm::APSInt& V); 00104 00105 const llvm::APSInt* getSymVal(ProgramStateRef state, 00106 SymbolRef sym) const; 00107 00108 bool isNotEqual(ProgramStateRef state, 00109 SymbolRef sym, 00110 const llvm::APSInt& V) const; 00111 00112 bool isEqual(ProgramStateRef state, 00113 SymbolRef sym, 00114 const llvm::APSInt& V) const; 00115 00116 ProgramStateRef removeDeadBindings(ProgramStateRef state, 00117 SymbolReaper& SymReaper); 00118 00119 bool performTest(llvm::APSInt SymVal, llvm::APSInt Adjustment, 00120 BinaryOperator::Opcode Op, llvm::APSInt ComparisonVal); 00121 00122 void print(ProgramStateRef state, 00123 raw_ostream &Out, 00124 const char* nl, 00125 const char *sep); 00126 }; 00127 00128 } // end anonymous namespace 00129 00130 ConstraintManager* 00131 ento::CreateBasicConstraintManager(ProgramStateManager& statemgr, 00132 SubEngine &subengine) { 00133 return new BasicConstraintManager(statemgr, subengine); 00134 } 00135 00136 // FIXME: This is a more general utility and should live somewhere else. 00137 bool BasicConstraintManager::performTest(llvm::APSInt SymVal, 00138 llvm::APSInt Adjustment, 00139 BinaryOperator::Opcode Op, 00140 llvm::APSInt ComparisonVal) { 00141 APSIntType Type(Adjustment); 00142 Type.apply(SymVal); 00143 Type.apply(ComparisonVal); 00144 SymVal += Adjustment; 00145 00146 assert(BinaryOperator::isComparisonOp(Op)); 00147 BasicValueFactory &BVF = getBasicVals(); 00148 const llvm::APSInt *Result = BVF.evalAPSInt(Op, SymVal, ComparisonVal); 00149 assert(Result && "Comparisons should always have valid results."); 00150 00151 return Result->getBoolValue(); 00152 } 00153 00154 ProgramStateRef 00155 BasicConstraintManager::assumeSymEquality(ProgramStateRef State, SymbolRef Sym, 00156 const llvm::APSInt &V, 00157 const llvm::APSInt &Adjustment, 00158 bool Assumption) { 00159 // Before we do any real work, see if the value can even show up. 00160 APSIntType AdjustmentType(Adjustment); 00161 if (AdjustmentType.testInRange(V) != APSIntType::RTR_Within) 00162 return Assumption ? NULL : State; 00163 00164 // Get the symbol type. 00165 BasicValueFactory &BVF = getBasicVals(); 00166 ASTContext &Ctx = BVF.getContext(); 00167 APSIntType SymbolType = BVF.getAPSIntType(Sym->getType(Ctx)); 00168 00169 // First, see if the adjusted value is within range for the symbol. 00170 llvm::APSInt Adjusted = AdjustmentType.convert(V) - Adjustment; 00171 if (SymbolType.testInRange(Adjusted) != APSIntType::RTR_Within) 00172 return Assumption ? NULL : State; 00173 00174 // Now we can do things properly in the symbol space. 00175 SymbolType.apply(Adjusted); 00176 00177 // Second, determine if sym == X, where X+Adjustment != V. 00178 if (const llvm::APSInt *X = getSymVal(State, Sym)) { 00179 bool IsFeasible = (*X == Adjusted); 00180 return (IsFeasible == Assumption) ? State : NULL; 00181 } 00182 00183 // Third, determine if we already know sym+Adjustment != V. 00184 if (isNotEqual(State, Sym, Adjusted)) 00185 return Assumption ? NULL : State; 00186 00187 // If we reach here, sym is not a constant and we don't know if it is != V. 00188 // Make the correct assumption. 00189 if (Assumption) 00190 return AddEQ(State, Sym, Adjusted); 00191 else 00192 return AddNE(State, Sym, Adjusted); 00193 } 00194 00195 // The logic for these will be handled in another ConstraintManager. 00196 // Approximate it here anyway by handling some edge cases. 00197 ProgramStateRef 00198 BasicConstraintManager::assumeSymLT(ProgramStateRef state, 00199 SymbolRef sym, 00200 const llvm::APSInt &V, 00201 const llvm::APSInt &Adjustment) { 00202 APSIntType ComparisonType(V), AdjustmentType(Adjustment); 00203 00204 // Is 'V' out of range above the type? 00205 llvm::APSInt Max = AdjustmentType.getMaxValue(); 00206 if (V > ComparisonType.convert(Max)) { 00207 // This path is trivially feasible. 00208 return state; 00209 } 00210 00211 // Is 'V' the smallest possible value, or out of range below the type? 00212 llvm::APSInt Min = AdjustmentType.getMinValue(); 00213 if (V <= ComparisonType.convert(Min)) { 00214 // sym cannot be any value less than 'V'. This path is infeasible. 00215 return NULL; 00216 } 00217 00218 // Reject a path if the value of sym is a constant X and !(X+Adj < V). 00219 if (const llvm::APSInt *X = getSymVal(state, sym)) { 00220 bool isFeasible = performTest(*X, Adjustment, BO_LT, V); 00221 return isFeasible ? state : NULL; 00222 } 00223 00224 // FIXME: For now have assuming x < y be the same as assuming sym != V; 00225 return assumeSymNE(state, sym, V, Adjustment); 00226 } 00227 00228 ProgramStateRef 00229 BasicConstraintManager::assumeSymGT(ProgramStateRef state, 00230 SymbolRef sym, 00231 const llvm::APSInt &V, 00232 const llvm::APSInt &Adjustment) { 00233 APSIntType ComparisonType(V), AdjustmentType(Adjustment); 00234 00235 // Is 'V' the largest possible value, or out of range above the type? 00236 llvm::APSInt Max = AdjustmentType.getMaxValue(); 00237 if (V >= ComparisonType.convert(Max)) { 00238 // sym cannot be any value greater than 'V'. This path is infeasible. 00239 return NULL; 00240 } 00241 00242 // Is 'V' out of range below the type? 00243 llvm::APSInt Min = AdjustmentType.getMinValue(); 00244 if (V < ComparisonType.convert(Min)) { 00245 // This path is trivially feasible. 00246 return state; 00247 } 00248 00249 // Reject a path if the value of sym is a constant X and !(X+Adj > V). 00250 if (const llvm::APSInt *X = getSymVal(state, sym)) { 00251 bool isFeasible = performTest(*X, Adjustment, BO_GT, V); 00252 return isFeasible ? state : NULL; 00253 } 00254 00255 // FIXME: For now have assuming x > y be the same as assuming sym != V; 00256 return assumeSymNE(state, sym, V, Adjustment); 00257 } 00258 00259 ProgramStateRef 00260 BasicConstraintManager::assumeSymGE(ProgramStateRef state, 00261 SymbolRef sym, 00262 const llvm::APSInt &V, 00263 const llvm::APSInt &Adjustment) { 00264 APSIntType ComparisonType(V), AdjustmentType(Adjustment); 00265 00266 // Is 'V' the largest possible value, or out of range above the type? 00267 llvm::APSInt Max = AdjustmentType.getMaxValue(); 00268 ComparisonType.apply(Max); 00269 00270 if (V > Max) { 00271 // sym cannot be any value greater than 'V'. This path is infeasible. 00272 return NULL; 00273 } else if (V == Max) { 00274 // If the path is feasible then as a consequence we know that 00275 // 'sym+Adjustment == V' because there are no larger values. 00276 // Add this constraint. 00277 return assumeSymEQ(state, sym, V, Adjustment); 00278 } 00279 00280 // Is 'V' out of range below the type? 00281 llvm::APSInt Min = AdjustmentType.getMinValue(); 00282 if (V < ComparisonType.convert(Min)) { 00283 // This path is trivially feasible. 00284 return state; 00285 } 00286 00287 // Reject a path if the value of sym is a constant X and !(X+Adj >= V). 00288 if (const llvm::APSInt *X = getSymVal(state, sym)) { 00289 bool isFeasible = performTest(*X, Adjustment, BO_GE, V); 00290 return isFeasible ? state : NULL; 00291 } 00292 00293 return state; 00294 } 00295 00296 ProgramStateRef 00297 BasicConstraintManager::assumeSymLE(ProgramStateRef state, 00298 SymbolRef sym, 00299 const llvm::APSInt &V, 00300 const llvm::APSInt &Adjustment) { 00301 APSIntType ComparisonType(V), AdjustmentType(Adjustment); 00302 00303 // Is 'V' out of range above the type? 00304 llvm::APSInt Max = AdjustmentType.getMaxValue(); 00305 if (V > ComparisonType.convert(Max)) { 00306 // This path is trivially feasible. 00307 return state; 00308 } 00309 00310 // Is 'V' the smallest possible value, or out of range below the type? 00311 llvm::APSInt Min = AdjustmentType.getMinValue(); 00312 ComparisonType.apply(Min); 00313 00314 if (V < Min) { 00315 // sym cannot be any value less than 'V'. This path is infeasible. 00316 return NULL; 00317 } else if (V == Min) { 00318 // If the path is feasible then as a consequence we know that 00319 // 'sym+Adjustment == V' because there are no smaller values. 00320 // Add this constraint. 00321 return assumeSymEQ(state, sym, V, Adjustment); 00322 } 00323 00324 // Reject a path if the value of sym is a constant X and !(X+Adj >= V). 00325 if (const llvm::APSInt *X = getSymVal(state, sym)) { 00326 bool isFeasible = performTest(*X, Adjustment, BO_LE, V); 00327 return isFeasible ? state : NULL; 00328 } 00329 00330 return state; 00331 } 00332 00333 ProgramStateRef BasicConstraintManager::AddEQ(ProgramStateRef state, 00334 SymbolRef sym, 00335 const llvm::APSInt& V) { 00336 // Now that we have an actual value, we can throw out the NE-set. 00337 // Create a new state with the old bindings replaced. 00338 state = state->remove<ConstNotEq>(sym); 00339 return state->set<ConstEq>(sym, &getBasicVals().getValue(V)); 00340 } 00341 00342 ProgramStateRef BasicConstraintManager::AddNE(ProgramStateRef state, 00343 SymbolRef sym, 00344 const llvm::APSInt& V) { 00345 00346 // First, retrieve the NE-set associated with the given symbol. 00347 ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym); 00348 ProgramState::IntSetTy S = T ? *T : ISetFactory.getEmptySet(); 00349 00350 // Now add V to the NE set. 00351 S = ISetFactory.add(S, &getBasicVals().getValue(V)); 00352 00353 // Create a new state with the old binding replaced. 00354 return state->set<ConstNotEq>(sym, S); 00355 } 00356 00357 const llvm::APSInt* BasicConstraintManager::getSymVal(ProgramStateRef state, 00358 SymbolRef sym) const { 00359 const ConstEqTy::data_type* T = state->get<ConstEq>(sym); 00360 return T ? *T : NULL; 00361 } 00362 00363 bool BasicConstraintManager::isNotEqual(ProgramStateRef state, 00364 SymbolRef sym, 00365 const llvm::APSInt& V) const { 00366 00367 // Retrieve the NE-set associated with the given symbol. 00368 const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym); 00369 00370 // See if V is present in the NE-set. 00371 return T ? T->contains(&getBasicVals().getValue(V)) : false; 00372 } 00373 00374 bool BasicConstraintManager::isEqual(ProgramStateRef state, 00375 SymbolRef sym, 00376 const llvm::APSInt& V) const { 00377 // Retrieve the EQ-set associated with the given symbol. 00378 const ConstEqTy::data_type* T = state->get<ConstEq>(sym); 00379 // See if V is present in the EQ-set. 00380 return T ? **T == V : false; 00381 } 00382 00383 /// Scan all symbols referenced by the constraints. If the symbol is not alive 00384 /// as marked in LSymbols, mark it as dead in DSymbols. 00385 ProgramStateRef 00386 BasicConstraintManager::removeDeadBindings(ProgramStateRef state, 00387 SymbolReaper& SymReaper) { 00388 00389 ConstEqTy CE = state->get<ConstEq>(); 00390 ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>(); 00391 00392 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) { 00393 SymbolRef sym = I.getKey(); 00394 if (SymReaper.maybeDead(sym)) 00395 CE = CEFactory.remove(CE, sym); 00396 } 00397 state = state->set<ConstEq>(CE); 00398 00399 ConstNotEqTy CNE = state->get<ConstNotEq>(); 00400 ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>(); 00401 00402 for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) { 00403 SymbolRef sym = I.getKey(); 00404 if (SymReaper.maybeDead(sym)) 00405 CNE = CNEFactory.remove(CNE, sym); 00406 } 00407 00408 return state->set<ConstNotEq>(CNE); 00409 } 00410 00411 void BasicConstraintManager::print(ProgramStateRef state, 00412 raw_ostream &Out, 00413 const char* nl, const char *sep) { 00414 // Print equality constraints. 00415 00416 ConstEqTy CE = state->get<ConstEq>(); 00417 00418 if (!CE.isEmpty()) { 00419 Out << nl << sep << "'==' constraints:"; 00420 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) 00421 Out << nl << " $" << I.getKey() << " : " << *I.getData(); 00422 } 00423 00424 // Print != constraints. 00425 00426 ConstNotEqTy CNE = state->get<ConstNotEq>(); 00427 00428 if (!CNE.isEmpty()) { 00429 Out << nl << sep << "'!=' constraints:"; 00430 00431 for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) { 00432 Out << nl << " $" << I.getKey() << " : "; 00433 bool isFirst = true; 00434 00435 ProgramState::IntSetTy::iterator J = I.getData().begin(), 00436 EJ = I.getData().end(); 00437 00438 for ( ; J != EJ; ++J) { 00439 if (isFirst) isFirst = false; 00440 else Out << ", "; 00441 00442 Out << (*J)->getSExtValue(); // Hack: should print to raw_ostream. 00443 } 00444 } 00445 } 00446 }