]> granicus.if.org Git - clang/commitdiff
[Sema][ObjC] Preserve syntactic sugar when removing
authorAkira Hatanaka <ahatanaka@apple.com>
Tue, 10 Oct 2017 01:24:33 +0000 (01:24 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Tue, 10 Oct 2017 01:24:33 +0000 (01:24 +0000)
ARCReclaimReturnedObject cast.

This is a follow-up to r314370.

Rather than throwing away the enclosing parentheses, this commit walks
down the expression until an ARCReclaimReturnedObject cast is found and
removes just the cast, preserving the syntactic sugar expressions
(parens and casts) that were visited up to that point.

rdar://problem/34705720

Differential Revision: https://reviews.llvm.org/D38659

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

lib/Sema/SemaExprObjC.cpp
test/CodeGenObjC/arc-bridged-cast.m

index 93c982356540f0f44c814dcc1212bbd080274d58..369ba64cd97b3809ccbfc5ab2aa7a2fdb8065f52 100644 (file)
@@ -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;
 }
index 93f5d7ccaa3e610a808315508b1b80c09b29d3e6..42795d5d800904c6084fae77914e4ffe54a5b8e7 100644 (file)
@@ -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;
 }