summaryrefslogtreecommitdiffstats
path: root/lib/ARCMigrate/TransUnbridgedCasts.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-09-14 18:17:09 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-09-14 18:17:09 +0000
commit4532b5553db699d5bed250454f9a45e0f66f4bf8 (patch)
treec8429403cb0c1f649fa62b5cb7907d6bea5f50b2 /lib/ARCMigrate/TransUnbridgedCasts.cpp
parent528a499eb84d61667f65b16a13780c135b822f6b (diff)
[arcmt] Use __bridge_retained when passing an objc object to a CF parameter
annotated with cf_consumed attribute. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139709 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ARCMigrate/TransUnbridgedCasts.cpp')
-rw-r--r--lib/ARCMigrate/TransUnbridgedCasts.cpp28
1 files changed, 28 insertions, 0 deletions
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp
index bc33c53b75..047dfb276a 100644
--- a/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -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))