1 //== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines SimpleConstraintManager, a class that holds code shared
11 //  between BasicConstraintManager and RangeConstraintManager.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "SimpleConstraintManager.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
19 
20 namespace clang {
21 
22 namespace ento {
23 
24 SimpleConstraintManager::~SimpleConstraintManager() {}
25 
26 bool SimpleConstraintManager::canReasonAbout(SVal X) const {
27   nonloc::SymbolVal *SymVal = dyn_cast<nonloc::SymbolVal>(&X);
28   if (SymVal && SymVal->isExpression()) {
29     const SymExpr *SE = SymVal->getSymbol();
30 
31     if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
32       switch (SIE->getOpcode()) {
33           // We don't reason yet about bitwise-constraints on symbolic values.
34         case BO_And:
35         case BO_Or:
36         case BO_Xor:
37           return false;
38         // We don't reason yet about these arithmetic constraints on
39         // symbolic values.
40         case BO_Mul:
41         case BO_Div:
42         case BO_Rem:
43         case BO_Shl:
44         case BO_Shr:
45           return false;
46         // All other cases.
47         default:
48           return true;
49       }
50     }
51 
52     return false;
53   }
54 
55   return true;
56 }
57 
58 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
59                                                DefinedSVal Cond,
60                                                bool Assumption) {
61   if (isa<NonLoc>(Cond))
62     return assume(state, cast<NonLoc>(Cond), Assumption);
63   else
64     return assume(state, cast<Loc>(Cond), Assumption);
65 }
66 
67 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, Loc cond,
68                                                bool assumption) {
69   state = assumeAux(state, cond, assumption);
70   return SU.processAssume(state, cond, assumption);
71 }
72 
73 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
74                                                   Loc Cond, bool Assumption) {
75   switch (Cond.getSubKind()) {
76   default:
77     assert (false && "'Assume' not implemented for this Loc.");
78     return state;
79 
80   case loc::MemRegionKind: {
81     // FIXME: Should this go into the storemanager?
82 
83     const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
84     const SubRegion *SubR = dyn_cast<SubRegion>(R);
85 
86     while (SubR) {
87       // FIXME: now we only find the first symbolic region.
88       if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
89         const llvm::APSInt &zero = getBasicVals().getZeroWithPtrWidth();
90         if (Assumption)
91           return assumeSymNE(state, SymR->getSymbol(), zero, zero);
92         else
93           return assumeSymEQ(state, SymR->getSymbol(), zero, zero);
94       }
95       SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
96     }
97 
98     // FALL-THROUGH.
99   }
100 
101   case loc::GotoLabelKind:
102     return Assumption ? state : NULL;
103 
104   case loc::ConcreteIntKind: {
105     bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
106     bool isFeasible = b ? Assumption : !Assumption;
107     return isFeasible ? state : NULL;
108   }
109   } // end switch
110 }
111 
112 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
113                                                NonLoc cond,
114                                                bool assumption) {
115   state = assumeAux(state, cond, assumption);
116   return SU.processAssume(state, cond, assumption);
117 }
118 
119 static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
120   // FIXME: This should probably be part of BinaryOperator, since this isn't
121   // the only place it's used. (This code was copied from SimpleSValBuilder.cpp.)
122   switch (op) {
123   default:
124     llvm_unreachable("Invalid opcode.");
125   case BO_LT: return BO_GE;
126   case BO_GT: return BO_LE;
127   case BO_LE: return BO_GT;
128   case BO_GE: return BO_LT;
129   case BO_EQ: return BO_NE;
130   case BO_NE: return BO_EQ;
131   }
132 }
133 
134 
135 ProgramStateRef
136 SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
137                                             SymbolRef Sym, bool Assumption) {
138   BasicValueFactory &BVF = getBasicVals();
139   QualType T = Sym->getType(BVF.getContext());
140 
141   // None of the constraint solvers currently support non-integer types.
142   if (!T->isIntegerType())
143     return State;
144 
145   const llvm::APSInt &zero = BVF.getValue(0, T);
146   if (Assumption)
147     return assumeSymNE(State, Sym, zero, zero);
148   else
149     return assumeSymEQ(State, Sym, zero, zero);
150 }
151 
152 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
153                                                   NonLoc Cond,
154                                                   bool Assumption) {
155 
156   // We cannot reason about SymSymExprs, and can only reason about some
157   // SymIntExprs.
158   if (!canReasonAbout(Cond)) {
159     // Just add the constraint to the expression without trying to simplify.
160     SymbolRef sym = Cond.getAsSymExpr();
161     return assumeAuxForSymbol(state, sym, Assumption);
162   }
163 
164   BasicValueFactory &BasicVals = getBasicVals();
165 
166   switch (Cond.getSubKind()) {
167   default:
168     llvm_unreachable("'Assume' not implemented for this NonLoc");
169 
170   case nonloc::SymbolValKind: {
171     nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
172     SymbolRef sym = SV.getSymbol();
173     assert(sym);
174 
175     // Handle SymbolData.
176     if (!SV.isExpression()) {
177       return assumeAuxForSymbol(state, sym, Assumption);
178 
179     // Handle symbolic expression.
180     } else {
181       // We can only simplify expressions whose RHS is an integer.
182       const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym);
183       if (!SE)
184         return assumeAuxForSymbol(state, sym, Assumption);
185 
186       BinaryOperator::Opcode op = SE->getOpcode();
187       // Implicitly compare non-comparison expressions to 0.
188       if (!BinaryOperator::isComparisonOp(op)) {
189         QualType T = SE->getType(BasicVals.getContext());
190         const llvm::APSInt &zero = BasicVals.getValue(0, T);
191         op = (Assumption ? BO_NE : BO_EQ);
192         return assumeSymRel(state, SE, op, zero);
193       }
194       // From here on out, op is the real comparison we'll be testing.
195       if (!Assumption)
196         op = NegateComparison(op);
197 
198       return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
199     }
200   }
201 
202   case nonloc::ConcreteIntKind: {
203     bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
204     bool isFeasible = b ? Assumption : !Assumption;
205     return isFeasible ? state : NULL;
206   }
207 
208   case nonloc::LocAsIntegerKind:
209     return assumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
210                      Assumption);
211   } // end switch
212 }
213 
214 static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
215   // Is it a "($sym+constant1)" expression?
216   if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
217     BinaryOperator::Opcode Op = SE->getOpcode();
218     if (Op == BO_Add || Op == BO_Sub) {
219       Sym = SE->getLHS();
220       Adjustment = APSIntType(Adjustment).convert(SE->getRHS());
221 
222       // Don't forget to negate the adjustment if it's being subtracted.
223       // This should happen /after/ promotion, in case the value being
224       // subtracted is, say, CHAR_MIN, and the promoted type is 'int'.
225       if (Op == BO_Sub)
226         Adjustment = -Adjustment;
227     }
228   }
229 }
230 
231 ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
232                                                      const SymExpr *LHS,
233                                                      BinaryOperator::Opcode op,
234                                                      const llvm::APSInt& Int) {
235   assert(BinaryOperator::isComparisonOp(op) &&
236          "Non-comparison ops should be rewritten as comparisons to zero.");
237 
238   BasicValueFactory &BVF = getBasicVals();
239   ASTContext &Ctx = BVF.getContext();
240 
241   // Get the type used for calculating wraparound.
242   APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType(Ctx));
243 
244   // We only handle simple comparisons of the form "$sym == constant"
245   // or "($sym+constant1) == constant2".
246   // The adjustment is "constant1" in the above expression. It's used to
247   // "slide" the solution range around for modular arithmetic. For example,
248   // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
249   // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
250   // the subclasses of SimpleConstraintManager to handle the adjustment.
251   SymbolRef Sym = LHS;
252   llvm::APSInt Adjustment = WraparoundType.getZeroValue();
253   computeAdjustment(Sym, Adjustment);
254 
255   // Convert the right-hand side integer as necessary.
256   APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
257   llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
258 
259   switch (op) {
260   default:
261     // No logic yet for other operators.  assume the constraint is feasible.
262     return state;
263 
264   case BO_EQ:
265     return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
266 
267   case BO_NE:
268     return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
269 
270   case BO_GT:
271     return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
272 
273   case BO_GE:
274     return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
275 
276   case BO_LT:
277     return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
278 
279   case BO_LE:
280     return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
281   } // end switch
282 }
283 
284 } // end of namespace ento
285 
286 } // end of namespace clang
287