clang API Documentation

SimpleConstraintManager.cpp
Go to the documentation of this file.
00001 //== SimpleConstraintManager.cpp --------------------------------*- 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 SimpleConstraintManager, a class that holds code shared
00011 //  between BasicConstraintManager and RangeConstraintManager.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "SimpleConstraintManager.h"
00016 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
00017 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
00018 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
00019 
00020 namespace clang {
00021 
00022 namespace ento {
00023 
00024 SimpleConstraintManager::~SimpleConstraintManager() {}
00025 
00026 bool SimpleConstraintManager::canReasonAbout(SVal X) const {
00027   nonloc::SymbolVal *SymVal = dyn_cast<nonloc::SymbolVal>(&X);
00028   if (SymVal && SymVal->isExpression()) {
00029     const SymExpr *SE = SymVal->getSymbol();
00030 
00031     if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
00032       switch (SIE->getOpcode()) {
00033           // We don't reason yet about bitwise-constraints on symbolic values.
00034         case BO_And:
00035         case BO_Or:
00036         case BO_Xor:
00037           return false;
00038         // We don't reason yet about these arithmetic constraints on
00039         // symbolic values.
00040         case BO_Mul:
00041         case BO_Div:
00042         case BO_Rem:
00043         case BO_Shl:
00044         case BO_Shr:
00045           return false;
00046         // All other cases.
00047         default:
00048           return true;
00049       }
00050     }
00051 
00052     return false;
00053   }
00054 
00055   return true;
00056 }
00057 
00058 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
00059                                                DefinedSVal Cond,
00060                                                bool Assumption) {
00061   if (isa<NonLoc>(Cond))
00062     return assume(state, cast<NonLoc>(Cond), Assumption);
00063   else
00064     return assume(state, cast<Loc>(Cond), Assumption);
00065 }
00066 
00067 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, Loc cond,
00068                                                bool assumption) {
00069   state = assumeAux(state, cond, assumption);
00070   return SU.processAssume(state, cond, assumption);
00071 }
00072 
00073 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
00074                                                   Loc Cond, bool Assumption) {
00075   switch (Cond.getSubKind()) {
00076   default:
00077     assert (false && "'Assume' not implemented for this Loc.");
00078     return state;
00079 
00080   case loc::MemRegionKind: {
00081     // FIXME: Should this go into the storemanager?
00082 
00083     const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
00084     const SubRegion *SubR = dyn_cast<SubRegion>(R);
00085 
00086     while (SubR) {
00087       // FIXME: now we only find the first symbolic region.
00088       if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
00089         const llvm::APSInt &zero = getBasicVals().getZeroWithPtrWidth();
00090         if (Assumption)
00091           return assumeSymNE(state, SymR->getSymbol(), zero, zero);
00092         else
00093           return assumeSymEQ(state, SymR->getSymbol(), zero, zero);
00094       }
00095       SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
00096     }
00097 
00098     // FALL-THROUGH.
00099   }
00100 
00101   case loc::GotoLabelKind:
00102     return Assumption ? state : NULL;
00103 
00104   case loc::ConcreteIntKind: {
00105     bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
00106     bool isFeasible = b ? Assumption : !Assumption;
00107     return isFeasible ? state : NULL;
00108   }
00109   } // end switch
00110 }
00111 
00112 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
00113                                                NonLoc cond,
00114                                                bool assumption) {
00115   state = assumeAux(state, cond, assumption);
00116   return SU.processAssume(state, cond, assumption);
00117 }
00118 
00119 static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
00120   // FIXME: This should probably be part of BinaryOperator, since this isn't
00121   // the only place it's used. (This code was copied from SimpleSValBuilder.cpp.)
00122   switch (op) {
00123   default:
00124     llvm_unreachable("Invalid opcode.");
00125   case BO_LT: return BO_GE;
00126   case BO_GT: return BO_LE;
00127   case BO_LE: return BO_GT;
00128   case BO_GE: return BO_LT;
00129   case BO_EQ: return BO_NE;
00130   case BO_NE: return BO_EQ;
00131   }
00132 }
00133 
00134 
00135 ProgramStateRef
00136 SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
00137                                             SymbolRef Sym, bool Assumption) {
00138   BasicValueFactory &BVF = getBasicVals();
00139   QualType T = Sym->getType(BVF.getContext());
00140 
00141   // None of the constraint solvers currently support non-integer types.
00142   if (!T->isIntegerType())
00143     return State;
00144 
00145   const llvm::APSInt &zero = BVF.getValue(0, T);
00146   if (Assumption)
00147     return assumeSymNE(State, Sym, zero, zero);
00148   else
00149     return assumeSymEQ(State, Sym, zero, zero);
00150 }
00151 
00152 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
00153                                                   NonLoc Cond,
00154                                                   bool Assumption) {
00155 
00156   // We cannot reason about SymSymExprs, and can only reason about some
00157   // SymIntExprs.
00158   if (!canReasonAbout(Cond)) {
00159     // Just add the constraint to the expression without trying to simplify.
00160     SymbolRef sym = Cond.getAsSymExpr();
00161     return assumeAuxForSymbol(state, sym, Assumption);
00162   }
00163 
00164   BasicValueFactory &BasicVals = getBasicVals();
00165 
00166   switch (Cond.getSubKind()) {
00167   default:
00168     llvm_unreachable("'Assume' not implemented for this NonLoc");
00169 
00170   case nonloc::SymbolValKind: {
00171     nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
00172     SymbolRef sym = SV.getSymbol();
00173     assert(sym);
00174 
00175     // Handle SymbolData.
00176     if (!SV.isExpression()) {
00177       return assumeAuxForSymbol(state, sym, Assumption);
00178 
00179     // Handle symbolic expression.
00180     } else {
00181       // We can only simplify expressions whose RHS is an integer.
00182       const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym);
00183       if (!SE)
00184         return assumeAuxForSymbol(state, sym, Assumption);
00185 
00186       BinaryOperator::Opcode op = SE->getOpcode();
00187       // Implicitly compare non-comparison expressions to 0.
00188       if (!BinaryOperator::isComparisonOp(op)) {
00189         QualType T = SE->getType(BasicVals.getContext());
00190         const llvm::APSInt &zero = BasicVals.getValue(0, T);
00191         op = (Assumption ? BO_NE : BO_EQ);
00192         return assumeSymRel(state, SE, op, zero);
00193       }
00194       // From here on out, op is the real comparison we'll be testing.
00195       if (!Assumption)
00196         op = NegateComparison(op);
00197 
00198       return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
00199     }
00200   }
00201 
00202   case nonloc::ConcreteIntKind: {
00203     bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
00204     bool isFeasible = b ? Assumption : !Assumption;
00205     return isFeasible ? state : NULL;
00206   }
00207 
00208   case nonloc::LocAsIntegerKind:
00209     return assumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
00210                      Assumption);
00211   } // end switch
00212 }
00213 
00214 static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
00215   // Is it a "($sym+constant1)" expression?
00216   if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
00217     BinaryOperator::Opcode Op = SE->getOpcode();
00218     if (Op == BO_Add || Op == BO_Sub) {
00219       Sym = SE->getLHS();
00220       Adjustment = APSIntType(Adjustment).convert(SE->getRHS());
00221 
00222       // Don't forget to negate the adjustment if it's being subtracted.
00223       // This should happen /after/ promotion, in case the value being
00224       // subtracted is, say, CHAR_MIN, and the promoted type is 'int'.
00225       if (Op == BO_Sub)
00226         Adjustment = -Adjustment;
00227     }
00228   }
00229 }
00230 
00231 ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
00232                                                      const SymExpr *LHS,
00233                                                      BinaryOperator::Opcode op,
00234                                                      const llvm::APSInt& Int) {
00235   assert(BinaryOperator::isComparisonOp(op) &&
00236          "Non-comparison ops should be rewritten as comparisons to zero.");
00237 
00238   BasicValueFactory &BVF = getBasicVals();
00239   ASTContext &Ctx = BVF.getContext();
00240 
00241   // Get the type used for calculating wraparound.
00242   APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType(Ctx));
00243 
00244   // We only handle simple comparisons of the form "$sym == constant"
00245   // or "($sym+constant1) == constant2".
00246   // The adjustment is "constant1" in the above expression. It's used to
00247   // "slide" the solution range around for modular arithmetic. For example,
00248   // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
00249   // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
00250   // the subclasses of SimpleConstraintManager to handle the adjustment.
00251   SymbolRef Sym = LHS;
00252   llvm::APSInt Adjustment = WraparoundType.getZeroValue();
00253   computeAdjustment(Sym, Adjustment);
00254 
00255   // Convert the right-hand side integer as necessary.
00256   APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
00257   llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
00258 
00259   switch (op) {
00260   default:
00261     // No logic yet for other operators.  assume the constraint is feasible.
00262     return state;
00263 
00264   case BO_EQ:
00265     return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
00266 
00267   case BO_NE:
00268     return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
00269 
00270   case BO_GT:
00271     return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
00272 
00273   case BO_GE:
00274     return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
00275 
00276   case BO_LT:
00277     return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
00278 
00279   case BO_LE:
00280     return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
00281   } // end switch
00282 }
00283 
00284 } // end of namespace ento
00285 
00286 } // end of namespace clang