r342770 - [analyzer] Process state in checkEndFunction in RetainCountChecker

George Karpenkov via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 21 13:37:20 PDT 2018


Author: george.karpenkov
Date: Fri Sep 21 13:37:20 2018
New Revision: 342770

URL: http://llvm.org/viewvc/llvm-project?rev=342770&view=rev
Log:
[analyzer] Process state in checkEndFunction in RetainCountChecker

Modify the RetainCountChecker to perform state "adjustments" in
checkEndFunction, as performing work in PreStmt<ReturnStmt> does not
work with destructors.
The previous version made an implicit assumption that no code runs
after the return statement is executed.

rdar://43945028

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

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
    cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
    cfe/trunk/test/Analysis/retain-release-arc.m
    cfe/trunk/test/Analysis/retain-release-path-notes.m

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp?rev=342770&r1=342769&r2=342770&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp Fri Sep 21 13:37:20 2018
@@ -814,12 +814,9 @@ bool RetainCountChecker::evalCall(const
   return true;
 }
 
-//===----------------------------------------------------------------------===//
-// Handle return statements.
-//===----------------------------------------------------------------------===//
-
-void RetainCountChecker::checkPreStmt(const ReturnStmt *S,
-                                      CheckerContext &C) const {
+ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
+                                                 CheckerContext &C) const {
+  ExplodedNode *Pred = C.getPredecessor();
 
   // Only adjust the reference count if this is the top-level call frame,
   // and not the result of inlining.  In the future, we should do
@@ -827,22 +824,25 @@ void RetainCountChecker::checkPreStmt(co
   // with their expected semantics (e.g., the method should return a retained
   // object, etc.).
   if (!C.inTopFrame())
-    return;
+    return Pred;
+
+  if (!S)
+    return Pred;
 
   const Expr *RetE = S->getRetValue();
   if (!RetE)
-    return;
+    return Pred;
 
   ProgramStateRef state = C.getState();
   SymbolRef Sym =
     state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
   if (!Sym)
-    return;
+    return Pred;
 
   // Get the reference count binding (if any).
   const RefVal *T = getRefBinding(state, Sym);
   if (!T)
-    return;
+    return Pred;
 
   // Change the reference count.
   RefVal X = *T;
@@ -861,20 +861,19 @@ void RetainCountChecker::checkPreStmt(co
       if (cnt) {
         X.setCount(cnt - 1);
         X = X ^ RefVal::ReturnedOwned;
-      }
-      else {
+      } else {
         X = X ^ RefVal::ReturnedNotOwned;
       }
       break;
     }
 
     default:
-      return;
+      return Pred;
   }
 
   // Update the binding.
   state = setRefBinding(state, Sym, X);
-  ExplodedNode *Pred = C.addTransition(state);
+  Pred = C.addTransition(state);
 
   // At this point we have updated the state properly.
   // Everything after this is merely checking to see if the return value has
@@ -882,15 +881,15 @@ void RetainCountChecker::checkPreStmt(co
 
   // Did we cache out?
   if (!Pred)
-    return;
+    return nullptr;
 
   // Update the autorelease counts.
   static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
-  state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
+  state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
 
-  // Did we cache out?
+  // Have we generated a sink node?
   if (!state)
-    return;
+    return nullptr;
 
   // Get the updated binding.
   T = getRefBinding(state, Sym);
@@ -913,10 +912,10 @@ void RetainCountChecker::checkPreStmt(co
     }
   }
 
-  checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
+  return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
 }
 
-void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
+ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
                                                   CheckerContext &C,
                                                   ExplodedNode *Pred,
                                                   RetEffect RE, RefVal X,
@@ -929,20 +928,17 @@ void RetainCountChecker::checkReturnWith
   //   [self addSubview:_contentView]; // invalidates 'self'
   //   [_contentView release];
   if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
-    return;
+    return Pred;
 
   // Any leaks or other errors?
   if (X.isReturnedOwned() && X.getCount() == 0) {
     if (RE.getKind() != RetEffect::NoRet) {
-      bool hasError = false;
       if (!RE.isOwned()) {
+
         // The returning type is a CF, we expect the enclosing method should
         // return ownership.
-        hasError = true;
         X = X ^ RefVal::ErrorLeakReturned;
-      }
 
-      if (hasError) {
         // Generate an error node.
         state = setRefBinding(state, Sym, X);
 
@@ -950,10 +946,12 @@ void RetainCountChecker::checkReturnWith
         ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
         if (N) {
           const LangOptions &LOpts = C.getASTContext().getLangOpts();
-          C.emitReport(llvm::make_unique<CFRefLeakReport>(
+          auto R = llvm::make_unique<CFRefLeakReport>(
               *getLeakAtReturnBug(LOpts), LOpts, SummaryLog, N, Sym, C,
-              IncludeAllocationLine));
+              IncludeAllocationLine);
+          C.emitReport(std::move(R));
         }
+        return N;
       }
     }
   } else if (X.isReturnedNotOwned()) {
@@ -977,13 +975,16 @@ void RetainCountChecker::checkReturnWith
           if (!returnNotOwnedForOwned)
             returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
 
-          C.emitReport(llvm::make_unique<CFRefReport>(
+          auto R = llvm::make_unique<CFRefReport>(
               *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
-              SummaryLog, N, Sym));
+              SummaryLog, N, Sym);
+          C.emitReport(std::move(R));
         }
+        return N;
       }
     }
   }
+  return Pred;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1107,16 +1108,14 @@ RetainCountChecker::checkRegionChanges(P
   return state;
 }
 
-//===----------------------------------------------------------------------===//
-// Handle dead symbols and end-of-path.
-//===----------------------------------------------------------------------===//
-
 ProgramStateRef
 RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
                                             ExplodedNode *Pred,
                                             const ProgramPointTag *Tag,
                                             CheckerContext &Ctx,
-                                            SymbolRef Sym, RefVal V) const {
+                                            SymbolRef Sym,
+                                            RefVal V,
+                                            const ReturnStmt *S) const {
   unsigned ACnt = V.getAutoreleaseCount();
 
   // No autorelease counts?  Nothing to be done.
@@ -1141,10 +1140,11 @@ RetainCountChecker::handleAutoreleaseCou
   if (ACnt <= Cnt) {
     if (ACnt == Cnt) {
       V.clearCounts();
-      if (V.getKind() == RefVal::ReturnedOwned)
+      if (V.getKind() == RefVal::ReturnedOwned) {
         V = V ^ RefVal::ReturnedNotOwned;
-      else
+      } else {
         V = V ^ RefVal::NotOwned;
+      }
     } else {
       V.setCount(V.getCount() - ACnt);
       V.setAutoreleaseCount(0);
@@ -1181,8 +1181,9 @@ RetainCountChecker::handleAutoreleaseCou
       overAutorelease.reset(new OverAutorelease(this));
 
     const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
-    Ctx.emitReport(llvm::make_unique<CFRefReport>(
-        *overAutorelease, LOpts, SummaryLog, N, Sym, os.str()));
+    auto R = llvm::make_unique<CFRefReport>(*overAutorelease, LOpts, SummaryLog,
+                                            N, Sym, os.str());
+    Ctx.emitReport(std::move(R));
   }
 
   return nullptr;
@@ -1281,9 +1282,15 @@ void RetainCountChecker::checkBeginFunct
 
 void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
                                           CheckerContext &Ctx) const {
-  ProgramStateRef state = Ctx.getState();
+  ExplodedNode *Pred = processReturn(RS, Ctx);
+
+  // Created state cached out.
+  if (!Pred) {
+    return;
+  }
+
+  ProgramStateRef state = Pred->getState();
   RefBindingsTy B = state->get<RefBindings>();
-  ExplodedNode *Pred = Ctx.getPredecessor();
 
   // Don't process anything within synthesized bodies.
   const LocationContext *LCtx = Pred->getLocationContext();

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h?rev=342770&r1=342769&r2=342770&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h Fri Sep 21 13:37:20 2018
@@ -252,7 +252,6 @@ class RetainCountChecker
                     check::PostStmt<ObjCBoxedExpr>,
                     check::PostStmt<ObjCIvarRefExpr>,
                     check::PostCall,
-                    check::PreStmt<ReturnStmt>,
                     check::RegionChanges,
                     eval::Assume,
                     eval::Call > {
@@ -388,8 +387,7 @@ public:
                      const LocationContext* LCtx,
                      const CallEvent *Call) const;
 
-  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
-  void checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
+  ExplodedNode* checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
                                 ExplodedNode *Pred, RetEffect RE, RefVal X,
                                 SymbolRef Sym, ProgramStateRef state) const;
 
@@ -416,12 +414,20 @@ public:
   ProgramStateRef
   handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
                           const ProgramPointTag *Tag, CheckerContext &Ctx,
-                          SymbolRef Sym, RefVal V) const;
+                          SymbolRef Sym,
+                          RefVal V,
+                          const ReturnStmt *S=nullptr) const;
 
   ExplodedNode *processLeaks(ProgramStateRef state,
                              SmallVectorImpl<SymbolRef> &Leaked,
                              CheckerContext &Ctx,
                              ExplodedNode *Pred = nullptr) const;
+
+private:
+  /// Perform the necessary checks and state adjustments at the end of the
+  /// function.
+  /// \p S Return statement, may be null.
+  ExplodedNode * processReturn(const ReturnStmt *S, CheckerContext &C) const;
 };
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist?rev=342770&r1=342769&r2=342770&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist (original)
+++ cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist Fri Sep 21 13:37:20 2018
@@ -2066,47 +2066,6 @@
          <key>file</key><integer>0</integer>
         </dict>
        </array>
-       <array>
-        <dict>
-         <key>line</key><integer>110</integer>
-         <key>col</key><integer>10</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>110</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
-     </array>
-     <key>depth</key><integer>0</integer>
-     <key>extended_message</key>
-     <string>Object returned to caller with a +0 retain count</string>
-     <key>message</key>
-     <string>Object returned to caller with a +0 retain count</string>
-    </dict>
-    <dict>
-     <key>kind</key><string>event</string>
-     <key>location</key>
-     <dict>
-      <key>line</key><integer>110</integer>
-      <key>col</key><integer>3</integer>
-      <key>file</key><integer>0</integer>
-     </dict>
-     <key>ranges</key>
-     <array>
-       <array>
-        <dict>
-         <key>line</key><integer>110</integer>
-         <key>col</key><integer>3</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>110</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
      </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
@@ -2228,47 +2187,6 @@
          <key>file</key><integer>0</integer>
         </dict>
        </array>
-       <array>
-        <dict>
-         <key>line</key><integer>115</integer>
-         <key>col</key><integer>10</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>115</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
-     </array>
-     <key>depth</key><integer>0</integer>
-     <key>extended_message</key>
-     <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-     <key>message</key>
-     <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-    </dict>
-    <dict>
-     <key>kind</key><string>event</string>
-     <key>location</key>
-     <dict>
-      <key>line</key><integer>115</integer>
-      <key>col</key><integer>3</integer>
-      <key>file</key><integer>0</integer>
-     </dict>
-     <key>ranges</key>
-     <array>
-       <array>
-        <dict>
-         <key>line</key><integer>115</integer>
-         <key>col</key><integer>3</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>115</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
      </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
@@ -2390,47 +2308,6 @@
          <key>file</key><integer>0</integer>
         </dict>
        </array>
-       <array>
-        <dict>
-         <key>line</key><integer>121</integer>
-         <key>col</key><integer>10</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>121</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
-     </array>
-     <key>depth</key><integer>0</integer>
-     <key>extended_message</key>
-     <string>Object returned to caller with a +0 retain count</string>
-     <key>message</key>
-     <string>Object returned to caller with a +0 retain count</string>
-    </dict>
-    <dict>
-     <key>kind</key><string>event</string>
-     <key>location</key>
-     <dict>
-      <key>line</key><integer>121</integer>
-      <key>col</key><integer>3</integer>
-      <key>file</key><integer>0</integer>
-     </dict>
-     <key>ranges</key>
-     <array>
-       <array>
-        <dict>
-         <key>line</key><integer>121</integer>
-         <key>col</key><integer>3</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>121</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
      </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
@@ -2552,47 +2429,6 @@
          <key>file</key><integer>0</integer>
         </dict>
        </array>
-       <array>
-        <dict>
-         <key>line</key><integer>126</integer>
-         <key>col</key><integer>10</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>126</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
-     </array>
-     <key>depth</key><integer>0</integer>
-     <key>extended_message</key>
-     <string>Object returned to caller with a +0 retain count</string>
-     <key>message</key>
-     <string>Object returned to caller with a +0 retain count</string>
-    </dict>
-    <dict>
-     <key>kind</key><string>event</string>
-     <key>location</key>
-     <dict>
-      <key>line</key><integer>126</integer>
-      <key>col</key><integer>3</integer>
-      <key>file</key><integer>0</integer>
-     </dict>
-     <key>ranges</key>
-     <array>
-       <array>
-        <dict>
-         <key>line</key><integer>126</integer>
-         <key>col</key><integer>3</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>126</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
      </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
@@ -2714,47 +2550,6 @@
          <key>file</key><integer>0</integer>
         </dict>
        </array>
-       <array>
-        <dict>
-         <key>line</key><integer>131</integer>
-         <key>col</key><integer>10</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>131</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
-     </array>
-     <key>depth</key><integer>0</integer>
-     <key>extended_message</key>
-     <string>Object returned to caller with a +0 retain count</string>
-     <key>message</key>
-     <string>Object returned to caller with a +0 retain count</string>
-    </dict>
-    <dict>
-     <key>kind</key><string>event</string>
-     <key>location</key>
-     <dict>
-      <key>line</key><integer>131</integer>
-      <key>col</key><integer>3</integer>
-      <key>file</key><integer>0</integer>
-     </dict>
-     <key>ranges</key>
-     <array>
-       <array>
-        <dict>
-         <key>line</key><integer>131</integer>
-         <key>col</key><integer>3</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>131</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
      </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
@@ -2876,47 +2671,6 @@
          <key>file</key><integer>0</integer>
         </dict>
        </array>
-       <array>
-        <dict>
-         <key>line</key><integer>136</integer>
-         <key>col</key><integer>10</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>136</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
-     </array>
-     <key>depth</key><integer>0</integer>
-     <key>extended_message</key>
-     <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-     <key>message</key>
-     <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-    </dict>
-    <dict>
-     <key>kind</key><string>event</string>
-     <key>location</key>
-     <dict>
-      <key>line</key><integer>136</integer>
-      <key>col</key><integer>3</integer>
-      <key>file</key><integer>0</integer>
-     </dict>
-     <key>ranges</key>
-     <array>
-       <array>
-        <dict>
-         <key>line</key><integer>136</integer>
-         <key>col</key><integer>3</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-        <dict>
-         <key>line</key><integer>136</integer>
-         <key>col</key><integer>15</integer>
-         <key>file</key><integer>0</integer>
-        </dict>
-       </array>
      </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
@@ -5262,7 +5016,7 @@
  </array>
  <key>files</key>
  <array>
-   <string>/clang/test/Analysis/retain-release-path-notes.m</string>
+  <string>/test/Analysis/retain-release-path-notes.m</string>
  </array>
 </dict>
 </plist>

Modified: cfe/trunk/test/Analysis/retain-release-arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-arc.m?rev=342770&r1=342769&r2=342770&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release-arc.m (original)
+++ cfe/trunk/test/Analysis/retain-release-arc.m Fri Sep 21 13:37:20 2018
@@ -95,8 +95,7 @@ void _dispatch_object_validate(dispatch_
   return (__bridge NSDictionary *)testDict;
 #if HAS_ARC
       // expected-warning at -2 {{Potential leak of an object stored into 'testDict'}}
-      // expected-note at -3 {{Object returned to caller as an owning reference (single retain count transferred to caller)}}
-      // expected-note at -4 {{Object leaked: object allocated and stored into 'testDict' is returned from a method managed by Automatic Reference Counting}}
+      // expected-note at -3 {{Object leaked: object allocated and stored into 'testDict' is returned from a method managed by Automatic Reference Counting}}
 #endif
 }
 

Modified: cfe/trunk/test/Analysis/retain-release-path-notes.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-path-notes.m?rev=342770&r1=342769&r2=342770&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release-path-notes.m (original)
+++ cfe/trunk/test/Analysis/retain-release-path-notes.m Fri Sep 21 13:37:20 2018
@@ -107,33 +107,33 @@ void makeCollectableIgnored() {
 
 CFTypeRef CFCopyRuleViolation () {
   CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
-  return object; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+  return object; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
 }
 
 CFTypeRef CFGetRuleViolation () {
   CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
-  return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' is returned from a function whose name ('CFGetRuleViolation') does not contain 'Copy' or 'Create'.  This violates the naming convention rules given in the Memory Management Guide for Core Foundation}}
+  return object; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'object' is returned from a function whose name ('CFGetRuleViolation') does not contain 'Copy' or 'Create'.  This violates the naming convention rules given in the Memory Management Guide for Core Foundation}}
 }
 
 @implementation Foo (FundamentalMemoryManagementRules)
 - (id)copyViolation {
   id result = self.propertyValue; // expected-note{{Property returns an Objective-C object with a +0 retain count}}
-  return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+  return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
 }
 
 - (id)copyViolationIndexedSubscript {
   id result = self[0]; // expected-note{{Subscript returns an Objective-C object with a +0 retain count}}
-  return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+  return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
 }
 
 - (id)copyViolationKeyedSubscript {
   id result = self[self]; // expected-note{{Subscript returns an Objective-C object with a +0 retain count}}
-  return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+  return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
 }
 
 - (id)getViolation {
   id result = [[Foo alloc] init]; // expected-note{{Method returns an instance of Foo with a +1 retain count}}
-  return result; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'result' is returned from a method whose name ('getViolation') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'.  This violates the naming convention rules given in the Memory Management Guide for Cocoa}}
+  return result; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'result' is returned from a method whose name ('getViolation') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'.  This violates the naming convention rules given in the Memory Management Guide for Cocoa}}
 }
 
 - (id)copyAutorelease {




More information about the cfe-commits mailing list