[cfe-commits] r124360 - in /cfe/trunk: lib/Lex/PPMacroExpansion.cpp lib/StaticAnalyzer/CFRefCount.cpp test/Analysis/retain-release.m www/analyzer/annotations.html

Ted Kremenek kremenek at apple.com
Wed Jan 26 22:54:14 PST 2011


Author: kremenek
Date: Thu Jan 27 00:54:14 2011
New Revision: 124360

URL: http://llvm.org/viewvc/llvm-project?rev=124360&view=rev
Log:
Hook up attribute ns_consumes_self in the ObjC retain/release checker in the static analyzer.

Modified:
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp
    cfe/trunk/test/Analysis/retain-release.m
    cfe/trunk/www/analyzer/annotations.html

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=124360&r1=124359&r2=124360&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Jan 27 00:54:14 2011
@@ -536,6 +536,7 @@
            .Case("attribute_ext_vector_type", true)
            .Case("attribute_ns_returns_not_retained", true)
            .Case("attribute_ns_returns_retained", true)
+           .Case("attribute_ns_consumes_self", true)
            .Case("attribute_objc_ivar_unused", true)
            .Case("attribute_overloadable", true)
            .Case("attribute_unavailable_with_message", true)

Modified: cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp?rev=124360&r1=124359&r2=124360&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp Thu Jan 27 00:54:14 2011
@@ -467,6 +467,10 @@
   ///  terminate the path.
   bool isEndPath() const { return EndPath; }
 
+  
+  /// Sets the effect on the receiver of the message.
+  void setReceiverEffect(ArgEffect e) { Receiver = e; }
+  
   /// getReceiverEffect - Returns the effect on the receiver of the call.
   ///  This is only meaningful if the summary applies to an ObjCMessageExpr*.
   ArgEffect getReceiverEffect() const { return Receiver; }
@@ -1219,6 +1223,11 @@
 
   bool isTrackedLoc = false;
 
+  // Effects on the receiver.
+  if (MD->getAttr<NSConsumesSelfAttr>()) {
+    Summ.setReceiverEffect(DecRefMsg);      
+  }
+  
   // Determine if there is a special return effect for this method.
   if (cocoa::isCocoaObjectRef(MD->getResultType())) {
     if (MD->getAttr<NSReturnsRetainedAttr>()) {

Modified: cfe/trunk/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=124360&r1=124359&r2=124360&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.m (original)
+++ cfe/trunk/test/Analysis/retain-release.m Thu Jan 27 00:54:14 2011
@@ -13,6 +13,9 @@
 #if __has_feature(attribute_cf_returns_not_retained)
 #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
 #endif
+#if __has_feature(attribute_ns_consumes_self)
+#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
+#endif
 
 //===----------------------------------------------------------------------===//
 // The following code is reduced using delta-debugging from Mac OS X headers:
@@ -1211,6 +1214,7 @@
 - (NSString*) newString NS_RETURNS_NOT_RETAINED; // no-warning
 - (NSString*) newStringNoAttr;
 - (int) returnsAnOwnedInt NS_RETURNS_RETAINED; // expected-warning{{'ns_returns_retained' attribute only applies to methods that return an Objective-C object}}
+- (id) pseudoInit NS_CONSUMES_SELF NS_RETURNS_RETAINED;
 @end
 
 static int ownership_attribute_doesnt_go_here NS_RETURNS_RETAINED; // expected-warning{{'ns_returns_retained' attribute only applies to functions and methods}}
@@ -1228,6 +1232,19 @@
   NSString *str2 = [X newStringNoAttr]; // expected-warning{{leak}}
 }
 
+void testattr2_a() {
+  TestOwnershipAttr *x = [TestOwnershipAttr alloc]; // expected-warning{{leak}}
+}
+
+void testattr2_b() {
+  TestOwnershipAttr *x = [[TestOwnershipAttr alloc] pseudoInit];  // expected-warning{{leak}}
+}
+
+void testattr2_c() {
+  TestOwnershipAttr *x = [[TestOwnershipAttr alloc] pseudoInit]; // no-warning
+  [x release];
+}
+
 @interface MyClassTestCFAttr : NSObject {}
 - (NSDate*) returnsCFRetained CF_RETURNS_RETAINED;
 - (CFDateRef) returnsCFRetainedAsCF CF_RETURNS_RETAINED;
@@ -1401,7 +1418,7 @@
     while (error_to_dump != ((void*)0)) {
         CFDictionaryRef info;
 
-        info = CFErrorCopyUserInfo(error_to_dump); // expected-warning{{Potential leak of an object allocated on line 1404 and stored into 'info'}}
+        info = CFErrorCopyUserInfo(error_to_dump); // expected-warning{{Potential leak of an object allocated on line 1421 and stored into 'info'}}
 
         if (info != ((void*)0)) {
         }

Modified: cfe/trunk/www/analyzer/annotations.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/annotations.html?rev=124360&r1=124359&r2=124360&view=diff
==============================================================================
--- cfe/trunk/www/analyzer/annotations.html (original)
+++ cfe/trunk/www/analyzer/annotations.html Thu Jan 27 00:54:14 2011
@@ -56,6 +56,7 @@
       <li><a href="#attr_ns_returns_not_retained">Attribute 'ns_returns_not_retained'</a></li>
       <li><a href="#attr_cf_returns_retained">Attribute 'cf_returns_retained'</a></li>
       <li><a href="#attr_cf_returns_not_retained">Attribute 'cf_returns_not_retained'</a></li>
+      <li><a href="#attr_ns_consumes_self">Attribute 'ns_consumes_self'</a></li>
     </ul>
     </li>
   </ul>
@@ -350,6 +351,38 @@
 #endif
 </pre>
 
+<h4 id="attr_ns_consumes_self">Attribute 'ns_consumes_self'
+(Clang-specific)</h4>
+
+<p>The 'ns_consumes_self' attribute can be placed only on an Objective-C method declaration.
+  It indicates that the receiver of the message is "consumed" (a single reference count decremented)
+  after the message is sent.  This matches the semantics of all "init" methods.
+</p>
+
+<p>One use of this attribute is declare your own init-like methods that do not follow the
+  standard Cocoa naming conventions.  For example:</p>
+  
+<pre class="code_example">
+#ifndef __has_feature
+#define __has_Feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+#ifndef NS_CONSUMES_SELF
+#if __has_feature((attribute_ns_consumes_self))
+#else
+#define NS_CONSUMES_SELF
+#endif
+#endif
+
+ at interface MyClass : NSObject
+- initWith:(MyClass *)x;
+- nonstandardInitWith:(MyClass *)x NS_CONSUMES_SELF NS_RETURNS_RETAINED;
+ at end
+</pre>
+
+<p>In this example, <tt>nonstandardInitWith:</tt> has the same ownership semantics as the init method <tt>initWith:</tt>.
+  The static analyzer will observe that the method consumes the receiver, and then returns an object with a +1 retain count.</p>
+
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 <h2 id="custom_assertions">Custom Assertion Handlers</h2>
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->





More information about the cfe-commits mailing list