summaryrefslogtreecommitdiffstats
path: root/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/ARCMigrate/TransUnbridgedCasts.cpp')
-rw-r--r--clang/lib/ARCMigrate/TransUnbridgedCasts.cpp21
1 files changed, 19 insertions, 2 deletions
diff --git a/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp b/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
index 37cebc9e3ad..72c0d8e7de3 100644
--- a/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -50,13 +50,15 @@ class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
MigrationPass &Pass;
IdentifierInfo *SelfII;
OwningPtr<ParentMap> StmtMap;
+ Decl *ParentD;
public:
- UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass) {
+ UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass), ParentD(0) {
SelfII = &Pass.Ctx.Idents.get("self");
}
- void transformBody(Stmt *body) {
+ void transformBody(Stmt *body, Decl *ParentD) {
+ this->ParentD = ParentD;
StmtMap.reset(new ParentMap(body));
TraverseStmt(body);
}
@@ -155,6 +157,21 @@ private:
}
}
}
+
+ // If returning an ivar or a member of an ivar from a +0 method, use
+ // a __bridge cast.
+ Expr *base = inner->IgnoreParenImpCasts();
+ while (isa<MemberExpr>(base))
+ base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts();
+ if (isa<ObjCIvarRefExpr>(base) &&
+ isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
+ if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
+ if (!method->hasAttr<NSReturnsRetainedAttr>()) {
+ castToObjCObject(E, /*retained=*/false);
+ return;
+ }
+ }
+ }
}
void castToObjCObject(CastExpr *E, bool retained) {
OpenPOWER on IntegriCloud