aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-07-07 23:04:17 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-07-07 23:04:17 +0000
commit7a084ec568f8336ec6f10011d0118a6b19e253cb (patch)
tree1c49bba913aae0ad3cdb8d6187df00c335b06740
parent7c9adf9113b1d1dfeca1d265a7c3bedb3671cfab (diff)
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
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaCXXCast.cpp12
-rw-r--r--lib/Sema/SemaExpr.cpp32
-rw-r--r--lib/Sema/SemaExprObjC.cpp17
-rw-r--r--test/SemaObjCXX/arc-unavailable-for-weakref.mm36
5 files changed, 77 insertions, 23 deletions
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<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
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<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
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'}}
+}
+