summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-02-19 00:22:37 +0000
committerTed Kremenek <kremenek@apple.com>2008-02-19 00:22:37 +0000
commit0f7130adc4492977eabc7b2fee65844fbf964c5e (patch)
tree731d75e9485c3f8a2255bc78281e613c567f0a18
parentc58fc4052e16b056ff776444f2eb03f7176cbf27 (diff)
downloadbcm5719-llvm-0f7130adc4492977eabc7b2fee65844fbf964c5e.tar.gz
bcm5719-llvm-0f7130adc4492977eabc7b2fee65844fbf964c5e.zip
--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
-rw-r--r--clang/Analysis/GRExprEngine.cpp46
-rw-r--r--clang/Analysis/GRSimpleVals.cpp12
-rw-r--r--clang/Analysis/ValueState.cpp4
-rw-r--r--clang/Driver/ASTConsumers.cpp4
-rw-r--r--clang/include/clang/Analysis/Analyses/GRSimpleVals.h6
-rw-r--r--clang/include/clang/Analysis/PathSensitive/GRExprEngine.h14
6 files changed, 61 insertions, 25 deletions
diff --git a/clang/Analysis/GRExprEngine.cpp b/clang/Analysis/GRExprEngine.cpp
index d709eff99fd..a004dc49080 100644
--- a/clang/Analysis/GRExprEngine.cpp
+++ b/clang/Analysis/GRExprEngine.cpp
@@ -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;
}
diff --git a/clang/Analysis/GRSimpleVals.cpp b/clang/Analysis/GRSimpleVals.cpp
index 87b39b70c53..c7fdfd050de 100644
--- a/clang/Analysis/GRSimpleVals.cpp
+++ b/clang/Analysis/GRSimpleVals.cpp
@@ -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
diff --git a/clang/Analysis/ValueState.cpp b/clang/Analysis/ValueState.cpp
index 016b070547a..32be0c6d713 100644
--- a/clang/Analysis/ValueState.cpp
+++ b/clang/Analysis/ValueState.cpp
@@ -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()) {
diff --git a/clang/Driver/ASTConsumers.cpp b/clang/Driver/ASTConsumers.cpp
index 9759e9af73c..305503fe07c 100644
--- a/clang/Driver/ASTConsumers.cpp
+++ b/clang/Driver/ASTConsumers.cpp
@@ -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';
diff --git a/clang/include/clang/Analysis/Analyses/GRSimpleVals.h b/clang/include/clang/Analysis/Analyses/GRSimpleVals.h
index 83b647360a3..62e10e943b0 100644
--- a/clang/include/clang/Analysis/Analyses/GRSimpleVals.h
+++ b/clang/include/clang/Analysis/Analyses/GRSimpleVals.h
@@ -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
diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h
index ff9c26cf7c6..1bdbb2afda9 100644
--- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -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);
OpenPOWER on IntegriCloud