aboutsummaryrefslogtreecommitdiff
path: root/gcc/objc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-11-10 07:26:18 -0800
committerIan Lance Taylor <iant@golang.org>2020-11-10 07:26:18 -0800
commit8d703821c69062c0cd255787d793e44f1a95d463 (patch)
tree6b1df9cdc36cc47b6164db69a14bc86a63dc77c6 /gcc/objc
parent9cd320ea6572c577cdf17ce1f9ea5230b166af6d (diff)
parentcf392dbdf17e38026f8e3c0e9af7f5b87f63be56 (diff)
downloadgcc-8d703821c69062c0cd255787d793e44f1a95d463.zip
gcc-8d703821c69062c0cd255787d793e44f1a95d463.tar.gz
gcc-8d703821c69062c0cd255787d793e44f1a95d463.tar.bz2
Merge from trunk revision cf392dbdf17e38026f8e3c0e9af7f5b87f63be56.
Diffstat (limited to 'gcc/objc')
-rw-r--r--gcc/objc/ChangeLog45
-rw-r--r--gcc/objc/objc-act.c368
-rw-r--r--gcc/objc/objc-act.h7
-rw-r--r--gcc/objc/objc-gnu-runtime-abi-01.c7
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c7
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c7
6 files changed, 315 insertions, 126 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index f69d2d7..5bc41c6 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,48 @@
+2020-11-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_prop_attr_kind_for_rid): Handle class
+ attribute.
+ (objc_add_property_declaration): Likewise.
+ * objc-act.h (PROPERTY_CLASS): Record class attribute state.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_prop_attr_kind_for_rid): Handle
+ RID_PROPATOMIC.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_compare_types): Handle NSObject type
+ attributes.
+ (objc_type_valid_for_messaging): Likewise.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (start_class): Accept visibility attributes
+ without warning.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_prop_attr_kind_for_rid): New.
+ (objc_add_property_declaration): Adjust to consume the
+ parser output using a vector of parsed attributes.
+
+2020-11-04 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_non_constant_expr_p): New.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (synth_module_prologue): Get the SEL identifier.
+ * objc-act.h (enum objc_tree_index): Add OCTI_SEL_NAME.
+ (objc_selector_name): New.
+ (SEL_TYPEDEF_NAME): New.
+ * objc-gnu-runtime-abi-01.c
+ (gnu_runtime_01_initialize): Initialize SEL typedef.
+ * objc-next-runtime-abi-01.c
+ (next_runtime_01_initialize): Likewise.
+ * objc-next-runtime-abi-02.c
+
2020-10-11 Iain Sandoe <iain@sandoe.co.uk>
* objc-next-runtime-abi-02.c
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 31a2cf3..b9ed32d 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -804,119 +804,76 @@ lookup_property (tree interface_type, tree property)
return inter;
}
+/* This routine returns a PROPERTY_KIND for the front end RID code supplied. */
+
+enum objc_property_attribute_kind
+objc_prop_attr_kind_for_rid (enum rid prop_rid)
+{
+ switch (prop_rid)
+ {
+ default: return OBJC_PROPERTY_ATTR_UNKNOWN;
+ case RID_GETTER: return OBJC_PROPERTY_ATTR_GETTER;
+ case RID_SETTER: return OBJC_PROPERTY_ATTR_SETTER;
+
+ case RID_READONLY: return OBJC_PROPERTY_ATTR_READONLY;
+ case RID_READWRITE: return OBJC_PROPERTY_ATTR_READWRITE;
+
+ case RID_ASSIGN: return OBJC_PROPERTY_ATTR_ASSIGN;
+ case RID_RETAIN: return OBJC_PROPERTY_ATTR_RETAIN;
+ case RID_COPY: return OBJC_PROPERTY_ATTR_COPY;
+
+ case RID_PROPATOMIC: return OBJC_PROPERTY_ATTR_ATOMIC;
+ case RID_NONATOMIC: return OBJC_PROPERTY_ATTR_NONATOMIC;
+
+ case RID_CLASS: return OBJC_PROPERTY_ATTR_CLASS;
+ }
+}
+
/* This routine is called by the parser when a
@property... declaration is found. 'decl' is the declaration of
the property (type/identifier), and the other arguments represent
property attributes that may have been specified in the Objective-C
declaration. 'parsed_property_readonly' is 'true' if the attribute
'readonly' was specified, and 'false' if not; similarly for the
- other bool parameters. 'parsed_property_getter_ident' is NULL_TREE
+ other bool parameters. 'property_getter_ident' is NULL_TREE
if the attribute 'getter' was not specified, and is the identifier
corresponding to the specified getter if it was; similarly for
- 'parsed_property_setter_ident'. */
+ 'property_setter_ident'. */
void
objc_add_property_declaration (location_t location, tree decl,
- bool parsed_property_readonly, bool parsed_property_readwrite,
- bool parsed_property_assign, bool parsed_property_retain,
- bool parsed_property_copy, bool parsed_property_nonatomic,
- tree parsed_property_getter_ident, tree parsed_property_setter_ident)
+ vec<property_attribute_info *>& prop_attr_list)
{
- tree property_decl;
- tree x;
- /* 'property_readonly' and 'property_assign_semantics' are the final
- attributes of the property after all parsed attributes have been
- considered (eg, if we parsed no 'readonly' and no 'readwrite', ie
- parsed_property_readonly = false and parsed_property_readwrite =
- false, then property_readonly will be false because the default
- is readwrite). */
- bool property_readonly = false;
- objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
- bool property_extension_in_class_extension = false;
-
if (flag_objc1_only)
- error_at (input_location, "%<@property%> is not available in Objective-C 1.0");
-
- if (parsed_property_readonly && parsed_property_readwrite)
- {
- error_at (location, "%<readonly%> attribute conflicts with %<readwrite%> attribute");
- /* In case of conflicting attributes (here and below), after
- producing an error, we pick one of the attributes and keep
- going. */
- property_readonly = false;
- }
- else
- {
- if (parsed_property_readonly)
- property_readonly = true;
-
- if (parsed_property_readwrite)
- property_readonly = false;
- }
-
- if (parsed_property_readonly && parsed_property_setter_ident)
- {
- error_at (location, "%<readonly%> attribute conflicts with %<setter%> attribute");
- property_readonly = false;
- }
-
- if (parsed_property_assign && parsed_property_retain)
- {
- error_at (location, "%<assign%> attribute conflicts with %<retain%> attribute");
- property_assign_semantics = OBJC_PROPERTY_RETAIN;
- }
- else if (parsed_property_assign && parsed_property_copy)
- {
- error_at (location, "%<assign%> attribute conflicts with %<copy%> attribute");
- property_assign_semantics = OBJC_PROPERTY_COPY;
- }
- else if (parsed_property_retain && parsed_property_copy)
- {
- error_at (location, "%<retain%> attribute conflicts with %<copy%> attribute");
- property_assign_semantics = OBJC_PROPERTY_COPY;
- }
- else
- {
- if (parsed_property_assign)
- property_assign_semantics = OBJC_PROPERTY_ASSIGN;
-
- if (parsed_property_retain)
- property_assign_semantics = OBJC_PROPERTY_RETAIN;
-
- if (parsed_property_copy)
- property_assign_semantics = OBJC_PROPERTY_COPY;
- }
+ /* FIXME: we probably ought to bail out at this point. */
+ error_at (location, "%<@property%> is not available in Objective-C 1.0");
+ /* We must be in an interface, category, or protocol. */
if (!objc_interface_context)
{
- error_at (location, "property declaration not in @interface or @protocol context");
+ error_at (location, "property declaration not in %<@interface%>,"
+ " %<@protocol%> or %<category%> context");
return;
}
- /* At this point we know that we are either in an interface, a
- category, or a protocol. */
+ /* Do some spot-checks for the most obvious invalid cases. */
- /* We expect a FIELD_DECL from the parser. Make sure we didn't get
- something else, as that would confuse the checks below. */
- if (TREE_CODE (decl) != FIELD_DECL)
+ gcc_checking_assert (decl && TREE_CODE (decl) == FIELD_DECL);
+
+ if (decl && !DECL_NAME (decl))
{
- error_at (location, "invalid property declaration");
+ error_at (location, "properties must be named");
return;
}
- /* Do some spot-checks for the most obvious invalid types. */
-
+ location_t decl_loc = DECL_SOURCE_LOCATION (decl);
+ decl_loc = make_location (decl_loc, location, decl_loc);
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
- error_at (location, "property cannot be an array");
+ error_at (decl_loc, "property cannot be an array");
return;
}
- /* The C++/ObjC++ parser seems to reject the ':' for a bitfield when
- parsing, while the C/ObjC parser accepts it and gives us a
- FIELD_DECL with a DECL_INITIAL set. So we use the DECL_INITIAL
- to check for a bitfield when doing ObjC. */
-#ifndef OBJCPLUS
- if (DECL_INITIAL (decl))
+ if (DECL_C_BIT_FIELD (decl))
{
/* A @property is not an actual variable, but it is a way to
describe a pair of accessor methods, so its type (which is
@@ -925,10 +882,118 @@ objc_add_property_declaration (location_t location, tree decl,
and arguments of functions cannot be bitfields). The
underlying instance variable could be a bitfield, but that is
a different matter. */
- error_at (location, "property cannot be a bit-field");
+ error_at (decl_loc, "property cannot be a bit-field");
return;
}
-#endif
+
+ /* The final results of parsing the (growing number) of property
+ attributes. */
+ property_attribute_info *attrs[OBJC_PROPATTR_GROUP_MAX] = { nullptr };
+
+ tree property_getter_ident = NULL_TREE;
+ tree property_setter_ident = NULL_TREE;
+ for (unsigned pn = 0; pn < prop_attr_list.length (); ++pn)
+ {
+ if (prop_attr_list[pn]->parse_error)
+ continue; /* Ignore attributes known to be wrongly parsed. */
+
+ switch (int g = (int) prop_attr_list[pn]->group())
+ {
+ case OBJC_PROPATTR_GROUP_UNKNOWN:
+ continue;
+ case OBJC_PROPATTR_GROUP_SETTER:
+ case OBJC_PROPATTR_GROUP_GETTER:
+ if (attrs[g])
+ {
+ warning_at (prop_attr_list[pn]->prop_loc, OPT_Wattributes,
+ "multiple property %qE methods specified, the latest"
+ " one will be used", attrs[g]->name);
+ inform (attrs[g]->prop_loc, "previous specification");
+ }
+ attrs[g] = prop_attr_list[pn];
+ if (g == OBJC_PROPATTR_GROUP_SETTER)
+ property_setter_ident = attrs[g]->ident;
+ else
+ property_getter_ident = attrs[g]->ident;
+ continue;
+ default:
+ {
+ if (!attrs[g])
+ ;
+ else if (attrs[g]->prop_kind != prop_attr_list[pn]->prop_kind)
+ {
+ error_at (prop_attr_list[pn]->prop_loc,
+ "%qE attribute conflicts with %qE attribute",
+ prop_attr_list[pn]->name, attrs[g]->name);
+ inform (attrs[g]->prop_loc, "%qE specified here",
+ attrs[g]->name );
+ }
+ else
+ {
+ warning_at (prop_attr_list[pn]->prop_loc, OPT_Wattributes,
+ "duplicate %qE attribute", attrs[g]->name);
+ inform (attrs[g]->prop_loc, "first specified here");
+ }
+ attrs[g] = prop_attr_list[pn];
+ }
+ continue;
+ }
+ }
+
+ /* The defaults for atomicity (atomic) and write-ability (readwrite) apply
+ even if the user provides no specified attributes. */
+ bool property_nonatomic = false;
+ bool property_readonly = false;
+
+ /* Set the values from any specified by the user; these are easy, only two
+ states. */
+ if (attrs[OBJC_PROPATTR_GROUP_ATOMIC])
+ property_nonatomic = attrs[OBJC_PROPATTR_GROUP_ATOMIC]->prop_kind
+ == OBJC_PROPERTY_ATTR_NONATOMIC;
+
+ if (attrs[OBJC_PROPATTR_GROUP_READWRITE])
+ property_readonly = attrs[OBJC_PROPATTR_GROUP_READWRITE]->prop_kind
+ == OBJC_PROPERTY_ATTR_READONLY;
+
+ /* One can't set a readonly value; we issue an error, but force the property
+ to readwrite as well. */
+ if (property_readonly && property_setter_ident)
+ {
+ error_at (attrs[OBJC_PROPATTR_GROUP_READWRITE]->prop_loc, "%<readonly%>"
+ " attribute conflicts with %<setter%> attribute");
+ gcc_checking_assert (attrs[OBJC_PROPATTR_GROUP_SETTER]);
+ inform (attrs[OBJC_PROPATTR_GROUP_SETTER]->prop_loc, "%<setter%>"
+ " specified here");
+ property_readonly = false;
+ }
+
+ /* Assign semantics is a tri-state property, and also needs some further
+ checking against the object type. */
+ objc_property_assign_semantics property_assign_semantics
+ = OBJC_PROPERTY_ASSIGN;
+
+ if (attrs[OBJC_PROPATTR_GROUP_ASSIGN])
+ {
+ if (attrs[OBJC_PROPATTR_GROUP_ASSIGN]->prop_kind
+ == OBJC_PROPERTY_ATTR_ASSIGN)
+ property_assign_semantics = OBJC_PROPERTY_ASSIGN;
+ else if (attrs[OBJC_PROPATTR_GROUP_ASSIGN]->prop_kind
+ == OBJC_PROPERTY_ATTR_RETAIN)
+ property_assign_semantics = OBJC_PROPERTY_RETAIN;
+ else if (attrs[OBJC_PROPATTR_GROUP_ASSIGN]->prop_kind
+ == OBJC_PROPERTY_ATTR_COPY)
+ property_assign_semantics = OBJC_PROPERTY_COPY;
+ else
+ gcc_unreachable ();
+ }
+
+ /* An attribute that indicates this property manipulates a class variable.
+ In this case, both the variable and the getter/setter must be provided
+ by the user. */
+ bool property_class = false;
+ if (attrs[OBJC_PROPATTR_GROUP_CLASS])
+ property_nonatomic = attrs[OBJC_PROPATTR_GROUP_CLASS]->prop_kind
+ == OBJC_PROPERTY_ATTR_CLASS;
/* TODO: Check that the property type is an Objective-C object or a
"POD". */
@@ -950,69 +1015,77 @@ objc_add_property_declaration (location_t location, tree decl,
for non-{Objective-C objects}, and to 'retain' for
Objective-C objects. But that would break compatibility with
other compilers. */
- if (!parsed_property_assign && !parsed_property_retain && !parsed_property_copy)
+ if (!attrs[OBJC_PROPATTR_GROUP_ASSIGN])
{
/* Use 'false' so we do not warn for Class objects. */
if (objc_type_valid_for_messaging (TREE_TYPE (decl), false))
{
- warning_at (location,
- 0,
- "object property %qD has no %<assign%>, %<retain%> or %<copy%> attribute; assuming %<assign%>",
- decl);
- inform (location,
- "%<assign%> can be unsafe for Objective-C objects; please state explicitly if you need it");
+ warning_at (decl_loc, 0, "object property %qD has no %<assign%>,"
+ " %<retain%> or %<copy%> attribute; assuming"
+ " %<assign%>", decl);
+ inform (decl_loc, "%<assign%> can be unsafe for Objective-C"
+ " objects; please state explicitly if you need it");
}
}
}
- if (property_assign_semantics == OBJC_PROPERTY_RETAIN
- && !objc_type_valid_for_messaging (TREE_TYPE (decl), true))
- error_at (location, "%<retain%> attribute is only valid for Objective-C objects");
+ /* Some attributes make no sense unless applied to an Objective-C object. */
+ bool prop_objc_object_p
+ = objc_type_valid_for_messaging (TREE_TYPE (decl), true);
+ if (!prop_objc_object_p)
+ {
+ tree p_name = NULL_TREE;
+ if (property_assign_semantics == OBJC_PROPERTY_RETAIN
+ || property_assign_semantics == OBJC_PROPERTY_COPY)
+ p_name = attrs[OBJC_PROPATTR_GROUP_ASSIGN]->name;
- if (property_assign_semantics == OBJC_PROPERTY_COPY
- && !objc_type_valid_for_messaging (TREE_TYPE (decl), true))
- error_at (location, "%<copy%> attribute is only valid for Objective-C objects");
+ if (p_name)
+ error_at (decl_loc, "%qE attribute is only valid for Objective-C"
+ " objects", p_name);
+ }
/* Now determine the final property getter and setter names. They
will be stored in the PROPERTY_DECL, from which they'll always be
extracted and used. */
/* Adjust, or fill in, setter and getter names. We overwrite the
- parsed_property_setter_ident and parsed_property_getter_ident
+ property_setter_ident and property_getter_ident
with the final setter and getter identifiers that will be
used. */
- if (parsed_property_setter_ident)
+ if (property_setter_ident)
{
/* The setter should be terminated by ':', but the parser only
gives us an identifier without ':'. So, we need to add ':'
at the end. */
- const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
+ const char *parsed_setter = IDENTIFIER_POINTER (property_setter_ident);
size_t length = strlen (parsed_setter);
char *final_setter = (char *)alloca (length + 2);
sprintf (final_setter, "%s:", parsed_setter);
- parsed_property_setter_ident = get_identifier (final_setter);
+ property_setter_ident = get_identifier (final_setter);
}
else
{
if (!property_readonly)
- parsed_property_setter_ident = get_identifier (objc_build_property_setter_name
+ property_setter_ident = get_identifier (objc_build_property_setter_name
(DECL_NAME (decl)));
}
- if (!parsed_property_getter_ident)
- parsed_property_getter_ident = DECL_NAME (decl);
+ if (!property_getter_ident)
+ property_getter_ident = DECL_NAME (decl);
/* Check for duplicate property declarations. We first check the
immediate context for a property with the same name. Any such
declarations are an error, unless this is a class extension and
we are extending a property from readonly to readwrite. */
+ bool property_extension_in_class_extension = false;
+ tree x = NULL_TREE;
for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
{
if (PROPERTY_NAME (x) == DECL_NAME (decl))
{
if (objc_in_class_extension
- && property_readonly == 0
+ && !property_readonly
&& PROPERTY_READONLY (x) == 1)
{
/* This is a class extension, and we are extending an
@@ -1087,7 +1160,7 @@ objc_add_property_declaration (location_t location, tree decl,
types, or it is compatible. */
location_t original_location = DECL_SOURCE_LOCATION (x);
- if (PROPERTY_NONATOMIC (x) != parsed_property_nonatomic)
+ if (PROPERTY_NONATOMIC (x) != property_nonatomic)
{
warning_at (location, 0,
"%<nonatomic%> attribute of property %qD conflicts with "
@@ -1098,7 +1171,7 @@ objc_add_property_declaration (location_t location, tree decl,
return;
}
- if (PROPERTY_GETTER_NAME (x) != parsed_property_getter_ident)
+ if (PROPERTY_GETTER_NAME (x) != property_getter_ident)
{
warning_at (location, 0,
"%<getter%> attribute of property %qD conflicts with "
@@ -1112,7 +1185,7 @@ objc_add_property_declaration (location_t location, tree decl,
/* We can only compare the setter names if both the old and new property have a setter. */
if (!property_readonly && !PROPERTY_READONLY(x))
{
- if (PROPERTY_SETTER_NAME (x) != parsed_property_setter_ident)
+ if (PROPERTY_SETTER_NAME (x) != property_setter_ident)
{
warning_at (location, 0,
"%<setter%> attribute of property %qD conflicts with "
@@ -1190,13 +1263,13 @@ objc_add_property_declaration (location_t location, tree decl,
if (property_extension_in_class_extension)
{
PROPERTY_READONLY (x) = 0;
- PROPERTY_SETTER_NAME (x) = parsed_property_setter_ident;
+ PROPERTY_SETTER_NAME (x) = property_setter_ident;
return;
}
}
/* Create a PROPERTY_DECL node. */
- property_decl = make_node (PROPERTY_DECL);
+ tree property_decl = make_node (PROPERTY_DECL);
/* Copy the basic information from the original decl. */
TREE_TYPE (property_decl) = TREE_TYPE (decl);
@@ -1205,10 +1278,11 @@ objc_add_property_declaration (location_t location, tree decl,
/* Add property-specific information. */
PROPERTY_NAME (property_decl) = DECL_NAME (decl);
- PROPERTY_GETTER_NAME (property_decl) = parsed_property_getter_ident;
- PROPERTY_SETTER_NAME (property_decl) = parsed_property_setter_ident;
+ PROPERTY_GETTER_NAME (property_decl) = property_getter_ident;
+ PROPERTY_SETTER_NAME (property_decl) = property_setter_ident;
PROPERTY_READONLY (property_decl) = property_readonly;
- PROPERTY_NONATOMIC (property_decl) = parsed_property_nonatomic;
+ PROPERTY_NONATOMIC (property_decl) = property_nonatomic;
+ PROPERTY_CLASS (property_decl) = property_class;
PROPERTY_ASSIGN_SEMANTICS (property_decl) = property_assign_semantics;
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
PROPERTY_DYNAMIC (property_decl) = 0;
@@ -1720,7 +1794,6 @@ objc_build_class_component_ref (tree class_name, tree property_ident)
}
-
/* This is used because we don't want to expose PROPERTY_REF to the
C/C++ frontends. Maybe we should! */
bool
@@ -1732,6 +1805,21 @@ objc_is_property_ref (tree node)
return false;
}
+/* We use this to report tree codes that are known to be invalid in const-
+ expression contexts. */
+bool
+objc_non_constant_expr_p (tree node)
+{
+ switch (TREE_CODE (node))
+ {
+ default:
+ return false;
+ case MESSAGE_SEND_EXPR:
+ case PROPERTY_REF:
+ return true;
+ }
+}
+
/* This function builds a setter call for a PROPERTY_REF (real, for a
declared property, or artificial, for a dot-syntax accessor which
is not corresponding to a property). 'lhs' must be a PROPERTY_REF
@@ -2399,9 +2487,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));
@@ -2446,17 +2539,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
@@ -2490,12 +2589,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
{
@@ -2503,7 +2605,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;
}
@@ -2954,6 +3056,7 @@ synth_module_prologue (void)
objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
objc_instancetype_name = get_identifier (INSTANCE_TYPEDEF_NAME);
objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
+ objc_selector_name = get_identifier (SEL_TYPEDEF_NAME);
/* Declare the 'id', 'instancetype' and 'Class' typedefs. */
type = lang_hooks.decls.pushdecl (build_decl (input_location,
@@ -6935,12 +7038,14 @@ start_class (enum tree_code code, tree class_name, tree super_name,
tree name = TREE_PURPOSE (attribute);
/* TODO: Document what the objc_exception attribute is/does. */
- /* We handle the 'deprecated' and (undocumented) 'objc_exception'
- attributes. */
+ /* We handle the 'deprecated', 'visibility' and (undocumented)
+ 'objc_exception' attributes. */
if (is_attribute_p ("deprecated", name))
TREE_DEPRECATED (klass) = 1;
else if (is_attribute_p ("objc_exception", name))
CLASS_HAS_EXCEPTION_ATTR (klass) = 1;
+ else if (is_attribute_p ("visibility", name))
+ ;
else
/* Warn about and ignore all others for now, but store them. */
warning (OPT_Wattributes, "%qE attribute directive ignored", name);
@@ -8579,11 +8684,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;
@@ -8596,6 +8709,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;
}
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 913e152..5b0433f 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -137,6 +137,10 @@ enum objc_property_assign_semantics {
#define PROPERTY_OPTIONAL(DECL) \
DECL_LANG_FLAG_5 (PROPERTY_DECL_CHECK (DECL))
+/* PROPERTY_CLASS can be 0 or 1. */
+#define PROPERTY_CLASS(DECL) \
+ DECL_LANG_FLAG_6 (PROPERTY_DECL_CHECK (DECL))
+
/* PROPERTY_REF. A PROPERTY_REF represents an 'object.property'
expression. It is normally used for property access, but when
the Objective-C 2.0 "dot-syntax" (object.component) is used
@@ -371,6 +375,7 @@ enum objc_tree_index
OCTI_ID_NAME,
OCTI_INSTANCETYPE_NAME,
OCTI_CLASS_NAME,
+ OCTI_SEL_NAME,
OCTI_CNST_STR_ID,
OCTI_CNST_STR_TYPE,
OCTI_CNST_STR_GLOB_ID,
@@ -576,6 +581,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define objc_object_name objc_global_trees[OCTI_ID_NAME]
#define objc_instancetype_name objc_global_trees[OCTI_INSTANCETYPE_NAME]
#define objc_class_name objc_global_trees[OCTI_CLASS_NAME]
+#define objc_selector_name objc_global_trees[OCTI_SEL_NAME]
/* Constant string classes. */
#define constant_string_id objc_global_trees[OCTI_CNST_STR_ID]
@@ -614,6 +620,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define OBJECT_TYPEDEF_NAME "id"
#define INSTANCE_TYPEDEF_NAME "instancetype"
#define CLASS_TYPEDEF_NAME "Class"
+#define SEL_TYPEDEF_NAME "SEL"
#define TAG_OBJECT "objc_object"
#define TAG_CLASS "objc_class"
diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c
index 25c0e01..ac9a862 100644
--- a/gcc/objc/objc-gnu-runtime-abi-01.c
+++ b/gcc/objc/objc-gnu-runtime-abi-01.c
@@ -208,6 +208,13 @@ static void gnu_runtime_01_initialize (void)
type = build_qualified_type (type, TYPE_QUAL_CONST);
objc_selector_type = build_pointer_type (type);
+ /* SEL typedef. */
+ type = lang_hooks.decls.pushdecl (build_decl (input_location,
+ TYPE_DECL,
+ objc_selector_name,
+ objc_selector_type));
+ TREE_NO_WARNING (type) = 1;
+
/* typedef id (*IMP)(id, SEL, ...); */
ftype = build_varargs_function_type_list (objc_object_type,
objc_object_type,
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 233d89e..7fc449b 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -277,6 +277,13 @@ static void next_runtime_01_initialize (void)
objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
get_identifier (TAG_SELECTOR)));
+ /* SEL typedef. */
+ type = lang_hooks.decls.pushdecl (build_decl (input_location,
+ TYPE_DECL,
+ objc_selector_name,
+ objc_selector_type));
+ TREE_NO_WARNING (type) = 1;
+
build_v1_class_template ();
build_super_template ();
build_v1_protocol_template ();
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index d7812ff..f3c285a 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -374,6 +374,13 @@ static void next_runtime_02_initialize (void)
objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
get_identifier (TAG_SELECTOR)));
+ /* SEL typedef. */
+ type = lang_hooks.decls.pushdecl (build_decl (input_location,
+ TYPE_DECL,
+ objc_selector_name,
+ objc_selector_type));
+ TREE_NO_WARNING (type) = 1;
+
/* IMP : id (*) (id, _message_ref_t*, ...)
SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
objc_v2_selector_type. */