diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-02-19 00:22:37 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-02-19 00:22:37 +0000 |
commit | 0f7130adc4492977eabc7b2fee65844fbf964c5e (patch) | |
tree | 731d75e9485c3f8a2255bc78281e613c567f0a18 | |
parent | c58fc4052e16b056ff776444f2eb03f7176cbf27 (diff) | |
download | bcm5719-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.cpp | 46 | ||||
-rw-r--r-- | clang/Analysis/GRSimpleVals.cpp | 12 | ||||
-rw-r--r-- | clang/Analysis/ValueState.cpp | 4 | ||||
-rw-r--r-- | clang/Driver/ASTConsumers.cpp | 4 | ||||
-rw-r--r-- | clang/include/clang/Analysis/Analyses/GRSimpleVals.h | 6 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/GRExprEngine.h | 14 |
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); |