[cfe-commits] r50071 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp
Ted Kremenek
kremenek at apple.com
Mon Apr 21 16:43:38 PDT 2008
Author: kremenek
Date: Mon Apr 21 18:43:38 2008
New Revision: 50071
URL: http://llvm.org/viewvc/llvm-project?rev=50071&view=rev
Log:
Added support for detected bad dereferences involving MemberExprs, e.g. x->f where "x" is NULL.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/lib/Analysis/GRExprEngine.cpp
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=50071&r1=50070&r2=50071&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Mon Apr 21 18:43:38 2008
@@ -479,6 +479,13 @@
/// other functions that handle specific kinds of statements.
void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
+ /// VisitLVal - Similar to Visit, but the specified expression is assummed
+ /// to be evaluated under the context where it evaluates to an LVal. For
+ /// example, if Ex is a DeclRefExpr, under Visit Ex would evaluate to the
+ /// value bound to Ex in the symbolic state, while under VisitLVal it would
+ /// evaluate to an LVal representing the location of the referred Decl.
+ void VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst);
+
/// VisitAsmStmt - Transfer function logic for inline asm.
void VisitAsmStmt(AsmStmt* A, NodeTy* Pred, NodeSet& Dst);
@@ -494,25 +501,13 @@
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
-
- void VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst);
+
/// VisitCall - Transfer function for function calls.
void VisitCall(CallExpr* CE, NodeTy* Pred,
CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
NodeSet& Dst);
- /// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
- void VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred, NodeSet& Dst);
-
- void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
- ObjCMessageExpr::arg_iterator I,
- ObjCMessageExpr::arg_iterator E,
- NodeTy* Pred, NodeSet& Dst);
-
- void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, NodeTy* Pred,
- NodeSet& Dst);
-
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
@@ -522,12 +517,36 @@
/// VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst);
+ void VisitDeref(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst,
+ bool GetLVal = false);
+
+ void VisitDeref(Expr* Ex, RVal V, ValueState* St, NodeTy* Pred, NodeSet& Dst,
+ bool GetLVal);
+
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, NodeTy* Pred, NodeSet& Dst);
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
void VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
+ /// VisitMemberExpr - Transfer function for member expressions.
+ void VisitMemberExpr(MemberExpr* M, NodeTy* Pred, NodeSet& Dst, bool asLVal);
+
+ void VisitMemberExprField(MemberExpr* M, Expr* Base, NodeTy* Pred,
+ NodeSet& Dst, bool asLVal);
+
+
+ /// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
+ void VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred, NodeSet& Dst);
+
+ void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
+ ObjCMessageExpr::arg_iterator I,
+ ObjCMessageExpr::arg_iterator E,
+ NodeTy* Pred, NodeSet& Dst);
+
+ void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, NodeTy* Pred,
+ NodeSet& Dst);
+
/// VisitReturnStmt - Transfer function logic for return statements.
void VisitReturnStmt(ReturnStmt* R, NodeTy* Pred, NodeSet& Dst);
@@ -541,8 +560,8 @@
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
- void VisitDeref(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst,
- bool GetLVal = false);
+
+
RVal EvalCast(RVal X, QualType CastT) {
if (X.isUnknownOrUndef())
@@ -554,6 +573,8 @@
return TF->EvalCast(*this, cast<NonLVal>(X), CastT);
}
+
+
RVal EvalMinus(UnaryOperator* U, RVal X) {
return X.isValid() ? TF->EvalMinus(*this, U, cast<NonLVal>(X)) : X;
}
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=50071&r1=50070&r2=50071&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Apr 21 18:43:38 2008
@@ -285,6 +285,11 @@
break;
}
+ case Stmt::MemberExprClass: {
+ VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst, false);
+ break;
+ }
+
case Stmt::ObjCMessageExprClass: {
VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);
break;
@@ -709,6 +714,36 @@
MakeNode(Dst, D, Pred, SetBlkExprRVal(St, D, Y));
}
+/// VisitMemberExpr - Transfer function for member expressions.
+void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred,
+ NodeSet& Dst, bool asLVal) {
+
+ Expr* Base = M->getBase()->IgnoreParens();
+
+ NodeSet Tmp;
+ VisitLVal(Base, Pred, Tmp);
+
+ if (Base->getType()->isPointerType()) {
+ NodeSet Tmp2;
+
+ for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ ValueState* St = GetState(*I);
+ VisitDeref(Base, GetRVal(St, Base), St, *I, Tmp2, true);
+ }
+
+ for (NodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I)
+ VisitMemberExprField(M, Base, *I, Dst, asLVal);
+ }
+ else
+ for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I)
+ VisitMemberExprField(M, Base, *I, Dst, asLVal);
+}
+
+void GRExprEngine::VisitMemberExprField(MemberExpr* M, Expr* Base, NodeTy* Pred,
+ NodeSet& Dst, bool asLVal) {
+ Dst.Add(Pred);
+}
+
void GRExprEngine::EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred,
ValueState* St, RVal TargetLV, RVal Val) {
@@ -1149,9 +1184,9 @@
void GRExprEngine::VisitDeref(UnaryOperator* U, NodeTy* Pred,
NodeSet& Dst, bool GetLVal) {
-
+
Expr* Ex = U->getSubExpr()->IgnoreParens();
-
+
NodeSet DstTmp;
if (isa<DeclRefExpr>(Ex))
@@ -1160,82 +1195,80 @@
Visit(Ex, Pred, DstTmp);
for (NodeSet::iterator I = DstTmp.begin(), DE = DstTmp.end(); I != DE; ++I) {
-
- NodeTy* N = *I;
- ValueState* St = GetState(N);
-
- // FIXME: Bifurcate when dereferencing a symbolic with no constraints?
-
+ ValueState* St = GetState(Pred);
RVal V = GetRVal(St, Ex);
-
- // Check for dereferences of undefined values.
-
- if (V.isUndef()) {
-
- NodeTy* Succ = Builder->generateNode(U, St, N);
-
- if (Succ) {
- Succ->markAsSink();
- UndefDeref.insert(Succ);
- }
-
- continue;
- }
-
- // Check for dereferences of unknown values. Treat as No-Ops.
-
- if (V.isUnknown()) {
- Dst.Add(N);
- continue;
+ VisitDeref(U, V, St, Pred, Dst, GetLVal);
+ }
+}
+
+void GRExprEngine::VisitDeref(Expr* Ex, RVal V, ValueState* St, NodeTy* Pred,
+ NodeSet& Dst, bool GetLVal) {
+
+ // Check for dereferences of undefined values.
+
+ if (V.isUndef()) {
+ if (NodeTy* Succ = Builder->generateNode(Ex, St, Pred)) {
+ Succ->markAsSink();
+ UndefDeref.insert(Succ);
}
- // 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.
-
- LVal LV = cast<LVal>(V);
- bool isFeasibleNotNull;
-
- // "Assume" that the pointer is Not-NULL.
-
- ValueState* StNotNull = Assume(St, LV, true, isFeasibleNotNull);
+ return;
+ }
+
+ // Check for dereferences of unknown values. Treat as No-Ops.
+
+ if (V.isUnknown()) {
+ Dst.Add(Pred);
+ 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.
+
+ LVal LV = cast<LVal>(V);
+ bool isFeasibleNotNull;
+
+ // "Assume" that the pointer is Not-NULL.
+
+ ValueState* StNotNull = Assume(St, LV, true, isFeasibleNotNull);
+
+ if (isFeasibleNotNull) {
- if (isFeasibleNotNull) {
-
- if (GetLVal) MakeNode(Dst, U, N, SetRVal(StNotNull, U, LV));
- else {
-
- // FIXME: Currently symbolic analysis "generates" new symbols
- // for the contents of values. We need a better approach.
+ if (GetLVal)
+ MakeNode(Dst, Ex, Pred, SetRVal(StNotNull, Ex, LV));
+ else {
- MakeNode(Dst, U, N, SetRVal(StNotNull, U,
- GetRVal(StNotNull, LV, U->getType())));
- }
+ // FIXME: Currently symbolic analysis "generates" new symbols
+ // for the contents of values. We need a better approach.
+
+ MakeNode(Dst, Ex, Pred,
+ SetRVal(StNotNull, Ex, GetRVal(StNotNull, LV, Ex->getType())));
}
+ }
+
+ bool isFeasibleNull;
+
+ // Now "assume" that the pointer is NULL.
+
+ ValueState* StNull = Assume(St, LV, false, isFeasibleNull);
+
+ if (isFeasibleNull) {
- bool isFeasibleNull;
-
- // Now "assume" that the pointer is NULL.
+ // We don't use "MakeNode" here because the node will be a sink
+ // and we have no intention of processing it later.
- ValueState* StNull = Assume(St, LV, false, isFeasibleNull);
+ NodeTy* NullNode = Builder->generateNode(Ex, StNull, Pred);
- if (isFeasibleNull) {
+ if (NullNode) {
- // We don't use "MakeNode" here because the node will be a sink
- // and we have no intention of processing it later.
-
- NodeTy* NullNode = Builder->generateNode(U, StNull, N);
+ NullNode->markAsSink();
- if (NullNode) {
-
- NullNode->markAsSink();
-
- if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode);
- else ExplicitNullDeref.insert(NullNode);
- }
- }
+ if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode);
+ else ExplicitNullDeref.insert(NullNode);
+ }
}
}
@@ -1387,23 +1420,36 @@
void GRExprEngine::VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
- if (Ex != CurrentStmt && getCFG().isBlkExpr(Ex)) {
- Dst.Add(Pred);
- return;
- }
-
Ex = Ex->IgnoreParens();
-
- if (isa<DeclRefExpr>(Ex)) {
+
+ if (Ex != CurrentStmt && getCFG().isBlkExpr(Ex)) {
Dst.Add(Pred);
return;
}
- if (UnaryOperator* U = dyn_cast<UnaryOperator>(Ex))
- if (U->getOpcode() == UnaryOperator::Deref) {
- VisitDeref(U, Pred, Dst, true);
+ switch (Ex->getStmtClass()) {
+ default:
+ break;
+
+ case Stmt::DeclRefExprClass:
+ Dst.Add(Pred);
return;
+
+ case Stmt::UnaryOperatorClass: {
+ UnaryOperator* U = cast<UnaryOperator>(Ex);
+
+ if (U->getOpcode() == UnaryOperator::Deref) {
+ VisitDeref(U, Pred, Dst, true);
+ return;
+ }
+
+ break;
}
+
+ case Stmt::MemberExprClass:
+ VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true);
+ return;
+ }
Visit(Ex, Pred, Dst);
}
More information about the cfe-commits
mailing list