[cfe-commits] r47441 - in /cfe/trunk: Analysis/GRExprEngine.cpp Analysis/GRSimpleVals.cpp Analysis/GRSimpleVals.h Analysis/GRTransferFuncs.cpp Analysis/RValues.cpp Analysis/ValueState.cpp Analysis/ValueState.h include/clang/Analysis/PathSensitive/GRExprEngine.h include/clang/Analysis/PathSensitive/GRTransferFuncs.h include/clang/Analysis/PathSensitive/RValues.h
Ted Kremenek
kremenek at apple.com
Thu Feb 21 10:02:17 PST 2008
Author: kremenek
Date: Thu Feb 21 12:02:17 2008
New Revision: 47441
URL: http://llvm.org/viewvc/llvm-project?rev=47441&view=rev
Log:
Major cleanup of path-sensitive analysis engine and the current analysis
based on constant. prop. and limited symbolics.
- Renamed class: RValue -> RVal, LValue -> LVal, etc.
- Minor method renamings and interface cleanups.
- Tightened the RVal "type system" so that UninitializedVal and UnknownVal
cannot be cast to LVal or NonLVal. This forces these corner cases values
to be explicitly handled early before being dispatched to plug-in transfer
function logic.
- Major cleanup in the transfer function logic for binary and unary operators.
Still fixing some regressions, but we now explicitly handle Uninitialized
and Unknown values in a more rigorous way.
Modified:
cfe/trunk/Analysis/GRExprEngine.cpp
cfe/trunk/Analysis/GRSimpleVals.cpp
cfe/trunk/Analysis/GRSimpleVals.h
cfe/trunk/Analysis/GRTransferFuncs.cpp
cfe/trunk/Analysis/RValues.cpp
cfe/trunk/Analysis/ValueState.cpp
cfe/trunk/Analysis/ValueState.h
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.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=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/Analysis/GRExprEngine.cpp Thu Feb 21 12:02:17 2008
@@ -24,7 +24,7 @@
using llvm::APSInt;
GRExprEngine::StateTy
-GRExprEngine::SetValue(StateTy St, Expr* S, const RValue& V) {
+GRExprEngine::SetRVal(StateTy St, Expr* Ex, const RVal& V) {
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
@@ -33,44 +33,41 @@
bool isBlkExpr = false;
- if (S == CurrentStmt) {
- isBlkExpr = getCFG().isBlkExpr(S);
+ if (Ex == CurrentStmt) {
+ isBlkExpr = getCFG().isBlkExpr(Ex);
if (!isBlkExpr)
return St;
}
- return StateMgr.SetValue(St, S, isBlkExpr, V);
+ return StateMgr.SetRVal(St, Ex, isBlkExpr, V);
}
const GRExprEngine::StateTy::BufferTy&
-GRExprEngine::SetValue(StateTy St, Expr* S, const RValue::BufferTy& RB,
+GRExprEngine::SetRVal(StateTy St, Expr* Ex, const RVal::BufferTy& RB,
StateTy::BufferTy& RetBuf) {
assert (RetBuf.empty());
- for (RValue::BufferTy::const_iterator I=RB.begin(), E=RB.end(); I!=E; ++I)
- RetBuf.push_back(SetValue(St, S, *I));
+ for (RVal::BufferTy::const_iterator I = RB.begin(), E = RB.end(); I!=E; ++I)
+ RetBuf.push_back(SetRVal(St, Ex, *I));
return RetBuf;
}
GRExprEngine::StateTy
-GRExprEngine::SetValue(StateTy St, const LValue& LV, const RValue& V) {
-
- if (LV.isUnknown())
- return St;
+GRExprEngine::SetRVal(StateTy St, const LVal& LV, const RVal& RV) {
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
StateCleaned = true;
}
- return StateMgr.SetValue(St, LV, V);
+ return StateMgr.SetRVal(St, LV, RV);
}
void GRExprEngine::ProcessBranch(Expr* Condition, Stmt* Term,
- BranchNodeBuilder& builder) {
+ BranchNodeBuilder& builder) {
// Remove old bindings for subexpressions.
StateTy PrevState = StateMgr.RemoveSubExprBindings(builder.getState());
@@ -90,18 +87,18 @@
return;
}
- RValue V = GetValue(PrevState, Condition);
+ RVal V = GetRVal(PrevState, Condition);
switch (V.getBaseKind()) {
default:
break;
- case RValue::UnknownKind:
+ case RVal::UnknownKind:
builder.generateNode(PrevState, true);
builder.generateNode(PrevState, false);
return;
- case RValue::UninitializedKind: {
+ case RVal::UninitializedKind: {
NodeTy* N = builder.generateNode(PrevState, true);
if (N) {
@@ -162,7 +159,7 @@
void GRExprEngine::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) {
StateTy St = builder.getState();
- LValue V = cast<LValue>(GetValue(St, builder.getTarget()));
+ RVal V = GetRVal(St, builder.getTarget());
// Three possibilities:
//
@@ -196,7 +193,7 @@
// This is really a catch-all. We don't support symbolics yet.
- assert (isa<UnknownVal>(V));
+ assert (V.isUnknown());
for (iterator I=builder.begin(), E=builder.end(); I != E; ++I)
builder.generateNode(I, St);
@@ -210,9 +207,9 @@
StateTy St = builder.getState();
Expr* CondE = builder.getCondition();
- NonLValue CondV = cast<NonLValue>(GetValue(St, CondE));
+ RVal CondV = GetRVal(St, CondE);
- if (isa<UninitializedVal>(CondV)) {
+ if (CondV.isUninit()) {
NodeTy* N = builder.generateDefaultCaseNode(St, true);
UninitBranches.insert(N);
return;
@@ -229,7 +226,7 @@
APSInt V1(bits, false);
APSInt V2 = V1;
- for (iterator I=builder.begin(), E=builder.end(); I!=E; ++I) {
+ for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) {
CaseStmt* Case = cast<CaseStmt>(I.getCase());
@@ -254,12 +251,12 @@
// FIXME: Eventually we should replace the logic below with a range
// comparison, rather than concretize the values within the range.
- // This should be easy once we have "ranges" for NonLValues.
+ // This should be easy once we have "ranges" for NonLVals.
do {
nonlval::ConcreteInt CaseVal(ValMgr.getValue(V1));
- NonLValue Res = EvalBinaryOp(BinaryOperator::EQ, CondV, CaseVal);
+ RVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal);
// Now "assume" that the case matches.
bool isFeasible = false;
@@ -297,22 +294,22 @@
void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
- NodeSet& Dst) {
+ NodeSet& Dst) {
bool hasR2;
StateTy PrevState = Pred->getState();
- RValue R1 = GetValue(PrevState, B->getLHS());
- RValue R2 = GetValue(PrevState, B->getRHS(), hasR2);
+ RVal R1 = GetRVal(PrevState, B->getLHS());
+ RVal R2 = GetRVal(PrevState, B->getRHS(), hasR2);
if (hasR2) {
- if (isa<UninitializedVal>(R2) || isa<UnknownVal>(R2)) {
- Nodify(Dst, B, Pred, SetValue(PrevState, B, R2));
+ if (R2.isUnknownOrUninit()) {
+ Nodify(Dst, B, Pred, SetRVal(PrevState, B, R2));
return;
}
}
- else if (isa<UninitializedVal>(R1) || isa<UnknownVal>(R1)) {
- Nodify(Dst, B, Pred, SetValue(PrevState, B, R1));
+ else if (R1.isUnknownOrUninit()) {
+ Nodify(Dst, B, Pred, SetRVal(PrevState, B, R1));
return;
}
@@ -321,7 +318,7 @@
// hasR2 == 'false' means that LHS evaluated to 'false' and that
// we short-circuited, leading to a value of '0' for the '&&' expression.
if (hasR2 == false) {
- Nodify(Dst, B, Pred, SetValue(PrevState, B, GetRValueConstant(0U, B)));
+ Nodify(Dst, B, Pred, SetRVal(PrevState, B, MakeConstantVal(0U, B)));
return;
}
}
@@ -330,7 +327,7 @@
// hasR2 == 'false' means that the LHS evaluate to 'true' and that
// we short-circuited, leading to a value of '1' for the '||' expression.
if (hasR2 == false) {
- Nodify(Dst, B, Pred, SetValue(PrevState, B, GetRValueConstant(1U, B)));
+ Nodify(Dst, B, Pred, SetRVal(PrevState, B, MakeConstantVal(1U, B)));
return;
}
}
@@ -342,19 +339,19 @@
StateTy St = Assume(PrevState, R2, true, isFeasible);
if (isFeasible)
- Nodify(Dst, B, Pred, SetValue(PrevState, B, GetRValueConstant(1U, B)));
+ Nodify(Dst, B, Pred, SetRVal(PrevState, B, MakeConstantVal(1U, B)));
St = Assume(PrevState, R2, false, isFeasible);
if (isFeasible)
- Nodify(Dst, B, Pred, SetValue(PrevState, B, GetRValueConstant(0U, B)));
+ Nodify(Dst, B, Pred, SetRVal(PrevState, B, MakeConstantVal(0U, B)));
}
void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
- Builder = &builder;
+ Builder = &builder;
StmtEntryNode = builder.getLastNode();
CurrentStmt = S;
NodeSet Dst;
@@ -364,11 +361,14 @@
// If no nodes were generated, generate a new node that has all the
// dead mappings removed.
+
if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
builder.generateNode(S, St, StmtEntryNode);
}
+ // For safety, NULL out these variables.
+
CurrentStmt = NULL;
StmtEntryNode = NULL;
Builder = NULL;
@@ -383,6 +383,7 @@
NodeTy* N = Builder->generateNode(S, St, Pred);
Dst.Add(N);
+
return N;
}
@@ -394,6 +395,7 @@
}
void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){
+
if (D != CurrentStmt) {
Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
return;
@@ -402,77 +404,85 @@
// If we are here, we are loading the value of the decl and binding
// it to the block-level expression.
- StateTy St = Pred->getState();
-
- Nodify(Dst, D, Pred, SetValue(St, D, GetValue(St, D)));
+ StateTy St = Pred->getState();
+ Nodify(Dst, D, Pred, SetRVal(St, D, GetRVal(St, D)));
}
void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred,
- CallExpr::arg_iterator I, CallExpr::arg_iterator E,
+ CallExpr::arg_iterator AI,
+ CallExpr::arg_iterator AE,
NodeSet& Dst) {
- if (I != E) {
+ // Process the arguments.
+
+ if (AI != AE) {
+
NodeSet DstTmp;
- Visit(*I, Pred, DstTmp);
- ++I;
+ Visit(*AI, Pred, DstTmp);
+ ++AI;
- for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI!=DE; ++DI)
- VisitCall(CE, *DI, I, E, Dst);
+ for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI != DE; ++DI)
+ VisitCall(CE, *DI, AI, AE, Dst);
return;
}
// If we reach here we have processed all of the arguments. Evaluate
// the callee expression.
- NodeSet DstTmp;
+ NodeSet DstTmp;
Visit(CE->getCallee(), Pred, DstTmp);
// Finally, evaluate the function call.
- for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI!=DE; ++DI) {
+ for (NodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) {
+
StateTy St = (*DI)->getState();
- LValue L = GetLValue(St, CE->getCallee());
+ RVal L = GetLVal(St, CE->getCallee());
// Check for uninitialized control-flow.
- if (isa<UninitializedVal>(L)) {
+
+ if (L.isUninit()) {
+
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()));
+ // FIXME: EvalCall must handle the case where the callee is Unknown.
+ assert (!L.isUnknown());
+
+ Nodify(Dst, CE, *DI, EvalCall(CE, cast<LVal>(L), (*DI)->getState()));
}
}
-void GRExprEngine::VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst) {
+void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
NodeSet S1;
- Visit(E, Pred, S1);
+ Visit(Ex, Pred, S1);
QualType T = CastE->getType();
// Check for redundant casts or casting to "void"
if (T->isVoidType() ||
- E->getType() == T ||
- (T->isPointerType() && E->getType()->isFunctionType())) {
+ Ex->getType() == T ||
+ (T->isPointerType() && Ex->getType()->isFunctionType())) {
- for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1)
+ for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1)
Dst.Add(*I1);
return;
}
- for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
+ for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
NodeTy* N = *I1;
StateTy St = N->getState();
- const RValue& V = GetValue(St, E);
- Nodify(Dst, CastE, N, SetValue(St, CastE, EvalCast(ValMgr, V, CastE)));
+ RVal V = GetRVal(St, Ex);
+ Nodify(Dst, CastE, N, SetRVal(St, CastE, EvalCast(ValMgr, V, CastE)));
}
}
void GRExprEngine::VisitDeclStmt(DeclStmt* DS, GRExprEngine::NodeTy* Pred,
- GRExprEngine::NodeSet& Dst) {
+ GRExprEngine::NodeSet& Dst) {
StateTy St = Pred->getState();
@@ -483,72 +493,80 @@
if (VD->getType()->isArrayType())
continue;
- const Expr* E = VD->getInit();
- St = SetValue(St, lval::DeclVal(VD),
- E ? GetValue(St, E) : UninitializedVal());
+ const Expr* Ex = VD->getInit();
+
+ St = SetRVal(St, lval::DeclVal(VD),
+ Ex ? GetRVal(St, Ex) : UninitializedVal());
}
Nodify(Dst, DS, Pred, St);
- if (Dst.empty())
- Dst.Add(Pred);
+ if (Dst.empty()) { Dst.Add(Pred); }
}
-void GRExprEngine::VisitGuardedExpr(Expr* S, Expr* LHS, Expr* RHS,
+void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
NodeTy* Pred, NodeSet& Dst) {
StateTy St = Pred->getState();
- RValue R = GetValue(St, LHS);
- if (isa<UnknownVal>(R)) R = GetValue(St, RHS);
+ RVal V = GetRVal(St, L);
+ if (isa<UnknownVal>(V)) V = GetRVal(St, R);
- Nodify(Dst, S, Pred, SetValue(St, S, R));
+ Nodify(Dst, Ex, Pred, SetRVal(St, Ex, V));
}
/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
-void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* S,
- NodeTy* Pred,
- NodeSet& Dst) {
+void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex,
+ NodeTy* Pred,
+ NodeSet& Dst) {
+
+ assert (Ex->isSizeOf() && "AlignOf(Expr) not yet implemented.");
// 6.5.3.4 sizeof: "The result type is an integer."
- QualType T = S->getArgumentType();
+ QualType T = Ex->getArgumentType();
+ // FIXME: Implement alignof
+ // FIXME: Add support for sizeof(void)
// FIXME: Add support for VLAs.
+
if (!T.getTypePtr()->isConstantSizeType())
return;
- SourceLocation L = S->getExprLoc();
- uint64_t size = getContext().getTypeSize(T, L) / 8;
+ SourceLocation Loc = Ex->getExprLoc();
+ uint64_t size = getContext().getTypeSize(T, Loc) / 8;
- Nodify(Dst, S, Pred,
- SetValue(Pred->getState(), S,
- NonLValue::GetValue(ValMgr, size, S->getType(), L)));
+ Nodify(Dst, Ex, Pred,
+ SetRVal(Pred->getState(), Ex,
+ NonLVal::MakeVal(ValMgr, size, Ex->getType(), Loc)));
}
void GRExprEngine::VisitDeref(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst) {
- Expr* E = U->getSubExpr()->IgnoreParens();
+ Expr* Ex = U->getSubExpr()->IgnoreParens();
NodeSet DstTmp;
- if (!isa<DeclRefExpr>(E))
+ if (!isa<DeclRefExpr>(Ex))
DstTmp.Add(Pred);
else
- Visit(E, Pred, DstTmp);
+ Visit(Ex, Pred, DstTmp);
- for (NodeSet::iterator I=DstTmp.begin(), DE=DstTmp.end(); I != DE; ++I) {
+ 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));
+ RVal V = GetRVal(St, Ex);
+
+ // Check for dereferences of uninitialized values.
- if (isa<UninitializedVal>(L)) {
+ if (V.isUninit()) {
+
NodeTy* Succ = Builder->generateNode(U, St, N);
if (Succ) {
@@ -559,7 +577,9 @@
continue;
}
- if (L.isUnknown()) {
+ // Check for dereferences of unknown values. Treat as No-Ops.
+
+ if (V.isUnknown()) {
Dst.Add(N);
continue;
}
@@ -570,48 +590,56 @@
//
// We add these assumptions.
+ LVal LV = cast<LVal>(V);
bool isFeasibleNotNull;
// "Assume" that the pointer is Not-NULL.
- StateTy StNotNull = Assume(St, L, true, isFeasibleNotNull);
+
+ StateTy StNotNull = Assume(St, LV, 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)));
+ Nodify(Dst, U, N, SetRVal(StNotNull, U,
+ GetRVal(StNotNull, LV, U->getType())));
}
bool isFeasibleNull;
- // "Assume" that the pointer is NULL.
- StateTy StNull = Assume(St, L, false, isFeasibleNull);
+ // Now "assume" that the pointer is NULL.
+
+ StateTy StNull = Assume(St, LV, 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);
+ if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode);
+ else ExplicitNullDeref.insert(NullNode);
}
}
}
}
-void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
- NodeTy* Pred, NodeSet& Dst) {
+void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
+ NodeSet& Dst) {
NodeSet S1;
assert (U->getOpcode() != UnaryOperator::Deref);
+ assert (U->getOpcode() != UnaryOperator::SizeOf);
+ assert (U->getOpcode() != UnaryOperator::AlignOf);
+
+ bool use_GetLVal = false;
switch (U->getOpcode()) {
case UnaryOperator::PostInc:
@@ -619,14 +647,9 @@
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);
+ // Evalue subexpression as an LVal.
+ use_GetLVal = true;
+ VisitLVal(U->getSubExpr(), Pred, S1);
break;
default:
@@ -634,29 +657,53 @@
break;
}
- for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
+ for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
NodeTy* N1 = *I1;
StateTy St = N1->getState();
+
+ RVal SubV = use_GetLVal ? GetLVal(St, U->getSubExpr()) :
+ GetRVal(St, U->getSubExpr());
+
+ if (SubV.isUnknown()) {
+ Dst.Add(N1);
+ continue;
+ }
+
+ if (SubV.isUninit()) {
+ Nodify(Dst, U, N1, SetRVal(St, U, SubV));
+ continue;
+ }
if (U->isIncrementDecrementOp()) {
// Handle ++ and -- (both pre- and post-increment).
- const LValue& L1 = GetLValue(St, U->getSubExpr());
- QualType T = U->getType();
- RValue R1 = GetValue(St, L1, &T);
+ LVal SubLV = cast<LVal>(SubV);
+ RVal V = GetRVal(St, SubLV, U->getType());
+
+ // An LVal should never bind to UnknownVal.
+ assert (!V.isUnknown());
+
+ // Propagate uninitialized values.
+ if (V.isUninit()) {
+ Nodify(Dst, U, N1, SetRVal(St, U, V));
+ continue;
+ }
+
+ // Handle all NonLVals.
BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
: BinaryOperator::Sub;
- RValue Result = EvalBinaryOp(Op, R1, GetRValueConstant(1U, U));
+ RVal Result = EvalBinOp(Op, cast<NonLVal>(V), MakeConstantVal(1U, U));
if (U->isPostfix())
- Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
+ St = SetRVal(SetRVal(St, U, V), SubLV, Result);
else
- Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
+ St = SetRVal(SetRVal(St, U, Result), SubLV, Result);
+ Nodify(Dst, U, N1, St);
continue;
}
@@ -664,104 +711,90 @@
switch (U->getOpcode()) {
- case UnaryOperator::Minus: {
- const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr()));
- Nodify(Dst, U, N1, SetValue(St, U, EvalMinus(ValMgr, U, R1)));
+ case UnaryOperator::Minus:
+ St = SetRVal(St, U, EvalMinus(U, cast<NonLVal>(SubV)));
break;
- }
- case UnaryOperator::Plus: {
- const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr()));
- Nodify(Dst, U, N1, SetValue(St, U, EvalPlus(ValMgr, U, R1)));
+ case UnaryOperator::Not:
+ St = SetRVal(St, U, EvalComplement(cast<NonLVal>(SubV)));
break;
- }
- case UnaryOperator::Not: {
- const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr()));
- Nodify(Dst, U, N1, SetValue(St, U, EvalComplement(ValMgr, R1)));
- break;
- }
+ case UnaryOperator::LNot:
- case UnaryOperator::LNot: {
// C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
//
// Note: technically we do "E == 0", but this is the same in the
// transfer functions as "0 == E".
-
- RValue V1 = GetValue(St, U->getSubExpr());
-
- if (isa<LValue>(V1)) {
- const LValue& L1 = cast<LValue>(V1);
- lval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
- Nodify(Dst, U, N1,
- SetValue(St, U, EvalBinaryOp(BinaryOperator::EQ,
- L1, V2)));
+
+ if (isa<LVal>(SubV)) {
+ lval::ConcreteInt V(ValMgr.getZeroWithPtrWidth());
+ RVal Result = EvalBinOp(BinaryOperator::EQ, cast<LVal>(SubV), V);
+ St = SetRVal(St, U, Result);
}
else {
- const NonLValue& R1 = cast<NonLValue>(V1);
- nonlval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
- Nodify(Dst, U, N1,
- SetValue(St, U, EvalBinaryOp(BinaryOperator::EQ,
- R1, V2)));
+ nonlval::ConcreteInt V(ValMgr.getZeroWithPtrWidth());
+ RVal Result = EvalBinOp(BinaryOperator::EQ, cast<NonLVal>(SubV), V);
+ St = SetRVal(St, U, Result);
}
break;
- }
-
- case UnaryOperator::SizeOf: {
- // 6.5.3.4 sizeof: "The result type is an integer."
-
- QualType T = U->getSubExpr()->getType();
-
- // FIXME: Add support for VLAs.
- if (!T.getTypePtr()->isConstantSizeType())
- return;
-
- SourceLocation L = U->getExprLoc();
- uint64_t size = getContext().getTypeSize(T, L) / 8;
-
- Nodify(Dst, U, N1,
- SetValue(St, U, NonLValue::GetValue(ValMgr, size,
- U->getType(), L)));
-
- break;
- }
case UnaryOperator::AddrOf: {
- const LValue& L1 = GetLValue(St, U->getSubExpr());
- Nodify(Dst, U, N1, SetValue(St, U, L1));
+ assert (isa<LVal>(SubV));
+ St = SetRVal(St, U, SubV);
break;
}
default: ;
assert (false && "Not implemented.");
- }
+ }
+
+ Nodify(Dst, U, N1, St);
}
}
-void GRExprEngine::VisitLValue(Expr* E, NodeTy* Pred, NodeSet& Dst) {
+void GRExprEngine::VisitSizeOfExpr(UnaryOperator* U, NodeTy* Pred,
+ NodeSet& Dst) {
+
+ QualType T = U->getSubExpr()->getType();
+
+ // FIXME: Add support for VLAs.
+ if (!T.getTypePtr()->isConstantSizeType())
+ return;
+
+ SourceLocation Loc = U->getExprLoc();
+ uint64_t size = getContext().getTypeSize(T, Loc) / 8;
+ StateTy St = Pred->getState();
+ St = SetRVal(St, U, NonLVal::MakeVal(ValMgr, size, U->getType(), Loc));
+
+ Nodify(Dst, U, Pred, St);
+}
+
+void GRExprEngine::VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
- E = E->IgnoreParens();
+ assert (Ex != CurrentStmt && !getCFG().isBlkExpr(Ex));
- if (isa<DeclRefExpr>(E)) {
+ Ex = Ex->IgnoreParens();
+
+ if (isa<DeclRefExpr>(Ex)) {
Dst.Add(Pred);
return;
}
- if (UnaryOperator* U = dyn_cast<UnaryOperator>(E)) {
+ if (UnaryOperator* U = dyn_cast<UnaryOperator>(Ex)) {
if (U->getOpcode() == UnaryOperator::Deref) {
- E = U->getSubExpr()->IgnoreParens();
+ Ex = U->getSubExpr()->IgnoreParens();
- if (isa<DeclRefExpr>(E))
+ if (isa<DeclRefExpr>(Ex))
Dst.Add(Pred);
else
- Visit(E, Pred, Dst);
+ Visit(Ex, Pred, Dst);
return;
}
}
- Visit(E, Pred, Dst);
+ Visit(Ex, Pred, Dst);
}
void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
@@ -770,119 +803,152 @@
NodeSet S1;
if (B->isAssignmentOp())
- VisitLValue(B->getLHS(), Pred, S1);
+ VisitLVal(B->getLHS(), Pred, S1);
else
Visit(B->getLHS(), Pred, S1);
for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
+
NodeTy* N1 = *I1;
// When getting the value for the LHS, check if we are in an assignment.
- // In such cases, we want to (initially) treat the LHS as an LValue,
- // so we use GetLValue instead of GetValue so that DeclRefExpr's are
- // evaluated to LValueDecl's instead of to an NonLValue.
- const RValue& V1 =
- B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
- : GetValue(N1->getState(), B->getLHS());
+ // In such cases, we want to (initially) treat the LHS as an LVal,
+ // so we use GetLVal instead of GetRVal so that DeclRefExpr's are
+ // evaluated to LValDecl's instead of to an NonLVal.
+
+ RVal LeftV = B->isAssignmentOp() ? GetLVal(N1->getState(), B->getLHS())
+ : GetRVal(N1->getState(), B->getLHS());
+
+ // Visit the RHS...
- NodeSet S2;
+ NodeSet S2;
Visit(B->getRHS(), N1, S2);
+
+ // Process the binary operator.
- for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
+ for (NodeSet::iterator I2 = S2.begin(), E2 = S2.end(); I2 != E2; ++I2) {
NodeTy* N2 = *I2;
- StateTy St = N2->getState();
- const RValue& V2 = GetValue(St, B->getRHS());
+ StateTy St = N2->getState();
+ RVal RightV = GetRVal(St, B->getRHS());
BinaryOperator::Opcode Op = B->getOpcode();
if (Op <= BinaryOperator::Or) {
- if (isa<UnknownVal>(V1) || isa<UninitializedVal>(V1)) {
- Nodify(Dst, B, N2, SetValue(St, B, V1));
+ // Process non-assignements except commas or short-circuited
+ // logical expressions (LAnd and LOr).
+
+ RVal Result = EvalBinOp(Op, LeftV, RightV);
+
+ if (Result.isUnknown()) {
+ Dst.Add(N2);
continue;
}
- Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(Op, V1, V2)));
+ Nodify(Dst, B, N2, SetRVal(St, B, Result));
continue;
-
}
-
- switch (Op) {
+
+ // Process assignments.
+
+ switch (Op) {
+
case BinaryOperator::Assign: {
- const LValue& L1 = cast<LValue>(V1);
+
+ // Simple assignments.
- if (isa<UninitializedVal>(L1))
+ if (LeftV.isUninit()) {
HandleUninitializedStore(B, N2);
- else
- Nodify(Dst, B, N2, SetValue(SetValue(St, B, V2), L1, V2));
+ continue;
+ }
+
+ if (LeftV.isUnknown()) {
+ St = SetRVal(St, B, RightV);
+ break;
+ }
+ St = SetRVal(SetRVal(St, B, RightV), cast<LVal>(LeftV), RightV);
break;
}
- default: { // Compound assignment operators.
+ // Compound assignment operators.
+
+ default: {
- assert (B->isCompoundAssignmentOp());
-
- const LValue& L1 = cast<LValue>(V1);
+ assert (B->isCompoundAssignmentOp());
- if (isa<UninitializedVal>(L1)) {
+ if (LeftV.isUninit()) {
HandleUninitializedStore(B, N2);
+ continue;
+ }
+
+ if (LeftV.isUnknown()) {
+
+ // While we do not know the location to store RightV,
+ // the entire expression does evaluate to RightV.
+
+ if (RightV.isUnknown()) {
+ Dst.Add(N2);
+ continue;
+ }
+
+ St = SetRVal(St, B, RightV);
break;
}
- if (isa<UninitializedVal>(V2)) {
- Nodify(Dst, B, N2, SetValue(SetValue(St, B, V2), L1, V2));
+ // At this pointer we know that the LHS evaluates to an LVal
+ // that is neither "Unknown" or "Unintialized."
+
+ LVal LeftLV = cast<LVal>(LeftV);
+
+ // Propagate uninitialized values (right-side).
+
+ if (RightV.isUninit()) {
+ St = SetRVal(SetRVal(St, B, RightV), LeftLV, RightV);
break;
}
- RValue Result = cast<NonLValue>(UnknownVal());
+ // Fetch the value of the LHS (the value of the variable, etc.).
+
+ RVal V = GetRVal(N1->getState(), LeftLV, B->getLHS()->getType());
+
+ // Propagate uninitialized value (left-side).
+
+ if (V.isUninit()) {
+ St = SetRVal(St, B, V);
+ break;
+ }
+
+ // Propagate unknown values.
+
+ assert (!V.isUnknown() &&
+ "An LVal should never bind to UnknownVal");
+
+ if (RightV.isUnknown()) {
+ St = SetRVal(SetRVal(St, LeftLV, RightV), B, RightV);
+ break;
+ }
+
+ // Neither the LHS or the RHS have Unknown/Uninit values. Process
+ // the operation and store the result.
if (Op >= BinaryOperator::AndAssign)
((int&) Op) -= (BinaryOperator::AndAssign - BinaryOperator::And);
else
((int&) Op) -= BinaryOperator::MulAssign;
- if (B->getType()->isPointerType()) { // Perform pointer arithmetic.
- const NonLValue& R2 = cast<NonLValue>(V2);
- 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(Op, L1, L2);
- }
- else {
- QualType T1 = B->getLHS()->getType();
- QualType T2 = B->getRHS()->getType();
-
- // An operation between two variables of a non-lvalue type.
- Result =
- EvalBinaryOp(Op,
- cast<NonLValue>(GetValue(N1->getState(), L1, &T1)),
- cast<NonLValue>(GetValue(N2->getState(), L2, &T2)));
- }
- }
- else { // Any other operation between two Non-LValues.
- QualType T = B->getLHS()->getType();
- const NonLValue& R1 = cast<NonLValue>(GetValue(N1->getState(),
- L1, &T));
- const NonLValue& R2 = cast<NonLValue>(V2);
- Result = EvalBinaryOp(Op, R1, R2);
- }
-
- Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
- break;
+ RVal Result = EvalBinOp(Op, V, RightV);
+ St = SetRVal(SetRVal(St, B, Result), LeftLV, Result);
}
}
+
+ Nodify(Dst, B, N2, St);
}
}
}
-void GRExprEngine::HandleUninitializedStore(Stmt* S, NodeTy* Pred) {
-
+void GRExprEngine::HandleUninitializedStore(Stmt* S, NodeTy* Pred) {
NodeTy* N = Builder->generateNode(S, Pred->getState(), Pred);
N->markAsSink();
UninitStores.insert(N);
@@ -917,7 +983,7 @@
}
else if (B->getOpcode() == BinaryOperator::Comma) {
StateTy St = Pred->getState();
- Nodify(Dst, B, Pred, SetValue(St, B, GetValue(St, B->getRHS())));
+ Nodify(Dst, B, Pred, SetRVal(St, B, GetRVal(St, B->getRHS())));
break;
}
@@ -944,12 +1010,15 @@
case Stmt::CharacterLiteralClass: {
CharacterLiteral* C = cast<CharacterLiteral>(S);
StateTy St = Pred->getState();
- NonLValue X = NonLValue::GetValue(ValMgr, C->getValue(), C->getType(),
+ NonLVal X = NonLVal::MakeVal(ValMgr, C->getValue(), C->getType(),
C->getLoc());
- Nodify(Dst, C, Pred, SetValue(St, C, X));
+ Nodify(Dst, C, Pred, SetRVal(St, C, X));
break;
}
+ // FIXME: ChooseExpr is really a constant. We need to fix
+ // the CFG do not model them as explicit control-flow.
+
case Stmt::ChooseExprClass: { // __builtin_choose_expr
ChooseExpr* C = cast<ChooseExpr>(S);
VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
@@ -981,8 +1050,8 @@
case Stmt::IntegerLiteralClass: {
StateTy St = Pred->getState();
IntegerLiteral* I = cast<IntegerLiteral>(S);
- NonLValue X = NonLValue::GetValue(ValMgr, I);
- Nodify(Dst, I, Pred, SetValue(St, I, X));
+ NonLVal X = NonLVal::MakeVal(ValMgr, I);
+ Nodify(Dst, I, Pred, SetRVal(St, I, X));
break;
}
@@ -1005,10 +1074,14 @@
StateTy St = Pred->getState();
Expr* LastExpr = cast<Expr>(*SE->getSubStmt()->body_rbegin());
- Nodify(Dst, SE, Pred, SetValue(St, SE, GetValue(St, LastExpr)));
+ Nodify(Dst, SE, Pred, SetRVal(St, SE, GetRVal(St, LastExpr)));
break;
}
+ // FIXME: We may wish to always bind state to ReturnStmts so
+ // that users can quickly query what was the state at the
+ // exit points of a function.
+
case Stmt::ReturnStmtClass: {
if (Expr* R = cast<ReturnStmt>(S)->getRetValue())
Visit(R, Pred, Dst);
@@ -1021,10 +1094,12 @@
case Stmt::UnaryOperatorClass: {
UnaryOperator* U = cast<UnaryOperator>(S);
- if (U->getOpcode() == UnaryOperator::Deref)
- VisitDeref(U, Pred, Dst);
- else
- VisitUnaryOperator(U, Pred, Dst);
+ switch (U->getOpcode()) {
+ case UnaryOperator::Deref: VisitDeref(U, Pred, Dst); break;
+ case UnaryOperator::Plus: Visit(U->getSubExpr(), Pred, Dst); break;
+ case UnaryOperator::SizeOf: VisitSizeOfExpr(U, Pred, Dst); break;
+ default: VisitUnaryOperator(U, Pred, Dst); break;
+ }
break;
}
@@ -1035,20 +1110,12 @@
// "Assume" logic.
//===----------------------------------------------------------------------===//
-GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, LValue Cond,
+GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, LVal Cond,
bool Assumption,
- bool& isFeasible) {
-
- assert (!isa<UninitializedVal>(Cond));
-
- if (isa<UnknownVal>(Cond)) {
- isFeasible = true;
- return St;
- }
-
+ bool& isFeasible) {
switch (Cond.getSubKind()) {
default:
- assert (false && "'Assume' not implemented for this LValue.");
+ assert (false && "'Assume' not implemented for this LVal.");
return St;
case lval::SymbolValKind:
@@ -1072,20 +1139,12 @@
}
}
-GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, NonLValue Cond,
+GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, NonLVal Cond,
bool Assumption,
- bool& isFeasible) {
-
- assert (!isa<UninitializedVal>(Cond));
-
- if (isa<UnknownVal>(Cond)) {
- isFeasible = true;
- return St;
- }
-
+ bool& isFeasible) {
switch (Cond.getSubKind()) {
default:
- assert (false && "'Assume' not implemented for this NonLValue.");
+ assert (false && "'Assume' not implemented for this NonLVal.");
return St;
@@ -1259,26 +1318,26 @@
}
static void PrintEQ(std::ostream& Out, GRExprEngine::StateTy St) {
- ValueState::ConstantEqTy CE = St.getImpl()->ConstantEq;
+ ValueState::ConstEqTy CE = St.getImpl()->ConstEq;
if (CE.isEmpty())
return;
Out << "\\l\\|'==' constraints:";
- for (ValueState::ConstantEqTy::iterator I=CE.begin(), E=CE.end(); I!=E;++I)
+ for (ValueState::ConstEqTy::iterator I=CE.begin(), E=CE.end(); I!=E;++I)
Out << "\\l $" << I.getKey() << " : " << I.getData()->toString();
}
static void PrintNE(std::ostream& Out, GRExprEngine::StateTy St) {
- ValueState::ConstantNotEqTy NE = St.getImpl()->ConstantNotEq;
+ ValueState::ConstNotEqTy NE = St.getImpl()->ConstNotEq;
if (NE.isEmpty())
return;
Out << "\\l\\|'!=' constraints:";
- for (ValueState::ConstantNotEqTy::iterator I=NE.begin(), EI=NE.end();
+ for (ValueState::ConstNotEqTy::iterator I=NE.begin(), EI=NE.end();
I != EI; ++I){
Out << "\\l $" << I.getKey() << " : ";
@@ -1340,7 +1399,7 @@
Out << "\\|Dereference of uninitialied value.\\l";
}
else if (GraphPrintCheckerState->isUninitStore(N)) {
- Out << "\\|Store to Uninitialized LValue.";
+ Out << "\\|Store to Uninitialized LVal.";
}
break;
Modified: cfe/trunk/Analysis/GRSimpleVals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRSimpleVals.cpp?rev=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRSimpleVals.cpp (original)
+++ cfe/trunk/Analysis/GRSimpleVals.cpp Thu Feb 21 12:02:17 2008
@@ -19,47 +19,46 @@
using namespace clang;
namespace clang {
- unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
- Diagnostic& Diag, bool Visualize) {
-
- if (Diag.hasErrorOccurred())
- return 0;
-
- GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
- GRExprEngine* CheckerState = &Engine.getCheckerState();
- GRSimpleVals GRSV;
- CheckerState->setTransferFunctions(GRSV);
+
+unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
+ Diagnostic& Diag, bool Visualize) {
+
+ if (Diag.hasErrorOccurred())
+ return 0;
+
+ GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
+ GRExprEngine* CheckerState = &Engine.getCheckerState();
+ GRSimpleVals GRSV;
+ CheckerState->setTransferFunctions(GRSV);
+
+ // Execute the worklist algorithm.
+ Engine.ExecuteWorkList(10000);
+
+ // Look for explicit-Null dereferences and warn about them.
+ for (GRExprEngine::null_iterator I=CheckerState->null_begin(),
+ E=CheckerState->null_end(); I!=E; ++I) {
- // Execute the worklist algorithm.
- Engine.ExecuteWorkList(10000);
+ const PostStmt& L = cast<PostStmt>((*I)->getLocation());
+ Expr* Exp = cast<Expr>(L.getStmt());
- // Look for explicit-Null dereferences and warn about them.
- for (GRExprEngine::null_iterator I=CheckerState->null_begin(),
- E=CheckerState->null_end(); I!=E; ++I) {
-
- const PostStmt& L = cast<PostStmt>((*I)->getLocation());
- Expr* Exp = cast<Expr>(L.getStmt());
+ Diag.Report(FullSourceLoc(Exp->getExprLoc(), Ctx.getSourceManager()),
+ diag::chkr_null_deref_after_check);
+ }
- Diag.Report(FullSourceLoc(Exp->getExprLoc(), Ctx.getSourceManager()),
- diag::chkr_null_deref_after_check);
- }
-
#ifndef NDEBUG
- if (Visualize) CheckerState->ViewGraph();
+ if (Visualize) CheckerState->ViewGraph();
#endif
-
- return Engine.getGraph().size();
- }
+
+ return Engine.getGraph().size();
+}
+
} // end clang namespace
//===----------------------------------------------------------------------===//
// Transfer function for Casts.
//===----------------------------------------------------------------------===//
-RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLValue X,
- Expr* CastExpr) {
-
- assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
+RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLVal X, Expr* CastExpr) {
if (!isa<nonlval::ConcreteInt>(X))
return UnknownVal();
@@ -77,10 +76,8 @@
// Casts.
-RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, LValue X, Expr* CastExpr) {
+RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, LVal X, Expr* CastExpr) {
- assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
-
if (CastExpr->getType()->isPointerType())
return X;
@@ -99,86 +96,65 @@
// Unary operators.
-NonLValue GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
- NonLValue X) {
-
- assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
+RVal GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U, NonLVal X){
switch (X.getSubKind()) {
+
case nonlval::ConcreteIntKind:
return cast<nonlval::ConcreteInt>(X).EvalMinus(ValMgr, U);
+
default:
- return cast<NonLValue>(UnknownVal());
- }
-}
-
-NonLValue GRSimpleVals::EvalPlus(ValueManager& ValMgr, UnaryOperator* U,
- NonLValue X) {
-
- assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
-
- switch (X.getSubKind()) {
- case nonlval::ConcreteIntKind:
- return cast<nonlval::ConcreteInt>(X).EvalPlus(ValMgr, U);
- default:
- return cast<NonLValue>(UnknownVal());
+ return UnknownVal();
}
}
+RVal GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLVal X) {
-NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) {
-
- assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
-
switch (X.getSubKind()) {
+
case nonlval::ConcreteIntKind:
return cast<nonlval::ConcreteInt>(X).EvalComplement(ValMgr);
+
default:
- return cast<NonLValue>(UnknownVal());
+ return UnknownVal();
}
}
// Binary operators.
-NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- NonLValue LHS, NonLValue RHS) {
-
- assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
- assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
-
- while(1) {
+RVal GRSimpleVals::EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ NonLVal L, NonLVal R) {
+ while (1) {
- switch (LHS.getSubKind()) {
+ switch (L.getSubKind()) {
default:
- return cast<NonLValue>(UnknownVal());
+ return cast<NonLVal>(UnknownVal());
case nonlval::ConcreteIntKind:
- if (isa<nonlval::ConcreteInt>(RHS)) {
- const nonlval::ConcreteInt& LHS_CI = cast<nonlval::ConcreteInt>(LHS);
- const nonlval::ConcreteInt& RHS_CI = cast<nonlval::ConcreteInt>(RHS);
- return LHS_CI.EvalBinaryOp(ValMgr, Op, RHS_CI);
+ if (isa<nonlval::ConcreteInt>(R)) {
+ const nonlval::ConcreteInt& L_CI = cast<nonlval::ConcreteInt>(L);
+ const nonlval::ConcreteInt& R_CI = cast<nonlval::ConcreteInt>(R);
+ return L_CI.EvalBinOp(ValMgr, Op, R_CI);
}
- else if(isa<UnknownVal>(RHS))
- return cast<NonLValue>(UnknownVal());
else {
- NonLValue tmp = RHS;
- RHS = LHS;
- LHS = tmp;
+ NonLVal tmp = R;
+ R = L;
+ L = tmp;
continue;
}
case nonlval::SymbolValKind: {
- if (isa<nonlval::ConcreteInt>(RHS)) {
+
+ if (isa<nonlval::ConcreteInt>(R)) {
const SymIntConstraint& C =
- ValMgr.getConstraint(cast<nonlval::SymbolVal>(LHS).getSymbol(), Op,
- cast<nonlval::ConcreteInt>(RHS).getValue());
+ ValMgr.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
+ cast<nonlval::ConcreteInt>(R).getValue());
return nonlval::SymIntConstraintVal(C);
}
else
- return cast<NonLValue>(UnknownVal());
+ return UnknownVal();
}
}
}
@@ -187,150 +163,140 @@
// Binary Operators (except assignments and comma).
-RValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- LValue LHS, LValue RHS) {
-
- assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
- assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
+RVal GRSimpleVals::EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ LVal L, LVal R) {
switch (Op) {
+
default:
return UnknownVal();
case BinaryOperator::EQ:
- return EvalEQ(ValMgr, LHS, RHS);
+ return EvalEQ(ValMgr, L, R);
case BinaryOperator::NE:
- return EvalNE(ValMgr, LHS, RHS);
+ return EvalNE(ValMgr, L, R);
}
}
// Pointer arithmetic.
-LValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- LValue LHS, NonLValue RHS) {
-
- assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
- assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
-
- return cast<LValue>(UnknownVal());
+RVal GRSimpleVals::EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ LVal L, NonLVal R) {
+ return UnknownVal();
}
-// Equality operators for LValues.
-
+// Equality operators for LVals.
-NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
+RVal GRSimpleVals::EvalEQ(ValueManager& ValMgr, LVal L, LVal R) {
- assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
- assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
-
- switch (LHS.getSubKind()) {
+ switch (L.getSubKind()) {
+
default:
- assert(false && "EQ not implemented for this LValue.");
- return cast<NonLValue>(UnknownVal());
+ assert(false && "EQ not implemented for this LVal.");
+ return UnknownVal();
case lval::ConcreteIntKind:
- if (isa<lval::ConcreteInt>(RHS)) {
- bool b = cast<lval::ConcreteInt>(LHS).getValue() ==
- cast<lval::ConcreteInt>(RHS).getValue();
+
+ if (isa<lval::ConcreteInt>(R)) {
+ bool b = cast<lval::ConcreteInt>(L).getValue() ==
+ cast<lval::ConcreteInt>(R).getValue();
- return NonLValue::GetIntTruthValue(ValMgr, b);
+ return NonLVal::MakeIntTruthVal(ValMgr, b);
}
- else if (isa<lval::SymbolVal>(RHS)) {
+ else if (isa<lval::SymbolVal>(R)) {
const SymIntConstraint& C =
- ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
+ ValMgr.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
BinaryOperator::EQ,
- cast<lval::ConcreteInt>(LHS).getValue());
+ cast<lval::ConcreteInt>(L).getValue());
return nonlval::SymIntConstraintVal(C);
}
break;
- case lval::SymbolValKind: {
- if (isa<lval::ConcreteInt>(RHS)) {
- const SymIntConstraint& C =
- ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
- BinaryOperator::EQ,
- cast<lval::ConcreteInt>(RHS).getValue());
-
- return nonlval::SymIntConstraintVal(C);
- }
-
- // FIXME: Implement unification
- return cast<NonLValue>(UnknownVal());
- //assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
+ case lval::SymbolValKind: {
+
+ if (isa<lval::ConcreteInt>(R)) {
+ const SymIntConstraint& C =
+ ValMgr.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
+ BinaryOperator::EQ,
+ cast<lval::ConcreteInt>(R).getValue());
- break;
+ return nonlval::SymIntConstraintVal(C);
}
- case lval::DeclValKind:
+ // FIXME: Implement unification
+ return cast<NonLVal>(UnknownVal());
+ //assert (!isa<lval::SymbolVal>(R) && "FIXME: Implement unification.");
- if (isa<lval::DeclVal>(RHS)) {
- bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
- return NonLValue::GetIntTruthValue(ValMgr, b);
- }
+ break;
+ }
- break;
+ case lval::DeclValKind:
+
+ if (isa<lval::DeclVal>(R)) {
+ bool b = cast<lval::DeclVal>(L) == cast<lval::DeclVal>(R);
+ return NonLVal::MakeIntTruthVal(ValMgr, b);
+ }
+
+ break;
}
- return NonLValue::GetIntTruthValue(ValMgr, false);
+ return NonLVal::MakeIntTruthVal(ValMgr, false);
}
-NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) {
+RVal GRSimpleVals::EvalNE(ValueManager& ValMgr, LVal L, LVal R) {
- assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
- assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
+ switch (L.getSubKind()) {
- switch (LHS.getSubKind()) {
default:
- assert(false && "NE not implemented for this LValue.");
- return cast<NonLValue>(UnknownVal());
+ assert(false && "NE not implemented for this LVal.");
+ return UnknownVal();
case lval::ConcreteIntKind:
- if (isa<lval::ConcreteInt>(RHS)) {
- bool b = cast<lval::ConcreteInt>(LHS).getValue() !=
- cast<lval::ConcreteInt>(RHS).getValue();
+
+ if (isa<lval::ConcreteInt>(R)) {
+ bool b = cast<lval::ConcreteInt>(L).getValue() !=
+ cast<lval::ConcreteInt>(R).getValue();
- return NonLValue::GetIntTruthValue(ValMgr, b);
+ return NonLVal::MakeIntTruthVal(ValMgr, b);
}
- else if (isa<lval::SymbolVal>(RHS)) {
+ else if (isa<lval::SymbolVal>(R)) {
const SymIntConstraint& C =
- ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
+ ValMgr.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
BinaryOperator::NE,
- cast<lval::ConcreteInt>(LHS).getValue());
+ cast<lval::ConcreteInt>(L).getValue());
return nonlval::SymIntConstraintVal(C);
}
break;
- case lval::SymbolValKind: {
- if (isa<lval::ConcreteInt>(RHS)) {
- const SymIntConstraint& C =
- ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
- BinaryOperator::NE,
- cast<lval::ConcreteInt>(RHS).getValue());
-
- return nonlval::SymIntConstraintVal(C);
- }
-
- assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement sym !=.");
+ case lval::SymbolValKind: {
+ if (isa<lval::ConcreteInt>(R)) {
+ const SymIntConstraint& C =
+ ValMgr.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
+ BinaryOperator::NE,
+ cast<lval::ConcreteInt>(R).getValue());
- break;
+ return nonlval::SymIntConstraintVal(C);
}
- case lval::DeclValKind:
- if (isa<lval::DeclVal>(RHS)) {
- bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
- return NonLValue::GetIntTruthValue(ValMgr, b);
- }
+ assert (!isa<lval::SymbolVal>(R) && "FIXME: Implement sym !=.");
break;
+ }
+
+ case lval::DeclValKind:
+ if (isa<lval::DeclVal>(R)) {
+ bool b = cast<lval::DeclVal>(L) == cast<lval::DeclVal>(R);
+ return NonLVal::MakeIntTruthVal(ValMgr, b);
+ }
+
+ break;
}
- return NonLValue::GetIntTruthValue(ValMgr, true);
+ return NonLVal::MakeIntTruthVal(ValMgr, true);
}
Modified: cfe/trunk/Analysis/GRSimpleVals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRSimpleVals.h?rev=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRSimpleVals.h (original)
+++ cfe/trunk/Analysis/GRSimpleVals.h Thu Feb 21 12:02:17 2008
@@ -28,40 +28,35 @@
// Casts.
- virtual RValue EvalCast(ValueManager& ValMgr, NonLValue V, Expr* CastExpr);
- virtual RValue EvalCast(ValueManager& ValMgr, LValue V, Expr* CastExpr);
+ virtual RVal EvalCast(ValueManager& ValMgr, NonLVal V, Expr* CastExpr);
+ virtual RVal EvalCast(ValueManager& ValMgr, LVal V, Expr* CastExpr);
// Unary Operators.
- virtual NonLValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
- NonLValue X);
-
- virtual NonLValue EvalPlus(ValueManager& ValMgr, UnaryOperator* U,
- NonLValue X);
-
- virtual NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X);
+ virtual RVal EvalMinus(ValueManager& ValMgr, UnaryOperator* U, NonLVal X);
+
+ virtual RVal EvalComplement(ValueManager& ValMgr, NonLVal X);
// Binary Operators.
- virtual NonLValue EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- NonLValue LHS, NonLValue RHS);
-
- virtual RValue EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- LValue LHS, LValue RHS);
+ virtual RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ NonLVal L, NonLVal R);
+
+ virtual RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ LVal L, LVal R);
// Pointer arithmetic.
- virtual LValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
- LValue LHS, NonLValue RHS);
+ virtual RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ LVal L, NonLVal R);
protected:
- // Equality operators for LValues.
- NonLValue EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS);
- NonLValue EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS);
-};
+ // Equality operators for LVals.
+
+ RVal EvalEQ(ValueManager& ValMgr, LVal L, LVal R);
+ RVal EvalNE(ValueManager& ValMgr, LVal L, LVal R);
+};
} // end clang namespace
Modified: cfe/trunk/Analysis/GRTransferFuncs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRTransferFuncs.cpp?rev=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRTransferFuncs.cpp (original)
+++ cfe/trunk/Analysis/GRTransferFuncs.cpp Thu Feb 21 12:02:17 2008
@@ -20,21 +20,21 @@
// Transfer function for Casts.
//===----------------------------------------------------------------------===//
-RValue GRTransferFuncs::EvalCast(ValueManager& ValMgr, RValue X,
- Expr* CastExpr) {
+RVal GRTransferFuncs::EvalCast(ValueManager& ValMgr, RVal X, Expr* CastExpr) {
switch (X.getBaseKind()) {
+
default:
- assert(false && "Invalid RValue."); break;
+ assert(false && "Invalid RVal."); break;
- case RValue::LValueKind:
- return EvalCast(ValMgr, cast<LValue>(X), CastExpr);
+ case RVal::LValKind:
+ return EvalCast(ValMgr, cast<LVal>(X), CastExpr);
- case RValue::NonLValueKind:
- return EvalCast(ValMgr, cast<NonLValue>(X), CastExpr);
+ case RVal::NonLValKind:
+ return EvalCast(ValMgr, cast<NonLVal>(X), CastExpr);
- case RValue::UninitializedKind:
- case RValue::UnknownKind: break;
+ case RVal::UninitializedKind:
+ case RVal::UnknownKind: break;
}
return X;
Modified: cfe/trunk/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.cpp?rev=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (original)
+++ cfe/trunk/Analysis/RValues.cpp Thu Feb 21 12:02:17 2008
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This files defines RValue, LValue, and NonLValue, classes that represent
+// This files defines RVal, LVal, and NonLVal, classes that represent
// abstract r-values for use with path-sensitive value tracking.
//
//===----------------------------------------------------------------------===//
@@ -24,45 +24,40 @@
// Symbol Iteration.
//===----------------------------------------------------------------------===//
-RValue::symbol_iterator RValue::symbol_begin() const {
- if (isa<LValue>(this)) {
- if (isa<lval::SymbolVal>(this))
- return (symbol_iterator) (&Data);
- }
- else {
- if (isa<nonlval::SymbolVal>(this))
- return (symbol_iterator) (&Data);
- else if (isa<nonlval::SymIntConstraintVal>(this)) {
- const SymIntConstraint& C =
- cast<nonlval::SymIntConstraintVal>(this)->getConstraint();
- return (symbol_iterator) &C.getSymbol();
- }
+RVal::symbol_iterator RVal::symbol_begin() const {
+ if (isa<lval::SymbolVal>(this))
+ return (symbol_iterator) (&Data);
+ else if (isa<nonlval::SymbolVal>(this))
+ return (symbol_iterator) (&Data);
+ else if (isa<nonlval::SymIntConstraintVal>(this)) {
+ const SymIntConstraint& C =
+ cast<nonlval::SymIntConstraintVal>(this)->getConstraint();
+
+ return (symbol_iterator) &C.getSymbol();
}
return NULL;
}
-RValue::symbol_iterator RValue::symbol_end() const {
+RVal::symbol_iterator RVal::symbol_end() const {
symbol_iterator X = symbol_begin();
return X ? X+1 : NULL;
}
//===----------------------------------------------------------------------===//
-// Transfer function dispatch for Non-LValues.
+// Transfer function dispatch for Non-LVals.
//===----------------------------------------------------------------------===//
nonlval::ConcreteInt
-nonlval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- const nonlval::ConcreteInt& RHS) const {
-
- return ValMgr.EvaluateAPSInt(Op, getValue(), RHS.getValue());
+nonlval::ConcreteInt::EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ const nonlval::ConcreteInt& R) const {
+
+ return ValMgr.EvaluateAPSInt(Op, getValue(), R.getValue());
}
// Bitwise-Complement.
-
nonlval::ConcreteInt
nonlval::ConcreteInt::EvalComplement(ValueManager& ValMgr) const {
return ValMgr.getValue(~getValue());
@@ -77,47 +72,40 @@
return ValMgr.getValue(-getValue());
}
-nonlval::ConcreteInt
-nonlval::ConcreteInt::EvalPlus(ValueManager& ValMgr, UnaryOperator* U) const {
- assert (U->getType() == U->getSubExpr()->getType());
- assert (U->getType()->isIntegerType());
- return ValMgr.getValue(getValue());
-}
-
//===----------------------------------------------------------------------===//
-// Transfer function dispatch for LValues.
+// Transfer function dispatch for LVals.
//===----------------------------------------------------------------------===//
lval::ConcreteInt
-lval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- const lval::ConcreteInt& RHS) const {
+lval::ConcreteInt::EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ const lval::ConcreteInt& R) const {
assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
(Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
- return ValMgr.EvaluateAPSInt(Op, getValue(), RHS.getValue());
+ return ValMgr.EvaluateAPSInt(Op, getValue(), R.getValue());
}
-NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const {
+NonLVal LVal::EQ(ValueManager& ValMgr, const LVal& R) const {
+
switch (getSubKind()) {
default:
- assert(false && "EQ not implemented for this LValue.");
- return cast<NonLValue>(UnknownVal());
+ assert(false && "EQ not implemented for this LVal.");
+ break;
case lval::ConcreteIntKind:
- if (isa<lval::ConcreteInt>(RHS)) {
+ if (isa<lval::ConcreteInt>(R)) {
bool b = cast<lval::ConcreteInt>(this)->getValue() ==
- cast<lval::ConcreteInt>(RHS).getValue();
+ cast<lval::ConcreteInt>(R).getValue();
- return NonLValue::GetIntTruthValue(ValMgr, b);
+ return NonLVal::MakeIntTruthVal(ValMgr, b);
}
- else if (isa<lval::SymbolVal>(RHS)) {
+ else if (isa<lval::SymbolVal>(R)) {
const SymIntConstraint& C =
- ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
- BinaryOperator::EQ,
- cast<lval::ConcreteInt>(this)->getValue());
+ ValMgr.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
+ BinaryOperator::EQ,
+ cast<lval::ConcreteInt>(this)->getValue());
return nonlval::SymIntConstraintVal(C);
}
@@ -125,50 +113,50 @@
break;
case lval::SymbolValKind: {
- if (isa<lval::ConcreteInt>(RHS)) {
+ if (isa<lval::ConcreteInt>(R)) {
const SymIntConstraint& C =
- ValMgr.getConstraint(cast<lval::SymbolVal>(this)->getSymbol(),
- BinaryOperator::EQ,
- cast<lval::ConcreteInt>(RHS).getValue());
+ ValMgr.getConstraint(cast<lval::SymbolVal>(this)->getSymbol(),
+ BinaryOperator::EQ,
+ cast<lval::ConcreteInt>(R).getValue());
return nonlval::SymIntConstraintVal(C);
}
- assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
+ assert (!isa<lval::SymbolVal>(R) && "FIXME: Implement unification.");
break;
}
case lval::DeclValKind:
- if (isa<lval::DeclVal>(RHS)) {
- bool b = cast<lval::DeclVal>(*this) == cast<lval::DeclVal>(RHS);
- return NonLValue::GetIntTruthValue(ValMgr, b);
+ if (isa<lval::DeclVal>(R)) {
+ bool b = cast<lval::DeclVal>(*this) == cast<lval::DeclVal>(R);
+ return NonLVal::MakeIntTruthVal(ValMgr, b);
}
break;
}
- return NonLValue::GetIntTruthValue(ValMgr, false);
+ return NonLVal::MakeIntTruthVal(ValMgr, false);
}
-NonLValue LValue::NE(ValueManager& ValMgr, const LValue& RHS) const {
+NonLVal LVal::NE(ValueManager& ValMgr, const LVal& R) const {
switch (getSubKind()) {
default:
- assert(false && "NE not implemented for this LValue.");
- return cast<NonLValue>(UnknownVal());
+ assert(false && "NE not implemented for this LVal.");
+ break;
case lval::ConcreteIntKind:
- if (isa<lval::ConcreteInt>(RHS)) {
+ if (isa<lval::ConcreteInt>(R)) {
bool b = cast<lval::ConcreteInt>(this)->getValue() !=
- cast<lval::ConcreteInt>(RHS).getValue();
+ cast<lval::ConcreteInt>(R).getValue();
- return NonLValue::GetIntTruthValue(ValMgr, b);
+ return NonLVal::MakeIntTruthVal(ValMgr, b);
}
- else if (isa<lval::SymbolVal>(RHS)) {
+ else if (isa<lval::SymbolVal>(R)) {
const SymIntConstraint& C =
- ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
+ ValMgr.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
BinaryOperator::NE,
cast<lval::ConcreteInt>(this)->getValue());
@@ -178,55 +166,56 @@
break;
case lval::SymbolValKind: {
- if (isa<lval::ConcreteInt>(RHS)) {
+ if (isa<lval::ConcreteInt>(R)) {
const SymIntConstraint& C =
ValMgr.getConstraint(cast<lval::SymbolVal>(this)->getSymbol(),
BinaryOperator::NE,
- cast<lval::ConcreteInt>(RHS).getValue());
+ cast<lval::ConcreteInt>(R).getValue());
return nonlval::SymIntConstraintVal(C);
}
- assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement sym !=.");
+ assert (!isa<lval::SymbolVal>(R) && "FIXME: Implement sym !=.");
break;
}
case lval::DeclValKind:
- if (isa<lval::DeclVal>(RHS)) {
- bool b = cast<lval::DeclVal>(*this) == cast<lval::DeclVal>(RHS);
- return NonLValue::GetIntTruthValue(ValMgr, b);
- }
+ if (isa<lval::DeclVal>(R)) {
+ bool b = cast<lval::DeclVal>(*this) == cast<lval::DeclVal>(R);
+ return NonLVal::MakeIntTruthVal(ValMgr, b);
+ }
- break;
+ break;
}
- return NonLValue::GetIntTruthValue(ValMgr, true);
+ return NonLVal::MakeIntTruthVal(ValMgr, true);
}
-
-
//===----------------------------------------------------------------------===//
-// Utility methods for constructing Non-LValues.
+// Utility methods for constructing Non-LVals.
//===----------------------------------------------------------------------===//
-NonLValue NonLValue::GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
- SourceLocation Loc) {
-
+NonLVal NonLVal::MakeVal(ValueManager& ValMgr, uint64_t X, QualType T,
+ SourceLocation Loc) {
+
return nonlval::ConcreteInt(ValMgr.getValue(X, T, Loc));
}
-NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) {
+NonLVal NonLVal::MakeVal(ValueManager& ValMgr, IntegerLiteral* I) {
+
return nonlval::ConcreteInt(ValMgr.getValue(APSInt(I->getValue(),
- I->getType()->isUnsignedIntegerType())));
+ I->getType()->isUnsignedIntegerType())));
}
-NonLValue NonLValue::GetIntTruthValue(ValueManager& ValMgr, bool b) {
+NonLVal NonLVal::MakeIntTruthVal(ValueManager& ValMgr, bool b) {
+
return nonlval::ConcreteInt(ValMgr.getTruthValue(b));
}
-RValue RValue::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) {
+RVal RVal::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) {
+
QualType T = D->getType();
if (T->isPointerType() || T->isReferenceType())
@@ -236,68 +225,66 @@
}
//===----------------------------------------------------------------------===//
-// Utility methods for constructing LValues.
+// Utility methods for constructing LVals.
//===----------------------------------------------------------------------===//
-LValue LValue::GetValue(AddrLabelExpr* E) {
- return lval::GotoLabel(E->getLabel());
-}
+LVal LVal::MakeVal(AddrLabelExpr* E) { return lval::GotoLabel(E->getLabel()); }
//===----------------------------------------------------------------------===//
// Pretty-Printing.
//===----------------------------------------------------------------------===//
-void RValue::printStdErr() const {
- print(*llvm::cerr.stream());
-}
+void RVal::printStdErr() const { print(*llvm::cerr.stream()); }
+
+void RVal::print(std::ostream& Out) const {
-void RValue::print(std::ostream& Out) const {
switch (getBaseKind()) {
+
case UnknownKind:
- Out << "Invalid";
- break;
+ Out << "Invalid"; break;
- case NonLValueKind:
- cast<NonLValue>(this)->print(Out);
- break;
+ case NonLValKind:
+ cast<NonLVal>(this)->print(Out); break;
- case LValueKind:
- cast<LValue>(this)->print(Out);
- break;
+ case LValKind:
+ cast<LVal>(this)->print(Out); break;
case UninitializedKind:
- Out << "Uninitialized";
- break;
+ Out << "Uninitialized"; break;
default:
- assert (false && "Invalid RValue.");
+ assert (false && "Invalid RVal.");
}
}
static void printOpcode(std::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;
+
+ 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;
+ 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 NonLValue::print(std::ostream& Out) const {
+void NonLVal::print(std::ostream& Out) const {
+
switch (getSubKind()) {
+
case nonlval::ConcreteIntKind:
Out << cast<nonlval::ConcreteInt>(this)->getValue().toString();
@@ -325,17 +312,18 @@
}
default:
- assert (false && "Pretty-printed not implemented for this NonLValue.");
+ assert (false && "Pretty-printed not implemented for this NonLVal.");
break;
}
}
-
-void LValue::print(std::ostream& Out) const {
+void LVal::print(std::ostream& Out) const {
+
switch (getSubKind()) {
+
case lval::ConcreteIntKind:
Out << cast<lval::ConcreteInt>(this)->getValue().toString()
- << " (LValue)";
+ << " (LVal)";
break;
case lval::SymbolValKind:
@@ -358,8 +346,7 @@
break;
default:
- assert (false && "Pretty-printed not implemented for this LValue.");
+ assert (false && "Pretty-printing not implemented for this LVal.");
break;
}
}
-
Modified: cfe/trunk/Analysis/ValueState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.cpp?rev=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/Analysis/ValueState.cpp (original)
+++ cfe/trunk/Analysis/ValueState.cpp Thu Feb 21 12:02:17 2008
@@ -17,18 +17,16 @@
using namespace clang;
bool ValueState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const {
- // First, retrieve the NE-set associated with the given symbol.
- ConstantNotEqTy::TreeTy* T = Data->ConstantNotEq.SlimFind(sym);
-
- if (!T)
- return false;
-
- // Second, see if V is present in the NE-set.
- return T->getValue().second.contains(&V);
+
+ // Retrieve the NE-set associated with the given symbol.
+ ConstNotEqTy::TreeTy* T = Data->ConstNotEq.SlimFind(sym);
+
+ // See if V is present in the NE-set.
+ return T ? T->getValue().second.contains(&V) : false;
}
const llvm::APSInt* ValueState::getSymVal(SymbolID sym) const {
- ConstantEqTy::TreeTy* T = Data->ConstantEq.SlimFind(sym);
+ ConstEqTy::TreeTy* T = Data->ConstEq.SlimFind(sym);
return T ? T->getValue().second : NULL;
}
@@ -53,21 +51,23 @@
NewSt.SubExprBindings = EXFactory.GetEmptyMap();
// Iterate over the block-expr bindings.
- for (ValueState::beb_iterator I=St.beb_begin(), E=St.beb_end(); I!=E ; ++I) {
-
+
+ for (ValueState::beb_iterator I = St.beb_begin(), E = St.beb_end();
+ I!=E ; ++I) {
Expr* BlkExpr = I.getKey();
if (Liveness.isLive(Loc, BlkExpr)) {
- RValue X = I.getData();
+ RVal X = I.getData();
if (isa<lval::DeclVal>(X)) {
lval::DeclVal LV = cast<lval::DeclVal>(X);
WList.push_back(LV.getDecl());
}
- for (RValue::symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end();
- SI != SE; ++SI)
- MarkedSymbols.insert(*SI);
+ for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
+ SI != SE; ++SI) {
+ MarkedSymbols.insert(*SI);
+ }
}
else
NewSt.BlockExprBindings = Remove(NewSt, BlkExpr);
@@ -76,12 +76,15 @@
}
// Iterate over the variable bindings.
+
for (ValueState::vb_iterator I = St.vb_begin(), E = St.vb_end(); I!=E ; ++I)
if (Liveness.isLive(Loc, I.getKey()))
WList.push_back(I.getKey());
-
+ // Perform the mark-and-sweep.
+
while (!WList.empty()) {
+
ValueDecl* V = WList.back();
WList.pop_back();
@@ -91,12 +94,13 @@
Marked.insert(V);
if (V->getType()->isPointerType()) {
- const LValue& LV =
- cast<LValue>(GetValue(St, lval::DeclVal(cast<VarDecl>(V))));
+ const LVal& LV =
+ cast<LVal>(GetRVal(St, lval::DeclVal(cast<VarDecl>(V))));
- for (RValue::symbol_iterator SI=LV.symbol_begin(), SE=LV.symbol_end();
- SI != SE; ++SI)
- MarkedSymbols.insert(*SI);
+ for (RVal::symbol_iterator SI = LV.symbol_begin(), SE = LV.symbol_end();
+ SI != SE; ++SI) {
+ MarkedSymbols.insert(*SI);
+ }
if (!isa<lval::DeclVal>(LV))
continue;
@@ -114,18 +118,18 @@
// Remove dead symbols.
for (ValueState::ce_iterator I = St.ce_begin(), E=St.ce_end(); I!=E; ++I)
if (!MarkedSymbols.count(I.getKey()))
- NewSt.ConstantEq = CEFactory.Remove(NewSt.ConstantEq, I.getKey());
+ NewSt.ConstEq = CEFactory.Remove(NewSt.ConstEq, I.getKey());
for (ValueState::cne_iterator I = St.cne_begin(), E=St.cne_end(); I!=E; ++I)
if (!MarkedSymbols.count(I.getKey()))
- NewSt.ConstantNotEq = CNEFactory.Remove(NewSt.ConstantNotEq, I.getKey());
+ NewSt.ConstNotEq = CNEFactory.Remove(NewSt.ConstNotEq, I.getKey());
return getPersistentState(NewSt);
}
-RValue ValueStateManager::GetValue(ValueState St, const LValue& LV,
- QualType* T) {
+RVal ValueStateManager::GetRVal(ValueState St, const LVal& LV, QualType T) {
+
if (isa<UnknownVal>(LV))
return UnknownVal();
@@ -134,27 +138,25 @@
switch (LV.getSubKind()) {
case lval::DeclValKind: {
ValueState::VarBindingsTy::TreeTy* T =
- // FIXME: We should make lval::DeclVal only contain VarDecl
- St->VarBindings.SlimFind(
- cast<VarDecl>(cast<lval::DeclVal>(LV).getDecl()));
+ St->VarBindings.SlimFind(cast<lval::DeclVal>(LV).getDecl());
return T ? T->getValue().second : UnknownVal();
}
- // FIXME: We should bind how far a "ContentsOf" will go...
+ // FIXME: We should limit how far a "ContentsOf" will go...
case lval::SymbolValKind: {
const lval::SymbolVal& SV = cast<lval::SymbolVal>(LV);
- assert (T);
+ assert (T.getTypePtr());
- if (T->getTypePtr()->isPointerType())
+ if (T.getTypePtr()->isPointerType())
return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
else
return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
}
default:
- assert (false && "Invalid LValue.");
+ assert (false && "Invalid LVal.");
break;
}
@@ -163,18 +165,17 @@
ValueState
ValueStateManager::AddNE(ValueState St, SymbolID sym, const llvm::APSInt& V) {
+
// First, retrieve the NE-set associated with the given symbol.
- ValueState::ConstantNotEqTy::TreeTy* T = St->ConstantNotEq.SlimFind(sym);
-
+ ValueState::ConstNotEqTy::TreeTy* T = St->ConstNotEq.SlimFind(sym);
ValueState::IntSetTy S = T ? T->getValue().second : ISetFactory.GetEmptySet();
- // Now add V to the NE set.
+ // Now add V to the NE set.
S = ISetFactory.Add(S, &V);
// Create a new state with the old binding replaced.
ValueStateImpl NewSt = *St;
- NewSt.ConstantNotEq = CNEFactory.Add(NewSt.ConstantNotEq,
- sym, S);
+ NewSt.ConstNotEq = CNEFactory.Add(NewSt.ConstNotEq, sym, S);
// Get the persistent copy.
return getPersistentState(NewSt);
@@ -182,43 +183,49 @@
ValueState
ValueStateManager::AddEQ(ValueState St, SymbolID sym, const llvm::APSInt& V) {
+
// Create a new state with the old binding replaced.
ValueStateImpl NewSt = *St;
- NewSt.ConstantEq = CEFactory.Add(NewSt.ConstantEq, sym, &V);
+ NewSt.ConstEq = CEFactory.Add(NewSt.ConstEq, sym, &V);
// Get the persistent copy.
return getPersistentState(NewSt);
}
-RValue ValueStateManager::GetValue(ValueState St, Expr* E, bool* hasVal) {
+RVal ValueStateManager::GetRVal(ValueState St, Expr* E, bool* hasVal) {
+
for (;;) {
+
switch (E->getStmtClass()) {
- case Stmt::AddrLabelExprClass:
- return LValue::GetValue(cast<AddrLabelExpr>(E));
+ case Stmt::AddrLabelExprClass:
+ return LVal::MakeVal(cast<AddrLabelExpr>(E));
// ParenExprs are no-ops.
- case Stmt::ParenExprClass:
+ case Stmt::ParenExprClass:
E = cast<ParenExpr>(E)->getSubExpr();
continue;
- // DeclRefExprs can either evaluate to an LValue or a Non-LValue
+ // DeclRefExprs can either evaluate to an LVal or a Non-LVal
// (assuming an implicit "load") depending on the context. In this
// context we assume that we are retrieving the value contained
// within the referenced variables.
case Stmt::DeclRefExprClass: {
+
ValueDecl* D = cast<DeclRefExpr>(E)->getDecl();
- if (VarDecl* VD = dyn_cast<VarDecl>(D))
- return GetValue(St, lval::DeclVal(VD));
+ if (VarDecl* VD = dyn_cast<VarDecl>(D)) {
+ return GetRVal(St, lval::DeclVal(VD));
+ }
else if (EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
+
// FIXME: Do we need to cache a copy of this enum, since it
// already has persistent storage? We do this because we
// are comparing states using pointer equality. Perhaps there is
// a better way, since APInts are fairly lightweight.
- return nonlval::ConcreteInt(ValMgr.getValue(ED->getInitVal()));
+ return nonlval::ConcreteInt(ValMgr.getValue(ED->getInitVal()));
}
else if (FunctionDecl* FD = dyn_cast<FunctionDecl>(D))
return lval::FuncVal(FD);
@@ -228,28 +235,13 @@
return UnknownVal();
}
-
-
- // Integer literals evaluate to an RValue. Simply retrieve the
- // RValue for the literal.
-#if 0
- case Stmt::IntegerLiteralClass:
- return NonLValue::GetValue(ValMgr, cast<IntegerLiteral>(E));
-
- case Stmt::CharacterLiteralClass: {
- CharacterLiteral* C = cast<CharacterLiteral>(E);
-
- return NonLValue::GetValue(ValMgr, C->getValue(), C->getType(),
- C->getLoc());
- }
-#endif
// Casts where the source and target type are the same
// are no-ops. We blast through these to get the descendant
// subexpression that has a value.
-
case Stmt::ImplicitCastExprClass: {
+
ImplicitCastExpr* C = cast<ImplicitCastExpr>(E);
QualType CT = C->getType();
@@ -262,6 +254,7 @@
E = C->getSubExpr();
continue;
}
+
break;
}
@@ -277,10 +270,23 @@
E = C->getSubExpr();
continue;
}
+
break;
}
- // Handle all other Stmt* using a lookup.
+ case Stmt::UnaryOperatorClass: {
+
+ UnaryOperator* U = cast<UnaryOperator>(E);
+
+ if (U->getOpcode() == UnaryOperator::Plus) {
+ E = U->getSubExpr();
+ continue;
+ }
+
+ break;
+ }
+
+ // Handle all other Expr* using a lookup.
default:
break;
@@ -308,7 +314,7 @@
}
}
-LValue ValueStateManager::GetLValue(ValueState St, Expr* E) {
+RVal ValueStateManager::GetLVal(ValueState St, Expr* E) {
E = E->IgnoreParens();
@@ -327,18 +333,17 @@
if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) {
lval::DeclVal X(cast<VarDecl>(DR->getDecl()));
- return cast<LValue>(GetValue(St, X));
+ return GetRVal(St, X);
}
else
- return cast<LValue>(GetValue(St, E));
+ return GetRVal(St, E);
}
- return cast<LValue>(GetValue(St, E));
+ return GetRVal(St, E);
}
ValueState
-ValueStateManager::SetValue(ValueState St, Expr* E, bool isBlkExpr,
- const RValue& V) {
+ValueStateManager::SetRVal(ValueState St, Expr* E, bool isBlkExpr, RVal V) {
assert (E);
@@ -347,36 +352,33 @@
ValueStateImpl NewSt = *St;
- if (isBlkExpr)
+ if (isBlkExpr) {
NewSt.BlockExprBindings = EXFactory.Add(NewSt.BlockExprBindings, E, V);
- else
+ }
+ else {
NewSt.SubExprBindings = EXFactory.Add(NewSt.SubExprBindings, E, V);
+ }
return getPersistentState(NewSt);
}
ValueState
-ValueStateManager::SetValue(ValueState St, const LValue& LV, const RValue& V) {
-
- if (isa<UnknownVal>(LV))
- return St;
+ValueStateManager::SetRVal(ValueState St, LVal LV, RVal V) {
- assert (!isa<UninitializedVal>(LV));
-
switch (LV.getSubKind()) {
+
case lval::DeclValKind:
- return V.isKnown() // FIXME: Have DeclVal only contain VarDecl
- ? BindVar(St, cast<VarDecl>(cast<lval::DeclVal>(LV).getDecl()), V)
- : UnbindVar(St, cast<VarDecl>(cast<lval::DeclVal>(LV).getDecl()));
+ return V.isUnknown()
+ ? UnbindVar(St, cast<lval::DeclVal>(LV).getDecl())
+ : BindVar(St, cast<lval::DeclVal>(LV).getDecl(), V);
default:
- assert ("SetValue for given LValue type not yet implemented.");
+ assert ("SetRVal for given LVal type not yet implemented.");
return St;
}
}
-ValueState
-ValueStateManager::BindVar(ValueState St, VarDecl* D, const RValue& V) {
+ValueState ValueStateManager::BindVar(ValueState St, VarDecl* D, RVal V) {
// Create a new state with the old binding removed.
ValueStateImpl NewSt = *St;
@@ -386,8 +388,7 @@
return getPersistentState(NewSt);
}
-ValueState
-ValueStateManager::UnbindVar(ValueState St, VarDecl* D) {
+ValueState ValueStateManager::UnbindVar(ValueState St, VarDecl* D) {
// Create a new state with the old binding removed.
ValueStateImpl NewSt = *St;
@@ -397,8 +398,7 @@
return getPersistentState(NewSt);
}
-ValueState
-ValueStateManager::getInitialState() {
+ValueState ValueStateManager::getInitialState() {
// Create a state with empty variable bindings.
ValueStateImpl StateImpl(EXFactory.GetEmptyMap(),
@@ -409,8 +409,7 @@
return getPersistentState(StateImpl);
}
-ValueState
-ValueStateManager::getPersistentState(const ValueStateImpl &State) {
+ValueState ValueStateManager::getPersistentState(const ValueStateImpl &State) {
llvm::FoldingSetNodeID ID;
State.Profile(ID);
@@ -426,17 +425,16 @@
}
void ValueState::printDOT(std::ostream& Out) const {
+
// Print Variable Bindings
Out << "Variables:\\l";
bool isFirst = true;
- for (vb_iterator I=vb_begin(), E=vb_end(); I!=E; ++I) {
+ for (vb_iterator I = vb_begin(), E = vb_end(); I != E; ++I) {
- if (isFirst)
- isFirst = false;
- else
- Out << "\\l";
+ if (isFirst) isFirst = false;
+ else Out << "\\l";
Out << ' ' << I.getKey()->getName() << " : ";
I.getData().print(Out);
@@ -446,14 +444,13 @@
isFirst = true;
- for (seb_iterator I=seb_begin(), E=seb_end(); I != E;++I) {
+ for (seb_iterator I = seb_begin(), E = seb_end(); I != E; ++I) {
if (isFirst) {
Out << "\\l\\lSub-Expressions:\\l";
isFirst = false;
}
- else
- Out << "\\l";
+ else { Out << "\\l"; }
Out << " (" << (void*) I.getKey() << ") ";
I.getKey()->printPretty(Out);
@@ -465,14 +462,13 @@
isFirst = true;
- for (beb_iterator I=beb_begin(), E=beb_end(); I != E; ++I) {
+ for (beb_iterator I = beb_begin(), E = beb_end(); I != E; ++I) {
if (isFirst) {
Out << "\\l\\lBlock-level Expressions:\\l";
isFirst = false;
}
- else
- Out << "\\l";
+ else { Out << "\\l"; }
Out << " (" << (void*) I.getKey() << ") ";
I.getKey()->printPretty(Out);
@@ -482,29 +478,31 @@
// Print equality constraints.
- if (!Data->ConstantEq.isEmpty()) {
+ if (!Data->ConstEq.isEmpty()) {
Out << "\\l\\|'==' constraints:";
- for (ConstantEqTy::iterator I=Data->ConstantEq.begin(),
- E=Data->ConstantEq.end(); I!=E;++I)
- Out << "\\l $" << I.getKey() << " : " << I.getData()->toString();
+ for (ConstEqTy::iterator I = Data->ConstEq.begin(),
+ E = Data->ConstEq.end(); I!=E; ++I) {
+
+ Out << "\\l $" << I.getKey()
+ << " : " << I.getData()->toString();
+ }
}
-
// Print != constraints.
- if (!Data->ConstantNotEq.isEmpty()) {
+ if (!Data->ConstNotEq.isEmpty()) {
Out << "\\l\\|'!=' constraints:";
- for (ConstantNotEqTy::iterator I=Data->ConstantNotEq.begin(),
- EI=Data->ConstantNotEq.end(); I != EI; ++I) {
+ for (ConstNotEqTy::iterator I = Data->ConstNotEq.begin(),
+ EI = Data->ConstNotEq.end(); I != EI; ++I) {
Out << "\\l $" << I.getKey() << " : ";
isFirst = true;
- IntSetTy::iterator J=I.getData().begin(), EJ=I.getData().end();
+ IntSetTy::iterator J = I.getData().begin(), EJ = I.getData().end();
for ( ; J != EJ; ++J) {
if (isFirst) isFirst = false;
Modified: cfe/trunk/Analysis/ValueState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.h?rev=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/Analysis/ValueState.h (original)
+++ cfe/trunk/Analysis/ValueState.h Thu Feb 21 12:02:17 2008
@@ -39,16 +39,16 @@
namespace clang {
//===----------------------------------------------------------------------===//
-// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues.
+// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RVals.
//===----------------------------------------------------------------------===//
namespace vstate {
typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
- typedef llvm::ImmutableMap<Expr*,RValue> ExprBindingsTy;
- typedef llvm::ImmutableMap<VarDecl*,RValue> VarBindingsTy;
- typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstantNotEqTy;
- typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstantEqTy;
+ typedef llvm::ImmutableMap<Expr*,RVal> ExprBindingsTy;
+ typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
+ typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstNotEqTy;
+ typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstEqTy;
}
/// ValueStateImpl - This class encapsulates the actual data values for
@@ -63,19 +63,17 @@
vstate::ExprBindingsTy SubExprBindings;
vstate::ExprBindingsTy BlockExprBindings;
vstate::VarBindingsTy VarBindings;
- vstate::ConstantNotEqTy ConstantNotEq;
- vstate::ConstantEqTy ConstantEq;
+ vstate::ConstNotEqTy ConstNotEq;
+ vstate::ConstEqTy ConstEq;
/// This ctor is used when creating the first ValueStateImpl object.
- ValueStateImpl(vstate::ExprBindingsTy EB,
- vstate::VarBindingsTy VB,
- vstate::ConstantNotEqTy CNE,
- vstate::ConstantEqTy CE)
+ ValueStateImpl(vstate::ExprBindingsTy EB, vstate::VarBindingsTy VB,
+ vstate::ConstNotEqTy CNE, vstate::ConstEqTy CE)
: SubExprBindings(EB),
BlockExprBindings(EB),
VarBindings(VB),
- ConstantNotEq(CNE),
- ConstantEq(CE) {}
+ ConstNotEq(CNE),
+ ConstEq(CE) {}
/// Copy ctor - We must explicitly define this or else the "Next" ptr
/// in FoldingSetNode will also get copied.
@@ -84,10 +82,8 @@
SubExprBindings(RHS.SubExprBindings),
BlockExprBindings(RHS.BlockExprBindings),
VarBindings(RHS.VarBindings),
- ConstantNotEq(RHS.ConstantNotEq),
- ConstantEq(RHS.ConstantEq) {}
-
-
+ ConstNotEq(RHS.ConstNotEq),
+ ConstEq(RHS.ConstEq) {}
/// Profile - Profile the contents of a ValueStateImpl object for use
/// in a FoldingSet.
@@ -95,8 +91,8 @@
V.SubExprBindings.Profile(ID);
V.BlockExprBindings.Profile(ID);
V.VarBindings.Profile(ID);
- V.ConstantNotEq.Profile(ID);
- V.ConstantEq.Profile(ID);
+ V.ConstNotEq.Profile(ID);
+ V.ConstEq.Profile(ID);
}
/// Profile - Used to profile the contents of this object for inclusion
@@ -129,8 +125,8 @@
typedef vstate::IntSetTy IntSetTy;
typedef vstate::ExprBindingsTy ExprBindingsTy;
typedef vstate::VarBindingsTy VarBindingsTy;
- typedef vstate::ConstantNotEqTy ConstantNotEqTy;
- typedef vstate::ConstantEqTy ConstantEqTy;
+ typedef vstate::ConstNotEqTy ConstNotEqTy;
+ typedef vstate::ConstEqTy ConstEqTy;
typedef llvm::SmallVector<ValueState,5> BufferTy;
@@ -153,13 +149,13 @@
beb_iterator beb_begin() const { return Data->BlockExprBindings.begin(); }
beb_iterator beb_end() const { return Data->BlockExprBindings.end(); }
- typedef ConstantNotEqTy::iterator cne_iterator;
- cne_iterator cne_begin() const { return Data->ConstantNotEq.begin(); }
- cne_iterator cne_end() const { return Data->ConstantNotEq.end(); }
-
- typedef ConstantEqTy::iterator ce_iterator;
- ce_iterator ce_begin() const { return Data->ConstantEq.begin(); }
- ce_iterator ce_end() const { return Data->ConstantEq.end(); }
+ typedef ConstNotEqTy::iterator cne_iterator;
+ cne_iterator cne_begin() const { return Data->ConstNotEq.begin(); }
+ cne_iterator cne_end() const { return Data->ConstNotEq.end(); }
+
+ typedef ConstEqTy::iterator ce_iterator;
+ ce_iterator ce_begin() const { return Data->ConstEq.begin(); }
+ ce_iterator ce_end() const { return Data->ConstEq.end(); }
// Profiling and equality testing.
@@ -177,7 +173,7 @@
void printDOT(std::ostream& Out) const;
void print(std::ostream& Out) const;
- void print() const { print(*llvm::cerr); }
+ void printStdErr() const { print(*llvm::cerr); }
};
@@ -188,25 +184,24 @@
static inline ValueState toState(void* P) {
return ValueState(static_cast<ValueStateImpl*>(P));
}
-};
-
+};
class ValueStateManager {
public:
typedef ValueState StateTy;
private:
- ValueState::IntSetTy::Factory ISetFactory;
- ValueState::ExprBindingsTy::Factory EXFactory;
- ValueState::VarBindingsTy::Factory VBFactory;
- ValueState::ConstantNotEqTy::Factory CNEFactory;
- ValueState::ConstantEqTy::Factory CEFactory;
+ ValueState::IntSetTy::Factory ISetFactory;
+ ValueState::ExprBindingsTy::Factory EXFactory;
+ ValueState::VarBindingsTy::Factory VBFactory;
+ ValueState::ConstNotEqTy::Factory CNEFactory;
+ ValueState::ConstEqTy::Factory CEFactory;
/// StateSet - FoldingSet containing all the states created for analyzing
/// a particular function. This is used to unique states.
llvm::FoldingSet<ValueStateImpl> StateSet;
- /// ValueMgr - Object that manages the data for all created RValues.
+ /// ValueMgr - Object that manages the data for all created RVals.
ValueManager ValMgr;
/// SymMgr - Object that manages the symbol information.
@@ -233,7 +228,7 @@
return Remove(V.VarBindings, D);
}
- ValueState BindVar(ValueState St, VarDecl* D, const RValue& V);
+ ValueState BindVar(ValueState St, VarDecl* D, RVal V);
ValueState UnbindVar(ValueState St, VarDecl* D);
public:
@@ -243,7 +238,8 @@
VBFactory(alloc),
CNEFactory(alloc),
CEFactory(alloc),
- ValMgr(Ctx, alloc), Alloc(alloc) {}
+ ValMgr(Ctx, alloc),
+ Alloc(alloc) {}
ValueState getInitialState();
@@ -258,14 +254,13 @@
NewSt.SubExprBindings = EXFactory.GetEmptyMap();
return getPersistentState(NewSt);
}
-
- ValueState SetValue(ValueState St, Expr* S, bool isBlkExpr, const RValue& V);
- ValueState SetValue(ValueState St, const LValue& LV, const RValue& V);
+ ValueState SetRVal(ValueState St, Expr* E, bool isBlkExpr, RVal V);
+ ValueState SetRVal(ValueState St, LVal LV, RVal V);
- RValue GetValue(ValueState St, Expr* S, bool* hasVal = NULL);
- RValue GetValue(ValueState St, const LValue& LV, QualType* T = NULL);
- LValue GetLValue(ValueState St, Expr* S);
+ RVal GetRVal(ValueState St, Expr* E, bool* hasVal = NULL);
+ RVal GetRVal(ValueState St, const LVal& LV, QualType T = QualType());
+ RVal GetLVal(ValueState St, Expr* E);
ValueState getPersistentState(const ValueStateImpl& Impl);
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=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Thu Feb 21 12:02:17 2008
@@ -45,37 +45,38 @@
class GRExprEngine {
public:
- typedef ValueStateManager::StateTy StateTy;
+ typedef ValueStateManager::StateTy StateTy;
typedef ExplodedGraph<GRExprEngine> GraphTy;
- typedef GraphTy::NodeTy NodeTy;
+ typedef GraphTy::NodeTy NodeTy;
// Builders.
- typedef GRStmtNodeBuilder<GRExprEngine> StmtNodeBuilder;
- typedef GRBranchNodeBuilder<GRExprEngine> BranchNodeBuilder;
- typedef GRIndirectGotoNodeBuilder<GRExprEngine> IndirectGotoNodeBuilder;
- typedef GRSwitchNodeBuilder<GRExprEngine> SwitchNodeBuilder;
+ typedef GRStmtNodeBuilder<GRExprEngine> StmtNodeBuilder;
+ typedef GRBranchNodeBuilder<GRExprEngine> BranchNodeBuilder;
+ typedef GRIndirectGotoNodeBuilder<GRExprEngine> IndirectGotoNodeBuilder;
+ typedef GRSwitchNodeBuilder<GRExprEngine> SwitchNodeBuilder;
class NodeSet {
typedef llvm::SmallVector<NodeTy*,3> ImplTy;
ImplTy Impl;
- public:
- NodeSet() {}
+ public:
+
NodeSet(NodeTy* N) { assert (N && !N->isSink()); Impl.push_back(N); }
+ NodeSet() {}
- void Add(NodeTy* N) { if (N && !N->isSink()) Impl.push_back(N); }
+ inline void Add(NodeTy* N) { if (N && !N->isSink()) Impl.push_back(N); }
typedef ImplTy::iterator iterator;
typedef ImplTy::const_iterator const_iterator;
- unsigned size() const { return Impl.size(); }
- bool empty() const { return Impl.empty(); }
+ inline unsigned size() const { return Impl.size(); }
+ inline bool empty() const { return Impl.empty(); }
- iterator begin() { return Impl.begin(); }
- iterator end() { return Impl.end(); }
+ inline iterator begin() { return Impl.begin(); }
+ inline iterator end() { return Impl.end(); }
- const_iterator begin() const { return Impl.begin(); }
- const_iterator end() const { return Impl.end(); }
+ inline const_iterator begin() const { return Impl.begin(); }
+ inline const_iterator end() const { return Impl.end(); }
};
protected:
@@ -93,11 +94,11 @@
/// StateMgr - Object that manages the data for all created states.
ValueStateManager StateMgr;
- /// ValueMgr - Object that manages the data for all created RValues.
+ /// ValueMgr - Object that manages the data for all created RVals.
ValueManager& ValMgr;
/// TF - Object that represents a bundle of transfer functions
- /// for manipulating and creating RValues.
+ /// for manipulating and creating RVals.
GRTransferFuncs* TF;
/// SymMgr - Object that manages the symbol information.
@@ -165,9 +166,11 @@
// Iterate the parameters.
FunctionDecl& F = G.getFunctionDecl();
- for (FunctionDecl::param_iterator I=F.param_begin(), E=F.param_end();
- I!=E; ++I)
- St = SetValue(St, lval::DeclVal(*I), RValue::GetSymbolValue(SymMgr, *I));
+ for (FunctionDecl::param_iterator I = F.param_begin(), E = F.param_end();
+ I != E; ++I) {
+ St = SetRVal(St, lval::DeclVal(*I),
+ RVal::GetSymbolValue(SymMgr, *I));
+ }
return St;
}
@@ -220,58 +223,63 @@
return StateMgr.RemoveDeadBindings(St, S, Liveness);
}
- StateTy SetValue(StateTy St, Expr* S, const RValue& V);
+ StateTy SetRVal(StateTy St, Expr* Ex, const RVal& V);
- StateTy SetValue(StateTy St, const Expr* S, const RValue& V) {
- return SetValue(St, const_cast<Expr*>(S), V);
+ StateTy SetRVal(StateTy St, const Expr* Ex, const RVal& V) {
+ return SetRVal(St, const_cast<Expr*>(Ex), V);
}
- /// SetValue - This version of SetValue is used to batch process a set
- /// of different possible RValues and return a set of different states.
- const StateTy::BufferTy& SetValue(StateTy St, Expr* S,
- const RValue::BufferTy& V,
- StateTy::BufferTy& RetBuf);
+ /// SetRVal - This version of SetRVal is used to batch process a set
+ /// of different possible RVals and return a set of different states.
+ const StateTy::BufferTy& SetRVal(StateTy St, Expr* Ex,
+ const RVal::BufferTy& V,
+ StateTy::BufferTy& RetBuf);
- StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
+ StateTy SetRVal(StateTy St, const LVal& LV, const RVal& V);
- inline RValue GetValue(const StateTy& St, Expr* S) {
- return StateMgr.GetValue(St, S);
+ RVal GetRVal(const StateTy& St, Expr* Ex) {
+ return StateMgr.GetRVal(St, Ex);
}
- inline RValue GetValue(const StateTy& St, Expr* S, bool& hasVal) {
- return StateMgr.GetValue(St, S, &hasVal);
+ RVal GetRVal(const StateTy& St, Expr* Ex, bool& hasVal) {
+ return StateMgr.GetRVal(St, Ex, &hasVal);
}
- inline RValue GetValue(const StateTy& St, const Expr* S) {
- return GetValue(St, const_cast<Expr*>(S));
+ RVal GetRVal(const StateTy& St, const Expr* Ex) {
+ return GetRVal(St, const_cast<Expr*>(Ex));
}
- inline RValue GetValue(const StateTy& St, const LValue& LV,
- QualType* T = NULL) {
+ RVal GetRVal(const StateTy& St, const LVal& LV,
+ QualType T = QualType()) {
- return StateMgr.GetValue(St, LV, T);
+ return StateMgr.GetRVal(St, LV, T);
}
- inline LValue GetLValue(const StateTy& St, Expr* S) {
- return StateMgr.GetLValue(St, S);
+ RVal GetLVal(const StateTy& St, Expr* Ex) {
+ return StateMgr.GetLVal(St, Ex);
}
- inline NonLValue GetRValueConstant(uint64_t X, Expr* E) {
- return NonLValue::GetValue(ValMgr, X, E->getType(), E->getLocStart());
+ inline NonLVal MakeConstantVal(uint64_t X, Expr* Ex) {
+ return NonLVal::MakeVal(ValMgr, X, Ex->getType(), Ex->getLocStart());
}
/// Assume - Create new state by assuming that a given expression
/// is true or false.
- inline StateTy Assume(StateTy St, RValue Cond, bool Assumption,
- bool& isFeasible) {
- if (isa<LValue>(Cond))
- return Assume(St, cast<LValue>(Cond), Assumption, isFeasible);
+ StateTy Assume(StateTy St, RVal Cond, bool Assumption, bool& isFeasible) {
+
+ if (Cond.isUnknown()) {
+ isFeasible = true;
+ return St;
+ }
+
+ if (isa<LVal>(Cond))
+ return Assume(St, cast<LVal>(Cond), Assumption, isFeasible);
else
- return Assume(St, cast<NonLValue>(Cond), Assumption, isFeasible);
+ return Assume(St, cast<NonLVal>(Cond), Assumption, isFeasible);
}
- StateTy Assume(StateTy St, LValue Cond, bool Assumption, bool& isFeasible);
- StateTy Assume(StateTy St, NonLValue Cond, bool Assumption, bool& isFeasible);
+ StateTy Assume(StateTy St, LVal Cond, bool Assumption, bool& isFeasible);
+ StateTy Assume(StateTy St, NonLVal Cond, bool Assumption, bool& isFeasible);
StateTy AssumeSymNE(StateTy St, SymbolID sym, const llvm::APSInt& V,
bool& isFeasible);
@@ -289,7 +297,7 @@
void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, const StateTy::BufferTy& SB);
/// HandleUninitializedStore - Create the necessary sink node to represent
- /// a store to an "uninitialized" LValue.
+ /// a store to an "uninitialized" LVal.
void HandleUninitializedStore(Stmt* S, NodeTy* Pred);
/// Visit - Transfer function logic for all statements. Dispatches to
@@ -299,15 +307,15 @@
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
- void VisitLValue(Expr* E, 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 I, CallExpr::arg_iterator E,
+ CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
NodeSet& Dst);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
- void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
+ void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
void VisitDeclRefExpr(DeclRefExpr* DR, NodeTy* Pred, NodeSet& Dst);
@@ -316,101 +324,62 @@
void VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst);
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
- void VisitGuardedExpr(Expr* S, Expr* LHS, Expr* RHS,
- NodeTy* Pred, NodeSet& Dst);
+ 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);
/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
- void VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* S, NodeTy* Pred,
+ void VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex, NodeTy* Pred,
NodeSet& Dst);
+ // VisitSizeOfExpr - Transfer function for sizeof(expr).
+ void VisitSizeOfExpr(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst);
+
/// 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))
- return X;
-
- return TF->EvalCast(ValMgr, X, CastExpr);
+ RVal EvalCast(ValueManager& ValMgr, RVal X, Expr* CastExpr) {
+ return X.isValid() ? TF->EvalCast(ValMgr, X, CastExpr) : X;
}
- inline NonLValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
- NonLValue X) {
- if (isa<UnknownVal>(X) || isa<UninitializedVal>(X))
- return X;
-
- return TF->EvalMinus(ValMgr, U, X);
+ RVal EvalMinus(UnaryOperator* U, RVal X) {
+ return X.isValid() ? TF->EvalMinus(ValMgr, U, cast<NonLVal>(X)) : X;
}
- inline NonLValue EvalPlus(ValueManager& ValMgr, UnaryOperator* U,
- NonLValue X) {
- if (isa<UnknownVal>(X) || isa<UninitializedVal>(X))
- return X;
-
- return TF->EvalPlus(ValMgr, U, X);
+ RVal EvalComplement(RVal X) {
+ return X.isValid() ? TF->EvalComplement(ValMgr, cast<NonLVal>(X)) : X;
}
- inline NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X) {
- if (isa<UnknownVal>(X) || isa<UninitializedVal>(X))
- return X;
-
- return TF->EvalComplement(ValMgr, X);
+ RVal EvalBinOp(BinaryOperator::Opcode Op, LVal L, RVal R) {
+ return R.isValid() ? TF->EvalBinOp(ValMgr, Op, L, cast<NonLVal>(R)) : R;
}
- inline NonLValue EvalBinaryOp(BinaryOperator::Opcode Op,
- NonLValue LHS, NonLValue RHS) {
-
- if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
- return cast<NonLValue>(UninitializedVal());
-
- if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
- return cast<NonLValue>(UnknownVal());
-
- return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
- }
-
- inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
- LValue LHS, LValue RHS) {
-
- if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
- return UninitializedVal();
-
- if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
- return UnknownVal();
-
- return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
- }
-
- inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
- LValue LHS, NonLValue RHS) {
-
- if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
- return UninitializedVal();
-
- if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
- return UnknownVal();
-
- return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
+ RVal EvalBinOp(BinaryOperator::Opcode Op, NonLVal L, RVal R) {
+ return R.isValid() ? TF->EvalBinOp(ValMgr, Op, L, cast<NonLVal>(R)) : R;
}
- inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
- RValue LHS, RValue RHS) {
+ RVal EvalBinOp(BinaryOperator::Opcode Op, RVal L, RVal R) {
- if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
+ if (L.isUninit() || R.isUninit())
return UninitializedVal();
- if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
+ if (L.isUnknown() || R.isUnknown())
return UnknownVal();
+
+ if (isa<LVal>(L)) {
+ if (isa<LVal>(R))
+ return TF->EvalBinOp(ValMgr, Op, cast<LVal>(L), cast<LVal>(R));
+ else
+ return TF->EvalBinOp(ValMgr, Op, cast<LVal>(L), cast<NonLVal>(R));
+ }
- return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
+ return TF->EvalBinOp(ValMgr, Op, cast<NonLVal>(L), cast<NonLVal>(R));
}
- StateTy EvalCall(CallExpr* CE, StateTy St) {
+ StateTy EvalCall(CallExpr* CE, LVal L, StateTy St) {
return St;
}
};
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h?rev=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h Thu Feb 21 12:02:17 2008
@@ -26,47 +26,28 @@
// Casts.
- RValue EvalCast(ValueManager& ValMgr, RValue V, Expr* CastExpr);
- virtual RValue EvalCast(ValueManager& ValMgr, NonLValue V, Expr* CastExpr) =0;
- virtual RValue EvalCast(ValueManager& ValMgr, LValue V, Expr* CastExpr) = 0;
+ RVal EvalCast(ValueManager& ValMgr, RVal V, Expr* CastExpr);
+ virtual RVal EvalCast(ValueManager& ValMgr, NonLVal V, Expr* CastExpr) =0;
+ virtual RVal EvalCast(ValueManager& ValMgr, LVal V, Expr* CastExpr) = 0;
// Unary Operators.
- virtual NonLValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
- NonLValue X) = 0;
+ virtual RVal EvalMinus(ValueManager& ValMgr, UnaryOperator* U, NonLVal X) = 0;
- virtual NonLValue EvalPlus(ValueManager& ValMgr, UnaryOperator* U,
- NonLValue X) = 0;
-
- virtual NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X) = 0;
+ virtual RVal EvalComplement(ValueManager& ValMgr, NonLVal X) = 0;
// Binary Operators.
- virtual NonLValue EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- NonLValue LHS, NonLValue RHS) = 0;
-
- virtual RValue EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- LValue LHS, LValue RHS) = 0;
+ virtual RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ NonLVal L, NonLVal R) = 0;
- // Pointer arithmetic.
+ virtual RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ LVal L, LVal R) = 0;
- virtual LValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
- LValue LHS, NonLValue RHS) = 0;
+ // Pointer arithmetic.
- inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
- const RValue& L, const RValue& R) {
-
- if (isa<LValue>(L)) {
- if (isa<LValue>(R))
- return EvalBinaryOp(ValMgr, Op, cast<LValue>(L), cast<LValue>(R));
- else
- return EvalBinaryOp(ValMgr, Op, cast<LValue>(L), cast<NonLValue>(R));
- }
- else
- return EvalBinaryOp(ValMgr, Op, cast<NonLValue>(L), cast<NonLValue>(R));
- }
+ virtual RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ LVal L, NonLVal R) = 0;
};
} // end clang namespace
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=47441&r1=47440&r2=47441&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Thu Feb 21 12:02:17 2008
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This files defines RValue, LValue, and NonLValue, classes that represent
+// This files defines RVal, LVal, and NonLVal, classes that represent
// abstract r-values for use with path-sensitive value tracking.
//
//===----------------------------------------------------------------------===//
@@ -19,57 +19,64 @@
#include "llvm/Support/Casting.h"
//==------------------------------------------------------------------------==//
-// Base RValue types.
+// Base RVal types.
//==------------------------------------------------------------------------==//
namespace clang {
-class RValue {
+class RVal {
public:
- enum BaseKind { LValueKind=0x0,
- NonLValueKind=0x1,
- UninitializedKind=0x2,
- UnknownKind=0x3 };
-
- enum { BaseBits = 2,
- BaseMask = 0x3 };
+ enum BaseKind { UninitializedKind, UnknownKind, LValKind, NonLValKind };
+ enum { BaseBits = 2, BaseMask = 0x3 };
protected:
void* Data;
unsigned Kind;
protected:
- RValue(const void* d, bool isLValue, unsigned ValKind)
+ RVal(const void* d, bool isLVal, unsigned ValKind)
: Data(const_cast<void*>(d)),
- Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
+ Kind((isLVal ? LValKind : NonLValKind) | (ValKind << BaseBits)) {}
- explicit RValue(BaseKind k)
+ explicit RVal(BaseKind k)
: Data(0), Kind(k) {}
public:
- ~RValue() {};
+ ~RVal() {};
- /// BufferTy - A temporary buffer to hold a set of RValues.
- typedef llvm::SmallVector<RValue,5> BufferTy;
+ /// BufferTy - A temporary buffer to hold a set of RVals.
+ typedef llvm::SmallVector<RVal,5> BufferTy;
- unsigned getRawKind() const { return Kind; }
- BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
- unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
+ inline unsigned getRawKind() const { return Kind; }
+ inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
+ inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
- void Profile(llvm::FoldingSetNodeID& ID) const {
+ inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getRawKind());
ID.AddPointer(reinterpret_cast<void*>(Data));
}
- bool operator==(const RValue& RHS) const {
- return getRawKind() == RHS.getRawKind() && Data == RHS.Data;
+ inline bool operator==(const RVal& R) const {
+ return getRawKind() == R.getRawKind() && Data == R.Data;
}
- static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
+ static RVal GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
+ inline bool isUnknown() const {
+ return getRawKind() == UnknownKind;
+ }
+
+ inline bool isUninit() const {
+ return getRawKind() == UninitializedKind;
+ }
+
+ inline bool isUnknownOrUninit() const {
+ return getRawKind() <= UnknownKind;
+ }
- inline bool isKnown() const { return getRawKind() != UnknownKind; }
- inline bool isUnknown() const { return getRawKind() == UnknownKind; }
+ inline bool isValid() const {
+ return getRawKind() > UnknownKind;
+ }
void print(std::ostream& OS) const;
void printStdErr() const;
@@ -79,247 +86,269 @@
symbol_iterator symbol_end() const;
// Implement isa<T> support.
- static inline bool classof(const RValue*) { return true; }
+ static inline bool classof(const RVal*) { return true; }
};
-class UnknownVal : public RValue {
+class UnknownVal : public RVal {
public:
- UnknownVal() : RValue(UnknownKind) {}
+ UnknownVal() : RVal(UnknownKind) {}
- static inline bool classof(const RValue* V) {
+ static inline bool classof(const RVal* V) {
return V->getBaseKind() == UnknownKind;
}
};
-class UninitializedVal : public RValue {
+class UninitializedVal : public RVal {
public:
- UninitializedVal() : RValue(UninitializedKind) {}
+ UninitializedVal() : RVal(UninitializedKind) {}
- static inline bool classof(const RValue* V) {
+ static inline bool classof(const RVal* V) {
return V->getBaseKind() == UninitializedKind;
}
};
-class NonLValue : public RValue {
+class NonLVal : public RVal {
protected:
- NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
+ NonLVal(unsigned SubKind, const void* d) : RVal(d, false, SubKind) {}
public:
void print(std::ostream& Out) const;
- // Utility methods to create NonLValues.
- static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
- SourceLocation Loc = SourceLocation());
+ // Utility methods to create NonLVals.
+ static NonLVal MakeVal(ValueManager& ValMgr, uint64_t X, QualType T,
+ SourceLocation Loc = SourceLocation());
- static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
+ static NonLVal MakeVal(ValueManager& ValMgr, IntegerLiteral* I);
- static NonLValue GetIntTruthValue(ValueManager& ValMgr, bool b);
+ static NonLVal MakeIntTruthVal(ValueManager& ValMgr, bool b);
// Implement isa<T> support.
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() >= NonLValueKind;
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == NonLValKind;
}
};
-class LValue : public RValue {
+class LVal : public RVal {
protected:
- LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D),
- true, SubKind) {}
-
+ LVal(unsigned SubKind, const void* D)
+ : RVal(const_cast<void*>(D), true, SubKind) {}
+
// Equality operators.
- NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
- NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
+ NonLVal EQ(ValueManager& ValMgr, const LVal& R) const;
+ NonLVal NE(ValueManager& ValMgr, const LVal& R) const;
public:
void print(std::ostream& Out) const;
- static LValue GetValue(AddrLabelExpr* E);
+ static LVal MakeVal(AddrLabelExpr* E);
// Implement isa<T> support.
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() != NonLValueKind;
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == LValKind;
}
};
//==------------------------------------------------------------------------==//
-// Subclasses of NonLValue.
+// Subclasses of NonLVal.
//==------------------------------------------------------------------------==//
namespace nonlval {
- enum Kind { ConcreteIntKind,
- SymbolValKind,
- SymIntConstraintValKind,
- NumKind };
-
- class SymbolVal : public NonLValue {
- public:
- SymbolVal(unsigned SymID)
- : NonLValue(SymbolValKind,
- reinterpret_cast<void*>((uintptr_t) SymID)) {}
-
- SymbolID getSymbol() const {
- return (SymbolID) reinterpret_cast<uintptr_t>(Data);
- }
-
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() == NonLValueKind &&
- V->getSubKind() == SymbolValKind;
- }
- };
-
- class SymIntConstraintVal : public NonLValue {
- public:
- SymIntConstraintVal(const SymIntConstraint& C)
- : NonLValue(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
-
- const SymIntConstraint& getConstraint() const {
- return *reinterpret_cast<SymIntConstraint*>(Data);
- }
-
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() == NonLValueKind &&
- V->getSubKind() == SymIntConstraintValKind;
- }
- };
-
- class ConcreteInt : public NonLValue {
- public:
- ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {}
-
- const llvm::APSInt& getValue() const {
- return *static_cast<llvm::APSInt*>(Data);
- }
-
- // Transfer functions for binary/unary operations on ConcreteInts.
- ConcreteInt EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- const ConcreteInt& RHS) const;
-
- ConcreteInt EvalComplement(ValueManager& ValMgr) const;
- ConcreteInt EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
- ConcreteInt EvalPlus(ValueManager& ValMgr, UnaryOperator* U) const;
-
- // Implement isa<T> support.
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() == NonLValueKind &&
- V->getSubKind() == ConcreteIntKind;
- }
- };
+enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind };
+
+class SymbolVal : public NonLVal {
+public:
+ SymbolVal(unsigned SymID)
+ : NonLVal(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
+
+ SymbolID getSymbol() const {
+ return (SymbolID) reinterpret_cast<uintptr_t>(Data);
+ }
+
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == NonLValKind &&
+ V->getSubKind() == SymbolValKind;
+ }
+
+ static inline bool classof(const NonLVal* V) {
+ return V->getSubKind() == SymbolValKind;
+ }
+};
+
+class SymIntConstraintVal : public NonLVal {
+public:
+ SymIntConstraintVal(const SymIntConstraint& C)
+ : NonLVal(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
+
+ const SymIntConstraint& getConstraint() const {
+ return *reinterpret_cast<SymIntConstraint*>(Data);
+ }
+
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == NonLValKind &&
+ V->getSubKind() == SymIntConstraintValKind;
+ }
+
+ static inline bool classof(const NonLVal* V) {
+ return V->getSubKind() == SymIntConstraintValKind;
+ }
+};
+
+class ConcreteInt : public NonLVal {
+public:
+ ConcreteInt(const llvm::APSInt& V) : NonLVal(ConcreteIntKind, &V) {}
+
+ const llvm::APSInt& getValue() const {
+ return *static_cast<llvm::APSInt*>(Data);
+ }
+
+ // Transfer functions for binary/unary operations on ConcreteInts.
+ ConcreteInt EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ const ConcreteInt& R) const;
+
+ ConcreteInt EvalComplement(ValueManager& ValMgr) const;
+
+ ConcreteInt EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == NonLValKind &&
+ V->getSubKind() == ConcreteIntKind;
+ }
+
+ static inline bool classof(const NonLVal* V) {
+ return V->getSubKind() == ConcreteIntKind;
+ }
+};
} // end namespace clang::nonlval
//==------------------------------------------------------------------------==//
-// Subclasses of LValue.
+// Subclasses of LVal.
//==------------------------------------------------------------------------==//
namespace lval {
- enum Kind { SymbolValKind,
- GotoLabelKind,
- DeclValKind,
- FuncValKind,
- ConcreteIntKind,
- NumKind };
-
- class SymbolVal : public LValue {
- public:
- SymbolVal(unsigned SymID)
- : LValue(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
-
- SymbolID getSymbol() const {
- return (SymbolID) reinterpret_cast<uintptr_t>(Data);
- }
-
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() == LValueKind &&
- V->getSubKind() == SymbolValKind;
- }
- };
-
- class GotoLabel : public LValue {
- public:
- GotoLabel(LabelStmt* Label) : LValue(GotoLabelKind, Label) {}
-
- LabelStmt* getLabel() const {
- return static_cast<LabelStmt*>(Data);
- }
-
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() == LValueKind &&
- V->getSubKind() == GotoLabelKind;
- }
- };
-
+enum Kind { SymbolValKind, GotoLabelKind, DeclValKind, FuncValKind,
+ ConcreteIntKind };
+
+class SymbolVal : public LVal {
+public:
+ SymbolVal(unsigned SymID)
+ : LVal(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
- class DeclVal : public LValue {
- public:
- DeclVal(const VarDecl* vd) : LValue(DeclValKind, vd) {}
-
- VarDecl* getDecl() const {
- return static_cast<VarDecl*>(Data);
- }
-
- inline bool operator==(const DeclVal& R) const {
- return getDecl() == R.getDecl();
- }
-
- inline bool operator!=(const DeclVal& R) const {
- return getDecl() != R.getDecl();
- }
-
- // Implement isa<T> support.
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() == LValueKind &&
- 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 V->getBaseKind() == LValueKind &&
- V->getSubKind() == FuncValKind;
- }
- };
-
- class ConcreteInt : public LValue {
- public:
- ConcreteInt(const llvm::APSInt& V) : LValue(ConcreteIntKind, &V) {}
-
- const llvm::APSInt& getValue() const {
- return *static_cast<llvm::APSInt*>(Data);
- }
-
+ SymbolID getSymbol() const {
+ return (SymbolID) reinterpret_cast<uintptr_t>(Data);
+ }
+
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == LValKind &&
+ V->getSubKind() == SymbolValKind;
+ }
+
+ static inline bool classof(const LVal* V) {
+ return V->getSubKind() == SymbolValKind;
+ }
+};
- // Transfer functions for binary/unary operations on ConcreteInts.
- ConcreteInt EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- const ConcreteInt& RHS) const;
-
- // Implement isa<T> support.
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() == LValueKind &&
- V->getSubKind() == ConcreteIntKind;
- }
- };
-} // end clang::lval namespace
+class GotoLabel : public LVal {
+public:
+ GotoLabel(LabelStmt* Label) : LVal(GotoLabelKind, Label) {}
+
+ LabelStmt* getLabel() const {
+ return static_cast<LabelStmt*>(Data);
+ }
+
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == LValKind &&
+ V->getSubKind() == GotoLabelKind;
+ }
+
+ static inline bool classof(const LVal* V) {
+ return V->getSubKind() == GotoLabelKind;
+ }
+};
+
+
+class DeclVal : public LVal {
+public:
+ DeclVal(const VarDecl* vd) : LVal(DeclValKind, vd) {}
+
+ VarDecl* getDecl() const {
+ return static_cast<VarDecl*>(Data);
+ }
+
+ inline bool operator==(const DeclVal& R) const {
+ return getDecl() == R.getDecl();
+ }
+
+ inline bool operator!=(const DeclVal& R) const {
+ return getDecl() != R.getDecl();
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == LValKind &&
+ V->getSubKind() == DeclValKind;
+ }
+
+ static inline bool classof(const LVal* V) {
+ return V->getSubKind() == DeclValKind;
+ }
+};
+class FuncVal : public LVal {
+public:
+ FuncVal(const FunctionDecl* fd) : LVal(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 RVal* V) {
+ return V->getBaseKind() == LValKind &&
+ V->getSubKind() == FuncValKind;
+ }
+
+ static inline bool classof(const LVal* V) {
+ return V->getSubKind() == FuncValKind;
+ }
+};
+
+class ConcreteInt : public LVal {
+public:
+ ConcreteInt(const llvm::APSInt& V) : LVal(ConcreteIntKind, &V) {}
+
+ const llvm::APSInt& getValue() const {
+ return *static_cast<llvm::APSInt*>(Data);
+ }
+
+ // Transfer functions for binary/unary operations on ConcreteInts.
+ ConcreteInt EvalBinOp(ValueManager& ValMgr,
+ BinaryOperator::Opcode Op,
+ const ConcreteInt& R) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == LValKind &&
+ V->getSubKind() == ConcreteIntKind;
+ }
+
+ static inline bool classof(const LVal* V) {
+ return V->getSubKind() == ConcreteIntKind;
+ }
+};
+
+} // end clang::lval namespace
} // end clang namespace
#endif
More information about the cfe-commits
mailing list