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 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