aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-07-07 18:55:47 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-07-07 18:55:47 +0000
commit04e5a2509d1eed48cc0c7115c52089bef35b36af (patch)
treecd9d87daa7bc3725bba7909fab71f6e42b8ce988
parent3582a6c0a35f202249b721e100229fde9de0d6a6 (diff)
objc-arc: diagnose assignment/cast of a weak-unavailable
object to a __weak object/type. // rdar://9732636. This is objc side of things. objc++ side tbd. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134624 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td5
-rw-r--r--include/clang/Sema/Sema.h4
-rw-r--r--lib/Sema/SemaExpr.cpp33
-rw-r--r--test/SemaObjC/arc-unavailable-for-weakref.m19
4 files changed, 59 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index b2301e18d7..2feb043946 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2572,6 +2572,11 @@ def err_arc_weak_no_runtime : Error<
"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<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 30719c1c01..8c68a1da44 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -5426,6 +5426,10 @@ public:
/// "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
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 68b767b474..cf03684c67 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4065,6 +4065,23 @@ ExprResult Sema::CheckCastTypes(SourceLocation CastStartLoc, SourceRange TyR,
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();
+ }
+ }
}
}
@@ -5124,6 +5141,7 @@ Sema::AssignConvertType
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.
@@ -5278,7 +5296,17 @@ Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs,
// 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*
@@ -8679,6 +8707,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
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;
diff --git a/test/SemaObjC/arc-unavailable-for-weakref.m b/test/SemaObjC/arc-unavailable-for-weakref.m
index 07a7e7b975..734fa53472 100644
--- a/test/SemaObjC/arc-unavailable-for-weakref.m
+++ b/test/SemaObjC/arc-unavailable-for-weakref.m
@@ -14,5 +14,22 @@ int main() {
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'}}
+}
+