forked from OSchip/llvm-project
objc-arc: CodeGen part of unbridged cast of CF types.
// rdar://9474349 llvm-svn: 133525
This commit is contained in:
parent
646dd0f4d1
commit
7887637c82
|
@ -5616,12 +5616,12 @@ public:
|
|||
|
||||
/// \brief Checks for valid expressions which can be cast to an ObjC
|
||||
/// pointer without needing a bridge cast.
|
||||
bool ValidObjCARCNoBridgeCastExpr(const Expr *Exp);
|
||||
bool ValidObjCARCNoBridgeCastExpr(Expr *&Exp, QualType castType);
|
||||
|
||||
/// \brief Checks for invalid conversions and casts between
|
||||
/// retainable pointers and other pointer kinds.
|
||||
void CheckObjCARCConversion(SourceRange castRange, QualType castType,
|
||||
Expr *op, CheckedConversionKind CCK);
|
||||
Expr *&op, CheckedConversionKind CCK);
|
||||
|
||||
/// checkRetainCycles - Check whether an Objective-C message send
|
||||
/// might create an obvious retain cycle.
|
||||
|
|
|
@ -641,8 +641,9 @@ CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType);
|
||||
}
|
||||
} else if (tcr == TC_Success && Self.getLangOptions().ObjCAutoRefCount) {
|
||||
Expr *Exp = SrcExpr.get();
|
||||
Self.CheckObjCARCConversion(OpRange, DestType,
|
||||
SrcExpr.get(), Sema::CCK_OtherCast);
|
||||
Exp, Sema::CCK_OtherCast);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,9 +705,11 @@ CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
} else if (tcr == TC_Success) {
|
||||
if (Kind == CK_BitCast)
|
||||
Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
|
||||
if (Self.getLangOptions().ObjCAutoRefCount)
|
||||
if (Self.getLangOptions().ObjCAutoRefCount) {
|
||||
Expr *Exp = SrcExpr.get();
|
||||
Self.CheckObjCARCConversion(OpRange, DestType,
|
||||
SrcExpr.get(), Sema::CCK_OtherCast);
|
||||
Exp, Sema::CCK_OtherCast);
|
||||
}
|
||||
}
|
||||
else if (Kind == CK_BitCast)
|
||||
Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
|
||||
|
|
|
@ -1551,14 +1551,50 @@ namespace {
|
|||
}
|
||||
|
||||
bool
|
||||
Sema::ValidObjCARCNoBridgeCastExpr(const Expr *Exp) {
|
||||
Exp = Exp->IgnoreParenImpCasts();
|
||||
return isa<ObjCMessageExpr>(Exp) || isa<ObjCPropertyRefExpr>(Exp);
|
||||
Sema::ValidObjCARCNoBridgeCastExpr(Expr *&Exp, QualType castType) {
|
||||
Expr *NewExp = Exp->IgnoreParenImpCasts();
|
||||
|
||||
if (!isa<ObjCMessageExpr>(NewExp) && !isa<ObjCPropertyRefExpr>(NewExp))
|
||||
return false;
|
||||
ObjCMethodDecl *method = 0;
|
||||
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(NewExp)) {
|
||||
method = PRE->getExplicitProperty()->getGetterMethodDecl();
|
||||
}
|
||||
else {
|
||||
ObjCMessageExpr *ME = cast<ObjCMessageExpr>(NewExp);
|
||||
method = ME->getMethodDecl();
|
||||
}
|
||||
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 (MethodReturnsPlusOne) {
|
||||
TypeSourceInfo *TSInfo =
|
||||
Context.getTrivialTypeSourceInfo(castType, SourceLocation());
|
||||
ExprResult ExpRes = BuildObjCBridgedCast(SourceLocation(), OBC_BridgeTransfer,
|
||||
SourceLocation(), TSInfo, Exp);
|
||||
Exp = ExpRes.take();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
|
||||
Expr *castExpr, CheckedConversionKind CCK) {
|
||||
Expr *&castExpr, CheckedConversionKind CCK) {
|
||||
QualType castExprType = castExpr->getType();
|
||||
|
||||
ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType);
|
||||
|
@ -1614,7 +1650,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
|
|||
castExprType->isCARCBridgableType()) {
|
||||
// explicit unbridged casts are allowed if the source of the cast is a
|
||||
// message sent to an objc method (or property access)
|
||||
if (ValidObjCARCNoBridgeCastExpr(castExpr))
|
||||
if (ValidObjCARCNoBridgeCastExpr(castExpr, castType))
|
||||
return;
|
||||
Diag(loc, diag::err_arc_cast_requires_bridge)
|
||||
<< 2
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -emit-llvm -fobjc-nonfragile-abi -fobjc-arc -o - %s | FileCheck %s
|
||||
// rdar://9744349
|
||||
|
||||
typedef const struct __CFString * CFStringRef;
|
||||
|
||||
@interface I
|
||||
@property CFStringRef P;
|
||||
- (CFStringRef) CFMeth __attribute__((cf_returns_retained));
|
||||
- (CFStringRef) newSomething;
|
||||
- (CFStringRef) P __attribute__((cf_returns_retained));
|
||||
@end
|
||||
|
||||
@implementation I
|
||||
@synthesize P;
|
||||
- (id) Meth {
|
||||
I* p1 = (id)[p1 P];
|
||||
id p2 = (id)[p1 CFMeth];
|
||||
id p3 = (id)[p1 newSomething];
|
||||
return (id) p1.P;
|
||||
}
|
||||
- (CFStringRef) CFMeth { return 0; }
|
||||
- (CFStringRef) newSomething { return 0; }
|
||||
- (CFStringRef) P { return 0; }
|
||||
- (void) setP : (CFStringRef)arg {}
|
||||
@end
|
||||
|
||||
// CHECK-NOT: call i8* @objc_retainAutoreleasedReturnValue
|
Loading…
Reference in New Issue