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 | 9b83be832bf6b2ad2143550838f126f9436049ff (patch) | |
tree | d32691c81d0cfc8e0c5798fdba019f4f0fa9b161 /clang/lib/Sema/SemaExprObjC.cpp | |
parent | d0abdab8d18f055d8fc3b8327d7628e5f237ae7c (diff) | |
download | bcm5719-llvm-9b83be832bf6b2ad2143550838f126f9436049ff.tar.gz bcm5719-llvm-9b83be832bf6b2ad2143550838f126f9436049ff.zip |
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
llvm-svn: 133535
Diffstat (limited to 'clang/lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index ff3f837bace..83b01f24a21 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/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()); |