mirror of
https://github.com/intel/llvm.git
synced 2026-02-09 01:52:26 +08:00
--grsimple now reports the number of nodes in the ExplodedGraph for
an analyzed function. GRExprEngine now records stores to "uninitialized lvalues" (which are sinks in the ExplodedGraph). llvm-svn: 47293
This commit is contained in:
@@ -304,15 +304,14 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
|
||||
|
||||
RValue R1 = GetValue(PrevState, B->getLHS());
|
||||
RValue R2 = GetValue(PrevState, B->getRHS(), hasR2);
|
||||
|
||||
if (isa<UnknownVal>(R1) &&
|
||||
(isa<UnknownVal>(R2) ||
|
||||
isa<UninitializedVal>(R2))) {
|
||||
|
||||
Nodify(Dst, B, Pred, SetValue(PrevState, B, R2));
|
||||
return;
|
||||
}
|
||||
else if (isa<UninitializedVal>(R1)) {
|
||||
|
||||
if (hasR2) {
|
||||
if (isa<UninitializedVal>(R2) || isa<UnknownVal>(R2)) {
|
||||
Nodify(Dst, B, Pred, SetValue(PrevState, B, R2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (isa<UninitializedVal>(R1) || isa<UnknownVal>(R1)) {
|
||||
Nodify(Dst, B, Pred, SetValue(PrevState, B, R1));
|
||||
return;
|
||||
}
|
||||
@@ -709,7 +708,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
||||
switch (Op) {
|
||||
case BinaryOperator::Assign: {
|
||||
const LValue& L1 = cast<LValue>(V1);
|
||||
Nodify(Dst, B, N2, SetValue(SetValue(St, B, V2), L1, V2));
|
||||
|
||||
if (isa<UninitializedVal>(L1))
|
||||
HandleUninitializedStore(B, N2);
|
||||
else
|
||||
Nodify(Dst, B, N2, SetValue(SetValue(St, B, V2), L1, V2));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -718,6 +722,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
||||
assert (B->isCompoundAssignmentOp());
|
||||
|
||||
const LValue& L1 = cast<LValue>(V1);
|
||||
|
||||
if (isa<UninitializedVal>(L1)) {
|
||||
HandleUninitializedStore(B, N2);
|
||||
break;
|
||||
}
|
||||
|
||||
RValue Result = cast<NonLValue>(UnknownVal());
|
||||
|
||||
if (Op >= BinaryOperator::AndAssign)
|
||||
@@ -763,9 +773,14 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
||||
}
|
||||
}
|
||||
|
||||
void GRExprEngine::HandleUninitializedStore(Stmt* S, NodeTy* Pred) {
|
||||
|
||||
NodeTy* N = Builder->generateNode(S, Pred->getState(), Pred);
|
||||
N->markAsSink();
|
||||
UninitStores.insert(N);
|
||||
}
|
||||
|
||||
void GRExprEngine::Visit(Stmt* S, GRExprEngine::NodeTy* Pred,
|
||||
GRExprEngine::NodeSet& Dst) {
|
||||
void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
|
||||
|
||||
// FIXME: add metadata to the CFG so that we can disable
|
||||
// this check when we KNOW that there is no block-level subexpression.
|
||||
@@ -1137,7 +1152,9 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
|
||||
static std::string getNodeAttributes(const GRExprEngine::NodeTy* N, void*) {
|
||||
|
||||
if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
|
||||
GraphPrintCheckerState->isExplicitNullDeref(N))
|
||||
GraphPrintCheckerState->isExplicitNullDeref(N) ||
|
||||
GraphPrintCheckerState->isUninitStore(N) ||
|
||||
GraphPrintCheckerState->isUninitControlFlow(N))
|
||||
return "color=\"red\",style=\"filled\"";
|
||||
|
||||
return "";
|
||||
@@ -1172,6 +1189,9 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
|
||||
else if (GraphPrintCheckerState->isExplicitNullDeref(N)) {
|
||||
Out << "\\|Explicit-Null Dereference.\\l";
|
||||
}
|
||||
else if (GraphPrintCheckerState->isUninitStore(N)) {
|
||||
Out << "\\|Store to Uninitialized LValue.";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
using namespace clang;
|
||||
|
||||
namespace clang {
|
||||
void RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
|
||||
Diagnostic& Diag, bool Visualize) {
|
||||
unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
|
||||
Diagnostic& Diag, bool Visualize) {
|
||||
|
||||
if (Diag.hasErrorOccurred())
|
||||
return;
|
||||
return 0;
|
||||
|
||||
GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
|
||||
GRExprEngine* CheckerState = &Engine.getCheckerState();
|
||||
@@ -31,7 +31,7 @@ namespace clang {
|
||||
CheckerState->setTransferFunctions(GRSV);
|
||||
|
||||
// Execute the worklist algorithm.
|
||||
Engine.ExecuteWorkList(10000);
|
||||
Engine.ExecuteWorkList(200);
|
||||
|
||||
// Look for explicit-Null dereferences and warn about them.
|
||||
for (GRExprEngine::null_iterator I=CheckerState->null_begin(),
|
||||
@@ -46,7 +46,9 @@ namespace clang {
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (Visualize) CheckerState->ViewGraph();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return Engine.getGraph().size();
|
||||
}
|
||||
} // end clang namespace
|
||||
|
||||
|
||||
@@ -329,7 +329,9 @@ ValueStateManager::SetValue(ValueState St, Expr* E, bool isBlkExpr,
|
||||
ValueState
|
||||
ValueStateManager::SetValue(ValueState St, const LValue& LV, const RValue& V) {
|
||||
|
||||
assert (!isa<UnknownVal>(LV));
|
||||
if (isa<UnknownVal>(LV))
|
||||
return St;
|
||||
|
||||
assert (!isa<UninitializedVal>(LV));
|
||||
|
||||
switch (LV.getSubKind()) {
|
||||
|
||||
@@ -611,9 +611,9 @@ void GRSimpleValsVisitor::VisitCFG(CFG& C, FunctionDecl& FD) {
|
||||
|
||||
llvm::Timer T("GRSimpleVals");
|
||||
T.startTimer();
|
||||
RunGRSimpleVals(C, FD, *Ctx, Diags, Visualize);
|
||||
unsigned size = RunGRSimpleVals(C, FD, *Ctx, Diags, Visualize);
|
||||
T.stopTimer();
|
||||
llvm::cerr << T.getWallTime() << '\n';
|
||||
llvm::cerr << size << ' ' << T.getWallTime() << '\n';
|
||||
}
|
||||
else {
|
||||
llvm::cerr << '\n';
|
||||
|
||||
@@ -23,9 +23,9 @@ namespace clang {
|
||||
/// RunGRSimpleVals - This is a simple driver to run the GRSimpleVals analysis
|
||||
/// on a provided CFG. This interface will eventually be replaced with
|
||||
/// something more elaborate as the requirements on the interface become
|
||||
/// clearer.
|
||||
void RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
|
||||
Diagnostic& Diag, bool Visualize);
|
||||
/// clearer. The value returned is the number of nodes in the ExplodedGraph.
|
||||
unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
|
||||
Diagnostic& Diag, bool Visualize);
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
|
||||
@@ -114,13 +114,17 @@ protected:
|
||||
typedef llvm::SmallPtrSet<NodeTy*,5> UninitBranchesTy;
|
||||
UninitBranchesTy UninitBranches;
|
||||
|
||||
/// UninitStores - Sinks in the ExplodedGraph that result from
|
||||
/// making a store to an uninitialized lvalue.
|
||||
typedef llvm::SmallPtrSet<NodeTy*,5> UninitStoresTy;
|
||||
UninitStoresTy UninitStores;
|
||||
|
||||
/// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
|
||||
/// taking a dereference on a symbolic pointer that may be NULL.
|
||||
typedef llvm::SmallPtrSet<NodeTy*,5> NullDerefTy;
|
||||
NullDerefTy ImplicitNullDeref;
|
||||
NullDerefTy ExplicitNullDeref;
|
||||
|
||||
|
||||
bool StateCleaned;
|
||||
|
||||
public:
|
||||
@@ -171,6 +175,10 @@ public:
|
||||
return N->isSink() && UninitBranches.count(const_cast<NodeTy*>(N)) != 0;
|
||||
}
|
||||
|
||||
bool isUninitStore(const NodeTy* N) const {
|
||||
return N->isSink() && UninitStores.count(const_cast<NodeTy*>(N)) != 0;
|
||||
}
|
||||
|
||||
bool isImplicitNullDeref(const NodeTy* N) const {
|
||||
return N->isSink() && ImplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0;
|
||||
}
|
||||
@@ -275,6 +283,10 @@ public:
|
||||
/// The states are not guaranteed to be unique.
|
||||
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.
|
||||
void HandleUninitializedStore(Stmt* S, NodeTy* Pred);
|
||||
|
||||
/// Visit - Transfer function logic for all statements. Dispatches to
|
||||
/// other functions that handle specific kinds of statements.
|
||||
void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
|
||||
|
||||
Reference in New Issue
Block a user