]> granicus.if.org Git - clang/commitdiff
[analyzer] Mark symbol values as dead in the environment.
authorJordan Rose <jordan_rose@apple.com>
Thu, 15 Nov 2012 19:11:27 +0000 (19:11 +0000)
committerJordan Rose <jordan_rose@apple.com>
Thu, 15 Nov 2012 19:11:27 +0000 (19:11 +0000)
This allows us to properly remove dead bindings at the end of the top-level
stack frame, using the ReturnStmt, if there is one, to keep the return value
live. This in turn removes the need for a check::EndPath callback in leak
checkers.

This does cause some changes in the path notes for leak checkers. Previously,
a leak would be reported at the location of the closing brace in a function.
Now, it gets reported at the last statement. This matches the way leaks are
currently reported for inlined functions, but is less than ideal for both.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168066 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
lib/StaticAnalyzer/Core/Environment.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
test/Analysis/malloc-plist.c
test/Analysis/malloc.c
test/Analysis/plist-output-alternate.m

index 78b254222e9e19d7970b01c260c7e6abd4fb329c..17de90e0001a35c7a142f6b6572ba0d3490ed157 100644 (file)
@@ -154,26 +154,33 @@ public:
   const ExplodedGraph& getGraph() const { return G; }
 
   /// \brief Run the analyzer's garbage collection - remove dead symbols and
-  /// bindings.
+  /// bindings from the state.
   ///
-  /// \param Node - The predecessor node, from which the processing should 
-  /// start.
-  /// \param Out - The returned set of output nodes.
-  /// \param ReferenceStmt - Run garbage collection using the symbols, 
-  /// which are live before the given statement.
-  /// \param LC - The location context of the ReferenceStmt.
-  /// \param DiagnosticStmt - the statement used to associate the diagnostic 
-  /// message, if any warnings should occur while removing the dead (leaks 
-  /// are usually reported here).
-  /// \param K - In some cases it is possible to use PreStmt kind. (Do 
-  /// not use it unless you know what you are doing.) 
-  /// If the ReferenceStmt is NULL, everything is this and parent contexts is
-  /// considered live.
-  /// If the stack frame context is NULL, everything on stack is considered
-  /// dead.
+  /// Checkers can participate in this process with two callbacks:
+  /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation
+  /// class for more information.
+  ///
+  /// \param Node The predecessor node, from which the processing should start.
+  /// \param Out The returned set of output nodes.
+  /// \param ReferenceStmt The statement which is about to be processed.
+  ///        Everything needed for this statement should be considered live.
+  ///        A null statement means that everything in child LocationContexts
+  ///        is dead.
+  /// \param LC The location context of the \p ReferenceStmt. A null location
+  ///        context means that we have reached the end of analysis and that
+  ///        all statements and local variables should be considered dead.
+  /// \param DiagnosticStmt Used as a location for any warnings that should
+  ///        occur while removing the dead (e.g. leaks). By default, the
+  ///        \p ReferenceStmt is used.
+  /// \param K Denotes whether this is a pre- or post-statement purge. This
+  ///        must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an
+  ///        entire location context is being cleared, in which case the
+  ///        \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise,
+  ///        it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default)
+  ///        and \p ReferenceStmt must be valid (non-null).
   void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
-            const Stmt *ReferenceStmt, const StackFrameContext *LC,
-            const Stmt *DiagnosticStmt,
+            const Stmt *ReferenceStmt, const LocationContext *LC,
+            const Stmt *DiagnosticStmt = 0,
             ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
 
   /// processCFGElement - Called by CoreEngine. Used to generate new successor
index bab89c545c343f79ec93e8c6b359102e2fd086bd..7dcd12c5bdf511c04be6cc83ebdf94f7566661cb 100644 (file)
@@ -241,6 +241,10 @@ EnvironmentManager::removeDeadBindings(Environment Env,
       // Mark all symbols in the block expr's value live.
       RSScaner.scan(X);
       continue;
+    } else {
+      SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
+      for (; SI != SE; ++SI)
+        SymReaper.maybeDead(*SI);
     }
   }
   
index 045591c9074bea61ebe3502dc406605ac8e38206..42bfe144db081c391c226db6977ed3ba9af8057e 100644 (file)
@@ -268,22 +268,39 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
 
 void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
                             const Stmt *ReferenceStmt,
-                            const StackFrameContext *LC,
+                            const LocationContext *LC,
                             const Stmt *DiagnosticStmt,
                             ProgramPoint::Kind K) {
   assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
-          ReferenceStmt == 0)
+          ReferenceStmt == 0 || isa<ReturnStmt>(ReferenceStmt))
           && "PostStmt is not generally supported by the SymbolReaper yet");
+  assert(LC && "Must pass the current (or expiring) LocationContext");
+
+  if (!DiagnosticStmt) {
+    DiagnosticStmt = ReferenceStmt;
+    assert(DiagnosticStmt && "Required for clearing a LocationContext");
+  }
+
   NumRemoveDeadBindings++;
   CleanedState = Pred->getState();
-  SymbolReaper SymReaper(LC, ReferenceStmt, SymMgr, getStoreManager());
+
+  // LC is the location context being destroyed, but SymbolReaper wants a
+  // location context that is still live. (If this is the top-level stack
+  // frame, this will be null.)
+  if (!ReferenceStmt) {
+    assert(K == ProgramPoint::PostStmtPurgeDeadSymbolsKind &&
+           "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");
+    LC = LC->getParent();
+  }
+
+  const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : 0;
+  SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());
 
   getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
 
   // Create a state in which dead bindings are removed from the environment
   // and the store. TODO: The function should just return new env and store,
   // not a new state.
-  const StackFrameContext *SFC = LC->getCurrentStackFrame();
   CleanedState = StateMgr.removeDeadBindings(CleanedState, SFC, SymReaper);
 
   // Process any special transfer function for dead symbols.
@@ -345,8 +362,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S,
   EntryNode = Pred;
   ExplodedNodeSet CleanedStates;
   if (shouldRemoveDeadBindings(AMgr, S, Pred, EntryNode->getLocationContext())){
-    removeDead(EntryNode, CleanedStates, currStmt,
-               Pred->getStackFrame(), currStmt);
+    removeDead(EntryNode, CleanedStates, currStmt, Pred->getLocationContext());
   } else
     CleanedStates.Add(EntryNode);
 
index 3ead0817f71b15ec42519be3852fe1f472d5f93e..a98e8b4922860e812483d52b193e8abc60b8b725 100644 (file)
@@ -168,27 +168,24 @@ static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy,
 void ExprEngine::removeDeadOnEndOfFunction(NodeBuilderContext& BC,
                                            ExplodedNode *Pred,
                                            ExplodedNodeSet &Dst) {
-  NodeBuilder Bldr(Pred, Dst, BC);
-
   // Find the last statement in the function and the corresponding basic block.
   const Stmt *LastSt = 0;
   const CFGBlock *Blk = 0;
   llvm::tie(LastSt, Blk) = getLastStmt(Pred);
   if (!Blk || !LastSt) {
+    Dst.Add(Pred);
     return;
   }
-  
-  // If the last statement is return, everything it references should stay live.
-  if (isa<ReturnStmt>(LastSt))
-    return;
 
   // Here, we call the Symbol Reaper with 0 stack context telling it to clean up
   // everything on the stack. We use LastStmt as a diagnostic statement, with 
-  // which the PreStmtPurgeDead point will be associated.
-  currBldrCtx = &BC;
-  removeDead(Pred, Dst, 0, 0, LastSt,
+  // which the program point will be associated. However, we only want to use
+  // LastStmt as a reference for what to clean up if it's a ReturnStmt;
+  // otherwise, everything is dead.
+  SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);
+  removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt),
+             Pred->getLocationContext(), LastSt,
              ProgramPoint::PostStmtPurgeDeadSymbolsKind);
-  currBldrCtx = 0;
 }
 
 static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call,
@@ -290,11 +287,11 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
 
     NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
     currBldrCtx = &Ctx;
-    // Here, we call the Symbol Reaper with 0 statement and caller location
+    // Here, we call the Symbol Reaper with 0 statement and callee location
     // context, telling it to clean up everything in the callee's context
-    // (and it's children). We use LastStmt as a diagnostic statement, which
-    // which the PreStmtPurge Dead point will be associated.
-    removeDead(BindedRetNode, CleanedNodes, 0, callerCtx, LastSt,
+    // (and its children). We use LastSt as a diagnostic statement, which
+    // which the program point will be associated.
+    removeDead(BindedRetNode, CleanedNodes, 0, calleeCtx, LastSt,
                ProgramPoint::PostStmtPurgeDeadSymbolsKind);
     currBldrCtx = 0;
   } else {
index 12430a6ffbf334e4556b0f841b2c20d4a49bae65..a99e34f4264d5b470ddcea49aa94751ecfaa64a7 100644 (file)
@@ -235,7 +235,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Assuming &apos;in&apos; is &gt; 5</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;in&apos; is &gt; 5</string>
+// CHECK-NEXT:      <string>Assuming &apos;in&apos; is &gt; 5</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -332,7 +332,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -380,7 +380,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;p&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;p&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;p&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;p&apos;</string>
@@ -494,7 +494,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -517,13 +517,13 @@ void use_function_with_leak7() {
 // CHECK-NEXT:         <key>end</key>
 // CHECK-NEXT:          <array>
 // CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>22</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
+// CHECK-NEXT:            <key>line</key><integer>21</integer>
+// CHECK-NEXT:            <key>col</key><integer>5</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>22</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
+// CHECK-NEXT:            <key>line</key><integer>21</integer>
+// CHECK-NEXT:            <key>col</key><integer>5</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:          </array>
@@ -534,15 +534,15 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>kind</key><string>event</string>
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
-// CHECK-NEXT:       <key>line</key><integer>22</integer>
-// CHECK-NEXT:       <key>col</key><integer>1</integer>
+// CHECK-NEXT:       <key>line</key><integer>21</integer>
+// CHECK-NEXT:       <key>col</key><integer>5</integer>
 // CHECK-NEXT:       <key>file</key><integer>0</integer>
 // CHECK-NEXT:      </dict>
 // CHECK-NEXT:      <key>depth</key><integer>0</integer>
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;A&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;A&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;A&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;A&apos;</string>
@@ -550,11 +550,11 @@ void use_function_with_leak7() {
 // CHECK-NEXT:    <key>type</key><string>Memory leak</string>
 // CHECK-NEXT:   <key>issue_context_kind</key><string>function</string>
 // CHECK-NEXT:   <key>issue_context</key><string>myArrayAllocation</string>
-// CHECK-NEXT:   <key>issue_hash</key><integer>4</integer>
+// CHECK-NEXT:   <key>issue_hash</key><integer>3</integer>
 // CHECK-NEXT:   <key>location</key>
 // CHECK-NEXT:   <dict>
-// CHECK-NEXT:    <key>line</key><integer>22</integer>
-// CHECK-NEXT:    <key>col</key><integer>1</integer>
+// CHECK-NEXT:    <key>line</key><integer>21</integer>
+// CHECK-NEXT:    <key>col</key><integer>5</integer>
 // CHECK-NEXT:    <key>file</key><integer>0</integer>
 // CHECK-NEXT:   </dict>
 // CHECK-NEXT:   </dict>
@@ -622,7 +622,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -719,7 +719,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Attempt to reallocate memory</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Attempt to reallocate memory</string>
+// CHECK-NEXT:      <string>Attempt to reallocate memory</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -816,7 +816,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Assuming &apos;tmp&apos; is null</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;tmp&apos; is null</string>
+// CHECK-NEXT:      <string>Assuming &apos;tmp&apos; is null</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -879,7 +879,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Reallocation failed</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Reallocation failed</string>
+// CHECK-NEXT:      <string>Reallocation failed</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -927,7 +927,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
@@ -1007,7 +1007,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;wrapper&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;wrapper&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;wrapper&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -1021,7 +1021,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;test_wrapper&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_wrapper&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;test_wrapper&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1118,7 +1118,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1215,7 +1215,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Assuming &apos;x&apos; is non-null</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is non-null</string>
+// CHECK-NEXT:      <string>Assuming &apos;x&apos; is non-null</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1278,7 +1278,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Returned allocated memory</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
+// CHECK-NEXT:      <string>Returned allocated memory</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1301,13 +1301,13 @@ void use_function_with_leak7() {
 // CHECK-NEXT:         <key>end</key>
 // CHECK-NEXT:          <array>
 // CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>46</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
+// CHECK-NEXT:            <key>line</key><integer>45</integer>
+// CHECK-NEXT:            <key>col</key><integer>3</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>46</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
+// CHECK-NEXT:            <key>line</key><integer>45</integer>
+// CHECK-NEXT:            <key>col</key><integer>3</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:          </array>
@@ -1318,15 +1318,15 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>kind</key><string>event</string>
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
-// CHECK-NEXT:       <key>line</key><integer>46</integer>
-// CHECK-NEXT:       <key>col</key><integer>1</integer>
+// CHECK-NEXT:       <key>line</key><integer>45</integer>
+// CHECK-NEXT:       <key>col</key><integer>3</integer>
 // CHECK-NEXT:       <key>file</key><integer>0</integer>
 // CHECK-NEXT:      </dict>
 // CHECK-NEXT:      <key>depth</key><integer>0</integer>
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
@@ -1334,11 +1334,11 @@ void use_function_with_leak7() {
 // CHECK-NEXT:    <key>type</key><string>Memory leak</string>
 // CHECK-NEXT:   <key>issue_context_kind</key><string>function</string>
 // CHECK-NEXT:   <key>issue_context</key><string>test_wrapper</string>
-// CHECK-NEXT:   <key>issue_hash</key><integer>3</integer>
+// CHECK-NEXT:   <key>issue_hash</key><integer>2</integer>
 // CHECK-NEXT:   <key>location</key>
 // CHECK-NEXT:   <dict>
-// CHECK-NEXT:    <key>line</key><integer>46</integer>
-// CHECK-NEXT:    <key>col</key><integer>1</integer>
+// CHECK-NEXT:    <key>line</key><integer>45</integer>
+// CHECK-NEXT:    <key>col</key><integer>3</integer>
 // CHECK-NEXT:    <key>file</key><integer>0</integer>
 // CHECK-NEXT:   </dict>
 // CHECK-NEXT:   </dict>
@@ -1406,7 +1406,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;my_malloc_and_free&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;my_malloc_and_free&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;my_malloc_and_free&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -1420,7 +1420,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;test_double_action_call&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_double_action_call&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;test_double_action_call&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1517,7 +1517,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1614,7 +1614,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;my_free&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;my_free&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;my_free&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -1628,7 +1628,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;my_malloc_and_free&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;my_malloc_and_free&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;my_malloc_and_free&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1691,7 +1691,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is released</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is released</string>
+// CHECK-NEXT:      <string>Memory is released</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -1720,7 +1720,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Returned released memory via 1st parameter</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Returned released memory via 1st parameter</string>
+// CHECK-NEXT:      <string>Returned released memory via 1st parameter</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1783,7 +1783,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Returned released memory via 1st parameter</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Returned released memory via 1st parameter</string>
+// CHECK-NEXT:      <string>Returned released memory via 1st parameter</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1846,7 +1846,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Use of memory after it is freed</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Use of memory after it is freed</string>
+// CHECK-NEXT:      <string>Use of memory after it is freed</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Use of memory after it is freed</string>
@@ -1926,7 +1926,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -1989,7 +1989,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;my_realloc&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;my_realloc&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;my_realloc&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -2003,7 +2003,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;reallocIntra&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;reallocIntra&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;reallocIntra&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2134,7 +2134,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Attempt to reallocate memory</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Attempt to reallocate memory</string>
+// CHECK-NEXT:      <string>Attempt to reallocate memory</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2231,7 +2231,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Assuming &apos;tmp&apos; is null</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;tmp&apos; is null</string>
+// CHECK-NEXT:      <string>Assuming &apos;tmp&apos; is null</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2294,7 +2294,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Reallocation failed</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Reallocation failed</string>
+// CHECK-NEXT:      <string>Reallocation failed</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2357,7 +2357,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Reallocation of 1st parameter failed</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Reallocation of 1st parameter failed</string>
+// CHECK-NEXT:      <string>Reallocation of 1st parameter failed</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2405,7 +2405,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;buf&apos;</string>
@@ -2485,7 +2485,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;malloc_wrapper_ret&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;malloc_wrapper_ret&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;malloc_wrapper_ret&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -2499,7 +2499,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;use_ret&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_ret&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;use_ret&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2596,7 +2596,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -2625,7 +2625,41 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Returned allocated memory</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
+// CHECK-NEXT:      <string>Returned allocated memory</string>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>control</string>
+// CHECK-NEXT:      <key>edges</key>
+// CHECK-NEXT:       <array>
+// CHECK-NEXT:        <dict>
+// CHECK-NEXT:         <key>start</key>
+// CHECK-NEXT:          <array>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>86</integer>
+// CHECK-NEXT:            <key>col</key><integer>5</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>86</integer>
+// CHECK-NEXT:            <key>col</key><integer>5</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:          </array>
+// CHECK-NEXT:         <key>end</key>
+// CHECK-NEXT:          <array>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>86</integer>
+// CHECK-NEXT:            <key>col</key><integer>9</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>86</integer>
+// CHECK-NEXT:            <key>col</key><integer>26</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:          </array>
+// CHECK-NEXT:        </dict>
+// CHECK-NEXT:       </array>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2648,13 +2682,13 @@ void use_function_with_leak7() {
 // CHECK-NEXT:         <key>end</key>
 // CHECK-NEXT:          <array>
 // CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>87</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
+// CHECK-NEXT:            <key>line</key><integer>86</integer>
+// CHECK-NEXT:            <key>col</key><integer>5</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>87</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
+// CHECK-NEXT:            <key>line</key><integer>86</integer>
+// CHECK-NEXT:            <key>col</key><integer>5</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:          </array>
@@ -2665,15 +2699,15 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>kind</key><string>event</string>
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
-// CHECK-NEXT:       <key>line</key><integer>87</integer>
-// CHECK-NEXT:       <key>col</key><integer>1</integer>
+// CHECK-NEXT:       <key>line</key><integer>86</integer>
+// CHECK-NEXT:       <key>col</key><integer>5</integer>
 // CHECK-NEXT:       <key>file</key><integer>0</integer>
 // CHECK-NEXT:      </dict>
 // CHECK-NEXT:      <key>depth</key><integer>0</integer>
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;v&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;v&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;v&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;v&apos;</string>
@@ -2681,11 +2715,11 @@ void use_function_with_leak7() {
 // CHECK-NEXT:    <key>type</key><string>Memory leak</string>
 // CHECK-NEXT:   <key>issue_context_kind</key><string>function</string>
 // CHECK-NEXT:   <key>issue_context</key><string>use_ret</string>
-// CHECK-NEXT:   <key>issue_hash</key><integer>3</integer>
+// CHECK-NEXT:   <key>issue_hash</key><integer>2</integer>
 // CHECK-NEXT:   <key>location</key>
 // CHECK-NEXT:   <dict>
-// CHECK-NEXT:    <key>line</key><integer>87</integer>
-// CHECK-NEXT:    <key>col</key><integer>1</integer>
+// CHECK-NEXT:    <key>line</key><integer>86</integer>
+// CHECK-NEXT:    <key>col</key><integer>5</integer>
 // CHECK-NEXT:    <key>file</key><integer>0</integer>
 // CHECK-NEXT:   </dict>
 // CHECK-NEXT:   </dict>
@@ -2787,7 +2821,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2835,7 +2869,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;m&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;m&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;m&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;m&apos;</string>
@@ -2881,7 +2915,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;function_with_leak1&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak1&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;function_with_leak1&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -2895,7 +2929,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak1&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak1&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak1&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -2992,7 +3026,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3040,7 +3074,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
@@ -3086,7 +3120,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;function_with_leak2&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak2&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;function_with_leak2&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -3100,7 +3134,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak2&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak2&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak2&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3197,7 +3231,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3245,7 +3279,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
@@ -3291,7 +3325,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;function_with_leak3&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak3&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;function_with_leak3&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -3305,7 +3339,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak3&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak3&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak3&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3402,7 +3436,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3499,7 +3533,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Assuming &apos;y&apos; is not equal to 0</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is not equal to 0</string>
+// CHECK-NEXT:      <string>Assuming &apos;y&apos; is not equal to 0</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3547,7 +3581,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
@@ -3593,7 +3627,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;function_with_leak4&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak4&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;function_with_leak4&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -3607,7 +3641,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak4&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak4&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak4&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3704,7 +3738,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3801,7 +3835,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Assuming &apos;y&apos; is 0</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is 0</string>
+// CHECK-NEXT:      <string>Assuming &apos;y&apos; is 0</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -3849,7 +3883,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
@@ -3895,7 +3929,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;function_with_leak5&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak5&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;function_with_leak5&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -3909,7 +3943,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak5&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak5&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak5&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -4006,7 +4040,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -4054,7 +4088,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
@@ -4100,7 +4134,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;function_with_leak6&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak6&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;function_with_leak6&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -4114,7 +4148,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak6&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak6&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak6&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -4211,7 +4245,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -4259,7 +4293,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak of memory pointed to by &apos;x&apos;</string>
@@ -4305,7 +4339,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Calling &apos;function_with_leak7&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak7&apos;</string>
+// CHECK-NEXT:      <string>Calling &apos;function_with_leak7&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -4319,7 +4353,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak7&apos;</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak7&apos;</string>
+// CHECK-NEXT:      <string>Entered call from &apos;use_function_with_leak7&apos;</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>control</string>
@@ -4416,7 +4450,7 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
+// CHECK-NEXT:      <string>Memory is allocated</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
@@ -4445,55 +4479,21 @@ void use_function_with_leak7() {
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Returned allocated memory</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT:     </dict>
-// CHECK-NEXT:     <dict>
-// CHECK-NEXT:      <key>kind</key><string>control</string>
-// CHECK-NEXT:      <key>edges</key>
-// CHECK-NEXT:       <array>
-// CHECK-NEXT:        <dict>
-// CHECK-NEXT:         <key>start</key>
-// CHECK-NEXT:          <array>
-// CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>169</integer>
-// CHECK-NEXT:            <key>col</key><integer>5</integer>
-// CHECK-NEXT:            <key>file</key><integer>0</integer>
-// CHECK-NEXT:           </dict>
-// CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>169</integer>
-// CHECK-NEXT:            <key>col</key><integer>23</integer>
-// CHECK-NEXT:            <key>file</key><integer>0</integer>
-// CHECK-NEXT:           </dict>
-// CHECK-NEXT:          </array>
-// CHECK-NEXT:         <key>end</key>
-// CHECK-NEXT:          <array>
-// CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>170</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
-// CHECK-NEXT:            <key>file</key><integer>0</integer>
-// CHECK-NEXT:           </dict>
-// CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>170</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
-// CHECK-NEXT:            <key>file</key><integer>0</integer>
-// CHECK-NEXT:           </dict>
-// CHECK-NEXT:          </array>
-// CHECK-NEXT:        </dict>
-// CHECK-NEXT:       </array>
+// CHECK-NEXT:      <string>Returned allocated memory</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
-// CHECK-NEXT:       <key>line</key><integer>170</integer>
-// CHECK-NEXT:       <key>col</key><integer>1</integer>
+// CHECK-NEXT:       <key>line</key><integer>169</integer>
+// CHECK-NEXT:       <key>col</key><integer>5</integer>
 // CHECK-NEXT:       <key>file</key><integer>0</integer>
 // CHECK-NEXT:      </dict>
 // CHECK-NEXT:      <key>depth</key><integer>0</integer>
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Memory is never released; potential leak</string>
 // CHECK-NEXT:      <key>message</key>
-// CHECK-NEXT: <string>Memory is never released; potential leak</string>
+// CHECK-NEXT:      <string>Memory is never released; potential leak</string>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:    </array>
 // CHECK-NEXT:    <key>description</key><string>Memory is never released; potential leak</string>
@@ -4501,11 +4501,11 @@ void use_function_with_leak7() {
 // CHECK-NEXT:    <key>type</key><string>Memory leak</string>
 // CHECK-NEXT:   <key>issue_context_kind</key><string>function</string>
 // CHECK-NEXT:   <key>issue_context</key><string>use_function_with_leak7</string>
-// CHECK-NEXT:   <key>issue_hash</key><integer>2</integer>
+// CHECK-NEXT:   <key>issue_hash</key><integer>1</integer>
 // CHECK-NEXT:   <key>location</key>
 // CHECK-NEXT:   <dict>
-// CHECK-NEXT:    <key>line</key><integer>170</integer>
-// CHECK-NEXT:    <key>col</key><integer>1</integer>
+// CHECK-NEXT:    <key>line</key><integer>169</integer>
+// CHECK-NEXT:    <key>col</key><integer>5</integer>
 // CHECK-NEXT:    <key>file</key><integer>0</integer>
 // CHECK-NEXT:   </dict>
 // CHECK-NEXT:   </dict>
index b939ac36d1ac846fcfc6258866b94c75af5817c3..76dd3a8fda33d6c2314be101898a1d5e94a24116 100644 (file)
@@ -1030,6 +1030,11 @@ void *test(void *ptr) {
   return newPtr;
 }
 
+
+char *testLeakWithinReturn(char *str) {
+  return strdup(strdup(str)); // expected-warning{{leak}}
+}
+
 // ----------------------------------------------------------------------------
 // False negatives.
 
index 423574d7819b88fe70a08f27f2c42a9d753e5415..7bb81bed1c5fae2396b61f073c4f7c8d3f7f2bff 100644 (file)
@@ -1199,6 +1199,40 @@ void rdar8331641(int x) {
 // CHECK-NEXT:          <array>
 // CHECK-NEXT:           <dict>
 // CHECK-NEXT:            <key>line</key><integer>57</integer>
+// CHECK-NEXT:            <key>col</key><integer>3</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>57</integer>
+// CHECK-NEXT:            <key>col</key><integer>3</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:          </array>
+// CHECK-NEXT:        </dict>
+// CHECK-NEXT:       </array>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>control</string>
+// CHECK-NEXT:      <key>edges</key>
+// CHECK-NEXT:       <array>
+// CHECK-NEXT:        <dict>
+// CHECK-NEXT:         <key>start</key>
+// CHECK-NEXT:          <array>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>57</integer>
+// CHECK-NEXT:            <key>col</key><integer>3</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>57</integer>
+// CHECK-NEXT:            <key>col</key><integer>3</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:          </array>
+// CHECK-NEXT:         <key>end</key>
+// CHECK-NEXT:          <array>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>57</integer>
 // CHECK-NEXT:            <key>col</key><integer>10</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
@@ -1232,13 +1266,13 @@ void rdar8331641(int x) {
 // CHECK-NEXT:         <key>end</key>
 // CHECK-NEXT:          <array>
 // CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>58</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
+// CHECK-NEXT:            <key>line</key><integer>57</integer>
+// CHECK-NEXT:            <key>col</key><integer>3</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:           <dict>
-// CHECK-NEXT:            <key>line</key><integer>58</integer>
-// CHECK-NEXT:            <key>col</key><integer>1</integer>
+// CHECK-NEXT:            <key>line</key><integer>57</integer>
+// CHECK-NEXT:            <key>col</key><integer>3</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:          </array>
@@ -1249,10 +1283,25 @@ void rdar8331641(int x) {
 // CHECK-NEXT:      <key>kind</key><string>event</string>
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
-// CHECK-NEXT:       <key>line</key><integer>58</integer>
-// CHECK-NEXT:       <key>col</key><integer>1</integer>
+// CHECK-NEXT:       <key>line</key><integer>57</integer>
+// CHECK-NEXT:       <key>col</key><integer>3</integer>
 // CHECK-NEXT:       <key>file</key><integer>0</integer>
 // CHECK-NEXT:      </dict>
+// CHECK-NEXT:      <key>ranges</key>
+// CHECK-NEXT:      <array>
+// CHECK-NEXT:        <array>
+// CHECK-NEXT:         <dict>
+// CHECK-NEXT:          <key>line</key><integer>57</integer>
+// CHECK-NEXT:          <key>col</key><integer>3</integer>
+// CHECK-NEXT:          <key>file</key><integer>0</integer>
+// CHECK-NEXT:         </dict>
+// CHECK-NEXT:         <dict>
+// CHECK-NEXT:          <key>line</key><integer>57</integer>
+// CHECK-NEXT:          <key>col</key><integer>14</integer>
+// CHECK-NEXT:          <key>file</key><integer>0</integer>
+// CHECK-NEXT:         </dict>
+// CHECK-NEXT:        </array>
+// CHECK-NEXT:      </array>
 // CHECK-NEXT:      <key>depth</key><integer>0</integer>
 // CHECK-NEXT:      <key>extended_message</key>
 // CHECK-NEXT:      <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
@@ -1265,11 +1314,11 @@ void rdar8331641(int x) {
 // CHECK-NEXT:    <key>type</key><string>Leak</string>
 // CHECK-NEXT:   <key>issue_context_kind</key><string>function</string>
 // CHECK-NEXT:   <key>issue_context</key><string>rdar8331641</string>
-// CHECK-NEXT:   <key>issue_hash</key><integer>6</integer>
+// CHECK-NEXT:   <key>issue_hash</key><integer>5</integer>
 // CHECK-NEXT:   <key>location</key>
 // CHECK-NEXT:   <dict>
-// CHECK-NEXT:    <key>line</key><integer>58</integer>
-// CHECK-NEXT:    <key>col</key><integer>1</integer>
+// CHECK-NEXT:    <key>line</key><integer>57</integer>
+// CHECK-NEXT:    <key>col</key><integer>3</integer>
 // CHECK-NEXT:    <key>file</key><integer>0</integer>
 // CHECK-NEXT:   </dict>
 // CHECK-NEXT:   </dict>