Commit d11dd684 by Ziemowit Laski Committed by Mike Stump

objc-act.c (objc_build_struct): New function.

        * objc-act.c (objc_build_struct): New function.
        (objc_derived_from_p): Likewise.
        (objc_build_component_ref): Likewise.
        (objc_copy_binfo): Likewise.
        (objc_xref_basetypes): Likewise.
        (objc_lookup_protocol): Likewise.
        (objc_compare_protocols): Likewise.
        (objc_volatilize_decl): Likewise.
        (encode_aggregate_fields): Likewise.
        (volatilized_hash): Likewise.
        (volatilized_eq): Likewise.
        (objc_compare_types): Likewise.
        (objc_type_quals_match): Likewise.
        (DERIVED_FROM_P): New ObjC macro, corresponding to C++ macro
        of same name.
        (get_class_ivars): Add second parameter indicating if entire
        hierarchy is desired.
        (struct volatilized_type): New type.
        (volatilized_htab): New hash table.
        (objc_types_compatible_p, objc_comptypes): Remove functions.
        (synth_module_prologue): Do not initialize 'unused_list'.
        (objc_get_class_reference): Fix ObjC++ impedance mismatches.
        (objc_declare_alias): Implement as a typedef.
        (objc_substitute_decl, objc_gimplify_expr): Reformat.
        (objc_get_class_ivars): Adjust call to get_class_ivars().
        (next_sjlj_build_enter_and_setjmp, synth_forward_declarations,
        build_ivar_reference, get_super_receiver): Call
        objc_build_component_ref() instead of build_component_ref().
        (objc_begin_catch_clause): Use DERIVED_FROM_P() instead of
        objc_comptypes().
        (build_private_template): Call objc_build_struct() instead of
        start_struct() and finish_struct().
        (hash_init): Initialize volatilized_htab.
        (objc_is_public): Adjust calls to objc_get_ivars(); adjust
        ObjC++ impedance mismatches.
        (encode_aggregate_within): Streamline by calling
        encode_aggregate_fields().
        * objc-act.h (objc_types_compatible_p): Remove prototype.
        (OCTI_UNUSED_LIST, unused_list): Remove slot.
        * objc-lang.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Remove.

From-SVN: r100123
parent 18d311d8
2005-05-24 Ziemowit Laski <zlaski@apple.com>
* objc-act.c (objc_build_struct): New function.
(objc_derived_from_p): Likewise.
(objc_build_component_ref): Likewise.
(objc_copy_binfo): Likewise.
(objc_xref_basetypes): Likewise.
(objc_lookup_protocol): Likewise.
(objc_compare_protocols): Likewise.
(objc_volatilize_decl): Likewise.
(encode_aggregate_fields): Likewise.
(volatilized_hash): Likewise.
(volatilized_eq): Likewise.
(objc_compare_types): Likewise.
(objc_type_quals_match): Likewise.
(DERIVED_FROM_P): New ObjC macro, corresponding to C++ macro
of same name.
(get_class_ivars): Add second parameter indicating if entire
hierarchy is desired.
(struct volatilized_type): New type.
(volatilized_htab): New hash table.
(objc_types_compatible_p, objc_comptypes): Remove functions.
(synth_module_prologue): Do not initialize 'unused_list'.
(objc_get_class_reference): Fix ObjC++ impedance mismatches.
(objc_declare_alias): Implement as a typedef.
(objc_substitute_decl, objc_gimplify_expr): Reformat.
(objc_get_class_ivars): Adjust call to get_class_ivars().
(next_sjlj_build_enter_and_setjmp, synth_forward_declarations,
build_ivar_reference, get_super_receiver): Call
objc_build_component_ref() instead of build_component_ref().
(objc_begin_catch_clause): Use DERIVED_FROM_P() instead of
objc_comptypes().
(build_private_template): Call objc_build_struct() instead of
start_struct() and finish_struct().
(hash_init): Initialize volatilized_htab.
(objc_is_public): Adjust calls to objc_get_ivars(); adjust
ObjC++ impedance mismatches.
(encode_aggregate_within): Streamline by calling
encode_aggregate_fields().
* objc-act.h (objc_types_compatible_p): Remove prototype.
(OCTI_UNUSED_LIST, unused_list): Remove slot.
* objc-lang.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Remove.
2005-05-18 Geoffrey Keating <geoffk@apple.com> 2005-05-18 Geoffrey Keating <geoffk@apple.com>
* Make-lang.in (cc1obj-dummy): New. * Make-lang.in (cc1obj-dummy): New.
......
...@@ -169,12 +169,20 @@ static tree is_ivar (tree, tree); ...@@ -169,12 +169,20 @@ static tree is_ivar (tree, tree);
static void build_objc_exception_stuff (void); static void build_objc_exception_stuff (void);
static void build_next_objc_exception_stuff (void); static void build_next_objc_exception_stuff (void);
/* We only need the following for ObjC; ObjC++ will use C++'s definition
of DERIVED_FROM_P. */
#ifndef OBJCPLUS
static bool objc_derived_from_p (tree, tree);
#define DERIVED_FROM_P(PARENT, CHILD) objc_derived_from_p (PARENT, CHILD)
#endif
static void objc_xref_basetypes (tree, tree);
static void build_class_template (void); static void build_class_template (void);
static void build_selector_template (void); static void build_selector_template (void);
static void build_category_template (void); static void build_category_template (void);
static void build_super_template (void); static void build_super_template (void);
static tree build_protocol_initializer (tree, tree, tree, tree, tree); static tree build_protocol_initializer (tree, tree, tree, tree, tree);
static tree get_class_ivars (tree); static tree get_class_ivars (tree, bool);
static tree generate_protocol_list (tree); static tree generate_protocol_list (tree);
static void build_protocol_reference (tree); static void build_protocol_reference (tree);
...@@ -388,6 +396,14 @@ struct string_descriptor GTY(()) ...@@ -388,6 +396,14 @@ struct string_descriptor GTY(())
static GTY((param_is (struct string_descriptor))) htab_t string_htab; static GTY((param_is (struct string_descriptor))) htab_t string_htab;
/* Store the EH-volatilized types in a hash table, for easy retrieval. */
struct volatilized_type GTY(())
{
tree type;
};
static GTY((param_is (struct volatilized_type))) htab_t volatilized_htab;
FILE *gen_declaration_file; FILE *gen_declaration_file;
/* Tells "encode_pointer/encode_aggregate" whether we are generating /* Tells "encode_pointer/encode_aggregate" whether we are generating
...@@ -777,351 +793,470 @@ objc_is_class_id (tree type) ...@@ -777,351 +793,470 @@ objc_is_class_id (tree type)
return OBJC_TYPE_NAME (type) == objc_class_id; return OBJC_TYPE_NAME (type) == objc_class_id;
} }
/* Construct a C struct with tag NAME, a base struct with tag
SUPER_NAME (if any), and FIELDS indicated. */
int static tree
objc_types_compatible_p (tree type1, tree type2) objc_build_struct (tree name, tree fields, tree super_name)
{
tree s = start_struct (RECORD_TYPE, name);
tree super = (super_name ? xref_tag (RECORD_TYPE, super_name) : NULL_TREE);
if (super)
{
/* Prepend a packed variant of the base class into the layout. This
is necessary to preserve ObjC ABI compatibility. */
tree base = build_decl (FIELD_DECL, NULL_TREE, super);
tree field = TYPE_FIELDS (super);
while (field && TREE_CHAIN (field)
&& TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
field = TREE_CHAIN (field);
/* For ObjC ABI purposes, the "packed" size of a base class is
the the sum of the offset and the size (in bits) of the last
field in the class. */
DECL_SIZE (base)
= (field && TREE_CODE (field) == FIELD_DECL
? size_binop (PLUS_EXPR,
size_binop (PLUS_EXPR,
size_binop
(MULT_EXPR,
convert (bitsizetype,
DECL_FIELD_OFFSET (field)),
bitsize_int (BITS_PER_UNIT)),
DECL_FIELD_BIT_OFFSET (field)),
DECL_SIZE (field))
: bitsize_zero_node);
DECL_SIZE_UNIT (base)
= size_binop (FLOOR_DIV_EXPR, convert (sizetype, DECL_SIZE (base)),
size_int (BITS_PER_UNIT));
DECL_ARTIFICIAL (base) = 1;
DECL_ALIGN (base) = 1;
DECL_FIELD_CONTEXT (base) = s;
#ifdef OBJCPLUS
DECL_FIELD_IS_BASE (base) = 1;
if (fields)
TREE_NO_WARNING (fields) = 1; /* Suppress C++ ABI warnings -- we */
#endif /* are following the ObjC ABI here. */
TREE_CHAIN (base) = fields;
fields = base;
}
s = finish_struct (s, fields, NULL_TREE);
/* Use TYPE_BINFO structures to point at the super class, if any. */
objc_xref_basetypes (s, super);
return s;
}
/* Mark DECL as being 'volatile' for purposes of Darwin
_setjmp()/_longjmp() exception handling. Called from
objc_mark_locals_volatile(). */
void
objc_volatilize_decl (tree decl)
{
/* Do not mess with variables that are 'static' or (already)
'volatile'. */
if (!TREE_THIS_VOLATILE (decl) && !TREE_STATIC (decl)
&& (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == PARM_DECL))
{
tree t = TREE_TYPE (decl);
struct volatilized_type key;
void **loc;
t = build_qualified_type (t, (TYPE_QUALS (t)
| TYPE_QUAL_VOLATILE));
key.type = t;
loc = htab_find_slot (volatilized_htab, &key, INSERT);
if (!*loc)
{
*loc = ggc_alloc (sizeof (key));
((struct volatilized_type *) *loc)->type = t;
}
TREE_TYPE (decl) = t;
TREE_THIS_VOLATILE (decl) = 1;
TREE_SIDE_EFFECTS (decl) = 1;
DECL_REGISTER (decl) = 0;
#ifndef OBJCPLUS
C_DECL_REGISTER (decl) = 0;
#endif
}
}
/* Check if protocol PROTO is adopted (directly or indirectly) by class CLS
(including its categoreis and superclasses) or by object type TYP.
Issue a warning if PROTO is not adopted anywhere and WARN is set. */
static bool
objc_lookup_protocol (tree proto, tree cls, tree typ, bool warn)
{ {
bool class_type = (cls != NULL_TREE);
if (objc_is_object_ptr (type1) || objc_is_object_ptr (type2) while (cls)
|| objc_is_class_name (type1) || objc_is_class_name (type2))
{ {
return lhd_types_compatible_p (type1, type2); tree c;
/* Check protocols adopted by the class and its categories. */
for (c = cls; c; c = CLASS_CATEGORY_LIST (c))
{
if (lookup_protocol_in_reflist (CLASS_PROTOCOL_LIST (c), proto))
return true;
}
/* Repeat for superclasses. */
cls = lookup_interface (CLASS_SUPER_NAME (cls));
} }
else
/* Check for any protocols attached directly to the object type. */
if (TYPE_HAS_OBJC_INFO (typ))
{ {
#ifdef OBJCPLUS if (lookup_protocol_in_reflist (TYPE_OBJC_PROTOCOL_LIST (typ), proto))
return cxx_types_compatible_p (type1, type2); return true;
#else }
return c_types_compatible_p (type1, type2);
#endif if (warn)
{
strcpy (errbuf, class_type ? "class \'" : "type \'");
gen_type_name_0 (class_type ? typ : TYPE_POINTER_TO (typ));
strcat (errbuf, "\' does not ");
/* NB: Types 'id' and 'Class' cannot reasonably be described as
"implementing" a given protocol, since they do not have an
implementation. */
strcat (errbuf, class_type ? "implement" : "conform to");
strcat (errbuf, " the \'");
strcat (errbuf, IDENTIFIER_POINTER (PROTOCOL_NAME (proto)));
strcat (errbuf, "\' protocol");
warning (0, errbuf);
} }
return false;
} }
/* Check if class RCLS and instance struct type RTYP conform to at least the
same protocols that LCLS and LTYP conform to. */
static bool
objc_compare_protocols (tree lcls, tree ltyp, tree rcls, tree rtyp, bool warn)
{
tree p;
bool have_lproto = false;
while (lcls)
{
/* NB: We do _not_ look at categories defined for LCLS; these may or
may not get loaded in, and therefore it is unreasonable to require
that RCLS/RTYP must implement any of their protocols. */
for (p = CLASS_PROTOCOL_LIST (lcls); p; p = TREE_CHAIN (p))
{
have_lproto = true;
/* Return 1 if LHS and RHS are compatible types for assignment or if (!objc_lookup_protocol (TREE_VALUE (p), rcls, rtyp, warn))
various other operations. Return 0 if they are incompatible, and return warn;
return -1 if we choose to not decide (because the types are really }
just C types, not ObjC specific ones). When the operation is
REFLEXIVE (typically comparisons), check for compatibility in
either direction; when it's not (typically assignments), don't.
This function is called in two cases: when both lhs and rhs are /* Repeat for superclasses. */
pointers to records (in which case we check protocols too), and lcls = lookup_interface (CLASS_SUPER_NAME (lcls));
when both lhs and rhs are records (in which case we check class }
inheritance only).
Warnings about classes/protocols not implementing a protocol are /* Check for any protocols attached directly to the object type. */
emitted here (multiple of those warnings might be emitted for a if (TYPE_HAS_OBJC_INFO (ltyp))
single line!); generic warnings about incompatible assignments and {
lacks of casts in comparisons are/must be emitted by the caller if for (p = TYPE_OBJC_PROTOCOL_LIST (ltyp); p; p = TREE_CHAIN (p))
we return 0. {
*/ have_lproto = true;
int if (!objc_lookup_protocol (TREE_VALUE (p), rcls, rtyp, warn))
objc_comptypes (tree lhs, tree rhs, int reflexive) return warn;
}
}
/* NB: If LTYP and LCLS have no protocols to search for, return 'true'
vacuously, _unless_ RTYP is a protocol-qualified 'id'. We can get
away with simply checking for 'id' or 'Class' (!RCLS), since this
routine will not get called in other cases. */
return have_lproto || (rcls != NULL_TREE);
}
/* Determine if it is permissible to assign (if ARGNO is greater than -3)
an instance of RTYP to an instance of LTYP or to compare the two
(if ARGNO is equal to -3), per ObjC type system rules. Before
returning 'true', this routine may issue warnings related to, e.g.,
protocol conformance. When returning 'false', the routine must
produce absolutely no warnings; the C or C++ front-end will do so
instead, if needed. If either LTYP or RTYP is not an Objective-C type,
the routine must return 'false'.
The ARGNO parameter is encoded as follows:
>= 1 Parameter number (CALLEE contains function being called);
0 Return value;
-1 Assignment;
-2 Initialization;
-3 Comparison (LTYP and RTYP may match in either direction). */
bool
objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
{ {
/* New clause for protocols. */ tree lcls, rcls, lproto, rproto;
bool pointers_compatible;
/* We must be dealing with pointer types */
if (!POINTER_TYPE_P (ltyp) || !POINTER_TYPE_P (rtyp))
return false;
/* Here we manage the case of a POINTER_TYPE = POINTER_TYPE. We only do
manage the ObjC ones, and leave the rest to the C code. */
if (TREE_CODE (lhs) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
&& TREE_CODE (rhs) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
{ {
int lhs_is_proto = IS_PROTOCOL_QUALIFIED_UNTYPED (lhs); ltyp = TREE_TYPE (ltyp); /* Remove indirections. */
int rhs_is_proto = IS_PROTOCOL_QUALIFIED_UNTYPED (rhs); rtyp = TREE_TYPE (rtyp);
}
while (POINTER_TYPE_P (ltyp) && POINTER_TYPE_P (rtyp));
if (lhs_is_proto) /* Past this point, we are only interested in ObjC class instances,
{ or 'id' or 'Class'. */
tree lproto, lproto_list = TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (lhs)); if (TREE_CODE (ltyp) != RECORD_TYPE || TREE_CODE (rtyp) != RECORD_TYPE)
tree rproto, rproto_list; return false;
tree p;
/* <Protocol> = <Protocol> */ if (!objc_is_object_id (ltyp) && !objc_is_class_id (ltyp)
if (rhs_is_proto) && !TYPE_HAS_OBJC_INFO (ltyp))
{ return false;
/* Class <Protocol> != id <Protocol>;
id <Protocol> != Class <Protocol> */
if (IS_ID (lhs) != IS_ID (rhs))
return 0;
rproto_list = TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rhs)); if (!objc_is_object_id (rtyp) && !objc_is_class_id (rtyp)
&& !TYPE_HAS_OBJC_INFO (rtyp))
return false;
if (!reflexive) /* Past this point, we are committed to returning 'true' to the caller.
{ However, we can still warn about type and/or protocol mismatches. */
/* An assignment between objects of type 'id
<Protocol>'; make sure the protocol on the lhs is
supported by the object on the rhs. */
for (lproto = lproto_list; lproto;
lproto = TREE_CHAIN (lproto))
{
p = TREE_VALUE (lproto);
rproto = lookup_protocol_in_reflist (rproto_list, p);
if (!rproto) if (TYPE_HAS_OBJC_INFO (ltyp))
warning {
(0, "object does not conform to the %qs protocol", lcls = TYPE_OBJC_INTERFACE (ltyp);
IDENTIFIER_POINTER (PROTOCOL_NAME (p))); lproto = TYPE_OBJC_PROTOCOL_LIST (ltyp);
} }
return 1; else
} lcls = lproto = NULL_TREE;
else
{
/* Obscure case - a comparison between two objects
of type 'id <Protocol>'. Check that either the
protocol on the lhs is supported by the object on
the rhs, or viceversa. */
/* Check if the protocol on the lhs is supported by the
object on the rhs. */
for (lproto = lproto_list; lproto;
lproto = TREE_CHAIN (lproto))
{
p = TREE_VALUE (lproto);
rproto = lookup_protocol_in_reflist (rproto_list, p);
if (!rproto)
{
/* Check failed - check if the protocol on the rhs
is supported by the object on the lhs. */
for (rproto = rproto_list; rproto;
rproto = TREE_CHAIN (rproto))
{
p = TREE_VALUE (rproto);
lproto = lookup_protocol_in_reflist (lproto_list,
p);
if (!lproto)
{
/* This check failed too: incompatible */
return 0;
}
}
return 1;
}
}
return 1;
}
}
/* <Protocol> = <class> * */
else if (TYPED_OBJECT (TREE_TYPE (rhs)))
{
tree rname = OBJC_TYPE_NAME (TREE_TYPE (rhs));
tree rinter;
/* Class <Protocol> != <class> * */ if (TYPE_HAS_OBJC_INFO (rtyp))
if (IS_CLASS (lhs)) {
return 0; rcls = TYPE_OBJC_INTERFACE (rtyp);
rproto = TYPE_OBJC_PROTOCOL_LIST (rtyp);
}
else
rcls = rproto = NULL_TREE;
/* Make sure the protocol is supported by the object on /* If either type is an unqualified 'id', we're done. */
the rhs. */ if ((!lproto && objc_is_object_id (ltyp))
for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto)) || (!rproto && objc_is_object_id (rtyp)))
{ return true;
p = TREE_VALUE (lproto);
rproto = 0;
rinter = lookup_interface (rname);
while (rinter && !rproto) pointers_compatible = (TYPE_MAIN_VARIANT (ltyp) == TYPE_MAIN_VARIANT (rtyp));
{
tree cat;
rproto_list = CLASS_PROTOCOL_LIST (rinter);
rproto = lookup_protocol_in_reflist (rproto_list, p);
/* If the underlying ObjC class does not have
the protocol we're looking for, check for "one-off"
protocols (e.g., `NSObject<MyProt> *foo;') attached
to the rhs. */
if (!rproto && TYPE_HAS_OBJC_INFO (TREE_TYPE (rhs)))
{
rproto_list = TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rhs));
rproto = lookup_protocol_in_reflist (rproto_list, p);
}
/* Check for protocols adopted by categories. */
cat = CLASS_CATEGORY_LIST (rinter);
while (cat && !rproto)
{
rproto_list = CLASS_PROTOCOL_LIST (cat);
rproto = lookup_protocol_in_reflist (rproto_list, p);
cat = CLASS_CATEGORY_LIST (cat);
}
rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
}
if (!rproto) /* If the underlying types are the same, and at most one of them has
warning (0, "class %qs does not implement the %qs protocol", a protocol list, we do not need to issue any diagnostics. */
IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_TYPE (rhs))), if (pointers_compatible && (!lproto || !rproto))
IDENTIFIER_POINTER (PROTOCOL_NAME (p))); return true;
}
return 1;
}
/* id <Protocol> = id; Class <Protocol> = id */
else if (objc_is_object_id (TREE_TYPE (rhs)))
{
return 1;
}
/* id <Protocol> != Class; Class <Protocol> = Class */
else if (objc_is_class_id (TREE_TYPE (rhs)))
{
return IS_CLASS (lhs);
}
/* <Protocol> = ?? : let comptypes decide. */
return -1;
}
else if (rhs_is_proto)
{
/* <class> * = <Protocol> */
if (TYPED_OBJECT (TREE_TYPE (lhs)))
{
/* <class> * != Class <Protocol> */
if (IS_CLASS (rhs))
return 0;
if (reflexive) /* If exactly one of the types is 'Class', issue a diagnostic; any
{ exceptions of this rule have already been handled. */
tree rname = OBJC_TYPE_NAME (TREE_TYPE (lhs)); if (objc_is_class_id (ltyp) ^ objc_is_class_id (rtyp))
tree rinter; pointers_compatible = false;
tree rproto, rproto_list = TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rhs)); /* Otherwise, check for inheritance relations. */
else
/* Make sure the protocol is supported by the object on {
the lhs. */ if (!pointers_compatible)
for (rproto = rproto_list; rproto; pointers_compatible
rproto = TREE_CHAIN (rproto)) = (objc_is_object_id (ltyp) || objc_is_object_id (rtyp));
{
tree p = TREE_VALUE (rproto); if (!pointers_compatible)
tree lproto = 0; pointers_compatible = DERIVED_FROM_P (ltyp, rtyp);
rinter = lookup_interface (rname);
if (!pointers_compatible && argno == -3)
while (rinter && !lproto) pointers_compatible = DERIVED_FROM_P (rtyp, ltyp);
{ }
tree cat;
/* If the pointers match modulo protocols, check for protocol conformance
tree lproto_list = CLASS_PROTOCOL_LIST (rinter); mismatches. */
lproto = lookup_protocol_in_reflist (lproto_list, p); if (pointers_compatible)
/* If the underlying ObjC class does not {
have the protocol we're looking for, pointers_compatible = objc_compare_protocols (lcls, ltyp, rcls, rtyp,
check for "one-off" protocols (e.g., argno != -3);
`NSObject<MyProt> *foo;') attached to the
lhs. */ if (!pointers_compatible && argno == -3)
if (!lproto && TYPE_HAS_OBJC_INFO (TREE_TYPE (lhs))) pointers_compatible = objc_compare_protocols (rcls, rtyp, lcls, ltyp,
{ argno != -3);
lproto_list = TYPE_OBJC_PROTOCOL_LIST }
(TREE_TYPE (lhs));
lproto = lookup_protocol_in_reflist if (!pointers_compatible)
(lproto_list, p); {
} /* NB: For the time being, we shall make our warnings look like their
C counterparts. In the future, we may wish to make them more
/* Check for protocols adopted by categories. */ ObjC-specific. */
cat = CLASS_CATEGORY_LIST (rinter); switch (argno)
while (cat && !lproto)
{
lproto_list = CLASS_PROTOCOL_LIST (cat);
lproto = lookup_protocol_in_reflist (lproto_list,
p);
cat = CLASS_CATEGORY_LIST (cat);
}
rinter = lookup_interface (CLASS_SUPER_NAME
(rinter));
}
if (!lproto)
warning (0, "class %qs does not implement the %qs protocol",
IDENTIFIER_POINTER (OBJC_TYPE_NAME
(TREE_TYPE (lhs))),
IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
}
return 1;
}
else
return 0;
}
/* id = id <Protocol>; id = Class <Protocol> */
else if (objc_is_object_id (TREE_TYPE (lhs)))
{
return 1;
}
/* Class != id <Protocol>; Class = Class <Protocol> */
else if (objc_is_class_id (TREE_TYPE (lhs)))
{
return IS_CLASS (rhs);
}
/* ??? = <Protocol> : let comptypes decide */
else
{
return -1;
}
}
else
{ {
/* Attention: we shouldn't defer to comptypes here. One bad case -3:
side effect would be that we might loose the REFLEXIVE warning (0, "comparison of distinct Objective-C types lacks a cast");
information. break;
*/
lhs = TREE_TYPE (lhs); case -2:
rhs = TREE_TYPE (rhs); warning (0, "initialization from distinct Objective-C type");
break;
case -1:
warning (0, "assignment from distinct Objective-C type");
break;
case 0:
warning (0, "distinct Objective-C type in return");
break;
default:
warning (0, "passing argument %d of %qE from distinct "
"Objective-C type", argno, callee);
break;
} }
} }
if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE) return true;
}
/* Check if LTYP and RTYP have the same type qualifiers. If either type
lives in the volatilized hash table, ignore the 'volatile' bit when
making the comparison. */
bool
objc_type_quals_match (tree ltyp, tree rtyp)
{
int lquals = TYPE_QUALS (ltyp), rquals = TYPE_QUALS (rtyp);
struct volatilized_type key;
key.type = ltyp;
if (htab_find_slot (volatilized_htab, &key, NO_INSERT))
lquals &= ~TYPE_QUAL_VOLATILE;
key.type = rtyp;
if (htab_find_slot (volatilized_htab, &key, NO_INSERT))
rquals &= ~TYPE_QUAL_VOLATILE;
return (lquals == rquals);
}
#ifndef OBJCPLUS
/* Determine if CHILD is derived from PARENT. The routine assumes that
both parameters are RECORD_TYPEs, and is non-reflexive. */
static bool
objc_derived_from_p (tree parent, tree child)
{
parent = TYPE_MAIN_VARIANT (parent);
for (child = TYPE_MAIN_VARIANT (child);
TYPE_BINFO (child) && BINFO_N_BASE_BINFOS (TYPE_BINFO (child));)
{ {
/* Nothing to do with ObjC - let immediately comptypes take child = TYPE_MAIN_VARIANT (BINFO_TYPE (BINFO_BASE_BINFO
responsibility for checking. */ (TYPE_BINFO (child),
return -1; 0)));
if (child == parent)
return true;
} }
/* `id' = `<class> *' `<class> *' = `id': always allow it. return false;
Please note that }
'Object *o = [[Object alloc] init]; falls #endif
in the case <class> * = `id'.
*/ static tree
if ((objc_is_object_id (lhs) && TYPED_OBJECT (rhs)) objc_build_component_ref (tree datum, tree component)
|| (objc_is_object_id (rhs) && TYPED_OBJECT (lhs))) {
return 1; /* If COMPONENT is NULL, the caller is referring to the anonymous
base class field. */
if (!component)
{
tree base = TYPE_FIELDS (TREE_TYPE (datum));
/* `id' = `Class', `Class' = `id' */ return build3 (COMPONENT_REF, TREE_TYPE (base), datum, base, NULL_TREE);
}
else if ((objc_is_object_id (lhs) && objc_is_class_id (rhs)) /* The 'build_component_ref' routine has been removed from the C++
|| (objc_is_class_id (lhs) && objc_is_object_id (rhs))) front-end, but 'finish_class_member_access_expr' seems to be
return 1; a worthy substitute. */
#ifdef OBJCPLUS
return finish_class_member_access_expr (datum, component);
#else
return build_component_ref (datum, component);
#endif
}
/* `Class' != `<class> *' && `<class> *' != `Class'! */ /* Recursively copy inheritance information rooted at BINFO. To do this,
else if ((OBJC_TYPE_NAME (lhs) == objc_class_id && TYPED_OBJECT (rhs)) we emulate the song and dance performed by cp/tree.c:copy_binfo(). */
|| (OBJC_TYPE_NAME (rhs) == objc_class_id && TYPED_OBJECT (lhs)))
return 0;
/* `<class> *' = `<class> *' */ static tree
objc_copy_binfo (tree binfo)
{
tree btype = BINFO_TYPE (binfo);
tree binfo2 = make_tree_binfo (BINFO_N_BASE_BINFOS (binfo));
tree base_binfo;
int ix;
else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs)) BINFO_TYPE (binfo2) = btype;
BINFO_OFFSET (binfo2) = BINFO_OFFSET (binfo);
BINFO_BASE_ACCESSES (binfo2) = BINFO_BASE_ACCESSES (binfo);
/* Recursively copy base binfos of BINFO. */
for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
{ {
tree lname = OBJC_TYPE_NAME (lhs); tree base_binfo2 = objc_copy_binfo (base_binfo);
tree rname = OBJC_TYPE_NAME (rhs);
tree inter; BINFO_INHERITANCE_CHAIN (base_binfo2) = binfo2;
BINFO_BASE_APPEND (binfo2, base_binfo2);
}
return binfo2;
}
/* Record superclass information provided in BASETYPE for ObjC class REF.
This is loosely based on cp/decl.c:xref_basetypes(). */
if (lname == rname) static void
return 1; objc_xref_basetypes (tree ref, tree basetype)
{
tree binfo = make_tree_binfo (basetype ? 1 : 0);
/* If the left hand side is a super class of the right hand side, TYPE_BINFO (ref) = binfo;
allow it. */ BINFO_OFFSET (binfo) = size_zero_node;
for (inter = lookup_interface (rname); inter; BINFO_TYPE (binfo) = ref;
inter = lookup_interface (CLASS_SUPER_NAME (inter)))
if (lname == CLASS_SUPER_NAME (inter))
return 1;
/* Allow the reverse when reflexive. */ if (basetype)
if (reflexive) {
for (inter = lookup_interface (lname); inter; tree base_binfo = objc_copy_binfo (TYPE_BINFO (basetype));
inter = lookup_interface (CLASS_SUPER_NAME (inter)))
if (rname == CLASS_SUPER_NAME (inter))
return 1;
return 0; BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, 1);
BINFO_BASE_APPEND (binfo, base_binfo);
BINFO_BASE_ACCESS_APPEND (binfo, access_public_node);
} }
else }
/* Not an ObjC type - let comptypes do the check. */
return -1; static hashval_t
volatilized_hash (const void *ptr)
{
tree typ = ((struct volatilized_type *)ptr)->type;
return (hashval_t) typ;
}
static int
volatilized_eq (const void *ptr1, const void *ptr2)
{
tree typ1 = ((struct volatilized_type *)ptr1)->type;
tree typ2 = ((struct volatilized_type *)ptr2)->type;
return typ1 == typ2;
} }
/* Called from finish_decl. */ /* Called from finish_decl. */
...@@ -1532,10 +1667,6 @@ synth_module_prologue (void) ...@@ -1532,10 +1667,6 @@ synth_module_prologue (void)
/* Pre-build the following entities - for speed/convenience. */ /* Pre-build the following entities - for speed/convenience. */
self_id = get_identifier ("self"); self_id = get_identifier ("self");
ucmd_id = get_identifier ("_cmd"); ucmd_id = get_identifier ("_cmd");
#ifndef OBJCPLUS
/* The C++ front-end does not appear to grok __attribute__((__unused__)). */
unused_list = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
#endif
#ifdef OBJCPLUS #ifdef OBJCPLUS
pop_lang_context (); pop_lang_context ();
...@@ -2512,23 +2643,29 @@ add_class_reference (tree ident) ...@@ -2512,23 +2643,29 @@ add_class_reference (tree ident)
tree tree
objc_get_class_reference (tree ident) objc_get_class_reference (tree ident)
{ {
tree orig_ident; tree orig_ident = (DECL_P (ident)
? DECL_NAME (ident)
: TYPE_P (ident)
? OBJC_TYPE_NAME (ident)
: ident);
bool local_scope = false; bool local_scope = false;
#ifdef OBJCPLUS #ifdef OBJCPLUS
if (processing_template_decl) if (processing_template_decl)
/* Must wait until template instantiation time. */ /* Must wait until template instantiation time. */
return build_min_nt (CLASS_REFERENCE_EXPR, ident); return build_min_nt (CLASS_REFERENCE_EXPR, ident);
#endif
if (TREE_CODE (ident) == TYPE_DECL) if (TREE_CODE (ident) == TYPE_DECL)
{ ident = (DECL_ORIGINAL_TYPE (ident)
/* The type must exist in the global namespace. */ ? DECL_ORIGINAL_TYPE (ident)
if (DECL_CONTEXT (ident) && DECL_CONTEXT (ident) != global_namespace) : TREE_TYPE (ident));
local_scope = true;
ident = DECL_NAME (ident); #ifdef OBJCPLUS
} if (TYPE_P (ident) && TYPE_CONTEXT (ident)
&& TYPE_CONTEXT (ident) != global_namespace)
local_scope = true;
#endif #endif
orig_ident = ident;
if (local_scope || !(ident = objc_is_class_name (ident))) if (local_scope || !(ident = objc_is_class_name (ident)))
{ {
...@@ -2656,7 +2793,20 @@ objc_declare_alias (tree alias_ident, tree class_ident) ...@@ -2656,7 +2793,20 @@ objc_declare_alias (tree alias_ident, tree class_ident)
else if (objc_is_class_name (alias_ident)) else if (objc_is_class_name (alias_ident))
warning (0, "class %qs already exists", IDENTIFIER_POINTER (alias_ident)); warning (0, "class %qs already exists", IDENTIFIER_POINTER (alias_ident));
else else
alias_chain = tree_cons (underlying_class, alias_ident, alias_chain); {
/* Implement @compatibility_alias as a typedef. */
#ifdef OBJCPLUS
push_lang_context (lang_name_c); /* extern "C" */
#endif
lang_hooks.decls.pushdecl (build_decl
(TYPE_DECL,
alias_ident,
xref_tag (RECORD_TYPE, underlying_class)));
#ifdef OBJCPLUS
pop_lang_context ();
#endif
alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
}
} }
void void
...@@ -2807,10 +2957,11 @@ objc_substitute_decl (tree expr, tree oldexpr, tree newexpr) ...@@ -2807,10 +2957,11 @@ objc_substitute_decl (tree expr, tree oldexpr, tree newexpr)
switch (TREE_CODE (expr)) switch (TREE_CODE (expr))
{ {
case COMPONENT_REF: case COMPONENT_REF:
return build_component_ref (objc_substitute_decl (TREE_OPERAND (expr, 0), return objc_build_component_ref
oldexpr, (objc_substitute_decl (TREE_OPERAND (expr, 0),
newexpr), oldexpr,
DECL_NAME (TREE_OPERAND (expr, 1))); newexpr),
DECL_NAME (TREE_OPERAND (expr, 1)));
case ARRAY_REF: case ARRAY_REF:
return build_array_ref (objc_substitute_decl (TREE_OPERAND (expr, 0), return build_array_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
oldexpr, oldexpr,
...@@ -3103,7 +3254,7 @@ objc_get_class_ivars (tree class_name) ...@@ -3103,7 +3254,7 @@ objc_get_class_ivars (tree class_name)
tree interface = lookup_interface (class_name); tree interface = lookup_interface (class_name);
if (interface) if (interface)
return get_class_ivars (interface); return get_class_ivars (interface, true);
error ("cannot find interface declaration for %qs", error ("cannot find interface declaration for %qs",
IDENTIFIER_POINTER (class_name)); IDENTIFIER_POINTER (class_name));
...@@ -3115,7 +3266,7 @@ objc_get_class_ivars (tree class_name) ...@@ -3115,7 +3266,7 @@ objc_get_class_ivars (tree class_name)
and for @defs constructs. */ and for @defs constructs. */
static tree static tree
get_class_ivars (tree interface) get_class_ivars (tree interface, bool inherited)
{ {
tree ivar_chain = copy_list (CLASS_RAW_IVARS (interface)); tree ivar_chain = copy_list (CLASS_RAW_IVARS (interface));
...@@ -3126,6 +3277,9 @@ get_class_ivars (tree interface) ...@@ -3126,6 +3277,9 @@ get_class_ivars (tree interface)
if (!CLASS_IVARS (interface)) if (!CLASS_IVARS (interface))
CLASS_IVARS (interface) = ivar_chain; CLASS_IVARS (interface) = ivar_chain;
if (!inherited)
return ivar_chain;
while (CLASS_SUPER_NAME (interface)) while (CLASS_SUPER_NAME (interface))
{ {
/* Prepend super-class ivars. */ /* Prepend super-class ivars. */
...@@ -3283,8 +3437,8 @@ next_sjlj_build_enter_and_setjmp (void) ...@@ -3283,8 +3437,8 @@ next_sjlj_build_enter_and_setjmp (void)
t = tree_cons (NULL, t, NULL); t = tree_cons (NULL, t, NULL);
enter = build_function_call (objc_exception_try_enter_decl, t); enter = build_function_call (objc_exception_try_enter_decl, t);
t = build_component_ref (cur_try_context->stack_decl, t = objc_build_component_ref (cur_try_context->stack_decl,
get_identifier ("buf")); get_identifier ("buf"));
t = build_fold_addr_expr (t); t = build_fold_addr_expr (t);
#ifdef OBJCPLUS #ifdef OBJCPLUS
/* Convert _setjmp argument to type that is expected. */ /* Convert _setjmp argument to type that is expected. */
...@@ -3569,7 +3723,7 @@ objc_begin_catch_clause (tree decl) ...@@ -3569,7 +3723,7 @@ objc_begin_catch_clause (tree decl)
t = CATCH_TYPES (stmt); t = CATCH_TYPES (stmt);
if (t == error_mark_node) if (t == error_mark_node)
continue; continue;
if (!t || objc_comptypes (TREE_TYPE (t), TREE_TYPE (type), 0) == 1) if (!t || DERIVED_FROM_P (TREE_TYPE (t), TREE_TYPE (type)))
{ {
warning (0, "exception of type %<%T%> will be caught", warning (0, "exception of type %<%T%> will be caught",
TREE_TYPE (type)); TREE_TYPE (type));
...@@ -3869,9 +4023,10 @@ build_private_template (tree class) ...@@ -3869,9 +4023,10 @@ build_private_template (tree class)
{ {
if (!CLASS_STATIC_TEMPLATE (class)) if (!CLASS_STATIC_TEMPLATE (class))
{ {
tree record = start_struct (RECORD_TYPE, CLASS_NAME (class)); tree record = objc_build_struct (CLASS_NAME (class),
get_class_ivars (class, false),
CLASS_SUPER_NAME (class));
finish_struct (record, get_class_ivars (class), NULL_TREE);
/* mark this record as class template - for class type checking */ /* mark this record as class template - for class type checking */
INIT_TYPE_OBJC_INFO (record); INIT_TYPE_OBJC_INFO (record);
TYPE_OBJC_INTERFACE (record) = class; TYPE_OBJC_INTERFACE (record) = class;
...@@ -4702,8 +4857,8 @@ synth_forward_declarations (void) ...@@ -4702,8 +4857,8 @@ synth_forward_declarations (void)
/* Pre-build the following entities - for speed/convenience. */ /* Pre-build the following entities - for speed/convenience. */
an_id = get_identifier ("super_class"); an_id = get_identifier ("super_class");
ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id); ucls_super_ref = objc_build_component_ref (UOBJC_CLASS_decl, an_id);
uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id); uucls_super_ref = objc_build_component_ref (UOBJC_METACLASS_decl, an_id);
} }
static void static void
...@@ -6482,7 +6637,7 @@ build_ivar_reference (tree id) ...@@ -6482,7 +6637,7 @@ build_ivar_reference (tree id)
self_decl = convert (objc_instance_type, self_decl); /* cast */ self_decl = convert (objc_instance_type, self_decl); /* cast */
} }
return build_component_ref (build_indirect_ref (self_decl, "->"), id); return objc_build_component_ref (build_indirect_ref (self_decl, "->"), id);
} }
/* Compute a hash value for a given method SEL_NAME. */ /* Compute a hash value for a given method SEL_NAME. */
...@@ -6510,6 +6665,10 @@ hash_init (void) ...@@ -6510,6 +6665,10 @@ hash_init (void)
/* Initialize the hash table used to hold the constant string objects. */ /* Initialize the hash table used to hold the constant string objects. */
string_htab = htab_create_ggc (31, string_hash, string_htab = htab_create_ggc (31, string_hash,
string_eq, NULL); string_eq, NULL);
/* Initialize the hash table used to hold EH-volatilized types. */
volatilized_htab = htab_create_ggc (31, volatilized_hash,
volatilized_eq, NULL);
} }
/* WARNING!!!! hash_enter is called with a method, and will peek /* WARNING!!!! hash_enter is called with a method, and will peek
...@@ -6924,8 +7083,14 @@ is_private (tree decl) ...@@ -6924,8 +7083,14 @@ is_private (tree decl)
int int
objc_is_public (tree expr, tree identifier) objc_is_public (tree expr, tree identifier)
{ {
tree basetype = TREE_TYPE (expr); tree basetype, decl;
tree decl;
#ifdef OBJCPLUS
if (processing_template_decl)
return 1;
#endif
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
if (basetype && TREE_CODE (basetype) == RECORD_TYPE) if (basetype && TREE_CODE (basetype) == RECORD_TYPE)
{ {
...@@ -6940,7 +7105,7 @@ objc_is_public (tree expr, tree identifier) ...@@ -6940,7 +7105,7 @@ objc_is_public (tree expr, tree identifier)
return 0; return 0;
} }
if ((decl = is_ivar (get_class_ivars (class), identifier))) if ((decl = is_ivar (get_class_ivars (class, true), identifier)))
{ {
if (TREE_PUBLIC (decl)) if (TREE_PUBLIC (decl))
return 1; return 1;
...@@ -6949,19 +7114,26 @@ objc_is_public (tree expr, tree identifier) ...@@ -6949,19 +7114,26 @@ objc_is_public (tree expr, tree identifier)
all instance variables should be public within the context all instance variables should be public within the context
of the implementation. */ of the implementation. */
if (objc_implementation_context if (objc_implementation_context
&& (((TREE_CODE (objc_implementation_context) && ((TREE_CODE (objc_implementation_context)
== CLASS_IMPLEMENTATION_TYPE) == CLASS_IMPLEMENTATION_TYPE)
|| (TREE_CODE (objc_implementation_context) || (TREE_CODE (objc_implementation_context)
== CATEGORY_IMPLEMENTATION_TYPE)) == CATEGORY_IMPLEMENTATION_TYPE)))
&& (CLASS_NAME (objc_implementation_context)
== OBJC_TYPE_NAME (basetype))))
{ {
int private = is_private (decl); tree curtype = TYPE_MAIN_VARIANT
(CLASS_STATIC_TEMPLATE
(implementation_template));
if (private) if (basetype == curtype
error ("instance variable %qs is declared private", || DERIVED_FROM_P (basetype, curtype))
IDENTIFIER_POINTER (DECL_NAME (decl))); {
return !private; int private = is_private (decl);
if (private)
error ("instance variable %qs is declared private",
IDENTIFIER_POINTER (DECL_NAME (decl)));
return !private;
}
} }
/* The 2.95.2 compiler sometimes allowed C functions to access /* The 2.95.2 compiler sometimes allowed C functions to access
...@@ -7396,7 +7568,7 @@ continue_class (tree class) ...@@ -7396,7 +7568,7 @@ continue_class (tree class)
pop_lang_context (); pop_lang_context ();
#endif /* OBJCPLUS */ #endif /* OBJCPLUS */
return get_class_ivars (implementation_template); return get_class_ivars (implementation_template, true);
} }
else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE) else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
...@@ -7682,6 +7854,47 @@ encode_array (tree type, int curtype, int format) ...@@ -7682,6 +7854,47 @@ encode_array (tree type, int curtype, int format)
} }
static void static void
encode_aggregate_fields (tree type, int pointed_to, int curtype, int format)
{
tree field = TYPE_FIELDS (type);
for (; field; field = TREE_CHAIN (field))
{
#ifdef OBJCPLUS
/* C++ static members, and things that are not field at all,
should not appear in the encoding. */
if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
continue;
#endif
/* Recursively encode fields of embedded base classes. */
if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
&& TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
{
encode_aggregate_fields (TREE_TYPE (field),
pointed_to, curtype, format);
continue;
}
if (generating_instance_variables && !pointed_to)
{
tree fname = DECL_NAME (field);
obstack_1grow (&util_obstack, '"');
if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
obstack_grow (&util_obstack,
IDENTIFIER_POINTER (fname),
strlen (IDENTIFIER_POINTER (fname)));
obstack_1grow (&util_obstack, '"');
}
encode_field_decl (field, curtype, format);
}
}
static void
encode_aggregate_within (tree type, int curtype, int format, int left, encode_aggregate_within (tree type, int curtype, int format, int left,
int right) int right)
{ {
...@@ -7721,30 +7934,8 @@ encode_aggregate_within (tree type, int curtype, int format, int left, ...@@ -7721,30 +7934,8 @@ encode_aggregate_within (tree type, int curtype, int format, int left,
if required. */ if required. */
if (inline_contents) if (inline_contents)
{ {
tree fields = TYPE_FIELDS (type);
obstack_1grow (&util_obstack, '='); obstack_1grow (&util_obstack, '=');
for (; fields; fields = TREE_CHAIN (fields)) encode_aggregate_fields (type, pointed_to, curtype, format);
{
#ifdef OBJCPLUS
/* C++ static members, and things that are not fields at all,
should not appear in the encoding. */
if (TREE_CODE (fields) != FIELD_DECL || TREE_STATIC (fields))
continue;
#endif
if (generating_instance_variables && !pointed_to)
{
tree fname = DECL_NAME (fields);
obstack_1grow (&util_obstack, '"');
if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
obstack_grow (&util_obstack,
IDENTIFIER_POINTER (fname),
strlen (IDENTIFIER_POINTER (fname)));
obstack_1grow (&util_obstack, '"');
}
encode_field_decl (fields, curtype, format);
}
} }
/* Close parenth/bracket. */ /* Close parenth/bracket. */
obstack_1grow (&util_obstack, right); obstack_1grow (&util_obstack, right);
...@@ -8392,13 +8583,13 @@ get_super_receiver (void) ...@@ -8392,13 +8583,13 @@ get_super_receiver (void)
} }
/* Set receiver to self. */ /* Set receiver to self. */
super_expr = build_component_ref (UOBJC_SUPER_decl, self_id); super_expr = objc_build_component_ref (UOBJC_SUPER_decl, self_id);
super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl); super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
super_expr_list = super_expr; super_expr_list = super_expr;
/* Set class to begin searching. */ /* Set class to begin searching. */
super_expr = build_component_ref (UOBJC_SUPER_decl, super_expr = objc_build_component_ref (UOBJC_SUPER_decl,
get_identifier ("super_class")); get_identifier ("super_class"));
if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
{ {
...@@ -9174,14 +9365,14 @@ objc_rewrite_function_call (tree function, tree params) ...@@ -9174,14 +9365,14 @@ objc_rewrite_function_call (tree function, tree params)
a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend or one a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend or one
of its cousins). */ of its cousins). */
enum gimplify_status objc_gimplify_expr (tree *expr_p, tree *pre_p, enum gimplify_status
tree *post_p) objc_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
{ {
enum gimplify_status r0, r1; enum gimplify_status r0, r1;
if (TREE_CODE (*expr_p) == OBJ_TYPE_REF if (TREE_CODE (*expr_p) == OBJ_TYPE_REF
&& TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR && TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0)) && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
== FUNCTION_DECL) == FUNCTION_DECL)
{ {
/* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
value of the OBJ_TYPE_REF, so force them to be emitted value of the OBJ_TYPE_REF, so force them to be emitted
...@@ -9193,8 +9384,10 @@ enum gimplify_status objc_gimplify_expr (tree *expr_p, tree *pre_p, ...@@ -9193,8 +9384,10 @@ enum gimplify_status objc_gimplify_expr (tree *expr_p, tree *pre_p,
is_gimple_val, fb_rvalue); is_gimple_val, fb_rvalue);
r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p, r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
is_gimple_val, fb_rvalue); is_gimple_val, fb_rvalue);
return MIN (r0, r1); return MIN (r0, r1);
} }
#ifdef OBJCPLUS #ifdef OBJCPLUS
return cp_gimplify_expr (expr_p, pre_p, post_p); return cp_gimplify_expr (expr_p, pre_p, post_p);
#else #else
......
...@@ -32,7 +32,6 @@ const char *objc_printable_name (tree, int); ...@@ -32,7 +32,6 @@ const char *objc_printable_name (tree, int);
tree objc_get_callee_fndecl (tree); tree objc_get_callee_fndecl (tree);
void objc_finish_file (void); void objc_finish_file (void);
tree objc_fold_obj_type_ref (tree, tree); tree objc_fold_obj_type_ref (tree, tree);
int objc_types_compatible_p (tree, tree);
enum gimplify_status objc_gimplify_expr (tree *, tree *, tree *); enum gimplify_status objc_gimplify_expr (tree *, tree *, tree *);
/* NB: The remaining public functions are prototyped in c-common.h, for the /* NB: The remaining public functions are prototyped in c-common.h, for the
...@@ -190,7 +189,6 @@ enum objc_tree_index ...@@ -190,7 +189,6 @@ enum objc_tree_index
OCTI_STATIC_NST_DECL, OCTI_STATIC_NST_DECL,
OCTI_SELF_ID, OCTI_SELF_ID,
OCTI_UCMD_ID, OCTI_UCMD_ID,
OCTI_UNUSED_LIST,
OCTI_SELF_DECL, OCTI_SELF_DECL,
OCTI_UMSG_DECL, OCTI_UMSG_DECL,
...@@ -305,7 +303,6 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; ...@@ -305,7 +303,6 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define self_id objc_global_trees[OCTI_SELF_ID] #define self_id objc_global_trees[OCTI_SELF_ID]
#define ucmd_id objc_global_trees[OCTI_UCMD_ID] #define ucmd_id objc_global_trees[OCTI_UCMD_ID]
#define unused_list objc_global_trees[OCTI_UNUSED_LIST]
#define self_decl objc_global_trees[OCTI_SELF_DECL] #define self_decl objc_global_trees[OCTI_SELF_DECL]
#define umsg_decl objc_global_trees[OCTI_UMSG_DECL] #define umsg_decl objc_global_trees[OCTI_UMSG_DECL]
......
...@@ -45,8 +45,6 @@ enum c_language_kind c_language = clk_objc; ...@@ -45,8 +45,6 @@ enum c_language_kind c_language = clk_objc;
#define LANG_HOOKS_INIT objc_init #define LANG_HOOKS_INIT objc_init
#undef LANG_HOOKS_DECL_PRINTABLE_NAME #undef LANG_HOOKS_DECL_PRINTABLE_NAME
#define LANG_HOOKS_DECL_PRINTABLE_NAME objc_printable_name #define LANG_HOOKS_DECL_PRINTABLE_NAME objc_printable_name
#undef LANG_HOOKS_TYPES_COMPATIBLE_P
#define LANG_HOOKS_TYPES_COMPATIBLE_P objc_types_compatible_p
#undef LANG_HOOKS_GIMPLIFY_EXPR #undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
#undef LANG_HOOKS_GET_CALLEE_FNDECL #undef LANG_HOOKS_GET_CALLEE_FNDECL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment