Newer
Older
case BinaryOperator::Mul: {
const RValue& R1 = cast<RValue>(V1);
const RValue& R2 = cast<RValue>(V2);
Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
Ted Kremenek
committed
case BinaryOperator::Assign: {
const LValue& L1 = cast<LValue>(V1);
const RValue& R2 = cast<RValue>(V2);
Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
break;
}
case BinaryOperator::AddAssign: {
const LValue& L1 = cast<LValue>(V1);
RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
break;
}
case BinaryOperator::SubAssign: {
const LValue& L1 = cast<LValue>(V1);
RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
RValue Result = R1.EvalSub(ValMgr, cast<RValue>(V2));
Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
break;
}
case BinaryOperator::MulAssign: {
const LValue& L1 = cast<LValue>(V1);
RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
RValue Result = R1.EvalMul(ValMgr, cast<RValue>(V2));
Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
break;
}
Ted Kremenek
committed
default:
Dst.Add(N2);
break;
}
}
}
}
Ted Kremenek
committed
void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
GRConstants::NodeSet& Dst) {
Ted Kremenek
committed
// FIXME: add metadata to the CFG so that we can disable
// this check when we KNOW that there is no block-level subexpression.
// The motivation is that this check requires a hashtable lookup.
Ted Kremenek
committed
if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
Dst.Add(Pred);
return;
}
switch (S->getStmtClass()) {
case Stmt::BinaryOperatorClass:
case Stmt::CompoundAssignOperatorClass:
Ted Kremenek
committed
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
break;
case Stmt::UnaryOperatorClass:
VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
break;
Ted Kremenek
committed
case Stmt::ParenExprClass:
Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
break;
case Stmt::ImplicitCastExprClass: {
ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
VisitCast(C, C->getSubExpr(), Pred, Dst);
break;
}
case Stmt::CastExprClass: {
CastExpr* C = cast<CastExpr>(S);
VisitCast(C, C->getSubExpr(), Pred, Dst);
break;
}
case Stmt::DeclStmtClass:
VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
break;
Ted Kremenek
committed
default:
Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
break;
}
//===----------------------------------------------------------------------===//
// Driver.
//===----------------------------------------------------------------------===//
#ifndef NDEBUG
namespace llvm {
template<>
struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
public DefaultDOTGraphTraits {
static void PrintKindLabel(std::ostream& Out, ValueKey::Kind kind) {
Ted Kremenek
committed
switch (kind) {
case ValueKey::IsSubExpr: Out << "Sub-Expressions:\\l"; break;
Ted Kremenek
committed
case ValueKey::IsDecl: Out << "Variables:\\l"; break;
case ValueKey::IsBlkExpr: Out << "Block-level Expressions:\\l"; break;
default: assert (false && "Unknown ValueKey type.");
}
}
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
static void PrintKind(std::ostream& Out, GRConstants::StateTy M,
ValueKey::Kind kind, bool isFirstGroup = false) {
bool isFirst = true;
for (GRConstants::StateTy::iterator I=M.begin(), E=M.end();I!=E;++I) {
if (I.getKey().getKind() != kind)
continue;
if (isFirst) {
if (!isFirstGroup) Out << "\\l\\l";
PrintKindLabel(Out, kind);
isFirst = false;
}
else
Out << "\\l";
Out << ' ';
if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey()))
Out << V->getName();
else {
Stmt* E = cast<Stmt>(I.getKey());
Out << " (" << (void*) E << ") ";
E->printPretty(Out);
}
Out << " : ";
I.getData().print(Out);
}
}
static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
std::ostringstream Out;
Ted Kremenek
committed
// Program Location.
ProgramPoint Loc = N->getLocation();
switch (Loc.getKind()) {
case ProgramPoint::BlockEntranceKind:
Out << "Block Entrance: B"
<< cast<BlockEntrance>(Loc).getBlock()->getBlockID();
break;
case ProgramPoint::BlockExitKind:
assert (false);
break;
case ProgramPoint::PostStmtKind: {
const PostStmt& L = cast<PostStmt>(Loc);
Out << L.getStmt()->getStmtClassName() << ':'
<< (void*) L.getStmt() << ' ';
L.getStmt()->printPretty(Out);
break;
}
default: {
const BlockEdge& E = cast<BlockEdge>(Loc);
Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
<< E.getDst()->getBlockID() << ')';
}
}
Ted Kremenek
committed
Out << "\\|";
PrintKind(Out, N->getState(), ValueKey::IsDecl, true);
PrintKind(Out, N->getState(), ValueKey::IsBlkExpr);
PrintKind(Out, N->getState(), ValueKey::IsSubExpr);
Ted Kremenek
committed
Out << "\\l";
return Out.str();
}
};
} // end llvm namespace
#endif
void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
GREngine<GRConstants> Engine(cfg, Ctx);
Engine.ExecuteWorkList();
#ifndef NDEBUG
llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
#endif
Ted Kremenek
committed
} // end clang namespace