aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp3
-rw-r--r--test/Analysis/misc-ps.c12
2 files changed, 14 insertions, 1 deletions
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}}
+}
+