[cfe-commits] r47356 - in /cfe/trunk: Analysis/GRExprEngine.cpp Analysis/RValues.cpp Analysis/ValueState.cpp include/clang/Analysis/PathSensitive/GRExprEngine.h include/clang/Analysis/PathSensitive/RValues.h
Ted Kremenek
kremenek at apple.com
Tue Feb 19 20:02:36 PST 2008
Author: kremenek
Date: Tue Feb 19 22:02:35 2008
New Revision: 47356
URL: http://llvm.org/viewvc/llvm-project?rev=47356&view=rev
Log:
Placed transfer function logic for dereferences in its own method, while at
the same time clearing up some logic of how the unary '*' operator is processed.
Modified:
cfe/trunk/Analysis/GRExprEngine.cpp
cfe/trunk/Analysis/RValues.cpp
cfe/trunk/Analysis/ValueState.cpp
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
Modified: cfe/trunk/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRExprEngine.cpp?rev=47356&r1=47355&r2=47356&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/Analysis/GRExprEngine.cpp Tue Feb 19 22:02:35 2008
@@ -528,32 +528,124 @@
}
+void GRExprEngine::VisitDeref(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst) {
+
+ Expr* E = U->getSubExpr()->IgnoreParens();
+
+ NodeSet DstTmp;
+
+ if (!isa<DeclRefExpr>(E))
+ DstTmp.Add(Pred);
+ else
+ Visit(E, Pred, DstTmp);
+
+ for (NodeSet::iterator I=DstTmp.begin(), DE=DstTmp.end(); I != DE; ++I) {
+
+ NodeTy* N = *I;
+ StateTy St = N->getState();
+
+ // FIXME: Bifurcate when dereferencing a symbolic with no constraints?
+
+ LValue L = cast<LValue>(GetValue(St, E));
+
+ if (isa<UninitializedVal>(L)) {
+ NodeTy* Succ = Builder->generateNode(U, St, N);
+
+ if (Succ) {
+ Succ->markAsSink();
+ UninitDeref.insert(Succ);
+ }
+
+ continue;
+ }
+
+ if (L.isUnknown()) {
+ Dst.Add(N);
+ continue;
+ }
+
+ // After a dereference, one of two possible situations arise:
+ // (1) A crash, because the pointer was NULL.
+ // (2) The pointer is not NULL, and the dereference works.
+ //
+ // We add these assumptions.
+
+ bool isFeasibleNotNull;
+
+ // "Assume" that the pointer is Not-NULL.
+ StateTy StNotNull = Assume(St, L, true, isFeasibleNotNull);
+
+ if (isFeasibleNotNull) {
+ QualType T = U->getType();
+
+ // FIXME: Currently symbolic analysis "generates" new symbols
+ // for the contents of values. We need a better approach.
+
+ Nodify(Dst, U, N, SetValue(StNotNull, U, GetValue(StNotNull, L, &T)));
+ }
+
+ bool isFeasibleNull;
+
+ // "Assume" that the pointer is NULL.
+ StateTy StNull = Assume(St, L, false, isFeasibleNull);
+
+ if (isFeasibleNull) {
+ // We don't use "Nodify" here because the node will be a sink
+ // and we have no intention of processing it later.
+ NodeTy* NullNode = Builder->generateNode(U, StNull, N);
+
+ if (NullNode) {
+ NullNode->markAsSink();
+
+ if (isFeasibleNotNull)
+ ImplicitNullDeref.insert(NullNode);
+ else
+ ExplicitNullDeref.insert(NullNode);
+ }
+ }
+ }
+}
+
void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
- GRExprEngine::NodeTy* Pred,
- GRExprEngine::NodeSet& Dst) {
+ NodeTy* Pred, NodeSet& Dst) {
NodeSet S1;
- UnaryOperator::Opcode Op = U->getOpcode();
- // FIXME: This is a hack so that for '*' and '&' we don't recurse
- // on visiting the subexpression if it is a DeclRefExpr. We should
- // probably just handle AddrOf and Deref in their own methods to make
- // this cleaner.
- if ((Op == UnaryOperator::Deref || Op == UnaryOperator::AddrOf) &&
- isa<DeclRefExpr>(U->getSubExpr()))
- S1.Add(Pred);
- else
- Visit(U->getSubExpr(), Pred, S1);
-
+ assert (U->getOpcode() != UnaryOperator::Deref);
+
+ switch (U->getOpcode()) {
+ case UnaryOperator::PostInc:
+ case UnaryOperator::PostDec:
+ case UnaryOperator::PreInc:
+ case UnaryOperator::PreDec:
+ case UnaryOperator::AddrOf:
+ // Evalue subexpression as an LValue.
+ VisitLValue(U->getSubExpr(), Pred, S1);
+ break;
+
+ case UnaryOperator::SizeOf:
+ case UnaryOperator::AlignOf:
+ // Do not evaluate subexpression.
+ S1.Add(Pred);
+ break;
+
+ default:
+ Visit(U->getSubExpr(), Pred, S1);
+ break;
+ }
+
for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
+
NodeTy* N1 = *I1;
StateTy St = N1->getState();
- // Handle ++ and -- (both pre- and post-increment).
-
if (U->isIncrementDecrementOp()) {
+
+ // Handle ++ and -- (both pre- and post-increment).
+
const LValue& L1 = GetLValue(St, U->getSubExpr());
- RValue R1 = GetValue(St, L1);
+ QualType T = U->getType();
+ RValue R1 = GetValue(St, L1, &T);
BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
: BinaryOperator::Sub;
@@ -634,77 +726,17 @@
Nodify(Dst, U, N1, SetValue(St, U, L1));
break;
}
-
- case UnaryOperator::Deref: {
- // FIXME: Stop when dereferencing an uninitialized value.
- // FIXME: Bifurcate when dereferencing a symbolic with no constraints?
-
- const RValue& V = GetValue(St, U->getSubExpr());
- const LValue& L1 = cast<LValue>(V);
-
- if (isa<UninitializedVal>(L1)) {
- NodeTy* N = Builder->generateNode(U, St, N1);
-
- if (N) {
- N->markAsSink();
- UninitDeref.insert(N);
- }
-
- return;
- }
-
- // After a dereference, one of two possible situations arise:
- // (1) A crash, because the pointer was NULL.
- // (2) The pointer is not NULL, and the dereference works.
- //
- // We add these assumptions.
- bool isFeasibleNotNull;
-
- // "Assume" that the pointer is Not-NULL.
- StateTy StNotNull = Assume(St, L1, true, isFeasibleNotNull);
-
- if (isFeasibleNotNull) {
- QualType T = U->getType();
- Nodify(Dst, U, N1, SetValue(StNotNull, U,
- GetValue(StNotNull, L1, &T)));
- }
-
- if (V.isUnknown())
- return;
-
- bool isFeasibleNull;
-
- // "Assume" that the pointer is NULL.
- StateTy StNull = Assume(St, L1, false, isFeasibleNull);
-
- if (isFeasibleNull) {
- // We don't use "Nodify" here because the node will be a sink
- // and we have no intention of processing it later.
- NodeTy* NullNode = Builder->generateNode(U, StNull, N1);
-
- if (NullNode) {
- NullNode->markAsSink();
-
- if (isFeasibleNotNull)
- ImplicitNullDeref.insert(NullNode);
- else
- ExplicitNullDeref.insert(NullNode);
- }
- }
-
- break;
- }
-
default: ;
assert (false && "Not implemented.");
}
}
}
-void GRExprEngine::VisitAssignmentLHS(Expr* E, GRExprEngine::NodeTy* Pred,
- GRExprEngine::NodeSet& Dst) {
-
+void GRExprEngine::VisitLValue(Expr* E, NodeTy* Pred, NodeSet& Dst) {
+
+ E = E->IgnoreParens();
+
if (isa<DeclRefExpr>(E)) {
Dst.Add(Pred);
return;
@@ -712,7 +744,13 @@
if (UnaryOperator* U = dyn_cast<UnaryOperator>(E)) {
if (U->getOpcode() == UnaryOperator::Deref) {
- Visit(U->getSubExpr(), Pred, Dst);
+ E = U->getSubExpr()->IgnoreParens();
+
+ if (isa<DeclRefExpr>(E))
+ Dst.Add(Pred);
+ else
+ Visit(E, Pred, Dst);
+
return;
}
}
@@ -726,7 +764,7 @@
NodeSet S1;
if (B->isAssignmentOp())
- VisitAssignmentLHS(B->getLHS(), Pred, S1);
+ VisitLValue(B->getLHS(), Pred, S1);
else
Visit(B->getLHS(), Pred, S1);
@@ -974,9 +1012,16 @@
break;
}
- case Stmt::UnaryOperatorClass:
- VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
+ case Stmt::UnaryOperatorClass: {
+ UnaryOperator* U = cast<UnaryOperator>(S);
+
+ if (U->getOpcode() == UnaryOperator::Deref)
+ VisitDeref(U, Pred, Dst);
+ else
+ VisitUnaryOperator(U, Pred, Dst);
+
break;
+ }
}
}
Modified: cfe/trunk/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.cpp?rev=47356&r1=47355&r2=47356&view=diff
==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (original)
+++ cfe/trunk/Analysis/RValues.cpp Tue Feb 19 22:02:35 2008
@@ -240,7 +240,7 @@
// Pretty-Printing.
//===----------------------------------------------------------------------===//
-void RValue::print() const {
+void RValue::printStdErr() const {
print(*llvm::cerr.stream());
}
Modified: cfe/trunk/Analysis/ValueState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.cpp?rev=47356&r1=47355&r2=47356&view=diff
==============================================================================
--- cfe/trunk/Analysis/ValueState.cpp (original)
+++ cfe/trunk/Analysis/ValueState.cpp Tue Feb 19 22:02:35 2008
@@ -310,9 +310,8 @@
LValue ValueStateManager::GetLValue(ValueState St, Expr* E) {
- while (ParenExpr* P = dyn_cast<ParenExpr>(E))
- E = P->getSubExpr();
-
+ E = E->IgnoreParens();
+
if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) {
ValueDecl* VD = DR->getDecl();
@@ -323,9 +322,17 @@
}
if (UnaryOperator* U = dyn_cast<UnaryOperator>(E))
- if (U->getOpcode() == UnaryOperator::Deref)
- return cast<LValue>(GetValue(St, U->getSubExpr()));
-
+ if (U->getOpcode() == UnaryOperator::Deref) {
+ E = U->getSubExpr()->IgnoreParens();
+
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) {
+ lval::DeclVal X(cast<VarDecl>(DR->getDecl()));
+ return cast<LValue>(GetValue(St, X));
+ }
+ else
+ return cast<LValue>(GetValue(St, E));
+ }
+
return cast<LValue>(GetValue(St, E));
}
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=47356&r1=47355&r2=47356&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Tue Feb 19 22:02:35 2008
@@ -299,7 +299,7 @@
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
- void VisitAssignmentLHS(Expr* E, NodeTy* Pred, NodeSet& Dst);
+ void VisitLValue(Expr* E, NodeTy* Pred, NodeSet& Dst);
/// VisitCall - Transfer function for function calls.
void VisitCall(CallExpr* CE, NodeTy* Pred,
@@ -329,6 +329,8 @@
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
+ void VisitDeref(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
+
inline RValue EvalCast(ValueManager& ValMgr, RValue X, Expr* CastExpr) {
if (isa<UnknownVal>(X) || isa<UninitializedVal>(X))
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h?rev=47356&r1=47355&r2=47356&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Tue Feb 19 22:02:35 2008
@@ -72,7 +72,7 @@
inline bool isUnknown() const { return getRawKind() == UnknownKind; }
void print(std::ostream& OS) const;
- void print() const;
+ void printStdErr() const;
typedef const SymbolID* symbol_iterator;
symbol_iterator symbol_begin() const;
More information about the cfe-commits
mailing list