[analyzer] Track leaking object through stores
authorValeriy Savchenko <vsavchenko@apple.com>
Tue, 20 Apr 2021 14:08:55 +0000 (17:08 +0300)
committerValeriy Savchenko <vsavchenko@apple.com>
Wed, 28 Apr 2021 15:37:38 +0000 (18:37 +0300)
Since we can report memory leaks on one variable, while the originally
allocated object was stored into another one, we should explain
how did it get there.

rdar://76645710

Differential Revision: https://reviews.llvm.org/D100852

clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
clang/test/Analysis/Inputs/expected-plists/edges-new.mm.plist
clang/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
clang/test/Analysis/osobject-retain-release.cpp
clang/test/Analysis/retain-release-path-notes.m

index 48b5f8d..eaa1e35 100644 (file)
@@ -616,7 +616,7 @@ static Optional<std::string> describeRegion(const MemRegion *MR) {
   return None;
 }
 
-using Bindings = llvm::SmallVector<const MemRegion *, 4>;
+using Bindings = llvm::SmallVector<std::pair<const MemRegion *, SVal>, 4>;
 
 class VarBindingsCollector : public StoreManager::BindingsHandler {
   SymbolRef Sym;
@@ -633,7 +633,7 @@ public:
       return true;
 
     if (isa<NonParamVarRegion>(R))
-      Result.push_back(R);
+      Result.emplace_back(R, Val);
 
     return true;
   }
@@ -968,11 +968,28 @@ void RefLeakReport::findBindingToReport(CheckerContext &Ctx,
   // `AllocFirstBinding` to be one of them.  In situations like this,
   // it would still be the easiest case to explain to our users.
   if (!AllVarBindings.empty() &&
-      llvm::count(AllVarBindings, AllocFirstBinding) == 0)
+      llvm::count_if(AllVarBindings,
+                     [this](const std::pair<const MemRegion *, SVal> Binding) {
+                       return Binding.first == AllocFirstBinding;
+                     }) == 0) {
     // Let's pick one of them at random (if there is something to pick from).
-    AllocBindingToReport = AllVarBindings[0];
-  else
+    AllocBindingToReport = AllVarBindings[0].first;
+
+    // Because 'AllocBindingToReport' is not the the same as
+    // 'AllocFirstBinding', we need to explain how the leaking object
+    // got from one to another.
+    //
+    // NOTE: We use the actual SVal stored in AllocBindingToReport here because
+    //       FindLastStoreBRVisitor compares SVal's and it can get trickier for
+    //       something like derived regions if we want to construct SVal from
+    //       Sym. Instead, we take the value that is definitely stored in that
+    //       region, thus guaranteeing that FindLastStoreBRVisitor will work.
+    addVisitor(std::make_unique<FindLastStoreBRVisitor>(
+        AllVarBindings[0].second.castAs<KnownSVal>(), AllocBindingToReport,
+        false, bugreporter::TrackingKind::Thorough));
+  } else {
     AllocBindingToReport = AllocFirstBinding;
+  }
 }
 
 RefLeakReport::RefLeakReport(const RefCountBug &D, const LangOptions &LOpts,
index 0665e97..62cd52b 100644 (file)
       </array>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>566</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>566</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>566</integer>
+         <key>col</key><integer>11</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;garply&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;garply&apos; initialized here</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
index 185525c..3b0ce87 100644 (file)
      <string>Method returns an instance of MyObj with a +1 retain count</string>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>215</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>215</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>215</integer>
+         <key>col</key><integer>21</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>1</integer>
+     <key>extended_message</key>
+     <string>Value assigned to &apos;self&apos;</string>
+     <key>message</key>
+     <string>Value assigned to &apos;self&apos;</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
+      <key>line</key><integer>216</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>216</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>216</integer>
+         <key>col</key><integer>13</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>1</integer>
+     <key>extended_message</key>
+     <string>Returning pointer (loaded from &apos;self&apos;)</string>
+     <key>message</key>
+     <string>Returning pointer (loaded from &apos;self&apos;)</string>
+    </dict>
+    <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
       <key>line</key><integer>337</integer>
       <key>col</key><integer>17</integer>
       <key>file</key><integer>0</integer>
       </array>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>337</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>337</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>337</integer>
+         <key>col</key><integer>13</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;Original&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;Original&apos; initialized here</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
           </dict>
           <dict>
            <key>line</key><integer>342</integer>
-           <key>col</key><integer>3</integer>
+           <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
          </array>
         </dict>
         <dict>
          <key>line</key><integer>342</integer>
+         <key>col</key><integer>8</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;New&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;New&apos; initialized here</string>
+    </dict>
+    <dict>
+     <key>kind</key><string>control</string>
+     <key>edges</key>
+      <array>
+       <dict>
+        <key>start</key>
+         <array>
+          <dict>
+           <key>line</key><integer>342</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+          <dict>
+           <key>line</key><integer>342</integer>
+           <key>col</key><integer>4</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+         </array>
+        <key>end</key>
+         <array>
+          <dict>
+           <key>line</key><integer>345</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+          <dict>
+           <key>line</key><integer>345</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+         </array>
+       </dict>
+      </array>
+    </dict>
+    <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>345</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>345</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>345</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>342</integer>
+   <key>line</key><integer>345</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
     <integer>221</integer>
     <integer>336</integer>
     <integer>337</integer>
-    <integer>339</integer>
-    <integer>340</integer>
-    <integer>341</integer>
     <integer>342</integer>
+    <integer>343</integer>
+    <integer>344</integer>
+    <integer>345</integer>
    </array>
   </dict>
   </dict>
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>350</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>350</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>350</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>350</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>347</integer>
+      <key>line</key><integer>350</integer>
       <key>col</key><integer>17</integer>
       <key>file</key><integer>0</integer>
      </dict>
      <array>
        <array>
         <dict>
-         <key>line</key><integer>347</integer>
+         <key>line</key><integer>350</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>347</integer>
+         <key>line</key><integer>350</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
      <string>Method returns an instance of MyObj with a +1 retain count</string>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>215</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>215</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>215</integer>
+         <key>col</key><integer>21</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>1</integer>
+     <key>extended_message</key>
+     <string>Value assigned to &apos;self&apos;</string>
+     <key>message</key>
+     <string>Value assigned to &apos;self&apos;</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>347</integer>
+      <key>line</key><integer>216</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>216</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>216</integer>
+         <key>col</key><integer>13</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>1</integer>
+     <key>extended_message</key>
+     <string>Returning pointer (loaded from &apos;self&apos;)</string>
+     <key>message</key>
+     <string>Returning pointer (loaded from &apos;self&apos;)</string>
+    </dict>
+    <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>350</integer>
       <key>col</key><integer>17</integer>
       <key>file</key><integer>0</integer>
      </dict>
      <array>
        <array>
         <dict>
-         <key>line</key><integer>347</integer>
+         <key>line</key><integer>350</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>347</integer>
+         <key>line</key><integer>350</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>350</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>350</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>350</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+          <dict>
+           <key>line</key><integer>350</integer>
+           <key>col</key><integer>4</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+         </array>
+       </dict>
+      </array>
+    </dict>
+    <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>350</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>350</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>350</integer>
+         <key>col</key><integer>13</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;Original&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;Original&apos; initialized here</string>
+    </dict>
+    <dict>
+     <key>kind</key><string>control</string>
+     <key>edges</key>
+      <array>
+       <dict>
+        <key>start</key>
+         <array>
+          <dict>
+           <key>line</key><integer>350</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+          <dict>
+           <key>line</key><integer>350</integer>
+           <key>col</key><integer>4</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+         </array>
+        <key>end</key>
+         <array>
+          <dict>
+           <key>line</key><integer>355</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+          <dict>
+           <key>line</key><integer>355</integer>
+           <key>col</key><integer>4</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+         </array>
+       </dict>
+      </array>
+    </dict>
+    <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>355</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>355</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>355</integer>
+         <key>col</key><integer>17</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;Intermediate&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;Intermediate&apos; initialized here</string>
+    </dict>
+    <dict>
+     <key>kind</key><string>control</string>
+     <key>edges</key>
+      <array>
+       <dict>
+        <key>start</key>
+         <array>
+          <dict>
+           <key>line</key><integer>355</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+          <dict>
+           <key>line</key><integer>355</integer>
+           <key>col</key><integer>4</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+         </array>
+        <key>end</key>
+         <array>
+          <dict>
+           <key>line</key><integer>356</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>356</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
       </array>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>356</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>356</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>356</integer>
+         <key>col</key><integer>8</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;New&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;New&apos; initialized here</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>356</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>347</integer>
+           <key>line</key><integer>356</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>353</integer>
+           <key>line</key><integer>359</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>353</integer>
+           <key>line</key><integer>359</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>353</integer>
+      <key>line</key><integer>359</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
      <array>
        <array>
         <dict>
-         <key>line</key><integer>353</integer>
+         <key>line</key><integer>359</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>353</integer>
+         <key>line</key><integer>359</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>353</integer>
+   <key>line</key><integer>359</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
     <integer>219</integer>
     <integer>220</integer>
     <integer>221</integer>
-    <integer>346</integer>
-    <integer>347</integer>
     <integer>349</integer>
     <integer>350</integer>
-    <integer>351</integer>
-    <integer>352</integer>
-    <integer>353</integer>
+    <integer>355</integer>
+    <integer>356</integer>
+    <integer>357</integer>
+    <integer>358</integer>
+    <integer>359</integer>
    </array>
   </dict>
   </dict>
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>371</integer>
+      <key>line</key><integer>377</integer>
       <key>col</key><integer>17</integer>
       <key>file</key><integer>0</integer>
      </dict>
      <array>
        <array>
         <dict>
-         <key>line</key><integer>371</integer>
+         <key>line</key><integer>377</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>371</integer>
+         <key>line</key><integer>377</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
      <string>Method returns an instance of MyObj with a +1 retain count</string>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>215</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>215</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>215</integer>
+         <key>col</key><integer>21</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>1</integer>
+     <key>extended_message</key>
+     <string>Value assigned to &apos;self&apos;</string>
+     <key>message</key>
+     <string>Value assigned to &apos;self&apos;</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>371</integer>
+      <key>line</key><integer>216</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>216</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>216</integer>
+         <key>col</key><integer>13</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>1</integer>
+     <key>extended_message</key>
+     <string>Returning pointer (loaded from &apos;self&apos;)</string>
+     <key>message</key>
+     <string>Returning pointer (loaded from &apos;self&apos;)</string>
+    </dict>
+    <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>377</integer>
       <key>col</key><integer>17</integer>
       <key>file</key><integer>0</integer>
      </dict>
      <array>
        <array>
         <dict>
-         <key>line</key><integer>371</integer>
+         <key>line</key><integer>377</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>371</integer>
+         <key>line</key><integer>377</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
       </array>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>377</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>377</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>377</integer>
+         <key>col</key><integer>13</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;Original&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;Original&apos; initialized here</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>371</integer>
+           <key>line</key><integer>377</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>376</integer>
+           <key>line</key><integer>383</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+          <dict>
+           <key>line</key><integer>383</integer>
+           <key>col</key><integer>5</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+         </array>
+       </dict>
+      </array>
+    </dict>
+    <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>383</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>383</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>383</integer>
+         <key>col</key><integer>16</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>Value assigned to &apos;New&apos;</string>
+     <key>message</key>
+     <string>Value assigned to &apos;New&apos;</string>
+    </dict>
+    <dict>
+     <key>kind</key><string>control</string>
+     <key>edges</key>
+      <array>
+       <dict>
+        <key>start</key>
+         <array>
+          <dict>
+           <key>line</key><integer>383</integer>
+           <key>col</key><integer>3</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+          <dict>
+           <key>line</key><integer>383</integer>
+           <key>col</key><integer>5</integer>
+           <key>file</key><integer>0</integer>
+          </dict>
+         </array>
+        <key>end</key>
+         <array>
+          <dict>
+           <key>line</key><integer>386</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>376</integer>
+           <key>line</key><integer>386</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>376</integer>
+      <key>line</key><integer>386</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
      <array>
        <array>
         <dict>
-         <key>line</key><integer>376</integer>
+         <key>line</key><integer>386</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>376</integer>
+         <key>line</key><integer>386</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>376</integer>
+   <key>line</key><integer>386</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
     <integer>219</integer>
     <integer>220</integer>
     <integer>221</integer>
-    <integer>357</integer>
-    <integer>358</integer>
-    <integer>359</integer>
-    <integer>360</integer>
     <integer>363</integer>
     <integer>364</integer>
     <integer>365</integer>
     <integer>366</integer>
-    <integer>367</integer>
+    <integer>369</integer>
     <integer>370</integer>
     <integer>371</integer>
+    <integer>372</integer>
     <integer>373</integer>
-    <integer>374</integer>
-    <integer>375</integer>
     <integer>376</integer>
+    <integer>377</integer>
+    <integer>382</integer>
+    <integer>383</integer>
+    <integer>384</integer>
+    <integer>385</integer>
+    <integer>386</integer>
    </array>
   </dict>
   </dict>
index 5ccca4c..61d96c6 100644 (file)
      <string>Object autoreleased</string>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>2286</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>2286</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>2286</integer>
+         <key>col</key><integer>18</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;second&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;second&apos; initialized here</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
      <string>Object autoreleased</string>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>2306</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>2306</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>2306</integer>
+         <key>col</key><integer>18</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;alias&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;alias&apos; initialized here</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
index 56d93bd..44da78a 100644 (file)
      <string>Object autoreleased</string>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>2286</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>2286</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>2286</integer>
+         <key>col</key><integer>18</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;second&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;second&apos; initialized here</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
      <string>Object autoreleased</string>
     </dict>
     <dict>
+     <key>kind</key><string>event</string>
+     <key>location</key>
+     <dict>
+      <key>line</key><integer>2306</integer>
+      <key>col</key><integer>3</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+       <array>
+        <dict>
+         <key>line</key><integer>2306</integer>
+         <key>col</key><integer>3</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+        <dict>
+         <key>line</key><integer>2306</integer>
+         <key>col</key><integer>18</integer>
+         <key>file</key><integer>0</integer>
+        </dict>
+       </array>
+     </array>
+     <key>depth</key><integer>0</integer>
+     <key>extended_message</key>
+     <string>&apos;alias&apos; initialized here</string>
+     <key>message</key>
+     <string>&apos;alias&apos; initialized here</string>
+    </dict>
+    <dict>
      <key>kind</key><string>control</string>
      <key>edges</key>
       <array>
index 3b56697..38d5968 100644 (file)
@@ -526,19 +526,58 @@ void check_dynamic_cast_null_branch(OSObject *obj) {
 
 void check_dynamic_cast_null_check() {
   OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1)); // expected-note{{Call to method 'OSObject::generateObject' returns an OSObject}}
-    // expected-warning@-1{{Potential leak of an object}}
-    // expected-note@-2{{Object leaked}}
-    // expected-note@-3{{Assuming dynamic cast returns null due to type mismatch}}
+                                                                      // expected-warning@-1{{Potential leak of an object}}
+                                                                      // expected-note@-2{{Object leaked}}
+                                                                      // expected-note@-3{{Assuming dynamic cast returns null due to type mismatch}}
   if (!arr)
     return;
   arr->release();
 }
 
+void check_dynamic_cast_alias() {
+  OSObject *originalPtr = OSObject::generateObject(1);   // expected-note {{Call to method 'OSObject::generateObject' returns an OSObject}}
+  OSArray *newPtr = OSDynamicCast(OSArray, originalPtr); // expected-note {{'newPtr' initialized here}}
+  if (newPtr) {                                          // expected-note {{'newPtr' is non-null}}
+                                                         // expected-note@-1 {{Taking true branch}}
+    originalPtr = OSObject::generateObject(42);
+    (void)newPtr;
+  }
+  originalPtr->release(); // expected-warning {{Potential leak of an object stored into 'newPtr'}}
+                          // expected-note@-1 {{Object leaked: object allocated and stored into 'newPtr' is not referenced later in this execution path and has a retain count of +1}}
+}
+
+void check_dynamic_cast_alias_cond() {
+  OSObject *originalPtr = OSObject::generateObject(1); // expected-note {{Call to method 'OSObject::generateObject' returns an OSObject}}
+  OSArray *newPtr = 0;
+  if ((newPtr = OSDynamicCast(OSArray, originalPtr))) { // expected-note {{Value assigned to 'newPtr'}}
+                                                        // expected-note@-1 {{'newPtr' is non-null}}
+                                                        // expected-note@-2 {{Taking true branch}}
+    originalPtr = OSObject::generateObject(42);
+    (void)newPtr;
+  }
+  originalPtr->release(); // expected-warning {{Potential leak of an object stored into 'newPtr'}}
+                          // expected-note@-1 {{Object leaked: object allocated and stored into 'newPtr' is not referenced later in this execution path and has a retain count of +1}}
+}
+
+void check_dynamic_cast_alias_intermediate() {
+  OSObject *originalPtr = OSObject::generateObject(1); // expected-note {{Call to method 'OSObject::generateObject' returns an OSObject of type 'OSObject' with a +1 retain count}}
+  OSObject *intermediate = originalPtr;                // TODO: add note here as well
+  OSArray *newPtr = 0;
+  if ((newPtr = OSDynamicCast(OSArray, intermediate))) { // expected-note {{Value assigned to 'newPtr'}}
+                                                         // expected-note@-1 {{'newPtr' is non-null}}
+                                                         // expected-note@-2 {{Taking true branch}}
+    intermediate = OSObject::generateObject(42);
+    (void)newPtr;
+  }
+  intermediate->release(); // expected-warning {{Potential leak of an object stored into 'newPtr'}}
+                           // expected-note@-1 {{Object leaked: object allocated and stored into 'newPtr' is not referenced later in this execution path and has a retain count of +1}}
+}
+
 void use_after_release() {
   OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
-  arr->release(); // expected-note{{Object released}}
-  arr->getCount(); // expected-warning{{Reference-counted object is used after it is released}}
-                   // expected-note@-1{{Reference-counted object is used after it is released}}
+  arr->release();                           // expected-note{{Object released}}
+  arr->getCount();                          // expected-warning{{Reference-counted object is used after it is released}}
+                                            // expected-note@-1{{Reference-counted object is used after it is released}}
 }
 
 void potential_leak() {
@@ -642,6 +681,7 @@ void test_smart_ptr_leak() {
   {
     OSObjectPtr p(obj); // expected-note{{Calling constructor for 'smart_ptr<OSObject>'}}
                         // expected-note@-1{{Returning from constructor for 'smart_ptr<OSObject>'}}
+                        // expected-note@-2 {{'p' initialized here}}
     // expected-note@os_smart_ptr.h:13{{Field 'pointer' is non-null}}
     // expected-note@os_smart_ptr.h:13{{Taking true branch}}
     // expected-note@os_smart_ptr.h:14{{Calling 'smart_ptr::_retain'}}
index e8ce8b4..9bf3b74 100644 (file)
@@ -335,8 +335,11 @@ int seed();
 @implementation LeakReassignmentTests
 +(void)testLeakAliasSimple {
   id Original = [[MyObj alloc] initY]; // expected-note {{Calling 'initY'}}
-                                       // expected-note@-1 {{Returning from 'initY'}}
-  id New = Original;
+                                       // expected-note@215 {{Value assigned to 'self'}}
+                                       // expected-note@216 {{Returning pointer (loaded from 'self')}}
+                                       // expected-note@-3 {{Returning from 'initY'}}
+                                       // expected-note@-4 {{'Original' initialized here}}
+  id New = Original;                   // expected-note {{'New' initialized here}}
   Original = [[MyObj alloc] initZ];
   (void)New;
   [Original release]; // expected-warning {{Potential leak of an object stored into 'New'}}
@@ -345,9 +348,12 @@ int seed();
 
 +(void)testLeakAliasChain {
   id Original = [[MyObj alloc] initY]; // expected-note {{Calling 'initY'}}
-                                       // expected-note@-1 {{Returning from 'initY'}}
-  id Intermediate = Original;
-  id New = Intermediate;
+                                       // expected-note@215 {{Value assigned to 'self'}}
+                                       // expected-note@216 {{Returning pointer (loaded from 'self')}}
+                                       // expected-note@-3 {{Returning from 'initY'}}
+                                       // expected-note@-4 {{'Original' initialized here}}
+  id Intermediate = Original;          // expected-note {{'Intermediate' initialized here}}
+  id New = Intermediate;               // expected-note {{'New' initialized here}}
   Original = [[MyObj alloc] initZ];
   (void)New;
   [Original release]; // expected-warning {{Potential leak of an object stored into 'New'}}
@@ -369,8 +375,12 @@ int seed();
 
 +(void)testLeakAliasDeathInExpr {
   id Original = [[MyObj alloc] initY]; // expected-note {{Calling 'initY'}}
-                                       // expected-note@-1 {{Returning from 'initY'}}
-  id New = Original;
+                                       // expected-note@215 {{Value assigned to 'self'}}
+                                       // expected-note@216 {{Returning pointer (loaded from 'self')}}
+                                       // expected-note@-3 {{Returning from 'initY'}}
+                                       // expected-note@-4 {{'Original' initialized here}}
+  id New = 0;
+  New = Original; // expected-note {{Value assigned to 'New'}}
   Original = [[MyObj alloc] initZ];
   [self log:New with:[self calculate]];
   [Original release]; // expected-warning {{Potential leak of an object stored into 'New'}}