aboutsummaryrefslogtreecommitdiff
path: root/gcc/objc
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2020-10-24 15:51:46 +0100
committerIain Sandoe <iain@sandoe.co.uk>2020-11-07 11:45:46 +0000
commit0c30bf43eb2325caa4cb32a697ac1127c15205d7 (patch)
treeb48fce515527857a67855662c4fde50b90cb6328 /gcc/objc
parentdf784801daf0185a1e22ebf03d48363530717882 (diff)
downloadgcc-0c30bf43eb2325caa4cb32a697ac1127c15205d7.zip
gcc-0c30bf43eb2325caa4cb32a697ac1127c15205d7.tar.gz
gcc-0c30bf43eb2325caa4cb32a697ac1127c15205d7.tar.bz2
Objective-C : Implement NSObject attribute.
This attribute allows pointers to be marked as pointers to an NSObject-compatible object. This allows for additional checking of assignment etc. when refering to pointers to opaque types. gcc/c-family/ChangeLog: * c-attribs.c (handle_nsobject_attribute): New. * c.opt: Add WNSObject-attribute. gcc/objc/ChangeLog: * objc-act.c (objc_compare_types): Handle NSObject type attributes. (objc_type_valid_for_messaging): Likewise. gcc/testsuite/ChangeLog: * obj-c++.dg/attributes/nsobject-01.mm: New test. * objc.dg/attributes/nsobject-01.m: New test.
Diffstat (limited to 'gcc/objc')
-rw-r--r--gcc/objc/objc-act.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 68d829f..8be4bea 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -2476,9 +2476,14 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
if (!POINTER_TYPE_P (ltyp) || !POINTER_TYPE_P (rtyp))
return false;
+ tree ltyp_attr, rtyp_attr;
do
{
- ltyp = TREE_TYPE (ltyp); /* Remove indirections. */
+ /* Remove indirections, but keep the type attributes from the innermost
+ pointer type, to check for NSObject. */
+ ltyp_attr = TYPE_ATTRIBUTES (ltyp);
+ ltyp = TREE_TYPE (ltyp);
+ rtyp_attr = TYPE_ATTRIBUTES (rtyp);
rtyp = TREE_TYPE (rtyp);
}
while (POINTER_TYPE_P (ltyp) && POINTER_TYPE_P (rtyp));
@@ -2523,17 +2528,23 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
return true;
}
+ /* We might have void * with NSObject type attr. */
+ bool l_NSObject_p = ltyp_attr && lookup_attribute ("NSObject", ltyp_attr);
+ bool r_NSObject_p = rtyp_attr && lookup_attribute ("NSObject", rtyp_attr);
+
/* Past this point, we are only interested in ObjC class instances,
- or 'id' or 'Class'. */
- if (TREE_CODE (ltyp) != RECORD_TYPE || TREE_CODE (rtyp) != RECORD_TYPE)
+ or 'id' or 'Class' (except if the user applied the NSObject type
+ attribute). */
+ if ((TREE_CODE (ltyp) != RECORD_TYPE && !l_NSObject_p)
+ || (TREE_CODE (rtyp) != RECORD_TYPE && !r_NSObject_p))
return false;
if (!objc_is_object_id (ltyp) && !objc_is_class_id (ltyp)
- && !TYPE_HAS_OBJC_INFO (ltyp))
+ && !TYPE_HAS_OBJC_INFO (ltyp) && !l_NSObject_p)
return false;
if (!objc_is_object_id (rtyp) && !objc_is_class_id (rtyp)
- && !TYPE_HAS_OBJC_INFO (rtyp))
+ && !TYPE_HAS_OBJC_INFO (rtyp) && !r_NSObject_p)
return false;
/* Past this point, we are committed to returning 'true' to the caller
@@ -2567,12 +2578,15 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
rcls = NULL_TREE;
/* If either type is an unqualified 'id', we're done. This is because
- an 'id' can be assigned to or from any type with no warnings. */
+ an 'id' can be assigned to or from any type with no warnings. When
+ the pointer has NSObject attribute, consider that to be equivalent. */
if (argno != -5)
{
if ((!lproto && objc_is_object_id (ltyp))
|| (!rproto && objc_is_object_id (rtyp)))
return true;
+ if (l_NSObject_p || r_NSObject_p)
+ return true;
}
else
{
@@ -2580,7 +2594,7 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
general type of object, hence if you try to specialize an
'NSArray *' (ltyp) property with an 'id' (rtyp) one, we need
to warn. */
- if (!lproto && objc_is_object_id (ltyp))
+ if (!lproto && (objc_is_object_id (ltyp) || l_NSObject_p))
return true;
}
@@ -8659,11 +8673,19 @@ objc_type_valid_for_messaging (tree type, bool accept_classes)
if (!POINTER_TYPE_P (type))
return false;
+ /* We will check for an NSObject type attribute on the pointer if other
+ tests fail. */
+ tree type_attr = TYPE_ATTRIBUTES (type);
+
/* Remove the pointer indirection; don't remove more than one
otherwise we'd consider "NSObject **" a valid type for messaging,
which it isn't. */
type = TREE_TYPE (type);
+ /* We allow void * to have an NSObject type attr. */
+ if (VOID_TYPE_P (type) && type_attr)
+ return lookup_attribute ("NSObject", type_attr) != NULL_TREE;
+
if (TREE_CODE (type) != RECORD_TYPE)
return false;
@@ -8676,6 +8698,9 @@ objc_type_valid_for_messaging (tree type, bool accept_classes)
if (TYPE_HAS_OBJC_INFO (type))
return true;
+ if (type_attr)
+ return lookup_attribute ("NSObject", type_attr) != NULL_TREE;
+
return false;
}