From: Fariborz Jahanian Date: Tue, 21 Jun 2011 19:42:38 +0000 (+0000) Subject: objc-arc: Add support for unbridged cast of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c8505ad9182c3ddcfda42bee250b2c32dd1f3219;p=clang objc-arc: Add support for unbridged cast of __builtin___CFStringMakeConstantString and CF typed function calls with explicit cf_returns_retained/cf_returns_not_retained attributes. // rdar://9544832 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133535 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index ff3f837bac..83b01f24a2 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1552,36 +1552,56 @@ namespace { bool Sema::ValidObjCARCNoBridgeCastExpr(Expr *&Exp, QualType castType) { - Expr *NewExp = Exp->IgnoreParenImpCasts(); + Expr *NewExp = Exp->IgnoreParenCasts(); - if (!isa(NewExp) && !isa(NewExp)) + if (!isa(NewExp) && !isa(NewExp) + && !isa(NewExp)) return false; ObjCMethodDecl *method = 0; + bool MethodReturnsPlusOne = false; + if (ObjCPropertyRefExpr *PRE = dyn_cast(NewExp)) { method = PRE->getExplicitProperty()->getGetterMethodDecl(); } - else { - ObjCMessageExpr *ME = cast(NewExp); + else if (ObjCMessageExpr *ME = dyn_cast(NewExp)) method = ME->getMethodDecl(); + else { + CallExpr *CE = cast(NewExp); + Decl *CallDecl = CE->getCalleeDecl(); + if (!CallDecl) + return false; + if (CallDecl->hasAttr()) + return true; + MethodReturnsPlusOne = CallDecl->hasAttr(); + if (!MethodReturnsPlusOne) { + if (NamedDecl *ND = dyn_cast(CallDecl)) + if (const IdentifierInfo *Id = ND->getIdentifier()) + if (Id->isStr("__builtin___CFStringMakeConstantString")) + return true; + } } - if (!method) - return false; - if (method->hasAttr()) - return true; - bool MethodReturnsPlusOne = method->hasAttr(); + if (!MethodReturnsPlusOne) { - ObjCMethodFamily family = method->getSelector().getMethodFamily(); - switch (family) { - case OMF_alloc: - case OMF_copy: - case OMF_mutableCopy: - case OMF_new: - MethodReturnsPlusOne = true; - break; - default: - break; + if (!method) + return false; + if (method->hasAttr()) + return true; + MethodReturnsPlusOne = method->hasAttr(); + if (!MethodReturnsPlusOne) { + ObjCMethodFamily family = method->getSelector().getMethodFamily(); + switch (family) { + case OMF_alloc: + case OMF_copy: + case OMF_mutableCopy: + case OMF_new: + MethodReturnsPlusOne = true; + break; + default: + break; + } } } + if (MethodReturnsPlusOne) { TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(castType, SourceLocation()); diff --git a/test/CodeGenObjC/arc-unbridged-cast.m b/test/CodeGenObjC/arc-unbridged-cast.m index 5c560e94ab..0f3db09f1f 100644 --- a/test/CodeGenObjC/arc-unbridged-cast.m +++ b/test/CodeGenObjC/arc-unbridged-cast.m @@ -24,4 +24,14 @@ typedef const struct __CFString * CFStringRef; - (void) setP : (CFStringRef)arg {} @end +// rdar://9544832 +CFStringRef SomeOtherFunc() __attribute__((cf_returns_retained)); +id MMM() +{ + id obj = (id)((CFStringRef) __builtin___CFStringMakeConstantString ("" "Some CF String" "")); + if (obj) + return (id) SomeOtherFunc(); + return 0; +} + // CHECK-NOT: call i8* @objc_retainAutoreleasedReturnValue