Commit 264fa2db by Ziemowit Laski Committed by Ziemowit Laski

MERGE OF objc-improvements-branch into MAINLINE.

2003-09-24  Ziemowit Laski  <zlaski@apple.com>

        MERGE OF objc-improvements-branch into MAINLINE.
	See 'gcc/ChangeLog' and 'gcc/testsuite/ChangeLog' for
	the gory details.

From-SVN: r71748
parent 3b6fdb2f
...@@ -821,7 +821,7 @@ C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \ ...@@ -821,7 +821,7 @@ C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-objc-common.o c-dump.o c-pch.o libcpp.a $(C_TARGET_OBJS) c-objc-common.o c-dump.o c-pch.o libcpp.a $(C_TARGET_OBJS)
# Language-specific object files for C. # Language-specific object files for C.
C_OBJS = c-parse.o c-lang.o c-pretty-print.o $(C_AND_OBJC_OBJS) C_OBJS = c-parse.o c-lang.o c-pretty-print.o stub-objc.o $(C_AND_OBJC_OBJS)
# Language-independent object files. # Language-independent object files.
...@@ -1263,8 +1263,8 @@ $(parsedir)/c-parse.c: $(parsedir)/c-parse.y ...@@ -1263,8 +1263,8 @@ $(parsedir)/c-parse.c: $(parsedir)/c-parse.y
$(parsedir)/c-parse.y: c-parse.in $(parsedir)/c-parse.y: c-parse.in
echo '/*WARNING: This file is automatically generated!*/' >tmp-c-parse.y echo '/*WARNING: This file is automatically generated!*/' >tmp-c-parse.y
sed -e "/^ifobjc$$/,/^end ifobjc$$/d" \ sed -e "/^@@ifobjc.*/,/^@@end_ifobjc.*/d" \
-e "/^ifc$$/d" -e "/^end ifc$$/d" \ -e "/^@@ifc.*/d" -e "/^@@end_ifc.*/d" \
$(srcdir)/c-parse.in >>tmp-c-parse.y $(srcdir)/c-parse.in >>tmp-c-parse.y
$(SHELL) $(srcdir)/move-if-change tmp-c-parse.y $(parsedir)/c-parse.y $(SHELL) $(srcdir)/move-if-change tmp-c-parse.y $(parsedir)/c-parse.y
...@@ -1281,6 +1281,7 @@ c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $( ...@@ -1281,6 +1281,7 @@ c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(
c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) $(C_PRETTY_PRINT_H) $(DIAGNOSTIC_H) \ $(C_TREE_H) $(C_PRETTY_PRINT_H) $(DIAGNOSTIC_H) \
$(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-c.h $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-c.h
stub-objc.o : stub-objc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) $(C_COMMON_H)
c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) debug.h $(C_TREE_H) $(C_COMMON_H) real.h c-incpath.h cppdefault.h \ $(RTL_H) debug.h $(C_TREE_H) $(C_COMMON_H) real.h c-incpath.h cppdefault.h \
c-pragma.h input.h intl.h flags.h toplev.h output.h \ c-pragma.h input.h intl.h flags.h toplev.h output.h \
......
...@@ -346,7 +346,25 @@ int warn_format_nonliteral; ...@@ -346,7 +346,25 @@ int warn_format_nonliteral;
int warn_format_security; int warn_format_security;
/* Zero means that faster, ...NonNil variants of objc_msgSend...
calls will be used in ObjC; passing nil receivers to such calls
will most likely result in crashes. */
int flag_nil_receivers = 1;
/* Nonzero means that we will allow new ObjC exception syntax (@throw,
@try, etc.) in source code. */
int flag_objc_exceptions = 0;
/* Nonzero means that code generation will be altered to support
"zero-link" execution. This currently affects ObjC only, but may
affect other languages in the future. */
int flag_zero_link = 0;
/* Nonzero means emit an '__OBJC, __image_info' for the current translation
unit. It will inform the ObjC runtime that class definition(s) herein
contained are to replace one(s) previously loaded. */
int flag_replace_objc_classes = 0;
/* C/ObjC language option variables. */ /* C/ObjC language option variables. */
......
...@@ -99,7 +99,10 @@ enum rid ...@@ -99,7 +99,10 @@ enum rid
RID_ID, RID_AT_ENCODE, RID_AT_END, RID_ID, RID_AT_ENCODE, RID_AT_END,
RID_AT_CLASS, RID_AT_ALIAS, RID_AT_DEFS, RID_AT_CLASS, RID_AT_ALIAS, RID_AT_DEFS,
RID_AT_PRIVATE, RID_AT_PROTECTED, RID_AT_PUBLIC, RID_AT_PRIVATE, RID_AT_PROTECTED, RID_AT_PUBLIC,
RID_AT_PROTOCOL, RID_AT_SELECTOR, RID_AT_INTERFACE, RID_AT_PROTOCOL, RID_AT_SELECTOR,
RID_AT_THROW, RID_AT_TRY, RID_AT_CATCH,
RID_AT_FINALLY, RID_AT_SYNCHRONIZED,
RID_AT_INTERFACE,
RID_AT_IMPLEMENTATION, RID_AT_IMPLEMENTATION,
RID_MAX, RID_MAX,
...@@ -354,6 +357,25 @@ extern void resort_sorted_fields (void *, void *, gt_pointer_operator, ...@@ -354,6 +357,25 @@ extern void resort_sorted_fields (void *, void *, gt_pointer_operator,
extern int flag_preprocess_only; extern int flag_preprocess_only;
/* Zero means that faster, ...NonNil variants of objc_msgSend...
calls will be used in ObjC; passing nil receivers to such calls
will most likely result in crashes. */
extern int flag_nil_receivers;
/* Nonzero means that we will allow new ObjC exception syntax (@throw,
@try, etc.) in source code. */
extern int flag_objc_exceptions;
/* Nonzero means that code generation will be altered to support
"zero-link" execution. This currently affects ObjC only, but may
affect other languages in the future. */
extern int flag_zero_link;
/* Nonzero means emit an '__OBJC, __image_info' for the current translation
unit. It will inform the ObjC runtime that class definition(s) herein
contained are to replace one(s) previously loaded. */
extern int flag_replace_objc_classes;
/* Nonzero means don't output line number information. */ /* Nonzero means don't output line number information. */
extern char flag_no_line_commands; extern char flag_no_line_commands;
...@@ -1309,6 +1331,19 @@ extern void fe_file_change (const struct line_map *); ...@@ -1309,6 +1331,19 @@ extern void fe_file_change (const struct line_map *);
extern int c_estimate_num_insns (tree decl); extern int c_estimate_num_insns (tree decl);
extern bool c_decl_uninit (tree t); extern bool c_decl_uninit (tree t);
/* The following have been moved here from c-tree.h, since they're needed
in the ObjC++ world, too. What is more, stub-objc.c could use a few
prototypes. */
extern tree lookup_interface (tree);
extern tree is_class_name (tree);
extern tree objc_is_object_ptr (tree);
extern void objc_check_decl (tree);
extern int objc_comptypes (tree, tree, int);
extern tree objc_message_selector (void);
extern tree lookup_objc_ivar (tree);
extern void *get_current_scope (void);
extern void objc_mark_locals_volatile (void *);
/* In c-ppoutput.c */ /* In c-ppoutput.c */
extern void init_pp_output (FILE *); extern void init_pp_output (FILE *);
extern void preprocess_file (cpp_reader *); extern void preprocess_file (cpp_reader *);
......
...@@ -410,6 +410,39 @@ pop_scope (void) ...@@ -410,6 +410,39 @@ pop_scope (void)
scope_freelist = scope; scope_freelist = scope;
} }
/* The Objective-C front-end often needs to determine the current scope. */
void *
get_current_scope (void)
{
return current_scope;
}
/* The following function is used only by Objective-C. It needs to live here
because it accesses the innards of c_scope. */
void
objc_mark_locals_volatile (void *enclosing_blk)
{
struct c_scope *scope;
for (scope = current_scope;
scope && scope != enclosing_blk;
scope = scope->outer)
{
tree decl;
for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
{
DECL_REGISTER (decl) = 0;
TREE_THIS_VOLATILE (decl) = 1;
}
/* Do not climb up past the current function. */
if (scope->function_body)
break;
}
}
/* Nonzero if we are currently in the global scope. */ /* Nonzero if we are currently in the global scope. */
int int
...@@ -2718,6 +2751,11 @@ finish_decl (tree decl, tree init, tree asmspec_tree) ...@@ -2718,6 +2751,11 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
if (init) if (init)
store_init_value (decl, init); store_init_value (decl, init);
if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == FIELD_DECL))
objc_check_decl (decl);
/* Deduce size of array from initialization, if not already known */ /* Deduce size of array from initialization, if not already known */
if (TREE_CODE (type) == ARRAY_TYPE if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == 0 && TYPE_DOMAIN (type) == 0
...@@ -2909,12 +2947,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) ...@@ -2909,12 +2947,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
mark_referenced (DECL_ASSEMBLER_NAME (decl)); mark_referenced (DECL_ASSEMBLER_NAME (decl));
if (TREE_CODE (decl) == TYPE_DECL) if (TREE_CODE (decl) == TYPE_DECL)
{ rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
/* This is a no-op in c-lang.c or something real in objc-act.c. */
if (c_dialect_objc ())
objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
}
/* At the end of a declaration, throw away any variable type sizes /* At the end of a declaration, throw away any variable type sizes
of types defined inside that declaration. There is no use of types defined inside that declaration. There is no use
...@@ -4778,8 +4811,6 @@ grokfield (tree declarator, tree declspecs, tree width) ...@@ -4778,8 +4811,6 @@ grokfield (tree declarator, tree declspecs, tree width)
finish_decl (value, NULL_TREE, NULL_TREE); finish_decl (value, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width; DECL_INITIAL (value) = width;
if (c_dialect_objc ())
objc_check_decl (value);
return value; return value;
} }
......
...@@ -179,52 +179,6 @@ const char *const tree_code_name[] = { ...@@ -179,52 +179,6 @@ const char *const tree_code_name[] = {
}; };
#undef DEFTREECODE #undef DEFTREECODE
/* Used by c-lex.c, but only for objc. */
tree
lookup_interface (tree arg ATTRIBUTE_UNUSED)
{
return 0;
}
tree
is_class_name (tree arg ATTRIBUTE_UNUSED)
{
return 0;
}
tree
objc_is_id (tree arg ATTRIBUTE_UNUSED)
{
return 0;
}
void
objc_check_decl (tree decl ATTRIBUTE_UNUSED)
{
}
int
objc_comptypes (tree lhs ATTRIBUTE_UNUSED, tree rhs ATTRIBUTE_UNUSED,
int reflexive ATTRIBUTE_UNUSED)
{
return -1;
}
tree
objc_message_selector (void)
{
return 0;
}
/* Used by c-typeck.c (build_external_ref), but only for objc. */
tree
lookup_objc_ivar (tree id ATTRIBUTE_UNUSED)
{
return 0;
}
void void
finish_file (void) finish_file (void)
{ {
...@@ -244,5 +198,4 @@ c_initialize_diagnostics (diagnostic_context *context) ...@@ -244,5 +198,4 @@ c_initialize_diagnostics (diagnostic_context *context)
free (base); free (base);
} }
#include "gtype-c.h" #include "gtype-c.h"
...@@ -847,10 +847,18 @@ c_common_handle_option (size_t scode, const char *arg, int value) ...@@ -847,10 +847,18 @@ c_common_handle_option (size_t scode, const char *arg, int value)
flag_next_runtime = value; flag_next_runtime = value;
break; break;
case OPT_fnil_receivers:
flag_nil_receivers = value;
break;
case OPT_fnonansi_builtins: case OPT_fnonansi_builtins:
flag_no_nonansi_builtin = !value; flag_no_nonansi_builtin = !value;
break; break;
case OPT_fobjc_exceptions:
flag_objc_exceptions = value;
break;
case OPT_foperator_names: case OPT_foperator_names:
cpp_opts->operator_names = value; cpp_opts->operator_names = value;
break; break;
...@@ -871,6 +879,10 @@ c_common_handle_option (size_t scode, const char *arg, int value) ...@@ -871,6 +879,10 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->preprocessed = value; cpp_opts->preprocessed = value;
break; break;
case OPT_freplace_objc_classes:
flag_replace_objc_classes = value;
break;
case OPT_frepo: case OPT_frepo:
flag_use_repository = value; flag_use_repository = value;
if (value) if (value)
...@@ -915,6 +927,10 @@ c_common_handle_option (size_t scode, const char *arg, int value) ...@@ -915,6 +927,10 @@ c_common_handle_option (size_t scode, const char *arg, int value)
flag_weak = value; flag_weak = value;
break; break;
case OPT_fzero_link:
flag_zero_link = value;
break;
case OPT_gen_decls: case OPT_gen_decls:
flag_gen_declaration = 1; flag_gen_declaration = 1;
break; break;
......
...@@ -153,17 +153,6 @@ struct lang_type GTY(()) ...@@ -153,17 +153,6 @@ struct lang_type GTY(())
#define KEEP_MAYBE 2 #define KEEP_MAYBE 2
/* in c-lang.c and objc-act.c */
extern tree lookup_interface (tree);
extern tree is_class_name (tree);
extern tree objc_is_id (tree);
extern void objc_check_decl (tree);
extern int objc_comptypes (tree, tree, int);
extern tree objc_message_selector (void);
extern tree lookup_objc_ivar (tree);
extern void c_expand_body (tree);
/* in c-parse.in */ /* in c-parse.in */
extern void c_parse_init (void); extern void c_parse_init (void);
...@@ -177,6 +166,7 @@ extern void pushlevel (int); ...@@ -177,6 +166,7 @@ extern void pushlevel (int);
extern void insert_block (tree); extern void insert_block (tree);
extern void set_block (tree); extern void set_block (tree);
extern tree pushdecl (tree); extern tree pushdecl (tree);
extern void c_expand_body (tree);
extern void c_init_decl_processing (void); extern void c_init_decl_processing (void);
extern void c_dup_lang_specific_decl (tree); extern void c_dup_lang_specific_decl (tree);
...@@ -306,6 +296,8 @@ extern int system_header_p; ...@@ -306,6 +296,8 @@ extern int system_header_p;
/* In c-decl.c */ /* In c-decl.c */
extern void c_finish_incomplete_decl (tree); extern void c_finish_incomplete_decl (tree);
extern void *get_current_scope (void);
extern void objc_mark_locals_volatile (void *);
extern void c_write_global_declarations (void); extern void c_write_global_declarations (void);
extern GTY(()) tree static_ctors; extern GTY(()) tree static_ctors;
......
...@@ -511,8 +511,12 @@ comptypes (tree type1, tree type2, int flags) ...@@ -511,8 +511,12 @@ comptypes (tree type1, tree type2, int flags)
switch (TREE_CODE (t1)) switch (TREE_CODE (t1))
{ {
case POINTER_TYPE: case POINTER_TYPE:
/* We must give ObjC the first crack at comparing pointers, since
protocol qualifiers may be involved. */
if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0)
break;
val = (TREE_TYPE (t1) == TREE_TYPE (t2) val = (TREE_TYPE (t1) == TREE_TYPE (t2)
? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags)); ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags));
break; break;
case FUNCTION_TYPE: case FUNCTION_TYPE:
...@@ -560,6 +564,8 @@ comptypes (tree type1, tree type2, int flags) ...@@ -560,6 +564,8 @@ comptypes (tree type1, tree type2, int flags)
} }
case RECORD_TYPE: case RECORD_TYPE:
/* We are dealing with two distinct structs. In assorted Objective-C
corner cases, however, these can still be deemed equivalent. */
if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1) if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1)
val = 1; val = 1;
...@@ -2927,7 +2933,7 @@ build_c_cast (tree type, tree expr) ...@@ -2927,7 +2933,7 @@ build_c_cast (tree type, tree expr)
/* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
only in <protocol> qualifications. But when constructing cast expressions, only in <protocol> qualifications. But when constructing cast expressions,
the protocols do matter and must be kept around. */ the protocols do matter and must be kept around. */
if (!c_dialect_objc () || !objc_is_id (type)) if (!c_dialect_objc () || !objc_is_object_ptr (type))
type = TYPE_MAIN_VARIANT (type); type = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (type) == ARRAY_TYPE) if (TREE_CODE (type) == ARRAY_TYPE)
...@@ -3488,6 +3494,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, ...@@ -3488,6 +3494,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
tree ttl = TREE_TYPE (type); tree ttl = TREE_TYPE (type);
tree ttr = TREE_TYPE (rhstype); tree ttr = TREE_TYPE (rhstype);
bool is_opaque_pointer; bool is_opaque_pointer;
int target_cmp = 0; /* Cache comp_target_types () result. */
/* Opaque pointers are treated like void pointers. */ /* Opaque pointers are treated like void pointers. */
is_opaque_pointer = ((*targetm.vector_opaque_p) (type) is_opaque_pointer = ((*targetm.vector_opaque_p) (type)
...@@ -3499,7 +3506,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, ...@@ -3499,7 +3506,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
and vice versa; otherwise, targets must be the same. and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */ Meanwhile, the lhs target must have all the qualifiers of the rhs. */
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| comp_target_types (type, rhstype, 0) || (target_cmp = comp_target_types (type, rhstype, 0))
|| is_opaque_pointer || is_opaque_pointer
|| (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl)) || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl))
== c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr)))) == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr))))
...@@ -3525,7 +3532,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, ...@@ -3525,7 +3532,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
/* If this is not a case of ignoring a mismatch in signedness, /* If this is not a case of ignoring a mismatch in signedness,
no warning. */ no warning. */
else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| comp_target_types (type, rhstype, 0)) || target_cmp)
; ;
/* If there is a mismatch, do warn. */ /* If there is a mismatch, do warn. */
else if (pedantic) else if (pedantic)
......
...@@ -551,7 +551,11 @@ C++ ObjC++ ...@@ -551,7 +551,11 @@ C++ ObjC++
fnext-runtime fnext-runtime
ObjC ObjC++ ObjC ObjC++
Generate code for NeXT runtime environment Generate code for NeXT (Apple Mac OS X) runtime environment
fnil-receivers
ObjC ObjC++
Assume that receivers of Objective-C messages may be nil
fnonansi-builtins fnonansi-builtins
C++ ObjC++ C++ ObjC++
...@@ -559,6 +563,10 @@ C++ ObjC++ ...@@ -559,6 +563,10 @@ C++ ObjC++
fnonnull-objects fnonnull-objects
C++ ObjC++ C++ ObjC++
fobjc-exceptions
ObjC ObjC++
Enable Objective-C exception and synchronization syntax
foperator-names foperator-names
C++ ObjC++ C++ ObjC++
Recognize C++ kewords like \"compl\" and \"xor\" Recognize C++ kewords like \"compl\" and \"xor\"
...@@ -578,6 +586,10 @@ fpreprocessed ...@@ -578,6 +586,10 @@ fpreprocessed
C ObjC C++ ObjC++ C ObjC C++ ObjC++
Treat the input file as already preprocessed Treat the input file as already preprocessed
freplace-objc-classes
ObjC ObjC++
Used in Fix-and-Continue mode to indicate that object files may be swapped in at runtime
frepo frepo
C++ ObjC++ C++ ObjC++
Enable automatic template instantiation Enable automatic template instantiation
...@@ -666,6 +678,10 @@ fxref ...@@ -666,6 +678,10 @@ fxref
C++ ObjC++ C++ ObjC++
Emit cross referencing information Emit cross referencing information
fzero-link
ObjC ObjC++
Generate lazy class lookup (via objc_getClass()) for use in Zero-Link mode
gen-decls gen-decls
ObjC ObjC++ ObjC ObjC++
Dump declarations to a .decl file Dump declarations to a .decl file
......
...@@ -1214,6 +1214,8 @@ machopic_select_section (tree exp, int reloc, ...@@ -1214,6 +1214,8 @@ machopic_select_section (tree exp, int reloc,
objc_symbols_section (); objc_symbols_section ();
else if (!strncmp (name, "_OBJC_MODULES", 13)) else if (!strncmp (name, "_OBJC_MODULES", 13))
objc_module_info_section (); objc_module_info_section ();
else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
objc_image_info_section ();
else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32)) else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
objc_cat_inst_meth_section (); objc_cat_inst_meth_section ();
else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29)) else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
......
...@@ -510,6 +510,7 @@ FUNCTION (void) \ ...@@ -510,6 +510,7 @@ FUNCTION (void) \
in_objc_symbols, in_objc_module_info, \ in_objc_symbols, in_objc_module_info, \
in_objc_protocol, in_objc_string_object, \ in_objc_protocol, in_objc_string_object, \
in_objc_constant_string_object, \ in_objc_constant_string_object, \
in_objc_image_info, \
in_objc_class_names, in_objc_meth_var_names, \ in_objc_class_names, in_objc_meth_var_names, \
in_objc_meth_var_types, in_objc_cls_refs, \ in_objc_meth_var_types, in_objc_cls_refs, \
in_machopic_nl_symbol_ptr, \ in_machopic_nl_symbol_ptr, \
...@@ -599,6 +600,10 @@ SECTION_FUNCTION (objc_string_object_section, \ ...@@ -599,6 +600,10 @@ SECTION_FUNCTION (objc_string_object_section, \
SECTION_FUNCTION (objc_constant_string_object_section, \ SECTION_FUNCTION (objc_constant_string_object_section, \
in_objc_constant_string_object, \ in_objc_constant_string_object, \
".section __OBJC, __cstring_object", 1) \ ".section __OBJC, __cstring_object", 1) \
/* Fix-and-Continue image marker. */ \
SECTION_FUNCTION (objc_image_info_section, \
in_objc_image_info, \
".section __OBJC, __image_info", 1) \
SECTION_FUNCTION (objc_class_names_section, \ SECTION_FUNCTION (objc_class_names_section, \
in_objc_class_names, \ in_objc_class_names, \
".objc_class_names", 1) \ ".objc_class_names", 1) \
......
...@@ -193,8 +193,14 @@ in the following sections. ...@@ -193,8 +193,14 @@ in the following sections.
@item Objective-C Language Options @item Objective-C Language Options
@xref{Objective-C Dialect Options,,Options Controlling Objective-C Dialect}. @xref{Objective-C Dialect Options,,Options Controlling Objective-C Dialect}.
@gccoptlist{-fconstant-string-class=@var{class-name} @gol @gccoptlist{
-fgnu-runtime -fnext-runtime -gen-decls @gol -fconstant-string-class=@var{class-name} @gol
-fgnu-runtime -fnext-runtime @gol
-fno-nil-receivers @gol
-fobjc-exceptions @gol
-freplace-objc-classes @gol
-fzero-link @gol
-gen-decls @gol
-Wno-protocol -Wselector -Wundeclared-selector} -Wno-protocol -Wselector -Wundeclared-selector}
@item Language Independent Options @item Language Independent Options
...@@ -1743,6 +1749,9 @@ In this example, G++ will synthesize a default @samp{A& operator = ...@@ -1743,6 +1749,9 @@ In this example, G++ will synthesize a default @samp{A& operator =
@cindex compiler options, Objective-C @cindex compiler options, Objective-C
@cindex Objective-C options, command line @cindex Objective-C options, command line
@cindex options, Objective-C @cindex options, Objective-C
(NOTE: This manual does not describe the Objective-C language itself. See
@w{@uref{http://gcc.gnu.org/readings.html}} for references.)
This section describes the command-line options that are only meaningful This section describes the command-line options that are only meaningful
for Objective-C programs, but you can also use most of the GNU compiler for Objective-C programs, but you can also use most of the GNU compiler
options regardless of what language your program is in. For example, options regardless of what language your program is in. For example,
...@@ -1765,7 +1774,11 @@ programs: ...@@ -1765,7 +1774,11 @@ programs:
@opindex fconstant-string-class @opindex fconstant-string-class
Use @var{class-name} as the name of the class to instantiate for each Use @var{class-name} as the name of the class to instantiate for each
literal string specified with the syntax @code{@@"@dots{}"}. The default literal string specified with the syntax @code{@@"@dots{}"}. The default
class name is @code{NXConstantString}. class name is @code{NXConstantString} if the GNU runtime is being used, and
@code{NSConstantString} if the NeXT runtime is being used (see below). The
@option{-fconstant-cfstrings} option, if also present, will override the
@option{-fconstant-string-class} setting and cause @code{@@"@dots{}"} literals
to be laid out as constant CoreFoundation strings.
@item -fgnu-runtime @item -fgnu-runtime
@opindex fgnu-runtime @opindex fgnu-runtime
...@@ -1779,6 +1792,127 @@ for NeXT-based systems, including Darwin and Mac OS X@. The macro ...@@ -1779,6 +1792,127 @@ for NeXT-based systems, including Darwin and Mac OS X@. The macro
@code{__NEXT_RUNTIME__} is predefined if (and only if) this option is @code{__NEXT_RUNTIME__} is predefined if (and only if) this option is
used. used.
@item -fno-nil-receivers
@opindex -fno-nil-receivers
Assume that all Objective-C message dispatches (e.g.,
@code{[receiver message:arg]}) in this translation unit ensure that the receiver
is not @code{nil}. This allows for more efficient entry points in the runtime to be
used. Currently, this option is only available in conjunciton with
the NeXT runtime on Mac OS X 10.3 and later.
@item -fobjc-exceptions
@opindex -fobjc-exceptions
Enable syntactic support for structured exception handling in Objective-C,
similar to what is offered by C++ and Java. Currently, this option is only
available in conjunciton with the NeXT runtime on Mac OS X 10.3 and later.
@smallexample
@@try @{
@dots{}
@@throw expr;
@dots{}
@}
@@catch (AnObjCClass *exc) @{
@dots{}
@@throw expr;
@dots{}
@@throw;
@dots{}
@}
@@catch (AnotherClass *exc) @{
@dots{}
@}
@@catch (id allOthers) @{
@dots{}
@}
@@finally @{
@dots{}
@@throw expr;
@dots{}
@}
@end smallexample
The @code{@@throw} statement may appear anywhere in an Objective-C or
Objective-C++ program; when used inside of a @code{@@catch} block, the
@code{@@throw} may appear without an argument (as shown above), in which case
the object caught by the @code{@@catch} will be rethrown.
Note that only (pointers to) Objective-C objects may be thrown and
caught using this scheme. When an object is thrown, it will be caught
by the nearest @code{@@catch} clause capable of handling objects of that type,
analogously to how @code{catch} blocks work in C++ and Java. A
@code{@@catch(id @dots{})} clause (as shown above) may also be provided to catch
any and all Objective-C exceptions not caught by previous @code{@@catch}
clauses (if any).
The @code{@@finally} clause, if present, will be executed upon exit from the
immediately preceding @code{@@try @dots{} @@catch} section. This will happen
regardless of whether any exceptions are thrown, caught or rethrown
inside the @code{@@try @dots{} @@catch} section, analogously to the behavior
of the @code{finally} clause in Java.
There are several caveats to using the new exception mechanism:
@itemize @bullet
@item
Although currently designed to be binary compatible with @code{NS_HANDLER}-style
idioms provided by the @code{NSException} class, the new
exceptions can only be used on Mac OS X 10.3 (Panther) and later
systems, due to additional functionality needed in the (NeXT) Objective-C
runtime.
@item
As mentioned above, the new exceptions do not support handling
types other than Objective-C objects. Furthermore, when used from
Objective-C++, the Objective-C exception model does not interoperate with C++
exceptions at this time. This means you cannot @code{@@throw} an exception
from Objective-C and @code{catch} it in C++, or vice versa
(i.e., @code{throw @dots{} @@catch}).
@end itemize
The @option{-fobjc-exceptions} switch also enables the use of synchronization
blocks for thread-safe execution:
@smallexample
@@synchronized (ObjCClass *guard) @{
@dots{}
@}
@end smallexample
Upon entering the @code{@@synchronized} block, a thread of execution shall
first check whether a lock has been placed on the corresponding @code{guard}
object by another thread. If it has, the current thread shall wait until
the other thread relinquishes its lock. Once @code{guard} becomes available,
the current thread will place its own lock on it, execute the code contained in
the @code{@@synchronized} block, and finally relinquish the lock (thereby
making @code{guard} available to other threads).
Unlike Java, Objective-C does not allow for entire methods to be marked
@code{@@synchronized}. Note that throwing exceptions out of
@code{@@synchronized} blocks is allowed, and will cause the guarding object
to be unlocked properly.
@item -freplace-objc-classes
@opindex -freplace-objc-classes
Emit a special marker instructing @command{ld(1)} not to statically link in
the resulting object file, and allow @command{dyld(1)} to load it in at
run time instead. This is used in conjunction with the Fix-and-Continue
debugging mode, where the object file in question may be recompiled and
dynamically reloaded in the course of program execution, without the need
to restart the program itself. Currently, Fix-and-Continue functionality
is only available in conjunciton withthe NeXT runtime on Mac OS X 10.3
and later.
@item -fzero-link
@opindex -fzero-link
When compiling for the NeXT runtime, the compiler ordinarily replaces calls
to @code{objc_getClass("@dots{}")} (when the name of the class is known at
compile time) with static class references that get initialized at load time,
which improves run-time performance. Specifying the @option{-fzero-link} flag
suppresses this behavior and causes calls to @code{objc_getClass("@dots{}")}
to be retained. This is useful in Zero-Link debugging mode, since it allows
for individual class implementations to be modified during program execution.
@item -gen-decls @item -gen-decls
@opindex gen-decls @opindex gen-decls
Dump interface declarations for all classes seen in the source file to a Dump interface declarations for all classes seen in the source file to a
......
...@@ -19,6 +19,9 @@ along with GCC; see the file COPYING. If not, write to the Free ...@@ -19,6 +19,9 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */ 02111-1307, USA. */
#ifndef GCC_FUNCTION_H
#define GCC_FUNCTION_H
struct var_refs_queue GTY(()) struct var_refs_queue GTY(())
{ {
rtx modified; rtx modified;
...@@ -628,3 +631,5 @@ extern void init_virtual_regs (struct emit_status *); ...@@ -628,3 +631,5 @@ extern void init_virtual_regs (struct emit_status *);
/* Called once, at initialization, to initialize function.c. */ /* Called once, at initialization, to initialize function.c. */
extern void init_function_once (void); extern void init_function_once (void);
#endif /* GCC_FUNCTION_H */
...@@ -194,6 +194,8 @@ ITYPE {IWORD}({WS}{IWORD})* ...@@ -194,6 +194,8 @@ ITYPE {IWORD}({WS}{IWORD})*
^"%{" { BEGIN(in_yacc_escape); } ^"%{" { BEGIN(in_yacc_escape); }
^"@@".* /* Used for c-parse.in C/ObjC demarcation. */
{WS} { update_lineno (yytext, yyleng); } {WS} { update_lineno (yytext, yyleng); }
"const"/[^[:alnum:]_] /* don't care */ "const"/[^[:alnum:]_] /* don't care */
......
...@@ -86,8 +86,8 @@ $(parsedir)/objc/objc-parse.c : $(parsedir)/objc/objc-parse.y ...@@ -86,8 +86,8 @@ $(parsedir)/objc/objc-parse.c : $(parsedir)/objc/objc-parse.y
$(parsedir)/objc/objc-parse.y: $(srcdir)/c-parse.in $(parsedir)/objc/objc-parse.y: $(srcdir)/c-parse.in
echo '/*WARNING: This file is automatically generated!*/' >tmp-objc-prs.y echo '/*WARNING: This file is automatically generated!*/' >tmp-objc-prs.y
sed -e "/^ifc$$/,/^end ifc$$/d" \ sed -e "/^@@ifc.*/,/^@@end_ifc.*/d" \
-e "/^ifobjc$$/d" -e "/^end ifobjc$$/d" \ -e "/^@@ifobjc.*/d" -e "/^@@end_ifobjc.*/d" \
$(srcdir)/c-parse.in >>tmp-objc-prs.y $(srcdir)/c-parse.in >>tmp-objc-prs.y
$(SHELL) $(srcdir)/move-if-change tmp-objc-prs.y $(parsedir)/objc/objc-parse.y $(SHELL) $(srcdir)/move-if-change tmp-objc-prs.y $(parsedir)/objc/objc-parse.y
......
...@@ -39,8 +39,8 @@ Boston, MA 02111-1307, USA. */ ...@@ -39,8 +39,8 @@ Boston, MA 02111-1307, USA. */
"%{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %{gen-decls}\ "%{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %{gen-decls}\
%{!fsyntax-only:%(invoke_as)}}}}", 0}, %{!fsyntax-only:%(invoke_as)}}}}", 0},
{"@objective-c-header", {"@objective-c-header",
"%{E|M|MM:%(trad_capable_cpp)\ "%{E|M|MM:cc1obj -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}\
-lang-objc %(cpp_options) %(cpp_debug_options)}\ %(cpp_options) %(cpp_debug_options)}\
%{!E:%{!M:%{!MM:\ %{!E:%{!M:%{!MM:\
%{traditional|ftraditional|traditional-cpp:\ %{traditional|ftraditional|traditional-cpp:\
%eGNU Objective C no longer supports traditional compilation}\ %eGNU Objective C no longer supports traditional compilation}\
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -38,16 +38,26 @@ void continue_method_def (void); ...@@ -38,16 +38,26 @@ void continue_method_def (void);
void finish_method_def (void); void finish_method_def (void);
tree start_protocol (enum tree_code, tree, tree); tree start_protocol (enum tree_code, tree, tree);
void finish_protocol (tree); void finish_protocol (tree);
void add_objc_decls (void);
tree objc_build_throw_stmt (tree);
tree objc_build_try_catch_finally_stmt (int, int);
void objc_build_synchronized_prologue (tree);
tree objc_build_synchronized_epilogue (void);
tree objc_build_try_prologue (void);
void objc_build_try_epilogue (int);
void objc_build_catch_stmt (tree);
void objc_build_catch_epilogue (void);
tree objc_build_finally_prologue (void);
tree objc_build_finally_epilogue (void);
tree is_ivar (tree, tree); tree is_ivar (tree, tree);
int is_private (tree); int is_private (tree);
int is_public (tree, tree); int is_public (tree, tree);
tree add_instance_variable (tree, int, tree, tree, tree); tree add_instance_variable (tree, int, tree, tree, tree);
tree add_class_method (tree, tree); tree add_method (tree, tree, int);
tree add_instance_method (tree, tree);
tree get_super_receiver (void); tree get_super_receiver (void);
tree get_class_ivars (tree); void objc_clear_super_receiver (void);
tree get_class_ivars_from_name (tree);
tree get_class_reference (tree); tree get_class_reference (tree);
tree get_static_reference (tree, tree); tree get_static_reference (tree, tree);
tree get_object_reference (tree); tree get_object_reference (tree);
...@@ -75,6 +85,9 @@ tree build_encode_expr (tree); ...@@ -75,6 +85,9 @@ tree build_encode_expr (tree);
/* Objective-C structures */ /* Objective-C structures */
#define CLASS_BINFO_ELTS 6
#define PROTOCOL_BINFO_ELTS 2
/* KEYWORD_DECL */ /* KEYWORD_DECL */
#define KEYWORD_KEY_NAME(DECL) ((DECL)->decl.name) #define KEYWORD_KEY_NAME(DECL) ((DECL)->decl.name)
#define KEYWORD_ARG_NAME(DECL) ((DECL)->decl.arguments) #define KEYWORD_ARG_NAME(DECL) ((DECL)->decl.arguments)
...@@ -105,10 +118,12 @@ tree build_encode_expr (tree); ...@@ -105,10 +118,12 @@ tree build_encode_expr (tree);
#define PROTOCOL_CLS_METHODS(CLASS) ((CLASS)->type.maxval) #define PROTOCOL_CLS_METHODS(CLASS) ((CLASS)->type.maxval)
#define PROTOCOL_FORWARD_DECL(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 1) #define PROTOCOL_FORWARD_DECL(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 1)
#define PROTOCOL_DEFINED(CLASS) TREE_USED (CLASS) #define PROTOCOL_DEFINED(CLASS) TREE_USED (CLASS)
#define TYPE_PROTOCOL_LIST(TYPE) \ /* We need to distinguish TYPE_PROTOCOL_LISTs from TYPE_CONTEXTs, both of which
((!TYPE_CHECK (TYPE)->type.context \ are stored in the same accessor slot. */
|| TREE_CODE ((TYPE)->type.context) == TRANSLATION_UNIT_DECL) \ #define TYPE_PROTOCOL_LIST(TYPE) \
? NULL_TREE : (TYPE)->type.context) ((TYPE_CHECK (TYPE)->type.context \
&& TREE_CODE ((TYPE)->type.context) == TREE_LIST) \
? (TYPE)->type.context : NULL_TREE)
#define SET_TYPE_PROTOCOL_LIST(TYPE, P) (TYPE_CHECK (TYPE)->type.context = (P)) #define SET_TYPE_PROTOCOL_LIST(TYPE, P) (TYPE_CHECK (TYPE)->type.context = (P))
/* Set by `continue_class' and checked by `is_public'. */ /* Set by `continue_class' and checked by `is_public'. */
...@@ -116,15 +131,20 @@ tree build_encode_expr (tree); ...@@ -116,15 +131,20 @@ tree build_encode_expr (tree);
#define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type)) #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
#define TYPED_OBJECT(type) \ #define TYPED_OBJECT(type) \
(TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type)) (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
#define OBJC_TYPE_NAME(type) TYPE_NAME(type)
/* Define the Objective-C or Objective-C++ language-specific tree codes. */ /* Define the Objective-C or Objective-C++ language-specific tree codes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM, #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
enum objc_tree_code { enum objc_tree_code {
#ifdef OBJCPLUS #if defined (GCC_CP_TREE_H)
LAST_BASE_TREE_CODE = LAST_CPLUS_TREE_CODE, LAST_BASE_TREE_CODE = LAST_CPLUS_TREE_CODE,
#else #else
#if defined (GCC_C_TREE_H)
LAST_BASE_TREE_CODE = LAST_C_TREE_CODE, LAST_BASE_TREE_CODE = LAST_C_TREE_CODE,
#else
#error You must include <c-tree.h> or <cp/cp-tree.h> before <objc/objc-act.h>
#endif
#endif #endif
#include "objc-tree.def" #include "objc-tree.def"
LAST_OBJC_TREE_CODE LAST_OBJC_TREE_CODE
...@@ -182,6 +202,8 @@ enum objc_tree_index ...@@ -182,6 +202,8 @@ enum objc_tree_index
OCTI_SELF_DECL, OCTI_SELF_DECL,
OCTI_UMSG_DECL, OCTI_UMSG_DECL,
OCTI_UMSG_SUPER_DECL, OCTI_UMSG_SUPER_DECL,
OCTI_UMSG_STRET_DECL,
OCTI_UMSG_SUPER_STRET_DECL,
OCTI_GET_CLASS_DECL, OCTI_GET_CLASS_DECL,
OCTI_GET_MCLASS_DECL, OCTI_GET_MCLASS_DECL,
OCTI_SUPER_TYPE, OCTI_SUPER_TYPE,
...@@ -245,6 +267,24 @@ enum objc_tree_index ...@@ -245,6 +267,24 @@ enum objc_tree_index
OCTI_CNST_STR_GLOB_ID, OCTI_CNST_STR_GLOB_ID,
OCTI_STRING_CLASS_DECL, OCTI_STRING_CLASS_DECL,
OCTI_SUPER_DECL, OCTI_SUPER_DECL,
OCTI_UMSG_NONNIL_DECL,
OCTI_UMSG_NONNIL_STRET_DECL,
OCTI_STORAGE_CLS,
OCTI_EXCEPTION_EXTRACT_DECL,
OCTI_EXCEPTION_TRY_ENTER_DECL,
OCTI_EXCEPTION_TRY_EXIT_DECL,
OCTI_EXCEPTION_MATCH_DECL,
OCTI_EXCEPTION_THROW_DECL,
OCTI_SYNC_ENTER_DECL,
OCTI_SYNC_EXIT_DECL,
OCTI_SETJMP_DECL,
OCTI_EXCDATA_TEMPL,
OCTI_STACK_EXCEPTION_DATA_DECL,
OCTI_LOCAL_EXCEPTION_DECL,
OCTI_RETHROW_EXCEPTION_DECL,
OCTI_EVAL_ONCE_DECL,
OCTI_EXCEPTION_BLK_STACK,
OCTI_CATCH_TYPE,
OCTI_MAX OCTI_MAX
}; };
...@@ -267,6 +307,8 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; ...@@ -267,6 +307,8 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define self_decl objc_global_trees[OCTI_SELF_DECL] #define self_decl objc_global_trees[OCTI_SELF_DECL]
#define umsg_decl objc_global_trees[OCTI_UMSG_DECL] #define umsg_decl objc_global_trees[OCTI_UMSG_DECL]
#define umsg_super_decl objc_global_trees[OCTI_UMSG_SUPER_DECL] #define umsg_super_decl objc_global_trees[OCTI_UMSG_SUPER_DECL]
#define umsg_stret_decl objc_global_trees[OCTI_UMSG_STRET_DECL]
#define umsg_super_stret_decl objc_global_trees[OCTI_UMSG_SUPER_STRET_DECL]
#define objc_get_class_decl objc_global_trees[OCTI_GET_CLASS_DECL] #define objc_get_class_decl objc_global_trees[OCTI_GET_CLASS_DECL]
#define objc_get_meta_class_decl \ #define objc_get_meta_class_decl \
objc_global_trees[OCTI_GET_MCLASS_DECL] objc_global_trees[OCTI_GET_MCLASS_DECL]
...@@ -285,7 +327,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; ...@@ -285,7 +327,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define IS_PROTOCOL_QUALIFIED_ID(TYPE) \ #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
(IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE)) (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
#define IS_SUPER(TYPE) \ #define IS_SUPER(TYPE) \
(super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type)) (TREE_CODE (TYPE) == POINTER_TYPE && TREE_TYPE (TYPE) == objc_super_template)
#define class_chain objc_global_trees[OCTI_CLS_CHAIN] #define class_chain objc_global_trees[OCTI_CLS_CHAIN]
#define alias_chain objc_global_trees[OCTI_ALIAS_CHAIN] #define alias_chain objc_global_trees[OCTI_ALIAS_CHAIN]
...@@ -339,6 +381,33 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; ...@@ -339,6 +381,33 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define ucls_super_ref objc_global_trees[OCTI_UCLS_SUPER_REF] #define ucls_super_ref objc_global_trees[OCTI_UCLS_SUPER_REF]
#define uucls_super_ref objc_global_trees[OCTI_UUCLS_SUPER_REF] #define uucls_super_ref objc_global_trees[OCTI_UUCLS_SUPER_REF]
#define umsg_nonnil_decl objc_global_trees[OCTI_UMSG_NONNIL_DECL]
#define umsg_nonnil_stret_decl objc_global_trees[OCTI_UMSG_NONNIL_STRET_DECL]
#define objc_storage_class objc_global_trees[OCTI_STORAGE_CLS]
#define objc_exception_extract_decl \
objc_global_trees[OCTI_EXCEPTION_EXTRACT_DECL]
#define objc_exception_try_enter_decl \
objc_global_trees[OCTI_EXCEPTION_TRY_ENTER_DECL]
#define objc_exception_try_exit_decl \
objc_global_trees[OCTI_EXCEPTION_TRY_EXIT_DECL]
#define objc_exception_match_decl \
objc_global_trees[OCTI_EXCEPTION_MATCH_DECL]
#define objc_exception_throw_decl \
objc_global_trees[OCTI_EXCEPTION_THROW_DECL]
#define objc_sync_enter_decl objc_global_trees[OCTI_SYNC_ENTER_DECL]
#define objc_sync_exit_decl objc_global_trees[OCTI_SYNC_EXIT_DECL]
#define objc_exception_data_template \
objc_global_trees[OCTI_EXCDATA_TEMPL]
#define objc_setjmp_decl objc_global_trees[OCTI_SETJMP_DECL]
#define objc_stack_exception_data \
objc_global_trees[OCTI_STACK_EXCEPTION_DATA_DECL]
#define objc_caught_exception objc_global_trees[OCTI_LOCAL_EXCEPTION_DECL]
#define objc_rethrow_exception objc_global_trees[OCTI_RETHROW_EXCEPTION_DECL]
#define objc_eval_once objc_global_trees[OCTI_EVAL_ONCE_DECL]
#define objc_exception_block_stack \
objc_global_trees[OCTI_EXCEPTION_BLK_STACK]
#define objc_catch_type objc_global_trees[OCTI_CATCH_TYPE]
#define objc_method_template objc_global_trees[OCTI_METH_TEMPL] #define objc_method_template objc_global_trees[OCTI_METH_TEMPL]
#define objc_ivar_template objc_global_trees[OCTI_IVAR_TEMPL] #define objc_ivar_template objc_global_trees[OCTI_IVAR_TEMPL]
#define objc_symtab_template objc_global_trees[OCTI_SYMTAB_TEMPL] #define objc_symtab_template objc_global_trees[OCTI_SYMTAB_TEMPL]
......
...@@ -33,3 +33,7 @@ DEFTREECODE (PROTOCOL_INTERFACE_TYPE, "protocol_interface_type", 't', 0) ...@@ -33,3 +33,7 @@ DEFTREECODE (PROTOCOL_INTERFACE_TYPE, "protocol_interface_type", 't', 0)
DEFTREECODE (KEYWORD_DECL, "keyword_decl", 'd', 0) DEFTREECODE (KEYWORD_DECL, "keyword_decl", 'd', 0)
DEFTREECODE (INSTANCE_METHOD_DECL, "instance_method_decl", 'd', 0) DEFTREECODE (INSTANCE_METHOD_DECL, "instance_method_decl", 'd', 0)
DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", 'd', 0) DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", 'd', 0)
/* Objective-C expressions. */
DEFTREECODE (MESSAGE_SEND_EXPR, "message_send_expr", 'e', 3)
DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", 'e', 1)
/* Stub functions for Objective-C and Objective-C++ routines
that are called from within the C and C++ front-ends,
respectively.
Copyright (C) 1991, 1995, 1997, 1998,
1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "c-common.h"
tree
lookup_interface (tree arg ATTRIBUTE_UNUSED)
{
return 0;
}
tree
is_class_name (tree arg ATTRIBUTE_UNUSED)
{
return 0;
}
tree
objc_is_object_ptr (tree arg ATTRIBUTE_UNUSED)
{
return 0;
}
tree
lookup_objc_ivar (tree arg ATTRIBUTE_UNUSED)
{
return 0;
}
void
objc_check_decl (tree decl ATTRIBUTE_UNUSED)
{
}
int
objc_comptypes (tree lhs ATTRIBUTE_UNUSED, tree rhs ATTRIBUTE_UNUSED,
int reflexive ATTRIBUTE_UNUSED)
{
return -1;
}
tree
objc_message_selector (void)
{
return 0;
}
2003-09-24 Ziemowit Laski <zlaski@apple.com>
MERGE OF objc-improvements-branch into MAINLINE:
* lib/objc.exp (objc_target_compile): Do not point at libobjc headers
if libobjc has not been built.
* objc/execute/IMP.m, objc/execute/_cmd.m, objc/execute/bf-common.h,
objc/execute/bycopy-3.m, objc/execute/class-{1-14}.m, objc/execute/class-self-2.m,
objc/execute/many_args_method.m, objc/execute/nested-3.m, objc/execute/np-2.m,
objc/execute/object_is_class.m, objc/execute/object_is_meta_class.m,
objc/execute/redefining_self.m, objc/execute/root_methods.m,
objc/execute/static-{1-2}.m, objc/execute/string-{1-4}.m, objc/execute/va_method.m,
objc.dg/comp-types-4.m, objc.dg/headers.m, objc.dg/special/unclaimed-category-1.h,
objc.dg/special/unclaimed-category-1.m: Make usable with NeXT as well as GNU runtime.
* execute/next_mapping.h: New header, for GNU->NeXT impedance matching.
* execute/cascading-1.m, execute/function-message-1.m, objc.dg/anon-1.m,
objc.dg/bitfield-{3-4}.m, objc.dg/call-super-{1-3}.m, objc.dg/category-1.m,
objc.dg/const-str-{3-6}.m, objc.dg/encode-{1-4}.m, objc.dg/func-ptr-1.m,
objc.dg/gnu-runtime-1.m, objc.dg/image-info.m, objc.dg/method-{3-12}.m,
objc.dg/missing-proto-{1-3}.m, objc.dg/nested-func-1.m, objc.dg/proto-lossage-2.m,
objc.dg/proto-qual-1.m, objc.dg/sizeof-1.m, objc.dg/static-1.m, objc.dg/symtab-1.m,
objc.dg/try-catch-{1-4}.m, objc.dg/type-size-{1-2}.m, objc.dg/zero-link-{1-2}.m:
New test cases.
* objc.dg/bitfield-2.m: Run only on Darwin.
* objc.dg/class-2.m, objc.dg/comp-types-1.m, objc.dg/desig-init-1.m,
objc.dg/method-{1-2}.m, objc.dg/proto-hier-1.m, objc.dg/proto-lossage-1.m:
Adjust for message wording changes.
* objc.dg/const-str-1.m: Fix constant string layout.
2003-09-24 Alexandre Oliva <aoliva@redhat.com> 2003-09-24 Alexandre Oliva <aoliva@redhat.com>
* gcc.dg/cpp/Wunknown-pragmas-1.c: New test. * gcc.dg/cpp/Wunknown-pragmas-1.c: New test.
......
...@@ -168,13 +168,15 @@ proc objc_target_compile { source dest type options } { ...@@ -168,13 +168,15 @@ proc objc_target_compile { source dest type options } {
set options [concat "additional_flags=$TOOL_OPTIONS" $options]; set options [concat "additional_flags=$TOOL_OPTIONS" $options];
} }
# Point to the ObjC headers in libobjc. # If we have built libobjc along with the compiler (which usually
set objc_include_dir "${srcdir}/../../libobjc" # _is not_ the case on Mac OS X systems), point the test harness
lappend options "additional_flags=-I${objc_include_dir}" # at it (and associated headers).
set objcpath "[get_multilibs]" set objcpath "[get_multilibs]"
set libobjc_dir [lookfor_file ${objcpath} libobjc/.libs/libobjc.a] set libobjc_dir [lookfor_file ${objcpath} libobjc/.libs/libobjc.a]
if { $libobjc_dir != "" } { if { $libobjc_dir != "" } {
set objc_include_dir "${srcdir}/../../libobjc"
lappend options "additional_flags=-I${objc_include_dir}"
set libobjc_dir [file dirname ${libobjc_dir}] set libobjc_dir [file dirname ${libobjc_dir}]
set objc_link_flags "-L${libobjc_dir}" set objc_link_flags "-L${libobjc_dir}"
lappend options "additional_flags=${objc_link_flags}" lappend options "additional_flags=${objc_link_flags}"
......
/* Test for graceful handling of anonymous ivars. */
/* { dg-do compile } */
@interface Foo {
unsigned char : 1;
int e: 3;
signed: 2;
float f;
}
@end
@implementation Foo
@end
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
the NeXT runtime is used. */ the NeXT runtime is used. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ /* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fnext-runtime -fsigned-char" } */ /* { dg-options "-fnext-runtime -fsigned-char" } */
/* { dg-do run } */ /* { dg-do run { target *-*-darwin* } } */
struct objc_object { struct objc_class *class_pointer; } *id; struct objc_object { struct objc_class *class_pointer; } *id;
......
/* Check if the @defs() construct preserves the correct
layout of bitfields. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-lobjc -Wpadded" } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort(void);
extern int strcmp(const char *str1, const char *str2);
#define CHECK_IF(expr) if(!(expr)) abort()
enum Enum { one, two, three, four };
@interface Base: Object {
unsigned a: 2;
int b: 3;
enum Enum c: 4;
unsigned d: 5;
} /* { dg-warning "padding struct size to alignment boundary" } */
@end
@interface Derived: Base {
signed e: 5;
int f: 4;
enum Enum g: 3;
} /* { dg-warning "padding struct size to alignment boundary" } */
@end
/* Note that the semicolon after @defs(...) is optional. */
typedef struct { @defs(Base) } Base_t; /* { dg-warning "padding struct size to alignment boundary" } */
typedef struct { @defs(Derived); } Derived_t; /* { dg-warning "padding struct size to alignment boundary" } */
int main(void)
{
CHECK_IF(sizeof(Base_t) == sizeof(Base));
CHECK_IF(sizeof(Derived_t) == sizeof(Derived));
#ifdef __NEXT_RUNTIME__
CHECK_IF(!strcmp(@encode(Base), "{Base=#b2b3b4b5}"));
CHECK_IF(!strcmp(@encode(Derived), "{Derived=#b2b3b4b5b5b4b3}"));
CHECK_IF(!strcmp(@encode(Base_t), "{?=#b2b3b4b5}"));
CHECK_IF(!strcmp(@encode(Derived_t), "{?=#b2b3b4b5b5b4b3}"));
#endif /* __NEXT_RUNTIME__ */
return 0;
}
/* Make sure that bitfield types are printed correctly, and that ivar redeclaration
(@interface vs. @implementation) checks take the bitfield width into account. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
@interface Base {
int i;
}
@end
@interface WithBitfields: Base {
void *isa;
unsigned a: 3;
signed b: 4;
int c: 5;
}
@end
@implementation WithBitfields {
char *isa; /* { dg-error "conflicting instance variable type .char \\*isa." } */
/* { dg-error "previous declaration of .void \\*isa." "" { target *-*-* } 12 } */
unsigned a: 5; /* { dg-error "conflicting instance variable type .unsigned a: 5." } */
/* { dg-error "previous declaration of .unsigned a: 3." "" { target *-*-* } 13 } */
signed b: 4; /* This one is fine. */
int c: 3; /* { dg-error "conflicting instance variable type .int c: 3." } */
/* { dg-error "previous declaration of .int c: 5." "" { target *-*-* } 15 } */
}
@end
/* Check if objc_super stack variables are created correctly (and
not clobbered by other values). */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-std=c99 -lobjc" } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
typedef struct _Point {
float x;
float y;
} Point;
Point MakePoint ( float x , float y ) {
Point p;
p.x = x;
p.y = y;
return p;
}
@interface Base: Object
- ( void ) translateOriginToPoint : ( Point ) translation ;
@end
@interface Derived : Base
- ( void ) scrollToPoint : ( Point ) newOrigin ;
- ( void ) translateOriginToPoint : ( Point ) translation ;
@end
int blort;
float result;
@implementation Base
- ( void ) translateOriginToPoint : ( Point ) translation {
result = translation.x + translation.y;
}
@end
@implementation Derived
- ( void ) scrollToPoint : ( Point ) newOrigin {
float transDeltaX =newOrigin.x, transDeltaY =newOrigin.y ;
Point w;
if ( ! blort ) {
w.x = transDeltaX ; w.y = transDeltaY ;
[ super translateOriginToPoint : w ] ;
return;
}
[ super translateOriginToPoint : MakePoint ( transDeltaX , transDeltaY ) ] ;
return;
}
- (void) translateOriginToPoint : ( Point ) translation {
/* This should never be called. */
CHECK_IF(0);
}
@end
int main(void) {
Derived *v = [Derived new];
float r0 = 1.5 + 1.5;
blort = 1;
[v scrollToPoint: MakePoint(1.5, 1.5)];
CHECK_IF(result == r0);
blort = 0;
[v scrollToPoint: MakePoint(1.5, 1.5)];
CHECK_IF(result == r0);
blort = 1;
[v scrollToPoint: MakePoint(1.5, 1.5)];
CHECK_IF(result == r0);
[v free];
return 0;
}
/* Check if casting 'self' or 'super' affects message lookup in the
correct way. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
#include <objc/objc.h>
#include <objc/Object.h>
#ifdef __NEXT_RUNTIME__
#define OBJC_GETCLASS objc_getClass
#else
#define OBJC_GETCLASS objc_get_class
#endif
@protocol Func
+ (int) class_func0;
- (int) instance_func0;
@end
@interface Derived: Object
+ (int) class_func1;
+ (int) class_func2;
+ (int) class_func3;
+ (int) class_func4;
+ (int) class_func5;
+ (int) class_func6;
+ (int) class_func7;
- (int) instance_func1;
- (int) instance_func2;
- (int) instance_func3;
- (int) instance_func4;
- (int) instance_func5;
- (int) instance_func6;
- (int) instance_func7;
@end
@interface Derived (Categ)
+ (int) categ_class_func1;
+ (int) categ_class_func2;
- (int) categ_instance_func1;
- (int) categ_instance_func2;
@end
@implementation Derived
+ (int) class_func1
{
int i = (int)[self class_func0]; /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */
/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 47 } */
/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 47 } */
/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 47 } */
return i + (int)[super class_func0]; /* { dg-warning ".Object. may not respond to .\\+class_func0." } */
}
+ (int) class_func2
{
int i = [(id <Func>)self class_func0];
return i + [(id <Func>)super class_func0];
}
+ (int) class_func3
{
return [(Object <Func> *)super class_func0];
}
+ (int) class_func4
{
return [(Derived <Func> *)super class_func0];
}
+ (int) class_func5
{
int i = (int)[Derived class_func0]; /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */
return i + (int)[Object class_func0]; /* { dg-warning ".Object. may not respond to .\\+class_func0." } */
}
+ (int) class_func6
{
return (int)[OBJC_GETCLASS("Object") class_func1]; /* { dg-warning ".Object. may not respond to .\\+class_func1." } */
}
+ (int) class_func7
{
return [OBJC_GETCLASS("Derived") class_func1];
}
- (int) instance_func1
{
int i = (int)[self instance_func0]; /* { dg-warning ".Derived. may not respond to .\\-instance_func0." } */
return i + (int)[super instance_func0]; /* { dg-warning ".Object. may not respond to .\\-instance_func0." } */
}
- (int) instance_func2
{
return [(id <Func>)super instance_func0];
}
- (int) instance_func3
{
return [(Object <Func> *)super instance_func0];
}
- (int) instance_func4
{
return [(Derived <Func> *)super instance_func0];
}
- (int) instance_func5
{
int i = (int)[Derived instance_func1]; /* { dg-warning ".Derived. may not respond to .\\+instance_func1." } */
return i + (int)[Object instance_func1]; /* { dg-warning ".Object. may not respond to .\\+instance_func1." } */
}
- (int) instance_func6
{
return (int)[OBJC_GETCLASS("Object") class_func1]; /* { dg-warning ".Object. may not respond to .\\+class_func1." } */
}
- (int) instance_func7
{
return [OBJC_GETCLASS("Derived") class_func1];
}
@end
@implementation Derived (Categ)
+ (int) categ_class_func1
{
int i = (int)[self class_func0]; /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */
i += [self class_func1];
i += [self categ_class_func2];
i += (int)[self categ_instance_func1]; /* { dg-warning ".Derived. may not respond to .\\+categ_instance_func1." } */
return i + (int)[super class_func0]; /* { dg-warning ".Object. may not respond to .\\+class_func0." } */
}
+ (int) categ_class_func2
{
int i = [(id <Func>)self class_func0];
return i + [(id <Func>)super class_func0];
}
- (int) categ_instance_func1
{
int i = (int)[self instance_func0]; /* { dg-warning ".Derived. may not respond to .\\-instance_func0." } */
i += [(Derived <Func> *)self categ_instance_func2];
i += (int)[(Object <Func> *)self categ_instance_func2]; /* { dg-warning ".Object. may not respond to .\\-categ_instance_func2." } */
/* { dg-warning ".\\-categ_instance_func2. not implemented by protocol" "" { target *-*-* } 129 } */
i += (int)[(id <Func>)self categ_instance_func2]; /* { dg-warning ".\\-categ_instance_func2. not implemented by protocol" } */
i += [(id)self categ_instance_func2];
return i + (int)[super instance_func0]; /* { dg-warning ".Object. may not respond to .\\-instance_func0." } */
}
- (int) categ_instance_func2
{
return [(id <Func>)super instance_func0];
}
@end
/* Check if sending messages to super does not interfere with sending messages
to classes. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
/* { dg-options "-lobjc" } */
#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
@interface Base: Object
+ (int) class_func1;
- (int) instance_func1;
@end
@interface Derived: Base
+ (int) class_func1;
@end
@interface Derived (Categ)
- (int) instance_func1;
@end
@implementation Base
+ (int) class_func1 { return 234; }
- (int) instance_func1 { return 345; }
@end
@implementation Derived
+ (int) class_func1 {
int i = [super class_func1];
i += [Base class_func1];
return i;
}
@end
@implementation Derived (Categ)
- (int) instance_func1 {
int i = [super instance_func1];
i += [Base class_func1]; /* { dg-bogus "invalid receiver type" } */
return i;
}
@end
int main(void) {
Base *base = [[Base alloc] init]; /* { dg-bogus "invalid receiver type" } */
Derived *derived = [[Derived alloc] init];
CHECK_IF([Base class_func1] == 234); /* { dg-bogus "invalid receiver type" } */
CHECK_IF([Derived class_func1] == 234 + 234);
CHECK_IF([base instance_func1] == 345);
CHECK_IF([derived instance_func1] == 234 + 345);
return 0;
}
/* Test class methods inside categories. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-lobjc" } */
/* { dg-do run } */
#include <objc/Object.h>
#ifdef __NEXT_RUNTIME__
#define SUPERCLASS superclass
#else
#define SUPERCLASS superClass
#endif
extern int strcmp(const char *s1, const char *s2);
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
@interface MyObject: Object
+ (Class)whatever1;
@end
@implementation MyObject
+ (Class)whatever1 { return [super SUPERCLASS]; }
@end
@interface MyObject (ThisWontCompile)
+(Class)whatever2;
@end
@implementation MyObject (ThisWontCompile)
+(Class)whatever2 { return [super SUPERCLASS]; }
@end
int main (int argc, const char * argv[])
{
Class w1 = [MyObject whatever1];
Class w2 = [MyObject whatever2];
CHECK_IF(!strcmp(w1->name, "Object"));
CHECK_IF(!strcmp(w2->name, "Object"));
return 0;
}
...@@ -10,6 +10,5 @@ ...@@ -10,6 +10,5 @@
@interface class1 : supclass1 @interface class1 : supclass1
@end @end
@implementation class1 : supclass2 @implementation class1 : supclass2 /* { dg-error "conflicting super class name" } */
@end /* { dg-error "conflicting super class name" } */ @end /* { dg-error "previous declaration" "" { target *-*-* } 13 } */
/* { dg-error "previous declaration" "" { target *-*-* } 14 } */
...@@ -41,7 +41,7 @@ int main() ...@@ -41,7 +41,7 @@ int main()
MyProtocol), but not from an 'id' or from a 'MyOtherClass *' MyProtocol), but not from an 'id' or from a 'MyOtherClass *'
(which implements MyProtocol). */ (which implements MyProtocol). */
obj_p = obj; /* Ok */ obj_p = obj; /* Ok */
obj_p = obj_c; /* { dg-warning "does not implement" } */ /*FIXME: Duplicated*/ obj_p = obj_c; /* { dg-warning "does not implement" } */
obj_p = obj_cp; /* Ok */ obj_p = obj_cp; /* Ok */
obj_p = obj_C; /* { dg-warning "incompatible pointer type" } */ obj_p = obj_C; /* { dg-warning "incompatible pointer type" } */
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
/* { dg-do compile } */ /* { dg-do compile } */
#include <objc/objc.h> #include <objc/objc.h>
/* The NeXT runtime headers do not define NULL. */
#ifndef NULL
#define NULL ((void *)0)
#endif
@protocol MyProtocol @protocol MyProtocol
- (void) method; - (void) method;
@end @end
......
...@@ -2,12 +2,21 @@ ...@@ -2,12 +2,21 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-fgnu-runtime" } */ /* { dg-options "-fgnu-runtime" } */
#ifdef __cplusplus
extern void baz(...);
#endif
void foo() void foo()
{ {
baz(@"hiya"); /* { dg-error "annot find interface declaration" } */ baz(@"hiya"); /* { dg-error "annot find interface declaration" } */
} }
@interface NXConstantString @interface NXConstantString
{
void *isa;
char *str;
int len;
}
@end @end
void bar() void bar()
......
/* Test the -fconstant-string-class=Foo option under the NeXT
runtime. */
/* Developed by Markus Hitter <mah@jump-ing.de>. */
/* { dg-options "-fnext-runtime -fconstant-string-class=Foo -lobjc" } */
/* { dg-do run { target *-*-darwin* } } */
#include <stdio.h>
#include <objc/objc.h>
#include <objc/Object.h>
@interface Foo: Object {
char *cString;
unsigned int len;
}
- (char *)customString;
@end
struct objc_class _FooClassReference;
@implementation Foo : Object
- (char *)customString {
return cString;
}
@end
int main () {
Foo *string = @"bla";
Foo *string2 = @"bla";
if(string != string2)
abort();
printf("Strings are being uniqued properly\n");
/* This memcpy has to be done before the first message is sent to a
constant string object. Can't be moved to +initialize since _that_
is already a message. */
memcpy(&_FooClassReference, objc_getClass("Foo"), sizeof(_FooClassReference));
if (strcmp ([string customString], "bla")) {
abort ();
}
printf([@"This is a working constant string object\n" customString]);
return 0;
}
/* Ensure that the preprocessor handles ObjC string constants gracefully. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-options "-fnext-runtime -fconstant-string-class=MyString -lobjc" } */
/* { dg-do run { target *-*-darwin* } } */
extern void abort(void);
@interface MyString
{
void *isa;
char *str;
int len;
}
@end
#define kMyStringMacro1 "My String"
#define kMyStringMacro2 @"My String"
void *_MyStringClassReference;
@implementation MyString
@end
int main(void) {
MyString* aString1 = @kMyStringMacro1;
MyString* aString2 = kMyStringMacro2;
if(aString1 != aString2) {
abort();
}
return 0;
}
/* Positive test case for constant string layout. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fconstant-string-class=MyConstantString" } */
/* { dg-do compile } */
@interface MyBase {
const char *p;
}
@end
@interface MyConstantString: MyBase {
union {
void *u;
unsigned char *c;
} _contents;
unsigned int _count;
}
@end
/* The NeXT runtime initializes the 'isa' pointer of string constants at
compile time. */
#ifdef __NEXT_RUNTIME__
extern void *_MyConstantStringClassReference;
#endif
MyConstantString *str = @"Hello";
/* Negative test case for constant string layout. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fconstant-string-class=MyConstantString" } */
/* { dg-do compile } */
@interface MyBase {
char p;
}
@end
@interface MyConstantString: MyBase {
union {
void *u;
unsigned char *c;
} _contents;
char _count;
}
@end
/* The NeXT runtime initializes the 'isa' pointer of string constants at
compile time. */
#ifdef __NEXT_RUNTIME__
extern void *_MyConstantStringClassReference;
#endif
MyConstantString *str = @"Hello"; /* { dg-error "interface .MyConstantString. does not have valid constant string layout" } */
...@@ -22,7 +22,10 @@ ...@@ -22,7 +22,10 @@
0, 0,
[Cls meth1], [Cls meth1],
[2 + 1] = 3, [2 + 1] = 3,
[2 * 2 ... 5] = [0 meth2], /* { dg-warning "invalid receiver type" } */ [2 * 2 ... 5] = (int)[0 meth2], /* { dg-warning "invalid receiver type" } */
/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 25 } */
/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 25 } */
/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 25 } */
[2] [Cls meth2] [2] [Cls meth2]
}; };
......
/* Test if the Objective-C @encode machinery distinguishes between
'BOOL *' (which should be encoded as a pointer to BOOL) and 'char *' (which
should be encoded as '*'). This is somewhat tricky wrt the NeXT runtime,
where we have 'typedef char BOOL'. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fnext-runtime -lobjc" } */
/* { dg-do run } */
#include <string.h>
#include <stdlib.h>
#include <objc/objc.h>
int main(void) {
const char *BOOL_ptr = @encode(BOOL *);
const char *BOOL_ = @encode(BOOL);
const char *char_ptr = @encode(char *);
if(*BOOL_ptr != '^' || strcmp(BOOL_ptr + 1, BOOL_))
abort();
if(strcmp(char_ptr, "*"))
abort();
return 0;
}
/* Test Objective-C method encodings. */
/* The _encoded_ parameter offsets for Objective-C methods are
computed inductively as follows:
- The first paramter (self) has offset 0;
- The k-th parameter (k > 1) has offset equal to the
sum of:
- the offset of the k-1-st paramter
- the int-promoted size of the k-1-st parameter.
Note that the encoded offsets need not correspond
to the actual placement of parameters (relative to 'self')
on the stack! Your target's ABI may have very different
opinions on the matter. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
#ifdef __NEXT_RUNTIME__
#define METHOD Method
#define OBJC_GETCLASS objc_getClass
#define CLASS_GETINSTANCEMETHOD class_getInstanceMethod
#else
#include <objc/objc-api.h>
#define METHOD Method_t
#define OBJC_GETCLASS objc_get_class
#define CLASS_GETINSTANCEMETHOD class_get_instance_method
#endif
extern int sscanf(const char *str, const char *format, ...);
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
@interface Foo: Object
typedef struct { float x, y; } XXPoint;
typedef struct { float width, height; } XXSize;
typedef struct _XXRect { XXPoint origin; XXSize size; } XXRect;
-(id)setRect:(XXRect)r withInt:(int)i;
-(void) char:(char)c float:(float)f double:(double)d long:(long)l;
@end
XXRect my_rect;
unsigned offs1, offs2, offs3, offs4, offs5, offs6, offs7;
@implementation Foo
-(id)setRect:(XXRect)r withInt:(int)i {
unsigned offs = sizeof(self);
CHECK_IF(offs == offs3);
offs += sizeof(_cmd);
CHECK_IF(offs == offs4);
offs += sizeof(r);
CHECK_IF(offs == offs5);
offs += sizeof(i);
CHECK_IF(offs == offs1);
return nil;
}
-(void) char:(char)c float:(float)f double:(double)d long:(long)l {
unsigned offs = sizeof(self);
CHECK_IF(offs == offs3);
offs += sizeof(_cmd);
CHECK_IF(offs == offs4);
offs += sizeof((int)c);
CHECK_IF(offs == offs5);
offs += sizeof(f);
CHECK_IF(offs == offs6);
offs += sizeof(d);
CHECK_IF(offs == offs7);
offs += sizeof(l);
CHECK_IF(offs == offs1);
}
@end
int main(void) {
Foo *foo = [[Foo alloc] init];
Class fooClass = OBJC_GETCLASS("Foo");
METHOD meth;
meth = CLASS_GETINSTANCEMETHOD(fooClass, @selector(setRect:withInt:));
offs2 = 9999;
sscanf(meth->method_types, "@%u@%u:%u{_XXRect={?=ff}{?=ff}}%ui%u", &offs1, &offs2, &offs3,
&offs4, &offs5);
CHECK_IF(!offs2);
[foo setRect:my_rect withInt:123];
meth = CLASS_GETINSTANCEMETHOD(fooClass, @selector(char:float:double:long:));
offs2 = 9999;
sscanf(meth->method_types, "v%u@%u:%uc%uf%ud%ul%u", &offs1, &offs2, &offs3,
&offs4, &offs5, &offs6, &offs7);
CHECK_IF(!offs2);
[foo char:'c' float:2.3 double:3.5 long:2345L];
return 0;
}
/* Method encoding tests for stand-alone @protocol declarations. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
#include <objc/Protocol.h>
#ifdef __cplusplus
#define ProtoBool bool
#else
#define ProtoBool _Bool
#endif
#ifndef __NEXT_RUNTIME__
#include <objc/objc-api.h>
#endif
extern int sscanf(const char *str, const char *format, ...);
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
enum Enum {
zero, one, two, three
};
typedef enum Enum Enum;
typedef signed char ObjCBool; /* as used by the NeXT runtime */
@protocol Proto
union __XXAngle { unsigned int alpha, beta; };
typedef struct { float x, y; union __XXAngle a; } XXPoint;
typedef struct { double width, height; } XXSize;
typedef struct _XXRect { XXPoint origin; XXSize size; struct _XXRect *next; } XXRect;
- (void) char:(char)c float:(float)f double:(double)d unsigned:(unsigned)u short:(short)s long:(long)l;
- (void *)setRect:(XXRect)r withBool:(ProtoBool)b withInt:(int)i;
+ (Enum *)getEnum:(XXPoint *)pt enum:(enum Enum)e bool:(ObjCBool)b;
+ (ProtoBool **)getBool:(ObjCBool **)b;
@end
Protocol *proto = @protocol(Proto);
struct objc_method_description *meth;
unsigned totsize, offs0, offs1, offs2, offs3, offs4, offs5, offs6, offs7;
static void scan_initial(const char *pattern) {
totsize = offs0 = offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = offs7 = (unsigned)-1;
sscanf(meth->types, pattern, &totsize, &offs0, &offs1, &offs2, &offs3,
&offs4, &offs5, &offs6, &offs7);
CHECK_IF(!offs0 && offs1 == sizeof(id) && offs2 == offs1 + sizeof(SEL) && totsize >= offs2);
}
int main(void) {
meth = [proto descriptionForInstanceMethod: @selector(char:float:double:unsigned:short:long:)];
scan_initial("v%u@%u:%uc%uf%ud%uI%us%ul%u");
CHECK_IF(offs3 == offs2 + sizeof(int) && offs4 == offs3 + sizeof(float));
CHECK_IF(offs5 == offs4 + sizeof(double) && offs6 == offs5 + sizeof(unsigned));
CHECK_IF(offs7 == offs6 + sizeof(int) && totsize == offs7 + sizeof(long));
meth = [proto descriptionForInstanceMethod: @selector(setRect:withBool:withInt:)];
scan_initial("^v%u@%u:%u{_XXRect={?=ff(__XXAngle=II)}{?=dd}^{_XXRect}}%uB%ui%u");
CHECK_IF(offs3 == offs2 + sizeof(XXRect) && offs4 == offs3 + sizeof(int));
CHECK_IF(totsize == offs4 + sizeof(int));
meth = [proto descriptionForClassMethod: @selector(getEnum:enum:bool:)];
scan_initial("^i%u@%u:%u^{?=ff(__XXAngle=II)}%ui%uc%u");
CHECK_IF(offs3 == offs2 + sizeof(XXPoint *) && offs4 == offs3 + sizeof(enum Enum));
CHECK_IF(totsize == offs4 + sizeof(int)); /* 'ObjCBool' is really 'char' */
meth = [proto descriptionForClassMethod: @selector(getBool:)];
scan_initial("^^B%u@%u:%u^*%u");
CHECK_IF(totsize == offs2 + sizeof(ObjCBool **));
return 0;
}
/* Encoding tests for ObjC class layouts. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-lobjc" } */
/* { dg-do run } */
#include <objc/Object.h>
#ifdef __NEXT_RUNTIME__
#include <objc/objc-class.h>
#define OBJC_GETCLASS objc_getClass
#else
#include <objc/objc-api.h>
#define OBJC_GETCLASS objc_get_class
#endif
extern void abort(void);
extern int strcmp(const char *s1, const char *s2);
#define CHECK_IF(expr) if(!(expr)) abort()
@class Int1, Int2;
struct Nested;
struct Innermost {
unsigned char a, b;
struct Nested *encl;
};
struct Nested {
float a, b;
Int1 *next;
struct Innermost innermost;
};
@interface Int1: Object {
char a, b;
Int2 *int2;
struct Nested nested;
}
@end
@interface Int2: Int1 {
struct Innermost *innermost;
Int1 *base;
}
@end
@implementation Int1
@end
@implementation Int2
@end
struct objc_ivar *ivar;
static void check_ivar(const char *name, const char *type) {
CHECK_IF(!strcmp(ivar->ivar_name, name));
CHECK_IF(!strcmp(ivar->ivar_type, type));
ivar++;
}
int main(void) {
ivar = ((Class)OBJC_GETCLASS("Int1"))->ivars->ivar_list;
check_ivar("a", "c");
check_ivar("b", "c");
check_ivar("int2", "@\"Int2\"");
check_ivar("nested",
"{Nested=\"a\"f\"b\"f\"next\"@\"Int1\"\"innermost\"{Innermost=\"a\"C\"b\"C\"encl\"^{Nested}}}");
ivar = ((Class)OBJC_GETCLASS("Int2"))->ivars->ivar_list;
check_ivar("innermost", "^{Innermost=CC^{Nested}}");
check_ivar("base", "@\"Int1\"");
return 0;
}
/* Test for handling of function pointer ivars */
/* { dg-do run } */
#include <objc/Object.h>
extern int strcmp(const char *, const char *);
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
typedef float (*floatfunc)(float, float);
@interface MyObject : Object
{
@public
int (*ivar)(int, int, int);
floatfunc ffunc;
}
- init;
@end
int foo(int a, int b, int c) {
return a + b + c;
}
float bar(float a, float b) {
return a * b;
}
@implementation MyObject
- - init {
[super init];
ivar = foo;
ffunc = bar;
return self;
}
@end
int main ()
{
MyObject *obj = [[MyObject alloc] init];
const char *enc = @encode(MyObject);
CHECK_IF(obj->ivar(4, 5, 6) == 15);
CHECK_IF(obj->ffunc(34.0, 45.0) == 34.0 * 45.0);
CHECK_IF(!strcmp(enc, "{MyObject=#^?^?}"));
return(0);
}
/* Test that compiling for the GNU runtime works (regardless of
the system runtime used). */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
/* { dg-options "-fgnu-runtime" } */
#include <objc/Object.h>
@interface FooBar: Object
- (void)boo;
@end
int main ()
{
id fooBarInst = [[FooBar alloc] init];
[fooBarInst boo];
return 0;
}
...@@ -3,14 +3,29 @@ ...@@ -3,14 +3,29 @@
// { dg-options "-Wall -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wshadow" } // { dg-options "-Wall -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wshadow" }
// { dg-do compile } // { dg-do compile }
#ifdef __NEXT_RUNTIME__
#include <Foundation/NSString.h>
#else
#include <objc/NXConstStr.h> #include <objc/NXConstStr.h>
#endif
#include <objc/Object.h> #include <objc/Object.h>
#include <objc/Protocol.h> #include <objc/Protocol.h>
#ifdef __NEXT_RUNTIME__
#include <objc/objc-runtime.h>
#else
#include <objc/encoding.h> #include <objc/encoding.h>
#include <objc/hash.h> #include <objc/hash.h>
#endif
#include <objc/objc-api.h> #include <objc/objc-api.h>
#ifndef __NEXT_RUNTIME__
#include <objc/objc-list.h> #include <objc/objc-list.h>
#endif
#include <objc/objc.h> #include <objc/objc.h>
#ifndef __NEXT_RUNTIME__
#include <objc/sarray.h> #include <objc/sarray.h>
#include <objc/thr.h> #include <objc/thr.h>
#include <objc/typedstream.h> #include <objc/typedstream.h>
#endif
/* Check if the '-freplace-objc-classes' option causes the
__OBJC,__image_info section to be emitted. This is only
usable on MacOS X 10.3 and later. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-freplace-objc-classes" } */
/* { dg-do compile { target *-*-darwin* } } */
#ifndef __NEXT_RUNTIME__
#error Feature not currently supported by the GNU runtime
#endif
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
@interface Base: Object {
@public
int a;
float b;
char c;
}
- init;
@end
@implementation Base
- - init {
[super init];
a = 123;
b = 1.23;
c = 'c';
return self;
}
@end
/* { dg-final { scan-assembler "\n.data\n.section __OBJC, __image_info\n\t.align.*\nL_OBJC_IMAGE_INFO:\n\t.long\t0\n\t.long\t1\n.data\n.objc_module_info\n" } } */
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
@interface class1 @interface class1
- (int) meth1; - (int) meth1;
- (void) meth1; /* { dg-error "duplicate declaration of instance method" } */ - (void) meth1; /* { dg-error "duplicate declaration of method .\\-meth1." } */
@end @end
@interface class2 @interface class2
+ (void) meth1; + (void) meth1;
+ (int) meth1; /* { dg-error "duplicate declaration of class method" } */ + (int) meth1; /* { dg-error "duplicate declaration of method .\\+meth1." } */
@end @end
@interface class3 @interface class3
...@@ -17,8 +17,7 @@ ...@@ -17,8 +17,7 @@
@implementation class3 @implementation class3
- (int) meth1 { return 0; } - (int) meth1 { return 0; }
- (int) meth1 { return 0; } /* { dg-error "duplicate definition of instance method" } */ - (int) meth1 { return 0; } /* { dg-error "redefinition of" } */
/* { dg-error "redefinition of" "" { target *-*-* } 20 } */
/* { dg-error "previously defined here" "" { target *-*-* } 19 } */ /* { dg-error "previously defined here" "" { target *-*-* } 19 } */
@end @end
...@@ -28,7 +27,6 @@ ...@@ -28,7 +27,6 @@
@implementation class4 @implementation class4
+ (void) meth1 {} + (void) meth1 {}
+ (void) meth1 {} /* { dg-error "duplicate definition of class method" } */ + (void) meth1 {} /* { dg-error "redefinition of" } */
/* { dg-error "redefinition of" "" { target *-*-* } 31 } */ /* { dg-error "previously defined here" "" { target *-*-* } 29 } */
/* { dg-error "previously defined here" "" { target *-*-* } 30 } */
@end @end
/* When there is only one candidate method available, make sure the
compiler uses its argument/return types when constructing the
message sends (so that proper C/C++ argument conversions may
take place). */
/* { dg-do run } */
#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
static double d = 4.5920234e2;
@interface Foo : Object
-(void) brokenType: (int)x floatingPoint: (double)y;
@end
@implementation Foo
-(void) brokenType: (int)x floatingPoint: (double)y
{
CHECK_IF(x == 459);
CHECK_IF(y == d);
}
@end
int main(void)
{
Foo *foo=[Foo new];
[foo brokenType: d floatingPoint: d];
return 0;
}
/* Ensure that we indeed cannot obtain the value of a message send
if the chosen method signature returns 'void'. There used to
exist a cheesy hack that allowed it. While at it, check that
the first lexically occurring method signature gets picked
when sending messages to 'id'. */
/* Contributed by Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
#include <objc/objc.h>
@interface Object1
- (void)initWithData:(Object1 *)data;
@end
@interface Object2
- (id)initWithData:(Object1 *)data;
@end
@interface Object3
- (id)initWithData:(Object2 *)data;
@end
void foo(void) {
id obj1, obj2 = 0;
obj2 = [obj1 initWithData: obj2];
/* { dg-warning "multiple methods named .\\-initWithData:. found" "" { target *-*-* } 25 } */
/* { dg-warning "using .\\-\\(void\\)initWithData:\\(Object1 \\*\\)data." "" { target *-*-* } 12 } */
/* { dg-warning "also found .\\-\\(id\\)initWithData:\\(Object1 \\*\\)data." "" { target *-*-* } 16 } */
/* { dg-warning "also found .\\-\\(id\\)initWithData:\\(Object2 \\*\\)data." "" { target *-*-* } 20 } */
/* The following error is a consequence of picking the "wrong" method signature. */
/* { dg-error "void value not ignored as it ought to be" "" { target *-*-* } 25 } */
}
/* Contributed by Igor Seleznev <selez@mail.ru>. */
/* This used to be broken. */
#include <objc/objc-api.h>
@interface A
+ (A *)currentContext;
@end
@interface B
+ (B *)currentContext;
@end
int main()
{
[A currentContext]; /* { dg-bogus "multiple declarations" } */
return 0;
}
@implementation A
+ (A *)currentContext { return nil; }
@end
@implementation B
+ (B *)currentContext { return nil; }
@end
...@@ -22,10 +22,11 @@ ...@@ -22,10 +22,11 @@
[self rootInstanceMethod]; /* class is searched for an instance method */ [self rootInstanceMethod]; /* class is searched for an instance method */
[MyIntermediate rootInstanceMethod]; /* with the same name. */ [MyIntermediate rootInstanceMethod]; /* with the same name. */
[self instanceMethod]; /* { dg-warning "cannot find class" } */ [self instanceMethod]; /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */
/* { dg-warning "defaults to id" "" { target *-*-* } 25 } */ /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 25 } */
[MyDerived instanceMethod]; /* { dg-warning "cannot find class" } */ /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 25 } */
/* { dg-warning "defaults to id" "" { target *-*-* } 27 } */ /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 25 } */
[MyDerived instanceMethod]; /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */
} }
@end @end
/* Test for sending messages to aliased classes (and instances thereof). */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-lobjc" } */
/* { dg-do run } */
#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
@interface Int1: Object
+ (int) classMeth;
- (int) instanceMeth;
@end
@interface Int2: Object
+ (int) classMeth;
- (int) instanceMeth;
@end
@implementation Int1
+ (int) classMeth { return 345; }
- (int) instanceMeth { return 697; }
@end
@implementation Int2
+ (int) classMeth { return 1345; }
- (int) instanceMeth { return 1697; }
@end
typedef Int1 Int1Typedef;
@compatibility_alias Int1Alias Int1Typedef;
@compatibility_alias Int2Alias Int2;
typedef Int2Alias Int2Typedef;
int main(void) {
Int1Alias *int1alias = [[Int1Typedef alloc] init];
Int2Typedef *int2typedef = [[Int2Alias alloc] init];
CHECK_IF([Int1Typedef classMeth] == 345 && [Int2Alias classMeth] == 1345);
CHECK_IF([int1alias instanceMeth] == 697 && [int2typedef instanceMeth] == 1697);
CHECK_IF([(Int2Typedef *)int1alias instanceMeth] == 697);
CHECK_IF([(Int1Alias *)int2typedef instanceMeth] == 1697);
return 0;
}
/* Check if class references (generated for the NeXT runtime) are appropriately
folded. This test is safe to run on all targets. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fnext-runtime" } */
/* { dg-do compile } */
#include <objc/Object.h>
typedef Object ObjectTypedef1;
typedef ObjectTypedef1 ObjectTypedef2;
@compatibility_alias ObjectAlias1 ObjectTypedef2;
@compatibility_alias ObjectAlias2 ObjectAlias1;
typedef ObjectAlias2 ObjectTypedef3;
void foo(void) {
id obj = [Object new];
obj = [ObjectTypedef1 new];
obj = [ObjectTypedef2 new];
obj = [ObjectTypedef3 new];
obj = [ObjectAlias1 new];
obj = [ObjectAlias2 new];
}
/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */
/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_1" } } */
/* Check if sending messages to "underspecified" objects is handled gracefully. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
@class UnderSpecified;
typedef struct NotAClass {
int a, b;
} NotAClass;
void foo(UnderSpecified *u, NotAClass *n) {
[n nonexistent_method]; /* { dg-warning "invalid receiver type" } */
/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 11 } */
/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 11 } */
/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 11 } */
[NotAClass nonexistent_method]; /* { dg-error ".NotAClass. is not an Objective\\-C class name or alias" } */
[u nonexistent_method]; /* { dg-warning ".UnderSpecified. may not respond to .\\-nonexistent_method." } */
[UnderSpecified nonexistent_method]; /* { dg-warning ".UnderSpecified. may not respond to .\\+nonexistent_method." } */
}
/* Check that sending messages to variables of type 'Class' does not involve instance methods. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
#include <objc/Protocol.h>
@interface Base
- (unsigned)port;
- (id)starboard;
@end
@interface Derived: Base
- (Object *)port;
+ (Protocol *)port;
@end
id foo(void) {
Class receiver;
id p = [receiver port]; /* there should be no warnings here! */
p = [receiver starboard]; /* { dg-warning ".Class. may not respond to .\\+starboard." } */
/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 20 } */
/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 20 } */
/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 20 } */
p = [Class port]; /* { dg-error ".Class. is not an Objective\\-C class name or alias" } */
return p;
}
/* Check if finding multiple signatures for a method is handled gracefully. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
#include <objc/Object.h>
@interface Class1
- (void)setWindow:(Object *)wdw;
@end
@interface Class2
- (void)setWindow:(Class1 *)window;
@end
id foo(void) {
Object *obj = [[Object alloc] init];
id obj2 = obj;
[obj setWindow:nil]; /* { dg-warning ".Object. may not respond to .\\-setWindow:." } */
/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 18 } */
/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 18 } */
/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 18 } */
[obj2 setWindow:nil]; /* { dg-warning "multiple methods named .\\-setWindow:. found" } */
/* { dg-warning "using .\\-\\(void\\)setWindow:\\(Object \\*\\)wdw." "" { target *-*-* } 8 } */
/* { dg-warning "also found .\\-\\(void\\)setWindow:\\(Class1 \\*\\)window." "" { target *-*-* } 12 } */
return obj;
}
/* Check if casting the receiver type causes method lookup to succeed. This was broken
in Objective-C++. */
/* Contributed by Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
@interface A
@end
@interface B: A
- (void)f;
@end
void g(A *p) { [(B *)p f]; }
/* Check if finding multiple signatures for a method is handled gracefully
when method lookup succeeds (see also method-7.m). */
/* Contributed by Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
#include <objc/Object.h>
@protocol MyObject
- (id)initWithData:(Object *)data;
@end
@protocol SomeOther
- (id)initWithData:(int)data;
@end
@protocol MyCoding
- (id)initWithData:(id<MyObject, MyCoding>)data;
@end
@interface NTGridDataObject: Object <MyCoding>
{
Object<MyCoding> *_data;
}
+ (NTGridDataObject*)dataObject:(id<MyObject, MyCoding>)data;
@end
@implementation NTGridDataObject
- (id)initWithData:(id<MyObject, MyCoding>)data {
return data;
}
+ (NTGridDataObject*)dataObject:(id<MyObject, MyCoding>)data
{
NTGridDataObject *result = [[NTGridDataObject alloc] initWithData:data];
/* { dg-warning "multiple methods named .\\-initWithData:. found" "" { target *-*-* } 33 } */
/* { dg-warning "using .\\-\\(id\\)initWithData:\\(Object \\*\\)data." "" { target *-*-* } 9 } */
/* { dg-warning "also found .\\-\\(id\\)initWithData:\\(id <MyObject, MyCoding>\\)data." "" { target *-*-* } 17 } */
/* { dg-warning "also found .\\-\\(id\\)initWithData:\\(int\\)data." "" { target *-*-* } 13 } */
/* The following warning is a consequence of picking the "wrong" method signature. */
/* { dg-warning "passing arg 1 of .initWithData:. from incompatible pointer type" "" { target *-*-* } 33 } */
return result;
}
@end
/* Test for graceful handling of missing protocol declarations. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
@interface Foo <Missing> /* { dg-error "cannot find protocol declaration for .Missing." } */
@end
/* Test for graceful handling of missing protocol declarations. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
void *protRef = @protocol(Missing); /* { dg-error "cannot find protocol declaration for .Missing." } */
/* Ensure that the compiler gracefully handles missing protocol declarations.
In addition to not crashing :-), the compiler should properly handle
valid protocol references, even when they're mixed with invalid ones. */
/* { dg-do compile } */
#include <objc/objc.h>
@protocol DefinedProtocol
- (id) missingMethod1;
@end
@interface MyClass <UndefinedProtocol, DefinedProtocol>
/* { dg-error "cannot find protocol declaration for .UndefinedProtocol." "" { target *-*-* } 12 } */
@end
@implementation MyClass
+(Class)class
{
return self;
}
@end
/* { dg-warning "incomplete implementation of class .MyClass." "" { target *-*-* } 21 } */
/* { dg-warning "method definition for .\\-missingMethod1. not found" "" { target *-*-* } 21 } */
/* { dg-warning "class .MyClass. does not fully implement the .DefinedProtocol. protocol" "" { target *-*-* } 21 } */
/* Test basic nested C function functionality within ObjC
methods. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-lobjc" } */
/* { dg-do run } */
#include <stdio.h>
#include <objc/objc.h>
#include <objc/Object.h>
int bappy (int (*blargh) (int a, int b, int c))
{
return blargh (4, 7, 2) + 3;
}
@interface Foo: Object
+ (int)foo;
@end
@implementation Foo
+ (int)foo
{
int blargh (int a, int b, int c)
{
return a * b + c;
}
return bappy (blargh);
}
@end
int main ()
{
int f = [Foo foo];
if (f != 33)
abort ();
return 0;
}
...@@ -48,7 +48,9 @@ int foo(void) { ...@@ -48,7 +48,9 @@ int foo(void) {
id<Booing, Fooing> stupidVar; id<Booing, Fooing> stupidVar;
[stupidVar boo]; [stupidVar boo];
[stupidVar foo]; [stupidVar foo];
[stupidVar anotherMsg]; /* { dg-warning "not implemented by protocol" } */ [stupidVar anotherMsg]; /* { dg-warning ".\-anotherMsg. not implemented by protocol" } */
/* { dg-warning "return type defaults to id" "" { target *-*-* } 51 } */ /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 51 } */
/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 51 } */
/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 51 } */
return 0; return 0;
} }
...@@ -35,7 +35,12 @@ typedef struct objc_object { struct objc_class *class_pointer; } *id; ...@@ -35,7 +35,12 @@ typedef struct objc_object { struct objc_class *class_pointer; } *id;
return (id <NSObject>)plate1; /* { dg-bogus "does not conform" } */ return (id <NSObject>)plate1; /* { dg-bogus "does not conform" } */
} }
- (int) getValue { - (int) getValue {
int i = [plate1 someValue]; /* { dg-warning "not implemented by protocol" } */ int i = [plate1 someValue]; /* { dg-warning ".\\-someValue. not implemented by protocol\\(s\\)" } */
/* { dg-warning "\\(Messages without a matching method signature" "" { target *-*-* } 38 } */
/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 38 } */
/* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 38 } */
/* { dg-warning "initialization makes integer from pointer without a cast" "" { target *-*-* } 38 } */
int j = [(id <NSObject>)plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */ int j = [(id <NSObject>)plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */
int k = [(id)plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */ int k = [(id)plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */
return i + j + k; return i + j + k;
......
/* Don't forget to look in protocols if a class (and its superclasses) do not
provide a suitable method. */
/* { dg-do compile } */
#include <objc/Object.h>
@protocol Zot
-(void) zot;
@end
@interface Foo : Object <Zot>
@end
int foo()
{
Foo *f=nil;
[f zot]; /* There should be no warnings here! */
return 0;
}
/* Check that protocol qualifiers are compiled and encoded properly. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-options "-lobjc" } */
/* { dg-do run } */
#include <objc/Protocol.h>
#ifndef __NEXT_RUNTIME__
#include <objc/objc-api.h>
#endif
extern int sscanf(const char *str, const char *format, ...);
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
@protocol Retain
+ (oneway void)retainArgument:(out bycopy id)arg1 with:(in signed char **)arg2;
- (bycopy) address:(byref inout id)location with:(out short unsigned **)arg2;
@end
@interface Foo <Retain>
+ (oneway void)retainArgument:(out bycopy id)arg with:(in signed char **)arg2;
@end
@implementation Foo
+ (oneway void)retainArgument:(out bycopy id)arg1 with:(in signed char **)arg2 { }
- (bycopy) address:(byref inout id)location with:(out short unsigned **)arg2 { return nil; }
@end
Protocol *proto = @protocol(Retain);
struct objc_method_description *meth;
unsigned totsize, offs0, offs1, offs2, offs3, offs4, offs5, offs6, offs7;
static void scan_initial(const char *pattern) {
totsize = offs0 = offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = offs7 = (unsigned)-1;
sscanf(meth->types, pattern, &totsize, &offs0, &offs1, &offs2, &offs3,
&offs4, &offs5, &offs6, &offs7);
CHECK_IF(!offs0 && offs1 == sizeof(id) && offs2 == offs1 + sizeof(SEL) && totsize >= offs2);
}
int main(void) {
meth = [proto descriptionForInstanceMethod: @selector(address:with:)];
scan_initial("O@%u@%u:%uNR@%uo^^S%u");
CHECK_IF(offs3 == offs2 + sizeof(id) && totsize == offs3 + sizeof(unsigned));
meth = [proto descriptionForClassMethod: @selector(retainArgument:with:)];
scan_initial("Vv%u@%u:%uOo@%un^*%u");
CHECK_IF(offs3 == offs2 + sizeof(id) && totsize == offs3 + sizeof(char **));
return 0;
}
/* Check that the sizeof() operator works with ObjC classes and their aliases. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-lobjc" } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
@interface Foo: Object {
int a, b;
float c, d;
}
@end
@implementation Foo
@end
typedef Object MyObject;
typedef struct Foo Foo_type;
@compatibility_alias AliasObject Object;
int main(void) {
CHECK_IF(sizeof(Foo) > sizeof(Object) && sizeof(Object) > 0);
CHECK_IF(sizeof(Foo) == sizeof(Foo_type));
CHECK_IF(sizeof(Object) == sizeof(MyObject));
CHECK_IF(sizeof(Object) == sizeof(AliasObject));
return 0;
}
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/Object.h> #include <objc/Object.h>
#ifdef __NEXT_RUNTIME__
#define objc_get_class(C) objc_getClass(C)
#define class_create_instance(C) class_createInstance(C, 0)
#endif
/* Test loading unclaimed categories - categories of a class defined /* Test loading unclaimed categories - categories of a class defined
separately from the class itself. */ separately from the class itself. */
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
{ {
return 4; return 4;
} }
#ifdef __NEXT_RUNTIME__
+ initialize { return self; }
#endif
@end @end
......
/* Test out static (non-heap) allocations of ObjC class instances.
These should elicit errors. */
/* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
@interface Object {
struct objc_class *isa;
}
@end
@compatibility_alias MyObject Object;
@interface Foo: Object {
int a;
Object *b;
Object c; /* { dg-error "statically allocated instance of Objective-C class .Object." } */
}
@end
@compatibility_alias MyFoo Foo;
typedef Foo FooAlias1;
typedef FooAlias1 FooAlias2;
typedef Object ObjectAlias1;
typedef struct Object ObjectAlias2;
Object staticObject1; /* { dg-error "statically allocated instance of Objective-C class .Object." } */
struct Object staticObject2; /* { dg-error "statically allocated instance of Objective-C class .Object." } */
static ObjectAlias1 staticObject3; /* { dg-error "statically allocated instance of Objective-C class .Object." } */
FooAlias1 staticFoo1; /* { dg-error "statically allocated instance of Objective-C class .Foo." } */
extern FooAlias2 externFoo1; /* { dg-error "statically allocated instance of Objective-C class .Foo." } */
static Foo staticFoo2; /* { dg-error "statically allocated instance of Objective-C class .Foo." } */
MyObject staticMyObject1; /* { dg-error "statically allocated instance of Objective-C class .Object." } */
MyFoo staticMyFoo1; /* { dg-error "statically allocated instance of Objective-C class .Foo." } */
/* Check if the objc_symtab descriptor is being laid out correctly. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fnext-runtime" } */
/* { dg-do compile { target *-*-darwin* } } */
#include <objc/Object.h>
@interface Base: Object
- (void)setValues;
@end
@interface Derived: Base
- (void)checkValues;
@end
@implementation Base
-(void)setValues { }
@end
@implementation Derived
-(void)checkValues { }
@end
/* { dg-final { scan-assembler "L_OBJC_SYMBOLS:\n\t.long\t0\n\t.long\t0\n\t.short\t2\n\t.short\t0\n\t.long\tL_OBJC_CLASS_Derived\n\t.long\tL_OBJC_CLASS_Base\n" } } */
/* Test if the compiler accepts @throw / @try..@catch..@finally
syntax. This will only be usable on MacOS X 10.3 and later. */
/* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile { target *-*-darwin* } } */
#include <objc/objc.h>
#include <objc/objc-runtime.h>
#include <objc/Object.h>
#include <stdio.h>
#include <setjmp.h>
@interface Frob: Object
@end
@implementation Frob: Object
@end
static int exc_control = 0;
int proc() {
if(exc_control) {
printf ("Throwing (%d)... ", exc_control);
@throw [Frob new];
}
return 1;
}
int foo()
{
@try {
return proc();
}
@catch (Frob* ex) {
if(exc_control > 1) {
printf("Rethrowing (%d)... ", exc_control);
@throw;
}
return 0;
}
@finally {
printf("In @finally block (%d)... ", exc_control);
}
}
/* Test out '@catch(id foo) {...}', which should catch
all uncaught exceptions. */
/* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fobjc-exceptions -lobjc" } */
/* { dg-do run { target *-*-darwin[789]* } } */
#include <objc/objc.h>
#include <objc/objc-runtime.h>
#include <objc/Object.h>
#include <stdio.h>
/* The following is not required in actual user code; we include it
here to check that the compiler generates an internal definition of
_setjmp that is consistent with what <setjmp.h> provides. */
#include <setjmp.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
@interface Frob: Object
@end
@implementation Frob: Object
@end
static Frob* _connection = nil;
//--------------------------------------------------------------------
void test (Object* sendPort)
{
int cleanupPorts = 1;
Frob* receivePort = nil;
@try {
printf ("receivePort = %p\n", receivePort);
printf ("sendPort = %p\n", sendPort);
printf ("cleanupPorts = %d\n", cleanupPorts);
printf ("---\n");
receivePort = (Frob *) -1;
_connection = (Frob *) -1;
printf ("receivePort = %p\n", receivePort);
printf ("sendPort = %p\n", sendPort);
printf ("cleanupPorts = %d\n", cleanupPorts);
printf ("---\n");
receivePort = nil;
sendPort = nil;
cleanupPorts = 0;
printf ("receivePort = %p\n", receivePort);
printf ("sendPort = %p\n", sendPort);
printf ("cleanupPorts = %d\n", cleanupPorts);
printf ("---\n");
@throw [Object new];
}
@catch(Frob *obj) {
printf ("Exception caught by incorrect handler!\n");
CHECK_IF(0);
}
@catch(id exc) {
printf ("Exception caught by correct handler.\n");
printf ("receivePort = %p (expected 0x0)\n", receivePort);
printf ("sendPort = %p (expected 0x0)\n", sendPort);
printf ("cleanupPorts = %d (expected 0)\n", cleanupPorts);
printf ("---");
CHECK_IF(!receivePort);
CHECK_IF(!sendPort);
CHECK_IF(!cleanupPorts);
}
@catch(Object *obj) { /* { dg-warning "Exception already handled by preceding .\\@catch\\(id\\)." } */
printf ("Exception caught by incorrect handler!\n");
CHECK_IF(0);
}
}
int main (void) {
test((Object *)-1);
return 0;
}
/* Test if caught exception objects are accessible inside the
@catch block. (Yes, I managed to break this.) */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-options "-fobjc-exceptions" } */
#include <objc/Object.h>
const char *foo(void)
{
@try {
return "foo";
}
@catch (Object* theException) {
return [theException name];
}
}
/* Check that the compiler does not incorrectly complain about
exceptions being caught by previous @catch blocks. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-options "-Wall -fobjc-exceptions" } */
@interface Exception
@end
@interface FooException : Exception
@end
extern void foo();
void test()
{
@try {
foo();
}
@catch (FooException* fe) {
}
@catch (Exception* e) {
}
}
/* Reject ivars with an unknown size. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
struct unknownStruct;
@interface ArrayTest
{
short unknownSize[unknownValue]; /* { dg-error ".unknownValue. (undeclared|was not declared)" } */
/* { dg-error "instance variable .unknownSize. has unknown size" "" { target *-*-* } 9 } */
struct unknownStruct unknownObj; /* { dg-error "field .unknownObj. has incomplete type" } */
/* { dg-error "instance variable .unknownObj. has unknown size" "" { target *-*-* } 11 } */
long knownSize[3]; /* ok */
char zeroSize[2 - 2]; /* ok (apparently) */
int missingSize[]; /* { dg-error "instance variable .missingSize. has unknown size" } */
}
@end
/* Make sure that array arguments to methods are given the size of pointers. */
/* As in the case of ivars, arrays without size (e.g., 'int []') are
encoded as pointers as well. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
#include <objc/objc.h>
#ifdef __NEXT_RUNTIME__
#include <objc/objc-runtime.h>
#define OBJC_GETCLASS objc_getClass
#define CLASS_GETINSTANCEMETHOD class_getInstanceMethod
#else
#include <objc/objc-api.h>
#define OBJC_GETCLASS objc_get_class
#define CLASS_GETINSTANCEMETHOD class_get_instance_method
#endif
extern int sscanf(const char *str, const char *format, ...);
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort()
enum Enum { one, two, three, four };
@interface ArrayTest
- (const char *)str:(signed char [])arg1 with:(unsigned char *)arg2 and:(enum Enum[4])en;
- (int)meth1:(int [])arg1 with:(int [0])arg2 with:(int [2])arg3;
@end
@implementation ArrayTest
- (int)meth1:(int [])arg1 with:(int [0])arg2 with:(int [2])arg3 { return 0; }
- (const char *)str:(signed char [])arg1 with:(unsigned char *)arg2 and:(enum Enum[4])en { return "str"; }
@end
Class cls;
struct objc_method *meth;
unsigned totsize, offs0, offs1, offs2, offs3, offs4, offs5, offs6, offs7;
static void scan_initial(const char *pattern) {
totsize = offs0 = offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = offs7 = (unsigned)-1;
sscanf(meth->method_types, pattern, &totsize, &offs0, &offs1, &offs2, &offs3,
&offs4, &offs5, &offs6, &offs7);
CHECK_IF(!offs0 && offs1 == sizeof(id) && offs2 == offs1 + sizeof(SEL) && totsize >= offs2);
}
int main(void) {
cls = OBJC_GETCLASS("ArrayTest");
meth = CLASS_GETINSTANCEMETHOD(cls, @selector(str:with:and:));
scan_initial("r*%u@%u:%u*%u*%u[4i]%u");
CHECK_IF(offs3 == offs2 + sizeof(signed char *) && offs4 == offs3 + sizeof(unsigned char *));
CHECK_IF(totsize == offs4 + sizeof(enum Enum *));
meth = CLASS_GETINSTANCEMETHOD(cls, @selector(meth1:with:with:));
scan_initial("i%u@%u:%u^i%u[0i]%u[2i]%u");
CHECK_IF(offs3 == offs2 + sizeof(int *) && offs4 == offs3 + sizeof(int *));
CHECK_IF(totsize == offs4 + sizeof(int *));
return 0;
}
/* Check if the '-fzero-link' flag correctly emits an objc_getClass() call. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fnext-runtime -fzero-link" } */
/* { dg-do compile } */
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
@interface Base: Object
+ (int) getValue;
@end
@implementation Base
+ (int) getValue { return 1593; }
@end
int main(void) {
int val = [Base getValue];
CHECK_IF(val == 1593);
return 0;
}
/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_0" } } */
/* { dg-final { scan-assembler "objc_getClass" } } */
/* Check if the '-fno-zero-link' flag correctly _omits_ an objc_getClass() call. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-options "-fnext-runtime -fno-zero-link" } */
/* { dg-do compile } */
#include <objc/objc.h>
#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
@interface Base: Object
+ (int) getValue;
@end
@implementation Base
+ (int) getValue { return 1593; }
@end
int main(void) {
int val = [Base getValue];
CHECK_IF(val == 1593);
return 0;
}
/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */
/* { dg-final { scan-assembler-not "objc_getClass" } } */
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Test getting and calling the IMP of a method */ /* Test getting and calling the IMP of a method */
@interface TestClass @interface TestClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Test the hidden argument _cmd to method calls */ /* Test the hidden argument _cmd to method calls */
@interface TestClass @interface TestClass
...@@ -16,6 +18,9 @@ ...@@ -16,6 +18,9 @@
{ {
return sel_get_name (_cmd); return sel_get_name (_cmd);
} }
#ifdef __NEXT_RUNTIME__
+ initialize { return self; }
#endif
@end @end
......
#ifndef __NEXT_RUNTIME__
#include <objc/encoding.h> #include <objc/encoding.h>
#endif
#include "next_mapping.h"
void print_ivars (Class class) void print_ivars (Class class)
{ {
...@@ -59,7 +61,7 @@ int main () ...@@ -59,7 +61,7 @@ int main ()
@defs (MyObject); @defs (MyObject);
}; };
int size1, size2; int size1, size2;
Class class = [MyObject class]; Class class = objc_get_class ("MyObject");
printf ("type = %s\n", @encode (struct class_vars)); printf ("type = %s\n", @encode (struct class_vars));
print_ivars (class); print_ivars (class);
......
...@@ -12,7 +12,11 @@ ...@@ -12,7 +12,11 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/Object.h> #include <objc/Object.h>
#include <objc/Protocol.h> #include <objc/Protocol.h>
#ifndef __NEXT_RUNTIME__
#include <objc/encoding.h> #include <objc/encoding.h>
#endif
#include "next_mapping.h"
@protocol MyProtocol @protocol MyProtocol
+ (bycopy id<MyProtocol>) bycopyMethod; + (bycopy id<MyProtocol>) bycopyMethod;
......
#include <objc/Object.h>
@interface Foo : Object
+ + foo;
+ + bar;
@end
int foocalled = 0;
int barcalled = 0;
@implementation Foo
+ + foo
{
if (foocalled)
abort ();
foocalled = 1;
return self;
}
+ bar
{
if (barcalled)
abort ();
barcalled = 1;
return self;
}
@end
int main(int argc,char **argv)
{
[[Foo foo] bar];
return 0;
}
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a RootClass */ /* Tests creating a RootClass */
@interface RootClass @interface RootClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with an ivar and /* Tests creating a root class and a subclass with an ivar and
accessor methods and a subclass overriding the superclass' accessor methods and a subclass overriding the superclass'
implementation, and using self to call another method of itself */ implementation, and using self to call another method of itself */
...@@ -13,6 +15,9 @@ ...@@ -13,6 +15,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
@interface SubClass : RootClass @interface SubClass : RootClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with an ivar and /* Tests creating a root class and a subclass with an ivar and
accessor methods and a subclass overriding the superclass' accessor methods and a subclass overriding the superclass'
implementation and using self to call another method of itself - in implementation and using self to call another method of itself - in
...@@ -14,6 +16,9 @@ ...@@ -14,6 +16,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
@interface SubClass : RootClass @interface SubClass : RootClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with a class methods */ /* Tests creating a root class and a subclass with a class methods */
@interface RootClass @interface RootClass
...@@ -11,6 +13,9 @@ ...@@ -11,6 +13,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
static int class_variable = 0; static int class_variable = 0;
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with a class accessor /* Tests creating a root class and a subclass with a class accessor
methods and a subclass overriding the superclass' implementation methods and a subclass overriding the superclass' implementation
but reusing it with super */ but reusing it with super */
...@@ -13,6 +15,9 @@ ...@@ -13,6 +15,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
static int class_variable = 0; static int class_variable = 0;
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with a class accessor /* Tests creating a root class and a subclass with a class accessor
methods and a subclass overriding the superclass' implementation, methods and a subclass overriding the superclass' implementation,
and using self to call another method of itself */ and using self to call another method of itself */
...@@ -13,6 +15,9 @@ ...@@ -13,6 +15,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
static int class_variable = 0; static int class_variable = 0;
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass */ /* Tests creating a root class and a subclass */
@interface RootClass @interface RootClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a minimal subclass tree */ /* Tests creating a root class and a minimal subclass tree */
@interface RootClass @interface RootClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with an ivar and /* Tests creating a root class and a subclass with an ivar and
accessor methods */ accessor methods */
...@@ -12,6 +14,9 @@ ...@@ -12,6 +14,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
@interface SubClass : RootClass @interface SubClass : RootClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with an ivar and /* Tests creating a root class and a subclass with an ivar and
accessor methods and a subclass overriding the superclass' accessor methods and a subclass overriding the superclass'
implementation */ implementation */
...@@ -13,6 +15,9 @@ ...@@ -13,6 +15,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
@interface SubClass : RootClass @interface SubClass : RootClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with an ivar and /* Tests creating a root class and a subclass with an ivar and
accessor methods and a subclass overriding the superclass' accessor methods and a subclass overriding the superclass'
implementation but reusing it with super */ implementation but reusing it with super */
...@@ -13,6 +15,9 @@ ...@@ -13,6 +15,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
@interface SubClass : RootClass @interface SubClass : RootClass
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with an ivar and /* Tests creating a root class and a subclass with an ivar and
accessor methods; accessor methods implemented in a separate accessor methods; accessor methods implemented in a separate
category */ category */
...@@ -13,6 +15,9 @@ ...@@ -13,6 +15,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
@interface SubClass : RootClass @interface SubClass : RootClass
...@@ -49,6 +54,13 @@ int main (void) ...@@ -49,6 +54,13 @@ int main (void)
SubClass *object; SubClass *object;
test_class_with_superclass ("SubClass", "RootClass"); test_class_with_superclass ("SubClass", "RootClass");
/* The NeXT runtime's category implementation is lazy: categories are not attached
to classes until the class is initialized (at +initialize time). */
#ifdef __NEXT_RUNTIME__
[SubClass initialize];
#endif
test_that_class_has_instance_method ("SubClass", @selector (setState:)); test_that_class_has_instance_method ("SubClass", @selector (setState:));
test_that_class_has_instance_method ("SubClass", @selector (state)); test_that_class_has_instance_method ("SubClass", @selector (state));
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include "next_mapping.h"
/* Tests creating a root class and a subclass with an ivar and /* Tests creating a root class and a subclass with an ivar and
accessor methods and a subclass overriding the superclass' accessor methods and a subclass overriding the superclass'
implementation - in a category */ implementation - in a category */
...@@ -13,6 +15,9 @@ ...@@ -13,6 +15,9 @@
@end @end
@implementation RootClass @implementation RootClass
#ifdef __NEXT_RUNTIME__
+ + initialize { return self; }
#endif
@end @end
@interface SubClass : RootClass @interface SubClass : RootClass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment