aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprObjC.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-06-21 19:42:38 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-06-21 19:42:38 +0000
commitc8505ad9182c3ddcfda42bee250b2c32dd1f3219 (patch)
tree947ab37798ec0a0d260d46c9543a9fd695ebacad /lib/Sema/SemaExprObjC.cpp
parente26bdb91b7e3912ffe895b78a446db94471a59dd (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.cpp58
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());