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   Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
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     if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
00053       if (BinaryOperator::isComparisonOp(SSE->getOpcode())) {
00054         // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
00055         if (Loc::isLocType(SSE->getLHS()->getType())) {
00056           assert(Loc::isLocType(SSE->getRHS()->getType()));
00057           return true;
00058         }
00059       }
00060     }
00061 
00062     return false;
00063   }
00064 
00065   return true;
00066 }
00067 
00068 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
00069                                                DefinedSVal Cond,
00070                                                bool Assumption) {
00071   // If we have a Loc value, cast it to a bool NonLoc first.
00072   if (Optional<Loc> LV = Cond.getAs<Loc>()) {
00073     SValBuilder &SVB = state->getStateManager().getSValBuilder();
00074     QualType T;
00075     const MemRegion *MR = LV->getAsRegion();
00076     if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
00077       T = TR->getLocationType();
00078     else
00079       T = SVB.getContext().VoidPtrTy;
00080 
00081     Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
00082   }
00083 
00084   return assume(state, Cond.castAs<NonLoc>(), Assumption);
00085 }
00086 
00087 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
00088                                                NonLoc cond,
00089                                                bool assumption) {
00090   state = assumeAux(state, cond, assumption);
00091   if (NotifyAssumeClients && SU)
00092     return SU->processAssume(state, cond, assumption);
00093   return state;
00094 }
00095 
00096 
00097 ProgramStateRef
00098 SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
00099                                             SymbolRef Sym, bool Assumption) {
00100   BasicValueFactory &BVF = getBasicVals();
00101   QualType T = Sym->getType();
00102 
00103   // None of the constraint solvers currently support non-integer types.
00104   if (!T->isIntegralOrEnumerationType())
00105     return State;
00106 
00107   const llvm::APSInt &zero = BVF.getValue(0, T);
00108   if (Assumption)
00109     return assumeSymNE(State, Sym, zero, zero);
00110   else
00111     return assumeSymEQ(State, Sym, zero, zero);
00112 }
00113 
00114 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
00115                                                   NonLoc Cond,
00116                                                   bool Assumption) {
00117 
00118   // We cannot reason about SymSymExprs, and can only reason about some
00119   // SymIntExprs.
00120   if (!canReasonAbout(Cond)) {
00121     // Just add the constraint to the expression without trying to simplify.
00122     SymbolRef sym = Cond.getAsSymExpr();
00123     return assumeAuxForSymbol(state, sym, Assumption);
00124   }
00125 
00126   switch (Cond.getSubKind()) {
00127   default:
00128     llvm_unreachable("'Assume' not implemented for this NonLoc");
00129 
00130   case nonloc::SymbolValKind: {
00131     nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
00132     SymbolRef sym = SV.getSymbol();
00133     assert(sym);
00134 
00135     // Handle SymbolData.
00136     if (!SV.isExpression()) {
00137       return assumeAuxForSymbol(state, sym, Assumption);
00138 
00139     // Handle symbolic expression.
00140     } else if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym)) {
00141       // We can only simplify expressions whose RHS is an integer.
00142 
00143       BinaryOperator::Opcode op = SE->getOpcode();
00144       if (BinaryOperator::isComparisonOp(op)) {
00145         if (!Assumption)
00146           op = BinaryOperator::negateComparisonOp(op);
00147 
00148         return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
00149       }
00150 
00151     } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(sym)) {
00152       // Translate "a != b" to "(b - a) != 0".
00153       // We invert the order of the operands as a heuristic for how loop
00154       // conditions are usually written ("begin != end") as compared to length
00155       // calculations ("end - begin"). The more correct thing to do would be to
00156       // canonicalize "a - b" and "b - a", which would allow us to treat
00157       // "a != b" and "b != a" the same.
00158       SymbolManager &SymMgr = getSymbolManager();
00159       BinaryOperator::Opcode Op = SSE->getOpcode();
00160       assert(BinaryOperator::isComparisonOp(Op));
00161 
00162       // For now, we only support comparing pointers.
00163       assert(Loc::isLocType(SSE->getLHS()->getType()));
00164       assert(Loc::isLocType(SSE->getRHS()->getType()));
00165       QualType DiffTy = SymMgr.getContext().getPointerDiffType();
00166       SymbolRef Subtraction = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub,
00167                                                    SSE->getLHS(), DiffTy);
00168 
00169       const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy);
00170       Op = BinaryOperator::reverseComparisonOp(Op);
00171       if (!Assumption)
00172         Op = BinaryOperator::negateComparisonOp(Op);
00173       return assumeSymRel(state, Subtraction, Op, Zero);
00174     }
00175 
00176     // If we get here, there's nothing else we can do but treat the symbol as
00177     // opaque.
00178     return assumeAuxForSymbol(state, sym, Assumption);
00179   }
00180 
00181   case nonloc::ConcreteIntKind: {
00182     bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
00183     bool isFeasible = b ? Assumption : !Assumption;
00184     return isFeasible ? state : nullptr;
00185   }
00186 
00187   case nonloc::LocAsIntegerKind:
00188     return assume(state, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
00189                   Assumption);
00190   } // end switch
00191 }
00192 
00193 static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
00194   // Is it a "($sym+constant1)" expression?
00195   if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
00196     BinaryOperator::Opcode Op = SE->getOpcode();
00197     if (Op == BO_Add || Op == BO_Sub) {
00198       Sym = SE->getLHS();
00199       Adjustment = APSIntType(Adjustment).convert(SE->getRHS());
00200 
00201       // Don't forget to negate the adjustment if it's being subtracted.
00202       // This should happen /after/ promotion, in case the value being
00203       // subtracted is, say, CHAR_MIN, and the promoted type is 'int'.
00204       if (Op == BO_Sub)
00205         Adjustment = -Adjustment;
00206     }
00207   }
00208 }
00209 
00210 ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
00211                                                      const SymExpr *LHS,
00212                                                      BinaryOperator::Opcode op,
00213                                                      const llvm::APSInt& Int) {
00214   assert(BinaryOperator::isComparisonOp(op) &&
00215          "Non-comparison ops should be rewritten as comparisons to zero.");
00216 
00217   // Get the type used for calculating wraparound.
00218   BasicValueFactory &BVF = getBasicVals();
00219   APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType());
00220 
00221   // We only handle simple comparisons of the form "$sym == constant"
00222   // or "($sym+constant1) == constant2".
00223   // The adjustment is "constant1" in the above expression. It's used to
00224   // "slide" the solution range around for modular arithmetic. For example,
00225   // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
00226   // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
00227   // the subclasses of SimpleConstraintManager to handle the adjustment.
00228   SymbolRef Sym = LHS;
00229   llvm::APSInt Adjustment = WraparoundType.getZeroValue();
00230   computeAdjustment(Sym, Adjustment);
00231 
00232   // Convert the right-hand side integer as necessary.
00233   APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
00234   llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
00235 
00236   // Prefer unsigned comparisons.
00237   if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
00238       ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
00239     Adjustment.setIsSigned(false);
00240 
00241   switch (op) {
00242   default:
00243     llvm_unreachable("invalid operation not caught by assertion above");
00244 
00245   case BO_EQ:
00246     return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
00247 
00248   case BO_NE:
00249     return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
00250 
00251   case BO_GT:
00252     return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
00253 
00254   case BO_GE:
00255     return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
00256 
00257   case BO_LT:
00258     return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
00259 
00260   case BO_LE:
00261     return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
00262   } // end switch
00263 }
00264 
00265 } // end of namespace ento
00266 
00267 } // end of namespace clang