diff options
Diffstat (limited to 'clang/lib/ARCMigrate/TransUnbridgedCasts.cpp')
-rw-r--r-- | clang/lib/ARCMigrate/TransUnbridgedCasts.cpp | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp b/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp index bc33c53b758..047dfb276ad 100644 --- a/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp +++ b/clang/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)) |