]> granicus.if.org Git - clang/commitdiff
Suppress -Wunused-variable when initializer uses bridge casts for memory management.
authorTed Kremenek <kremenek@apple.com>
Thu, 14 Nov 2013 01:42:17 +0000 (01:42 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 14 Nov 2013 01:42:17 +0000 (01:42 +0000)
Fixes <rdar://problem/15432770>.

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

lib/Sema/SemaDecl.cpp
test/SemaObjC/arc-bridged-cast.m

index 9281951a814b2518bc50851adf31b1cd3e173f0f..a7b37c55e92aa0cd652b9fffaa8ff967ec7c6b9f 100644 (file)
@@ -1313,6 +1313,28 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
       }
     }
 
+    // Under ARC, bridged casts can have side-effects on memory
+    // management semantics.  Some users assign a bridged
+    // value to a temporary to adjust reference counts.
+    const Expr *Init = VD->getInit();
+    if (Init) {
+      if (const ExprWithCleanups *EC = dyn_cast<ExprWithCleanups>(Init))
+        Init = EC->getSubExpr();
+      Init = Init->IgnoreParens();
+      if (const ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(Init)) {
+        switch (IC->getCastKind()) {
+        case CK_ARCProduceObject:
+        case CK_ARCConsumeObject:
+        case CK_ARCReclaimReturnedObject:
+        case CK_ARCExtendBlockObject:
+        case CK_CopyAndAutoreleaseBlockObject:
+          return false;
+        default:
+          break;
+        }
+      }
+    }
+
     // TODO: __attribute__((unused)) templates?
   }
   
index 439d3821165d96aea711f004913fbcbf34873851..6f5f3782d529ff042d4aa71bcd29569d971030bd 100644 (file)
@@ -62,3 +62,15 @@ CFTypeRef fixitsWithSpace(id obj) {
   // CHECK: fix-it:"{{.*}}":{59:9-59:9}:"(__bridge CFTypeRef)"
   // CHECK: fix-it:"{{.*}}":{59:9-59:9}:" CFBridgingRetain"
 }
+
+// <rdar://problem/15432770>
+// Suppressed -Wunused-variable when the initializer is a bridge cast.
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-Wunused-variable"
+void rdar15432770() {
+  void (^block1)() = ^ { };
+  void *ptr = (__bridge_retained void *)(block1);
+  void (^block2)() = (__bridge_transfer void(^)())ptr; // no-warning
+  int x = 1; // expected-warning {{unused variable}}
+}
+#pragma clang diagnostic pop