From 7a084ec568f8336ec6f10011d0118a6b19e253cb Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 7 Jul 2011 23:04:17 +0000 Subject: [PATCH] objc++-arc: diagnose assignment/cast of a weak-unavailable object to a __weak object/type. // rdar://9732636. One item is yet todo. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134655 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 3 ++ lib/Sema/SemaCXXCast.cpp | 12 +++++-- lib/Sema/SemaExpr.cpp | 32 ++++++----------- lib/Sema/SemaExprObjC.cpp | 17 +++++++++ .../SemaObjCXX/arc-unavailable-for-weakref.mm | 36 +++++++++++++++++++ 5 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 test/SemaObjCXX/arc-unavailable-for-weakref.mm diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 8c68a1da44..e0f2f39b22 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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. diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index d053d5a9e9..0721814c18 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -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) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index cf03684c67..fea31aa046 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4066,22 +4066,12 @@ ExprResult Sema::CheckCastTypes(SourceLocation CastStartLoc, SourceRange TyR, } } } - else { - QualType canCastType = - Context.getCanonicalType(castType).getUnqualifiedType(); - if (isa(canCastType) && - castType.getObjCLifetime() == Qualifiers::OCL_Weak && - castExprType->isObjCObjectPointerType()) { - if (const ObjCObjectPointerType *ObjT = - castExprType->getAs()) - 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()) - 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 diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index fa51098f1a..22953da97b 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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(canCastType) && + castType.getObjCLifetime() == Qualifiers::OCL_Weak && + canExprType->isObjCObjectPointerType()) { + if (const ObjCObjectPointerType *ObjT = + canExprType->getAs()) + 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 diff --git a/test/SemaObjCXX/arc-unavailable-for-weakref.mm b/test/SemaObjCXX/arc-unavailable-for-weakref.mm new file mode 100644 index 0000000000..a22d79789c --- /dev/null +++ b/test/SemaObjCXX/arc-unavailable-for-weakref.mm @@ -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'}} +} + -- 2.40.0