clang API Documentation
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