clang  3.7.0
SimpleConstraintManager.cpp
Go to the documentation of this file.
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 
19 
20 namespace clang {
21 
22 namespace ento {
23 
25 
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  if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
53  if (BinaryOperator::isComparisonOp(SSE->getOpcode())) {
54  // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
55  if (Loc::isLocType(SSE->getLHS()->getType())) {
56  assert(Loc::isLocType(SSE->getRHS()->getType()));
57  return true;
58  }
59  }
60  }
61 
62  return false;
63  }
64 
65  return true;
66 }
67 
69  DefinedSVal Cond,
70  bool Assumption) {
71  // If we have a Loc value, cast it to a bool NonLoc first.
72  if (Optional<Loc> LV = Cond.getAs<Loc>()) {
73  SValBuilder &SVB = state->getStateManager().getSValBuilder();
74  QualType T;
75  const MemRegion *MR = LV->getAsRegion();
76  if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
77  T = TR->getLocationType();
78  else
79  T = SVB.getContext().VoidPtrTy;
80 
81  Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
82  }
83 
84  return assume(state, Cond.castAs<NonLoc>(), Assumption);
85 }
86 
88  NonLoc cond,
89  bool assumption) {
90  state = assumeAux(state, cond, assumption);
91  if (NotifyAssumeClients && SU)
92  return SU->processAssume(state, cond, assumption);
93  return state;
94 }
95 
96 
99  SymbolRef Sym, bool Assumption) {
101  QualType T = Sym->getType();
102 
103  // None of the constraint solvers currently support non-integer types.
104  if (!T->isIntegralOrEnumerationType())
105  return State;
106 
107  const llvm::APSInt &zero = BVF.getValue(0, T);
108  if (Assumption)
109  return assumeSymNE(State, Sym, zero, zero);
110  else
111  return assumeSymEQ(State, Sym, zero, zero);
112 }
113 
115  NonLoc Cond,
116  bool Assumption) {
117 
118  // We cannot reason about SymSymExprs, and can only reason about some
119  // SymIntExprs.
120  if (!canReasonAbout(Cond)) {
121  // Just add the constraint to the expression without trying to simplify.
122  SymbolRef sym = Cond.getAsSymExpr();
123  return assumeAuxForSymbol(state, sym, Assumption);
124  }
125 
126  switch (Cond.getSubKind()) {
127  default:
128  llvm_unreachable("'Assume' not implemented for this NonLoc");
129 
130  case nonloc::SymbolValKind: {
132  SymbolRef sym = SV.getSymbol();
133  assert(sym);
134 
135  // Handle SymbolData.
136  if (!SV.isExpression()) {
137  return assumeAuxForSymbol(state, sym, Assumption);
138 
139  // Handle symbolic expression.
140  } else if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym)) {
141  // We can only simplify expressions whose RHS is an integer.
142 
143  BinaryOperator::Opcode op = SE->getOpcode();
145  if (!Assumption)
147 
148  return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
149  }
150 
151  } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(sym)) {
152  // Translate "a != b" to "(b - a) != 0".
153  // We invert the order of the operands as a heuristic for how loop
154  // conditions are usually written ("begin != end") as compared to length
155  // calculations ("end - begin"). The more correct thing to do would be to
156  // canonicalize "a - b" and "b - a", which would allow us to treat
157  // "a != b" and "b != a" the same.
158  SymbolManager &SymMgr = getSymbolManager();
159  BinaryOperator::Opcode Op = SSE->getOpcode();
160  assert(BinaryOperator::isComparisonOp(Op));
161 
162  // For now, we only support comparing pointers.
163  assert(Loc::isLocType(SSE->getLHS()->getType()));
164  assert(Loc::isLocType(SSE->getRHS()->getType()));
165  QualType DiffTy = SymMgr.getContext().getPointerDiffType();
166  SymbolRef Subtraction = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub,
167  SSE->getLHS(), DiffTy);
168 
169  const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy);
171  if (!Assumption)
173  return assumeSymRel(state, Subtraction, Op, Zero);
174  }
175 
176  // If we get here, there's nothing else we can do but treat the symbol as
177  // opaque.
178  return assumeAuxForSymbol(state, sym, Assumption);
179  }
180 
182  bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
183  bool isFeasible = b ? Assumption : !Assumption;
184  return isFeasible ? state : nullptr;
185  }
186 
188  return assume(state, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
189  Assumption);
190  } // end switch
191 }
192 
193 static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
194  // Is it a "($sym+constant1)" expression?
195  if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
196  BinaryOperator::Opcode Op = SE->getOpcode();
197  if (Op == BO_Add || Op == BO_Sub) {
198  Sym = SE->getLHS();
199  Adjustment = APSIntType(Adjustment).convert(SE->getRHS());
200 
201  // Don't forget to negate the adjustment if it's being subtracted.
202  // This should happen /after/ promotion, in case the value being
203  // subtracted is, say, CHAR_MIN, and the promoted type is 'int'.
204  if (Op == BO_Sub)
205  Adjustment = -Adjustment;
206  }
207  }
208 }
209 
211  const SymExpr *LHS,
213  const llvm::APSInt& Int) {
214  assert(BinaryOperator::isComparisonOp(op) &&
215  "Non-comparison ops should be rewritten as comparisons to zero.");
216 
217  // Get the type used for calculating wraparound.
219  APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType());
220 
221  // We only handle simple comparisons of the form "$sym == constant"
222  // or "($sym+constant1) == constant2".
223  // The adjustment is "constant1" in the above expression. It's used to
224  // "slide" the solution range around for modular arithmetic. For example,
225  // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
226  // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
227  // the subclasses of SimpleConstraintManager to handle the adjustment.
228  SymbolRef Sym = LHS;
229  llvm::APSInt Adjustment = WraparoundType.getZeroValue();
230  computeAdjustment(Sym, Adjustment);
231 
232  // Convert the right-hand side integer as necessary.
233  APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
234  llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
235 
236  // Prefer unsigned comparisons.
237  if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
238  ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
239  Adjustment.setIsSigned(false);
240 
241  switch (op) {
242  default:
243  llvm_unreachable("invalid operation not caught by assertion above");
244 
245  case BO_EQ:
246  return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
247 
248  case BO_NE:
249  return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
250 
251  case BO_GT:
252  return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
253 
254  case BO_GE:
255  return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
256 
257  case BO_LT:
258  return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
259 
260  case BO_LE:
261  return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
262  } // end switch
263 }
264 
265 } // end of namespace ento
266 
267 } // end of namespace clang
const SymExpr * getAsSymExpr() const
Definition: SVals.cpp:128
CanQualType VoidPtrTy
Definition: ASTContext.h:831
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:77
virtual ProgramStateRef assumeSymNE(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment)=0
SVal evalCast(SVal val, QualType castTy, QualType originalType)
Value representing integer constant.
Definition: SVals.h:339
Symbolic value. These values used to capture symbolic execution of the program.
Definition: SymbolManager.h:42
bool isComparisonOp() const
Definition: Expr.h:3008
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:3023
virtual ProgramStateRef assumeSymGT(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment)=0
LineState State
static bool isLocType(QualType T)
Definition: SVals.h:291
BinaryOperatorKind
uint32_t getBitWidth() const
Definition: APSIntType.h:31
A record of the "type" of an APSInt, used for conversions.
Definition: APSIntType.h:20
virtual ProgramStateRef assumeSymGE(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment)=0
Represents a symbolic expression like 'x' + 3.
virtual ProgramStateRef assumeSymEQ(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment)=0
llvm::APSInt getZeroValue() const LLVM_READONLY
Returns an all-zero value for this type.
Definition: APSIntType.h:56
virtual QualType getType() const =0
static Opcode negateComparisonOp(Opcode Opc)
Definition: Expr.h:3010
bool isUnsigned() const
Definition: APSIntType.h:32
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:86
virtual ProgramStateRef assumeSymLE(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment)=0
virtual ProgramStateRef processAssume(ProgramStateRef state, SVal cond, bool assumption)=0
static SVal getValue(SVal val, SValBuilder &svalBuilder)
ProgramStateRef assumeSymRel(ProgramStateRef state, const SymExpr *LHS, BinaryOperator::Opcode op, const llvm::APSInt &Int)
const SymSymExpr * getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t)
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:5476
ProgramStateRef assumeAux(ProgramStateRef state, NonLoc Cond, bool Assumption)
ASTContext & getContext()
Definition: SValBuilder.h:121
ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond, bool Assumption) override
SymbolRef getSymbol() const
Definition: SVals.h:317
llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY
Definition: APSIntType.h:49
unsigned getSubKind() const
Definition: SVals.h:100
ProgramStateRef assumeAuxForSymbol(ProgramStateRef State, SymbolRef Sym, bool Assumption)
bool isExpression() const
Definition: SVals.h:321
Represents symbolic expression.
Definition: SVals.h:313
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>. Pointer - pointer requires t...
X
Definition: SemaDecl.cpp:11429
static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment)
virtual ProgramStateRef assumeSymLT(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment)=0
APSIntType getAPSIntType(QualType T) const
Returns the type of the APSInt used to store values of the given QualType.
CanQualType BoolTy
Definition: ASTContext.h:818
BasicValueFactory & getBasicVals() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:75
Represents a symbolic expression like 'x' + 'y'.
TypedRegion - An abstract class representing regions that are typed.
Definition: MemRegion.h:476