From 4bf38da038cebf9396470630c3c39519e41706da Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 5 Mar 2008 21:15:02 +0000 Subject: [PATCH] Fixed bug that could case unwanted bifurcation of states when evaluating calls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47964 91177308-0d34-0410-b5e6-96231b3b80d8 --- Analysis/GRExprEngine.cpp | 55 ++++++++++++------- .../Analysis/PathSensitive/ExplodedGraph.h | 2 + .../Analysis/PathSensitive/GRCoreEngine.h | 10 +++- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp index 77e97875d0..f8ebbec597 100644 --- a/Analysis/GRExprEngine.cpp +++ b/Analysis/GRExprEngine.cpp @@ -21,6 +21,18 @@ #include #endif +// SaveAndRestore - A utility class that uses RIIA to save and restore +// the value of a variable. +template +struct VISIBILITY_HIDDEN SaveAndRestore { + SaveAndRestore(T& x) : X(x), old_value(x) {} + ~SaveAndRestore() { X = old_value; } + T get() { return old_value; } + + T& X; + T old_value; +}; + using namespace clang; using llvm::dyn_cast; using llvm::cast; @@ -482,7 +494,27 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, } continue; - } + } + + // Check for the "noreturn" attribute. + + SaveAndRestore OldSink(Builder->BuildSinks); + + if (isa(L)) + if (cast(L).getDecl()->getAttr()) { + for (NodeSet::iterator I=Dst.begin(), E=Dst.end(); I != E; ++I ) { + + NodeTy* N = *I; + + if (!N->isSink()) + N->markAsSink(); + } + + Builder->BuildSinks = true; + } + + // Evaluate the call. + bool invalidateArgs = false; @@ -506,7 +538,9 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, if (isa(V)) St = SetRVal(St, cast(V), UnknownVal()); - } + } + + Nodify(Dst, CE, *DI, St); } else { @@ -542,23 +576,6 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, if (Dst.size() == size) Nodify(Dst, CE, *DI, St); } - - // Check for the "noreturn" attribute. - - if (isa(L)) - if (cast(L).getDecl()->getAttr()) { - - NodeTy* N = Builder->generateNode(CE, St, *DI); - - if (N) { - N->markAsSink(); - NoReturnCalls.insert(N); - } - - continue; - } - - Nodify(Dst, CE, *DI, St); } } diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h index c1dc2224f8..65936399b3 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -389,6 +389,8 @@ public: inline unsigned size() const { return Impl.size(); } inline bool empty() const { return Impl.empty(); } + + inline void clear() { Impl.clear(); } inline iterator begin() { return Impl.begin(); } inline iterator end() { return Impl.end(); } diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h index 151f202dee..e38f86e07a 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -162,7 +162,7 @@ class GRStmtNodeBuilder { GRStmtNodeBuilderImpl& NB; public: - GRStmtNodeBuilder(GRStmtNodeBuilderImpl& nb) : NB(nb) {} + GRStmtNodeBuilder(GRStmtNodeBuilderImpl& nb) : NB(nb), BuildSinks(false) {} NodeTy* getLastNode() const { return static_cast(NB.getLastNode()); @@ -186,10 +186,16 @@ public: } NodeTy* N = generateNode(S, St, Pred); - Dst.Add(N); + + if (N && BuildSinks) + N->markAsSink(); + else + Dst.Add(N); + return N; } + bool BuildSinks; }; class GRBranchNodeBuilderImpl {