diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-06-21 19:42:38 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-06-21 19:42:38 +0000 |
commit | c8505ad9182c3ddcfda42bee250b2c32dd1f3219 (patch) | |
tree | 947ab37798ec0a0d260d46c9543a9fd695ebacad /lib/Sema/SemaExprObjC.cpp | |
parent | e26bdb91b7e3912ffe895b78a446db94471a59dd (diff) |
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
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 58 |
1 files changed, 39 insertions, 19 deletions
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<ObjCMessageExpr>(NewExp) && !isa<ObjCPropertyRefExpr>(NewExp)) + if (!isa<ObjCMessageExpr>(NewExp) && !isa<ObjCPropertyRefExpr>(NewExp) + && !isa<CallExpr>(NewExp)) return false; ObjCMethodDecl *method = 0; + bool MethodReturnsPlusOne = false; + if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(NewExp)) { method = PRE->getExplicitProperty()->getGetterMethodDecl(); } - else { - ObjCMessageExpr *ME = cast<ObjCMessageExpr>(NewExp); + else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(NewExp)) method = ME->getMethodDecl(); + else { + CallExpr *CE = cast<CallExpr>(NewExp); + Decl *CallDecl = CE->getCalleeDecl(); + if (!CallDecl) + return false; + if (CallDecl->hasAttr<CFReturnsNotRetainedAttr>()) + return true; + MethodReturnsPlusOne = CallDecl->hasAttr<CFReturnsRetainedAttr>(); + if (!MethodReturnsPlusOne) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(CallDecl)) + if (const IdentifierInfo *Id = ND->getIdentifier()) + if (Id->isStr("__builtin___CFStringMakeConstantString")) + return true; + } } - if (!method) - return false; - if (method->hasAttr<CFReturnsNotRetainedAttr>()) - return true; - bool MethodReturnsPlusOne = method->hasAttr<CFReturnsRetainedAttr>(); + 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<CFReturnsNotRetainedAttr>()) + return true; + MethodReturnsPlusOne = method->hasAttr<CFReturnsRetainedAttr>(); + 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()); |