diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9281951a814b..a7b37c55e92a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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(Init)) + Init = EC->getSubExpr(); + Init = Init->IgnoreParens(); + if (const ImplicitCastExpr *IC = dyn_cast(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? } diff --git a/clang/test/SemaObjC/arc-bridged-cast.m b/clang/test/SemaObjC/arc-bridged-cast.m index 439d3821165d..6f5f3782d529 100644 --- a/clang/test/SemaObjC/arc-bridged-cast.m +++ b/clang/test/SemaObjC/arc-bridged-cast.m @@ -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" } + +// +// 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