clang API Documentation

BasicConstraintManager.cpp
Go to the documentation of this file.
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 }