From: Jordan Rose Date: Sat, 6 Apr 2013 01:42:02 +0000 (+0000) Subject: [analyzer] When creating a trimmed graph, preserve whether a node is a sink. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3e5ebf1a05603e08f2d0b2b2a5fa9406fe4cfb22;p=clang [analyzer] When creating a trimmed graph, preserve whether a node is a sink. This is important because sometimes two nodes are identical, except the second one is a sink. This bug has probably been around for a while, but it wouldn't have been an issue in the old report graph algorithm. I'm ashamed to say I actually looked at this the first time around and thought it would never be a problem...and then didn't include an assertion to back that up. PR15684 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178944 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 8f8eb3bb85..76cfb89d49 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2010,7 +2010,8 @@ bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) { while (true) { // Create the equivalent node in the new graph with the same state // and location. - ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState()); + ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState(), + OrigN->isSink()); // Store the mapping to the original node. InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN); diff --git a/test/Analysis/misc-ps.c b/test/Analysis/misc-ps.c index 5369ab1061..b302860a2f 100644 --- a/test/Analysis/misc-ps.c +++ b/test/Analysis/misc-ps.c @@ -163,3 +163,15 @@ int PR14634(int x) { return !y; } + +// PR15684: If a checker generates a sink node after generating a regular node +// and no state changes between the two, graph trimming would consider the two +// the same node, forming a loop. +struct PR15684 { + void (*callback)(int); +}; +void sinkAfterRegularNode(struct PR15684 *context) { + int uninitialized; + context->callback(uninitialized); // expected-warning {{uninitialized}} +} +