Skip to content

Commit 24e7ead

Browse files
committed
This patch adds two more SymbolData subclasses: SymIntExpr and SymSymExpr, for
representing symbolic expressions like 'x'+3 and 'x'+'y'. The design is subjected to change later when we fix the class hierarchy of symbolic expressions. llvm-svn: 67678
1 parent b2304ee commit 24e7ead

File tree

7 files changed

+152
-28
lines changed

7 files changed

+152
-28
lines changed

clang/include/clang/Analysis/PathSensitive/SVals.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ class NonLoc : public SVal {
181181

182182
static NonLoc MakeVal(SymbolRef sym);
183183

184+
static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
185+
BinaryOperator::Opcode op, const llvm::APSInt& v);
186+
187+
static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
188+
BinaryOperator::Opcode op, SymbolRef rhs);
189+
184190
static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
185191
bool isUnsigned);
186192

clang/include/clang/Analysis/PathSensitive/SymbolManager.h

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ namespace clang {
8585

8686
class SymbolData : public llvm::FoldingSetNode {
8787
public:
88-
enum Kind { RegionRValue, ConjuredKind };
88+
enum Kind { RegionRValue, ConjuredKind, SymIntKind, SymSymKind };
8989

9090
private:
9191
Kind K;
@@ -171,6 +171,65 @@ class SymbolConjured : public SymbolData {
171171
}
172172
};
173173

174+
// SymIntExpr - Represents symbolic expression like 'x' + 3.
175+
class SymIntExpr : public SymbolData {
176+
SymbolRef LHS;
177+
BinaryOperator::Opcode Op;
178+
const llvm::APSInt& Val;
179+
QualType T;
180+
181+
public:
182+
SymIntExpr(SymbolRef sym, SymbolRef lhs, BinaryOperator::Opcode op,
183+
const llvm::APSInt& V, QualType t)
184+
: SymbolData(SymIntKind, sym), LHS(lhs), Op(op), Val(V), T(t) {}
185+
186+
QualType getType(ASTContext& C) const {
187+
return T;
188+
}
189+
190+
static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs,
191+
BinaryOperator::Opcode op, const llvm::APSInt& V,
192+
QualType t) {
193+
lhs.Profile(ID);
194+
ID.AddInteger(op);
195+
ID.AddPointer(&V);
196+
ID.Add(t);
197+
}
198+
199+
void Profile(llvm::FoldingSetNodeID& ID) {
200+
Profile(ID, LHS, Op, Val, T);
201+
}
202+
};
203+
204+
// SymSymExpr - Represents symbolic expression like 'x' + 'y'.
205+
class SymSymExpr : public SymbolData {
206+
SymbolRef LHS;
207+
BinaryOperator::Opcode Op;
208+
SymbolRef RHS;
209+
QualType T;
210+
211+
public:
212+
SymSymExpr(SymbolRef sym, SymbolRef lhs, BinaryOperator::Opcode op,
213+
SymbolRef rhs, QualType t)
214+
: SymbolData(SymSymKind, sym), LHS(lhs), Op(op), RHS(rhs), T(t) {}
215+
216+
QualType getType(ASTContext& C) const {
217+
return T;
218+
}
219+
220+
static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs,
221+
BinaryOperator::Opcode op, SymbolRef rhs, QualType t) {
222+
lhs.Profile(ID);
223+
ID.AddInteger(op);
224+
rhs.Profile(ID);
225+
ID.Add(t);
226+
}
227+
228+
void Profile(llvm::FoldingSetNodeID& ID) {
229+
Profile(ID, LHS, Op, RHS, T);
230+
}
231+
};
232+
174233
// Constraints on symbols. Usually wrapped by SValues.
175234

176235
class SymIntConstraint : public llvm::FoldingSetNode {
@@ -230,6 +289,12 @@ class SymbolManager {
230289
const void* SymbolTag = 0) {
231290
return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
232291
}
292+
293+
SymbolRef getSymIntExpr(SymbolRef lhs, BinaryOperator::Opcode op,
294+
const llvm::APSInt& v, QualType t);
295+
296+
SymbolRef getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
297+
SymbolRef rhs, QualType t);
233298

234299
const SymbolData& getSymbolData(SymbolRef ID) const;
235300

clang/lib/Analysis/GRSimpleVals.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,16 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
230230

231231
case nonloc::SymbolValKind:
232232
if (isa<nonloc::ConcreteInt>(R)) {
233-
const SymIntConstraint& C =
234-
BasicVals.getConstraint(cast<nonloc::SymbolVal>(L).getSymbol(), Op,
235-
cast<nonloc::ConcreteInt>(R).getValue());
236-
237-
return nonloc::SymIntConstraintVal(C);
233+
if (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE) {
234+
const SymIntConstraint& C =
235+
BasicVals.getConstraint(cast<nonloc::SymbolVal>(L).getSymbol(),
236+
Op, cast<nonloc::ConcreteInt>(R).getValue());
237+
return nonloc::SymIntConstraintVal(C);
238+
} else {
239+
return NonLoc::MakeVal(Eng.getSymbolManager(),
240+
cast<nonloc::SymbolVal>(L).getSymbol(),
241+
Op, cast<nonloc::ConcreteInt>(R).getValue());
242+
}
238243
}
239244
else
240245
return UnknownVal();

clang/lib/Analysis/SVals.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,23 @@ NonLoc NonLoc::MakeVal(SymbolRef sym) {
283283
return nonloc::SymbolVal(sym);
284284
}
285285

286+
NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
287+
BinaryOperator::Opcode op, const APSInt& v) {
288+
// The Environment ensures we always get a persistent APSInt in
289+
// BasicValueFactory, so we don't need to get the APSInt from
290+
// BasicValueFactory again.
291+
292+
SymbolRef sym = SymMgr.getSymIntExpr(lhs, op, v, SymMgr.getType(lhs));
293+
return nonloc::SymbolVal(sym);
294+
}
295+
296+
NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
297+
BinaryOperator::Opcode op, SymbolRef rhs) {
298+
assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
299+
SymbolRef sym = SymMgr.getSymSymExpr(lhs, op, rhs, SymMgr.getType(lhs));
300+
return nonloc::SymbolVal(sym);
301+
}
302+
286303
NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
287304
bool isUnsigned) {
288305
return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned));

clang/lib/Analysis/SimpleConstraintManager.cpp

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,11 @@ namespace clang {
2121
SimpleConstraintManager::~SimpleConstraintManager() {}
2222

2323
bool SimpleConstraintManager::canReasonAbout(SVal X) const {
24-
if (nonloc::SymIntConstraintVal *Y = dyn_cast<nonloc::SymIntConstraintVal>(&X)) {
25-
const SymIntConstraint& C = Y->getConstraint();
26-
switch (C.getOpcode()) {
27-
// We don't reason yet about bitwise-constraints on symbolic values.
28-
case BinaryOperator::And:
29-
case BinaryOperator::Or:
30-
case BinaryOperator::Xor:
31-
return false;
32-
// We don't reason yet about arithmetic constraints on symbolic values.
33-
case BinaryOperator::Mul:
34-
case BinaryOperator::Div:
35-
case BinaryOperator::Rem:
36-
case BinaryOperator::Add:
37-
case BinaryOperator::Sub:
38-
case BinaryOperator::Shl:
39-
case BinaryOperator::Shr:
40-
return false;
41-
42-
// All other cases.
43-
default:
44-
return true;
45-
}
24+
if (nonloc::SymbolVal* SymVal = dyn_cast<nonloc::SymbolVal>(&X)) {
25+
const SymbolData& data
26+
= getSymbolManager().getSymbolData(SymVal->getSymbol());
27+
return !(data.getKind() == SymbolData::SymIntKind ||
28+
data.getKind() == SymbolData::SymSymKind );
4629
}
4730

4831
return true;
@@ -143,6 +126,12 @@ SimpleConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption,
143126
const GRState*
144127
SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
145128
bool Assumption, bool& isFeasible) {
129+
// We cannot reason about SymIntExpr and SymSymExpr.
130+
if (!canReasonAbout(Cond)) {
131+
isFeasible = true;
132+
return St;
133+
}
134+
146135
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
147136
SymbolManager& SymMgr = StateMgr.getSymbolManager();
148137

clang/lib/Analysis/SimpleConstraintManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class SimpleConstraintManager : public ConstraintManager {
7676

7777
private:
7878
BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
79+
SymbolManager& getSymbolManager() const { return StateMgr.getSymbolManager(); }
7980
};
8081

8182
} // end clang namespace

clang/lib/Analysis/SymbolManager.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,47 @@ SymbolRef SymbolManager::getConjuredSymbol(const Stmt* E, QualType T,
7474
return SymbolCounter++;
7575
}
7676

77+
SymbolRef SymbolManager::getSymIntExpr(SymbolRef lhs,BinaryOperator::Opcode op,
78+
const llvm::APSInt& v, QualType t) {
79+
llvm::FoldingSetNodeID ID;
80+
SymIntExpr::Profile(ID, lhs, op, v, t);
81+
void* InsertPos;
82+
83+
SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
84+
85+
if (data)
86+
return data->getSymbol();
87+
88+
data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
89+
new (data) SymIntExpr(SymbolCounter, lhs, op, v, t);
90+
91+
DataSet.InsertNode(data, InsertPos);
92+
DataMap[SymbolCounter] = data;
93+
94+
return SymbolCounter++;
95+
}
96+
97+
SymbolRef SymbolManager::getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
98+
SymbolRef rhs, QualType t) {
99+
llvm::FoldingSetNodeID ID;
100+
SymSymExpr::Profile(ID, lhs, op, rhs, t);
101+
void* InsertPos;
102+
103+
SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
104+
105+
if (data)
106+
return data->getSymbol();
107+
108+
data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
109+
new (data) SymSymExpr(SymbolCounter, lhs, op, rhs, t);
110+
111+
DataSet.InsertNode(data, InsertPos);
112+
DataMap[SymbolCounter] = data;
113+
114+
return SymbolCounter++;
115+
}
116+
117+
77118
const SymbolData& SymbolManager::getSymbolData(SymbolRef Sym) const {
78119
DataMapTy::const_iterator I = DataMap.find(Sym);
79120
assert (I != DataMap.end());

0 commit comments

Comments
 (0)