"clang/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "7d002beb5bd1ffdfeb43bd5a06d951a6f24cb773"
Newer
Older
Ted Kremenek
committed
continue;
Ted Kremenek
committed
}
case BinaryOperator::Div:
case BinaryOperator::Rem:
// Special checking for integer denominators.
if (RHS->getType()->isIntegerType()
&& CheckDivideZero(B, St, *I2, RightV))
continue;
// FALL-THROUGH.
default: {
if (B->isAssignmentOp())
break;
// Process non-assignements except commas or short-circuited
// logical expressions (LAnd and LOr).
RVal Result = EvalBinOp(Op, LeftV, RightV);
if (Result.isUnknown()) {
Dst.Add(*I2);
continue;
}
if (Result.isUndef() && !LeftV.isUndef() && !RightV.isUndef()) {
// The operands were *not* undefined, but the result is undefined.
// This is a special node that should be flagged as an error.
if (NodeTy* UndefNode = Builder->generateNode(B, St, *I2)) {
UndefNode->markAsSink();
UndefResults.insert(UndefNode);
}
continue;
}
// Otherwise, create a new node.
MakeNode(Dst, B, *I2, SetRVal(St, B, Result));
continue;
}
}
assert (B->isCompoundAssignmentOp());
if (Op >= BinaryOperator::AndAssign)
((int&) Op) -= (BinaryOperator::AndAssign - BinaryOperator::And);
else
((int&) Op) -= BinaryOperator::MulAssign;
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
// Perform a load (the LHS). This performs the checks for
// null dereferences, and so on.
NodeSet Tmp3;
RVal location = GetRVal(St, LHS);
EvalLoad(Tmp3, LHS, *I2, St, location);
for (NodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3; ++I3) {
St = GetState(*I3);
RVal V = GetRVal(St, LHS);
// Propagate undefined values (left-side).
if (V.isUndef()) {
EvalStore(Dst, B, *I3, SetRVal(St, B, V), location, V);
continue;
}
// Propagate unknown values (left and right-side).
if (RightV.isUnknown() || V.isUnknown()) {
EvalStore(Dst, B, *I3, SetRVal(St, B, UnknownVal()), location,
UnknownVal());
continue;
}
// At this point:
//
// The LHS is not Undef/Unknown.
// The RHS is not Unknown.
// Get the computation type.
QualType CTy = cast<CompoundAssignOperator>(B)->getComputationType();
// Perform promotions.
V = EvalCast(V, CTy);
RightV = EvalCast(RightV, CTy);
// Evaluate operands and promote to result type.
if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem)
&& RHS->getType()->isIntegerType()) {
if (CheckDivideZero(B, St, *I3, RightV))
continue;
}
else if (RightV.isUndef()) {
// Propagate undefined values (right-side).
EvalStore(Dst, B, *I3, SetRVal(St, B, RightV), location, RightV);
continue;
}
// Compute the result of the operation.
RVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType());
if (Result.isUndef()) {
// The operands were not undefined, but the result is undefined.
Ted Kremenek
committed
if (NodeTy* UndefNode = Builder->generateNode(B, St, *I3)) {
UndefNode->markAsSink();
UndefResults.insert(UndefNode);
Ted Kremenek
committed
}
Ted Kremenek
committed
continue;
EvalStore(Dst, B, *I3, SetRVal(St, B, Result), location, Result);
Ted Kremenek
committed
}
}
}
}
//===----------------------------------------------------------------------===//
// "Assume" logic.
//===----------------------------------------------------------------------===//
ValueState* GRExprEngine::Assume(ValueState* St, LVal Cond,
bool Assumption, bool& isFeasible) {
St = AssumeAux(St, Cond, Assumption, isFeasible);
return isFeasible ? TF->EvalAssume(*this, St, Cond, Assumption, isFeasible)
: St;
}
ValueState* GRExprEngine::AssumeAux(ValueState* St, LVal Cond,
bool Assumption, bool& isFeasible) {
switch (Cond.getSubKind()) {
default:
assert (false && "'Assume' not implemented for this LVal.");
Ted Kremenek
committed
case lval::SymbolValKind:
if (Assumption)
return AssumeSymNE(St, cast<lval::SymbolVal>(Cond).getSymbol(),
BasicVals.getZeroWithPtrWidth(), isFeasible);
Ted Kremenek
committed
else
return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(),
BasicVals.getZeroWithPtrWidth(), isFeasible);
case lval::DeclValKind:
Ted Kremenek
committed
case lval::FuncValKind:
case lval::GotoLabelKind:
case lval::StringLiteralValKind:
isFeasible = Assumption;
return St;
Ted Kremenek
committed
case lval::FieldOffsetKind:
return AssumeAux(St, cast<lval::FieldOffset>(Cond).getBase(),
Assumption, isFeasible);
case lval::ArrayOffsetKind:
return AssumeAux(St, cast<lval::ArrayOffset>(Cond).getBase(),
Assumption, isFeasible);
case lval::ConcreteIntKind: {
bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
isFeasible = b ? Assumption : !Assumption;
return St;
}
}
}
ValueState* GRExprEngine::Assume(ValueState* St, NonLVal Cond,
bool Assumption, bool& isFeasible) {
St = AssumeAux(St, Cond, Assumption, isFeasible);
return isFeasible ? TF->EvalAssume(*this, St, Cond, Assumption, isFeasible)
: St;
}
ValueState* GRExprEngine::AssumeAux(ValueState* St, NonLVal Cond,
bool Assumption, bool& isFeasible) {
switch (Cond.getSubKind()) {
default:
assert (false && "'Assume' not implemented for this NonLVal.");
return St;
Ted Kremenek
committed
case nonlval::SymbolValKind: {
nonlval::SymbolVal& SV = cast<nonlval::SymbolVal>(Cond);
Ted Kremenek
committed
SymbolID sym = SV.getSymbol();
if (Assumption)
return AssumeSymNE(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
Ted Kremenek
committed
isFeasible);
else
return AssumeSymEQ(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
Ted Kremenek
committed
isFeasible);
}
Ted Kremenek
committed
case nonlval::SymIntConstraintValKind:
return
AssumeSymInt(St, Assumption,
cast<nonlval::SymIntConstraintVal>(Cond).getConstraint(),
isFeasible);
case nonlval::ConcreteIntKind: {
bool b = cast<nonlval::ConcreteInt>(Cond).getValue() != 0;
isFeasible = b ? Assumption : !Assumption;
return St;
}
Ted Kremenek
committed
case nonlval::LValAsIntegerKind: {
return AssumeAux(St, cast<nonlval::LValAsInteger>(Cond).getLVal(),
Assumption, isFeasible);
}
}
}
ValueState*
GRExprEngine::AssumeSymNE(ValueState* St, SymbolID sym,
Ted Kremenek
committed
const llvm::APSInt& V, bool& isFeasible) {
Ted Kremenek
committed
// First, determine if sym == X, where X != V.
if (const llvm::APSInt* X = St->getSymVal(sym)) {
Ted Kremenek
committed
isFeasible = *X != V;
return St;
}
// Second, determine if sym != V.
if (St->isNotEqual(sym, V)) {
Ted Kremenek
committed
isFeasible = true;
return St;
}
// If we reach here, sym is not a constant and we don't know if it is != V.
// Make that assumption.
isFeasible = true;
return StateMgr.AddNE(St, sym, V);
}
ValueState*
GRExprEngine::AssumeSymEQ(ValueState* St, SymbolID sym,
Ted Kremenek
committed
const llvm::APSInt& V, bool& isFeasible) {
// First, determine if sym == X, where X != V.
if (const llvm::APSInt* X = St->getSymVal(sym)) {
Ted Kremenek
committed
isFeasible = *X == V;
return St;
}
// Second, determine if sym != V.
if (St->isNotEqual(sym, V)) {
Ted Kremenek
committed
isFeasible = false;
return St;
}
// If we reach here, sym is not a constant and we don't know if it is == V.
// Make that assumption.
isFeasible = true;
return StateMgr.AddEQ(St, sym, V);
}
ValueState*
GRExprEngine::AssumeSymInt(ValueState* St, bool Assumption,
Ted Kremenek
committed
const SymIntConstraint& C, bool& isFeasible) {
switch (C.getOpcode()) {
default:
// No logic yet for other operators.
Ted Kremenek
committed
isFeasible = true;
Ted Kremenek
committed
return St;
case BinaryOperator::EQ:
if (Assumption)
return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
else
return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
case BinaryOperator::NE:
if (Assumption)
return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
else
return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
}
}
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
#ifndef NDEBUG
static GRExprEngine* GraphPrintCheckerState;
Ted Kremenek
committed
static SourceManager* GraphPrintSourceManager;
Ted Kremenek
committed
static ValueState::CheckerStatePrinter* GraphCheckerStatePrinter;
namespace llvm {
template<>
struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
public DefaultDOTGraphTraits {
static void PrintVarBindings(std::ostream& Out, ValueState* St) {
Out << "Variables:\\l";
bool isFirst = true;
for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E;++I) {
if (isFirst)
isFirst = false;
else
Out << "\\l";
Out << ' ' << I.getKey()->getName() << " : ";
I.getData().print(Out);
}
}
static void PrintSubExprBindings(std::ostream& Out, ValueState* St){
bool isFirst = true;
for (ValueState::seb_iterator I=St->seb_begin(), E=St->seb_end();I!=E;++I) {
if (isFirst) {
Out << "\\l\\lSub-Expressions:\\l";
isFirst = false;
}
else
Out << "\\l";
Out << " (" << (void*) I.getKey() << ") ";
I.getKey()->printPretty(Out);
Out << " : ";
I.getData().print(Out);
}
}
static void PrintBlkExprBindings(std::ostream& Out, ValueState* St){
bool isFirst = true;
for (ValueState::beb_iterator I=St->beb_begin(), E=St->beb_end(); I!=E;++I){
if (isFirst) {
Out << "\\l\\lBlock-level Expressions:\\l";
isFirst = false;
}
else
Out << "\\l";
Out << " (" << (void*) I.getKey() << ") ";
I.getKey()->printPretty(Out);
Out << " : ";
I.getData().print(Out);
}
}
static void PrintEQ(std::ostream& Out, ValueState* St) {
ValueState::ConstEqTy CE = St->ConstEq;
if (CE.isEmpty())
return;
Out << "\\l\\|'==' constraints:";
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, ValueState* St) {
ValueState::ConstNotEqTy NE = St->ConstNotEq;
if (NE.isEmpty())
return;
Out << "\\l\\|'!=' constraints:";
for (ValueState::ConstNotEqTy::iterator I=NE.begin(), EI=NE.end();
I != EI; ++I){
Out << "\\l $" << I.getKey() << " : ";
bool isFirst = true;
ValueState::IntSetTy::iterator J=I.getData().begin(),
EJ=I.getData().end();
for ( ; J != EJ; ++J) {
if (isFirst) isFirst = false;
else Out << ", ";
Out << (*J)->toString();
}
}
}
static std::string getNodeAttributes(const GRExprEngine::NodeTy* N, void*) {
if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
GraphPrintCheckerState->isExplicitNullDeref(N) ||
Ted Kremenek
committed
GraphPrintCheckerState->isUndefDeref(N) ||
GraphPrintCheckerState->isUndefStore(N) ||
GraphPrintCheckerState->isUndefControlFlow(N) ||
GraphPrintCheckerState->isExplicitBadDivide(N) ||
GraphPrintCheckerState->isImplicitBadDivide(N) ||
Ted Kremenek
committed
GraphPrintCheckerState->isUndefResult(N) ||
GraphPrintCheckerState->isBadCall(N) ||
GraphPrintCheckerState->isUndefArg(N))
return "color=\"red\",style=\"filled\"";
Ted Kremenek
committed
if (GraphPrintCheckerState->isNoReturnCall(N))
return "color=\"blue\",style=\"filled\"";
return "";
}
static std::string getNodeLabel(const GRExprEngine::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::PostLoadKind:
case ProgramPoint::PostPurgeDeadSymbolsKind:
case ProgramPoint::PostStmtKind: {
Ted Kremenek
committed
const PostStmt& L = cast<PostStmt>(Loc);
Stmt* S = L.getStmt();
SourceLocation SLoc = S->getLocStart();
Out << S->getStmtClassName() << ' ' << (void*) S << ' ';
S->printPretty(Out);
if (SLoc.isFileID()) {
Out << "\\lline="
<< GraphPrintSourceManager->getLineNumber(SLoc) << " col="
<< GraphPrintSourceManager->getColumnNumber(SLoc) << "\\l";
}
Ted Kremenek
committed
if (GraphPrintCheckerState->isImplicitNullDeref(N))
Out << "\\|Implicit-Null Dereference.\\l";
Ted Kremenek
committed
else if (GraphPrintCheckerState->isExplicitNullDeref(N))
Ted Kremenek
committed
Out << "\\|Explicit-Null Dereference.\\l";
Ted Kremenek
committed
else if (GraphPrintCheckerState->isUndefDeref(N))
Ted Kremenek
committed
Out << "\\|Dereference of undefialied value.\\l";
Ted Kremenek
committed
else if (GraphPrintCheckerState->isUndefStore(N))
Ted Kremenek
committed
Out << "\\|Store to Undefined LVal.";
else if (GraphPrintCheckerState->isExplicitBadDivide(N))
Out << "\\|Explicit divide-by zero or undefined value.";
else if (GraphPrintCheckerState->isImplicitBadDivide(N))
Out << "\\|Implicit divide-by zero or undefined value.";
Ted Kremenek
committed
else if (GraphPrintCheckerState->isUndefResult(N))
Ted Kremenek
committed
Out << "\\|Result of operation is undefined.";
else if (GraphPrintCheckerState->isNoReturnCall(N))
Out << "\\|Call to function marked \"noreturn\".";
Ted Kremenek
committed
else if (GraphPrintCheckerState->isBadCall(N))
Out << "\\|Call to NULL/Undefined.";
else if (GraphPrintCheckerState->isUndefArg(N))
Out << "\\|Argument in call is undefined";
break;
}
default: {
const BlockEdge& E = cast<BlockEdge>(Loc);
Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
<< E.getDst()->getBlockID() << ')';
if (Stmt* T = E.getSrc()->getTerminator()) {
Ted Kremenek
committed
SourceLocation SLoc = T->getLocStart();
Out << "\\|Terminator: ";
Ted Kremenek
committed
E.getSrc()->printTerminator(Out);
if (SLoc.isFileID()) {
Out << "\\lline="
<< GraphPrintSourceManager->getLineNumber(SLoc) << " col="
<< GraphPrintSourceManager->getColumnNumber(SLoc);
}
Ted Kremenek
committed
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
if (isa<SwitchStmt>(T)) {
Stmt* Label = E.getDst()->getLabel();
if (Label) {
if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
Out << "\\lcase ";
C->getLHS()->printPretty(Out);
if (Stmt* RHS = C->getRHS()) {
Out << " .. ";
RHS->printPretty(Out);
}
Out << ":";
}
else {
assert (isa<DefaultStmt>(Label));
Out << "\\ldefault:";
}
}
else
Out << "\\l(implicit) default:";
}
else if (isa<IndirectGotoStmt>(T)) {
// FIXME
}
else {
Out << "\\lCondition: ";
if (*E.getSrc()->succ_begin() == E.getDst())
Out << "true";
else
Out << "false";
}
Out << "\\l";
}
Ted Kremenek
committed
if (GraphPrintCheckerState->isUndefControlFlow(N)) {
Out << "\\|Control-flow based on\\lUndefined value.\\l";
}
}
}
Out << "\\|StateID: " << (void*) N->getState() << "\\|";
Ted Kremenek
committed
N->getState()->printDOT(Out, GraphCheckerStatePrinter);
Ted Kremenek
committed
Out << "\\l";
return Out.str();
}
};
} // end llvm namespace
#endif
#ifndef NDEBUG
template <typename ITERATOR>
GRExprEngine::NodeTy* GetGraphNode(ITERATOR I) { return *I; }
template <>
GRExprEngine::NodeTy*
GetGraphNode<llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator>
(llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator I) {
return I->first;
}
template <typename ITERATOR>
static void AddSources(std::vector<GRExprEngine::NodeTy*>& Sources,
ITERATOR I, ITERATOR E) {
llvm::SmallPtrSet<void*,10> CachedSources;
for ( ; I != E; ++I ) {
GRExprEngine::NodeTy* N = GetGraphNode(I);
void* p = N->getLocation().getRawData();
if (CachedSources.count(p))
continue;
CachedSources.insert(p);
Sources.push_back(N);
}
}
#endif
void GRExprEngine::ViewGraph(bool trim) {
#ifndef NDEBUG
if (trim) {
std::vector<NodeTy*> Src;
// Fixme: Migrate over to the new way of adding nodes.
AddSources(Src, null_derefs_begin(), null_derefs_end());
AddSources(Src, undef_derefs_begin(), undef_derefs_end());
AddSources(Src, explicit_bad_divides_begin(), explicit_bad_divides_end());
AddSources(Src, undef_results_begin(), undef_results_end());
AddSources(Src, bad_calls_begin(), bad_calls_end());
AddSources(Src, undef_arg_begin(), undef_arg_end());
AddSources(Src, undef_branches_begin(), undef_branches_end());
// The new way.
for (BugTypeSet::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
(*I)->GetErrorNodes(Src);
ViewGraph(&Src[0], &Src[0]+Src.size());
}
else {
GraphPrintCheckerState = this;
GraphPrintSourceManager = &getContext().getSourceManager();
Ted Kremenek
committed
GraphCheckerStatePrinter = TF->getCheckerStatePrinter();
llvm::ViewGraph(*G.roots_begin(), "GRExprEngine");
GraphPrintCheckerState = NULL;
GraphPrintSourceManager = NULL;
Ted Kremenek
committed
GraphCheckerStatePrinter = NULL;
}
#endif
}
void GRExprEngine::ViewGraph(NodeTy** Beg, NodeTy** End) {
#ifndef NDEBUG
GraphPrintCheckerState = this;
GraphPrintSourceManager = &getContext().getSourceManager();
Ted Kremenek
committed
GraphCheckerStatePrinter = TF->getCheckerStatePrinter();
GRExprEngine::GraphTy* TrimmedG = G.Trim(Beg, End);
if (!TrimmedG)
llvm::cerr << "warning: Trimmed ExplodedGraph is empty.\n";
else {
llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedGRExprEngine");
delete TrimmedG;
}
GraphPrintCheckerState = NULL;
Ted Kremenek
committed
GraphPrintSourceManager = NULL;
Ted Kremenek
committed
GraphCheckerStatePrinter = NULL;