diff options
author | Iain Sandoe <iain@sandoe.co.uk> | 2020-10-24 15:51:46 +0100 |
---|---|---|
committer | Iain Sandoe <iain@sandoe.co.uk> | 2020-11-07 11:45:46 +0000 |
commit | 0c30bf43eb2325caa4cb32a697ac1127c15205d7 (patch) | |
tree | b48fce515527857a67855662c4fde50b90cb6328 /gcc/objc | |
parent | df784801daf0185a1e22ebf03d48363530717882 (diff) | |
download | gcc-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.c | 39 |
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; } |