diff options
| -rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 39 | ||||
| -rw-r--r-- | clang/test/CodeGenObjC/arc-bridged-cast.m | 1 |
2 files changed, 32 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 93c98235654..369ba64cd97 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -4317,14 +4317,37 @@ bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType, /// Look for an ObjCReclaimReturnedObject cast and destroy it. static Expr *maybeUndoReclaimObject(Expr *e) { - // For now, we just undo operands that are *immediately* reclaim - // expressions, which prevents the vast majority of potential - // problems here. To catch them all, we'd need to rebuild arbitrary - // value-propagating subexpressions --- we can't reliably rebuild - // in-place because of expression sharing. - if (auto *ice = dyn_cast<ImplicitCastExpr>(e->IgnoreParens())) - if (ice->getCastKind() == CK_ARCReclaimReturnedObject) - return ice->getSubExpr(); + Expr *curExpr = e, *prevExpr = nullptr; + + // Walk down the expression until we hit an implicit cast of kind + // ARCReclaimReturnedObject or an Expr that is neither a Paren nor a Cast. + while (true) { + if (auto *pe = dyn_cast<ParenExpr>(curExpr)) { + prevExpr = curExpr; + curExpr = pe->getSubExpr(); + continue; + } + + if (auto *ce = dyn_cast<CastExpr>(curExpr)) { + if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) + if (ice->getCastKind() == CK_ARCReclaimReturnedObject) { + if (!prevExpr) + return ice->getSubExpr(); + if (auto *pe = dyn_cast<ParenExpr>(prevExpr)) + pe->setSubExpr(ice->getSubExpr()); + else + cast<CastExpr>(prevExpr)->setSubExpr(ice->getSubExpr()); + return e; + } + + prevExpr = curExpr; + curExpr = ce->getSubExpr(); + continue; + } + + // Break out of the loop if curExpr is neither a Paren nor a Cast. + break; + } return e; } diff --git a/clang/test/CodeGenObjC/arc-bridged-cast.m b/clang/test/CodeGenObjC/arc-bridged-cast.m index 93f5d7ccaa3..42795d5d800 100644 --- a/clang/test/CodeGenObjC/arc-bridged-cast.m +++ b/clang/test/CodeGenObjC/arc-bridged-cast.m @@ -102,5 +102,6 @@ CFStringRef bridge_of_paren_expr() { // CHECK-NOT: call i8* @objc_retainAutoreleasedReturnValue( // CHECK-NOT: call void @objc_release( CFStringRef r = (__bridge CFStringRef)(CreateNSString()); + r = (__bridge CFStringRef)((NSString *)(CreateNSString())); return r; } |

