/* Implement classes and message passing for Objective C.
Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Steve Naroff.
This file is part of GCC.
#include "c-tree.h"
#include "c-common.h"
#include "flags.h"
+#include "langhooks.h"
#include "objc-act.h"
#include "input.h"
#include "except.h"
#include "target.h"
#include "diagnostic.h"
#include "cgraph.h"
-
-#define OBJC_VOID_AT_END build_tree_list (NULL_TREE, void_type_node)
+#include "tree-iterator.h"
+#include "libfuncs.h"
/* This is the default way of generating a method name. */
/* I am not sure it is really correct.
static void generate_strings (void);
static tree get_proto_encoding (tree);
static void build_selector_translation_table (void);
-
+static tree lookup_interface (tree);
static tree objc_add_static_instance (tree, tree);
static void build_objc_exception_stuff (void);
-static tree objc_declare_variable (enum rid, tree, tree, tree);
-static tree objc_enter_block (void);
-static tree objc_exit_block (void);
-static void objc_build_try_enter_fragment (void);
-static void objc_build_try_exit_fragment (void);
-static void objc_build_extract_fragment (void);
-static tree objc_build_extract_expr (void);
+static void build_next_objc_exception_stuff (void);
static tree build_ivar_template (void);
static tree build_method_template (void);
static void build_class_template (void);
static void build_selector_template (void);
static void build_category_template (void);
-static tree lookup_method_in_hash_lists (tree);
+static tree lookup_method_in_hash_lists (tree, int);
static void build_super_template (void);
static tree build_category_initializer (tree, tree, tree, tree, tree, tree);
static tree build_protocol_initializer (tree, tree, tree, tree, tree);
static void generate_dispatch_tables (void);
static void generate_shared_structures (void);
static tree generate_protocol_list (tree);
-static void generate_forward_declaration_to_string_table (void);
static void build_protocol_reference (tree);
static tree build_keyword_selector (tree);
static void hash_add_attr (hash, tree);
static tree lookup_method (tree, tree);
static tree lookup_method_static (tree, tree, int);
+static void add_method_to_hash_list (hash *, tree);
static tree add_class (tree);
static void add_category (tree, tree);
+static inline tree lookup_category (tree, tree);
enum string_section
{
static void generate_category (tree);
static int is_objc_type_qualifier (tree);
static tree adjust_type_for_id_default (tree);
-static tree check_duplicates (hash, int);
+static tree check_duplicates (hash, int, int);
static tree receiver_is_class_object (tree, int, int);
static int check_methods (tree, tree, int);
static int conforms_to_protocol (tree, tree);
#define TAG_RETURN_STRUCT "objc_return_struct"
#define UTAG_EXCDATA "_objc_exception_data"
-#define UTAG_EXCDATA_VAR "_stackExceptionData"
-#define UTAG_CAUGHTEXC_VAR "_caughtException"
-#define UTAG_RETHROWEXC_VAR "_rethrowException"
-#define UTAG_EVALONCE_VAR "_eval_once"
-
-struct val_stack {
- long val;
- struct val_stack *next;
-};
-static struct val_stack *catch_count_stack, *exc_binding_stack;
-
-/* useful for debugging */
-static int if_nesting_count;
-static int blk_nesting_count;
-
-static void val_stack_push (struct val_stack **, long);
-static void val_stack_pop (struct val_stack **);
/* The OCTI_... enumeration itself is in objc/objc-act.h. */
tree objc_global_trees[OCTI_MAX];
}
void
-finish_file (void)
+objc_finish_file (void)
{
mark_referenced_methods ();
- c_objc_common_finish_file ();
/* Finalize Objective-C runtime data. No need to generate tables
and code if only checking syntax. */
return decl;
}
+/* Return the first occurrence of a method declaration corresponding
+ to sel_name in rproto_list. Search rproto_list recursively.
+ If is_class is 0, search for instance methods, otherwise for class
+ methods. */
static tree
lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
- int class_meth)
+ int is_class)
{
tree rproto, p;
tree fnd = 0;
if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
{
- if ((fnd = lookup_method (class_meth
+ if ((fnd = lookup_method (is_class
? PROTOCOL_CLS_METHODS (p)
: PROTOCOL_NST_METHODS (p), sel_name)))
;
else if (PROTOCOL_LIST (p))
fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
- sel_name, class_meth);
+ sel_name, is_class);
}
else
{
return 0;
}
+/* Return 1 if IDENT is an ObjC/ObjC++ reserved keyword in the context of
+ an '@'. */
+
+int
+objc_is_reserved_word (tree ident)
+{
+ unsigned char code = C_RID_CODE (ident);
+
+ return (OBJC_IS_AT_KEYWORD (code)
+#ifdef OBJCPLUS
+ || code == RID_CLASS || code == RID_PUBLIC
+ || code == RID_PROTECTED || code == RID_PRIVATE
+ || code == RID_TRY || code == RID_THROW || code == RID_CATCH
+#endif
+ );
+}
+
+/* Return true if TYPE is 'id'. */
+
+static bool
+objc_is_object_id (tree type)
+{
+ return OBJC_TYPE_NAME (type) == objc_object_id;
+}
+
+static bool
+objc_is_class_id (tree type)
+{
+ return OBJC_TYPE_NAME (type) == objc_class_id;
+}
+
/* Return 1 if LHS and RHS are compatible types for assignment or
various other operations. Return 0 if they are incompatible, and
return -1 if we choose to not decide (because the types are really
return 1;
}
/* <Protocol> = id */
- else if (OBJC_TYPE_NAME (TREE_TYPE (rhs)) == objc_object_id)
+ else if (objc_is_object_id (TREE_TYPE (rhs)))
{
return 1;
}
/* <Protocol> = Class */
- else if (OBJC_TYPE_NAME (TREE_TYPE (rhs)) == objc_class_id)
+ else if (objc_is_class_id (TREE_TYPE (rhs)))
{
return 0;
}
return 0;
}
/* id = <Protocol> */
- else if (OBJC_TYPE_NAME (TREE_TYPE (lhs)) == objc_object_id)
+ else if (objc_is_object_id (TREE_TYPE (lhs)))
{
return 1;
}
/* Class = <Protocol> */
- else if (OBJC_TYPE_NAME (TREE_TYPE (lhs)) == objc_class_id)
+ else if (objc_is_class_id (TREE_TYPE (lhs)))
{
return 0;
}
'Object *o = [[Object alloc] init]; falls
in the case <class> * = `id'.
*/
- if ((OBJC_TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
- || (OBJC_TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
+ if ((objc_is_object_id (lhs) && TYPED_OBJECT (rhs))
+ || (objc_is_object_id (rhs) && TYPED_OBJECT (lhs)))
return 1;
/* `id' = `Class', `Class' = `id' */
- else if ((OBJC_TYPE_NAME (lhs) == objc_object_id
- && OBJC_TYPE_NAME (rhs) == objc_class_id)
- || (OBJC_TYPE_NAME (lhs) == objc_class_id
- && OBJC_TYPE_NAME (rhs) == objc_object_id))
+ else if ((objc_is_object_id (lhs) && objc_is_class_id (rhs))
+ || (objc_is_class_id (lhs) && objc_is_object_id (rhs)))
return 1;
+ /* `Class' != `<class> *' && `<class> *' != `Class'! */
+ else if ((OBJC_TYPE_NAME (lhs) == objc_class_id && TYPED_OBJECT (rhs))
+ || (OBJC_TYPE_NAME (rhs) == objc_class_id && TYPED_OBJECT (lhs)))
+ return 0;
+
/* `<class> *' = `<class> *' */
else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
if (TREE_CODE (type) != RECORD_TYPE)
return;
- if (TYPE_NAME (type) && (type = is_class_name (TYPE_NAME (type)))
- && type != constant_string_type)
+ if (OBJC_TYPE_NAME (type) && (type = objc_is_class_name (OBJC_TYPE_NAME (type))))
error ("statically allocated instance of Objective-C class `%s'",
- IDENTIFIER_POINTER (type));
+ IDENTIFIER_POINTER (type));
}
/* Implement static typing. At this point, we know we have an interface. */
if (protocols)
{
- tree t, m = TYPE_MAIN_VARIANT (type);
-
- t = copy_node (type);
-
- /* Add this type to the chain of variants of TYPE. */
- TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
- TYPE_NEXT_VARIANT (m) = t;
-
+ type = build_variant_type_copy (type);
+
/* Look up protocols and install in lang specific list. Note
that the protocol list can have a different lifetime than T! */
- SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
-
- /* This forces a new pointer type to be created later
- (in build_pointer_type)...so that the new template
- we just created will actually be used...what a hack! */
- if (TYPE_POINTER_TO (t))
- TYPE_POINTER_TO (t) = NULL_TREE;
-
- type = t;
+ SET_TYPE_PROTOCOL_LIST (type, lookup_and_install_protocols (protocols));
}
return type;
}
+/* Return a declaration corresponding to a protocol list qualified 'id'. */
tree
-get_object_reference (tree protocols)
+get_protocol_reference (tree protocols)
{
tree type_decl = lookup_name (objc_id_id);
tree type;
if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
{
type = TREE_TYPE (type_decl);
- if (TYPE_MAIN_VARIANT (type) != id_type)
+ if (TYPE_MAIN_VARIANT (type) != objc_id_type)
warning ("unexpected type for `id' (%s)",
gen_declaration (type, errbuf));
}
if (protocols)
{
- tree t, m = TYPE_MAIN_VARIANT (type);
-
- t = copy_node (type);
-
- /* Add this type to the chain of variants of TYPE. */
- TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
- TYPE_NEXT_VARIANT (m) = t;
+ type = build_variant_type_copy (type);
/* Look up protocols...and install in lang specific list */
- SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
-
- /* This forces a new pointer type to be created later
- (in build_pointer_type)...so that the new template
- we just created will actually be used...what a hack! */
- if (TYPE_POINTER_TO (t))
- TYPE_POINTER_TO (t) = NULL_TREE;
-
- type = t;
+ SET_TYPE_PROTOCOL_LIST (type, lookup_and_install_protocols (protocols));
}
return type;
}
if (code == VAR_DECL)
{
TREE_STATIC (decl) = 1;
- make_decl_rtl (decl, 0);
+ make_decl_rtl (decl);
pushdecl (decl);
DECL_ARTIFICIAL (decl) = 1;
}
objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
- id_type = build_pointer_type (objc_object_reference);
+ objc_id_type = build_pointer_type (objc_object_reference);
objc_id_id = get_identifier (TYPE_ID);
objc_class_id = get_identifier (TAG_CLASS);
objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
temp_type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
objc_declare_class (tree_cons (NULL_TREE, temp_type, NULL_TREE));
- protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
- temp_type));
+ objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE, temp_type));
/* Declare type of selector-objects that represent an operation name. */
- /* `struct objc_selector *' */
- selector_type
- = build_pointer_type (xref_tag (RECORD_TYPE,
- get_identifier (TAG_SELECTOR)));
+ if (flag_next_runtime)
+ /* `struct objc_selector *' */
+ objc_selector_type
+ = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (TAG_SELECTOR)));
+ else
+ /* `const struct objc_selector *' */
+ objc_selector_type
+ = build_pointer_type
+ (build_qualified_type (xref_tag (RECORD_TYPE,
+ get_identifier (TAG_SELECTOR)),
+ TYPE_QUAL_CONST));
- /* Forward declare type, or else the prototype for msgSendSuper will
- complain. */
+ /* Declare receiver type used for dispatching messages to 'super'. */
/* `struct objc_super *' */
- super_type = build_pointer_type (xref_tag (RECORD_TYPE,
- get_identifier (TAG_SUPER)));
-
-
- /* id objc_msgSend (id, SEL, ...); */
+ objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (TAG_SUPER)));
- temp_type
- = build_function_type (id_type,
- tree_cons (NULL_TREE, id_type,
- tree_cons (NULL_TREE, selector_type,
- NULL_TREE)));
-
- if (! flag_next_runtime)
+ if (flag_next_runtime)
{
- umsg_decl = build_decl (FUNCTION_DECL,
- get_identifier (TAG_MSGSEND), temp_type);
- DECL_EXTERNAL (umsg_decl) = 1;
- TREE_PUBLIC (umsg_decl) = 1;
- DECL_INLINE (umsg_decl) = 1;
- DECL_ARTIFICIAL (umsg_decl) = 1;
+ /* NB: In order to call one of the ..._stret (struct-returning)
+ functions, the function *MUST* first be cast to a signature that
+ corresponds to the actual ObjC method being invoked. This is
+ what is done by the build_objc_method_call() routine below. */
- make_decl_rtl (umsg_decl, NULL);
- pushdecl (umsg_decl);
- }
- else
- {
+ /* id objc_msgSend (id, SEL, ...); */
+ /* id objc_msgSendNonNil (id, SEL, ...); */
+ /* id objc_msgSend_stret (id, SEL, ...); */
+ /* id objc_msgSendNonNil_stret (id, SEL, ...); */
+ temp_type
+ = build_function_type (objc_id_type,
+ tree_cons (NULL_TREE, objc_id_type,
+ tree_cons (NULL_TREE,
+ objc_selector_type,
+ NULL_TREE)));
umsg_decl = builtin_function (TAG_MSGSEND,
temp_type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
- /* id objc_msgSendNonNil (id, SEL, ...); */
umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
temp_type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
- }
-
- /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
-
- temp_type
- = build_function_type (id_type,
- tree_cons (NULL_TREE, super_type,
- tree_cons (NULL_TREE, selector_type,
- NULL_TREE)));
-
- umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
- temp_type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
-
- /* The NeXT runtime defines the following additional entry points,
- used for dispatching calls to methods returning structs:
-
- #if defined(__cplusplus)
- id objc_msgSend_stret(id self, SEL op, ...);
- id objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...);
- #else
- void objc_msgSend_stret(void * stretAddr, id self, SEL op, ...);
- void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
- SEL op, ...);
- #endif
-
- struct objc_return_struct objc_msgSendNonNil_stret(id self, SEL op, ...);
-
- These prototypes appear in <objc/objc-runtime.h>; however, they
- CANNOT BE USED DIRECTLY. In order to call one of the ..._stret
- functions, the function must first be cast to a signature that
- corresponds to the actual ObjC method being invoked. This is
- what is done by the build_objc_method_call() routine below. */
-
- if (flag_next_runtime)
- {
- tree objc_return_struct_type
- = xref_tag (RECORD_TYPE,
- get_identifier (TAG_RETURN_STRUCT));
-
- tree stret_temp_type
- = build_function_type (id_type,
- tree_cons (NULL_TREE, id_type,
- tree_cons (NULL_TREE, selector_type,
- NULL_TREE)));
-
umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
- stret_temp_type, 0, NOT_BUILT_IN,
+ temp_type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
- stret_temp_type
- = build_function_type (objc_return_struct_type,
- tree_cons (NULL_TREE, id_type,
- tree_cons (NULL_TREE, selector_type,
- NULL_TREE)));
-
umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
- stret_temp_type, 0, NOT_BUILT_IN,
+ temp_type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
- stret_temp_type
- = build_function_type (id_type,
- tree_cons (NULL_TREE, super_type,
- tree_cons (NULL_TREE, selector_type,
+ /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
+ /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
+ temp_type
+ = build_function_type (objc_id_type,
+ tree_cons (NULL_TREE, objc_super_type,
+ tree_cons (NULL_TREE,
+ objc_selector_type,
NULL_TREE)));
-
+ umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
+ temp_type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
- stret_temp_type, 0, NOT_BUILT_IN, 0,
+ temp_type, 0, NOT_BUILT_IN, 0,
NULL_TREE);
}
+ else
+ {
+ /* GNU runtime messenger entry points. */
+
+ /* typedef id (*IMP)(id, SEL, ...); */
+ tree IMP_type
+ = build_pointer_type
+ (build_function_type (objc_id_type,
+ tree_cons (NULL_TREE, objc_id_type,
+ tree_cons (NULL_TREE,
+ objc_selector_type,
+ NULL_TREE))));
+
+ /* IMP objc_msg_lookup (id, SEL); */
+ temp_type
+ = build_function_type (IMP_type,
+ tree_cons (NULL_TREE, objc_id_type,
+ tree_cons (NULL_TREE,
+ objc_selector_type,
+ void_list_node)));
+ umsg_decl = builtin_function (TAG_MSGSEND,
+ temp_type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
+ temp_type
+ = build_function_type (IMP_type,
+ tree_cons (NULL_TREE, objc_super_type,
+ tree_cons (NULL_TREE,
+ objc_selector_type,
+ void_list_node)));
+ umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
+ temp_type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ }
/* id objc_getClass (const char *); */
- temp_type = build_function_type (id_type,
+ temp_type = build_function_type (objc_id_type,
tree_cons (NULL_TREE,
const_string_type_node,
- OBJC_VOID_AT_END));
+ void_list_node));
objc_get_class_decl
= builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
= builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
build_super_template ();
+ build_objc_exception_stuff ();
if (flag_next_runtime)
- build_objc_exception_stuff ();
+ build_next_objc_exception_stuff ();
/* static SEL _OBJC_SELECTOR_TABLE[]; */
debug_hooks = save_hooks;
}
else
- temp_type = build_array_type (selector_type, NULL_TREE);
+ temp_type = build_array_type (objc_selector_type, NULL_TREE);
layout_type (temp_type);
UOBJC_SELECTOR_TABLE_decl
TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
}
- generate_forward_declaration_to_string_table ();
-
/* Forward declare constant_string_id and constant_string_type. */
if (!constant_string_class_name)
constant_string_class_name = default_constant_string_class_name;
NXConstantString class object. */
tree
-build_objc_string_object (tree string)
+objc_build_string_object (tree string)
{
tree initlist, constructor, constant_string_class;
int length;
+ tree fields;
string = fix_string_type (string);
}
add_class_reference (constant_string_id);
}
+ fields = TYPE_FIELDS (constant_string_type);
/* & ((NXConstantString) { NULL, string, length }) */
return error_mark_node;
}
initlist = build_tree_list
- (NULL_TREE,
+ (fields,
copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
}
else
{
- initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
+ initlist = build_tree_list (fields, build_int_cst (NULL_TREE, 0));
}
+ fields = TREE_CHAIN (fields);
+
initlist
- = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
+ = tree_cons (fields, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
initlist);
- initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
+
+ fields = TREE_CHAIN (fields);
+
+ initlist = tree_cons (fields, build_int_cst (NULL_TREE, length), initlist);
constructor = objc_build_constructor (constant_string_type,
nreverse (initlist));
= objc_add_static_instance (constructor, constant_string_type);
}
- return (build_unary_op (ADDR_EXPR, constructor, 1));
+ constructor = build_unary_op (ADDR_EXPR, constructor, 1);
+ TREE_CONSTANT (constructor) = true;
+ return constructor;
}
/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
Postpone till end of input. */
DECL_DEFER_OUTPUT (decl) = 1;
pushdecl_top_level (decl);
- rest_of_decl_compilation (decl, 0, 1, 0);
+ rest_of_decl_compilation (decl, 1, 0);
/* Add the DECL to the head of this CLASS' list. */
TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
/* SEL *refs; */
field_decl = create_builtin_decl (FIELD_DECL,
- build_pointer_type (selector_type),
+ build_pointer_type (objc_selector_type),
"refs");
chainon (field_decl_chain, field_decl);
(FIELD_DECL,
build_array_type
(ptr_type_node,
- build_index_type (build_int_2 (index, 0))),
+ build_index_type (build_int_cst (NULL_TREE, index))),
"defs");
chainon (field_decl_chain, field_decl);
}
if (static_instances_decl)
expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
else
- expr = build_int_2 (0, 0);
+ expr = build_int_cst (NULL_TREE, 0);
initlist = tree_cons (NULL_TREE, expr, initlist);
}
/* sel_ref_cnt = { ..., 5, ... } */
- initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
+ initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
/* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
if (flag_next_runtime || ! sel_ref_chain)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
initlist = tree_cons (NULL_TREE,
build_unary_op (ADDR_EXPR,
/* cls_def_cnt = { ..., 5, ... } */
- initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, imp_count), initlist);
/* cat_def_cnt = { ..., 5, ... } */
- initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, cat_count), initlist);
/* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
/* version = { 1, ... } */
- expr = build_int_2 (OBJC_VERSION, 0);
+ expr = build_int_cst (NULL_TREE, OBJC_VERSION);
initlist = build_tree_list (NULL_TREE, expr);
/* size = { ..., sizeof (struct objc_module), ... } */
if (UOBJC_SYMBOLS_decl)
expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
else
- expr = build_int_2 (0, 0);
+ expr = build_int_cst (NULL_TREE, 0);
initlist = tree_cons (NULL_TREE, expr, initlist);
return objc_build_constructor (type, nreverse (initlist));
/* Mark the decl to avoid "defined but not used" warning. */
DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
+
+ mark_decl_referenced (UOBJC_MODULES_decl);
/* Generate a constructor call for the module descriptor.
This code was generated by reading the grammar rules
{
tree parms, execclass_decl, decelerator, void_list_node_1;
- tree init_function_name, init_function_decl;
+ tree init_function_name, init_function_decl, compound;
/* Declare void __objc_execClass (void *); */
get_identifier (TAG_EXECCLASS),
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
- OBJC_VOID_AT_END)));
+ void_list_node)));
DECL_EXTERNAL (execclass_decl) = 1;
DECL_ARTIFICIAL (execclass_decl) = 1;
TREE_PUBLIC (execclass_decl) = 1;
pushdecl (execclass_decl);
- rest_of_decl_compilation (execclass_decl, 0, 0, 0);
+ rest_of_decl_compilation (execclass_decl, 0, 0);
assemble_external (execclass_decl);
/* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
start_function (void_list_node_1,
build_nt (CALL_EXPR, init_function_name,
tree_cons (NULL_TREE, NULL_TREE,
- OBJC_VOID_AT_END),
+ void_list_node),
NULL_TREE),
NULL_TREE);
store_parm_decls ();
+ compound = c_begin_compound_stmt (true);
init_function_decl = current_function_decl;
TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
/* Don't let this one be deferred. */
DECL_INLINE (init_function_decl) = 0;
DECL_UNINLINABLE (init_function_decl) = 1;
- current_function_cannot_inline
- = "static constructors and destructors cannot be inlined";
parms
= build_tree_list (NULL_TREE,
build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
decelerator = build_function_call (execclass_decl, parms);
- c_expand_expr_stmt (decelerator);
+ add_stmt (decelerator);
+ add_stmt (c_end_compound_stmt (compound, true));
finish_function ();
}
}
-/* extern const char _OBJC_STRINGS[]; */
-
-static void
-generate_forward_declaration_to_string_table (void)
-{
- tree sc_spec, decl_specs, expr_decl;
-
- sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
- decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
-
- expr_decl
- = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
-
- UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
-}
-
/* Return the DECL of the string IDENT in the SECTION. */
static tree
{
tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
tree class_name, class, decl, initlist;
- tree cl_chain, in_chain, type;
+ tree cl_chain, in_chain;
int num_inst, num_class;
char buf[256];
sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
ident = get_identifier (buf);
- expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
+ expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
build_tree_list (NULL_TREE,
ridpointers[(int) RID_STATIC]));
decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
DECL_CONTEXT (decl) = 0;
DECL_ARTIFICIAL (decl) = 1;
+ TREE_USED (decl) = 1;
/* Output {class_name, ...}. */
class = TREE_VALUE (cl_chain);
}
/* Output {..., NULL}. */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
finish_decl (decl, expr, NULL_TREE);
- TREE_USED (decl) = 1;
-
- type = build_array_type (build_pointer_type (void_type_node), 0);
- decl = build_decl (VAR_DECL, ident, type);
- TREE_USED (decl) = 1;
- TREE_STATIC (decl) = 1;
decls
= tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
}
- decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
+ decls = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), decls);
ident = get_identifier ("_OBJC_STATIC_INSTANCES");
- expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
+ expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
build_tree_list (NULL_TREE,
ridpointers[(int) RID_STATIC]));
expr = objc_build_constructor (TREE_TYPE (static_instances_decl),
nreverse (decls));
finish_decl (static_instances_decl, expr, NULL_TREE);
+ rest_of_decl_compilation (static_instances_decl, 0, 0);
}
/* Output all strings. */
sc_spec
= tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
- expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
+ expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+ NULL_TREE, NULL_TREE);
decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
DECL_CONTEXT (decl) = NULL_TREE;
string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
sc_spec
= tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
- expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
+ expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+ NULL_TREE, NULL_TREE);
decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
DECL_CONTEXT (decl) = NULL_TREE;
string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
sc_spec
= tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
- expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
+ expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+ NULL_TREE, NULL_TREE);
decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
DECL_CONTEXT (decl) = NULL_TREE;
string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
ident = get_identifier (buf);
- decl = build_decl (VAR_DECL, ident, selector_type);
+ decl = build_decl (VAR_DECL, ident, objc_selector_type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 0;
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_CONTEXT (decl) = 0;
- make_decl_rtl (decl, 0);
+ make_decl_rtl (decl);
pushdecl_top_level (decl);
return decl;
if (flag_typed_selectors)
return expr;
else
- return build_c_cast (selector_type, expr); /* cast! */
+ return build_c_cast (objc_selector_type, expr); /* cast! */
}
static void
sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
/* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
- decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
+ decl_specs = tree_cons (NULL_TREE, objc_selector_type, sc_spec);
var_decl = name;
DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
/* NULL terminate the list and fix the decl for output. */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node;
initlist = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
nreverse (initlist));
return add_objc_string (encoding, meth_var_types);
}
else
- return build_int_2 (0, 0);
+ return build_int_cst (NULL_TREE, 0);
}
/* sel_ref_chain is a list whose "value" fields will be instances of
return_at_index:
expr = build_unary_op (ADDR_EXPR,
build_array_ref (UOBJC_SELECTOR_TABLE_decl,
- build_int_2 (index, 0)),
+ build_int_cst (NULL_TREE, index)),
1);
- return build_c_cast (selector_type, expr);
+ return build_c_cast (objc_selector_type, expr);
}
static tree
return (flag_next_runtime
? TREE_PURPOSE (*chain)
: build_array_ref (UOBJC_SELECTOR_TABLE_decl,
- build_int_2 (index, 0)));
+ build_int_cst (NULL_TREE, index)));
index++;
chain = &TREE_CHAIN (*chain);
return (flag_next_runtime
? expr
: build_array_ref (UOBJC_SELECTOR_TABLE_decl,
- build_int_2 (index, 0)));
+ build_int_cst (NULL_TREE, index)));
}
static GTY(()) int class_reference_idx;
DECL_CONTEXT (decl) = 0;
DECL_ARTIFICIAL (decl) = 1;
- make_decl_rtl (decl, 0);
+ make_decl_rtl (decl);
pushdecl_top_level (decl);
return decl;
reference variable. */
tree
-get_class_reference (tree ident)
+objc_get_class_reference (tree ident)
{
tree orig_ident;
#endif
orig_ident = ident;
- if (!(ident = is_class_name (ident)))
+ if (!(ident = objc_is_class_name (ident)))
{
error ("`%s' is not an Objective-C class name or alias",
IDENTIFIER_POINTER (orig_ident));
DECL_CONTEXT (decl) = 0;
DECL_ARTIFICIAL (decl) = 1;
- make_decl_rtl (decl, 0);
+ make_decl_rtl (decl);
pushdecl_top_level (decl);
return decl;
}
#endif /* OBJCPLUS */
- if (!(underlying_class = is_class_name (class_ident)))
+ if (!(underlying_class = objc_is_class_name (class_ident)))
warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
- else if (is_class_name (alias_ident))
+ else if (objc_is_class_name (alias_ident))
warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
else
alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
{
tree ident = TREE_VALUE (list);
- if (! is_class_name (ident))
+ if (! objc_is_class_name (ident))
{
tree record = lookup_name (ident);
}
tree
-is_class_name (tree ident)
+objc_is_class_name (tree ident)
{
tree chain;
if (!type || TREE_CODE (type) != POINTER_TYPE)
return 0;
/* NB: This function may be called before the ObjC front-end has
- been initialized, in which case ID_TYPE will be NULL. */
- if (id_type && type && TYPE_P (type)
+ been initialized, in which case OBJC_ID_TYPE will be NULL. */
+ if (objc_id_type && type && TYPE_P (type)
&& (IS_ID (type)
|| TREE_TYPE (type) == TREE_TYPE (objc_class_type)))
return type;
- return is_class_name (OBJC_TYPE_NAME (TREE_TYPE (type)));
+ return objc_is_class_name (OBJC_TYPE_NAME (TREE_TYPE (type)));
}
-tree
+static tree
lookup_interface (tree ident)
{
tree chain;
/* Implement @defs (<classname>) within struct bodies. */
tree
-get_class_ivars_from_name (tree class_name)
+objc_get_class_ivars (tree class_name)
{
tree interface = lookup_interface (class_name);
tree field, fields = NULL_TREE;
}
static tree
-objc_enter_block (void)
-{
- tree block;
-
-#ifdef OBJCPLUS
- block = begin_compound_stmt (0);
-#else
- block = c_begin_compound_stmt ();
- pushlevel (0);
- clear_last_expr ();
- add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-#endif
-
- objc_exception_block_stack = tree_cons (NULL_TREE, block,
- objc_exception_block_stack);
-
- blk_nesting_count++;
- return block;
-}
-
-static tree
-objc_exit_block (void)
-{
- tree block = TREE_VALUE (objc_exception_block_stack);
-#ifndef OBJCPLUS
- tree scope_stmt, inner;
-#endif
-
- objc_clear_super_receiver ();
-#ifdef OBJCPLUS
- finish_compound_stmt (0, block);
-#else
- scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
- inner = poplevel (KEEP_MAYBE, 1, 0);
-
- SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
- = SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
- = inner;
- RECHAIN_STMTS (block, COMPOUND_BODY (block));
-#endif
- last_expr_type = NULL_TREE;
- objc_exception_block_stack = TREE_CHAIN (objc_exception_block_stack);
-
- blk_nesting_count--;
- return block;
-}
-
-static tree
-objc_declare_variable (enum rid scspec, tree name, tree type, tree init)
+objc_create_temporary_var (tree type)
{
tree decl;
-
- type = tree_cons (NULL_TREE, type,
- tree_cons (NULL_TREE, ridpointers[(int) scspec],
- NULL_TREE));
- TREE_STATIC (type) = 1;
- decl = start_decl (name, type, (init != NULL_TREE), NULL_TREE);
- finish_decl (decl, init, NULL_TREE);
- /* This prevents `unused variable' warnings when compiling with -Wall. */
+
+ decl = build_decl (VAR_DECL, NULL_TREE, type);
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ DECL_CONTEXT (decl) = current_function_decl;
+
return decl;
}
+\f
+/* Exception handling constructs. We begin by having the parser do most
+ of the work and passing us blocks. What we do next depends on whether
+ we're doing "native" exception handling or legacy Darwin setjmp exceptions.
+ We abstract all of this in a handful of appropriately named routines. */
-tree
-objc_build_throw_stmt (tree throw_expr)
+/* Stack of open try blocks. */
+
+struct objc_try_context
{
- tree func_params;
+ struct objc_try_context *outer;
- if (!flag_objc_exceptions)
- fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
+ /* Statements (or statement lists) as processed by the parser. */
+ tree try_body;
+ tree finally_body;
- if (!throw_expr && objc_caught_exception)
- throw_expr = TREE_VALUE (objc_caught_exception);
+ /* Some file position locations. */
+ location_t try_locus;
+ location_t end_try_locus;
+ location_t end_catch_locus;
+ location_t finally_locus;
+ location_t end_finally_locus;
- if (!throw_expr)
- {
- error ("`@throw;' (rethrow) used outside of a `@catch' block");
- return error_mark_node;
- }
+ /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
+ of a TRY_CATCH_EXPR. Even when doing Darwin setjmp. */
+ tree catch_list;
- func_params = tree_cons (NULL_TREE, throw_expr, NULL_TREE);
+ /* The CATCH_EXPR of an open @catch clause. */
+ tree current_catch;
- assemble_external (objc_exception_throw_decl);
- return c_expand_expr_stmt (build_function_call (objc_exception_throw_decl,
- func_params));
-}
+ /* The VAR_DECL holding the Darwin equivalent of EXC_PTR_EXPR. */
+ tree caught_decl;
+ tree stack_decl;
+ tree rethrow_decl;
+};
-static void
-val_stack_push (struct val_stack **nc, long val)
-{
- struct val_stack *new_elem = xmalloc (sizeof (struct val_stack));
- new_elem->val = val;
- new_elem->next = *nc;
- *nc = new_elem;
-}
+static struct objc_try_context *cur_try_context;
-static void
-val_stack_pop (struct val_stack **nc)
+/* This hook, called via lang_eh_runtime_type, generates a runtime object
+ that represents TYPE. For Objective-C, this is just the class name. */
+/* ??? Isn't there a class object or some such? Is it easy to get? */
+
+static tree
+objc_eh_runtime_type (tree type)
{
- struct val_stack *old_elem = *nc;
- *nc = old_elem->next;
- free (old_elem);
+ return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
}
+/* Initialize exception handling. */
+
static void
-objc_build_try_enter_fragment (void)
+objc_init_exceptions (void)
{
- /* objc_exception_try_enter(&_stackExceptionData);
- if (!_setjmp(&_stackExceptionData.buf)) { */
-
- tree func_params, if_stmt, cond;
+ static bool done = false;
+ if (done)
+ return;
+ done = true;
- func_params
- = tree_cons (NULL_TREE,
- build_unary_op (ADDR_EXPR,
- TREE_VALUE (objc_stack_exception_data),
- 0),
- NULL_TREE);
+ /* Why? */
+ if (!flag_objc_exceptions)
+ warning ("use %<-fobjc-exceptions%> to enable Objective-C "
+ "exception syntax");
- assemble_external (objc_exception_try_enter_decl);
- c_expand_expr_stmt (build_function_call
- (objc_exception_try_enter_decl, func_params));
-
- if_stmt = c_begin_if_stmt ();
- if_nesting_count++;
- /* If <setjmp.h> has been included, the _setjmp prototype has
- acquired a real, breathing type for its parameter. Cast our
- argument to that type. */
- func_params
- = tree_cons (NULL_TREE,
- build_c_cast (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))
- ? TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
- : ptr_type_node,
- build_unary_op
- (ADDR_EXPR,
- build_component_ref (TREE_VALUE (objc_stack_exception_data),
- get_identifier ("buf")), 0)),
- NULL_TREE);
- assemble_external (objc_setjmp_decl);
- cond = build_unary_op (TRUTH_NOT_EXPR,
- build_function_call (objc_setjmp_decl, func_params),
- 0);
- c_expand_start_cond (c_common_truthvalue_conversion (cond),
- 0, if_stmt);
- objc_enter_block ();
+ if (!flag_objc_sjlj_exceptions)
+ {
+ c_eh_initialized_p = true;
+ eh_personality_libfunc
+ = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+ ? "__gnu_objc_personality_sj0"
+ : "__gnu_objc_personality_v0");
+ using_eh_for_cleanups ();
+ lang_eh_runtime_type = objc_eh_runtime_type;
+ }
}
+/* Build an EXC_PTR_EXPR, or the moral equivalent. In the case of Darwin,
+ we'll arrange for it to be initialized (and associated with a binding)
+ later. */
+
static tree
-objc_build_extract_expr (void)
+objc_build_exc_ptr (void)
{
- /* ... = objc_exception_extract(&_stackExceptionData); */
+ if (flag_objc_sjlj_exceptions)
+ {
+ tree var = cur_try_context->caught_decl;
+ if (!var)
+ {
+ var = objc_create_temporary_var (objc_id_type);
+ cur_try_context->caught_decl = var;
+ }
+ return var;
+ }
+ else
+ return build (EXC_PTR_EXPR, objc_id_type);
+}
- tree func_params
- = tree_cons (NULL_TREE,
- build_unary_op (ADDR_EXPR,
- TREE_VALUE (objc_stack_exception_data), 0),
- NULL_TREE);
+/* Build "objc_exception_try_exit(&_stack)". */
- assemble_external (objc_exception_extract_decl);
- return build_function_call (objc_exception_extract_decl, func_params);
+static tree
+next_sjlj_build_try_exit (void)
+{
+ tree t;
+ t = build_fold_addr_expr (cur_try_context->stack_decl);
+ t = tree_cons (NULL, t, NULL);
+ t = build_function_call (objc_exception_try_exit_decl, t);
+ return t;
}
-static void
-objc_build_try_exit_fragment (void)
-{
- /* objc_exception_try_exit(&_stackExceptionData); */
+/* Build
+ objc_exception_try_enter (&_stack);
+ if (_setjmp(&_stack.buf))
+ ;
+ else
+ ;
+ Return the COND_EXPR. Note that the THEN and ELSE fields are left
+ empty, ready for the caller to fill them in. */
- tree func_params
- = tree_cons (NULL_TREE,
- build_unary_op (ADDR_EXPR,
- TREE_VALUE (objc_stack_exception_data), 0),
- NULL_TREE);
+static tree
+next_sjlj_build_enter_and_setjmp (void)
+{
+ tree t, enter, sj, cond;
- assemble_external (objc_exception_try_exit_decl);
- c_expand_expr_stmt (build_function_call (objc_exception_try_exit_decl,
- func_params));
-}
+ t = build_fold_addr_expr (cur_try_context->stack_decl);
+ t = tree_cons (NULL, t, NULL);
+ enter = build_function_call (objc_exception_try_enter_decl, t);
-static void
-objc_build_extract_fragment (void)
-{
- /* } else {
- _rethrowException = objc_exception_extract(&_stackExceptionData);
- } */
+ t = build_component_ref (cur_try_context->stack_decl,
+ get_identifier ("buf"));
+ t = build_fold_addr_expr (t);
+ t = convert (ptr_type_node, t);
+ t = tree_cons (NULL, t, NULL);
+ sj = build_function_call (objc_setjmp_decl, t);
- objc_exit_block ();
- c_finish_then ();
+ cond = build (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
+ cond = lang_hooks.truthvalue_conversion (cond);
- c_expand_start_else ();
- objc_enter_block ();
- c_expand_expr_stmt (build_modify_expr
- (TREE_VALUE (objc_rethrow_exception),
- NOP_EXPR,
- objc_build_extract_expr ()));
- objc_exit_block ();
- c_finish_else ();
- c_expand_end_cond ();
- if_nesting_count--;
+ return build (COND_EXPR, void_type_node, cond, NULL, NULL);
}
-tree
-objc_build_try_prologue (void)
+/* Build
+ DECL = objc_exception_extract(&_stack);
+*/
+
+static tree
+next_sjlj_build_exc_extract (tree decl)
{
- /* { // new scope
- struct _objc_exception_data _stackExceptionData;
- volatile id _rethrowException = nil;
- { // begin TRY-CATCH scope
- objc_exception_try_enter(&_stackExceptionData);
- if (!_setjmp(&_stackExceptionData.buf)) { */
+ tree t;
- tree try_catch_block;
+ t = build_fold_addr_expr (cur_try_context->stack_decl);
+ t = tree_cons (NULL, t, NULL);
+ t = build_function_call (objc_exception_extract_decl, t);
+ t = convert (TREE_TYPE (decl), t);
+ t = build (MODIFY_EXPR, void_type_node, decl, t);
- if (!flag_objc_exceptions)
- fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
-
- objc_mark_locals_volatile ((void *)(exc_binding_stack
- ? exc_binding_stack->val
- : 0));
- objc_enter_block ();
- objc_stack_exception_data
- = tree_cons (NULL_TREE,
- objc_declare_variable (RID_AUTO,
- get_identifier (UTAG_EXCDATA_VAR),
- xref_tag (RECORD_TYPE,
- get_identifier (UTAG_EXCDATA)),
- NULL_TREE),
- objc_stack_exception_data);
- objc_rethrow_exception = tree_cons (NULL_TREE,
- objc_declare_variable (RID_VOLATILE,
- get_identifier (UTAG_RETHROWEXC_VAR),
- id_type,
- build_int_2 (0, 0)),
- objc_rethrow_exception);
-
- try_catch_block = objc_enter_block ();
- val_stack_push (&exc_binding_stack, (long) get_current_scope ());
- objc_build_try_enter_fragment ();
-
- return try_catch_block;
+ return t;
}
-void
-objc_build_try_epilogue (int also_catch_prologue)
+/* Build
+ if (objc_exception_match(obj_get_class(TYPE), _caught)
+ BODY
+ else if (...)
+ ...
+ else
+ {
+ _rethrow = _caught;
+ objc_exception_try_exit(&_stack);
+ }
+ from the sequence of CATCH_EXPRs in the current try context. */
+
+static tree
+next_sjlj_build_catch_list (void)
{
- if (also_catch_prologue)
+ tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
+ tree catch_seq, t;
+ tree *last = &catch_seq;
+ bool saw_id = false;
+
+ for (; !tsi_end_p (i); tsi_next (&i))
{
- /* } else {
- register id _caughtException = objc_exception_extract( &_stackExceptionData);
- objc_exception_try_enter(&_stackExceptionData);
- if(!_setjmp(&_stackExceptionData.buf)) {
- if (0) { */
+ tree stmt = tsi_stmt (i);
+ tree type = CATCH_TYPES (stmt);
+ tree body = CATCH_BODY (stmt);
- tree if_stmt;
+ if (type == NULL)
+ {
+ *last = body;
+ saw_id = true;
+ break;
+ }
+ else
+ {
+ tree args, cond;
- objc_exit_block ();
- c_finish_then ();
-
- c_expand_start_else ();
- objc_enter_block ();
- objc_caught_exception
- = tree_cons (NULL_TREE,
- objc_declare_variable (RID_REGISTER,
- get_identifier (UTAG_CAUGHTEXC_VAR),
- id_type,
- objc_build_extract_expr ()),
- objc_caught_exception);
- objc_build_try_enter_fragment ();
- val_stack_push (&catch_count_stack, 1);
- if_stmt = c_begin_if_stmt ();
- if_nesting_count++;
- c_expand_start_cond (c_common_truthvalue_conversion (boolean_false_node),
- 0, if_stmt);
- objc_enter_block ();
-
- /* Start a new chain of @catch statements for this @try. */
- objc_catch_type = tree_cons (objc_catch_type, NULL_TREE, NULL_TREE);
- }
- else
- { /* !also_catch_prologue */
+ if (type == error_mark_node)
+ cond = error_mark_node;
+ else
+ {
+ args = tree_cons (NULL, cur_try_context->caught_decl, NULL);
+ t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
+ args = tree_cons (NULL, t, args);
+ t = build_function_call (objc_exception_match_decl, args);
+ cond = lang_hooks.truthvalue_conversion (t);
+ }
+ t = build (COND_EXPR, void_type_node, cond, body, NULL);
+ SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
- /* } else {
- _rethrowException = objc_exception_extract( &_stackExceptionData);
- }
- } */
- objc_build_extract_fragment ();
- objc_exit_block ();
+ *last = t;
+ last = &COND_EXPR_ELSE (t);
+ }
}
-}
-void
-objc_build_catch_stmt (tree catch_expr)
-{
- /* } else if (objc_exception_match(objc_get_class("SomeClass"), _caughtException)) {
- register SomeClass *e = _caughtException; */
-
- tree if_stmt, cond, func_params, prev_catch, var_name, var_type;
- int catch_id;
-
-#ifndef OBJCPLUS
- /* Yet another C/C++ impedance mismatch. */
- catch_expr = TREE_PURPOSE (catch_expr);
-#endif
+ if (!saw_id)
+ {
+ t = build (MODIFY_EXPR, void_type_node, cur_try_context->rethrow_decl,
+ cur_try_context->caught_decl);
+ annotate_with_locus (t, cur_try_context->end_catch_locus);
+ append_to_statement_list (t, last);
- var_name = TREE_VALUE (catch_expr);
- var_type = TREE_VALUE (TREE_PURPOSE (catch_expr));
- if (TREE_CODE (var_name) == INDIRECT_REF)
- var_name = TREE_OPERAND (var_name, 0);
- if (TREE_CODE (var_type) == TYPE_DECL
- || TREE_CODE (var_type) == POINTER_TYPE)
- var_type = TREE_TYPE (var_type);
- catch_id = (var_type == TREE_TYPE (id_type));
+ t = next_sjlj_build_try_exit ();
+ annotate_with_locus (t, cur_try_context->end_catch_locus);
+ append_to_statement_list (t, last);
+ }
- if (!flag_objc_exceptions)
- fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
+ return catch_seq;
+}
- if (!(catch_id || TYPED_OBJECT (var_type)))
- fatal_error ("`@catch' parameter is not a known Objective-C class type");
+/* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
+ exception handling. We aim to build:
- /* Examine previous @catch clauses for the current @try block for
- superclasses of the 'var_type' class. */
- for (prev_catch = objc_catch_type; TREE_VALUE (prev_catch);
- prev_catch = TREE_CHAIN (prev_catch))
- {
- if (TREE_VALUE (prev_catch) == TREE_TYPE (id_type))
{
- warning ("Exception already handled by preceding `@catch(id)'");
- break;
+ struct _objc_exception_data _stack;
+ id volatile _rethrow = 0;
+ try
+ {
+ objc_exception_try_enter (&_stack);
+ if (_setjmp(&_stack.buf))
+ {
+ id _caught = objc_exception_extract(&_stack);
+ objc_exception_try_enter (&_stack);
+ if (_setjmp(&_stack.buf))
+ _rethrow = objc_exception_extract(&_stack);
+ else
+ CATCH-LIST
+ }
+ else
+ TRY-BLOCK
+ }
+ finally
+ {
+ if (!_rethrow)
+ objc_exception_try_exit(&_stack);
+ FINALLY-BLOCK
+ if (_rethrow)
+ objc_exception_throw(_rethrow);
+ }
}
- else if (!catch_id
- && objc_comptypes (TREE_VALUE (prev_catch), var_type, 0) == 1)
- warning ("Exception of type `%s *' already handled by `@catch (%s *)'",
- IDENTIFIER_POINTER (OBJC_TYPE_NAME (var_type)),
- IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_VALUE (prev_catch))));
- }
- objc_catch_type = tree_cons (NULL_TREE, var_type, objc_catch_type);
+ If CATCH-LIST is empty, we can omit all of the block containing
+ "_caught" except for the setting of _rethrow. Note the use of
+ a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
+ but handles goto and other exits from the block. */
- objc_exit_block ();
- c_finish_then ();
+static tree
+next_sjlj_build_try_catch_finally (void)
+{
+ tree rethrow_decl, stack_decl, t;
+ tree catch_seq, try_fin, bind;
- c_expand_start_else ();
- catch_count_stack->val++;
- if_stmt = c_begin_if_stmt ();
- if_nesting_count++;
+ /* Create the declarations involved. */
+ t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
+ stack_decl = objc_create_temporary_var (t);
+ cur_try_context->stack_decl = stack_decl;
- if (catch_id)
- cond = integer_one_node;
- else
- {
- cond = get_class_reference (OBJC_TYPE_NAME (var_type));
-
- func_params
- = tree_cons (NULL_TREE, cond,
- tree_cons (NULL_TREE,
- TREE_VALUE (objc_caught_exception),
- NULL_TREE));
- assemble_external (objc_exception_match_decl);
- cond = build_function_call (objc_exception_match_decl, func_params);
- }
+ rethrow_decl = objc_create_temporary_var (objc_id_type);
+ cur_try_context->rethrow_decl = rethrow_decl;
+ TREE_THIS_VOLATILE (rethrow_decl) = 1;
+ TREE_CHAIN (rethrow_decl) = stack_decl;
- c_expand_start_cond (c_common_truthvalue_conversion (cond),
- 0, if_stmt);
- objc_enter_block ();
- objc_declare_variable (RID_REGISTER, var_name,
- build_pointer_type (var_type),
- TREE_VALUE (objc_caught_exception));
-}
+ /* Build the outermost varible binding level. */
+ bind = build (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
+ annotate_with_locus (bind, cur_try_context->try_locus);
+ TREE_SIDE_EFFECTS (bind) = 1;
-void
-objc_build_catch_epilogue (void)
-{
- /* } else {
- _rethrowException = _caughtException;
- objc_exception_try_exit(&_stackExceptionData);
- }
- } else {
- _rethrowException = objc_exception_extract(&_stackExceptionData);
- }
- }
- } // end TRY-CATCH scope
- */
+ /* Initialize rethrow_decl. */
+ t = build (MODIFY_EXPR, void_type_node, rethrow_decl,
+ convert (objc_id_type, null_pointer_node));
+ annotate_with_locus (t, cur_try_context->try_locus);
+ append_to_statement_list (t, &BIND_EXPR_BODY (bind));
- objc_exit_block ();
- c_finish_then ();
+ /* Build the outermost TRY_FINALLY_EXPR. */
+ try_fin = build (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
+ annotate_with_locus (try_fin, cur_try_context->try_locus);
+ TREE_SIDE_EFFECTS (try_fin) = 1;
+ append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
- c_expand_start_else ();
- objc_enter_block ();
- c_expand_expr_stmt
- (build_modify_expr
- (TREE_VALUE (objc_rethrow_exception),
- NOP_EXPR,
- TREE_VALUE (objc_caught_exception)));
- objc_build_try_exit_fragment ();
- objc_exit_block ();
- while (catch_count_stack->val--)
+ /* Create the complete catch sequence. */
+ if (cur_try_context->catch_list)
{
- c_finish_else (); /* close off all the nested ifs ! */
- c_expand_end_cond ();
- if_nesting_count--;
+ tree caught_decl = objc_build_exc_ptr ();
+ catch_seq = build_stmt (BIND_EXPR, caught_decl, NULL, NULL);
+
+ t = next_sjlj_build_exc_extract (caught_decl);
+ append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
+
+ t = next_sjlj_build_enter_and_setjmp ();
+ COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (rethrow_decl);
+ COND_EXPR_ELSE (t) = next_sjlj_build_catch_list ();
+ append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
}
- val_stack_pop (&catch_count_stack);
- objc_caught_exception = TREE_CHAIN (objc_caught_exception);
+ else
+ catch_seq = next_sjlj_build_exc_extract (rethrow_decl);
+ annotate_with_locus (catch_seq, cur_try_context->end_try_locus);
- objc_build_extract_fragment ();
+ /* Build the main register-and-try if statement. */
+ t = next_sjlj_build_enter_and_setjmp ();
+ annotate_with_locus (t, cur_try_context->try_locus);
+ COND_EXPR_THEN (t) = catch_seq;
+ COND_EXPR_ELSE (t) = cur_try_context->try_body;
+ TREE_OPERAND (try_fin, 0) = t;
- objc_exit_block ();
- c_finish_else ();
- c_expand_end_cond ();
- if_nesting_count--;
- objc_exit_block ();
+ /* Build the complete FINALLY statement list. */
+ t = next_sjlj_build_try_exit ();
+ t = build_stmt (COND_EXPR,
+ lang_hooks.truthvalue_conversion (rethrow_decl),
+ NULL, t);
+ annotate_with_locus (t, cur_try_context->finally_locus);
+ append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
- /* Return to enclosing chain of @catch statements (if any). */
- while (TREE_VALUE (objc_catch_type))
- objc_catch_type = TREE_CHAIN (objc_catch_type);
- objc_catch_type = TREE_PURPOSE (objc_catch_type);
-}
+ append_to_statement_list (cur_try_context->finally_body,
+ &TREE_OPERAND (try_fin, 1));
-tree
-objc_build_finally_prologue ()
-{
- /* { // begin FINALLY scope
- if (!_rethrowException) {
- objc_exception_try_exit(&_stackExceptionData);
- } */
+ t = tree_cons (NULL, rethrow_decl, NULL);
+ t = build_function_call (objc_exception_throw_decl, t);
+ t = build_stmt (COND_EXPR,
+ lang_hooks.truthvalue_conversion (rethrow_decl),
+ t, NULL);
+ annotate_with_locus (t, cur_try_context->end_finally_locus);
+ append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
- tree blk = objc_enter_block ();
+ return bind;
+}
- tree if_stmt = c_begin_if_stmt ();
- if_nesting_count++;
+/* Called just after parsing the @try and its associated BODY. We now
+ must prepare for the tricky bits -- handling the catches and finally. */
- c_expand_start_cond (c_common_truthvalue_conversion
- (build_unary_op
- (TRUTH_NOT_EXPR,
- TREE_VALUE (objc_rethrow_exception), 0)),
- 0, if_stmt);
- objc_enter_block ();
- objc_build_try_exit_fragment ();
- objc_exit_block ();
- c_finish_then ();
- c_expand_end_cond ();
- if_nesting_count--;
+void
+objc_begin_try_stmt (location_t try_locus, tree body)
+{
+ struct objc_try_context *c = xcalloc (1, sizeof (*c));
+ c->outer = cur_try_context;
+ c->try_body = body;
+ c->try_locus = try_locus;
+ c->end_try_locus = input_location;
+ cur_try_context = c;
- return blk;
+ objc_init_exceptions ();
}
-tree
-objc_build_finally_epilogue (void)
+/* Called just after parsing "@catch (parm)". Open a binding level,
+ enter PARM into the binding level, and initialize it. Leave the
+ binding level open while the body of the compound statement is parsed. */
+
+void
+objc_begin_catch_clause (tree parm)
{
- /* if (_rethrowException) {
- objc_exception_throw(_rethrowException);
- }
- } // end FINALLY scope
- } */
+ tree compound, decl, type, t;
+
+ /* Begin a new scope that the entire catch clause will live in. */
+ compound = c_begin_compound_stmt (1);
- tree if_stmt = c_begin_if_stmt ();
- if_nesting_count++;
+ /* Turn the raw declarator/declspecs into a decl in the current scope. */
+ decl = define_decl (TREE_VALUE (TREE_PURPOSE (parm)),
+ TREE_PURPOSE (TREE_PURPOSE (parm)));
- c_expand_start_cond
- (c_common_truthvalue_conversion (TREE_VALUE (objc_rethrow_exception)),
- 0, if_stmt);
- objc_enter_block ();
- objc_build_throw_stmt (TREE_VALUE (objc_rethrow_exception));
- objc_exit_block ();
- c_finish_then ();
- c_expand_end_cond ();
- if_nesting_count--;
+ /* Since a decl is required here by syntax, don't warn if its unused. */
+ /* ??? As opposed to __attribute__((unused))? Anyway, this appears to
+ be what the previous objc implementation did. */
+ TREE_USED (decl) = 1;
- objc_exit_block ();
- objc_rethrow_exception = TREE_CHAIN (objc_rethrow_exception);
- objc_stack_exception_data = TREE_CHAIN (objc_stack_exception_data);
+ /* Verify that the type of the catch is valid. It must be a pointer
+ to an Objective-C class, or "id" (which is catch-all). */
+ type = TREE_TYPE (decl);
+ if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
+ type = NULL;
+ else if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
+ {
+ error ("@catch parameter is not a known Objective-C class type");
+ type = error_mark_node;
+ }
+ else if (cur_try_context->catch_list)
+ {
+ /* Examine previous @catch clauses and see if we've already
+ caught the type in question. */
+ tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
+ for (; !tsi_end_p (i); tsi_next (&i))
+ {
+ tree stmt = tsi_stmt (i);
+ t = CATCH_TYPES (stmt);
+ if (t == error_mark_node)
+ continue;
+ if (!t || objc_comptypes (TREE_TYPE (t), TREE_TYPE (type), 0) == 1)
+ {
+ warning ("exception of type %<%T%> will be caught",
+ TREE_TYPE (type));
+ warning ("%H by earlier handler for %<%T%>",
+ EXPR_LOCUS (stmt), TREE_TYPE (t ? t : objc_id_type));
+ break;
+ }
+ }
+ }
+
+ /* Record the data for the catch in the try context so that we can
+ finalize it later. */
+ t = build_stmt (CATCH_EXPR, type, compound);
+ cur_try_context->current_catch = t;
- val_stack_pop (&exc_binding_stack);
- return objc_exit_block ();
+ /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
+ t = objc_build_exc_ptr ();
+ t = convert (TREE_TYPE (decl), t);
+ t = build (MODIFY_EXPR, void_type_node, decl, t);
+ add_stmt (t);
}
-tree
-objc_build_try_catch_finally_stmt (int has_catch, int has_finally)
-{
- /* NB: The operative assumption here is that TRY_FINALLY_EXPR will
- deal with all exits from 'try_catch_blk' and route them through
- 'finally_blk'. */
- tree outer_blk = objc_build_finally_epilogue ();
- tree prec_stmt = TREE_CHAIN (TREE_CHAIN (COMPOUND_BODY (outer_blk)));
- tree try_catch_blk = TREE_CHAIN (prec_stmt), try_catch_expr;
- tree finally_blk = TREE_CHAIN (try_catch_blk), finally_expr;
- tree succ_stmt = TREE_CHAIN (finally_blk);
- tree try_finally_stmt, try_finally_expr;
+/* Called just after parsing the closing brace of a @catch clause. Close
+ the open binding level, and record a CATCH_EXPR for it. */
- if (!flag_objc_exceptions)
- fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
+void
+objc_finish_catch_clause (void)
+{
+ tree c = cur_try_context->current_catch;
+ cur_try_context->current_catch = NULL;
+ cur_try_context->end_catch_locus = input_location;
- /* It is an error to have a @try block without a @catch and/or @finally
- (even though sensible code can be generated nonetheless). */
+ CATCH_BODY (c) = c_end_compound_stmt (CATCH_BODY (c), 1);
+ append_to_statement_list (c, &cur_try_context->catch_list);
+}
- if (!has_catch && !has_finally)
- error ("`@try' without `@catch' or `@finally'");
+/* Called after parsing a @finally clause and its associated BODY.
+ Record the body for later placement. */
- /* We shall now do something truly disgusting. We shall remove the
- 'try_catch_blk' and 'finally_blk' from the 'outer_blk' statement
- chain, and replace them with a TRY_FINALLY_EXPR statement! If
- this doesn't work, we will have to learn (from Per/gcj) how to
- construct the 'outer_blk' lazily. */
-
- TREE_CHAIN (try_catch_blk) = TREE_CHAIN (finally_blk) = NULL_TREE;
- try_catch_expr = build1 (STMT_EXPR, void_type_node, try_catch_blk);
- TREE_SIDE_EFFECTS (try_catch_expr) = 1;
- finally_expr = build1 (STMT_EXPR, void_type_node, finally_blk);
- TREE_SIDE_EFFECTS (finally_expr) = 1;
- try_finally_expr = build (TRY_FINALLY_EXPR, void_type_node, try_catch_expr,
- finally_expr);
- TREE_SIDE_EFFECTS (try_finally_expr) = 1;
- try_finally_stmt = build_stmt (EXPR_STMT, try_finally_expr);
- TREE_CHAIN (prec_stmt) = try_finally_stmt;
- TREE_CHAIN (try_finally_stmt) = succ_stmt;
-
- return outer_blk; /* the whole enchilada */
+void
+objc_build_finally_clause (location_t finally_locus, tree body)
+{
+ cur_try_context->finally_body = body;
+ cur_try_context->finally_locus = finally_locus;
+ cur_try_context->end_finally_locus = input_location;
}
+/* Called to finalize a @try construct. */
+
void
-objc_build_synchronized_prologue (tree sync_expr)
+objc_finish_try_stmt (void)
{
- /* {
- id _eval_once = <sync_expr>;
- @try {
- objc_sync_enter( _eval_once ); */
+ struct objc_try_context *c = cur_try_context;
+ tree stmt;
- tree func_params;
+ if (c->catch_list == NULL && c->finally_body == NULL)
+ error ("`@try' without `@catch' or `@finally'");
- if (!flag_objc_exceptions)
- fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
-
- objc_enter_block ();
- objc_eval_once
- = tree_cons (NULL_TREE,
- objc_declare_variable (RID_AUTO,
- get_identifier (UTAG_EVALONCE_VAR),
- id_type,
- sync_expr),
- objc_eval_once);
- objc_build_try_prologue ();
- objc_enter_block ();
- func_params = tree_cons (NULL_TREE,
- TREE_VALUE (objc_eval_once),
- NULL_TREE);
+ /* If we're doing Darwin setjmp exceptions, build the big nasty. */
+ if (flag_objc_sjlj_exceptions)
+ {
+ if (!cur_try_context->finally_body)
+ {
+ cur_try_context->finally_locus = input_location;
+ cur_try_context->end_finally_locus = input_location;
+ }
+ stmt = next_sjlj_build_try_catch_finally ();
+ }
+ else
+ {
+ /* Otherwise, nest the CATCH inside a FINALLY. */
+ stmt = c->try_body;
+ if (c->catch_list)
+ {
+ stmt = build_stmt (TRY_CATCH_EXPR, stmt, c->catch_list);
+ annotate_with_locus (stmt, cur_try_context->try_locus);
+ }
+ if (c->finally_body)
+ {
+ stmt = build_stmt (TRY_FINALLY_EXPR, stmt, c->finally_body);
+ annotate_with_locus (stmt, cur_try_context->try_locus);
+ }
+ }
+ add_stmt (stmt);
- assemble_external (objc_sync_enter_decl);
- c_expand_expr_stmt (build_function_call
- (objc_sync_enter_decl, func_params));
+ cur_try_context = c->outer;
+ free (c);
}
tree
-objc_build_synchronized_epilogue (void)
+objc_build_throw_stmt (tree throw_expr)
{
- /* }
- @finally {
- objc_sync_exit( _eval_once );
- }
- } */
+ tree args;
- tree func_params;
+ objc_init_exceptions ();
- objc_exit_block ();
- objc_build_try_epilogue (0);
- objc_build_finally_prologue ();
- func_params = tree_cons (NULL_TREE, TREE_VALUE (objc_eval_once),
- NULL_TREE);
+ if (throw_expr == NULL)
+ {
+ /* If we're not inside a @catch block, there is no "current
+ exception" to be rethrown. */
+ if (cur_try_context == NULL
+ || cur_try_context->current_catch == NULL)
+ {
+ error ("%<@throw%> (rethrow) used outside of a @catch block");
+ return NULL_TREE;
+ }
+
+ /* Otherwise the object is still sitting in the EXC_PTR_EXPR
+ value that we get from the runtime. */
+ throw_expr = objc_build_exc_ptr ();
+ }
+
+ /* A throw is just a call to the runtime throw function with the
+ object as a parameter. */
+ args = tree_cons (NULL, throw_expr, NULL);
+ return add_stmt (build_function_call (objc_exception_throw_decl, args));
+}
+
+void
+objc_build_synchronized (location_t start_locus, tree mutex, tree body)
+{
+ tree args, call;
+
+ /* First lock the mutex. */
+ mutex = save_expr (mutex);
+ args = tree_cons (NULL, mutex, NULL);
+ call = build_function_call (objc_sync_enter_decl, args);
+ annotate_with_locus (call, start_locus);
+ add_stmt (call);
- assemble_external (objc_sync_exit_decl);
- c_expand_expr_stmt (build_function_call (objc_sync_exit_decl,
- func_params));
- objc_build_try_catch_finally_stmt (0, 1);
+ /* Build the mutex unlock. */
+ args = tree_cons (NULL, mutex, NULL);
+ call = build_function_call (objc_sync_exit_decl, args);
+ annotate_with_locus (call, input_location);
- return objc_exit_block ();
+ /* Put the that and the body in a TRY_FINALLY. */
+ objc_begin_try_stmt (start_locus, body);
+ objc_build_finally_clause (input_location, call);
+ objc_finish_try_stmt ();
}
+\f
/* Predefine the following data type:
struct _objc_exception_data
#endif
static void
-build_objc_exception_stuff (void)
+build_next_objc_exception_stuff (void)
{
tree field_decl, field_decl_chain, index, temp_type;
write_symbols = NO_DEBUG;
debug_hooks = &do_nothing_debug_hooks;
+
objc_exception_data_template
= start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
/* int buf[_JBLEN]; */
- index = build_index_type (build_int_2 (_JBLEN - 1, 0));
+ index = build_index_type (build_int_cst (NULL_TREE, _JBLEN - 1));
field_decl = create_builtin_decl (FIELD_DECL,
build_array_type (integer_type_node, index),
"buf");
/* void *pointers[4]; */
- index = build_index_type (build_int_2 (4 - 1, 0));
+ index = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
field_decl = create_builtin_decl (FIELD_DECL,
build_array_type (ptr_type_node, index),
"pointers");
finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
/* int _setjmp(...); */
- /* If the user includes <setjmp.h>, this shall be superceded by
+ /* If the user includes <setjmp.h>, this shall be superseded by
'int _setjmp(jmp_buf);' */
temp_type = build_function_type (integer_type_node, NULL_TREE);
objc_setjmp_decl
/* id objc_exception_extract(struct _objc_exception_data *); */
temp_type
- = build_function_type (id_type,
+ = build_function_type (objc_id_type,
tree_cons (NULL_TREE,
build_pointer_type (objc_exception_data_template),
- OBJC_VOID_AT_END));
+ void_list_node));
objc_exception_extract_decl
= builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
/* void objc_exception_try_enter(struct _objc_exception_data *); */
= build_function_type (void_type_node,
tree_cons (NULL_TREE,
build_pointer_type (objc_exception_data_template),
- OBJC_VOID_AT_END));
+ void_list_node));
objc_exception_try_enter_decl
= builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
objc_exception_try_exit_decl
= builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+ /* int objc_exception_match(id, id); */
+ temp_type
+ = build_function_type (integer_type_node,
+ tree_cons (NULL_TREE, objc_id_type,
+ tree_cons (NULL_TREE, objc_id_type,
+ void_list_node)));
+ objc_exception_match_decl
+ = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+ write_symbols = save_write_symbols;
+ debug_hooks = save_hooks;
+}
+
+static void
+build_objc_exception_stuff (void)
+{
+ tree noreturn_list, nothrow_list, temp_type;
+
+ noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
+ nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
+
/* void objc_exception_throw(id) __attribute__((noreturn)); */
/* void objc_sync_enter(id); */
/* void objc_sync_exit(id); */
temp_type = build_function_type (void_type_node,
- tree_cons (NULL_TREE, id_type,
- OBJC_VOID_AT_END));
+ tree_cons (NULL_TREE, objc_id_type,
+ void_list_node));
objc_exception_throw_decl
- = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
- DECL_ATTRIBUTES (objc_exception_throw_decl)
- = tree_cons (get_identifier ("noreturn"), NULL_TREE, NULL_TREE);
+ = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
+ noreturn_list);
objc_sync_enter_decl
- = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
+ NULL, nothrow_list);
objc_sync_exit_decl
- = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
- /* int objc_exception_match(id, id); */
- temp_type = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, id_type,
- tree_cons (NULL_TREE, id_type,
- OBJC_VOID_AT_END)));
- objc_exception_match_decl
- = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
-
- write_symbols = save_write_symbols;
- debug_hooks = save_hooks;
+ = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
+ NULL, nothrow_list);
}
+
/* struct <classname> {
struct objc_class *isa;
...
TREE_STATIC_TEMPLATE (uprivate_record) = 1;
}
- instance_type
+ objc_instance_type
= groktypename (build_tree_list (build_tree_list (NULL_TREE,
uprivate_record),
build1 (INDIRECT_REF, NULL_TREE,
decl_specs = build_tree_list (NULL_TREE, list_type);
field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
- build_int_2 (size, 0));
+ build_int_cst (NULL_TREE, size), NULL_TREE, NULL_TREE);
field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
chainon (field_decl_chain, field_decl);
decl_specs, 1, NULL_TREE);
DECL_CONTEXT (decl) = NULL_TREE;
- initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
+ initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
initlist = tree_cons (NULL_TREE, list, initlist);
finish_decl (decl, objc_build_constructor (type, nreverse (initlist)),
TREE_TYPE (refs_expr) = cast_type2;
}
else
- refs_expr = build_int_2 (0, 0);
+ refs_expr = build_int_cst (NULL_TREE, 0);
/* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
by generate_method_descriptors, which is called above. */
/* Filling the "isa" in with one allows the runtime system to
detect that the version change...should remove before final release. */
- expr = build_int_2 (PROTOCOL_VERSION, 0);
- TREE_TYPE (expr) = cast_type;
+ expr = build_int_cst (cast_type, PROTOCOL_VERSION);
initlist = tree_cons (NULL_TREE, expr, initlist);
initlist = tree_cons (NULL_TREE, protocol_name, initlist);
initlist = tree_cons (NULL_TREE, protocol_list, initlist);
if (!instance_methods)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
}
if (!class_methods)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
expr = build_unary_op (ADDR_EXPR, class_methods, 0);
/* static struct objc_class _OBJC_METACLASS_<my_name>; */
UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
objc_class_template);
+
+ mark_decl_referenced (UOBJC_CLASS_decl);
+ mark_decl_referenced (UOBJC_METACLASS_decl);
/* Pre-build the following entities - for speed/convenience. */
t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
- if (!comptypes (t1, t2, false)
+ if (TREE_VALUE (TREE_VALUE (rawimpdecls)))
+ {
+ /* t1 is the bit-field type, so t2 must be converted to the
+ bit-field type for comparison as well. */
+ unsigned HOST_WIDE_INT width
+ = tree_low_cst (TREE_VALUE (TREE_VALUE (rawimpdecls)), 1);
+ if (width != TYPE_PRECISION (t2))
+ t2 = build_nonstandard_integer_type (width, TYPE_UNSIGNED (t2));
+ }
+
+ if (!comptypes (t1, t2)
|| !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
TREE_VALUE (TREE_VALUE (rawimpdecls))))
{
field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
field_decl_chain = field_decl;
+#ifdef OBJCPLUS
+ /* struct objc_class *super_class; */
+#else
/* struct objc_class *class; */
+#endif
decl_specs = get_identifier (UTAG_CLASS);
decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
+#ifdef OBJCPLUS
+ field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
+#else
field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
+#endif
field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
chainon (field_decl_chain, field_decl);
decl_specs = build_tree_list (NULL_TREE, list_type);
field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
- build_int_2 (size, 0));
+ build_int_cst (NULL_TREE, size), NULL_TREE, NULL_TREE);
field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
chainon (field_decl_chain, field_decl);
decl_specs = build_tree_list (NULL_TREE, list_type);
field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
- build_int_2 (size, 0));
+ build_int_cst (NULL_TREE, size), NULL_TREE, NULL_TREE);
field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
chainon (field_decl_chain, field_decl);
ivar);
else
/* Unnamed bit-field ivar (yuck). */
- ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
+ ivar = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), ivar);
/* Set type. */
encode_field_decl (field_decl,
decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
decl_specs, 1, NULL_TREE);
- initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
+ initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
initlist = tree_cons (NULL_TREE, list, initlist);
finish_decl (decl,
/* Count only the fields occurring in T. */
static int
-ivar_list_length (t)
- tree t;
+ivar_list_length (tree t)
{
int count = 0;
decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
decl_specs, 1, NULL_TREE);
- initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
- initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
+ initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, size), initlist);
initlist = tree_cons (NULL_TREE, list, initlist);
finish_decl (decl,
size++;
/* Build initializer. */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), NULL_TREE);
- e = build_int_2 (size, 0);
- TREE_TYPE (e) = cast_type;
+ e = build_int_cst (cast_type, size);
initlist = tree_cons (NULL_TREE, e, initlist);
for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
expr_decl = build_nt (ARRAY_REF,
synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
i_or_p),
- build_int_2 (size + 2, 0));
+ build_int_cst (NULL_TREE, size + 2), NULL_TREE, NULL_TREE);
else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
expr_decl = build_nt (ARRAY_REF,
synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
i_or_p),
- build_int_2 (size + 2, 0));
+ build_int_cst (NULL_TREE, size + 2), NULL_TREE, NULL_TREE);
else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
expr_decl
= build_nt (ARRAY_REF,
synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
i_or_p),
- build_int_2 (size + 2, 0));
+ build_int_cst (NULL_TREE, size + 2), NULL_TREE, NULL_TREE);
else
abort ();
initlist = tree_cons (NULL_TREE, class_name, initlist);
if (!instance_methods)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
initlist = tree_cons (NULL_TREE, expr, initlist);
}
if (!class_methods)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
expr = build_unary_op (ADDR_EXPR, class_methods, 0);
/* protocol_list = */
if (!protocol_list)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
tree cast_type2 = groktypename
initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
/* version = */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
/* info = */
- initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, status), initlist);
/* instance_size = */
initlist = tree_cons (NULL_TREE, size, initlist);
/* objc_ivar_list = */
if (!ivar_list)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
/* objc_method_list = */
if (!dispatch_table)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
if (flag_next_runtime)
/* method_cache = */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
/* dtable = */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
/* subclass_list = */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
/* sibling_class = */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
}
/* protocol_list = */
if (! protocol_list)
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
tree cast_type2
if (flag_next_runtime)
/* sel_id = NULL */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
/* gc_object_type = NULL */
- initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
return objc_build_constructor (type, nreverse (initlist));
}
+/* Retrieve category interface CAT_NAME (if any) associated with CLASS. */
+
+static inline tree
+lookup_category (tree class, tree cat_name)
+{
+ tree category = CLASS_CATEGORY_LIST (class);
+
+ while (category && CLASS_SUPER_NAME (category) != cat_name)
+ category = CLASS_CATEGORY_LIST (category);
+ return category;
+}
+
/* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
static void
class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
- category = CLASS_CATEGORY_LIST (implementation_template);
-
- /* find the category interface from the class it is associated with */
- while (category)
- {
- if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
- break;
- category = CLASS_CATEGORY_LIST (category);
- }
+ category = lookup_category (implementation_template,
+ CLASS_SUPER_NAME (cat));
if (category && CLASS_PROTOCOL_LIST (category))
{
super_expr = build_c_cast (cast_type, super_expr); /* cast! */
}
else
- super_expr = build_int_2 (0, 0);
+ super_expr = build_int_cst (NULL_TREE, 0);
root_expr = add_objc_string (my_root_id, class_names);
root_expr = build_c_cast (cast_type, root_expr); /* cast! */
Out: an instance of "keyword_decl". */
tree
-build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
+objc_build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
{
tree keyword_decl;
/* Receiver type. */
if (flag_next_runtime && superflag)
- arglist = build_tree_list (NULL_TREE, super_type);
+ arglist = build_tree_list (NULL_TREE, objc_super_type);
else if (context == METHOD_DEF)
arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
else
- arglist = build_tree_list (NULL_TREE, id_type);
+ arglist = build_tree_list (NULL_TREE, objc_id_type);
/* Selector type - will eventually change to `int'. */
- chainon (arglist, build_tree_list (NULL_TREE, selector_type));
+ chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
/* No actual method prototype given -- assume that remaining arguments
are `...'. */
if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
/* We have a `, ...' immediately following the selector,
- finalize the arglist...simulate get_parm_info (0). */
+ finalize the arglist...simulate get_parm_info (true). */
;
else if (METHOD_ADD_ARGS (meth))
{
chainon (arglist, add_arg_list);
}
else
- /* finalize the arglist...simulate get_parm_info (1) */
- chainon (arglist, OBJC_VOID_AT_END);
+ /* finalize the arglist...simulate get_parm_info (false) */
+ chainon (arglist, void_list_node);
return arglist;
}
static tree
-check_duplicates (hash hsh, int methods)
+check_duplicates (hash hsh, int methods, int is_class)
{
tree meth = NULL_TREE;
/* We have two or more methods with the same name but
different types. */
attr loop;
- char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
warning ("multiple %s named `%c%s' found",
- methods ? "methods" : "selectors", type,
+ methods ? "methods" : "selectors",
+ (is_class ? '+' : '-'),
IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
- warn_with_method (methods ? "using" : "found", type, meth);
+ warn_with_method (methods ? "using" : "found",
+ ((TREE_CODE (meth) == INSTANCE_METHOD_DECL)
+ ? '-'
+ : '+'),
+ meth);
for (loop = hsh->list; loop; loop = loop->next)
- warn_with_method ("also found", type, loop->value);
+ warn_with_method ("also found",
+ ((TREE_CODE (loop->value) == INSTANCE_METHOD_DECL)
+ ? '-'
+ : '+'),
+ loop->value);
}
}
return meth;
}
/* If RECEIVER is a class reference, return the identifier node for
- the referenced class. RECEIVER is created by get_class_reference,
+ the referenced class. RECEIVER is created by objc_get_class_reference,
so we check the exact form created depending on which runtimes are
used. */
&& (exp = TREE_OPERAND (exp, 0))
&& TREE_CODE (exp) == FUNCTION_DECL
/* For some reason, we sometimes wind up with multiple FUNCTION_DECL
- prototypes for objc_get_class(). Thankfuly, they seem to share the
+ prototypes for objc_get_class(). Thankfully, they seem to share the
same function type. */
&& TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
(*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
tree
-build_message_expr (tree mess)
+objc_build_message_expr (tree mess)
{
tree receiver = TREE_PURPOSE (mess);
tree sel_name;
return finish_message_expr (receiver, sel_name, method_params);
}
+/* Look up method SEL_NAME that would be suitable for receiver
+ of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
+ nonzero), and report on any duplicates. */
+
static tree
-lookup_method_in_hash_lists (tree sel_name)
+lookup_method_in_hash_lists (tree sel_name, int is_class)
{
- hash method_prototype = hash_lookup (nst_method_hash_list,
- sel_name);
+ hash method_prototype = NULL;
+
+ if (!is_class)
+ method_prototype = hash_lookup (nst_method_hash_list,
+ sel_name);
if (!method_prototype)
- method_prototype = hash_lookup (cls_method_hash_list,
- sel_name);
+ {
+ method_prototype = hash_lookup (cls_method_hash_list,
+ sel_name);
+ is_class = 1;
+ }
- return check_duplicates (method_prototype, 1);
+ return check_duplicates (method_prototype, 1, is_class);
}
/* The 'finish_message_expr' routine is called from within
- 'build_message_expr' for non-template functions. In the case of
+ 'objc_build_message_expr' for non-template functions. In the case of
C++ template functions, it is called from 'build_expr_from_tree'
(in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded. */
finish_message_expr (tree receiver, tree sel_name, tree method_params)
{
tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
- tree selector, retval, is_class;
+ tree selector, retval, class_tree;
int self, super, have_cast;
/* Extract the receiver of the message, as well as its type
/* If the receiver is a class object, retrieve the corresponding
@interface, if one exists. */
- is_class = receiver_is_class_object (receiver, self, super);
+ class_tree = receiver_is_class_object (receiver, self, super);
/* Now determine the receiver type (if an explicit cast has not been
provided). */
if (!have_cast)
{
- if (is_class)
- rtype = lookup_interface (is_class);
+ if (class_tree)
+ rtype = lookup_interface (class_tree);
/* Handle `self' and `super'. */
else if (super)
{
|| TREE_TYPE (rtype) == TREE_TYPE (objc_class_type))
{
if (!rtype)
- rtype = xref_tag (RECORD_TYPE, is_class);
+ rtype = xref_tag (RECORD_TYPE, class_tree);
else if (IS_ID (rtype))
{
rprotos = TYPE_PROTOCOL_LIST (rtype);
rtype = NULL_TREE;
}
else
- is_class = TYPE_NAME (rtype) = get_identifier ("Class");
+ class_tree = TYPE_NAME (rtype) = get_identifier ("Class");
if (rprotos)
method_prototype
= lookup_method_in_protocol_list (rprotos, sel_name,
- is_class != NULL_TREE);
+ class_tree != NULL_TREE);
if (!method_prototype && !rprotos)
method_prototype
- = (is_class
- ? check_duplicates (hash_lookup (cls_method_hash_list, sel_name), 1)
- : lookup_method_in_hash_lists (sel_name));
+ = lookup_method_in_hash_lists (sel_name,
+ class_tree != NULL_TREE);
}
else
{
in the published @interface for the class (and its
superclasses). */
method_prototype
- = lookup_method_static (rtype, sel_name, is_class != NULL_TREE);
+ = lookup_method_static (rtype, sel_name, class_tree != NULL_TREE);
/* If the method was not found in the @interface, it may still
exist locally as part of the @implementation. */
== OBJC_TYPE_NAME (rtype))
method_prototype
= lookup_method
- ((is_class
+ ((class_tree
? CLASS_CLS_METHODS (objc_implementation_context)
: CLASS_NST_METHODS (objc_implementation_context)),
sel_name);
if (!method_prototype && rprotos)
method_prototype
= lookup_method_in_protocol_list (rprotos, sel_name,
- is_class != NULL_TREE);
+ class_tree != NULL_TREE);
}
else
{
if (rtype)
warning ("`%s' may not respond to `%c%s'",
IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
- (is_class ? '+' : '-'),
+ (class_tree ? '+' : '-'),
IDENTIFIER_POINTER (sel_name));
if (rprotos)
warning ("`%c%s' not implemented by protocol(s)",
- (is_class ? '+' : '-'),
+ (class_tree ? '+' : '-'),
IDENTIFIER_POINTER (sel_name));
if (!warn_missing_methods)
{
(!flag_next_runtime || flag_nil_receivers
? umsg_decl
: umsg_nonnil_decl));
- tree rcv_p = (super_flag ? super_type : id_type);
+ tree rcv_p = (super_flag ? objc_super_type : objc_id_type);
/* If a prototype for the method to be called exists, then cast
the sender's return type and arguments to match that of the method.
tree ret_type
= (method_prototype
? groktypename (TREE_TYPE (method_prototype))
- : id_type);
+ : objc_id_type);
tree sender_cast
= build_pointer_type
(build_function_type
(ret_type,
get_arg_type_list
(method_prototype, METHOD_REF, super_flag)));
+ tree method, t;
lookup_object = build_c_cast (rcv_p, lookup_object);
+
+ /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
+ lookup_object = save_expr (lookup_object);
if (flag_next_runtime)
{
-#ifdef STRUCT_VALUE
/* If we are returning a struct in memory, and the address
of that memory location is passed as a hidden first
argument, then change which messenger entry point this
expr will call. NB: Note that sender_cast remains
unchanged (it already has a struct return type). */
- if ((TREE_CODE (ret_type) == RECORD_TYPE
- || TREE_CODE (ret_type) == UNION_TYPE)
-#if defined (DEFAULT_PCC_STRUCT_RETURN) && DEFAULT_PCC_STRUCT_RETURN == 0
- && RETURN_IN_MEMORY (ret_type)
-#endif
- && STRUCT_VALUE == 0)
+ if (!targetm.calls.struct_value_rtx (0, 0)
+ && (TREE_CODE (ret_type) == RECORD_TYPE
+ || TREE_CODE (ret_type) == UNION_TYPE)
+ && targetm.calls.return_in_memory (ret_type, 0))
sender = (super_flag ? umsg_super_stret_decl :
flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
-#endif
+
method_params = tree_cons (NULL_TREE, lookup_object,
tree_cons (NULL_TREE, selector,
method_params));
- TREE_USED (sender) = 1;
- assemble_external (sender);
- /* We want to cast the sender, not convert it. */
- return build_function_call (build_c_cast (sender_cast, sender),
- method_params);
+ method = build_fold_addr_expr (sender);
}
else
{
/* This is the portable (GNU) way. */
- tree method, object;
+ tree object;
/* First, call the lookup function to get a pointer to the method,
- then cast the pointer, then call it with the method arguments.
- Use SAVE_EXPR to avoid evaluating the receiver twice. */
- lookup_object = save_expr (lookup_object);
+ then cast the pointer, then call it with the method arguments. */
+
object = (super_flag ? self_decl : lookup_object);
- TREE_USED (sender) = 1;
- assemble_external (sender);
- method
- = build_function_call (sender,
- tree_cons (NULL_TREE, lookup_object,
- tree_cons (NULL_TREE, selector,
- NULL_TREE)));
+
+ t = tree_cons (NULL_TREE, selector, NULL_TREE);
+ t = tree_cons (NULL_TREE, lookup_object, t);
+ method = build_function_call (sender, t);
/* Pass the object to the method. */
- TREE_USED (method) = 1;
- assemble_external (method);
- return build_function_call
- (build_c_cast (sender_cast, method),
- tree_cons (NULL_TREE, object,
- tree_cons (NULL_TREE, selector, method_params)));
+ method_params = tree_cons (NULL_TREE, object,
+ tree_cons (NULL_TREE, selector,
+ method_params));
}
+
+ /* ??? Selector is not at this point something we can use inside
+ the compiler itself. Set it to garbage for the nonce. */
+ t = build (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
+ return build_function_call (t, method_params);
}
\f
static void
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
- make_decl_rtl (decl, 0);
+ make_decl_rtl (decl);
pushdecl_top_level (decl);
}
/* This function is called by the parser when (and only when) a
@protocol() expression is found, in order to compile it. */
tree
-build_protocol_expr (tree protoname)
+objc_build_protocol_expr (tree protoname)
{
tree expr;
tree p = lookup_protocol (protoname);
expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
- TREE_TYPE (expr) = protocol_type;
+ /* ??? Ideally we'd build the reference with objc_protocol_type directly,
+ if we have it, rather than converting it here. */
+ expr = convert (objc_protocol_type, expr);
/* The @protocol() expression is being compiled into a pointer to a
statically allocated instance of the Protocol class. To become
if (! flag_next_runtime)
{
/* This type is a struct containing the fields of a Protocol
- object. (Cfr. protocol_type instead is the type of a pointer
+ object. (Cfr. objc_protocol_type instead is the type of a pointer
to such a struct). */
tree protocol_struct_type = xref_tag
(RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
is found, in order to compile it. It is only called by the parser
and only to compile a @selector(). */
tree
-build_selector_expr (tree selnamelist)
+objc_build_selector_expr (tree selnamelist)
{
tree selname;
}
tree
-build_encode_expr (tree type)
+objc_build_encode_expr (tree type)
{
tree result;
const char *string;
paradigm. */
warning ("instance variable `%s' accessed in class method",
IDENTIFIER_POINTER (id));
- TREE_TYPE (self_decl) = instance_type; /* cast */
+ TREE_TYPE (self_decl) = objc_instance_type; /* cast */
}
return build_component_ref (build_indirect_ref (self_decl, "->"), id);
return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
}
+/* Add the method to the hash list if it doesn't contain an identical
+ method already. */
+static void
+add_method_to_hash_list (hash *hash_list, tree method)
+{
+ hash hsh;
+
+ if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
+ {
+ /* Install on a global chain. */
+ hash_enter (hash_list, method);
+ }
+ else
+ {
+ /* Check types against those; if different, add to a list. */
+ attr loop;
+ int already_there = comp_proto_with_proto (method, hsh->key);
+ for (loop = hsh->list; !already_there && loop; loop = loop->next)
+ already_there |= comp_proto_with_proto (method, loop->value);
+ if (!already_there)
+ hash_add_attr (hsh, method);
+ }
+}
+
tree
-add_method (tree class, tree method, int is_class)
+objc_add_method (tree class, tree method, int is_class)
{
tree mth;
- hash hsh;
if (!(mth = lookup_method (is_class ? CLASS_CLS_METHODS (class) : CLASS_NST_METHODS (class), method)))
{
}
else
{
- /* When processing an @interface for a class or category, give hard errors on methods with
- identical selectors but differing argument and/or return types. We do not do this for
- @implementations, because C/C++ will do it for us (i.e., there will be
- duplicate function definition errors). */
+ /* When processing an @interface for a class or category, give hard
+ errors on methods with identical selectors but differing argument
+ and/or return types. We do not do this for @implementations, because
+ C/C++ will do it for us (i.e., there will be duplicate function
+ definition errors). */
if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
|| TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
&& !comp_proto_with_proto (method, mth))
is_class ? '+' : '-', IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
}
- if (!(hsh = hash_lookup (is_class
- ? cls_method_hash_list
- : nst_method_hash_list, METHOD_SEL_NAME (method))))
- {
- /* Install on a global chain. */
- hash_enter (is_class ? cls_method_hash_list : nst_method_hash_list, method);
- }
+ if (is_class)
+ add_method_to_hash_list (cls_method_hash_list, method);
else
{
- /* Check types against those; if different, add to a list. */
- attr loop;
- int already_there = comp_proto_with_proto (method, hsh->key);
- for (loop = hsh->list; !already_there && loop; loop = loop->next)
- already_there |= comp_proto_with_proto (method, loop->value);
- if (!already_there)
- hash_add_attr (hsh, method);
+ add_method_to_hash_list (nst_method_hash_list, method);
+
+ /* Instance methods in root classes (and categories thereof)
+ may acts as class methods as a last resort. */
+ if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE
+ || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
+ class = lookup_interface (CLASS_NAME (class));
+
+ if (TREE_CODE (class) != PROTOCOL_INTERFACE_TYPE
+ && !CLASS_SUPER_NAME (class))
+ add_method_to_hash_list (cls_method_hash_list, method);
}
+
return method;
}
add_category (tree class, tree category)
{
/* Put categories on list in reverse order. */
- tree cat = CLASS_CATEGORY_LIST (class);
+ tree cat = lookup_category (class, CLASS_SUPER_NAME (category));
- while (cat)
+ if (cat)
{
- if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
-#ifdef OBJCPLUS
- error ("duplicate interface declaration for category `%s(%s)'",
-#else
- warning ("duplicate interface declaration for category `%s(%s)'",
-#endif
- IDENTIFIER_POINTER (CLASS_NAME (class)),
- IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
- cat = CLASS_CATEGORY_LIST (cat);
+ warning ("duplicate interface declaration for category `%s(%s)'",
+ IDENTIFIER_POINTER (CLASS_NAME (class)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
+ }
+ else
+ {
+ CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
+ CLASS_CATEGORY_LIST (class) = category;
}
-
- CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
- CLASS_CATEGORY_LIST (class) = category;
}
/* Called after parsing each instance variable declaration. Necessary to
int
is_private (tree decl)
{
- if (TREE_PRIVATE (decl)
- && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
- {
- error ("instance variable `%s' is declared private",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- return 1;
- }
- else
- return 0;
+ return (TREE_PRIVATE (decl)
+ && ! is_ivar (CLASS_IVARS (implementation_template),
+ DECL_NAME (decl)));
}
/* We have an instance variable reference;, check to see if it is public. */
int
-is_public (tree expr, tree identifier)
+objc_is_public (tree expr, tree identifier)
{
tree basetype = TREE_TYPE (expr);
enum tree_code code = TREE_CODE (basetype);
== CATEGORY_IMPLEMENTATION_TYPE))
&& (CLASS_NAME (objc_implementation_context)
== OBJC_TYPE_NAME (basetype))))
- return ! is_private (decl);
+ {
+ int private = is_private (decl);
+
+ if (private)
+ error ("instance variable `%s' is declared private",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ return !private;
+ }
/* The 2.95.2 compiler sometimes allowed C functions to access
non-@public ivars. We will let this slide for now... */
}
class = make_node (code);
- TYPE_BINFO (class) = make_tree_vec (CLASS_BINFO_ELTS);
+ TYPE_LANG_SLOT_1 (class) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
CLASS_NAME (class) = class_name;
CLASS_SUPER_NAME (class) = super_name;
CLASS_CLS_METHODS (class) = NULL_TREE;
- if (! is_class_name (class_name)
+ if (! objc_is_class_name (class_name)
&& (decl = lookup_name (class_name)))
{
error ("`%s' redeclared as different kind of symbol",
else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
{
- tree category = CLASS_CATEGORY_LIST (implementation_template);
-
- /* Find the category interface from the class it is associated with. */
- while (category)
- {
- if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
- break;
- category = CLASS_CATEGORY_LIST (category);
- }
+ tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
if (category)
{
{
tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
- TYPE_BINFO (protocol) = make_tree_vec (2);
+ TYPE_LANG_SLOT_1 (protocol)
+ = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
PROTOCOL_NAME (protocol) = name;
PROTOCOL_LIST (protocol) = NULL_TREE;
add_protocol (protocol);
if (!protocol)
{
protocol = make_node (code);
- TYPE_BINFO (protocol) = make_tree_vec (2);
+ TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
PROTOCOL_NAME (protocol) = name;
PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
{
switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
{
- case 8: c = TREE_UNSIGNED (type) ? 'C' : 'c'; break;
- case 16: c = TREE_UNSIGNED (type) ? 'S' : 's'; break;
+ case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
+ case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
case 32:
if (type == long_unsigned_type_node
|| type == long_integer_type_node)
- c = TREE_UNSIGNED (type) ? 'L' : 'l';
+ c = TYPE_UNSIGNED (type) ? 'L' : 'l';
else
- c = TREE_UNSIGNED (type) ? 'I' : 'i';
+ c = TYPE_UNSIGNED (type) ? 'I' : 'i';
break;
- case 64: c = TREE_UNSIGNED (type) ? 'Q' : 'q'; break;
+ case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
default: abort ();
}
obstack_1grow (&util_obstack, c);
build1 (INDIRECT_REF, NULL_TREE, self_id)),
unused_list));
- decl_specs = build_tree_list (NULL_TREE,
- xref_tag (RECORD_TYPE,
- get_identifier (TAG_SELECTOR)));
+ decl_specs = build_tree_list (NULL_TREE, TREE_TYPE (objc_selector_type));
push_parm_decl (build_tree_list
(build_tree_list (decl_specs,
build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
UOBJC_SUPER_decl = NULL_TREE;
/* Must be called BEFORE start_function. */
- pushlevel (0);
+ push_scope ();
+ declare_parm_level ();
/* Generate prototype declarations for arguments..."new-style". */
synth_self_and_ucmd_args ();
function1_template = make_node (FUNCTION_TYPE);
/* Install argument types - normally set by build_function_type. */
- TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
+ TYPE_ARG_TYPES (function1_template)
+ = get_arg_type_list (proto, METHOD_DEF, 0);
/* install return type */
TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
- return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template,
- false);
+ return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
}
/* Return 1 if TYPE1 is equivalent to TYPE2. */
METHOD_SEL_NAME (method),
TREE_CODE (method) == CLASS_METHOD_DECL);
- if (proto && ! comp_method_with_proto (method, proto))
+ if (proto)
{
- char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
+ if (!comp_method_with_proto (method, proto))
+ {
+ char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
- warn_with_method ("conflicting types for", type, method);
- warn_with_method ("previous declaration of", type, proto);
+ warn_with_method ("conflicting types for", type, method);
+ warn_with_method ("previous declaration of", type, proto);
+ }
+ }
+ else
+ {
+ /* We have a method @implementation even though we did not
+ see a corresponding @interface declaration (which is allowed
+ by Objective-C rules). Go ahead and place the method in
+ the @interface anyway, so that message dispatch lookups
+ will see it. */
+ tree interface = implementation_template;
+
+ if (TREE_CODE (objc_implementation_context)
+ == CATEGORY_IMPLEMENTATION_TYPE)
+ interface = lookup_category
+ (interface,
+ CLASS_SUPER_NAME (objc_implementation_context));
+
+ if (interface)
+ objc_add_method (interface, copy_node (method),
+ TREE_CODE (method) == CLASS_METHOD_DECL);
}
}
}
if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
/* We have a `, ...' immediately following the selector. */
- parmlist = get_parm_info (0);
+ parmlist = get_parm_info (/*ellipsis=*/true);
else
- parmlist = get_parm_info (1); /* place a `void_at_end' */
+ parmlist = get_parm_info (/*ellipsis=*/false);
#ifndef OBJCPLUS
/* Set self_decl from the first argument...this global is used by
self_decl = TREE_PURPOSE (parmlist);
#endif /* !OBJCPLUS */
- poplevel (0, 0, 0);
+ pop_scope ();
really_start_method (objc_method_context, parmlist);
store_parm_decls ();
}
TREE_USED (UOBJC_SUPER_decl) = 1;
DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
- UOBJC_SUPER_scope = get_current_scope ();
+ UOBJC_SUPER_scope = objc_get_current_scope ();
}
/* Set receiver to self. */
super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
- super_expr_list = build_tree_list (NULL_TREE, super_expr);
+ super_expr_list = super_expr;
/* Set class to begin searching. */
+#ifdef OBJCPLUS
+ super_expr = build_component_ref (UOBJC_SUPER_decl,
+ get_identifier ("super_class"));
+#else
super_expr = build_component_ref (UOBJC_SUPER_decl,
get_identifier ("class"));
+#endif
if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
{
if (flag_next_runtime && !flag_zero_link)
{
- super_class = get_class_reference (super_name);
+ super_class = objc_get_class_reference (super_name);
if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
/* If we are in a class method, we must retrieve the
_metaclass_ for the current class, pointed at by
super_class));
}
- chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
+ super_expr_list = build_compound_expr (super_expr_list, super_expr);
super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
- chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
+ super_expr_list = build_compound_expr (super_expr_list, super_expr);
- return build_compound_expr (super_expr_list);
+ return super_expr_list;
}
else
{
objc_clear_super_receiver (void)
{
if (objc_method_context
- && UOBJC_SUPER_scope == get_current_scope ()) {
+ && UOBJC_SUPER_scope == objc_get_current_scope ()) {
UOBJC_SUPER_decl = 0;
UOBJC_SUPER_scope = 0;
}
dispatched, so suppress all thoughts of doing so. */
DECL_INLINE (current_function_decl) = 0;
DECL_UNINLINABLE (current_function_decl) = 1;
- current_function_cannot_inline = "methods cannot be inlined";
finish_function ();
lang_expand_function_end = NULL;
else if (code == POINTER_TYPE)
{
strcpy (tmpbuf, "*");
- if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
+ if (TYPE_READONLY (decl) || TYPE_VOLATILE (decl))
{
- if (TREE_READONLY (decl))
+ if (TYPE_READONLY (decl))
strcat (tmpbuf, " const");
if (TYPE_VOLATILE (decl))
strcat (tmpbuf, " volatile");
else
{
/* Type qualifiers. */
- if (TREE_READONLY (declspecs))
+ if (TYPE_READONLY (declspecs))
strcat (buf, "const ");
if (TYPE_VOLATILE (declspecs))
strcat (buf, "volatile ");
objc_implementation_context = NULL_TREE;
}
- generate_forward_declaration_to_string_table ();
-
/* Process the static instances here because initialization of objc_symtab
depends on them. */
if (objc_static_instances)
for (slot = 0; slot < SIZEHASHTABLE; slot++)
{
for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
- check_duplicates (hsh, 0);
+ check_duplicates (hsh, 0, 1);
for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
- check_duplicates (hsh, 0);
+ check_duplicates (hsh, 0, 1);
}
}
TREE_PUBLIC (decl) = 1;
pushdecl (decl);
- rest_of_decl_compilation (decl, 0, 0, 0);
+ rest_of_decl_compilation (decl, 0, 0);
/* Make a decl for the address. */
sprintf (string, "%sobjc_class_ref_%s",
TREE_USED (decl) = 1;
pushdecl (decl);
- rest_of_decl_compilation (decl, 0, 0, 0);
+ rest_of_decl_compilation (decl, 0, 0);
}
static void
{
tree decl, init;
- init = build_int_2 (0, 0);
- TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
+ init = build_int_cst (c_common_type_for_size (BITS_PER_WORD, 1), 0);
decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
TREE_PUBLIC (decl) = 1;
TREE_READONLY (decl) = 1;
}
}
\f
-/* The Fix-and-Countinue functionality available in Mac OS X 10.3 and
+/* The Fix-and-Continue functionality available in Mac OS X 10.3 and
later requires that ObjC translation units participating in F&C be
specially marked. The following routine accomplishes this. */
tree_cons (NULL_TREE,
build_array_type
(integer_type_node,
- build_index_type (build_int_2 (1, 0))),
+ build_index_type (build_int_cst (NULL_TREE, 1))),
sc_spec),
1,
NULL_TREE);
- initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
- initlist = tree_cons (NULL_TREE, build_int_2 (1, 0), initlist);
+ initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 1), initlist);
initlist = build_constructor (TREE_TYPE (decl), nreverse (initlist));
TREE_USED (decl) = DECL_IGNORED_P (decl) = DECL_ARTIFICIAL (decl) = 1;
/* Look up ID as an instance variable. */
tree
-lookup_objc_ivar (tree id)
+objc_lookup_ivar (tree id)
{
tree decl;
else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
{
if (is_private (decl))
- return error_mark_node;
+ return 0;
else
return build_ivar_reference (id);
}
}
#include "gt-objc-objc-act.h"
-#include "gtype-objc.h"