From: Ted Kremenek Date: Tue, 19 Feb 2008 00:22:37 +0000 (+0000) Subject: --grsimple now reports the number of nodes in the ExplodedGraph for X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9dca062461a6244cf0f733346657fa3eee853f9b;p=clang --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). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47293 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp index d709eff99f..a004dc4908 100644 --- a/Analysis/GRExprEngine.cpp +++ b/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(R1) && - (isa(R2) || - isa(R2))) { - - Nodify(Dst, B, Pred, SetValue(PrevState, B, R2)); - return; - } - else if (isa(R1)) { + + if (hasR2) { + if (isa(R2) || isa(R2)) { + Nodify(Dst, B, Pred, SetValue(PrevState, B, R2)); + return; + } + } + else if (isa(R1) || isa(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(V1); - Nodify(Dst, B, N2, SetValue(SetValue(St, B, V2), L1, V2)); + + if (isa(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(V1); + + if (isa(L1)) { + HandleUninitializedStore(B, N2); + break; + } + RValue Result = cast(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 : 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 : else if (GraphPrintCheckerState->isExplicitNullDeref(N)) { Out << "\\|Explicit-Null Dereference.\\l"; } + else if (GraphPrintCheckerState->isUninitStore(N)) { + Out << "\\|Store to Uninitialized LValue."; + } break; } diff --git a/Analysis/GRSimpleVals.cpp b/Analysis/GRSimpleVals.cpp index 87b39b70c5..c7fdfd050d 100644 --- a/Analysis/GRSimpleVals.cpp +++ b/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 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/Analysis/ValueState.cpp b/Analysis/ValueState.cpp index 016b070547..32be0c6d71 100644 --- a/Analysis/ValueState.cpp +++ b/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(LV)); + if (isa(LV)) + return St; + assert (!isa(LV)); switch (LV.getSubKind()) { diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 9759e9af73..305503fe07 100644 --- a/Driver/ASTConsumers.cpp +++ b/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/include/clang/Analysis/Analyses/GRSimpleVals.h b/include/clang/Analysis/Analyses/GRSimpleVals.h index 83b647360a..62e10e943b 100644 --- a/include/clang/Analysis/Analyses/GRSimpleVals.h +++ b/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/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index ff9c26cf7c..1bdbb2afda 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -114,13 +114,17 @@ protected: typedef llvm::SmallPtrSet UninitBranchesTy; UninitBranchesTy UninitBranches; + /// UninitStores - Sinks in the ExplodedGraph that result from + /// making a store to an uninitialized lvalue. + typedef llvm::SmallPtrSet 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 NullDerefTy; NullDerefTy ImplicitNullDeref; NullDerefTy ExplicitNullDeref; - bool StateCleaned; public: @@ -171,6 +175,10 @@ public: return N->isSink() && UninitBranches.count(const_cast(N)) != 0; } + bool isUninitStore(const NodeTy* N) const { + return N->isSink() && UninitStores.count(const_cast(N)) != 0; + } + bool isImplicitNullDeref(const NodeTy* N) const { return N->isSink() && ImplicitNullDeref.count(const_cast(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);