diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index fb1c90950822..3764a4091546 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -263,6 +263,11 @@ def warn_objc_protocol_qualifier_missing_id : Warning< def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">; def err_illegal_super_cast : Error< "cannot cast 'super' (it isn't an expression)">; + +let CategoryName = "Automatic Reference Counting Issue" in { +def err_arc_bridge_retain : Error< + "unknown cast annotation __bridge_retain; did you mean __bridge_retained?">; +} def err_objc_illegal_visibility_spec : Error< "illegal visibility specification">; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 14f3805cd971..39db0e90450d 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1781,17 +1781,29 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, (Tok.is(tok::kw___bridge) || Tok.is(tok::kw___bridge_transfer) || Tok.is(tok::kw___bridge_retained) || - Tok.is(tok::kw___bridge_retain))) { // FIXME: temporary workaround + Tok.is(tok::kw___bridge_retain))) { + tok::TokenKind tokenKind = Tok.getKind(); + SourceLocation BridgeKeywordLoc = ConsumeToken(); + // Parse an Objective-C ARC ownership cast expression. ObjCBridgeCastKind Kind; - if (Tok.is(tok::kw___bridge)) + if (tokenKind == tok::kw___bridge) Kind = OBC_Bridge; - else if (Tok.is(tok::kw___bridge_transfer)) + else if (tokenKind == tok::kw___bridge_transfer) Kind = OBC_BridgeTransfer; - else + else if (tokenKind == tok::kw___bridge_retained) Kind = OBC_BridgeRetained; + else { + // As a hopefully temporary workaround, allow __bridge_retain as + // a synonym for __bridge_retained, but only in system headers. + assert(tokenKind == tok::kw___bridge_retain); + Kind = OBC_BridgeRetained; + if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc)) + Diag(BridgeKeywordLoc, diag::err_arc_bridge_retain) + << FixItHint::CreateReplacement(BridgeKeywordLoc, + "__bridge_retained"); + } - SourceLocation BridgeKeywordLoc = ConsumeToken(); TypeResult Ty = ParseTypeName(); SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, OpenLoc); ExprResult SubExpr = ParseCastExpression(false, false, ParsedType()); diff --git a/clang/test/SemaObjC/Inputs/arc-system-header.h b/clang/test/SemaObjC/Inputs/arc-system-header.h index 9e76cd84ab7d..5012a2a37837 100644 --- a/clang/test/SemaObjC/Inputs/arc-system-header.h +++ b/clang/test/SemaObjC/Inputs/arc-system-header.h @@ -40,3 +40,13 @@ extern struct Test6 *const kMagicConstant; @interface Test7 @property id *prop; @end + + + + + + + +static inline void *test8(id ptr) { + return (__bridge_retain void*) ptr; +} diff --git a/clang/test/SemaObjC/arc-bridged-cast.m b/clang/test/SemaObjC/arc-bridged-cast.m index d302182476d0..e883406db908 100644 --- a/clang/test/SemaObjC/arc-bridged-cast.m +++ b/clang/test/SemaObjC/arc-bridged-cast.m @@ -30,7 +30,7 @@ void to_cf(id obj) { CFStringRef cf4 = (__bridge CFStringRef)CreateNSString(); // rdar://problem/9629566 - temporary workaround - CFTypeRef cf5 = (__bridge_retain CFTypeRef)CreateSomething(); + CFTypeRef cf5 = (__bridge_retain CFTypeRef)CreateSomething(); // expected-error {{unknown cast annotation __bridge_retain; did you mean __bridge_retained?}} } void fixits() { diff --git a/clang/test/SemaObjC/arc-system-header.m b/clang/test/SemaObjC/arc-system-header.m index e635dc0a80bc..9d8aaf43d29e 100644 --- a/clang/test/SemaObjC/arc-system-header.m +++ b/clang/test/SemaObjC/arc-system-header.m @@ -46,3 +46,5 @@ void test7(Test7 *p) { [p setProp: 0]; // expected-error {{'setProp:' is unavailable: this system declaration uses an unsupported type}} } #endif + +// test8 in header