objc++-arc: diagnose assignment/cast of a weak-unavailable

object to a __weak object/type. // rdar://9732636.
One item is yet todo.

llvm-svn: 134655
This commit is contained in:
Fariborz Jahanian
2011-07-07 23:04:17 +00:00
parent 0c912c5f9b
commit 7fcce6829d
5 changed files with 77 additions and 23 deletions

View File

@@ -5626,6 +5626,9 @@ public:
/// retainable pointers and other pointer kinds.
void CheckObjCARCConversion(SourceRange castRange, QualType castType,
Expr *&op, CheckedConversionKind CCK);
bool CheckObjCARCUnavailableWeakConversion(QualType castType,
QualType ExprType);
/// checkRetainCycles - Check whether an Objective-C message send
/// might create an obvious retain cycle.

View File

@@ -1717,7 +1717,8 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
Kind = CK_Dependent;
return Owned(CastExpr);
}
QualType origCastExprType = CastExpr->getType();
if (VK == VK_RValue && !CastTy->isRecordType()) {
ExprResult CastExprRes = DefaultFunctionArrayLvalueConversion(CastExpr);
if (CastExprRes.isInvalid())
@@ -1773,8 +1774,15 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
}
}
if (getLangOptions().ObjCAutoRefCount && tcr == TC_Success)
if (getLangOptions().ObjCAutoRefCount && tcr == TC_Success) {
CheckObjCARCConversion(R, CastTy, CastExpr, CCK);
if (!CheckObjCARCUnavailableWeakConversion(CastTy,
origCastExprType))
Diag(CastExpr->getLocStart(),
diag::err_arc_cast_of_weak_unavailable)
<< origCastExprType << CastTy
<< CastExpr->getSourceRange();
}
if (tcr != TC_Success && msg != 0) {
if (CastExpr->getType() == Context.OverloadTy) {

View File

@@ -4066,22 +4066,12 @@ ExprResult Sema::CheckCastTypes(SourceLocation CastStartLoc, SourceRange TyR,
}
}
}
else {
QualType canCastType =
Context.getCanonicalType(castType).getUnqualifiedType();
if (isa<ObjCObjectPointerType>(canCastType) &&
castType.getObjCLifetime() == Qualifiers::OCL_Weak &&
castExprType->isObjCObjectPointerType()) {
if (const ObjCObjectPointerType *ObjT =
castExprType->getAs<ObjCObjectPointerType>())
if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) {
Diag(castExpr->getLocStart(),
diag::err_arc_cast_of_weak_unavailable)
else if (!CheckObjCARCUnavailableWeakConversion(castType, castExprType)) {
Diag(castExpr->getLocStart(),
diag::err_arc_cast_of_weak_unavailable)
<< castExprType << castType
<< castExpr->getSourceRange();
return ExprError();
}
}
return ExprError();
}
}
@@ -5300,12 +5290,8 @@ Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs,
checkObjCPointerTypesForAssignment(*this, lhsType, rhsType);
if (getLangOptions().ObjCAutoRefCount &&
result == Compatible &&
origLhsType.getObjCLifetime() == Qualifiers::OCL_Weak) {
if (const ObjCObjectPointerType *ObjT =
rhsType->getAs<ObjCObjectPointerType>())
if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable())
result = IncompatibleObjCWeakRef;
}
!CheckObjCARCUnavailableWeakConversion(origLhsType, rhsType))
result = IncompatibleObjCWeakRef;
return result;
}
@@ -5474,8 +5460,12 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, ExprResult &rExpr) {
AA_Assigning);
if (Res.isInvalid())
return Incompatible;
Sema::AssignConvertType result = Compatible;
if (getLangOptions().ObjCAutoRefCount &&
!CheckObjCARCUnavailableWeakConversion(lhsType, rExpr.get()->getType()))
result = IncompatibleObjCWeakRef;
rExpr = move(Res);
return Compatible;
return result;
}
// FIXME: Currently, we fall through and treat C++ classes like C

View File

@@ -1771,6 +1771,23 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
<< castRange << castExpr->getSourceRange();
}
bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,
QualType exprType) {
QualType canCastType =
Context.getCanonicalType(castType).getUnqualifiedType();
QualType canExprType =
Context.getCanonicalType(exprType).getUnqualifiedType();
if (isa<ObjCObjectPointerType>(canCastType) &&
castType.getObjCLifetime() == Qualifiers::OCL_Weak &&
canExprType->isObjCObjectPointerType()) {
if (const ObjCObjectPointerType *ObjT =
canExprType->getAs<ObjCObjectPointerType>())
if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable())
return false;
}
return true;
}
/// Look for an ObjCReclaimReturnedObject cast and destroy it.
static Expr *maybeUndoReclaimObject(Expr *e) {
// For now, we just undo operands that are *immediately* reclaim

View File

@@ -0,0 +1,36 @@
// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-nonfragile-abi -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify %s
// rdar://9693477
__attribute__((objc_arc_weak_reference_unavailable))
@interface NSOptOut1072 // expected-note {{class is declared here}}
@end
@interface sub : NSOptOut1072 @end // expected-note 2 {{class is declared here}}
int main() {
__weak sub *w2; // expected-error {{class is incompatible with __weak references}}
__weak NSOptOut1072 *ns1; // expected-error {{class is incompatible with __weak references}}
id obj;
ns1 = (__weak sub *)obj; // expected-error {{assignment of a weak-unavailable object to a __weak object}} \
// expected-error {{class is incompatible with __weak references}}
}
// rdar://9732636
__attribute__((objc_arc_weak_reference_unavailable))
@interface NOWEAK
+ (id) new;
@end
NOWEAK * Test9732636() {
NOWEAK * strong1 = [NOWEAK new];
__weak id weak1;
weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
// FIXME. NYI.
__weak id weak2 = strong1; // expected-FIXME {{assignment of a weak-unavailable object to a __weak object}}
return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *__strong' to a __weak object of type '__weak id'}}
}