[cfe-commits] r47298 - 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
Mon Feb 18 17:44:53 PST 2008
Author: kremenek
Date: Mon Feb 18 19:44:53 2008
New Revision: 47298
URL: http://llvm.org/viewvc/llvm-project?rev=47298&view=rev
Log:
Added boilerplate transfer function support for CallExprs.
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=47298&r1=47297&r2=47298&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/Analysis/GRExprEngine.cpp Mon Feb 18 19:44:53 2008
@@ -259,7 +259,7 @@
do {
nonlval::ConcreteInt CaseVal(ValMgr.getValue(V1));
- NonLValue Res = EvalBinaryOp(ValMgr, BinaryOperator::EQ, CondV, CaseVal);
+ NonLValue Res = EvalBinaryOp(BinaryOperator::EQ, CondV, CaseVal);
// Now "assume" that the case matches.
bool isFeasible = false;
@@ -407,12 +407,51 @@
Nodify(Dst, D, Pred, SetValue(St, D, GetValue(St, D)));
}
+void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred,
+ CallExpr::arg_iterator I, CallExpr::arg_iterator E,
+ NodeSet& Dst) {
+
+ if (I != E) {
+ NodeSet DstTmp;
+ Visit(*I, Pred, DstTmp);
+ ++I;
+
+ for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI!=DE; ++DI)
+ VisitCall(CE, *DI, I, E, Dst);
+
+ return;
+ }
+
+ // If we reach here we have processed all of the arguments. Evaluate
+ // the callee expression.
+ NodeSet DstTmp;
+ Visit(CE->getCallee(), Pred, DstTmp);
+
+ // Finally, evaluate the function call.
+ for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI!=DE; ++DI) {
+ StateTy St = (*DI)->getState();
+ LValue L = GetLValue(St, CE->getCallee());
+
+ // Check for uninitialized control-flow.
+ if (isa<UninitializedVal>(L)) {
+ NodeTy* N = Builder->generateNode(CE, St, *DI);
+ N->markAsSink();
+ UninitBranches.insert(N);
+ continue;
+ }
+
+ // Note: EvalCall must handle the case where the callee is "UnknownVal."
+ Nodify(Dst, CE, *DI, EvalCall(CE, (*DI)->getState()));
+ }
+}
+
void GRExprEngine::VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst) {
QualType T = CastE->getType();
// Check for redundant casts.
- if (E->getType() == T) {
+ if (E->getType() == T ||
+ (T->isPointerType() && E->getType()->isFunctionType())) {
Dst.Add(Pred);
return;
}
@@ -515,7 +554,7 @@
BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
: BinaryOperator::Sub;
- RValue Result = EvalBinaryOp(ValMgr, Op, R1, GetRValueConstant(1U, U));
+ RValue Result = EvalBinaryOp(Op, R1, GetRValueConstant(1U, U));
if (U->isPostfix())
Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
@@ -553,14 +592,14 @@
const LValue& L1 = cast<LValue>(V1);
lval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
Nodify(Dst, U, N1,
- SetValue(St, U, EvalBinaryOp(ValMgr, BinaryOperator::EQ,
+ SetValue(St, U, EvalBinaryOp(BinaryOperator::EQ,
L1, V2)));
}
else {
const NonLValue& R1 = cast<NonLValue>(V1);
nonlval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
Nodify(Dst, U, N1,
- SetValue(St, U, EvalBinaryOp(ValMgr, BinaryOperator::EQ,
+ SetValue(St, U, EvalBinaryOp(BinaryOperator::EQ,
R1, V2)));
}
@@ -705,7 +744,7 @@
continue;
}
- Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(ValMgr, Op, V1, V2)));
+ Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(Op, V1, V2)));
continue;
}
@@ -742,14 +781,14 @@
if (B->getType()->isPointerType()) { // Perform pointer arithmetic.
const NonLValue& R2 = cast<NonLValue>(V2);
- Result = EvalBinaryOp(ValMgr, Op, L1, R2);
+ Result = EvalBinaryOp(Op, L1, R2);
}
else if (isa<LValue>(V2)) {
const LValue& L2 = cast<LValue>(V2);
if (B->getRHS()->getType()->isPointerType()) {
// LValue comparison.
- Result = EvalBinaryOp(ValMgr, Op, L1, L2);
+ Result = EvalBinaryOp(Op, L1, L2);
}
else {
QualType T1 = B->getLHS()->getType();
@@ -757,7 +796,7 @@
// An operation between two variables of a non-lvalue type.
Result =
- EvalBinaryOp(ValMgr, Op,
+ EvalBinaryOp(Op,
cast<NonLValue>(GetValue(N1->getState(), L1, &T1)),
cast<NonLValue>(GetValue(N2->getState(), L2, &T2)));
}
@@ -767,7 +806,7 @@
const NonLValue& R1 = cast<NonLValue>(GetValue(N1->getState(),
L1, &T));
const NonLValue& R2 = cast<NonLValue>(V2);
- Result = EvalBinaryOp(ValMgr, Op, R1, R2);
+ Result = EvalBinaryOp(Op, R1, R2);
}
Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
@@ -821,6 +860,12 @@
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
break;
}
+
+ case Stmt::CallExprClass: {
+ CallExpr* C = cast<CallExpr>(S);
+ VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
+ break;
+ }
case Stmt::CastExprClass: {
CastExpr* C = cast<CastExpr>(S);
Modified: cfe/trunk/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.cpp?rev=47298&r1=47297&r2=47298&view=diff
==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (original)
+++ cfe/trunk/Analysis/RValues.cpp Mon Feb 18 19:44:53 2008
@@ -342,7 +342,12 @@
case lval::DeclValKind:
Out << '&'
- << cast<lval::DeclVal>(this)->getDecl()->getIdentifier()->getName();
+ << cast<lval::DeclVal>(this)->getDecl()->getIdentifier()->getName();
+ break;
+
+ case lval::FuncValKind:
+ Out << "function "
+ << cast<lval::FuncVal>(this)->getDecl()->getIdentifier()->getName();
break;
default:
Modified: cfe/trunk/Analysis/ValueState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.cpp?rev=47298&r1=47297&r2=47298&view=diff
==============================================================================
--- cfe/trunk/Analysis/ValueState.cpp (original)
+++ cfe/trunk/Analysis/ValueState.cpp Mon Feb 18 19:44:53 2008
@@ -220,6 +220,8 @@
// a better way, since APInts are fairly lightweight.
return nonlval::ConcreteInt(ValMgr.getValue(ED->getInitVal()));
}
+ else if (FunctionDecl* FD = dyn_cast<FunctionDecl>(D))
+ return lval::FuncVal(FD);
assert (false &&
"ValueDecl support for this ValueDecl not implemented.");
@@ -248,7 +250,10 @@
case Stmt::ImplicitCastExprClass: {
ImplicitCastExpr* C = cast<ImplicitCastExpr>(E);
- if (C->getType() == C->getSubExpr()->getType()) {
+ QualType CT = C->getType();
+ QualType ST = C->getSubExpr()->getType();
+
+ if (CT == ST || (CT->isPointerType() && ST->isFunctionType())) {
E = C->getSubExpr();
continue;
}
@@ -257,7 +262,10 @@
case Stmt::CastExprClass: {
CastExpr* C = cast<CastExpr>(E);
- if (C->getType() == C->getSubExpr()->getType()) {
+ QualType CT = C->getType();
+ QualType ST = C->getSubExpr()->getType();
+
+ if (CT == ST || (CT->isPointerType() && ST->isFunctionType())) {
E = C->getSubExpr();
continue;
}
@@ -297,8 +305,14 @@
while (ParenExpr* P = dyn_cast<ParenExpr>(E))
E = P->getSubExpr();
- if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
- return lval::DeclVal(cast<VarDecl>(DR->getDecl()));
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) {
+ ValueDecl* VD = DR->getDecl();
+
+ if (FunctionDecl* FD = dyn_cast<FunctionDecl>(VD))
+ return lval::FuncVal(FD);
+ else
+ return lval::DeclVal(cast<VarDecl>(DR->getDecl()));
+ }
if (UnaryOperator* U = dyn_cast<UnaryOperator>(E))
if (U->getOpcode() == UnaryOperator::Deref)
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=47298&r1=47297&r2=47298&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Mon Feb 18 19:44:53 2008
@@ -296,6 +296,11 @@
void VisitAssignmentLHS(Expr* E, NodeTy* Pred, NodeSet& Dst);
+ /// VisitCall - Transfer function for function calls.
+ void VisitCall(CallExpr* CE, NodeTy* Pred,
+ CallExpr::arg_iterator I, CallExpr::arg_iterator E,
+ NodeSet& Dst);
+
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
@@ -342,7 +347,7 @@
return TF->EvalComplement(ValMgr, X);
}
- inline NonLValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ inline NonLValue EvalBinaryOp(BinaryOperator::Opcode Op,
NonLValue LHS, NonLValue RHS) {
if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
@@ -354,7 +359,7 @@
return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
- inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
LValue LHS, LValue RHS) {
if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
@@ -366,7 +371,7 @@
return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
- inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
LValue LHS, NonLValue RHS) {
if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
@@ -378,7 +383,7 @@
return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
- inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
RValue LHS, RValue RHS) {
if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
@@ -389,5 +394,9 @@
return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
+
+ StateTy EvalCall(CallExpr* CE, StateTy St) {
+ return St;
+ }
};
} // end clang namespace
\ No newline at end of file
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=47298&r1=47297&r2=47298&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Mon Feb 18 19:44:53 2008
@@ -147,9 +147,9 @@
namespace nonlval {
- enum Kind { SymbolValKind,
+ enum Kind { ConcreteIntKind,
+ SymbolValKind,
SymIntConstraintValKind,
- ConcreteIntKind,
NumKind };
class SymbolVal : public NonLValue {
@@ -218,6 +218,7 @@
enum Kind { SymbolValKind,
GotoLabelKind,
DeclValKind,
+ FuncValKind,
ConcreteIntKind,
NumKind };
@@ -282,6 +283,32 @@
return V->getSubKind() == DeclValKind;
}
};
+
+ class FuncVal : public LValue {
+ public:
+ FuncVal(const FunctionDecl* fd) : LValue(FuncValKind, fd) {}
+
+ FunctionDecl* getDecl() const {
+ return static_cast<FunctionDecl*>(Data);
+ }
+
+ inline bool operator==(const FuncVal& R) const {
+ return getDecl() == R.getDecl();
+ }
+
+ inline bool operator!=(const FuncVal& R) const {
+ return getDecl() != R.getDecl();
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const RValue* V) {
+ return isa<LValue>(V) && V->getSubKind() == FuncValKind;
+ }
+
+ static inline bool classof(const LValue* V) {
+ return V->getSubKind() == FuncValKind;
+ }
+ };
class ConcreteInt : public LValue {
public:
More information about the cfe-commits
mailing list