"the current deployment target does not support automated __weak references">;
def err_arc_unsupported_weak_class : Error<
"class is incompatible with __weak references">;
+def err_arc_weak_unavailable_assign : Error<
+ "assignment of a weak-unavailable object to a __weak object">;
+def err_arc_cast_of_weak_unavailable : Error<
+ "cast of weak-unavailable object of type %0 to"
+ " a __weak object of type %1">;
def err_arc_illegal_explicit_message : Error<
"ARC forbids explicit message send of %0">;
def err_arc_unused_init_message : Error<
/// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol.
IncompatibleObjCQualifiedId,
+ /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
+ /// object with __weak qualifier.
+ IncompatibleObjCWeakRef,
+
/// Incompatible - We reject this conversion outright, it is invalid to
/// represent it in the AST.
Incompatible
return ExprError();
}
}
+ }
+ 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)
+ << castExprType << castType
+ << castExpr->getSourceRange();
+ return ExprError();
+ }
+ }
}
}
Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs,
CastKind &Kind) {
QualType rhsType = rhs.get()->getType();
+ QualType origLhsType = lhsType;
// Get canonical types. We're not formatting these types, just comparing
// them.
// A* -> B*
if (rhsType->isObjCObjectPointerType()) {
Kind = CK_BitCast;
- return checkObjCPointerTypesForAssignment(*this, lhsType, rhsType);
+ Sema::AssignConvertType result =
+ 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;
+ }
+ return result;
}
// int or null -> A*
case IncompatibleVectors:
DiagKind = diag::warn_incompatible_vectors;
break;
+ case IncompatibleObjCWeakRef:
+ DiagKind = diag::err_arc_weak_unavailable_assign;
+ break;
case Incompatible:
DiagKind = diag::err_typecheck_convert_incompatible;
isInvalid = true;
id obj;
- ns1 = (__weak sub *)obj; // expected-error {{class is incompatible with __weak references}}
+ 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}}
+
+ __weak id weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
+ return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}}
+}
+