]> granicus.if.org Git - clang/commitdiff
[arcmt] Use __bridge_retained when passing an objc object to a CF parameter
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 14 Sep 2011 18:17:09 +0000 (18:17 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 14 Sep 2011 18:17:09 +0000 (18:17 +0000)
annotated with cf_consumed attribute.

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

lib/ARCMigrate/TransUnbridgedCasts.cpp
test/ARCMT/Common.h
test/ARCMT/nonobjc-to-objc-cast.m
test/ARCMT/nonobjc-to-objc-cast.m.result

index bc33c53b758d7de971ee7af55f64d7b21ced2196..047dfb276ad7c22cf6bb6d6322e8be751cb51e6f 100644 (file)
@@ -242,6 +242,11 @@ private:
       if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
         return rewriteToBridgedCast(E, OBC_Bridge);
     }
+
+    bool isConsumed = false;
+    if (isPassedToCParamWithKnownOwnership(E, isConsumed))
+      return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
+                                                : OBC_Bridge);
   }
 
   static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
@@ -265,6 +270,29 @@ private:
     return false;
   }
 
+  bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
+    if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
+                                     StmtMap->getParentIgnoreParenImpCasts(E)))
+      if (FunctionDecl *
+            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
+        unsigned i = 0;
+        for (unsigned e = callE->getNumArgs(); i != e; ++i) {
+          Expr *arg = callE->getArg(i);
+          if (arg == E || arg->IgnoreParenImpCasts() == E)
+            break;
+        }
+        if (i < callE->getNumArgs()) {
+          ParmVarDecl *PD = FD->getParamDecl(i);
+          if (PD->getAttr<CFConsumedAttr>()) {
+            isConsumed = true;
+            return true;
+          }
+        }
+      }
+
+    return false;
+  }
+
   bool isSelf(Expr *E) const {
     E = E->IgnoreParenLValueCasts();
     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
index f10ae0d2a73645badd907727672d4c040b5b79a8..2603730cad9daacb2bc85be78cc0040b611d38e5 100644 (file)
@@ -4,6 +4,8 @@
 #define NS_AUTOMATED_REFCOUNT_UNAVAILABLE
 #endif
 
+#define CF_CONSUMED __attribute__((cf_consumed))
+
 #define nil ((void*) 0)
 
 typedef int BOOL;
index b4e4080149676cf11dc41ae79a5f1ceab15818d7..080399dfb1f381be897d32b6eb72b434c4f8e070 100644 (file)
@@ -40,6 +40,8 @@ void f(BOOL b, id p) {
 }
 @end
 
+extern void consumeParam(CFStringRef CF_CONSUMED p);
+
 void f2(NSString *s) {
   CFStringRef ref = [s string];
   ref = (CFStringRef)[s string];
@@ -53,4 +55,7 @@ void f2(NSString *s) {
   ref = CFRetain([s string]);
   ref = CFRetain(s);
   ref = [s retain];
+
+  consumeParam((CFStringRef)s);
+  consumeParam(s);
 }
index 1fc2774c14926d4ee9772523287dec59a273e9f7..1e9dab979f53f2b38e69e1e6a0286b80ac7c272d 100644 (file)
@@ -40,6 +40,8 @@ void f(BOOL b, id p) {
 }
 @end
 
+extern void consumeParam(CFStringRef CF_CONSUMED p);
+
 void f2(NSString *s) {
   CFStringRef ref = (__bridge CFStringRef)([s string]);
   ref = (__bridge CFStringRef)[s string];
@@ -53,4 +55,7 @@ void f2(NSString *s) {
   ref = (__bridge_retained CFTypeRef)([s string]);
   ref = (__bridge_retained CFTypeRef)(s);
   ref = (__bridge_retained CFStringRef)(s);
+
+  consumeParam((__bridge_retained CFStringRef)s);
+  consumeParam((__bridge_retained CFStringRef)(s));
 }