summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/SVals.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis/SVals.cpp')
-rw-r--r--clang/lib/Analysis/SVals.cpp216
1 files changed, 107 insertions, 109 deletions
diff --git a/clang/lib/Analysis/SVals.cpp b/clang/lib/Analysis/SVals.cpp
index 0f345602a22..9225f994d3f 100644
--- a/clang/lib/Analysis/SVals.cpp
+++ b/clang/lib/Analysis/SVals.cpp
@@ -22,37 +22,13 @@ using llvm::cast;
using llvm::APSInt;
//===----------------------------------------------------------------------===//
-// Symbol Iteration.
+// Symbol iteration within an SVal.
//===----------------------------------------------------------------------===//
-SVal::symbol_iterator SVal::symbol_begin() const {
- // FIXME: This is a rat's nest. Cleanup.
-
- if (isa<loc::SymbolVal>(this))
- return symbol_iterator(SymbolRef((uintptr_t)Data));
- else if (isa<nonloc::SymbolVal>(this))
- return symbol_iterator(SymbolRef((uintptr_t)Data));
- else if (isa<nonloc::SymIntConstraintVal>(this)) {
- const SymIntConstraint& C =
- cast<nonloc::SymIntConstraintVal>(this)->getConstraint();
- return symbol_iterator(C.getSymbol());
- }
- else if (isa<nonloc::LocAsInteger>(this)) {
- const nonloc::LocAsInteger& V = cast<nonloc::LocAsInteger>(*this);
- return V.getPersistentLoc().symbol_begin();
- }
- else if (isa<loc::MemRegionVal>(this)) {
- const MemRegion* R = cast<loc::MemRegionVal>(this)->getRegion();
- if (const SymbolicRegion* S = dyn_cast<SymbolicRegion>(R))
- return symbol_iterator(S->getSymbol());
- }
-
- return symbol_iterator();
-}
-SVal::symbol_iterator SVal::symbol_end() const {
- return symbol_iterator();
-}
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
/// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
/// wraps a symbol, return that SymbolRef. Otherwise return a SymbolRef
@@ -78,7 +54,7 @@ SymbolRef SVal::getAsLocSymbol() const {
}
}
- return SymbolRef();
+ return 0;
}
/// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
@@ -87,9 +63,66 @@ SymbolRef SVal::getAsSymbol() const {
if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
return X->getSymbol();
+ if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
+ if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression()))
+ return Y;
+
return getAsLocSymbol();
}
+/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+/// return that expression. Otherwise return NULL.
+const SymExpr *SVal::getAsSymbolicExpression() const {
+ if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
+ return X->getSymbolicExpression();
+
+ return getAsSymbol();
+}
+
+bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
+ return itr == X.itr;
+}
+
+bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const {
+ return itr != X.itr;
+}
+
+SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) {
+ itr.push_back(SE);
+ while (!isa<SymbolData>(itr.back())) expand();
+}
+
+SVal::symbol_iterator& SVal::symbol_iterator::operator++() {
+ assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
+ assert(isa<SymbolData>(itr.back()));
+ itr.pop_back();
+ if (!itr.empty())
+ while (!isa<SymbolData>(itr.back())) expand();
+ return *this;
+}
+
+SymbolRef SVal::symbol_iterator::operator*() {
+ assert(!itr.empty() && "attempting to dereference an 'end' iterator");
+ return cast<SymbolData>(itr.back());
+}
+
+void SVal::symbol_iterator::expand() {
+ const SymExpr *SE = itr.back();
+ itr.pop_back();
+
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
+ itr.push_back(SIE->getLHS());
+ return;
+ }
+ else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
+ itr.push_back(SSE->getLHS());
+ itr.push_back(SSE->getRHS());
+ return;
+ }
+
+ assert(false && "unhandled expansion case");
+}
+
//===----------------------------------------------------------------------===//
// Other Iterators.
//===----------------------------------------------------------------------===//
@@ -168,7 +201,7 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
return UndefinedVal();
}
-NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const {
+NonLoc Loc::EQ(SymbolManager& SymMgr, const Loc& R) const {
switch (getSubKind()) {
default:
@@ -180,49 +213,48 @@ NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const {
bool b = cast<loc::ConcreteInt>(this)->getValue() ==
cast<loc::ConcreteInt>(R).getValue();
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
}
else if (isa<loc::SymbolVal>(R)) {
-
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
+ const SymIntExpr *SE =
+ SymMgr.getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(),
BinaryOperator::EQ,
- cast<loc::ConcreteInt>(this)->getValue());
+ cast<loc::ConcreteInt>(this)->getValue(),
+ SymMgr.getContext().IntTy);
- return nonloc::SymIntConstraintVal(C);
+ return nonloc::SymExprVal(SE);
}
break;
case loc::SymbolValKind: {
if (isa<loc::ConcreteInt>(R)) {
-
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(),
+ const SymIntExpr *SE =
+ SymMgr.getSymIntExpr(cast<loc::SymbolVal>(this)->getSymbol(),
BinaryOperator::EQ,
- cast<loc::ConcreteInt>(R).getValue());
+ cast<loc::ConcreteInt>(R).getValue(),
+ SymMgr.getContext().IntTy);
- return nonloc::SymIntConstraintVal(C);
+ return nonloc::SymExprVal(SE);
}
-
- assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification.");
-
+
+ assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification.");
break;
}
case loc::MemRegionKind:
if (isa<loc::MemRegionVal>(R)) {
bool b = cast<loc::MemRegionVal>(*this) == cast<loc::MemRegionVal>(R);
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
}
break;
}
- return NonLoc::MakeIntTruthVal(BasicVals, false);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), false);
}
-NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const {
+NonLoc Loc::NE(SymbolManager& SymMgr, const Loc& R) const {
switch (getSubKind()) {
default:
assert(false && "NE not implemented for this Loc.");
@@ -233,46 +265,43 @@ NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const {
bool b = cast<loc::ConcreteInt>(this)->getValue() !=
cast<loc::ConcreteInt>(R).getValue();
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
}
else if (isa<loc::SymbolVal>(R)) {
-
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
- BinaryOperator::NE,
- cast<loc::ConcreteInt>(this)->getValue());
-
- return nonloc::SymIntConstraintVal(C);
+ const SymIntExpr *SE =
+ SymMgr.getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(),
+ BinaryOperator::NE,
+ cast<loc::ConcreteInt>(this)->getValue(),
+ SymMgr.getContext().IntTy);
+ return nonloc::SymExprVal(SE);
}
-
break;
case loc::SymbolValKind: {
if (isa<loc::ConcreteInt>(R)) {
+ const SymIntExpr *SE =
+ SymMgr.getSymIntExpr(cast<loc::SymbolVal>(this)->getSymbol(),
+ BinaryOperator::NE,
+ cast<loc::ConcreteInt>(R).getValue(),
+ SymMgr.getContext().IntTy);
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(),
- BinaryOperator::NE,
- cast<loc::ConcreteInt>(R).getValue());
-
- return nonloc::SymIntConstraintVal(C);
+ return nonloc::SymExprVal(SE);
}
assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement sym !=.");
-
break;
}
case loc::MemRegionKind:
if (isa<loc::MemRegionVal>(R)) {
bool b = cast<loc::MemRegionVal>(*this)==cast<loc::MemRegionVal>(R);
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
}
break;
}
- return NonLoc::MakeIntTruthVal(BasicVals, true);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), true);
}
//===----------------------------------------------------------------------===//
@@ -283,21 +312,21 @@ NonLoc NonLoc::MakeVal(SymbolRef sym) {
return nonloc::SymbolVal(sym);
}
-NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
- BinaryOperator::Opcode op, const APSInt& v) {
+NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const APSInt& v, QualType T) {
// The Environment ensures we always get a persistent APSInt in
// BasicValueFactory, so we don't need to get the APSInt from
// BasicValueFactory again.
-
- SymbolRef sym = SymMgr.getSymIntExpr(lhs, op, v, SymMgr.getType(lhs));
- return nonloc::SymbolVal(sym);
+ assert(!Loc::IsLocType(T));
+ return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
}
-NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
- BinaryOperator::Opcode op, SymbolRef rhs) {
+NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const SymExpr *rhs,
+QualType T) {
assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
- SymbolRef sym = SymMgr.getSymSymExpr(lhs, op, rhs, SymMgr.getType(lhs));
- return nonloc::SymbolVal(sym);
+ assert(!Loc::IsLocType(T));
+ return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
}
NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
@@ -419,30 +448,6 @@ void SVal::print(llvm::raw_ostream& Out) const {
}
}
-static void printOpcode(llvm::raw_ostream& Out, BinaryOperator::Opcode Op) {
-
- switch (Op) {
- case BinaryOperator::Mul: Out << '*' ; break;
- case BinaryOperator::Div: Out << '/' ; break;
- case BinaryOperator::Rem: Out << '%' ; break;
- case BinaryOperator::Add: Out << '+' ; break;
- case BinaryOperator::Sub: Out << '-' ; break;
- case BinaryOperator::Shl: Out << "<<" ; break;
- case BinaryOperator::Shr: Out << ">>" ; break;
- case BinaryOperator::LT: Out << "<" ; break;
- case BinaryOperator::GT: Out << '>' ; break;
- case BinaryOperator::LE: Out << "<=" ; break;
- case BinaryOperator::GE: Out << ">=" ; break;
- case BinaryOperator::EQ: Out << "==" ; break;
- case BinaryOperator::NE: Out << "!=" ; break;
- case BinaryOperator::And: Out << '&' ; break;
- case BinaryOperator::Xor: Out << '^' ; break;
- case BinaryOperator::Or: Out << '|' ; break;
-
- default: assert(false && "Not yet implemented.");
- }
-}
-
void NonLoc::print(llvm::raw_ostream& Out) const {
switch (getSubKind()) {
@@ -459,17 +464,10 @@ void NonLoc::print(llvm::raw_ostream& Out) const {
Out << '$' << cast<nonloc::SymbolVal>(this)->getSymbol();
break;
- case nonloc::SymIntConstraintValKind: {
- const nonloc::SymIntConstraintVal& C =
- *cast<nonloc::SymIntConstraintVal>(this);
-
- Out << '$' << C.getConstraint().getSymbol() << ' ';
- printOpcode(Out, C.getConstraint().getOpcode());
- Out << ' ' << C.getConstraint().getInt().getZExtValue();
-
- if (C.getConstraint().getInt().isUnsigned())
- Out << 'U';
-
+ case nonloc::SymExprValKind: {
+ const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this);
+ const SymExpr *SE = C.getSymbolicExpression();
+ Out << SE;
break;
}
OpenPOWER on IntegriCloud