[llvm-branch-commits] [cfe-branch] r73557 - in /cfe/branches/Apple/Dib: lib/Analysis/BugReporter.cpp lib/Analysis/CFRefCount.cpp test/Analysis/retain-release-gc-only.m test/Analysis/retain-release.m

Daniel Dunbar daniel at zuster.org
Tue Jun 16 14:59:07 PDT 2009


Author: ddunbar
Date: Tue Jun 16 16:59:07 2009
New Revision: 73557

URL: http://llvm.org/viewvc/llvm-project?rev=73557&view=rev
Log:
Merge in analyzer changes since clang-20.

Quoth Dr. Ted: This patch has the combined changes for the following radars:

<rdar://problem/6899990> report shortest path for bug reports
<rdar://problem/6900055> Fix PR 4230: Don't flag leaks of NSAutoreleasePools
until we know that we aren' at the top-most scope of autorelease pools.
<rdar://problem/6893565> False positive: don't flag leaks for return types that
cannot be determined to be CF types
<rdar://problem/6948053> False positive: object substitution during -init*
methods warns about returning +0 when using -fobjc-gc-only
<rdar://problem/6902710> clang: false positives w/QC and CoreImage methods
<rdar://problem/6961230> add knowledge of IOKit functions to retain/release
checker
<rdar://problem/6945561> -[CIContext createCGLayerWithSize:info:] misinterpreted
by clang scan-build

Modified:
    cfe/branches/Apple/Dib/lib/Analysis/BugReporter.cpp
    cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp
    cfe/branches/Apple/Dib/test/Analysis/retain-release-gc-only.m
    cfe/branches/Apple/Dib/test/Analysis/retain-release.m

Modified: cfe/branches/Apple/Dib/lib/Analysis/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/lib/Analysis/BugReporter.cpp?rev=73557&r1=73556&r2=73557&view=diff

==============================================================================
--- cfe/branches/Apple/Dib/lib/Analysis/BugReporter.cpp (original)
+++ cfe/branches/Apple/Dib/lib/Analysis/BugReporter.cpp Tue Jun 16 16:59:07 2009
@@ -1347,16 +1347,19 @@
   // Find the (first) error node in the trimmed graph.  We just need to consult
   // the node map (NMap) which maps from nodes in the original graph to nodes
   // in the new graph.
-  const ExplodedNode<GRState>* N = 0;
-  unsigned NodeIndex = 0;
+
+  std::queue<const ExplodedNode<GRState>*> WS;
+  typedef llvm::DenseMap<const ExplodedNode<GRState>*,unsigned> IndexMapTy;
+  IndexMapTy IndexMap;
 
   for (const ExplodedNode<GRState>** I = NStart; I != NEnd; ++I)
-    if ((N = NMap->getMappedNode(*I))) {
-      NodeIndex = (I - NStart) / sizeof(*I);
-      break;
+    if (const ExplodedNode<GRState> *N = NMap->getMappedNode(*I)) {
+      unsigned NodeIndex = (I - NStart) / sizeof(*I);
+      WS.push(N);
+      IndexMap[*I] = NodeIndex;
     }
   
-  assert(N && "No error node found in the trimmed graph.");
+  assert(!WS.empty() && "No error node found in the trimmed graph.");
 
   // Create a new (third!) graph with a single path.  This is the graph
   // that will be returned to the caller.
@@ -1368,8 +1371,6 @@
   // to the root node, and then construct a new graph that contains only
   // a single path.
   llvm::DenseMap<const void*,unsigned> Visited;
-  std::queue<const ExplodedNode<GRState>*> WS;
-  WS.push(N);
   
   unsigned cnt = 0;
   const ExplodedNode<GRState>* Root = 0;
@@ -1393,17 +1394,18 @@
       WS.push(*I);
   }
   
-  assert (Root);
+  assert(Root);
   
   // Now walk from the root down the BFS path, always taking the successor
   // with the lowest number.
   ExplodedNode<GRState> *Last = 0, *First = 0;  
   NodeBackMap *BM = new NodeBackMap();
+  unsigned NodeIndex = 0;
   
-  for ( N = Root ;;) {
+  for ( const ExplodedNode<GRState> *N = Root ;;) {
     // Lookup the number associated with the current node.
     llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N);
-    assert (I != Visited.end());
+    assert(I != Visited.end());
     
     // Create the equivalent node in the new graph with the same state
     // and location.
@@ -1422,8 +1424,11 @@
     Last = NewN;
     
     // Are we at the final node?
-    if (I->second == 0) {
+    IndexMapTy::iterator IMI =
+      IndexMap.find((const ExplodedNode<GRState>*)(IMitr->second));
+    if (IMI != IndexMap.end()) {
       First = NewN;
+      NodeIndex = IMI->second;
       break;
     }
     
@@ -1446,10 +1451,11 @@
       }
     }
     
-    assert (N);
+    assert(N);
   }
   
-  assert (First);
+  assert(First);
+
   return std::make_pair(std::make_pair(GNew, BM),
                         std::make_pair(First, NodeIndex));
 }

Modified: cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp?rev=73557&r1=73556&r2=73557&view=diff

==============================================================================
--- cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp Tue Jun 16 16:59:07 2009
@@ -636,6 +636,10 @@
   /// ObjCAllocRetE - Default return effect for methods returning Objective-C
   ///  objects.
   RetEffect ObjCAllocRetE;
+
+  /// ObjCInitRetE - Default return effect for init methods returning Objective-C
+  ///  objects.
+  RetEffect ObjCInitRetE;
   
   RetainSummary DefaultSummary;
   RetainSummary* StopSummary;
@@ -776,6 +780,8 @@
      GCEnabled(gcenabled), AF(BPAlloc), ScratchArgs(AF.GetEmptyMap()),
      ObjCAllocRetE(gcenabled ? RetEffect::MakeGCNotOwned()
                              : RetEffect::MakeOwned(RetEffect::ObjC, true)),
+     ObjCInitRetE(gcenabled ? RetEffect::MakeGCNotOwned()
+                            : RetEffect::MakeOwnedWhenTrackedReceiver()),
      DefaultSummary(AF.GetEmptyMap() /* per-argument effects (none) */,
                     RetEffect::MakeNoRet() /* return effect */,
                     MayEscape, /* default argument effect */
@@ -894,11 +900,18 @@
   if (!OT)
     return true;
     
-  // Does the interface subclass NSObject?
-  // FIXME: We can memoize here if this gets too expensive.  
-  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
+  // Does the interface subclass NSObject?    
+  // FIXME: We can memoize here if this gets too expensive.    
   ObjCInterfaceDecl* ID = OT->getDecl();  
 
+  // Assume that anything declared with a forward declaration and no
+  // @interface subclasses NSObject.
+  if (ID->isForwardDecl())
+    return true;
+  
+  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
+
+
   for ( ; ID ; ID = ID->getSuperClass())
     if (ID->getIdentifier() == NSObjectII)
       return true;
@@ -958,15 +971,96 @@
     
     // FIXME: This should all be refactored into a chain of "summary lookup"
     //  filters.
-    if (strcmp(FName, "IOServiceGetMatchingServices") == 0) {
-      // FIXES: <rdar://problem/6326900>
-      // This should be addressed using a API table.  This strcmp is also
-      // a little gross, but there is no need to super optimize here.
-      assert (ScratchArgs.isEmpty());
-      ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
-      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
-      break;
+    assert (ScratchArgs.isEmpty());
+    
+    switch (strlen(FName)) {
+      default: break;
+        
+
+      case 17:
+        // Handle: id NSMakeCollectable(CFTypeRef)
+        if (!memcmp(FName, "NSMakeCollectable", 17)) {
+          S = (RetTy == Ctx.getObjCIdType())
+              ? getUnarySummary(FT, cfmakecollectable)
+              : getPersistentStopSummary();
+        }
+        else if (!memcmp(FName, "IOBSDNameMatching", 17) ||
+                 !memcmp(FName, "IOServiceMatching", 17)) {
+          // Part of <rdar://problem/6961230>. (IOKit)
+          // This should be addressed using a API table.
+          S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+                                   DoNothing, DoNothing);
+        }
+        break;
+
+      case 21:
+        if (!memcmp(FName, "IOServiceNameMatching", 21)) {
+          // Part of <rdar://problem/6961230>. (IOKit)
+          // This should be addressed using a API table.
+          S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+                                   DoNothing, DoNothing);
+        }
+        break;
+
+      case 24:
+        if (!memcmp(FName, "IOServiceAddNotification", 24)) {
+          // Part of <rdar://problem/6961230>. (IOKit)
+          // This should be addressed using a API table.
+          ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
+          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);         
+        }
+        break;
+        
+      case 25:
+        if (!memcmp(FName, "IORegistryEntryIDMatching", 25)) {
+          // Part of <rdar://problem/6961230>. (IOKit)
+          // This should be addressed using a API table.
+          S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+                                   DoNothing, DoNothing);
+        }
+        break;
+        
+      case 26:
+        if (!memcmp(FName, "IOOpenFirmwarePathMatching", 26)) {
+          // Part of <rdar://problem/6961230>. (IOKit)
+          // This should be addressed using a API table.
+          S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+                                   DoNothing, DoNothing);          
+        }
+        break;
+
+      case 27:
+        if (!memcmp(FName, "IOServiceGetMatchingService", 27)) {
+          // Part of <rdar://problem/6961230>.
+          // This should be addressed using a API table.
+          ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
+          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);         
+        }
+        break;
+
+      case 28:
+        if (!memcmp(FName, "IOServiceGetMatchingServices", 28)) {
+          // FIXES: <rdar://problem/6326900>
+          // This should be addressed using a API table.  This strcmp is also
+          // a little gross, but there is no need to super optimize here.
+          ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
+          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+        }
+        break;
+        
+      case 32:
+        if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
+          // Part of <rdar://problem/6961230>.
+          // This should be addressed using a API table.
+          ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
+          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);         
+        }
+        break;
     }
+    
+    // Did we get a summary?
+    if (S)
+      break;
 
     // Enable this code once the semantics of NSDeallocateObject are resolved
     // for GC.  <rdar://problem/6619988>
@@ -979,15 +1073,6 @@
         : getPersistentStopSummary();
     }
 #endif
-    
-    // Handle: id NSMakeCollectable(CFTypeRef)
-    if (strcmp(FName, "NSMakeCollectable") == 0) {
-      S = (RetTy == Ctx.getObjCIdType())
-          ? getUnarySummary(FT, cfmakecollectable)
-          : getPersistentStopSummary();
-        
-      break;
-    }
 
     if (RetTy->isPointerType()) {
       // For CoreFoundation ('CF') types.
@@ -1149,8 +1234,7 @@
   // 'init' methods conceptually return a newly allocated object and claim
   // the receiver.  
   if (isTrackedObjCObjectType(RetTy) || isTrackedCFObjectType(RetTy))
-    return getPersistentSummary(RetEffect::MakeOwnedWhenTrackedReceiver(),
-                                DecRefMsg);
+    return getPersistentSummary(ObjCInitRetE, DecRefMsg);
   
   return getDefaultSummary();
 }
@@ -1161,8 +1245,10 @@
   if (!FD)
     return;
 
+  QualType RetTy = FD->getResultType();
+  
   // Determine if there is a special return effect for this method.
-  if (isTrackedObjCObjectType(FD->getResultType())) {
+  if (isTrackedObjCObjectType(RetTy)) {
     if (FD->getAttr<NSReturnsRetainedAttr>()) {
       Summ.setRetEffect(ObjCAllocRetE);
     }
@@ -1170,6 +1256,11 @@
       Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
     }
   }
+  else if (RetTy->getAsPointerType()) {
+    if (FD->getAttr<CFReturnsRetainedAttr>()) {
+      Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+    }
+  }
 }
 
 void
@@ -1360,21 +1451,20 @@
   // Create the "init" selector.  It just acts as a pass-through for the
   // receiver.
   addNSObjectMethSummary(GetNullarySelector("init", Ctx),
-                 getPersistentSummary(RetEffect::MakeOwnedWhenTrackedReceiver(),
-                 DecRefMsg));
+                         getPersistentSummary(ObjCInitRetE, DecRefMsg));
   
   // The next methods are allocators.
-  RetainSummary* Summ = getPersistentSummary(ObjCAllocRetE);  
+  RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);  
   
   // Create the "copy" selector.  
-  addNSObjectMethSummary(GetNullarySelector("copy", Ctx), Summ);  
+  addNSObjectMethSummary(GetNullarySelector("copy", Ctx), AllocSumm);  
 
   // Create the "mutableCopy" selector.
-  addNSObjectMethSummary(GetNullarySelector("mutableCopy", Ctx), Summ);
+  addNSObjectMethSummary(GetNullarySelector("mutableCopy", Ctx), AllocSumm);
   
   // Create the "retain" selector.
   RetEffect E = RetEffect::MakeReceiverAlias();
-  Summ = getPersistentSummary(E, IncRefMsg);
+  RetainSummary *Summ = getPersistentSummary(E, IncRefMsg);
   addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
   
   // Create the "release" selector.
@@ -1431,6 +1521,10 @@
   addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
                      "styleMask", "backing", "defer", "screen", NULL);
 #endif
+  
+  // Don't track allocated autorelease pools yet, as it is okay to prematurely
+  // exit a method.
+  addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
 
   // Create NSAssertionHandler summaries.
   addPanicSummary("NSAssertionHandler", "handleFailureInFunction", "file",
@@ -1438,6 +1532,21 @@
   
   addPanicSummary("NSAssertionHandler", "handleFailureInMethod", "object",
                   "file", "lineNumber", "description", NULL);
+  
+  // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
+  addInstMethSummary("QCRenderer", AllocSumm,
+                     "createSnapshotImageOfType", NULL);
+  addInstMethSummary("QCView", AllocSumm,
+                     "createSnapshotImageOfType", NULL);
+
+  // Create summaries for CIContext, 'createCGImage' and
+  // 'createCGLayerWithSize'.
+  addInstMethSummary("CIContext", AllocSumm,
+                     "createCGImage", "fromRect", NULL);
+  addInstMethSummary("CIContext", AllocSumm,
+                     "createCGImage", "fromRect", "format", "colorSpace", NULL);  
+  addInstMethSummary("CIContext", AllocSumm, "createCGLayerWithSize",
+           "info", NULL);
 }
 
 //===----------------------------------------------------------------------===//
@@ -3142,22 +3251,24 @@
       RetEffect RE = Summ.getRetEffect();
       bool hasError = false;
 
-      if (isGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
-        // Things are more complicated with garbage collection.  If the
-        // returned object is suppose to be an Objective-C object, we have
-        // a leak (as the caller expects a GC'ed object) because no
-        // method should return ownership unless it returns a CF object.
-        X = X ^ RefVal::ErrorGCLeakReturned;
-        
-        // Keep this false until this is properly tested.
-        hasError = true;
-      }
-      else if (!RE.isOwned()) {
-        // Either we are using GC and the returned object is a CF type
-        // or we aren't using GC.  In either case, we expect that the
-        // enclosing method is expected to return ownership.        
-        hasError = true;
-        X = X ^ RefVal::ErrorLeakReturned;
+      if (RE.getKind() != RetEffect::NoRet) {
+        if (isGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
+          // Things are more complicated with garbage collection.  If the
+          // returned object is suppose to be an Objective-C object, we have
+          // a leak (as the caller expects a GC'ed object) because no
+          // method should return ownership unless it returns a CF object.
+          X = X ^ RefVal::ErrorGCLeakReturned;
+          
+          // Keep this false until this is properly tested.
+          hasError = true;
+        }
+        else if (!RE.isOwned()) {
+          // Either we are using GC and the returned object is a CF type
+          // or we aren't using GC.  In either case, we expect that the
+          // enclosing method is expected to return ownership.        
+          hasError = true;
+          X = X ^ RefVal::ErrorLeakReturned;
+        }
       }
       
       if (hasError) {        

Modified: cfe/branches/Apple/Dib/test/Analysis/retain-release-gc-only.m
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/test/Analysis/retain-release-gc-only.m?rev=73557&r1=73556&r2=73557&view=diff

==============================================================================
--- cfe/branches/Apple/Dib/test/Analysis/retain-release-gc-only.m (original)
+++ cfe/branches/Apple/Dib/test/Analysis/retain-release-gc-only.m Tue Jun 16 16:59:07 2009
@@ -5,6 +5,8 @@
 // Header stuff.
 //===----------------------------------------------------------------------===//
 
+typedef struct objc_class *Class;
+
 typedef unsigned int __darwin_natural_t;
 typedef struct {} div_t;
 typedef unsigned long UInt32;
@@ -56,6 +58,7 @@
 @end  @protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder;
 @end
 @interface NSObject <NSObject> {}
+- (Class)class;
 + (id)alloc;
 + (id)allocWithZone:(NSZone *)zone;
 @end   typedef float CGFloat;
@@ -101,6 +104,11 @@
 
 CFTypeRef CFMakeCollectable(CFTypeRef cf) ;
 
+static __inline__ __attribute__((always_inline)) id NSMakeCollectable(CFTypeRef 
+cf) {
+    return cf ? (id)CFMakeCollectable(cf) : ((void*)0);
+}
+
 //===----------------------------------------------------------------------===//
 // Test cases.
 //===----------------------------------------------------------------------===//
@@ -124,6 +132,31 @@
   CFRetain(A);
 }
 
+void f3b() {
+  CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning
+  CFMakeCollectable(A);
+}
+
+
+void f4() {
+  CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}}
+  NSMakeCollectable(A);
+  CFRetain(A);
+}
+
+void f4b() {
+  CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning
+  NSMakeCollectable(A);
+}
+
+void f5() {
+  id x = [NSMakeCollectable(CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks)) autorelease]; // no-warning
+}
+
+void f5b() {
+  id x = [(id) CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks) autorelease]; // expected-warning{{leak}}
+}
+
 // Test return of non-owned objects in contexts where an owned object
 // is expected.
 @interface TestReturnNotOwnedWhenExpectedOwned
@@ -133,7 +166,7 @@
 
 @implementation TestReturnNotOwnedWhenExpectedOwned
 - (NSString*)newString {
-  NSString *s = [NSString stringWithUTF8String:"hello"]; // expected-warning{{Potential leak (when using garbage collection) of an object allocated on line 136 and stored into 's'}}
+  NSString *s = [NSString stringWithUTF8String:"hello"]; // expected-warning{{Potential leak (when using garbage collection) of an object allocated}}
   CFRetain(s);
   return s;
 }
@@ -143,6 +176,28 @@
 @end
 
 //===----------------------------------------------------------------------===//
+// <rdar://problem/6948053> False positive: object substitution during -init*
+//   methods warns about returning +0 when using -fobjc-gc-only
+//===----------------------------------------------------------------------===//
+
+ at interface MyClassRdar6948053 : NSObject
+- (id) init;
++ (id) shared;
+ at end
+
+ at implementation MyClassRdar6948053
++(id) shared {
+  return (id) 0;
+}
+- (id) init
+{
+  Class myClass = [self class];  
+  [self release];
+  return [[myClass shared] retain]; // no-warning
+}
+ at end
+
+//===----------------------------------------------------------------------===//
 // Tests of ownership attributes.
 //===----------------------------------------------------------------------===//
 
@@ -159,3 +214,27 @@
   NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
 }
 
+ at interface MyClassTestCFAttr : NSObject {}
+- (NSDate*) returnsCFRetained __attribute__((cf_returns_retained));
+- (NSDate*) alsoReturnsRetained;
+- (NSDate*) returnsNSRetained __attribute__((ns_returns_retained));
+ at end
+
+__attribute__((cf_returns_retained))
+CFDateRef returnsRetainedCFDate()  {
+  return CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+}
+
+ at implementation MyClassTestCFAttr
+- (NSDate*) returnsCFRetained {
+  return (NSDate*) returnsRetainedCFDate(); // No leak.
+}
+
+- (NSDate*) alsoReturnsRetained {
+  return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
+}
+
+- (NSDate*) returnsNSRetained {
+  return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
+}
+ at end
\ No newline at end of file

Modified: cfe/branches/Apple/Dib/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/test/Analysis/retain-release.m?rev=73557&r1=73556&r2=73557&view=diff

==============================================================================
--- cfe/branches/Apple/Dib/test/Analysis/retain-release.m (original)
+++ cfe/branches/Apple/Dib/test/Analysis/retain-release.m Tue Jun 16 16:59:07 2009
@@ -1,14 +1,17 @@
+//>>SLICER
 // RUN: clang-cc -analyze -checker-cfref -verify %s &&
 // RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
 
-
 //===----------------------------------------------------------------------===//
-// The following code is reduced using delta-debugging from
-// Foundation.h (Mac OS X).
+// The following code is reduced using delta-debugging from Mac OS X headers:
+//
+// #include <Cocoa/Cocoa.h>
+// #include <CoreFoundation/CoreFoundation.h>
+// #include <DiskArbitration/DiskArbitration.h>
+// #include <QuartzCore/QuartzCore.h>
+// #include <Quartz/Quartz.h>
 //
 // It includes the basic definitions for the test cases below.
-// Not including Foundation.h directly makes this test case both svelte and
-// portable to non-Mac platforms.
 //===----------------------------------------------------------------------===//
 
 typedef unsigned int __darwin_natural_t;
@@ -17,9 +20,9 @@
 typedef const void * CFTypeRef;
 typedef const struct __CFString * CFStringRef;
 typedef const struct __CFAllocator * CFAllocatorRef;
-extern const CFAllocatorRef kCFAllocatorDefault;
 extern CFTypeRef CFRetain(CFTypeRef cf);
 extern void CFRelease(CFTypeRef cf);
+extern const CFAllocatorRef kCFAllocatorDefault;
 typedef struct {
 }
 CFArrayCallBacks;
@@ -39,17 +42,16 @@
 extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void);
 typedef const struct __CFDate * CFDateRef;
 extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
-extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
+CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
+enum {
+kCFCalendarComponentsWrap = (1UL << 0) };
 typedef __darwin_natural_t natural_t;
 typedef natural_t mach_port_name_t;
 typedef mach_port_name_t mach_port_t;
 typedef int kern_return_t;
 typedef kern_return_t mach_error_t;
-typedef struct objc_selector *SEL;
 typedef signed char BOOL;
 typedef unsigned long NSUInteger;
- at class NSString, Protocol;
-extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
 typedef struct _NSZone NSZone;
 @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
 @protocol NSObject  - (BOOL)isEqual:(id)object;
@@ -69,20 +71,30 @@
 }
 NSFastEnumerationState;
 @protocol NSFastEnumeration  - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
- at end           @class NSString, NSDictionary;
-typedef double NSTimeInterval;
+ at end      @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>  - (NSUInteger)count;
+ at end  @interface NSArray (NSArrayCreation)  + (id)array;
+ at end        @interface NSAutoreleasePool : NSObject {
+}
+- (void)drain;
+ at end    typedef double NSTimeInterval;
 @interface NSDate : NSObject <NSCopying, NSCoding>  - (NSTimeInterval)timeIntervalSinceReferenceDate;
- at end            typedef unsigned short unichar;
+ at end  enum {
+NSWrapCalendarComponents = kCFCalendarComponentsWrap, };
 @interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>    - (NSUInteger)length;
 - ( const char *)UTF8String;
 - (id)initWithUTF8String:(const char *)nullTerminatedCString;
 + (id)stringWithUTF8String:(const char *)nullTerminatedCString;
- at end        @class NSDictionary;
- at interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>  - (NSUInteger)count;
+ at end      @interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding>  - (NSUInteger)length;
++ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length;
++ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b;
+ at end      @interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>  - (NSUInteger)count;
 @end    @interface NSMutableDictionary : NSDictionary  - (void)removeObjectForKey:(id)aKey;
 - (void)setObject:(id)anObject forKey:(id)aKey;
 @end  @interface NSMutableDictionary (NSMutableDictionaryCreation)  + (id)dictionaryWithCapacity:(NSUInteger)numItems;
- at end @class NSString, NSDictionary, NSArray;
+struct CGRect {
+};
+typedef struct CGRect CGRect;
+- (id)init;
 typedef mach_port_t io_object_t;
 typedef io_object_t io_service_t;
 typedef struct __DASession * DASessionRef;
@@ -92,27 +104,20 @@
 extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media );
 extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk );
 extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk );
- at interface NSTask : NSObject - (id)init;
- at end  extern NSString * const NSTaskDidTerminateNotification;
+typedef struct CGColorSpace *CGColorSpaceRef;
+typedef struct CGImage *CGImageRef;
+ at end   @class CIContext;
+ at class NSArray, NSError, NSEvent, NSMenu, NSUndoManager, NSWindow;
 @interface NSResponder : NSObject <NSCoding> {
-struct __vaFlags {
-}
-_vaFlags;
 }
 @end    @protocol NSAnimatablePropertyContainer      - (id)animator;
 @end  extern NSString *NSAnimationTriggerOrderIn ;
- at class NSBitmapImageRep, NSCursor, NSGraphicsContext, NSImage, NSPasteboard, NSScrollView, NSTextInputContext, NSWindow, NSAttributedString;
 @interface NSView : NSResponder  <NSAnimatablePropertyContainer>  {
-struct __VFlags2 {
-}
-_vFlags2;
 }
- at end  @class NSColor, NSFont, NSNotification;
- at interface NSTextTab : NSObject <NSCopying, NSCoding> {
-}
- at end @protocol NSValidatedUserInterfaceItem - (SEL)action;
+ at end   @class NSColor, NSFont, NSNotification;
+ at protocol NSValidatedUserInterfaceItem - (SEL)action;
 @end   @protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem;
- at end @class NSArray, NSError, NSImage, NSView, NSNotificationCenter, NSURL, NSScreen, NSRunningApplication;
+ at end    typedef struct NSThreadPrivate _NSThreadPrivate;
 @interface NSApplication : NSResponder <NSUserInterfaceValidations> {
 }
 @end   enum {
@@ -121,29 +126,30 @@
 @protocol NSApplicationDelegate <NSObject> @optional        - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
 @end    enum {
 NSUserInterfaceLayoutDirectionLeftToRight = 0,     NSUserInterfaceLayoutDirectionRightToLeft = 1 };
- at interface NSManagedObject : NSObject {
+ at interface CIImage : NSObject <NSCoding, NSCopying> {
+}
+typedef int CIFormat;
+typedef struct __SFlags {
 }
- at end enum {
+_SFlags;
+ at end    extern NSString * const kCAGravityCenter     __attribute__((visibility("default")));
+enum {
 kDAReturnSuccess = 0,     kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01,     kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02,     kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03,     kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04,     kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05,     kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06,     kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07,     kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08,     kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09,     kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A,     kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B,     kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C };
 typedef mach_error_t DAReturn;
 typedef const struct __DADissenter * DADissenterRef;
 extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string );
-
- @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
- - (NSUInteger)count;
- + (id)array;
- @end
- 
- at interface NSAutoreleasePool : NSObject {}
-+ (void)addObject:(id)anObject;
-- (void)addObject:(id)anObject;
-- (void)drain;
- at end
-
- at interface NSData : NSObject {}
-+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length;
-+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b;
+ at interface CIContext: NSObject {
+}
+- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r;
+- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r     format:(CIFormat)f colorSpace:(CGColorSpaceRef)cs;
+ at end     @protocol QCCompositionRenderer      @end   @interface QCRenderer : NSObject <QCCompositionRenderer> {
+}
+- (id) createSnapshotImageOfType:(NSString*)type;
+ at end     @interface QCView : NSView <QCCompositionRenderer> {
+}
+- (id) createSnapshotImageOfType:(NSString*)type;
 @end
+extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
 
 //===----------------------------------------------------------------------===//
 // Test cases.
@@ -619,6 +625,18 @@
 }
 
 //===----------------------------------------------------------------------===//
+// PR 4230 - an autorelease pool is not necessarily leaked during a premature
+//  return
+//===----------------------------------------------------------------------===//
+
+static void PR4230(void)
+{
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // no-warning
+  NSString *object = [[[NSString alloc] init] autorelease]; // no-warning
+  return;
+}
+
+//===----------------------------------------------------------------------===//
 // Method name that has a null IdentifierInfo* for its first selector slot.
 // This test just makes sure that we handle it.
 //===----------------------------------------------------------------------===//
@@ -630,6 +648,39 @@
 + (id):(int)x, ... {
   return [[NSString alloc] init]; // expected-warning{{leak}}
 }
+ at end
+
+//===----------------------------------------------------------------------===//
+// <rdar://problem/6893565> don't flag leaks for return types that cannot be 
+//                          determined to be CF types
+//===----------------------------------------------------------------------===//
+
+// We don't know if 'struct s6893565' represents a Core Foundation type, so
+// we shouldn't emit an error here.
+typedef struct s6893565* TD6893565;
+
+ at interface RDar6893565 {}
+-(TD6893565)newThing;
+ at end
+
+ at implementation RDar6893565
+-(TD6893565)newThing {  
+  return (TD6893565) [[NSString alloc] init]; // no-warning
+}
+ at end
+
+//===----------------------------------------------------------------------===//
+// <rdar://problem/6902710> clang: false positives w/QC and CoreImage methods
+//===----------------------------------------------------------------------===//
+
+void rdar6902710(QCView *view, QCRenderer *renderer, CIContext *context,
+                 NSString *str, CIImage *img, CGRect rect,
+                 CIFormat form, CGColorSpaceRef cs) {
+  [view createSnapshotImageOfType:str]; // expected-warning{{leak}}
+  [renderer createSnapshotImageOfType:str]; // expected-warning{{leak}}
+  [context createCGImage:img fromRect:rect]; // expected-warning{{leak}}
+  [context createCGImage:img fromRect:rect format:form colorSpace:cs]; // expected-warning{{leak}}
+}
 
 //===----------------------------------------------------------------------===//
 // Tests of ownership attributes.
@@ -654,3 +705,30 @@
   NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
 }
 
+ at interface MyClassTestCFAttr : NSObject {}
+- (NSDate*) returnsCFRetained __attribute__((cf_returns_retained));
+- (NSDate*) alsoReturnsRetained;
+- (NSDate*) returnsNSRetained __attribute__((ns_returns_retained));
+ at end
+
+__attribute__((cf_returns_retained))
+CFDateRef returnsRetainedCFDate()  {
+  return CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+}
+
+ at implementation MyClassTestCFAttr
+- (NSDate*) returnsCFRetained {
+  return (NSDate*) returnsRetainedCFDate(); // No leak.
+}
+
+- (NSDate*) alsoReturnsRetained {
+  return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
+}
+
+- (NSDate*) returnsNSRetained {
+  return (NSDate*) returnsRetainedCFDate(); // no-warning
+}
+ at end
+
+
+





More information about the llvm-branch-commits mailing list