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);
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());
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) {
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:
//
// 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);
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;
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());
// 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;
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;
}
// 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;
}
}
// 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;
}
}
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;
// 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;
NodeTy* N = Builder->generateNode(S, St, Pred);
Dst.Add(N);
+
return N;
}
}
void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){
+
if (D != CurrentStmt) {
Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
return;
// 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();
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) {
continue;
}
- if (L.isUnknown()) {
+ // Check for dereferences of unknown values. Treat as No-Ops.
+
+ if (V.isUnknown()) {
Dst.Add(N);
continue;
}
//
// 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:
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:
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;
}
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) {
- E = E->IgnoreParens();
+ QualType T = U->getSubExpr()->getType();
+
+ // FIXME: Add support for VLAs.
+ if (!T.getTypePtr()->isConstantSizeType())
+ return;
- if (isa<DeclRefExpr>(E)) {
+ 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) {
+
+ assert (Ex != CurrentStmt && !getCFG().isBlkExpr(Ex));
+
+ 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,
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());
-
- NodeSet S2;
+ // 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;
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);
}
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;
}
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);
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;
}
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);
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;
}
// "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:
}
}
-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;
}
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() << " : ";
Out << "\\|Dereference of uninitialied value.\\l";
}
else if (GraphPrintCheckerState->isUninitStore(N)) {
- Out << "\\|Store to Uninitialized LValue.";
+ Out << "\\|Store to Uninitialized LVal.";
}
break;
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();
// 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;
// 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();
}
}
}
// 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) {
-
- assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
- assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
+RVal GRSimpleVals::EvalEQ(ValueManager& ValMgr, LVal L, LVal R) {
- 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);
}
// 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 RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ NonLVal L, NonLVal R);
- virtual RValue EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- LValue LHS, LValue RHS);
+ 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
// 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;
//
//===----------------------------------------------------------------------===//
//
-// 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.
//
//===----------------------------------------------------------------------===//
// 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());
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);
}
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());
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())
}
//===----------------------------------------------------------------------===//
-// 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();
}
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:
break;
default:
- assert (false && "Pretty-printed not implemented for this LValue.");
+ assert (false && "Pretty-printing not implemented for this LVal.");
break;
}
}
-
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;
}
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);
}
// 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();
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;
// 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();
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;
}
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);
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);
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();
E = C->getSubExpr();
continue;
}
+
break;
}
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;
}
}
-LValue ValueStateManager::GetLValue(ValueState St, Expr* E) {
+RVal ValueStateManager::GetLVal(ValueState St, Expr* E) {
E = E->IgnoreParens();
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);
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;
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;
return getPersistentState(NewSt);
}
-ValueState
-ValueStateManager::getInitialState() {
+ValueState ValueStateManager::getInitialState() {
// Create a state with empty variable bindings.
ValueStateImpl StateImpl(EXFactory.GetEmptyMap(),
return getPersistentState(StateImpl);
}
-ValueState
-ValueStateManager::getPersistentState(const ValueStateImpl &State) {
+ValueState ValueStateManager::getPersistentState(const ValueStateImpl &State) {
llvm::FoldingSetNodeID ID;
State.Profile(ID);
}
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);
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);
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);
// 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;
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
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.
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.
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
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;
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 ConstNotEqTy::iterator cne_iterator;
+ cne_iterator cne_begin() const { return Data->ConstNotEq.begin(); }
+ cne_iterator cne_end() const { return Data->ConstNotEq.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 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.
void printDOT(std::ostream& Out) const;
void print(std::ostream& Out) const;
- void print() const { print(*llvm::cerr); }
+ void printStdErr() const { print(*llvm::cerr); }
};
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.
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:
VBFactory(alloc),
CNEFactory(alloc),
CEFactory(alloc),
- ValMgr(Ctx, alloc), Alloc(alloc) {}
+ ValMgr(Ctx, alloc),
+ Alloc(alloc) {}
ValueState getInitialState();
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);
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:
/// 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.
// 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;
}
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);
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
/// 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);
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;
}
};
// 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 RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ NonLVal L, NonLVal R) = 0;
- virtual RValue EvalBinaryOp(ValueManager& ValMgr,
- BinaryOperator::Opcode Op,
- LValue LHS, LValue RHS) = 0;
+ virtual RVal EvalBinOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+ LVal L, LVal R) = 0;
// Pointer arithmetic.
- virtual LValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
- LValue LHS, NonLValue RHS) = 0;
-
- 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
//
//===----------------------------------------------------------------------===//
//
-// 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.
//
//===----------------------------------------------------------------------===//
#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;
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 };
+enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind };
- 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)) {}
+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;
+ }
+};
- const SymIntConstraint& getConstraint() const {
- return *reinterpret_cast<SymIntConstraint*>(Data);
- }
-
- static inline bool classof(const RValue* V) {
- return V->getBaseKind() == NonLValueKind &&
- V->getSubKind() == SymIntConstraintValKind;
- }
- };
+class SymIntConstraintVal : public NonLVal {
+public:
+ SymIntConstraintVal(const SymIntConstraint& C)
+ : NonLVal(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
- 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;
- }
- };
+ 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;
- }
- };
+ 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;
+ }
+};
- class ConcreteInt : public LValue {
- public:
- ConcreteInt(const llvm::APSInt& V) : LValue(ConcreteIntKind, &V) {}
-
- const llvm::APSInt& getValue() const {
- return *static_cast<llvm::APSInt*>(Data);
- }
-
+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;
+ }
+};
+
- // 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 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