From 5bfc7db451684e8c22024c4b4da99cca401563d3 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Sun, 5 Jan 2014 00:43:28 +0000 Subject: [PATCH] gcc: Add support for Apple's Block extension Block objects [1] are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed. This port is based on Apple's GCC 5646 with some bugfixes from Apple GCC 5666.3. It has some small differences with the support in clang, which remains the recommended compiler. Perhaps the most notable difference is that in GCC that __block is not actually a keyword, but a macro. There will be workaround for this issue in a near future. Other issues can be consulted in the clang documentation [2] For better compatiblity with Apple's GCC and llvm-gcc some related fixes and features from Apple have been included. Support for the non-standard nested functions in GCC is now off by default. No effort was made to update the ObjC support since FreeBSD doesn't carry ObjC in the base system, but some of the code crept in and was more difficult to remove than to adjust. Reference: [1] https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html [2] http://clang.llvm.org/compatibility.html#block-variable-initialization Obtained from: Apple GCC 4.2 MFC after: 3 weeks --- contrib/gcc/ChangeLog.apple | 902 +++++++++- contrib/gcc/attribs.c | 11 +- contrib/gcc/c-common.c | 359 +++- contrib/gcc/c-common.h | 213 ++- contrib/gcc/c-convert.c | 4 + contrib/gcc/c-cppbuiltin.c | 5 + contrib/gcc/c-decl.c | 1014 ++++++++++- contrib/gcc/c-objc-common.h | 6 + contrib/gcc/c-opts.c | 7 + contrib/gcc/c-parser.c | 1868 ++++++++++++++++++-- contrib/gcc/c-pretty-print.c | 26 +- contrib/gcc/c-pretty-print.h | 2 + contrib/gcc/c-tree.h | 10 + contrib/gcc/c-typeck.c | 550 +++++- contrib/gcc/c.opt | 12 + contrib/gcc/calls.c | 3 +- contrib/gcc/cgraph.h | 2 + contrib/gcc/cgraphunit.c | 16 +- contrib/gcc/convert.c | 61 +- contrib/gcc/convert.h | 2 + contrib/gcc/cp/ChangeLog.apple | 652 +++++++ contrib/gcc/cp/call.c | 32 +- contrib/gcc/cp/class.c | 31 +- contrib/gcc/cp/cp-gimplify.c | 25 +- contrib/gcc/cp/cp-objcp-common.c | 32 + contrib/gcc/cp/cp-objcp-common.h | 6 + contrib/gcc/cp/cp-tree.h | 44 +- contrib/gcc/cp/decl.c | 583 ++++++- contrib/gcc/cp/decl.h | 6 + contrib/gcc/cp/decl2.c | 129 +- contrib/gcc/cp/error.c | 11 +- contrib/gcc/cp/init.c | 14 +- contrib/gcc/cp/mangle.c | 7 + contrib/gcc/cp/name-lookup.c | 6 + contrib/gcc/cp/name-lookup.h | 2 + contrib/gcc/cp/parser.c | 2479 ++++++++++++++++++++++++++- contrib/gcc/cp/pt.c | 5 + contrib/gcc/cp/semantics.c | 179 +- contrib/gcc/cp/tree.c | 9 + contrib/gcc/cp/typeck.c | 299 +++- contrib/gcc/dbxout.c | 2 + contrib/gcc/doc/extend.texi | 41 +- contrib/gcc/doc/invoke.texi | 22 +- contrib/gcc/dwarf2.h | 9 +- contrib/gcc/dwarf2out.c | 34 +- contrib/gcc/expmed.c | 12 +- contrib/gcc/expr.c | 2 + contrib/gcc/fold-const.c | 2 + contrib/gcc/function.c | 174 +- contrib/gcc/function.h | 8 + contrib/gcc/ggc-common.c | 22 +- contrib/gcc/ggc.h | 6 +- contrib/gcc/langhooks-def.h | 18 + contrib/gcc/langhooks.c | 16 + contrib/gcc/langhooks.h | 12 + contrib/gcc/stor-layout.c | 2 + contrib/gcc/stub-objc.c | 278 ++- contrib/gcc/targhooks.c | 12 + contrib/gcc/toplev.c | 15 +- contrib/gcc/tree-gimple.h | 3 +- contrib/gcc/tree-nested.c | 10 +- contrib/gcc/tree.c | 30 + contrib/gcc/tree.def | 5 + contrib/gcc/tree.h | 69 +- contrib/gcc/varasm.c | 2 + contrib/gcclibs/include/libiberty.h | 4 + contrib/gcclibs/libiberty/physmem.c | 30 + 67 files changed, 10055 insertions(+), 409 deletions(-) diff --git a/contrib/gcc/ChangeLog.apple b/contrib/gcc/ChangeLog.apple index b2004ee16569..325a282c225b 100644 --- a/contrib/gcc/ChangeLog.apple +++ b/contrib/gcc/ChangeLog.apple @@ -1,8 +1,908 @@ -006-02-15 Fariborz Jahanian +2010-03-16 Fariborz Jahanian + + Radar 7760213 + * c-common.h (HasByrefArray): New decl. + * c-common.c (HasByrefArray): New definition. + * c-typeck.c (build_external_ref): Diagnose access of + __block array. + +2010-03-12 Jim Grosbach + + Radar 7744816 + + * expmed.c (synth_mult): Remove incorrect special case handling for + 0xffffffff. + +2010-03-12 Fariborz Jahanian + + Radar 7735196 + * c-parser.c (build_block_struct_initlist): + Set BLOCK_USE_STRET flag in block descriptor for + blocks which return their aggregate value in memory. + * c-common.h (BLOCK_USE_STRET): New flag. + +2010-03-05 Fariborz Jahanian + + Radar 7721728 + * c-typeck.c (build_external_ref): Diagnose + importation of copied-in variables. + +2009-03-12 Caroline Tice + + Radar 6144634 + * c-parser.c (c_parser_statement_after_labels): When + re-setting the expression location at the end, use the input + location for Block pointer assignments. + +2009-02-11 Fariborz Jahanian + + Radar 6573923 + * c-decl.c (synth_block_byref_id_object_copy_func, + synth_block_byref_id_object_dispose_func): Set BLOCK_BYREF_CALLER + flag in call to copy/dispose helper functions. + * c-common.h (BLOCK_BYREF_CALLER): New flag. + +2008-12-21 Caroline Tice + + Radar 6455678 + * cp/typeck.c (original_type): Stop if the type + and its DECL_ORIGINAL_TYPE are the same. + +2008-12-18 Bill Wendling + + Radar 6457359 + * c-parser.c (build_block_struct_initlist): Changed type. + * cp/parser.c (build_block_struct_initlist): Ditto. + +2008-12-02 Caroline Tice + + Radar 6386976 + * objcp/objcp-decl.h (TYPE_HAS_OBJCXX_INFO): New macro. + * objcp/objcp-lang.c (objcp-decl.h): New include statement, with + required define. + (LANG_HOOKS_IS_RUNTIME_SPECIFIC_TYPE): Redefine for + obj-c++. + (objcxx_is_runtime_type): New function. + +2008-12-02 Fariborz Jahanian + + Radar 6411649 + * funciton.h: Added new field. + * c-common.c (build_block_helper_name): Produce a unique + block number per each enclosing function when building + the block helper function name. + +2008-11-18 Stuart Hastings + + Radar 6353006 + * tree.c (generic_block_literal_struct_type): Fix APPLE LOCAL. + * langhooks-def.h (lhd_build_generic_block_struct_type): Fix + APPLE LOCAL. + +2008-11-07 Fariborz Jahanian + + Radar 5847976 + * c-decl.c (synth_block_byref_id_object_copy_func): Takes a new + 'flag' argument and generates the much simplified API. + (synth_block_byref_id_object_dispose_func): Ditto. + (new_block_byref_decl): Hack to prevent issuing bogus warning + on a field declared as __weak. + (init_byref_decl): Takes an additional 'flag' argument + and passes it down to synth_block_byref_id_object_copy_func and + synth_block_byref_id_object_dispose_func. + (finish_decl): Computes the flag for the block variable declaration. + * c-common.c (build_block_byref_release_decl, + build_block_byref_assign_copy_decl): Removed. + (build_block_byref_release_exp): Use the new API. + (build_block_object_assign_decl, build_block_object_assign_call_exp, + build_block_object_dispose_decl, build_block_object_dispose_call_exp): New. + (build_indirect_object_id_exp): Fixed a code gen bug which was exposed in + c/c++ mode, but not in ObjC/ObjC++ mode. + * c-common.h (build_block_object_assign_call_exp, + build_block_object_dispose_call_exp, + objc_is_gcable_type): New decls. + Declaration of several new flags. + (cast_to_pointer_to_id): Removed. + * stub-objc.c (objc_is_gcable_type): New + (copy_in_object, retain_block_component, release_block_component): Removed. + (cast_to_pointer_to_id): Removed. + * c-parser.c (build_block_struct_initlist): Remove call to copy_in_object. + (synth_copy_helper_block_func): Generates much simplified API. + (synth_destroy_helper_block_func): Ditto. + (block_object_dispose): Removed. + * config/darwin-c.c (darwin_cpp_builtins): Define __weak even when + -fobjc-gc is off. + +2008-10-31 Fariborz Jahanian + + Radar 6175959 + * stub-objc.c (block_requires_copying): Object pointers with + NSObject attribute also require copy/release API. + * c-parser.c (synth_copy_helper_block_func): Use the new API + _Block_object_assign for ObjC object copying. + (block_object_dispose): New + (synth_destroy_helper_block_func): Call block_object_dispose + to use new _Block_object_dispose API for ObjC object release. + +2008-10-27 Fariborz Jahanian + + Radar 6231433 + * c-typeck.c (objc_compare_types, objc_have_common_type): + Take an extra argument for better diagnostics. + * c-common.c (objc_compare_types, objc_have_common_type): + Take extra argument. + * stub-objc.c: Ditto + +2008-10-24 Fariborz Jahanian + + Radar 6305545 + * cgraph.h (lower_if_nested_functions): New decl. + * tree-gimple.h (lower_nested_functions): Takes one more arg. + * cgraphunit.c (lower_if_nested_functions): New + * tree-nested.c (lower_nested_functions): Skip structors. + +2008-10-24 Fariborz Jahanian + + Radar 5847213 (minor tweak) + * c-decl.c (build_block_descriptor_type): + Make descriptor_ptr_type and descriptor_ptr_type_with_copydispose + visible to pch. + +2008-10-23 Caroline Tice + + Radar 6300081 + * tree.c(build_block_pointer_type): Add call to + build_generic_block_struct_type to initialize + generic_block_literal_struct_type if necessary. + * cp/parser.c (build_generic_block_struct_type): Update comments. + (build_block_struct_type): Remove call to + build_generic_block_struct_type. + (make_block_pointer_declarator): Likewise. + * c-decl.c (make_block_pointer_declarator): Likewise. + * c-parser.c (build_block_struct_type): Likewise. + (build_generic_block_struct_type): Update comments. + +2008-10-22 Caroline Tice + + Radar 6300081 & Radar 6163705 + * tree.h (generic_block_literal_struct_type): Extern global variable + decl. + (build_generic_block_struct_type): New extern function decl. + * cp/parser (build_generic_block_struct_type): New function. + (build_block_struct_type): Call build_generic_block_struct_type + to initialize generic_block_literal_struct_type. + (make_block_pointer_declarator): Likewise. + (declare_block_prologue_local_vars): Temporarily set input_location + to 1 before the start of the block function; re-set input_location at + the end of this function. + * dwarf2out.c (add_type_attribute): If the type is a + BLOCK_POINTER_TYPE, assign it to be a pointer to a + generic_block_literal_struct_type. + * c-decl.c (make_block_pointer_declarator): Call + build_generic_block_struct_type to initialize + generic_block_literal_struct_type. + * c-common.c (generic_block_literal_struct_type): New global variable. + * c-parser.c (build_generic_block_struct_type): New function. + (build_block_struct_type): Call build_generic_block_struct_type + to initialize generic_block_literal_struct_type. + * testsuite/gcc.apple/block-debug-1.c: Fix test to work with new + compiler modifications. + * testsuite/gcc.apple/block-debug-2.c: Likewise. + * testsuite/g++.apple/block-debug-1.C: Likewise. + * testsuite/g++.apple/block-debug-2.C: Likewise. + +2008-10-10 Fariborz Jahanian + + Radar 5847213 - New Block ABI + * dwarf2out.c (add_type_attribute): Unusuable code + for radar 5811943 is removed. + * c-decl.c (build_block_byref_decl): Removed unneeded + build of block_original_byref_decl_list. + (build_block_internal_types): Removed. + (build_block_descriptor_type): New routine to build the descriptor type. + (make_block_pointer_declarator): Unused code is removed. + * c-typeck.c (build_block_call): New code gen for block calls. + * c-common.c (invoke_impl_ptr_type): Removed. + * c-common.h (block_original_byref_decl_list, build_block_internal_types): Removed + (build_block_descriptor_type, BLOCK_HAS_DESCRIPTOR): Decls added. + * c-parser.c (build_block_struct_type): Block literal expression internal type + is redeclared into its new layout. + (build_block_struct_initlist): Initializer list for above type is redone. + (build_descriptor_block_decl): New routine to declare the descriptor variable + (build_block_literal_tmp): Modified for the new type and initiazation. + +2008-10-06 Fariborz Jahanian + + Radar 6268817 + * c-decl.c (check_for_loop_decls): Block helper function + is OK if declared in a for-loop main statement block. + +2008-10-02 Fariborz Jahanian + + Radar 6246527 + * attribs.c (decl_attributes): Added support for adding attributes + on block pointer variable declarations. + * c-common.c (block_delta_format_args): Add + (any_recognized_block_attribute): Add + * c-common.h (any_recognized_block_attribute): New decl. + * c-parser.c (c_parser_block_literal_expr): Call to do the delta + on printf attribute. + +2008-09-30 Fariborz Jahanian + + Radar 6225809 + * c-decl.c (build_block_byref_decl): Add __block vaiables + to intervening blocks. + +2008-09-25 Fariborz Jahanian + + Radar 6237713 + * c-common.c (handle_noreturn_attribute): Add 'noreturn' + attribute to block pointer decls. + * c-parser.c (c_parser_block_literal_expr): Parse and set + attributes on block literals. + +2008-09-25 Fariborz Jahanian + + Radar 6244520 - minor addition + * c-common.c (build_indirect_object_id_exp): offset needs + be updated to accomodate addition of the new field. + +2008-09-16 Fariborz Jahanian + + Radar 6214617 + * c-common: New flag BLOCK_HAS_CXX_OBJ replaces BLOCK_NO_COPY. + (BlockImportsCxxObjects): New field replaces BlockHasByrefVar. + * c-parser.c (build_block_struct_type): Remove setting of + BLOCK_NO_COPY flag. + +2008-09-16 Fariborz Jahanian + + Radar 6217257 + * c-common.c (handle_blocks_attribute): Diagnose + vla __block declarations. + +2008-09-12 Fariborz Jahanian + + Radar 6212722 (tweak) + * c-decl.c (build_block_ref_decl): Use array_to_pointer_conversion + and function_to_pointer_conversion. + * c-typeck.c (array_to_pointer_conversion, function_to_pointer_conversion): + Made them global. + * c-common.h (array_to_pointer_conversion, function_to_pointer_conversion): + Declare. + +2008-09-09 Fariborz Jahanian + + Radar 6169580 + * c-commmon.c (build_block_helper_name): Fix bug in + block helper function name mangling. + +2008-09-03 Fariborz Jahanian + + Radar 6185344 + * c-typeck.c (c_finish_return): Don't do block specific + stuff when block has a return type. + * c-common.h (block_sema_info): block_has_return_type is + a new field. + * c-parser.c (c_parser_direct_declarator): Terminate type + parsing for block return types. + (c_parser_block_literal_expr): Added support to parse and + handle explicit return type for blocks. + +2008-08-28 Fariborz Jahanian + + Radar 6160536 + * c-commmon.c (build_block_helper_name): New + * c-common.h (build_block_helper_name): New decl. + * c-parser.c (c_parser_block_literal_expr): Call + build_block_helper_name to build pretty helper function + name. + +2008-08-28 Fariborz Jahanian + + Radar 6180456 + * c-decl.c (synth_block_byref_id_object_copy_func): Different + API for copying __block declared objects in c. + (synth_block_byref_id_object_dispose_func): Different API + for releasing __block declared objects in c. + * c-common.c (block_byref_assign_copy_decl): New + (build_indirect_object_id_exp): Cast to 'id *' in objective-c + mode only. + * c-common.h (build_block_byref_assign_copy_decl): New decl. + * c-parser.c (synth_copy_helper_block_func): Refactored code + to call build_block_byref_assign_copy_decl(). + +2008-08-24 Caroline Tice + + Radars 6144664, 6145471, 6144634 + c-decl.c (build_block_byref_decl): Assign the source + location for each byref decl to the source location of + the helper function decl. + (build_block_ref_decl): Ditto for ref decls. + +2008-08-14 Fariborz Jahanian + + Radar 5822844 + * c-typeck.c (digest_init): Handler block as initializer. + (c_finish_return): check for completed block before + analyzing block's return expression. + * varasm.c (output_constant): Allow outputting block data. + * c-common.h (BLOCK_IS_GLOBAL): New flag. + (block_is_complete): New field in block data structure. + * c-parser.c (build_block_struct_initlist): New initializer and + flag for global block data. + (build_block_literal_tmp): Temporary data for global block is + declared as global static. + (c_parser_block_literal_expr): Removed diagnostics for global blocks. + Moved fixing helper function type earlier before its tree is built. + +2008-08-06 Fariborz Jahanian + + Radar 6014138 + * c-decl.c (build_block_byref_decl): In the presence of nested "{" + move up the scope chain until reaching the main function body's scope. + +2008-08-04 Fariborz Jahanian + + Radar 6040305 - work in progress. + * c-decl.c (build_indirect_object_id_exp): Removed. + * c-common.c (build_indirect_object_id_exp): Added + * c-common.h (build_indirect_object_id_exp): New decl. + * config/darwin-c.c (darwin_cpp_builtins): Define __byref + in c++ mode as well. + +2008-07-18 Fariborz Jahanian + + Radar 6083129 - twiked + * c-decl.c (release_all_local_byrefs_at_return): Do not release + imported __byref variables in the block. + * c-parser.c (gen_block_byref_release_exp): Do not release __byref + variables outside of the block when returning from the block. + +2008-07-15 Fariborz Jahanian + + Radar 5988451 + * c-decl.c (build_block_ref_decl): Insert copied in variable + in each enclosing block which does not use it. + (begin_block): Remove setting of "the_scope" field of the block. + (in_imm_block): Fix effect of changing the "the_scope" field. + (lookup_name_in_block): Do not skip over copied-in variables when + looking up a variable in the block. + * c-parser.c (c_parser_block_literal_expr): Set block's "the_scope" field + to the helper function's outer-most body scope. + +2008-07-08 Fariborz Jahanian + + Radar 6048570 + * c-typeck.c (c_finish_return): Error on returning a block on the stack. + +2008-06-05 Fariborz Jahanian + + Radar 5988995 + * c-typeck.c (types_are_closure_compatible): Nested block pointer + types must be considered when matching block types. + +2008-06-05 Fariborz Jahanian + + Radar 5982990 + * c-parser.c (c_parser_objc_synch_compound_statement): New + (c_parser_objc_synchronized_statement): Call + c_parser_objc_synch_compound_statement. + +2008-06-04 Fariborz Jahanian + + Radar 5985368 + * c-parser.c (c_parser_declaration_or_fndef): Better diagnostics for + a bad block definition. + +2008-05-23 Fariborz Jahanian + + Radar 5925781 + * c-common.c (handle_nonnull_attribute): Support block pointer + just like a pointer for nonnull attribute. + (check_nonnull_arg): Ditto. + +2008-05-20 Fariborz Jahanian + + Radar 5932809 - minor change for runtime delight. + * c-parser.c (build_closure_struct_type): Add strcutor fields + for __byref 'id' object blocks as well. + (build_closure_struct_initlist): And their initializers. + +2008-04-30 Caroline Tice + + Radar 5811961 + * c-decl.c: (declare_closure_prologue_local_vars): Set the source + location for the new decl expr statement to be the source location of + the decl tree. + +2008-04-25 Fariborz Jahanian + + Radar 5803005 (tweaked) + * c-typeck.c (build_external_ref): Refactored global decl checks. + +2008-04-24 Caroline Tice + + Radar 5811943 + * tree.h (TYPE_CLOSURE_IMPL_STRUCT): New macro. + (lang_flag_2): Use previously unused field in tree_type to indicate + closure structs. + * dwarf2out.c (c-common.h): New include statement. + (dwarf_attr_name): Add case for DW_AT_APPLE_closure. + (gen_variable_die): Give pointers to closures the + invoke_impl_ptr_type. + (gen_struct_or_union_type_die): Add DW_AT_APPLE_closure + to structs that define closures. + * dwarf2.h (DW_AT_APPLE_closure): New Dwarf attribute. + * c-typeck.c (invoke_impl_ptr_type): Move declaration from here to + c-common.c + (build_closure_internal_types): Set TYPE_CLOSURE_IMPL_STRUCT + flag for closure structs. + * c-common.c (invoke_impl_ptr_type): Move declaration to here from + c-typeck.c. + +2008-04-23 Fariborz Jahanian + + Radar 5882266 + * c-typeck.c (types_are_closure_compatible): Check for underlying + pointer types as well. + +2008-04-15 Stuart Hastings + + Radar 5862465 + * tree.h (PTR_OR_REF_CHECK, POINTER_TYPE_P): Add + CLOSURE_POINTER_TYPE. + * fold-const.c (fold_convert): Add CLOSURE_POINTER_TYPE. + * testsuite/gcc.apple/closure-5862465.c: New. + +2008-03-31 Fariborz Jahanian + + Radar 5831855 + * c-typeck.c (convert_for_assignment): Block and 'id' types + are interchangeable. + +2008-03-28 Fariborz Jahanian + + Radar 5809099 + * convert.c (convert_to_pointer): Allow typecast of closure + pointer to 'id'. + (convert_to_closure_pointer): Allow typecast of 'id' + of a closure pointer expression. + +2008-03-25 Fariborz Jahanian + + Radar 5811887 (minor change) + * c-opts.c (c_common_post_options): Remove conditional check + of pedantic when setting flag_blocks. + +2008-03-24 Fariborz Jahanian + + Radar 5811887 + * c-cppbuiltin.c: flag_closures renamed to flag_blocks + * c-parser.c: Ditto. + * c.opt: flag_closures renamed to flag_blocks. flag_blocks + defaulted to -1. + * c-opts.c (c_common_post_options): All flavors of c99, blocks are off by + default unless requested via -fblocks. + +2008-03-24 Fariborz Jahanian + + Radar 5814025 + * c-tree.h (make_closure_pointer_declarator): Takes + additional argument. + * c-decl.c (grokdeclarator): Get 'const'-ness of closure + pointer. + (make_closure_pointer_declarator): Takes additional argument for + const/volatile. + * c-parser.c (c_parser_declarator): Pass down attribute info. + to make_closure_pointer_declarator. + +2008-03-20 Fariborz Jahanian + + Radar 5802025 + * c-common.h (objc_build_property_getter_func_call): New decl. + * stub-objc.c (objc_build_property_getter_func_call): New stub. + +2008-03-18 Fariborz Jahanian + + Radar 5803600 + * c-decl.c (add_closure_global_byref_list, + in_closure_global_byref_list): New defs. + * c-common.h (add_closure_global_byref_list, + in_closure_global_byref_list): New decls. + * c-typeck.c (build_external_ref): global variables + declared as 'byref' are enterred in their own list + of such declarations per each closure. + * c-parser.c (c_parser_postfix_expression): Remove previous fix. + (c_parser_closure_byref_declaration): Check for global + 'byref' by calling in_closure_global_byref_list. + +2008-03-13 Fariborz Jahanian + + Radar 5795493 + * c-typeck.c: Renamed typesAreClosureCompatible to + types_are_closure_compatible. + +2008-03-11 Fariborz Jahanian + + Radar 5732232 (Related to change of command option/macro) + * c-cppbuiltin.c: __CLOSURES__ macro rename __BLOCKS__ + * c.opt: -fclosures change to -fblocks. + +2008-03-10 Fariborz Jahanian + + Radar 5782740 - part 2 (bug fix). + * c-parser.c (synth_copy_helper_closure, + synth_destroy_helper_closure): set DECL_ARG_TYPE field of input + arguments for the two synthesized helper functions. + +2008-02-21 Caroline Tice + + Radar 5741070 + * objc/objc-act.c (objc_finish_message_expr): Find + the record-type tree from the class interface, and mark the record + type as used, for emitting debug info. + * cp/cp-objcp-common.c (c_return_interface_record_type): New function. + * cp/cp-tree.h (c_return_interface_record_type): New extern function + declaration. + * c-tree.h (c_return_interface_record_type): Likewise + * c-decl.c (c_return_interface_record_type): New function. + +2007-08-22 Fariborz Jahanian + + Radar 4947311 + * c-common.h (objc_declare_protocols, objc_start_protocol): Decl changed. + * stub-objc.c (objc_declare_protocols, objc_start_protocol): Changed. + * c-parser.c (c_parser_external_declaration): Call to + c_parser_objc_protocol_definition takes additional argument. + (c_parser_declaration_or_fndef): Protocols with attributes are processed + here by passing it to c_parser_objc_protocol_definition. + (c_parser_objc_protocol_definition): Takes additional argument and passes + it to objc_declare_protocols or objc_start_protocol. + +2007-07-13 Fariborz Jahanian + + Radar 5277239 + * c-parser.c (c_parser_next_token_starts_declspecs): Exclude + objc2's property dot-syntax as a declarator. + (c_parser_postfix_expression): Convert property dot-syntax on + class objects into a property reference expression. + +2007-07-10 Fariborz Jahanian + + Radar 5285911 + * tree.h (CALL_EXPR_OBJC_PROPERTY_GETTER): Macro removed. + * c-typeck.c (build_component_ref): Call + objc_build_property_reference_expr instead of objc_build_getter_call. + (build_modify_expr): Call objc_property_reference_expr instead of + objc_property_call. + * c-common.h (objc_build_getter_call, objc_property_call): Decl removed. + (objc_build_property_reference_expr, objc_property_reference_expr): Decl. + added. + * stub-objc.c (objc_build_getter_call, objc_property_call): Stub removed. + (objc_build_property_reference_expr, objc_property_reference_expr): + Stub added. + +2007-06-29 Fariborz Jahanian + + Radar 5276085 + * c-parser.c (c_parser_binary_expression) : objc_generate_weak_read + replaced with call to objc_build_weak_reference_tree + * c-typeck.c (build_modify_expr, c_objc_common_truthvalue_conversion): + objc_remove_weak_read replaced with call to objc_weak_reference_expr. + * c-common.h (objc_weak_reference_expr, + objc_build_weak_reference_tree) : New decl. + (objc_generate_weak_read, objc_remove_weak_read): remove. + * stub-objc.c (objc_weak_reference_expr, + objc_build_weak_reference_tree): New stub. + (objc_generate_weak_read, objc_remove_weak_read): remove. + +2007-05-23 Fariborz Jahanian + + Radar 5195402 + * c-format.c (handle_format_arg_attribute): Check for NSString * + and CFStringRef as valid formatting types. + (check_format_string): Ditto. + * c-common.h (objc_check_format_nsstring, + objc_check_cfstringref_type): New decls. + * stub-objc.c (objc_check_nsstring_pointer_type): New stub. + * config/darwin-c.c (objc_check_cfstringref_type): New + (objc_check_format_cfstring): Call objc_check_cfstringref_type + for valid CFStringRef argument type. + * config/darwin-protos.h (objc_check_cfstringref_type): New decl. + * config/darwin.h (CFSTRING_TYPE_CHECK): New macro. + +2007-05-18 Fariborz Jahanian + + Radar 5202926 + * c-common.h (objc_anonymous_local_objc_name): New decl. + * config/darwin-protos.h (objc_anonymous_local_objc_name): Decl. + * stub-objc.c (objc_anonymous_local_objc_name): New stub. + * config/darwin.h (ASM_OUTPUT_LABELREF) Call + objc_anonymous_local_objc_name. + +2007-05-07 Fariborz Jahanian + + Radar 4157812 + * c-common.h (objc_build_keyword_decl): Takes a new argument. + * stub-objc.c (objc_build_keyword_decl): Ditto. + * c-parser.c (c_parser_objc_method_decl): Recognize optional + method's argument attribute. + (c_parser_objc_method_decl): Handle errornous selector. + +2007-05-02 Fariborz Jahanian + + Radar 4502186 + * c-typeck.c (convert_for_assignment): Remove synthesized 'volatile' + type before doing type comparison. + +2007-03-29 Fariborz Jahanian + + Radar 4564694 + * c-parse.c (c_parser_objc_class_instance_variables): Add @package + support to syntax. + * c-common.h (RID_AT_PACKAGE): Add + +2007-03-29 Fariborz Jahanian + + Radar 4947014 - objc atomic property + * c-common.h (RID_NONATOMIC): Add + * c-parse.c (c_parser_objc_property_attribute) : Recognize 'nonatomic' + as new property. + +2007-03-23 Fariborz Jahanian + + Radar 4985544 + * c-format.c (enum format_type): New entry for NSString format. + (format_typ): Has a new entry for NSString format. + (decode_format_attr): Error on use of NSString format on a + non-objective-c program. + (objc_check_nsformat_arg): New. + (check_format_info): Call back for NSString is objc_check_nsformat_arg + (handle_format_attribute): Use objc_check_format_nsstring for + NSString format. + * c-common.h (objc_NSString_format): New decl. + (objc_check_format_nsstring): New decl. + * stub-objc.c (objc_NSString_format, objc_check_format_nsstring): New + stubs. + * config/darwin-protos.h (darwin_cfstring_type_node): New decl. + * config/darwin.c (darwin_cfstring_type_node): New + * config/darwin.h (TARGET_CFSTRING_P): New macro + +2007-03-23 Fariborz Jahanian + + Radar 4985544 + * c-format.c (enum format_type): New entry for NSString format. + (format_typ): Has a new entry for NSString format. + (decode_format_attr): Error on use of NSString format on a + non-objective-c program. + (objc_check_nsformat_arg): New. + (check_format_info): Call back for NSString is objc_check_nsformat_arg + (handle_format_attribute): Use objc_check_format_nsstring for + NSString format. + * c-common.h (objc_NSString_format): New decl. + (objc_check_format_nsstring): New decl. + * stub-objc.c (objc_NSString_format, objc_check_format_nsstring): New + stubs. + * config/darwin-protos.h (darwin_cfstring_type_node): New decl. + * config/darwin.c (darwin_cfstring_type_node): New + * config/darwin.h (TARGET_CFSTRING_P): New macro + +2007-03-22 Fariborz Jahanian + + Radar 4965989 + * c-parser.c (c_parser_objc_class_definition): Add supprt for anonymous + category syntax. + +2007-03-21 Fariborz Jahanian + + Radar 2848255 + * c-parser.c (c_parser_objc_try_catch_statement): Parse @catch(...). + * c.opt: Add -fobjc-zerocost-exceptions option. + * c-opts.c (c_common_post_options): Set the flags for + -fobjc-zerocost-exceptions. + * c-common.h: Add some declarations. + * stub-objc.c (objc2_valid_objc_catch_type, objc2_build_throw_call): + New stubs. + * config/darwin.h (OBJC_FLAG_OBJC_ABI): Check for proper + use of -fobjc-zerocost-exceptions option. + +2006-11-06 Fariborz Jahanian + + Radar 4781080 (part 2) + * targhooks.c (default_objc_fpreturn_msgcall): Takes 2nd argument. + * targhooks.h (default_objc_fpreturn_msgcall): Changed Decl. + * target.h (objc_fpreturn_msgcall): Changed Decl. + * config/i386/i386.h (OBJC_FPRETURN_MSGCALL): Changed Decl. + * config/i386/i386-protos.h (ix86_objc_fpreturn_msgcall): Changed Decl. + * config/i386/i386.c (ix86_objc_fpreturn_msgcall): Changed definition. +2006-09-15 Fariborz Jahanian + + Radar 4727659 + * c-common.c (handle_noreturn_attribute): Handle method_decl + nodes as well. + +2006-09-01 Fariborz Jahanian + + Radar 4712269 + * c-common.h (objc_build_incr_decr_setter_call): New decl. + * stub-objc.c (objc_build_incr_decr_setter_call): New stub. + * c-typeck.c (build_unary_op): Call objc_build_incr_decr_setter_call + for potential ince/decr pre/post expressions involving properties. + +2006-08-31 Fariborz Jahanian + + Radar 4697411 + * c-common.h (objc_volatilize_component_ref): New decl. + * c-typeck.c (build_component_ref): Call objc_volatilize_component_ref. + * stub-objc.c (objc_volatilize_component_ref): New stub. + +2006-07-18 Fariborz Jahanian + + Radar 4592503 + * c-decl.c (finish_struct): Check on illegal use of __weak + on struct fields. + * decl.c (start_decl): Check on illegal use of __weak on + variable declarations. + * stub-objc.c (objc_checkon_weak_attribute): New stub. + * c-common.h (objc_checkon_weak_attribute): New decl. + +2006-06-26 Fariborz Jahanian + + Radar 4591909 + * c-parse.in: New/modified grammar for new attributes in + properties. + (yylexname): Change to recognize new attribute terminals. + * c-common.h (RID_DYNAMIC): New enum declaration. + +2006-07-14 Fariborz Jahanian + + Radar 4621020 + * c-parse.in: Added 'weak' attribute keyword for @property. + * c-common.h: 'weak' related declarations. + +2006-05-18 Fariborz Jahanian + + Radar 4548636 (objc attributes on class) + * c-parse.in: Add attribute non-terminal before + AT_INTERFACE. + * c-common.h (objc_start_class_interface): New argument added. + * stub-objc.c (objc_start_class_interface): Ditto. + +2006-05-16 Fariborz Jahanian + + Radar 4547045 + * c-gimplify.c (obj_reuse_bc_block): Removed. + (objc_pop_label, objc_push_label): New. + (gimplify_c_loop): Fix up foreach's innerloop break label. + +2006-04-26 Fariborz Jahanian + + Radar 3803157 (method attributes) + * c-parse.in: Add grammar support for declaring + attribute for objc methods. + * c-common.c (handle_deprecated_attribute): Recognize + objc methods as valid declarations. + (handle_unavailable_attribute): Ditto. + * c-common.h: Bunch of new extern declarations. + * stub-objc.c (objc_add_method_declaration, objc_start_method_definition): + Added new argument. + (objc_method_decl): New stub. + +2006-04-12 Fariborz Jahanian + + Radar 4507230 + * c-common.h (objc_type_valid_for_messaging): Declare. + * stub-objc.c (objc_type_valid_for_messaging): New stub. + +2006-04-06 Fariborz Jahanian + + Radar 4436866 + (Missing copies attribute) + * c-parse.in: Add grammer for 'copies' attribute. + * c-common.h (RID_COPIES): New enumerator. + +2006-03-27 Fariborz Jahanian + + Radar 4133425 + * c-common.h (objc_diagnose_private_ivar): New decl. + * stub-objc.c (objc_diagnose_private_ivar): New stub. + * c-decl.c (undeclared_variable): Issue disnostic on + private 'ivar' access. + +2006-03-27 Fariborz Jahanian + + Radar 4491608 + * c-typeck.c (convert_arguments): function name must come from 'selector' + when diagnosing 'too many arguments'. + +2006-03-23 Fariborz Jahanian + + Radar 4193359 + * c-typeck.c (convert_for_assignment): Remove Objective-C EH machinery + 'volatile' qualifier before doing type comparison. + +2006-02-28 Fariborz Jahanian + + Radar 4441049 + * c-common.h (objc_v2_bitfield_ivar_bitpos): New decl. + * expr.h (objc_v2_bitfield_ivar_bitpos): New decl. + * stub-objc.c (objc_v2_bitfield_ivar_bitpos): New stub. + * expr.c (get_inner_reference): Compute ivar's bitfield bit offset. + +2006-02-15 Fariborz Jahanian Radar 4445586 * c-common.def (DO_STMT): Takes an extra argument. +2006-02-02 Fariborz Jahanian + + Radar 4426814 + * c-parse.in (cast_expr): generate objc_read_weak call on + each __weak object in the expession. + * c-typeck.c (build_modify_expr): Undo the call to objc_read_weak + on LHS expression. + * c-objc-common.c (c_objc_common_truthvalue_conversion): Generate + objc_read_weak call before generating tree for !exp, etc. + * c-common.h (objc_generate_weak_read, objc_remove_weak_read): New decl. + * stub-objc.c (objc_generate_weak_read, objc_remove_weak_read): New stubs. + +2005-12-15 Fariborz Jahanian + + Radar 4229905 + * c-typeck.c (build_conditional_expr): Call objc_have_common_type when + looking for objective-c common pointer types. + * c-common.h objc_have_common_type): New declaration. + * stub-objc.c (objc_have_common_type): New stub. + +2005-12-05 Mike Stump + + Radar 4357979 + * doc/invoke.texi (C Dialect Options): Improve -fnested-functions wording. + * doc/extend.texi (Nested Functions): Note that on darwin nested + functions are off by default. + +2005-11-08 Fariborz Jahanian + + Radar 4330422 + + * c-common.h (objc_non_volatilized_type): New declaration + * stub-objc.c (objc_non_volatilized_type): New stub. + +2005-10-12 Fariborz Jahanian + + Radar 4291785 + + * c-common.h (objc_get_interface_ivars): New declaration + (objc_detect_field_duplicates): Ditto. + * c-decl.c (finish_struct): Check for duplicate among + flattened fields if objective-c. + * stub-objc.c (objc_get_interface_ivars): New stub. + (objc_detect_field_duplicates): Ditto. + +2005-09-28 Devang Patel + + Radar 4258406 + * c-parse.in (nested_function): Report an error, instead of a warning. + (nontype_nested_function): Same. + * c.opt (Wnested-funcs): Remove. + * doc/invoke.texi: Remove Wnested-funcs documentations. + +2005-08-03 Fariborz Jahanian + + Radar 4188876 + * c-typeck.c (pop_init_level): Issue diagnostic on non-constant + vector initializers. + +2005-06-22 Ziemowit Laski + + Radar 4154928 + * c-common.h (objc_common_type): New prototype. + * c-typeck.c (build_conditional_expr): For two ObjC pointer types, + use their ObjC common type. + * stub-objc.c (objc_common_type): New stub. + /* APPLE LOCAL merge marger */ /* Stuff under is in fsf mainline, but not in the 4.2 branch */ diff --git a/contrib/gcc/attribs.c b/contrib/gcc/attribs.c index 7377c57691df..77caebc7c936 100644 --- a/contrib/gcc/attribs.c +++ b/contrib/gcc/attribs.c @@ -216,7 +216,8 @@ decl_attributes (tree *node, tree attributes, int flags) if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE && TREE_CODE (*anode) != METHOD_TYPE) { - if (TREE_CODE (*anode) == POINTER_TYPE + /* APPLE LOCAL radar 6246527 */ + if ((TREE_CODE (*anode) == POINTER_TYPE || TREE_CODE (*anode) == BLOCK_POINTER_TYPE) && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE)) { @@ -323,6 +324,14 @@ decl_attributes (tree *node, tree attributes, int flags) if (fn_ptr_tmp) { + /* APPLE LOCAL begin radar 6246527 */ + if (DECL_P (*node) && TREE_TYPE (*node) && + TREE_CODE (TREE_TYPE (*node)) == BLOCK_POINTER_TYPE) + /* Rebuild the block pointer type and put it in the + appropriate place. */ + fn_ptr_tmp = build_block_pointer_type (fn_ptr_tmp); + else + /* APPLE LOCAL end radar 6246527 */ /* Rebuild the function pointer type and put it in the appropriate place. */ fn_ptr_tmp = build_pointer_type (fn_ptr_tmp); diff --git a/contrib/gcc/c-common.c b/contrib/gcc/c-common.c index f9b06f4ff837..2fc1d1e332f8 100644 --- a/contrib/gcc/c-common.c +++ b/contrib/gcc/c-common.c @@ -552,6 +552,8 @@ static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *); static tree handle_warn_unused_result_attribute (tree *, tree, tree, int, bool *); static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *); +/* APPLE LOCAL radar 5932809 - copyable byref blocks */ +static tree handle_blocks_attribute (tree *, tree, tree, int, bool *); static void check_function_nonnull (tree, tree); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); @@ -607,7 +609,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_section_attribute }, { "aligned", 0, 1, false, false, false, handle_aligned_attribute }, - { "weak", 0, 0, true, false, false, + /* APPLE LOCAL weak types 5954418 */ + { "weak", 0, 0, false, false, false, handle_weak_attribute }, { "alias", 1, 1, true, false, false, handle_alias_attribute }, @@ -650,6 +653,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_warn_unused_result_attribute }, { "sentinel", 0, 1, false, true, true, handle_sentinel_attribute }, + /* APPLE LOCAL radar 5932809 - copyable byref blocks */ + { "blocks", 1, 1, true, false, false, handle_blocks_attribute }, { NULL, 0, 0, false, false, false, NULL } }; @@ -4259,7 +4264,10 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args), tree type = TREE_TYPE (*node); /* See FIXME comment in c_common_attribute_table. */ - if (TREE_CODE (*node) == FUNCTION_DECL) + /* APPLE LOCAL begin radar 4727659 */ + if (TREE_CODE (*node) == FUNCTION_DECL + || objc_method_decl (TREE_CODE (*node))) + /* APPLE LOCAL end radar 4727659 */ TREE_THIS_VOLATILE (*node) = 1; else if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) @@ -4267,6 +4275,14 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args), = build_pointer_type (build_type_variant (TREE_TYPE (type), TYPE_READONLY (TREE_TYPE (type)), 1)); + /* APPLE LOCAL begin radar 6237713 */ + else if (TREE_CODE (type) == BLOCK_POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) + = build_block_pointer_type + (build_type_variant (TREE_TYPE (type), + TYPE_READONLY (TREE_TYPE (type)), 1)); + /* APPLE LOCAL end radar 6237713 */ else { warning (OPT_Wattributes, "%qE attribute ignored", name); @@ -4893,6 +4909,23 @@ handle_weak_attribute (tree *node, tree name, if (TREE_CODE (*node) == FUNCTION_DECL || TREE_CODE (*node) == VAR_DECL) declare_weak (*node); + /* APPLE LOCAL begin weak types 5954418 */ + else if (!DECL_P (*node) + /* If the weak flag can be associated with something else, + prefer that. */ + && (flags & (ATTR_FLAG_FUNCTION_NEXT + |ATTR_FLAG_DECL_NEXT + |ATTR_FLAG_ARRAY_NEXT))) + { + *no_add_attrs = true; + return tree_cons (name, args, NULL_TREE); + } + else if (! targetm.cxx.class_data_always_comdat () + && TREE_CODE (*node) == RECORD_TYPE) + { + /* Leave on the type for the C++ front end */ + } + /* APPLE LOCAL end weak types 5954418 */ else warning (OPT_Wattributes, "%qE attribute ignored", name); @@ -5381,8 +5414,10 @@ handle_unavailable_attribute (tree *node, tree name, || TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == FIELD_DECL) - /* Removed radar 3803157 - objc attribute */ + /* APPLE LOCAL begin radar 3803157 - objc attribute */ + || TREE_CODE (decl) == FIELD_DECL + || objc_method_decl (TREE_CODE (decl))) + /* APPLE LOCAL end radar 3803157 - objc attribute */ { TREE_UNAVAILABLE (decl) = 1; } @@ -5558,7 +5593,10 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), return NULL_TREE; } - if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE) + /* APPLE LOCAL begin blocks 5925781 */ + if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE && + TREE_CODE (TREE_VALUE (argument)) != BLOCK_POINTER_TYPE) + /* APPLE LOCAL end blocks 5925781 */ { error ("nonnull argument references non-pointer operand (argument %lu, operand %lu)", (unsigned long) attr_arg_num, (unsigned long) arg_num); @@ -5705,8 +5743,11 @@ check_nonnull_arg (void * ARG_UNUSED (ctx), tree param, happen if the "nonnull" attribute was given without an operand list (which means to check every pointer argument). */ - if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE) - return; + /* APPLE LOCAL begin blocks 5925781 */ + if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE && + TREE_CODE (TREE_TYPE (param)) != BLOCK_POINTER_TYPE) + /* APPLE LOCAL end blocks 5925781 */ + return; if (integer_zerop (param)) warning (OPT_Wnonnull, "null argument where non-null required " @@ -5809,6 +5850,168 @@ handle_warn_unused_result_attribute (tree *node, tree name, return NULL_TREE; } +/* APPLE LOCAL begin radar 5932809 - copyable byref blocks */ +/* Handle "blocks" attribute. */ +static tree +handle_blocks_attribute (tree *node, tree name, + tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree arg_ident; + /* APPLE LOCAL radar 6217257 */ + tree type; + *no_add_attrs = true; + if (!(*node) || TREE_CODE (*node) != VAR_DECL) + { + error ("__block attribute can be specified on variables only"); + return NULL_TREE; + } + arg_ident = TREE_VALUE (args); + gcc_assert (TREE_CODE (arg_ident) == IDENTIFIER_NODE); + /* APPLE LOCAL radar 6096219 */ + if (strcmp (IDENTIFIER_POINTER (arg_ident), "byref")) + { + /* APPLE LOCAL radar 6096219 */ + warning (OPT_Wattributes, "Only \"byref\" is allowed - %qE attribute ignored", + name); + return NULL_TREE; + } + /* APPLE LOCAL begin radar 6217257 */ + type = TREE_TYPE (*node); + if (TREE_CODE (type) == ERROR_MARK) + return NULL_TREE; + if (TREE_CODE (type) == ARRAY_TYPE) + { + if (!TYPE_SIZE (type) || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + { + error ("__block not allowed on a variable length array declaration"); + return NULL_TREE; + } + } + /* APPLE LOCAL end radar 6217257 */ + COPYABLE_BYREF_LOCAL_VAR (*node) = 1; + COPYABLE_BYREF_LOCAL_NONPOD (*node) = block_requires_copying (*node); + return NULL_TREE; +} +/* APPLE LOCAL end radar 5932809 - copyable byref blocks */ + +/* APPLE LOCAL begin blocks 6040305 */ + +/* This routine builds: + *(void **)(EXP+20) expression which references the object pointer. +*/ +tree +build_indirect_object_id_exp (tree exp) +{ + tree dst_obj; + int int_size = int_cst_value (TYPE_SIZE_UNIT (unsigned_type_node)); + int offset; + /* dst->object In thid case 'object' is the field + of the object passed offset by: void * + void* + int + int + void* + void * + This must match definition of Block_byref structs. */ + /* APPLE LOCAL radar 6244520 */ + offset = GET_MODE_SIZE (Pmode) + GET_MODE_SIZE (Pmode) + + int_size + int_size + GET_MODE_SIZE (Pmode) + + GET_MODE_SIZE (Pmode); + dst_obj = build2 (PLUS_EXPR, ptr_type_node, exp, + build_int_cst (NULL_TREE, offset)); + /* APPLE LOCAL begin radar 6180456 */ + /* Type case to: 'void **' */ + dst_obj = build_c_cast (build_pointer_type (ptr_type_node), dst_obj); + dst_obj = build_indirect_ref (dst_obj, "unary *"); + /* APPLE LOCAL end radar 6180456 */ + return dst_obj; +} + +/* This routine builds call to: + _Block_object_dispose(VAR_DECL.__forwarding, BLOCK_FIELD_IS_BYREF); + and adds it to the statement list. + */ +tree +build_block_byref_release_exp (tree var_decl) +{ + tree exp = var_decl, call_exp; + tree type = TREE_TYPE (var_decl); + /* __block variables imported into Blocks are not _Block_object_dispose() + from within the Block statement itself; otherwise, each envokation of + the block causes a release. Make sure to release __block variables declared + and used locally in the block though. */ + if (cur_block + && (BLOCK_DECL_COPIED (var_decl) || BLOCK_DECL_BYREF (var_decl))) + return NULL_TREE; + if (BLOCK_DECL_BYREF (var_decl)) { + /* This is a "struct Block_byref_X *" type. Get its pointee. */ + gcc_assert (POINTER_TYPE_P (type)); + type = TREE_TYPE (type); + exp = build_indirect_ref (exp, "unary *"); + } + TREE_USED (var_decl) = 1; + + /* Declare: _Block_object_dispose(void*, BLOCK_FIELD_IS_BYREF) if not done already. */ + exp = build_component_ref (exp, get_identifier ("__forwarding")); + call_exp = build_block_object_dispose_call_exp (exp, BLOCK_FIELD_IS_BYREF); + return call_exp; +} +/* APPLE LOCAL end blocks 6040305 */ +/* APPLE LOCAL begin radar 5803600 */ +/** add_block_global_byref_list - Adds global variable decl to the list of + byref global declarations in the current block. +*/ +void add_block_global_byref_list (tree decl) +{ + cur_block->block_byref_global_decl_list = + tree_cons (NULL_TREE, decl, cur_block->block_byref_global_decl_list); +} + +/** in_block_global_byref_list - returns TRUE if global variable is + in the list of 'byref' declarations. +*/ +bool in_block_global_byref_list (tree decl) +{ + tree chain; + if (TREE_STATIC (decl)) { + for (chain = cur_block->block_byref_global_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (TREE_VALUE (chain) == decl) + return true; + } + return false; +} +/* APPLE LOCAL end radar 5803600 */ + +/* APPLE LOCAL begin radar 6160536 */ +tree +build_block_helper_name (int unique_count) +{ + char *buf; + if (!current_function_decl) + { + /* APPLE LOCAL begin radar 6411649 */ + static int global_count; + buf = (char *)alloca (32); + sprintf (buf, "__block_global_%d", ++global_count); + /* APPLE LOCAL end radar 6411649 */ + } + else + { + tree outer_decl = current_function_decl; + /* APPLE LOCAL begin radar 6169580 */ + while (outer_decl && + DECL_CONTEXT (outer_decl) && TREE_CODE (DECL_CONTEXT (outer_decl)) == FUNCTION_DECL) + /* APPLE LOCAL end radar 6169580 */ + outer_decl = DECL_CONTEXT (outer_decl); + /* APPLE LOCAL begin radar 6411649 */ + if (!unique_count) + unique_count = ++DECL_STRUCT_FUNCTION(outer_decl)->unqiue_block_number; + /* APPLE LOCAL end radar 6411649 */ + buf = (char *)alloca (IDENTIFIER_LENGTH (DECL_NAME (outer_decl)) + 32); + sprintf (buf, "__%s_block_invoke_%d", + IDENTIFIER_POINTER (DECL_NAME (outer_decl)), unique_count); + } + return get_identifier (buf); +} +/* APPLE LOCAL end radar 6160536 */ + /* Handle a "sentinel" attribute. */ static tree @@ -6725,5 +6928,147 @@ warn_about_parentheses (enum tree_code code, enum tree_code code_left, "have their mathematical meaning"); } +/* APPLE LOCAL begin radar 6246527 */ +/* This routine is called for a "format" attribute. It adds the number of + hidden argument ('1') to the format's 2nd and 3rd argument to compensate + for these two arguments. This is to make rest of the "format" attribute + processing done in the middle-end to work seemlessly. */ +static void +block_delta_format_args (tree format) +{ + tree format_num_expr, first_arg_num_expr; + int val; + tree args = TREE_VALUE (format); + gcc_assert (TREE_CHAIN (args) && TREE_CHAIN (TREE_CHAIN (args))); + format_num_expr = TREE_VALUE (TREE_CHAIN (args)); + first_arg_num_expr = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))); + if (format_num_expr && TREE_CODE (format_num_expr) == INTEGER_CST) + { + val = TREE_INT_CST_LOW (format_num_expr); + TREE_VALUE (TREE_CHAIN (args)) = build_int_cst (NULL_TREE, val+1); + } + if (first_arg_num_expr && TREE_CODE (first_arg_num_expr) == INTEGER_CST) + { + val = TREE_INT_CST_LOW (first_arg_num_expr); + if (val != 0) + TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))) = + build_int_cst (NULL_TREE, val+1); + } +} + +/* This routine recognizes legal block attributes. In case of block's "format" + attribute, it calls block_delta_format_args to compensate for hidden + argument _self getting passed to block's helper function. */ +bool +any_recognized_block_attribute (tree attributes) +{ + tree chain; + bool res = false; + for (chain = attributes; chain; chain = TREE_CHAIN (chain)) + { + if (is_attribute_p ("format", TREE_PURPOSE (chain))) + { + block_delta_format_args (chain); + res = true; + } + else if (is_attribute_p ("sentinel", TREE_PURPOSE (chain))) + res = true; + } + return res; +} +/* APPLE LOCAL end radar 6246527 */ +/* APPLE LOCAL begin radar 5847976 */ +static GTY(()) tree block_object_assign_decl; +static GTY(()) tree block_object_dispose_func_decl; +/* This routine declares: + void _Block_object_assign (void *, void *, int) or uses an + existing one. +*/ +static tree +build_block_object_assign_decl (void) +{ + tree func_type; + if (block_object_assign_decl) + return block_object_assign_decl; + block_object_assign_decl = lookup_name (get_identifier ("_Block_object_assign")); + if (block_object_assign_decl) + return block_object_assign_decl; + func_type = + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, integer_type_node, void_list_node)))); + + block_object_assign_decl = builtin_function ("_Block_object_assign", func_type, + 0, NOT_BUILT_IN, 0, NULL_TREE); + TREE_NOTHROW (block_object_assign_decl) = 0; + return block_object_assign_decl; +} + +/* This routine builds: + _Block_object_assign(dest, src, flag) +*/ +tree build_block_object_assign_call_exp (tree dst, tree src, int flag) +{ + tree func_params = tree_cons (NULL_TREE, dst, + tree_cons (NULL_TREE, src, + tree_cons (NULL_TREE, + build_int_cst (integer_type_node, flag), + NULL_TREE))); + return build_function_call (build_block_object_assign_decl (), func_params); +} + +/* This routine declares: + void _Block_object_dispose (void *, int) or uses an + existing one. +*/ +static tree +build_block_object_dispose_decl (void) +{ + tree func_type; + if (block_object_dispose_func_decl) + return block_object_dispose_func_decl; + block_object_dispose_func_decl = lookup_name (get_identifier ("_Block_object_dispose")); + if (block_object_dispose_func_decl) + return block_object_dispose_func_decl; + func_type = + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, integer_type_node, void_list_node))); + + block_object_dispose_func_decl = builtin_function ("_Block_object_dispose", func_type, + 0, NOT_BUILT_IN, 0, NULL_TREE); + TREE_NOTHROW (block_object_dispose_func_decl) = 0; + return block_object_dispose_func_decl; +} + +/* This routine builds the call tree: + _Block_object_dispose(src, flag) +*/ +tree build_block_object_dispose_call_exp (tree src, int flag) +{ + tree func_params = tree_cons (NULL_TREE, src, + tree_cons (NULL_TREE, + build_int_cst (integer_type_node, flag), + NULL_TREE)); + return build_function_call (build_block_object_dispose_decl (), func_params); +} +/* APPLE LOCAL end radar 5847976 */ +/* APPLE LOCAL begin radar 7760213 */ +int HasByrefArray(tree byrefType) +{ + tree s1; + /* Check for possibility of an error condition. */ + if (TREE_CODE(byrefType) != RECORD_TYPE) + return 0; + + for (s1 = TYPE_FIELDS (byrefType); s1; s1 = TREE_CHAIN (s1)) + { + if (TREE_CODE(TREE_TYPE(s1)) == ARRAY_TYPE) + return 1; + } + return 0; +} +/* APPLE LOCAL end radar 7760213 */ #include "gt-c-common.h" diff --git a/contrib/gcc/c-common.h b/contrib/gcc/c-common.h index 8848ea5fdaf0..af7bd0de1a86 100644 --- a/contrib/gcc/c-common.h +++ b/contrib/gcc/c-common.h @@ -93,12 +93,20 @@ enum rid /* Objective-C */ RID_AT_ENCODE, RID_AT_END, RID_AT_CLASS, RID_AT_ALIAS, RID_AT_DEFS, - RID_AT_PRIVATE, RID_AT_PROTECTED, RID_AT_PUBLIC, + /* APPLE LOCAL radar 4564694 */ + RID_AT_PACKAGE, RID_AT_PRIVATE, RID_AT_PROTECTED, RID_AT_PUBLIC, RID_AT_PROTOCOL, RID_AT_SELECTOR, RID_AT_THROW, RID_AT_TRY, RID_AT_CATCH, RID_AT_FINALLY, RID_AT_SYNCHRONIZED, RID_AT_INTERFACE, + /* APPLE LOCAL C* language */ + RID_AT_OPTIONAL, RID_AT_REQUIRED, + /* APPLE LOCAL C* property (Radar 4436866) */ + RID_AT_PROPERTY, RID_AT_IMPLEMENTATION, + /* APPLE LOCAL C* property (Radar 4436866, 4591909, 4621020) */ + RID_READONLY, RID_GETTER, RID_SETTER, + RID_NONATOMIC, RID_MAX, @@ -888,8 +896,23 @@ extern void c_parse_error (const char *, enum cpp_ttype, tree); extern tree objc_is_class_name (tree); extern tree objc_is_object_ptr (tree); extern void objc_check_decl (tree); +/* APPLE LOCAL radar 4281748 */ +extern void objc_check_global_decl (tree); extern int objc_is_reserved_word (tree); -extern bool objc_compare_types (tree, tree, int, tree); +/* APPLE LOCAL 4154928 */ +extern tree objc_common_type (tree, tree); +/* APPLE LOCAL 4330422 */ +extern tree objc_non_volatilized_type (tree); +/* APPLE LOCAL radar 4697411 */ +extern void objc_volatilize_component_ref (tree, tree); +/* APPLE LOCAL radar 6231433 */ +extern bool objc_compare_types (tree, tree, int, tree, const char *); +/* APPLE LOCAL radar 4229905 - radar 6231433 */ +extern bool objc_have_common_type (tree, tree, int, tree, const char *); +/* APPLE LOCAL radar 4133425 */ +extern bool objc_diagnose_private_ivar (tree); +/* APPLE LOCAL radar 4507230 */ +bool objc_type_valid_for_messaging (tree); extern void objc_volatilize_decl (tree); extern bool objc_type_quals_match (tree, tree); extern tree objc_rewrite_function_call (tree, tree); @@ -900,7 +923,8 @@ extern int objc_is_public (tree, tree); extern tree objc_is_id (tree); extern void objc_declare_alias (tree, tree); extern void objc_declare_class (tree); -extern void objc_declare_protocols (tree); +/* APPLE LOCAL radar 4947311 - protocol attributes */ +extern void objc_declare_protocols (tree, tree); extern tree objc_build_message_expr (tree); extern tree objc_finish_message_expr (tree, tree, tree); extern tree objc_build_selector_expr (tree); @@ -910,23 +934,40 @@ extern tree objc_build_string_object (tree); extern tree objc_get_protocol_qualified_type (tree, tree); extern tree objc_get_class_reference (tree); extern tree objc_get_class_ivars (tree); -extern void objc_start_class_interface (tree, tree, tree); +/* APPLE LOCAL begin radar 4291785 */ +extern tree objc_get_interface_ivars (tree); +extern void objc_detect_field_duplicates (tree); +/* APPLE LOCAL end radar 4291785 */ +/* APPLE LOCAL radar 4548636 */ +extern void objc_start_class_interface (tree, tree, tree, tree); extern void objc_start_category_interface (tree, tree, tree); -extern void objc_start_protocol (tree, tree); +/* APPLE LOCAL radar 4947311 - protocol attributes */ +extern void objc_start_protocol (tree, tree, tree); extern void objc_continue_interface (void); extern void objc_finish_interface (void); extern void objc_start_class_implementation (tree, tree); extern void objc_start_category_implementation (tree, tree); +/* APPLE LOCAL radar 4592503 */ +extern void objc_checkon_weak_attribute (tree); +/* APPLE LOCAL begin radar 5847976 */ +extern tree build_block_object_assign_call_exp (tree, tree, int); +extern tree build_block_object_dispose_call_exp (tree, int); +extern int objc_is_gcable_type (tree); +/* APPLE LOCAL end radar 5847976 */ extern void objc_continue_implementation (void); extern void objc_finish_implementation (void); extern void objc_set_visibility (int); extern void objc_set_method_type (enum tree_code); extern tree objc_build_method_signature (tree, tree, tree, bool); -extern void objc_add_method_declaration (tree); -extern void objc_start_method_definition (tree); +/* APPLE LOCAL begin radar 3803157 - objc attribute */ +extern bool objc_method_decl (enum tree_code); +extern void objc_add_method_declaration (tree, tree); +extern void objc_start_method_definition (tree, tree); +/* APPLE LOCAL end radar 3803157 - objc attribute */ extern void objc_finish_method_definition (tree); extern void objc_add_instance_variable (tree); -extern tree objc_build_keyword_decl (tree, tree, tree); +/* APPLE LOCAL radar 4157812 */ +extern tree objc_build_keyword_decl (tree, tree, tree, tree); extern tree objc_build_throw_stmt (tree); extern void objc_begin_try_stmt (location_t, tree); extern tree objc_finish_try_stmt (void); @@ -937,6 +978,52 @@ extern tree objc_build_synchronized (location_t, tree, tree); extern int objc_static_init_needed_p (void); extern tree objc_generate_static_init_call (tree); extern tree objc_generate_write_barrier (tree, enum tree_code, tree); +/* APPLE LOCAL radar 5276085 */ +extern void objc_weak_reference_expr (tree*); +/* APPLE LOCAL begin 5276085 */ +extern tree objc_build_weak_reference_tree (tree); +/* APPLE LOCAL end 5276085 */ + +/* APPLE LOCAL begin C* language */ +extern void objc_set_method_opt (int); +void objc_finish_foreach_loop (location_t, tree, tree, tree, tree); +tree objc_build_component_ref (tree, tree); +tree objc_build_foreach_components (tree, tree*, tree*, tree*, + tree*, tree*, tree*); +/* APPLE LOCAL end C* language */ +/* APPLE LOCAL begin C* property (Radar 4436866) */ +void objc_set_property_attr (int, tree); +void objc_add_property_variable (tree); +/* APPLE LOCAL begin radar 5285911 */ +tree objc_build_property_reference_expr (tree, tree); +bool objc_property_reference_expr (tree); +/* APPLE LOCAL end radar 5285911 */ +/* APPLE LOCAL radar 5802025 */ +tree objc_build_property_getter_func_call (tree); +tree objc_build_setter_call (tree, tree); +/* APPLE LOCAL end C* property (Radar 4436866) */ +/* APPLE LOCAL radar 4712269 */ +tree objc_build_incr_decr_setter_call (enum tree_code, tree, tree); + +/* APPLE LOCAL begin C* warnings to easy porting to new abi */ +void diagnose_selector_cast (tree cast_type, tree sel_exp); +/* APPLE LOCAL end C* warnings to easy porting to new abi */ + +/* APPLE LOCAL begin radar 4441049 */ +tree objc_v2_component_ref_field_offset (tree); +tree objc_v2_bitfield_ivar_bitpos (tree); +/* APPLE LOCAL end radar 4441049 */ + +/* APPLE LOCAL begin 4985544 */ +bool objc_check_format_nsstring (tree, unsigned HOST_WIDE_INT, bool *); +/* APPLE LOCAL end 4985544 */ + +/* APPLE LOCAL radar 5202926 */ +bool objc_anonymous_local_objc_name (const char *); +/* APPLE LOCAL begin radar 5195402 */ +bool objc_check_nsstring_pointer_type (tree); +bool objc_check_cfstringref_type (tree); +/* APPLE LOCAL end radar 5195402 */ /* The following are provided by the C and C++ front-ends, and called by ObjC/ObjC++. */ @@ -950,6 +1037,116 @@ extern void pp_file_change (const struct line_map *); extern void pp_dir_change (cpp_reader *, const char *); extern bool check_missing_format_attribute (tree, tree); + +/* APPLE LOCAL begin radar 5847976 */ +/* Runtime support functions used by compiler when generating copy/dispose helpers */ +enum { + BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), block, ... */ + BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ + BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the __block variable */ + BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy helpers */ + BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose support routines */ + BLOCK_BYREF_CURRENT_MAX = 256 +}; +/* APPLE LOCAL end radar 5847976 */ +/* APPLE LOCAL begin radar 5732232 - blocks */ +enum { + BLOCK_NEEDS_FREE = (1 << 24), + BLOCK_HAS_COPY_DISPOSE = (1 << 25), + /* APPLE LOCAL radar 6214617 */ + BLOCK_HAS_CXX_OBJ = (1 << 26), + BLOCK_IS_GC = (1 << 27), + /* APPLE LOCAL radar 5822844 */ + BLOCK_IS_GLOBAL = (1 << 28), + /* APPLE LOCAL radar 7735196 */ + BLOCK_USE_STRET = (1 << 29) +}; + +struct block_sema_info { + tree helper_func_decl; + tree copy_helper_func_decl; + tree destroy_helper_func_decl; + tree block_arg_ptr_type; + /* This is for C. */ + struct c_arg_info * arg_info; + tree block_ref_decl_list; + tree block_byref_decl_list; + /* APPLE LOCAL radar 5803600 */ + tree block_byref_global_decl_list; + tree block_original_ref_decl_list; + /* APPLE LOCAL radar 5847213 - tree block_original_byref_decl_list is removed. */ + tree block_body; + bool BlockHasCopyDispose; + /* APPLE LOCAL radar 6214617 */ + bool BlockImportsCxxObjects; + /* APPLE LOCAL radar 6185344 */ + bool block_has_return_type; /* When true, block has a declared return type. */ + + /* the_scope - This is the scope for the block itself, which + contains arguments etc. Use only for C. */ + struct c_scope *the_scope; + /* Same as the above, only for C++. */ + struct cp_binding_level *cp_the_scope; + + /* return_type - This will get set to block result type, by looking + at return types, if any, in the block body. */ + tree return_type; + + /* prev_block_info - If this is nested inside another block, this points + to the outer block. */ + struct block_sema_info *prev_block_info; +}; + +extern struct block_sema_info *cur_block; +extern tree build_helper_func_decl (tree, tree); +extern tree build_block_byref_decl (tree, tree, tree); +extern tree build_block_ref_decl (tree, tree); +extern tree begin_block (void); +extern struct block_sema_info *finish_block (tree); +extern bool in_imm_block (void); +extern bool lookup_name_in_block (tree, tree*); +extern void push_to_top_level (void); +extern void pop_from_top_level (void); +extern void start_block_helper_function (tree func_decl); +extern void block_build_prologue (struct block_sema_info *block_impl); +extern tree c_finish_return (tree); +extern bool block_requires_copying (tree); +/* APPLE LOCAL begin radar 5803600 */ +extern void add_block_global_byref_list (tree); +extern bool in_block_global_byref_list (tree); +/* APPLE LOCAL end radar 5803600 */ +/* APPLE LOCAL end radar 5732232 - blocks */ +/* APPLE LOCAL begin radar 5932809 - copyable byref blocks */ +extern tree build_byref_local_var_access (tree, tree); +extern tree do_digest_init (tree, tree); +/* APPLE LOCAL end radar 5932809 - copyable byref blocks */ +/* APPLE LOCAL begin radar 6237713 */ +extern bool any_recognized_block_attribute (tree); +/* APPLE LOCAL end radar 6237713 */ + +/* APPLE LOCAL begin radar 5847213 */ +extern tree build_block_descriptor_type (bool); +/* APPLE LOCAL end radar 5847213 */ +/* APPLE LOCAL begin radar 6083129 - byref escapes */ +extern tree build_block_byref_release_exp (tree); +/* APPLE LOCAL end radar 6083129 - byref escapes */ + +/* APPLE LOCAL radar 6040305 - blocks */ +extern tree build_indirect_object_id_exp (tree); +/* APPLE LOCAL begin radar 6212722 */ +extern tree array_to_pointer_conversion (tree); +extern tree function_to_pointer_conversion (tree); +/* APPLE LOCAL end radar 6212722 */ + +/* APPLE LOCAL radar 6160536 */ +extern tree build_block_helper_name (int); + +/* APPLE LOCAL radar 6353006 */ +extern tree c_build_generic_block_struct_type (void); + +/* APPLE LOCAL radar 7760213 */ +extern int HasByrefArray(tree); + /* In c-omp.c */ extern tree c_finish_omp_master (tree); extern tree c_finish_omp_critical (tree, tree); diff --git a/contrib/gcc/c-convert.c b/contrib/gcc/c-convert.c index b2b5ea10fc71..b13a713ac7b6 100644 --- a/contrib/gcc/c-convert.c +++ b/contrib/gcc/c-convert.c @@ -104,6 +104,10 @@ convert (tree type, tree expr) return fold_convert (type, c_objc_common_truthvalue_conversion (expr)); if (code == POINTER_TYPE || code == REFERENCE_TYPE) return fold (convert_to_pointer (type, e)); + /* APPLE LOCAL begin blocks (C++ ck) */ + if (code == BLOCK_POINTER_TYPE) + return fold (convert_to_block_pointer (type, e)); + /* APPLE LOCAL end blocks (C++ ck) */ if (code == REAL_TYPE) return fold (convert_to_real (type, e)); if (code == COMPLEX_TYPE) diff --git a/contrib/gcc/c-cppbuiltin.c b/contrib/gcc/c-cppbuiltin.c index 906ef555408a..6dd6e18b6e0d 100644 --- a/contrib/gcc/c-cppbuiltin.c +++ b/contrib/gcc/c-cppbuiltin.c @@ -501,6 +501,11 @@ c_cpp_builtins (cpp_reader *pfile) /* Other target-independent built-ins determined by command-line options. */ + /* APPLE LOCAL begin blocks */ + /* APPLE LOCAL radar 5868913 */ + if (flag_blocks) + cpp_define (pfile, "__BLOCKS__=1"); + /* APPLE LOCAL end blocks */ if (optimize_size) cpp_define (pfile, "__OPTIMIZE_SIZE__"); if (optimize) diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c index 7b3833c384aa..0f23ee3f09cb 100644 --- a/contrib/gcc/c-decl.c +++ b/contrib/gcc/c-decl.c @@ -71,6 +71,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA enum decl_context { NORMAL, /* Ordinary declaration */ FUNCDEF, /* Function definition */ + /* APPLE LOCAL blocks 6339747 */ + BLOCKDEF, /* Block literal declaration */ PARM, /* Declaration of parm before function body */ FIELD, /* Declaration inside struct or union */ TYPENAME}; /* Typename (inside cast or sizeof) */ @@ -3191,7 +3193,28 @@ add_flexible_array_elts_to_size (tree decl, tree init) = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type)); } } - + +/* APPLE LOCAL begin blocks 6339747 */ +/* Decode a block literal type, such as "int **", returning a ...FUNCTION_DECL node. */ + +tree +grokblockdecl (struct c_declspecs *specs, struct c_declarator *declarator) +{ + tree decl; + tree attrs = specs->attrs; + + specs->attrs = NULL_TREE; + + decl = grokdeclarator (declarator, specs, BLOCKDEF, + false, NULL); + + /* Apply attributes. */ + decl_attributes (&decl, attrs, 0); + + return decl; +} +/* APPLE LOCAL end blocks 6339747 */ + /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ tree @@ -3453,6 +3476,322 @@ c_maybe_initialize_eh (void) using_eh_for_cleanups (); } +/* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ cr) */ +#define BLOCK_ALIGN_MAX 18 +static tree block_byref_id_object_copy[BLOCK_BYREF_CURRENT_MAX*(BLOCK_ALIGN_MAX+1)]; +static tree block_byref_id_object_dispose[BLOCK_BYREF_CURRENT_MAX*(BLOCK_ALIGN_MAX+1)]; + +/** + This routine builds: + + void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, + struct Block_byref_id_object *src) { + _Block_object_assign (&_dest->object, _src->object, BLOCK_FIELD_IS_OBJECT[|BLOCK_FIELD_IS_WEAK]) // objects + _Block_object_assign(&_dest->object, _src->object, BLOCK_FIELD_IS_BLOCK[|BLOCK_FIELD_IS_WEAK]) // blocks + } */ +static void +synth_block_byref_id_object_copy_func (int flag, int kind) +{ + tree stmt, fnbody; + tree dst_arg, src_arg; + tree dst_obj, src_obj; + struct c_arg_info * arg_info; + tree call_exp; + gcc_assert (block_byref_id_object_copy[kind]); + /* Set up: (void* _dest, void*_src) parameters. */ + dst_arg = build_decl (PARM_DECL, get_identifier ("_dst"), + ptr_type_node); + TREE_USED (dst_arg) = 1; + DECL_ARG_TYPE (dst_arg) = ptr_type_node; + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + ptr_type_node); + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = ptr_type_node; + arg_info = xcalloc (1, sizeof (struct c_arg_info)); + TREE_CHAIN (dst_arg) = src_arg; + arg_info->parms = dst_arg; + arg_info->types = tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, + ptr_type_node, + NULL_TREE)); + /* function header synthesis. */ + push_function_context (); + start_block_helper_function (block_byref_id_object_copy[kind]); + store_parm_decls_from (arg_info); + + /* Body of the function. */ + stmt = c_begin_compound_stmt (true); + /* Build dst->object */ + dst_obj = build_indirect_object_id_exp (dst_arg); + + + /* src_obj is: _src->object. */ + src_obj = build_indirect_object_id_exp (src_arg); + + /* APPLE LOCAL begin radar 6180456 */ + /* _Block_object_assign (&_dest->object, _src->object, BLOCK_FIELD_IS_OBJECT) or : + _Block_object_assign (&_dest->object, _src->object, BLOCK_FIELD_IS_BLOCK) */ + /* APPLE LOCAL begin radar 6573923 */ + /* Also add the new flag when calling _Block_object_dispose + from byref dispose helper. */ + flag |= BLOCK_BYREF_CALLER; + /* APPLE LOCAL end radar 6573923 */ + call_exp = build_block_object_assign_call_exp (build_fold_addr_expr (dst_obj), src_obj, flag); + add_stmt (call_exp); + /* APPLE LOCAL end radar 6180456 */ + + fnbody = c_end_compound_stmt (stmt, true); + add_stmt (fnbody); + finish_function (); + pop_function_context (); + free (arg_info); +} + +/** + This routine builds: + + void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { + _Block_object_dispose(_src->object, BLOCK_FIELD_IS_OBJECT[|BLOCK_FIELD_IS_WEAK]) // object + _Block_object_dispose(_src->object, BLOCK_FIELD_IS_BLOCK[|BLOCK_FIELD_IS_WEAK]) // block + } */ +static void +synth_block_byref_id_object_dispose_func (int flag, int kind) +{ + tree stmt, fnbody; + tree src_arg, src_obj, rel_exp; + struct c_arg_info * arg_info; + gcc_assert (block_byref_id_object_dispose[kind]); + /* Set up: (void *_src) parameter. */ + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + ptr_type_node); + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = ptr_type_node; + arg_info = xcalloc (1, sizeof (struct c_arg_info)); + arg_info->parms = src_arg; + arg_info->types = tree_cons (NULL_TREE, ptr_type_node, + NULL_TREE); + /* function header synthesis. */ + push_function_context (); + start_block_helper_function (block_byref_id_object_dispose[kind]); + store_parm_decls_from (arg_info); + + /* Body of the function. */ + stmt = c_begin_compound_stmt (true); + src_obj = build_indirect_object_id_exp (src_arg); + + /* APPLE LOCAL begin radar 6180456 */ + /* _Block_object_dispose(_src->object, BLOCK_FIELD_IS_OBJECT) : or + _Block_object_dispose(_src->object, BLOCK_FIELD_IS_BLOCK) */ + /* APPLE LOCAL begin radar 6573923 */ + /* Also add the new flag when calling _Block_object_dispose + from byref dispose helper. */ + flag |= BLOCK_BYREF_CALLER; + /* APPLE LOCAL end radar 6573923 */ + rel_exp = build_block_object_dispose_call_exp (src_obj, flag); + /* APPLE LOCAL end radar 6180456 */ + add_stmt (rel_exp); + + fnbody = c_end_compound_stmt (stmt, true); + add_stmt (fnbody); + finish_function (); + pop_function_context (); + free (arg_info); +} + +/* new_block_byref_decl - This routine changes a 'typex x' declared variable into: + + struct __Block_byref_x { + // APPLE LOCAL radar 6244520 + void *__isa; // NULL for everything except __weak pointers + struct Block_byref_x *__forwarding; + int32_t __flags; + int32_t __size; + void *__ByrefKeepFuncPtr; // Only if variable is __block ObjC object + void *__ByrefDestroyFuncPtr; // Only if variable is __block ObjC object + typex x; + } x; +*/ + +static tree +new_block_byref_decl (tree decl) +{ + static int unique_count; + /* APPLE LOCAL radar 5847976 */ + int save_flag_objc_gc; + tree Block_byref_type; + tree field_decl_chain, field_decl; + const char *prefix = "__Block_byref_"; + char *string = alloca (strlen (IDENTIFIER_POINTER (DECL_NAME (decl))) + + strlen (prefix) + 8 /* to hold the count */); + + sprintf (string, "%s%d_%s", prefix, ++unique_count, + IDENTIFIER_POINTER (DECL_NAME (decl))); + + push_to_top_level (); + Block_byref_type = start_struct (RECORD_TYPE, get_identifier (string)); + + /* APPLE LOCAL begin radar 6244520 */ + /* void *__isa; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node); + field_decl_chain = field_decl; + /* APPLE LOCAL end radar 6244520 */ + + /* struct Block_byref_x *__forwarding; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__forwarding"), + build_pointer_type (Block_byref_type)); + /* APPLE LOCAL radar 6244520 */ + chainon (field_decl_chain, field_decl); + + /* int32_t __flags; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__flags"), + unsigned_type_node); + chainon (field_decl_chain, field_decl); + + /* int32_t __size; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__size"), + unsigned_type_node); + chainon (field_decl_chain, field_decl); + + if (COPYABLE_BYREF_LOCAL_NONPOD (decl)) + { + /* void *__ByrefKeepFuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__ByrefKeepFuncPtr"), + ptr_type_node); + chainon (field_decl_chain, field_decl); + + /* void *__ByrefDestroyFuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__ByrefDestroyFuncPtr"), + ptr_type_node); + chainon (field_decl_chain, field_decl); + } + + /* typex x; */ + field_decl = build_decl (FIELD_DECL, DECL_NAME (decl), TREE_TYPE (decl)); + chainon (field_decl_chain, field_decl); + + pop_from_top_level (); + /* APPLE LOCAL begin radar 5847976 */ + /* Hack so we don't issue warning on a field_decl having __weak attribute */ + save_flag_objc_gc = flag_objc_gc; + flag_objc_gc = 0; + finish_struct (Block_byref_type, field_decl_chain, NULL_TREE); + flag_objc_gc = save_flag_objc_gc; + /* APPLE LOCAL end radar 5847976 */ + + TREE_TYPE (decl) = Block_byref_type; + /* Force layout_decl to recompute these fields. */ + DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0; + layout_decl (decl, 0); + return decl; +} + +/* init_byref_decl - This routine builds the initializer for the __Block_byref_x + type in the form of: + { NULL, &x, 0, sizeof(struct __Block_byref_x), initializer-expr}; + + or: + { NULL, &x, 0, sizeof(struct __Block_byref_x)}; + when INIT is NULL_TREE + + For __block ObjC objects, it also adds "byref_keep" and "byref_destroy" + Funtion pointers. So the most general initializers would be: + + { NULL, &x, 0, sizeof(struct __Block_byref_x), &byref_keep, &byref_destroy, + &initializer-expr}; +*/ +static tree +/* APPLE LOCAL radar 5847976 */ +init_byref_decl (tree decl, tree init, int flag) +{ + tree initlist; + tree block_byref_type = TREE_TYPE (decl); + int size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (block_byref_type)); + unsigned flags = 0; + tree fields; + + if (COPYABLE_BYREF_LOCAL_NONPOD (decl)) + flags = BLOCK_HAS_COPY_DISPOSE; + + fields = TYPE_FIELDS (block_byref_type); + /* APPLE LOCAL begin radar 6244520 */ + /* APPLE LOCAL begin radar 5847976 */ + initlist = tree_cons (fields, fold_convert (ptr_type_node, ((flag & BLOCK_FIELD_IS_WEAK) != 0) ? integer_one_node + : integer_zero_node), 0); + /* APPLE LOCAL end radar 5847976 */ + fields = TREE_CHAIN (fields); + + initlist = tree_cons (fields, + build_unary_op (ADDR_EXPR, decl, 0), initlist); + /* APPLE LOCAL end radar 6244520 */ + fields = TREE_CHAIN (fields); + + initlist = tree_cons (fields, build_int_cst (TREE_TYPE (fields), flags), + initlist); + fields = TREE_CHAIN (fields); + initlist = tree_cons (fields, build_int_cst (TREE_TYPE (fields), size), + initlist); + fields = TREE_CHAIN (fields); + + if (COPYABLE_BYREF_LOCAL_NONPOD (decl)) + { + char name[64]; + int align = exact_log2 ((DECL_ALIGN (decl)+TYPE_ALIGN (ptr_type_node)-1) / TYPE_ALIGN (ptr_type_node)); + int kind; + if (align == -1 || align > BLOCK_ALIGN_MAX) { + error ("invalid alignment for __block variable"); + kind = 0; + } else + kind = align*BLOCK_BYREF_CURRENT_MAX + flag; + /* Add &__Block_byref_id_object_copy, &__Block_byref_id_object_dispose + initializers. */ + if (!block_byref_id_object_copy[kind]) + { + /* Build a void __Block_byref_id_object_copy(void*, void*) type. */ + tree func_type = + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node))); + sprintf (name, "__Block_byref_id_object_copy%d", kind); + block_byref_id_object_copy[kind] = build_helper_func_decl (get_identifier (name), + func_type); + /* Synthesize function definition. */ + synth_block_byref_id_object_copy_func (flag, kind); + } + initlist = tree_cons (fields, + build_fold_addr_expr (block_byref_id_object_copy[kind]), + initlist); + fields = TREE_CHAIN (fields); + + if (!block_byref_id_object_dispose[kind]) + { + /* Synthesize void __Block_byref_id_object_dispose (void*) and + build &__Block_byref_id_object_dispose. */ + tree func_type = + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, void_list_node)); + sprintf (name, "__Block_byref_id_object_dispose%d", kind); + block_byref_id_object_dispose[kind] = build_helper_func_decl (get_identifier (name), + func_type); + /* Synthesize function definition. */ + synth_block_byref_id_object_dispose_func (flag, kind); + } + initlist = tree_cons (fields, + build_fold_addr_expr (block_byref_id_object_dispose[kind]), + initlist); + fields = TREE_CHAIN (fields); + } + + if (init) + { + init = do_digest_init (TREE_TYPE (fields), init); + initlist = tree_cons (fields, init, initlist); + } + init = build_constructor_from_list (block_byref_type, nreverse (initlist)); + return init; +} +/* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ cr) */ + /* Finish processing of a declaration; install its initial value. If the length of an array type is not known before, @@ -3479,6 +3818,45 @@ finish_decl (tree decl, tree init, tree asmspec_tree) /* Don't crash if parm is initialized. */ if (TREE_CODE (decl) == PARM_DECL) init = 0; + /* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ cq) */ + /* We build a new type for each local variable declared as __block + and initialize it to a list of initializers. */ + else if (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl)) + { + if (DECL_EXTERNAL (decl) || TREE_STATIC (decl)) + { + error ("__block attribute on %q+D not allowed, only allowed on local variables", decl); + COPYABLE_BYREF_LOCAL_VAR (decl) = 0; + COPYABLE_BYREF_LOCAL_NONPOD (decl) = 0; + } + else + { + int flag = 0; + if (objc_is_gcable_type (TREE_TYPE (decl)) == -1) + flag = BLOCK_FIELD_IS_WEAK; + if (block_requires_copying (decl)) + { + if (TREE_CODE (TREE_TYPE (decl)) == BLOCK_POINTER_TYPE) + flag |= BLOCK_FIELD_IS_BLOCK; + else + flag |= BLOCK_FIELD_IS_OBJECT; + } + decl = new_block_byref_decl (decl); + /* APPLE LOCAL begin radar 6289031 */ +#if 0 + if (! flag_objc_gc_only) +#endif + { + push_cleanup (decl, build_block_byref_release_exp (decl), false); + } + /* APPLE LOCAL end radar 6289031 */ + /* APPLE LOCAL begin radar 5847976 */ + COPYABLE_WEAK_BLOCK (decl) = ((flag & BLOCK_FIELD_IS_WEAK) != 0); + init = init_byref_decl (decl, init, flag); + /* APPLE LOCAL end radar 5847976 */ + } + } + /* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ cq) */ if (init) store_init_value (decl, init); @@ -4097,6 +4475,8 @@ grokdeclarator (const struct c_declarator *declarator, case cdk_function: case cdk_array: case cdk_pointer: + /* APPLE LOCAL radar 5732232 - blocks */ + case cdk_block_pointer: funcdef_syntax = (decl->kind == cdk_function); decl = decl->declarator; break; @@ -4705,6 +5085,30 @@ grokdeclarator (const struct c_declarator *declarator, declarator = declarator->declarator; break; } + + + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cj) */ + case cdk_block_pointer: + { + if (TREE_CODE (type) != FUNCTION_TYPE) + { + error ("block pointer to non-function type is invalid"); + type = error_mark_node; + } + else + { + type = build_block_pointer_type (type); + /* APPLE LOCAL begin radar 5814025 (C++ cj) */ + /* Process type qualifiers (such as const or volatile) + that were given inside the `^'. */ + type_quals = declarator->u.pointer_quals; + /* APPLE LOCAL end radar 5814025 (C++ cj) */ + declarator = declarator->declarator; + } + break; + } + /* APPLE LOCAL end radar 5732232 - blocks (C++ cj) */ + default: gcc_unreachable (); } @@ -4730,6 +5134,41 @@ grokdeclarator (const struct c_declarator *declarator, type = error_mark_node; } + /* APPLE LOCAL begin blocks 6339747 */ + if (decl_context == BLOCKDEF) + { + tree decl; + + if (type == error_mark_node) + return error_mark_node; + + if (TREE_CODE (type) != FUNCTION_TYPE) + { + tree arg_types; + + if (TREE_CODE (type) == ARRAY_TYPE) + { + error ("block declared as returning an array"); + return error_mark_node; + } + + arg_info = XOBNEW (&parser_obstack, struct c_arg_info); + arg_info->parms = 0; + arg_info->tags = 0; + arg_info->types = 0; + arg_info->others = 0; + arg_info->pending_sizes = 0; + arg_info->had_vla_unspec = 0; + arg_types = grokparms (arg_info, false); + type_quals = TYPE_UNQUALIFIED; + type = build_function_type (type, arg_types); + } + decl = build_decl (FUNCTION_DECL, NULL_TREE, type); + DECL_ARGUMENTS (decl) = arg_info ? arg_info->parms : NULL_TREE; + return decl; + } + /* APPLE LOCAL end blocks 6339747 */ + /* If this is declaring a typedef name, return a TYPE_DECL. */ if (storage_class == csc_typedef) @@ -7071,6 +7510,13 @@ check_for_loop_decls (void) error ("% declared in % loop initial declaration", id); break; + /* APPLE LOCAL begin radar 6268817 */ + case FUNCTION_DECL: + /* Block helper function can be declared in the statement block + for the for-loop declarations. */ + if (BLOCK_SYNTHESIZED_FUNC (decl)) + break; + /* APPLE LOCAL end radar 6268817 */ default: error ("declaration of non-variable %q+D in % loop " "initial declaration", decl); @@ -7111,7 +7557,10 @@ c_pop_function_context (struct function *f) { struct language_function *p = f->language; - if (DECL_STRUCT_FUNCTION (current_function_decl) == 0 + /* APPLE LOCAL begin blocks 6040305 */ + if (current_function_decl + && DECL_STRUCT_FUNCTION (current_function_decl) == 0 + /* APPLE LOCAL end blocks 6040305 */ && DECL_SAVED_TREE (current_function_decl) == NULL_TREE) { /* Stop pointing to the local nodes about to be freed. */ @@ -7294,6 +7743,536 @@ make_pointer_declarator (struct c_declspecs *type_quals_attrs, return ret; } +/* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ ch) */ +/* build_byref_local_var_access - converts EXPR to: + EXPR.__forwarding->. +*/ +tree +build_byref_local_var_access (tree expr, tree decl_name) +{ + tree exp = build_component_ref (expr, get_identifier ("__forwarding")); + exp = build_indirect_ref (exp, "unary *"); + exp = build_component_ref (exp, decl_name); + return exp; +} +/* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ ch) */ +/* APPLE LOCAL begin radar 5732232 - blocks (C++ ch) */ +/** + build_block_byref_decl - This routine inserts a variable declared as a + 'byref' variable using the |...| syntax in helper function's outer-most scope. +*/ +tree +build_block_byref_decl (tree name, tree decl, tree exp) +{ + struct c_scope *scope = current_scope; + tree ptr_type, byref_decl; + /* APPLE LOCAL begin radar 6225809 */ + if (cur_block->prev_block_info) { + /* Traverse enclosing blocks. Insert a __block variable in + each enclosing block which has no declaration of this + variable. This is to ensure that the current (inner) block + gets the __block version of the variable; */ + struct block_sema_info *cb = cur_block->prev_block_info; + while (cb) { + struct c_binding *b = I_SYMBOL_BINDING (name); + /* Find the first declaration not in current block. */ + while (b && b->decl + && (TREE_CODE (b->decl) == VAR_DECL + || TREE_CODE (b->decl) == PARM_DECL) + && b->depth >= cur_block->the_scope->depth) + b = b->shadowed; + + /* Is the next declaration not in enclosing block? */ + if (b && b->decl + && (TREE_CODE (b->decl) == VAR_DECL + || TREE_CODE (b->decl) == PARM_DECL) + && b->depth < cb->the_scope->depth) { + /* No declaration of variable seen in the block. Must insert one. */ + struct c_scope *save_scope = current_scope; + struct block_sema_info *save_current_block = cur_block; + current_scope = cb->the_scope; + cur_block = cb; + decl = build_block_byref_decl (name, decl, exp); + cur_block = save_current_block; + current_scope = save_scope; + } + cb = cb->prev_block_info; + } + } + /* APPLE LOCAL end radar 6225809 */ + + /* If it is already a byref declaration, do not add the pointer type + because such declarations already have the pointer type + added. This happens when we have two nested byref declarations in + nested blocks. */ + ptr_type = (TREE_CODE (decl) == VAR_DECL && BLOCK_DECL_BYREF (decl)) + ? TREE_TYPE (decl) : build_pointer_type (TREE_TYPE (decl)); + byref_decl = build_decl (VAR_DECL, name, ptr_type); + /* APPLE LOCAL begin radars 6144664 & 6145471 */ + DECL_SOURCE_LOCATION (byref_decl) = DECL_SOURCE_LOCATION + (cur_block->helper_func_decl); + /* APPLE LOCAL end radars 6144664 & 6145471 */ + BLOCK_DECL_BYREF (byref_decl) = 1; + + /* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ ch) */ + if (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl)) + { + COPYABLE_BYREF_LOCAL_VAR (byref_decl) = 1; + COPYABLE_BYREF_LOCAL_NONPOD (byref_decl) = COPYABLE_BYREF_LOCAL_NONPOD (decl); + /* APPLE LOCAL radar 5847976 */ + COPYABLE_WEAK_BLOCK (byref_decl) = COPYABLE_WEAK_BLOCK (decl); + } + /* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ ch) */ + + /* In the presence of nested "{" + move up the scope chain until reaching the main function body's scope. + */ + while (scope && !scope->function_body) + scope = scope->outer; + /* Current scope must be that of the main function body. */ + gcc_assert (scope && scope->function_body); + bind (name, byref_decl, + scope, /*invisible=*/false, /*nested=*/false); + cur_block->block_byref_decl_list = + tree_cons (NULL_TREE, byref_decl, cur_block->block_byref_decl_list); + /* APPLE LOCAL radar 5847213 - building block_original_byref_decl_list list removed. */ + /* APPLE LOCAL begin radar 6289031 */ +#if 0 + if (! flag_objc_gc_only) +#endif + push_cleanup (byref_decl, build_block_byref_release_exp (byref_decl), false); + /* APPLE LOCAL end radar 6289031 */ + + return byref_decl; +} + +/** + build_block_ref_decl - This routine inserts a copied-in variable (a variable + referenced in the block but whose scope is outside the block) in helper + function's outer-most scope. It also sets its type to 'const' as such + variables are read-only. +*/ +tree +build_block_ref_decl (tree name, tree decl) +{ + struct c_scope *scope = current_scope; + tree ref_decl; + /* APPLE LOCAL radar 6212722 */ + tree type, exp; + /* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ ch) */ + /* 'decl' was previously declared as __block. Simply, copy the value + embedded in the above variable. */ + if (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl)) + decl = build_byref_local_var_access (decl, DECL_NAME (decl)); + else { + /* APPLE LOCAL begin radar 5988451 (C++ ch) */ + if (cur_block->prev_block_info) { + /* Traverse enclosing blocks. Insert a copied-in variable in + each enclosing block which has no declaration of this + variable. This is to ensure that the current (inner) block + has the 'frozen' value of the copied-in variable; which means + the value of the copied in variable is at the point of the + block declaration and *not* when the inner block is + invoked. */ + struct block_sema_info *cb = cur_block->prev_block_info; + while (cb) { + struct c_binding *b = I_SYMBOL_BINDING (name); + /* Find the first declaration not in current block. */ + while (b && b->decl + && (TREE_CODE (b->decl) == VAR_DECL + || TREE_CODE (b->decl) == PARM_DECL) + && b->depth >= cur_block->the_scope->depth) + b = b->shadowed; + + /* Is the next declaration not in enclosing block? */ + if (b && b->decl + && (TREE_CODE (b->decl) == VAR_DECL + || TREE_CODE (b->decl) == PARM_DECL) + && b->depth < cb->the_scope->depth) { + /* No declaration of variable seen in the block. Must insert one, + so it 'freezes' the variable in this block. */ + struct c_scope *save_scope = current_scope; + struct block_sema_info *save_current_block = cur_block; + current_scope = cb->the_scope; + cur_block = cb; + decl = build_block_ref_decl (name, decl); + cur_block = save_current_block; + current_scope = save_scope; + } + cb = cb->prev_block_info; + } + } + /* APPLE LOCAL end radar 5988451 (C++ ch) */ + } + /* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ ch) */ + /* APPLE LOCAL begin radar 6212722 */ + exp = decl; + type = TREE_TYPE (exp); + if (TREE_CODE (type) == ARRAY_TYPE) { + exp = array_to_pointer_conversion (decl); + type = TREE_TYPE (exp); + } + else if (TREE_CODE (type) == FUNCTION_TYPE) { + exp = function_to_pointer_conversion (exp); + type = TREE_TYPE (exp); + } + ref_decl = build_decl (VAR_DECL, name, + build_qualified_type (type, TYPE_QUAL_CONST)); + /* APPLE LOCAL end radar 6212722 */ + /* APPLE LOCAL begin radars 6144664 & 6145471 */ + DECL_SOURCE_LOCATION (ref_decl) = DECL_SOURCE_LOCATION + (cur_block->helper_func_decl); + /* APPLE LOCAL end radars 6144664 & 6145471 */ + DECL_INITIAL (ref_decl) = error_mark_node; + /* APPLE LOCAL radar 5805175 - blocks (C++ ch) */ + c_apply_type_quals_to_decl (TYPE_QUAL_CONST, ref_decl); + BLOCK_DECL_COPIED (ref_decl) = 1; + + /* Find the scope for function body (outer-most scope) and insert + this variable in that scope. This is to avoid duplicate + declaration of the save variable. */ + while (scope && !scope->function_body) + scope = scope->outer; + /* We are enterring the copied-in variable in helper function's + outer scope; that of its main body. */ + gcc_assert (scope); + bind (name, ref_decl, + scope, /*invisible=*/false, /*nested=*/false); + cur_block->block_ref_decl_list = + tree_cons (NULL_TREE, ref_decl, cur_block->block_ref_decl_list); + cur_block->block_original_ref_decl_list = + /* APPLE LOCAL radar 6212722 */ + tree_cons (NULL_TREE, exp, cur_block->block_original_ref_decl_list); + return ref_decl; +} + +/* APPLE LOCAL begin radar 5847213 - radar 6329245 */ +static GTY (()) tree descriptor_ptr_type; +static GTY (()) tree descriptor_ptr_type_with_copydispose; +/** build_block_descriptor_type - This routine builds following internal type: + struct __block_descriptor { + unsigned long int reserved; // NULL + unsigned long int Size; // sizeof(struct Block_literal_1) + + // optional helper functions + void *CopyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE is set (withCopyDispose true) + void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE is set (withCopyDispose true) +} *descriptor_ptr_type; + +Objects of this type will always be static. This is one main component of abi change. +*/ +tree +build_block_descriptor_type (bool withCopyDispose) +{ + tree field_decl_chain, field_decl; + tree main_type; + + if (withCopyDispose && descriptor_ptr_type_with_copydispose) + return descriptor_ptr_type_with_copydispose; + if (!withCopyDispose && descriptor_ptr_type) + return descriptor_ptr_type; + + main_type = + withCopyDispose ? + start_struct (RECORD_TYPE, get_identifier ("__block_descriptor_withcopydispose")) + : start_struct (RECORD_TYPE, get_identifier ("__block_descriptor")); + + /* unsigned long int reserved; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("reserved"), long_unsigned_type_node); + field_decl_chain = field_decl; + + /* unsigned long int Size; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("Size"), long_unsigned_type_node); + chainon (field_decl_chain, field_decl); + + if (withCopyDispose) + { + /* void *CopyFuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("CopyFuncPtr"), ptr_type_node); + chainon (field_decl_chain, field_decl); + /* void *DestroyFuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("DestroyFuncPtr"), ptr_type_node); + chainon (field_decl_chain, field_decl); + } + + /* Mark this struct as being a block struct rather than a 'normal' + struct. */ + TYPE_BLOCK_IMPL_STRUCT (main_type) = 1; + finish_struct (main_type, field_decl_chain, NULL_TREE); + + main_type = build_pointer_type (main_type); + if (withCopyDispose) + descriptor_ptr_type_with_copydispose = main_type; + else + descriptor_ptr_type = main_type; + return main_type; +} +/* APPLE LOCAL end radar 5847213 - radar 6329245 */ + +/* APPLE LOCAL begin radar 5814025 (C++ ch) */ +struct c_declarator * +make_block_pointer_declarator (struct c_declspecs *type_quals_attrs, + struct c_declarator *target) +{ + int quals = 0; + struct c_declarator *itarget = target; + struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator); + + if (type_quals_attrs) + { + tree attrs = type_quals_attrs->attrs; + quals = quals_from_declspecs (type_quals_attrs); + if (attrs != NULL_TREE) + itarget = build_attrs_declarator (attrs, target); + } + ret->kind = cdk_block_pointer; + /* APPLE LOCAL radar 5882266 (C++ ch) */ + ret->declarator = itarget; + ret->u.pointer_quals = quals; + return ret; +} +/* APPLE LOCAL end radar 5814025 (C++ ch) */ + +tree +begin_block (void) +{ + struct block_sema_info *csi; +#if 0 + push_scope (); +#endif + csi = (struct block_sema_info*)xcalloc (1, sizeof (struct block_sema_info)); + csi->prev_block_info = cur_block; + cur_block = csi; + return NULL_TREE; +} + +struct block_sema_info * +finish_block (tree block __attribute__ ((__unused__))) +{ + struct block_sema_info *csi = cur_block; + cur_block = cur_block->prev_block_info; +#if 0 + pop_scope (); +#endif + return csi; +} + +bool +in_imm_block (void) +{ + /* APPLE LOCAL radar 5988451 (C++ ch) */ + return (cur_block && cur_block->the_scope == current_scope); +} + +/* This routine returns 'true' if 'name' has a declaration inside the + current block, 'false' otherwise. If 'name' has no declaration in + the current block, it returns in DECL the user declaration for + 'name' found in the enclosing scope. Note that if it is declared + in current declaration, it can be either a user declaration or a + byref/copied-in declaration added in current block's scope by the + compiler. */ +bool +lookup_name_in_block (tree name, tree *decl) +{ + if (cur_block) + { + struct c_binding *b = I_SYMBOL_BINDING (name); + if (b->depth >= cur_block->the_scope->depth) + return true; + + /* Check for common case of block nested inside a non-block. */ + if (!cur_block->prev_block_info) + return false; + /* Check for less common case of nested blocks. */ + /* Declaration not in current block. Find the first user + declaration of 'name' in outer scope. */ + /* APPLE LOCAL begin radar 5988451 (C++ ch) */ + /* Check for variables only, as we may have parameters, such as + 'self' */ + /* Note that if a copied-in variable (BLOCK_DECL_COPIED) in the + enclosing block is found, it must be returned as this is + where the variable in current (nested block) will have to get + its value. */ + while (b && b->decl + && (TREE_CODE (b->decl) == VAR_DECL) + && BLOCK_DECL_BYREF (b->decl)) + b = b->shadowed; + /* APPLE LOCAL end radar 5988451 (C++ ch) */ + if (b && b->decl) + *decl = b->decl; + } + return false; +} + +static struct c_scope *save_current_scope; +static tree save_current_function_decl; +void +push_to_top_level (void) +{ + save_current_scope = current_scope; + save_current_function_decl = current_function_decl; + current_scope = file_scope; + current_function_decl = NULL_TREE; +} + +void +pop_from_top_level (void) +{ + current_scope = save_current_scope; + current_function_decl = save_current_function_decl; +} + +/** + build_helper_func_decl - This routine builds a FUNCTION_DECL for + a block helper function. +*/ +tree +build_helper_func_decl (tree ident, tree type) +{ + tree func_decl = build_decl (FUNCTION_DECL, ident, type); + DECL_EXTERNAL (func_decl) = 0; + TREE_PUBLIC (func_decl) = 0; + TREE_USED (func_decl) = 1; + TREE_NOTHROW (func_decl) = 0; + /* APPLE LOCAL radar 6172148 */ + BLOCK_SYNTHESIZED_FUNC (func_decl) = 1; + return func_decl; +} + +/** + start_block_helper_function - This is a light-weight version of start_function(). + It has removed all the fuss in the start_function(). + */ +void +start_block_helper_function (tree decl1) +{ + struct c_label_context_se *nstack_se; + struct c_label_context_vm *nstack_vm; + tree restype, resdecl; + + current_function_returns_value = 0; /* Assume, until we see it does. */ + current_function_returns_null = 0; + current_function_returns_abnormally = 0; + warn_about_return_type = 0; + c_switch_stack = NULL; + + nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se); + nstack_se->labels_def = NULL; + nstack_se->labels_used = NULL; + nstack_se->next = label_context_stack_se; + label_context_stack_se = nstack_se; + + nstack_vm = XOBNEW (&parser_obstack, struct c_label_context_vm); + nstack_vm->labels_def = NULL; + nstack_vm->labels_used = NULL; + nstack_vm->scope = 0; + nstack_vm->next = label_context_stack_vm; + label_context_stack_vm = nstack_vm; + + /* Indicate no valid break/continue context by setting these variables + to some non-null, non-label value. We'll notice and emit the proper + error message in c_finish_bc_stmt. */ + c_break_label = c_cont_label = size_zero_node; + + announce_function (decl1); + + /* Make the init_value nonzero so pushdecl knows this is not tentative. + error_mark_node is replaced below (in pop_scope) with the BLOCK. */ + DECL_INITIAL (decl1) = error_mark_node; + + current_function_prototype_locus = UNKNOWN_LOCATION; + current_function_prototype_built_in = false; + current_function_prototype_arg_types = NULL_TREE; + + /* This function exists in static storage. + (This does not mean `static' in the C sense!) */ + TREE_STATIC (decl1) = 1; + /* A helper function is not global */ + TREE_PUBLIC (decl1) = 0; + + /* This is the earliest point at which we might know the assembler + name of the function. Thus, if it's set before this, die horribly. */ + gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1)); + current_function_decl = pushdecl (decl1); + + push_scope (); + declare_parm_level (); + + restype = TREE_TYPE (TREE_TYPE (current_function_decl)); + resdecl = build_decl (RESULT_DECL, NULL_TREE, restype); + DECL_ARTIFICIAL (resdecl) = 1; + DECL_IGNORED_P (resdecl) = 1; + DECL_RESULT (current_function_decl) = resdecl; + + start_fname_decls (); +} + +/** + declare_block_prologue_local_vars - utility routine to do the actual + declaration and initialization for each referecned block variable. +*/ +static void +declare_block_prologue_local_vars (tree self_parm, tree component, + tree stmt) +{ + tree decl, block_component; + tree_stmt_iterator i; + tree decl_stmt; + + decl = component; + block_component = build_component_ref (build_indirect_ref (self_parm, "->"), + DECL_NAME (component)); + gcc_assert (block_component); + DECL_EXTERNAL (decl) = 0; + TREE_STATIC (decl) = 0; + TREE_USED (decl) = 1; + DECL_CONTEXT (decl) = current_function_decl; + DECL_ARTIFICIAL (decl) = 1; + DECL_INITIAL (decl) = block_component; + /* Prepend a DECL_EXPR statement to the statement list. */ + i = tsi_start (stmt); + decl_stmt = build_stmt (DECL_EXPR, decl); + /* APPLE LOCAL Radar 5811961, Fix location of block prologue vars (C++ ch) */ + SET_EXPR_LOCATION (decl_stmt, DECL_SOURCE_LOCATION (decl)); + /* APPLE LOCAL begin radar 6163705, Blocks prologues */ + /* Give the prologue statements a line number of one before the beginning of + the function, to make them easily identifiable later. */ + EXPR_LINENO (decl_stmt) = DECL_SOURCE_LINE (decl) - 1; + /* APPLE LOCAL end radar 6163705, Blocks prologues */ + tsi_link_before (&i, decl_stmt, TSI_SAME_STMT); +} + +/** + block_build_prologue + - This routine builds the declarations for the + variables referenced in the block; as in: + int *y = .block_descriptor->y; + int x = .block_descriptor->x; + + The decl_expr declaration for each initialization is enterred at the + beginning of the helper function's statement-list which is passed + in block_impl->block_body. +*/ +void +block_build_prologue (struct block_sema_info *block_impl) +{ + tree chain; + /* APPLE LOCAL radar 6404979 */ + tree self_parm = lookup_name (get_identifier (".block_descriptor")); + gcc_assert (self_parm); + + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + declare_block_prologue_local_vars (self_parm, TREE_VALUE (chain), + block_impl->block_body); + + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + declare_block_prologue_local_vars (self_parm, TREE_VALUE (chain), + block_impl->block_body); +} +/* APPLE LOCAL end radar 5732232 - blocks (C++ ch) */ + /* Return a pointer to a structure for an empty list of declaration specifiers. */ @@ -8131,4 +9110,35 @@ c_write_global_declarations (void) ext_block = NULL; } +/* APPLE LOCAL begin radar 5741070 */ + +/* Given an IDENTIFIER tree for a class interface, find (if possible) and + return the record type for the class interface. */ + +tree +c_return_interface_record_type (tree typename) +{ + enum tree_code_class class; + enum tree_code code; + tree retval = NULL; + + if (typename == NULL) + return retval; + + code = TREE_CODE (typename); + class = TREE_CODE_CLASS (code); + + if (code != IDENTIFIER_NODE + || class != tcc_exceptional) + return retval; + + retval = I_TAG_DECL (typename); + + if (TREE_CODE (retval) != RECORD_TYPE) + retval = NULL; + + return retval; +} +/* APPLE LOCAL end radar 5741070 */ + #include "gt-c-decl.h" diff --git a/contrib/gcc/c-objc-common.h b/contrib/gcc/c-objc-common.h index 49f9ce428b16..a12704ae6bea 100644 --- a/contrib/gcc/c-objc-common.h +++ b/contrib/gcc/c-objc-common.h @@ -140,4 +140,10 @@ extern void c_initialize_diagnostics (diagnostic_context *); #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p +/* APPLE LOCAL begin radar 6353006 */ +#undef LANG_HOOKS_BUILD_GENERIC_BLOCK_STRUCT_TYPE +#define LANG_HOOKS_BUILD_GENERIC_BLOCK_STRUCT_TYPE \ +c_build_generic_block_struct_type +/* APPLE LOCAL end radar 6353006 */ + #endif /* GCC_C_OBJC_COMMON */ diff --git a/contrib/gcc/c-opts.c b/contrib/gcc/c-opts.c index 39abfb33006d..7d6b603a3721 100644 --- a/contrib/gcc/c-opts.c +++ b/contrib/gcc/c-opts.c @@ -1040,6 +1040,13 @@ c_common_post_options (const char **pfilename) if (flag_inline_functions) flag_inline_trees = 2; + /* APPLE LOCAL begin radar 5811887 - radar 6084601 */ + /* In all flavors of c99, except for ObjC/ObjC++, blocks are off by default + unless requested via -fblocks. */ + if (flag_blocks == -1 && flag_iso && !c_dialect_objc()) + flag_blocks = 0; + /* APPLE LOCAL end radar 5811887 - radar 6084601 */ + /* By default we use C99 inline semantics in GNU99 or C99 mode. C99 inline semantics are not supported in GNU89 or C89 mode. */ if (flag_gnu89_inline == -1) diff --git a/contrib/gcc/c-parser.c b/contrib/gcc/c-parser.c index a8c8a1ecb93d..a86c80ca9fb6 100644 --- a/contrib/gcc/c-parser.c +++ b/contrib/gcc/c-parser.c @@ -78,6 +78,17 @@ static int objc_need_raw_identifier = 0; objc_need_raw_identifier = VAL; \ } while (0) +/* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 d) */ +/* For checking property attribute keywords */ +static int objc_property_attr_context; +/* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 d) */ +/* APPLE LOCAL radar 3803157 - objc attribute (in 4.2 e) */ +static tree objc_method_attributes; +/* APPLE LOCAL begin C* language (in 4.2 f) */ +/* For checking for 'foreach' context. */ +static int objc_foreach_context; +/* APPLE LOCAL end C* language (in 4.2 f) */ + /* The reserved keyword table. */ struct resword { @@ -179,6 +190,14 @@ static const struct resword reswords[] = { "end", RID_AT_END, D_OBJC }, { "implementation", RID_AT_IMPLEMENTATION, D_OBJC }, { "interface", RID_AT_INTERFACE, D_OBJC }, + /* APPLE LOCAL begin C* language (in 4.2 j) */ + { "optional", RID_AT_OPTIONAL, D_OBJC }, + { "required", RID_AT_REQUIRED, D_OBJC }, + /* APPLE LOCAL end C* language (in 4.2 j) */ + /* APPLE LOCAL C* property (Radar 4436866) (in 4.2 k) */ + { "property", RID_AT_PROPERTY, D_OBJC }, + /* APPLE LOCAL radar 4564694 */ + { "package", RID_AT_PACKAGE, D_OBJC }, { "private", RID_AT_PRIVATE, D_OBJC }, { "protected", RID_AT_PROTECTED, D_OBJC }, { "protocol", RID_AT_PROTOCOL, D_OBJC }, @@ -197,6 +216,14 @@ static const struct resword reswords[] = { "inout", RID_INOUT, D_OBJC }, { "oneway", RID_ONEWAY, D_OBJC }, { "out", RID_OUT, D_OBJC }, + /* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 l) */ + /* These are recognized inside a property attribute list */ + { "readonly", RID_READONLY, D_OBJC }, + { "getter", RID_GETTER, D_OBJC }, + { "setter", RID_SETTER, D_OBJC }, + /* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 l) */ + /* APPLE LOCAL radar 4947014 - objc atomic property */ + { "nonatomic", RID_NONATOMIC, D_OBJC }, }; #define N_reswords (sizeof reswords / sizeof (struct resword)) @@ -325,11 +352,13 @@ typedef struct c_parser GTY(()) static GTY (()) c_parser *the_parser; +/* APPLE LOCAL C* language (in 4.2 ae) */ +static c_token * c_parser_peek_2nd_token (c_parser *); /* Read in and lex a single token, storing it in *TOKEN. */ static void -c_lex_one_token (c_token *token) +c_lex_one_token (c_token *token, c_parser *parser) { timevar_push (TV_LEX); @@ -363,6 +392,27 @@ c_lex_one_token (c_token *token) token->keyword = rid_code; break; } + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + else if (objc_foreach_context && rid_code == RID_IN) + { + /* This is dangerous, we assume we don't need 3 input tokens look ahead. */ + c_token *tk = c_parser_peek_2nd_token (parser); + if (tk->type == CPP_NAME + || tk->type == CPP_OPEN_PAREN + || tk->type == CPP_MULT + || tk->type == CPP_PLUS + || tk->type == CPP_PLUS_PLUS + || tk->type == CPP_MINUS + || tk->type == CPP_MINUS_MINUS + /* APPLE LOCAL radar 4529200 (in 4.2 af) */ + || tk->type == CPP_OPEN_SQUARE) + { + token->type = CPP_KEYWORD; + token->keyword = rid_code; + break; + } + } + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ } else { @@ -433,8 +483,11 @@ c_parser_peek_token (c_parser *parser) { if (parser->tokens_avail == 0) { - c_lex_one_token (&parser->tokens[0]); + /* APPLE LOCAL begin switch these two */ parser->tokens_avail = 1; + /* APPLE LOCAL C* language (in 4.2 ae) */ + c_lex_one_token (&parser->tokens[0], parser); + /* APPLE LOCAL end switch these two */ } return &parser->tokens[0]; } @@ -609,7 +662,13 @@ static inline bool c_parser_next_token_starts_declspecs (c_parser *parser) { c_token *token = c_parser_peek_token (parser); - return c_token_starts_declspecs (token); + /* APPLE LOCAL begin radar 5277239 */ + /* Yes, we can have CLASS.method to mean property-style dot-syntax + notation to call a class method (equiv to [CLASS meth]). */ + return c_token_starts_declspecs (token) + && (token->id_kind != C_ID_CLASSNAME + || c_parser_peek_2nd_token (parser)->type != CPP_DOT); + /* APPLE LOCAL end radar 5277239 */ } /* Return a pointer to the next-but-one token from PARSER, reading it @@ -623,8 +682,11 @@ c_parser_peek_2nd_token (c_parser *parser) gcc_assert (parser->tokens_avail == 1); gcc_assert (parser->tokens[0].type != CPP_EOF); gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL); - c_lex_one_token (&parser->tokens[1]); + /* APPLE LOCAL begin switch these two */ parser->tokens_avail = 2; + /* APPLE LOCAL C* language (in 4.2 ae) */ + c_lex_one_token (&parser->tokens[1], parser); + /* APPLE LOCAL end switch these two */ return &parser->tokens[1]; } @@ -965,6 +1027,10 @@ typedef enum c_dtr_syn { C_DTR_NORMAL, /* An abstract declarator (maybe empty). */ C_DTR_ABSTRACT, + /* APPLE LOCAL begin blocks 6339747 */ + /* A block declarator (maybe empty). */ + C_DTR_BLOCK, + /* APPLE LOCAL end blocks 6339747 */ /* A parameter declarator: may be either, but after a type name does not redeclare a typedef name as an identifier if it can alternatively be interpreted as a typedef name; see DR#009, @@ -980,7 +1046,8 @@ typedef enum c_dtr_syn { static void c_parser_external_declaration (c_parser *); static void c_parser_asm_definition (c_parser *); -static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool); +/* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ +static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool, tree*); static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool, bool); static struct c_typespec c_parser_enum_specifier (c_parser *); @@ -1015,6 +1082,9 @@ static void c_parser_while_statement (c_parser *); static void c_parser_do_statement (c_parser *); static void c_parser_for_statement (c_parser *); static tree c_parser_asm_statement (c_parser *); +/* APPLE LOCAL begin radar 5732232 - blocks (C++ ca) */ +static tree c_parser_block_literal_expr (c_parser *); +/* APPLE LOCAL end radar 5732232 - blocks (C++ ca) */ static tree c_parser_asm_operands (c_parser *, bool); static tree c_parser_asm_clobbers (c_parser *); static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *); @@ -1043,14 +1113,19 @@ static bool c_parser_pragma (c_parser *, enum pragma_context); /* These Objective-C parser functions are only ever called when compiling Objective-C. */ -static void c_parser_objc_class_definition (c_parser *); +/* APPLE LOCAL radar 4548636 - class attributes. */ +static void c_parser_objc_class_definition (c_parser *, tree); static void c_parser_objc_class_instance_variables (c_parser *); static void c_parser_objc_class_declaration (c_parser *); static void c_parser_objc_alias_declaration (c_parser *); -static void c_parser_objc_protocol_definition (c_parser *); +/* APPLE LOCAL radar 4947311 - protocol attributes */ +static void c_parser_objc_protocol_definition (c_parser *, tree); static enum tree_code c_parser_objc_method_type (c_parser *); static void c_parser_objc_method_definition (c_parser *); -static void c_parser_objc_methodprotolist (c_parser *); +/* APPLE LOCAL C* property (Radar 4436866) (in 4.2 b) */ +static void c_parser_objc_interfacedecllist (c_parser *); +/* APPLE LOCAL C* property (Radar 4436866) (in 4.2 x) */ +static void c_parser_objc_property_declaration (c_parser *); static void c_parser_objc_methodproto (c_parser *); static tree c_parser_objc_method_decl (c_parser *); static tree c_parser_objc_type_name (c_parser *); @@ -1144,7 +1219,8 @@ c_parser_external_declaration (c_parser *parser) case RID_AT_INTERFACE: case RID_AT_IMPLEMENTATION: gcc_assert (c_dialect_objc ()); - c_parser_objc_class_definition (parser); + /* APPLE LOCAL radar 4548636 - class attributes. */ + c_parser_objc_class_definition (parser, NULL_TREE); break; case RID_AT_CLASS: gcc_assert (c_dialect_objc ()); @@ -1156,8 +1232,15 @@ c_parser_external_declaration (c_parser *parser) break; case RID_AT_PROTOCOL: gcc_assert (c_dialect_objc ()); - c_parser_objc_protocol_definition (parser); + /* APPLE LOCAL begin radar 4947311 - protocol attributes */ + c_parser_objc_protocol_definition (parser, NULL_TREE); break; + /* APPLE LOCAL end radar 4947311 - protocol attributes */ + /* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 x) */ + case RID_AT_PROPERTY: + c_parser_objc_property_declaration (parser); + break; + /* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 x) */ case RID_AT_END: gcc_assert (c_dialect_objc ()); c_parser_consume_token (parser); @@ -1189,7 +1272,8 @@ c_parser_external_declaration (c_parser *parser) /* A declaration or a function definition. We can only tell which after parsing the declaration specifiers, if any, and the first declarator. */ - c_parser_declaration_or_fndef (parser, true, true, false, true); + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, true, true, false, true, NULL); break; } } @@ -1254,7 +1338,8 @@ c_parser_external_declaration (c_parser *parser) static void c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, - bool nested, bool start_attr_ok) + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + bool nested, bool start_attr_ok, tree *foreach_elem) { struct c_declspecs *specs; tree prefix_attrs; @@ -1287,6 +1372,29 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, c_parser_consume_token (parser); return; } + /* APPLE LOCAL begin radar 4548636 - class attributes. */ + else if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE) + || c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION)) + { + gcc_assert (c_dialect_objc ()); + if (!specs->declspecs_seen_p || specs->attrs == NULL_TREE + || specs->type_seen_p || specs->non_sc_seen_p) + c_parser_error (parser, "no type or storage class may be specified here"); + c_parser_objc_class_definition (parser, specs->attrs); + return; + } + /* APPLE LOCAL end radar 4548636 - class attributes. */ + /* APPLE LOCAL begin radar 4947311 - protocol attributes */ + else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL)) + { + gcc_assert (c_dialect_objc ()); + if (!specs->declspecs_seen_p || specs->attrs == NULL_TREE + || specs->type_seen_p || specs->non_sc_seen_p) + c_parser_error (parser, "no type or storage class may be specified here"); + c_parser_objc_protocol_definition (parser, specs->attrs); + return; + } + /* APPLE LOCAL end radar 4947311 - protocol attributes */ pending_xref_error (); prefix_attrs = specs->attrs; all_prefix_attrs = prefix_attrs; @@ -1311,6 +1419,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, || c_parser_next_token_is (parser, CPP_COMMA) || c_parser_next_token_is (parser, CPP_SEMICOLON) || c_parser_next_token_is_keyword (parser, RID_ASM) + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + || c_parser_next_token_is_keyword (parser, RID_IN) || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) { tree asm_name = NULL_TREE; @@ -1327,6 +1437,18 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, asm_name = c_parser_simple_asm_expr (parser); if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) postfix_attrs = c_parser_attributes (parser); + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + if (c_parser_next_token_is_keyword (parser, RID_IN)) + { + gcc_assert (foreach_elem); + *foreach_elem = start_decl (declarator, specs, true, + chainon (postfix_attrs, all_prefix_attrs)); + if (!*foreach_elem) + *foreach_elem = error_mark_node; + start_init (*foreach_elem, asm_name, global_bindings_p ()); + return; + } + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ if (c_parser_next_token_is (parser, CPP_EQ)) { tree d; @@ -1387,8 +1509,17 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, /* Function definition (nested or otherwise). */ if (nested) { - if (pedantic) + /* APPLE LOCAL begin radar 5985368 */ + if (declarator->declarator && declarator->declarator->kind == cdk_block_pointer) + error ("bad definition of a block"); + else if (pedantic) + /* APPLE LOCAL end radar 5985368 */ pedwarn ("ISO C forbids nested functions"); + /* APPLE LOCAL begin nested functions 4258406 4357979 (in 4.2 m) */ + else if (flag_nested_functions == 0) + error ("nested functions are disabled, use -fnested-functions to re-enable"); + /* APPLE LOCAL end nested functions 4258406 4357979 (in 4.2 m) */ + push_function_context (); } if (!start_function (specs, declarator, all_prefix_attrs)) @@ -1416,7 +1547,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, function definitions either. */ while (c_parser_next_token_is_not (parser, CPP_EOF) && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) - c_parser_declaration_or_fndef (parser, false, false, true, false); + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, false, false, true, false, NULL); DECL_SOURCE_LOCATION (current_function_decl) = c_parser_peek_token (parser)->location; store_parm_decls (); @@ -1438,6 +1570,23 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, } } +static tree +finish_parse_foreach_header (c_parser *parser, tree foreach_elem_selector) +{ + tree res; + int save_flag_isoc99 = flag_isoc99; + gcc_assert (foreach_elem_selector); + /* Consume 'in' keyword */ + c_parser_consume_token (parser); + res = build_tree_list (foreach_elem_selector, c_parser_initializer (parser).value); + finish_init (); + flag_isoc99 = 1; + check_for_loop_decls (); + flag_isoc99 = save_flag_isoc99; + return res; +} +/* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ + /* Parse an asm-definition (asm() outside a function body). This is a GNU extension. @@ -2251,6 +2400,18 @@ c_parser_typeof_specifier (c_parser *parser) parameter-list ; parameter-forward-declarations parameter-list ; + APPLE LOCAL begin blocks 6339747 + block-declarator: + pointer + pointer[opt] direct-block-declarator + + direct-block-declarator: + ( attributes[opt] block-declarator ) + direct-block-declarator[opt] array-declarator + direct-block-declarator[opt] + ( parameter-type-list[opt] ) [opt] + APPLE LOCAL end blocks 6339747 + The uses of attributes shown above are GNU extensions. Some forms of array declarator are not included in C99 in the @@ -2277,6 +2438,20 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, else return make_pointer_declarator (quals_attrs, inner); } + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cc) */ + else if (flag_blocks && c_parser_next_token_is (parser, CPP_XOR)) { + struct c_declspecs *quals_attrs = build_null_declspecs (); + struct c_declarator *inner; + c_parser_consume_token (parser); + c_parser_declspecs (parser, quals_attrs, false, false, true); + inner = c_parser_declarator (parser, type_seen_p, kind, seen_id); + if (inner == NULL) + return NULL; + else + /* APPLE LOCAL radar 5814025 (C++ cc) */ + return make_block_pointer_declarator (quals_attrs, inner); + } + /* APPLE LOCAL end radar 5732232 - blocks (C++ cc) */ /* Now we have a direct declarator, direct abstract declarator or nothing (which counts as a direct abstract declarator here). */ return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id); @@ -2323,10 +2498,14 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, ??? Also following the old parser, typedef names may be redeclared in declarators, but not Objective-C class names. */ - if (kind != C_DTR_ABSTRACT + /* APPLE LOCAL blocks 6339747 */ + if ((kind != C_DTR_ABSTRACT && kind != C_DTR_BLOCK) && c_parser_next_token_is (parser, CPP_NAME) && ((type_seen_p - && c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME) + /* APPLE LOCAL begin radar 4281748 */ + && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME + || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)) + /* APPLE LOCAL end radar 4281748 */ || c_parser_peek_token (parser)->id_kind == C_ID_ID)) { struct c_declarator *inner @@ -3379,6 +3558,8 @@ c_parser_compound_statement_nostart (c_parser *parser) { bool last_stmt = false; bool last_label = false; + /* APPLE LOCAL radar 5732232 - blocks (not in C++) */ + bool first_stmt = true; if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { c_parser_consume_token (parser); @@ -3389,30 +3570,30 @@ c_parser_compound_statement_nostart (c_parser *parser) /* Read zero or more forward-declarations for labels that nested functions can jump to. */ while (c_parser_next_token_is_keyword (parser, RID_LABEL)) - { - c_parser_consume_token (parser); - /* Any identifiers, including those declared as type names, - are OK here. */ - while (true) - { - tree label; - if (c_parser_next_token_is_not (parser, CPP_NAME)) { - c_parser_error (parser, "expected identifier"); - break; + c_parser_consume_token (parser); + /* Any identifiers, including those declared as type names, + are OK here. */ + while (true) + { + tree label; + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + break; } - label + label = declare_label (c_parser_peek_token (parser)->value); - C_DECLARED_LABEL_FLAG (label) = 1; - add_stmt (build_stmt (DECL_EXPR, label)); - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_COMMA)) + C_DECLARED_LABEL_FLAG (label) = 1; + add_stmt (build_stmt (DECL_EXPR, label)); c_parser_consume_token (parser); - else - break; - } - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + break; } + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + } /* ??? Locating this diagnostic on the token after the declarations end follows the old parser, but it might be better to locate it where the declarations start instead. */ @@ -3430,81 +3611,85 @@ c_parser_compound_statement_nostart (c_parser *parser) { location_t loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is_keyword (parser, RID_CASE) - || c_parser_next_token_is_keyword (parser, RID_DEFAULT) - || (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) - { - last_label = true; - last_stmt = false; - c_parser_label (parser); - } + || c_parser_next_token_is_keyword (parser, RID_DEFAULT) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + { + last_label = true; + last_stmt = false; + c_parser_label (parser); + } else if (!last_label - && c_parser_next_token_starts_declspecs (parser)) - { - last_label = false; - c_parser_declaration_or_fndef (parser, true, true, true, true); - if (last_stmt - && ((pedantic && !flag_isoc99) - || warn_declaration_after_statement)) - pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", - &loc); - last_stmt = false; - } - else if (!last_label - && c_parser_next_token_is_keyword (parser, RID_EXTENSION)) - { - /* __extension__ can start a declaration, but is also an - unary operator that can start an expression. Consume all - but the last of a possible series of __extension__ to - determine which. */ - while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD - && (c_parser_peek_2nd_token (parser)->keyword - == RID_EXTENSION)) - c_parser_consume_token (parser); - if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser))) - { - int ext; - ext = disable_extension_diagnostics (); - c_parser_consume_token (parser); - last_label = false; - c_parser_declaration_or_fndef (parser, true, true, true, true); - /* Following the old parser, __extension__ does not - disable this diagnostic. */ - restore_extension_diagnostics (ext); - if (last_stmt - && ((pedantic && !flag_isoc99) - || warn_declaration_after_statement)) + && c_parser_next_token_starts_declspecs (parser)) + { + last_label = false; + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, true, true, true, true, NULL); + if (last_stmt + && ((pedantic && !flag_isoc99) + || warn_declaration_after_statement)) pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", - &loc); - last_stmt = false; - } - else - goto statement; + &loc); + last_stmt = false; + } + else if (!last_label + && c_parser_next_token_is_keyword (parser, RID_EXTENSION)) + { + /* __extension__ can start a declaration, but is also an + unary operator that can start an expression. Consume all + but the last of a possible series of __extension__ to + determine which. */ + while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD + && (c_parser_peek_2nd_token (parser)->keyword + == RID_EXTENSION)) + c_parser_consume_token (parser); + if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser))) + { + int ext; + ext = disable_extension_diagnostics (); + c_parser_consume_token (parser); + last_label = false; + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, true, true, true, true, NULL); + /* Following the old parser, __extension__ does not + disable this diagnostic. */ + restore_extension_diagnostics (ext); + if (last_stmt + && ((pedantic && !flag_isoc99) + || warn_declaration_after_statement)) + pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", + &loc); + last_stmt = false; } + else + goto statement; + } else if (c_parser_next_token_is (parser, CPP_PRAGMA)) - { - /* External pragmas, and some omp pragmas, are not associated - with regular c code, and so are not to be considered statements - syntactically. This ensures that the user doesn't put them - places that would turn into syntax errors if the directive - were ignored. */ - if (c_parser_pragma (parser, pragma_compound)) - last_label = false, last_stmt = true; - } + { + /* External pragmas, and some omp pragmas, are not associated + with regular c code, and so are not to be considered statements + syntactically. This ensures that the user doesn't put them + places that would turn into syntax errors if the directive + were ignored. */ + if (c_parser_pragma (parser, pragma_compound)) + last_label = false, last_stmt = true; + } else if (c_parser_next_token_is (parser, CPP_EOF)) - { - c_parser_error (parser, "expected declaration or statement"); - return; - } + { + c_parser_error (parser, "expected declaration or statement"); + return; + } else - { - statement: - last_label = false; - last_stmt = true; - c_parser_statement_after_labels (parser); - } - + { + statement: + last_label = false; + last_stmt = true; + c_parser_statement_after_labels (parser); + } + parser->error = false; + /* APPLE LOCAL radar 5732232 - blocks (not in C++) */ + first_stmt = false; } if (last_label) error ("label at end of compound statement"); @@ -3720,6 +3905,10 @@ c_parser_statement_after_labels (c_parser *parser) c_parser_for_statement (parser); break; case RID_GOTO: + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cb) */ + if (cur_block) + error ("goto not allowed in block literal"); + /* APPLE LOCAL end radar 5732232 - blocks (C++ cb) */ c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -3817,8 +4006,20 @@ c_parser_statement_after_labels (c_parser *parser) (recursively) all of the component statements should already have line numbers assigned. ??? Can we discard no-op statements earlier? */ + /* APPLE LOCAL begin Radar 6144634 */ + /* Normal expr stmts, including modify exprs, get the location where + the statement began, i.e. 'loc'. Assignments of Blocks to Block + pointer variables get the location of the end of the Block definition, + i.e. 'input_location', which should already be set by this point. */ if (stmt && EXPR_P (stmt)) - SET_EXPR_LOCATION (stmt, loc); + { + if (TREE_CODE (stmt) == MODIFY_EXPR + && TREE_CODE (TREE_TYPE (TREE_OPERAND (stmt, 0))) == BLOCK_POINTER_TYPE) + SET_EXPR_LOCATION (stmt, input_location); + else + SET_EXPR_LOCATION (stmt, loc); + } + /* APPLE LOCAL end Radar 6144634 */ } /* Parse a parenthesized condition from an if, do or while statement. @@ -4048,6 +4249,8 @@ c_parser_for_statement (c_parser *parser) tree block, cond, incr, save_break, save_cont, body, attrs; /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ location_t loc; + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + bool foreach_p = false; gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR)); loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); @@ -4065,8 +4268,18 @@ c_parser_for_statement (c_parser *parser) } else if (c_parser_next_token_starts_declspecs (parser)) { - c_parser_declaration_or_fndef (parser, true, true, true, true); - check_for_loop_decls (); + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + cond = NULL_TREE; + c_parser_declaration_or_fndef (parser, true, true, true, true, &cond); + /* APPLE LOCAL radar 5925639 */ + if (c_parser_next_token_is_keyword (parser, RID_IN) && cond) + { + cond = finish_parse_foreach_header (parser, cond); + foreach_p = true; + } + else + check_for_loop_decls (); + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ } else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) { @@ -4083,9 +4296,19 @@ c_parser_for_statement (c_parser *parser) int ext; ext = disable_extension_diagnostics (); c_parser_consume_token (parser); - c_parser_declaration_or_fndef (parser, true, true, true, true); + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + cond = NULL_TREE; + c_parser_declaration_or_fndef (parser, true, true, true, true, &cond); restore_extension_diagnostics (ext); - check_for_loop_decls (); + /* APPLE LOCAL radar 5925639 */ + if (c_parser_next_token_is_keyword (parser, RID_IN) && cond) + { + cond = finish_parse_foreach_header (parser, cond); + foreach_p = true; + } + else + check_for_loop_decls (); + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ } else goto init_expr; @@ -4093,9 +4316,22 @@ c_parser_for_statement (c_parser *parser) else { init_expr: - c_finish_expr_stmt (c_parser_expression (parser).value); - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + cond = c_parser_expression (parser).value; + if (c_parser_next_token_is_keyword (parser, RID_IN)) + { + c_parser_consume_token (parser); /* IN */ + cond = build_tree_list (cond, c_parser_initializer (parser).value); + foreach_p = true; + } + else + { + c_finish_expr_stmt (cond); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + } } + objc_foreach_context = 0; + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ /* Parse the loop condition. */ loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) @@ -4103,6 +4339,10 @@ c_parser_for_statement (c_parser *parser) c_parser_consume_token (parser); cond = NULL_TREE; } + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + else if (foreach_p) + ; + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ else { tree ocond = c_parser_expression_conv (parser).value; @@ -4607,6 +4847,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) } while (0) gcc_assert (!after || c_dialect_objc ()); stack[0].expr = c_parser_cast_expression (parser, after); + /* APPLE LOCAL begin radar 4426814 */ + if (c_dialect_objc() && flag_objc_gc) + /* APPLE LOCAL radar 5276085 */ + stack[0].expr.value = objc_build_weak_reference_tree (stack[0].expr.value); + /* APPLE LOCAL end radar 4426814 */ stack[0].prec = PREC_NONE; sp = 0; while (true) @@ -4718,6 +4963,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) } sp++; stack[sp].expr = c_parser_cast_expression (parser, NULL); + /* APPLE LOCAL begin radar 4426814 */ + if (c_dialect_objc() && flag_objc_gc) + /* APPLE LOCAL radar 5276085 */ + stack[sp].expr.value = objc_build_weak_reference_tree (stack[sp].expr.value); + /* APPLE LOCAL end radar 4426814 */ stack[sp].prec = oprec; stack[sp].op = ocode; } @@ -5054,6 +5304,8 @@ c_parser_alignof_expression (c_parser *parser) assignment-expression , assignment-expression ) __builtin_types_compatible_p ( type-name , type-name ) + APPLE LOCAL blocks (C++ cf) + block-literal-expr offsetof-member-designator: identifier @@ -5098,6 +5350,21 @@ c_parser_postfix_expression (c_parser *parser) c_parser_consume_token (parser); break; case CPP_NAME: + /* APPLE LOCAL begin radar 5277239 */ + if (c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME + && c_parser_peek_2nd_token (parser)->type == CPP_DOT) + { + /* CLASS.class_method expression. */ + tree receiver, component; + receiver = c_parser_objc_receiver (parser); + /* consume '.' operator */ + c_parser_consume_token (parser); + component = c_parser_objc_message_args (parser); + expr.value = objc_build_property_reference_expr (receiver, component); + expr.original_code = ERROR_MARK; + break; + } + /* APPLE LOCAL end radar 5277239 */ if (c_parser_peek_token (parser)->id_kind != C_ID_ID) { c_parser_error (parser, "expected expression"); @@ -5112,6 +5379,34 @@ c_parser_postfix_expression (c_parser *parser) expr.value = build_external_ref (id, (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN), loc); + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cd) */ + /* If a variabled declared as referenced variable, using |...| syntax, + is used in the block, it has to be derefrenced because this + variable holds address of the outside variable referenced in. */ + + /* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ cd) */ + if (TREE_CODE (expr.value) == VAR_DECL) + { + if (BLOCK_DECL_BYREF (expr.value)) + { + tree orig_decl = expr.value; + expr.value = build_indirect_ref (expr.value, "unary *"); + if (COPYABLE_BYREF_LOCAL_VAR (orig_decl)) { + /* What we have is an expression which is of type + struct __Block_byref_X. Must get to the value of the variable + embedded in this structure. It is at: + __Block_byref_X.__forwarding->x */ + expr.value = build_byref_local_var_access (expr.value, + DECL_NAME (orig_decl)); + } + } + else if (COPYABLE_BYREF_LOCAL_VAR (expr.value)) + expr.value = build_byref_local_var_access (expr.value, + DECL_NAME (expr.value)); + } + /* APPLE LOCAL end radar 5932809 - copyable byref blocks */ + + /* APPLE LOCAL end radar 5732232 - blocks (C++ cd) */ expr.original_code = ERROR_MARK; } break; @@ -5447,6 +5742,18 @@ c_parser_postfix_expression (c_parser *parser) break; } break; + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cf) */ + case CPP_XOR: + if (flag_blocks) { + expr.value = c_parser_block_literal_expr (parser); + expr.original_code = ERROR_MARK; + break; + } + c_parser_error (parser, "expected expression"); + expr.value = error_mark_node; + expr.original_code = ERROR_MARK; + break; + /* APPLE LOCAL end radar 5732232 - blocks (C++ cf) */ case CPP_OPEN_SQUARE: if (c_dialect_objc ()) { @@ -5680,7 +5987,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p) objc-protocol-refs and objc-class-instance-variables are omitted. */ static void -c_parser_objc_class_definition (c_parser *parser) +/* APPLE LOCAL radar 4548636 - class attributes. */ +c_parser_objc_class_definition (c_parser *parser, tree prefix_attrs) { bool iface_p; tree id1; @@ -5688,40 +5996,60 @@ c_parser_objc_class_definition (c_parser *parser) if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE)) iface_p = true; else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION)) - iface_p = false; + /* APPLE LOCAL begin radar 4548636 - class attributes. */ + { + if (prefix_attrs) + { + error ("attributes may not be specified on an implementation"); + prefix_attrs = NULL_TREE; + } + iface_p = false; + } + /* APPLE LOCAL end radar 4548636 - class attributes. */ else gcc_unreachable (); c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) { - c_parser_error (parser, "expected identifier"); - return; - } - id1 = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) - { - tree id2; + /* APPLE LOCAL radar 4965989 */ + tree id2 = NULL_TREE; tree proto = NULL_TREE; c_parser_consume_token (parser); - if (c_parser_next_token_is_not (parser, CPP_NAME)) + /* APPLE LOCAL begin radar 4965989 */ + if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return; + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + return; + } + id2 = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); } - id2 = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); + /* APPLE LOCAL end radar 4965989 */ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (!iface_p) { + /* APPLE LOCAL begin radar 4965989 */ + if (id2 == NULL_TREE) + { + error ("cannot implement anonymous category"); + return; + } + /* APPLE LOCAL end radar 4965989 */ objc_start_category_implementation (id1, id2); return; } if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); + /* APPLE LOCAL begin radar 4548636 - class attributes. */ + if (prefix_attrs) + error ("attributes may not be specified on a category"); + /* APPLE LOCAL end radar 4548636 - class attributes. */ objc_start_category_interface (id1, id2, proto); - c_parser_objc_methodprotolist (parser); + /* APPLE LOCAL C* property (Radar 4436866) (in 4.2 q) */ + c_parser_objc_interfacedecllist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); objc_finish_interface (); return; @@ -5744,7 +6072,8 @@ c_parser_objc_class_definition (c_parser *parser) tree proto = NULL_TREE; if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); - objc_start_class_interface (id1, superclass, proto); + /* APPLE LOCAL radar 4548636 - class attributes. */ + objc_start_class_interface (id1, superclass, proto, prefix_attrs); } else objc_start_class_implementation (id1, superclass); @@ -5753,7 +6082,8 @@ c_parser_objc_class_definition (c_parser *parser) if (iface_p) { objc_continue_interface (); - c_parser_objc_methodprotolist (parser); + /* APPLE LOCAL C* property (Radar 4436866) (in 4.2 q) */ + c_parser_objc_interfacedecllist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); objc_finish_interface (); } @@ -5764,6 +6094,129 @@ c_parser_objc_class_definition (c_parser *parser) } } +/* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 s) */ +static tree +c_parser_objc_eq_identifier (c_parser *parser) +{ + tree id; + if (c_parser_next_token_is_not (parser, CPP_EQ)) + { + c_parser_error (parser, "expected %<=%>"); + return NULL_TREE; + } + /* Consume '=' */ + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + return NULL_TREE; + } + id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + return id; +} + +/* Parse obj-property-attribute. +*/ +static void +c_parser_objc_property_attribute (c_parser *parser) +{ + tree id; + if (c_parser_peek_token (parser)->type != CPP_KEYWORD) + { + c_parser_error (parser, "expected a property attribute"); + c_parser_consume_token (parser); + return; + } + switch (c_parser_peek_token (parser)->keyword) + { + case RID_READONLY: + c_parser_consume_token (parser); + objc_set_property_attr (1, NULL_TREE); + break; + case RID_GETTER: + c_parser_consume_token (parser); + id = c_parser_objc_eq_identifier (parser); + if (id) + objc_set_property_attr (2, id); + break; + case RID_SETTER: + c_parser_consume_token (parser); + id = c_parser_objc_eq_identifier (parser); + if (id) + objc_set_property_attr (3, id); + /* Consume the ':' which must always follow the setter name. */ + if (c_parser_next_token_is (parser, CPP_COLON)) + c_parser_consume_token (parser); + break; + /* APPLE LOCAL begin radar 4947014 - objc atomic property */ + case RID_NONATOMIC: + c_parser_consume_token (parser); + objc_set_property_attr (13, NULL_TREE); + break; + /* APPLE LOCAL end radar 4947014 - objc atomic property */ + default: + c_parser_error (parser, "expected a property attribute"); + c_parser_consume_token (parser); + } +} + +static void +c_parser_objc_property_attrlist (c_parser *parser) +{ + while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN) + && c_parser_next_token_is_not (parser, CPP_EOF)) + { + c_parser_objc_property_attribute (parser); + /* APPLE LOCAL begin radar 6302949 */ + if (c_parser_next_token_is_not (parser, CPP_COMMA) + && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN) + && c_parser_next_token_is_not (parser, CPP_EOF)) + warning (0, "property attributes must be separated by a comma"); + /* APPLE LOCAL end radar 6302949 */ + if (c_parser_next_token_is (parser, CPP_COMMA) + || c_parser_next_token_is (parser, CPP_NAME) /* error */) + c_parser_consume_token (parser); + } +} + +static void +c_parser_objc_property_attr_decl (c_parser *parser) +{ + if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + return; + c_parser_consume_token (parser); + c_parser_objc_property_attrlist (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); +} + +static tree +c_parser_component_decl (c_parser *parser) +{ + tree decl = c_parser_struct_declaration (parser); + return decl; +} + +static void +c_parser_objc_property_declaration (c_parser *parser) +{ + tree prop; + c_parser_require_keyword (parser, RID_AT_PROPERTY, "expected %<@property%>"); + objc_property_attr_context = 1; + objc_set_property_attr (0, NULL_TREE); + c_parser_objc_property_attr_decl (parser); + objc_property_attr_context = 0; + prop = c_parser_component_decl (parser); + /* Comma-separated properties are chained together in + reverse order; add them one by one. */ + prop = nreverse (prop); + + for (; prop; prop = TREE_CHAIN (prop)) + objc_add_property_variable (copy_node (prop)); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); +} +/* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 s) */ + /* Parse objc-class-instance-variables. objc-class-instance-variables: @@ -5827,6 +6280,14 @@ c_parser_objc_class_instance_variables (c_parser *parser) objc_set_visibility (1); continue; } + /* APPLE LOCAL begin radar 4564694 */ + else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE)) + { + c_parser_consume_token (parser); + objc_set_visibility (3); + continue; + } + /* APPLE LOCAL end radar 4564694 */ else if (c_parser_next_token_is (parser, CPP_PRAGMA)) { c_parser_pragma (parser, pragma_external); @@ -5924,7 +6385,8 @@ c_parser_objc_alias_declaration (c_parser *parser) omitted. */ static void -c_parser_objc_protocol_definition (c_parser *parser) +/* APPLE LOCAL radar 4947311 - protocol attributes */ +c_parser_objc_protocol_definition (c_parser *parser, tree attributes) { gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL)); c_parser_consume_token (parser); @@ -5956,7 +6418,8 @@ c_parser_objc_protocol_definition (c_parser *parser) break; } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); - objc_declare_protocols (list); + /* APPLE LOCAL radar 4947311 - protocol attributes */ + objc_declare_protocols (list, attributes); } else { @@ -5966,8 +6429,10 @@ c_parser_objc_protocol_definition (c_parser *parser) if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); objc_pq_context = 1; - objc_start_protocol (id, proto); - c_parser_objc_methodprotolist (parser); + /* APPLE LOCAL radar 4947311 - protocol attributes */ + objc_start_protocol (id, proto, attributes); + /* APPLE LOCAL C* property (Radar 4436866) (in 4.2 r) */ + c_parser_objc_interfacedecllist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); objc_pq_context = 0; objc_finish_interface (); @@ -6023,11 +6488,28 @@ c_parser_objc_method_definition (c_parser *parser) return; } objc_pq_context = 0; - objc_start_method_definition (decl); + /* APPLE LOCAL begin radar 3803157 - objc attribute (in 4.2 a) */ + objc_start_method_definition (decl, objc_method_attributes); + objc_method_attributes = NULL_TREE; + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 a) */ add_stmt (c_parser_compound_statement (parser)); objc_finish_method_definition (current_function_decl); } +/* APPLE LOCAL begin C* language (in 4.2 w) */ +/* True iff the gioven TOKEN starts a methodproto. */ + +static bool +c_token_starts_methodproto (c_token *token) +{ + return token->type == CPP_PLUS + || token->type == CPP_MINUS + || (token->type == CPP_KEYWORD + && (token->keyword == RID_AT_REQUIRED + || token->keyword == RID_AT_OPTIONAL)); +} +/* APPLE LOCAL end C* language (in 4.2 w) */ + /* Parse an objc-methodprotolist. objc-methodprotolist: @@ -6043,10 +6525,29 @@ c_parser_objc_method_definition (c_parser *parser) function. */ static void -c_parser_objc_methodprotolist (c_parser *parser) +/* APPLE LOCAL C* property (Radar 4436866) (in 4.2 b) */ +c_parser_objc_interfacedecllist (c_parser *parser) { while (true) { + /* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 b) */ + c_token *token; + token = c_parser_peek_token (parser); + if (token->type == CPP_KEYWORD + && token->keyword == RID_AT_PROPERTY) + { + c_parser_objc_property_declaration (parser); + continue; + } + /* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 b) */ + /* APPLE LOCAL begin C* language (in 4.2 w) */ + if (c_token_starts_methodproto (token)) + { + c_parser_objc_methodproto (parser); + continue; + } + /* APPLE LOCAL end C* language (in 4.2 w) */ + /* The list is terminated by @end. */ switch (c_parser_peek_token (parser)->type) { @@ -6055,10 +6556,9 @@ c_parser_objc_methodprotolist (c_parser *parser) pedwarn ("ISO C does not allow extra %<;%> outside of a function"); c_parser_consume_token (parser); break; - case CPP_PLUS: - case CPP_MINUS: - c_parser_objc_methodproto (parser); - break; + /* APPLE LOCAL begin C* language (in 4.2 w) */ + /* CPP_PLUS and CPP_MINUS deleted */ + /* APPLE LOCAL end C* language (in 4.2 w) */ case CPP_PRAGMA: c_parser_pragma (parser, pragma_external); break; @@ -6067,7 +6567,8 @@ c_parser_objc_methodprotolist (c_parser *parser) default: if (c_parser_next_token_is_keyword (parser, RID_AT_END)) return; - c_parser_declaration_or_fndef (parser, false, true, false, true); + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, false, true, false, true, NULL); break; } } @@ -6082,15 +6583,35 @@ c_parser_objc_methodprotolist (c_parser *parser) static void c_parser_objc_methodproto (c_parser *parser) { - enum tree_code type = c_parser_objc_method_type (parser); + /* APPLE LOCAL C* language */ + enum tree_code type; tree decl; + /* APPLE LOCAL begin C* language */ + if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED)) + { + objc_set_method_opt (0); + c_parser_consume_token (parser); + return; + } + if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL)) + { + objc_set_method_opt (1); + c_parser_consume_token (parser); + return; + } + /* APPLE LOCAL begin C* language */ + /* APPLE LOCAL C* language */ + type = c_parser_objc_method_type (parser); objc_set_method_type (type); /* Remember protocol qualifiers in prototypes. */ objc_pq_context = 1; decl = c_parser_objc_method_decl (parser); /* Forget protocol qualifiers here. */ objc_pq_context = 0; - objc_add_method_declaration (decl); + /* APPLE LOCAL begin radar 3803157 - objc attribute (in 4.2 c) */ + objc_add_method_declaration (decl, objc_method_attributes); + objc_method_attributes = NULL_TREE; + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 c) */ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } @@ -6148,6 +6669,8 @@ c_parser_objc_method_decl (c_parser *parser) tree list = NULL_TREE; while (true) { + /* APPLE LOCAL radar 4157812 */ + tree attr = NULL_TREE; tree atype = NULL_TREE, id, keyworddecl; if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) break; @@ -6158,6 +6681,10 @@ c_parser_objc_method_decl (c_parser *parser) c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } + /* APPLE LOCAL begin radar 4157812 */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + attr = c_parser_attributes (parser); + /* APPLE LOCAL end radar 4157812 */ if (c_parser_next_token_is_not (parser, CPP_NAME)) { c_parser_error (parser, "expected identifier"); @@ -6165,12 +6692,17 @@ c_parser_objc_method_decl (c_parser *parser) } id = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); - keyworddecl = objc_build_keyword_decl (tsel, atype, id); + /* APPLE LOCAL radar 4157812 */ + keyworddecl = objc_build_keyword_decl (tsel, atype, id, attr); list = chainon (list, keyworddecl); tsel = c_parser_objc_selector (parser); if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON)) break; } + /* APPLE LOCAL begin radar 3803157 - objc attribute (in 4.2 y) */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + objc_method_attributes = c_parser_attributes (parser); + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 y) */ /* Parse the optional parameter list. Optional Objective-C method parameters follow the C syntax, and may include '...' to denote a variable number of arguments. */ @@ -6183,6 +6715,12 @@ c_parser_objc_method_decl (c_parser *parser) { ellipsis = true; c_parser_consume_token (parser); + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 y) */ + if (objc_method_attributes) + error ("method attributes must be specified at the end only"); + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + objc_method_attributes = c_parser_attributes (parser); + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 y) */ break; } parm = c_parser_parameter_declaration (parser, NULL_TREE); @@ -6193,6 +6731,21 @@ c_parser_objc_method_decl (c_parser *parser) } sel = list; } + /* APPLE LOCAL begin radar 3803157 - objc attribute (in 4.2 y) */ + else + { + gcc_assert (objc_method_attributes == NULL_TREE); + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + objc_method_attributes = c_parser_attributes (parser); + } + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 y) */ + /* APPLE LOCAL begin radar 4157812 */ + if (sel == NULL) + { + c_parser_error (parser, "objective-c method declaration is expected"); + return error_mark_node; + } + /* APPLE LOCAL end radar 4157812 */ return objc_build_method_signature (type, sel, parms, ellipsis); } @@ -6227,7 +6780,8 @@ c_parser_objc_type_name (c_parser *parser) || token->keyword == RID_BYREF || token->keyword == RID_ONEWAY)) { - quals = chainon (quals, build_tree_list (NULL_TREE, token->value)); + /* APPLE LOCAL radar 4301047 (in 4.2 z) */ + quals = chainon (build_tree_list (NULL_TREE, token->value), quals); c_parser_consume_token (parser); } else @@ -6301,14 +6855,26 @@ c_parser_objc_try_catch_statement (c_parser *parser) c_parser_consume_token (parser); if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) break; - parm = c_parser_parameter_declaration (parser, NULL_TREE); - if (parm == NULL) + /* APPLE LOCAL begin radar 2848255 */ + if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - break; + /* @catch (...) */ + c_parser_consume_token (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + objc_begin_catch_clause (NULL_TREE); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); - objc_begin_catch_clause (grokparm (parm)); + else + { + parm = c_parser_parameter_declaration (parser, NULL_TREE); + if (parm == NULL) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + break; + } + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + objc_begin_catch_clause (grokparm (parm)); + } + /* APPLE LOCAL end radar 2848255 */ if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) c_parser_compound_statement_nostart (parser); objc_finish_catch_clause (); @@ -6325,6 +6891,26 @@ c_parser_objc_try_catch_statement (c_parser *parser) objc_finish_try_stmt (); } +/* APPLE LOCAL begin radar 5982990 */ +/* This routine is called from c_parser_objc_synchronized_statement + and is identical to c_parser_compound_statement with + the addition of volatizing local variables seen in the scope + of @synchroniz block. +*/ +static tree +c_parser_objc_synch_compound_statement (c_parser *parser) +{ + tree stmt; + if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + return error_mark_node; + stmt = c_begin_compound_stmt (true); + c_parser_compound_statement_nostart (parser); + if (flag_objc_sjlj_exceptions) + objc_mark_locals_volatile (NULL); + return c_end_compound_stmt (stmt, true); +} +/* APPLE LOCAL end radar 5982990 */ + /* Parse an objc-synchronized-statement. objc-synchronized-statement: @@ -6346,7 +6932,8 @@ c_parser_objc_synchronized_statement (c_parser *parser) } else expr = error_mark_node; - stmt = c_parser_compound_statement (parser); + /* APPLE LOCAL radar 5982990 */ + stmt = c_parser_objc_synch_compound_statement (parser); objc_build_synchronized (loc, expr, stmt); } @@ -7433,7 +8020,8 @@ c_parser_omp_for_loop (c_parser *parser) /* Parse the initialization declaration or expression. */ if (c_parser_next_token_starts_declspecs (parser)) { - c_parser_declaration_or_fndef (parser, true, true, true, true); + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, true, true, true, true, NULL); decl = check_for_loop_decls (); if (decl == NULL) goto error_init; @@ -7902,4 +8490,980 @@ c_parse_file (void) the_parser = NULL; } +/* APPLE LOCAL begin radar 5732232 - blocks (C++ ce) */ + +/* APPLE LOCAL begin radar 6300081 */ + +/* This function builds a "generic" block struct type, to be passed + into the debug information for blocks pointers, to allow gdb to + find the actual function pointer for the block. Any time the Blocks + structure layout changes, this may also need to change. + + Currently a block pointer is a pointer to a __block_literal_n struct, + the third field of which is a pointer to a __block_descriptor struct, + whose third field is the function pointer. There are other fields as + well, but these are the ones gdb needs to know about to find the + function pointer. Therefore a generic block struct currently looks + like this: + + struct __block_literal_generic + { + void * __isa; + int __flags; + int __reserved; + void (*__FuncPtr)(void *); + struct __block_descriptor + { + unsigned long int reserved; + unsigned long int Size; + } *__descriptor; + }; + + IF AT ANY TIME THE STRUCTURE OF A __BLOCK_LITERAL_N CHANGES, THIS + MUST BE CHANGED ALSO!! + +*/ + +tree +/* APPLE LOCAL radar 6353006 */ +c_build_generic_block_struct_type (void) +{ + tree field_decl_chain; + tree field_decl; + tree block_struct_type; + + push_to_top_level (); + block_struct_type = start_struct (RECORD_TYPE, + get_identifier ("__block_literal_generic")); + + field_decl = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node); + field_decl_chain = field_decl; + + field_decl = build_decl (FIELD_DECL, get_identifier ("__flags"), + integer_type_node); + chainon (field_decl_chain, field_decl); + + field_decl = build_decl (FIELD_DECL, get_identifier ("__reserved"), + integer_type_node); + chainon (field_decl_chain, field_decl); + + /* void *__FuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__FuncPtr"), ptr_type_node); + chainon (field_decl_chain, field_decl); + + field_decl = build_decl (FIELD_DECL, get_identifier ("__descriptor"), + build_block_descriptor_type (false)); + chainon (field_decl_chain, field_decl); + + TYPE_BLOCK_IMPL_STRUCT (block_struct_type) = 1; + finish_struct (block_struct_type, field_decl_chain, NULL_TREE); + pop_from_top_level (); + return block_struct_type; +} +/* APPLE LOCAL end radar 6300081 */ + +/* APPLE LOCAL begin radar 5847213 - radar 6329245 */ +/** build_block_struct_type - + struct __block_literal_n { + void *__isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int __flags; + int __reserved; + void *__FuncPtr; + struct __block_descriptor { + unsigned long int reserved; // NULL + unsigned long int Size; // sizeof(struct __block_literal_n) + + // optional helper functions + void *CopyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + } *__descriptor; + + // imported variables + int x; // ref variable list ... + int *y; // byref variable list + }; +*/ +static tree +build_block_struct_type (struct block_sema_info * block_impl) +{ + tree field_decl_chain, field_decl, chain; + char buffer[32]; + static int unique_count; + tree block_struct_type; + + /* Check and see if this block is required to have a Copy/Dispose + helper function. If yes, set BlockHasCopyDispose to TRUE. */ + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (block_requires_copying (TREE_VALUE (chain))) + { + block_impl->BlockHasCopyDispose = TRUE; + break; + } + + /* Further check to see that we have __block variables which require + Copy/Dispose helpers. */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + block_impl->BlockHasCopyDispose = TRUE; + break; + } + + sprintf(buffer, "__block_literal_%d", ++unique_count); + push_to_top_level (); + block_struct_type = start_struct (RECORD_TYPE, get_identifier (buffer)); + + /* void *__isa; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node); + field_decl_chain = field_decl; + + /* int __flags */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__flags"), + integer_type_node); + chainon (field_decl_chain, field_decl); + + /* int __reserved */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__reserved"), + integer_type_node); + chainon (field_decl_chain, field_decl); + + /* void *__FuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__FuncPtr"), ptr_type_node); + chainon (field_decl_chain, field_decl); + + /* struct __block_descriptor *__descriptor */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__descriptor"), + build_block_descriptor_type (block_impl->BlockHasCopyDispose)); + chainon (field_decl_chain, field_decl); + + if (block_impl->BlockHasCopyDispose) + { + /* If inner block of a nested block has BlockHasCopyDispose, so + does its outer block. */ + if (block_impl->prev_block_info) + block_impl->prev_block_info->BlockHasCopyDispose = TRUE; + } + + /* int x; // ref variable list ... */ + for (chain = block_impl->block_ref_decl_list; chain; chain = TREE_CHAIN (chain)) + { + tree p = TREE_VALUE (chain); + /* Note! const-ness of copied in variable must not be carried over to the + type of the synthesized struct field. It prevents to assign to this + field when copy constructor is synthesized. */ + field_decl = build_decl (FIELD_DECL, DECL_NAME (p), + c_build_qualified_type (TREE_TYPE (p), + TYPE_UNQUALIFIED)); + chainon (field_decl_chain, field_decl); + } + + /* int *y; // byref variable list */ + for (chain = block_impl->block_byref_decl_list; chain; chain = TREE_CHAIN (chain)) + { + tree p = TREE_VALUE (chain); + field_decl = build_decl (FIELD_DECL, DECL_NAME (p), + TREE_TYPE (p)); + chainon (field_decl_chain, field_decl); + } + pop_from_top_level (); + finish_struct (block_struct_type, field_decl_chain, NULL_TREE); + return block_struct_type; +} + +/** build_descriptor_block_decl - + This routine builds a static block_descriptior variable of type: + struct __block_descriptor; and initializes it to: + {0, sizeof(struct literal_block_n), + copy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE + destroy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE + } +*/ +static tree +build_descriptor_block_decl (tree block_struct_type, struct block_sema_info *block_impl) +{ + extern tree create_tmp_var_raw (tree, const char *); + static int desc_unique_count; + int size; + tree helper_addr, fields; + tree decl, constructor, initlist; + tree exp, bind; + char name [32]; + tree descriptor_type = + TREE_TYPE (build_block_descriptor_type (block_impl->BlockHasCopyDispose)); + + sprintf (name, "__block_descriptor_tmp_%d", ++desc_unique_count); + decl = create_tmp_var_raw (descriptor_type, name); + DECL_CONTEXT (decl) = NULL_TREE; + DECL_ARTIFICIAL (decl) = 1; + + /* Initialize "reserved" field to 0 for now. */ + fields = TYPE_FIELDS (descriptor_type); + initlist = build_tree_list (fields, build_int_cst (long_unsigned_type_node, 0)); + fields = TREE_CHAIN (fields); + + /* Initialize "Size" field. */ + size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (block_struct_type)); + initlist = tree_cons (fields, + build_int_cst (long_unsigned_type_node, size), + initlist); + + if (block_impl->BlockHasCopyDispose) + { + /* Initialize "CopyFuncPtr" and "DestroyFuncPtr" fields. */ + /* Helpers were previously generated completeley as a nested + function (and context was required for code gen.) But they are not, + so context must be set to NULL so initialization logic does not complain. */ + DECL_CONTEXT (block_impl->copy_helper_func_decl) = NULL_TREE; + fields = TREE_CHAIN (fields); + helper_addr = build_fold_addr_expr (block_impl->copy_helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + initlist = tree_cons (fields, helper_addr, initlist); + DECL_CONTEXT (block_impl->destroy_helper_func_decl) = NULL_TREE; + fields = TREE_CHAIN (fields); + helper_addr = build_fold_addr_expr (block_impl->destroy_helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + initlist = tree_cons (fields, helper_addr, initlist); + } + constructor = build_constructor_from_list (descriptor_type, + nreverse (initlist)); + TREE_CONSTANT (constructor) = 1; + TREE_STATIC (constructor) = 1; + TREE_READONLY (constructor) = 1; + DECL_INITIAL (decl) = constructor; + exp = build_stmt (DECL_EXPR, decl); + bind = build3 (BIND_EXPR, void_type_node, decl, exp, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + TREE_PUBLIC (decl) = 0; + TREE_STATIC (decl) = 1; + finish_decl (decl, constructor, NULL_TREE); + return decl; +} + +/** + build_block_struct_initlist - builds the initializer list: + { &_NSConcreteStackBlock or &_NSConcreteGlobalBlock // __isa, + BLOCK_USE_STRET | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL // __flags, + 0, // __reserved + &helper_1, // __FuncPtr, + &static_descriptor_variable // __descriptor, + x, // user variables. + &y + ... + } +*/ +static tree +build_block_struct_initlist (tree block_struct_type, + struct block_sema_info *block_impl) +{ + tree initlist, helper_addr; + tree chain, fields; + /* APPLE LOCAL radar 7735196 */ + unsigned int flags = 0; + static tree NSConcreteStackBlock_decl = NULL_TREE; + static tree NSConcreteGlobalBlock_decl = NULL_TREE; + tree descriptor_block_decl = build_descriptor_block_decl (block_struct_type, block_impl); + + if (block_impl->BlockHasCopyDispose) + /* Note! setting of this flag merely indicates to the runtime that + we have destroy_helper_block/copy_helper_block helper + routines. */ + flags |= BLOCK_HAS_COPY_DISPOSE; + /* APPLE LOCAL begin radar 7735196 */ + if (block_impl->return_type && aggregate_value_p(block_impl->return_type, 0)) + flags |= BLOCK_USE_STRET; + /* APPLE LOCAL end 7735196 */ + + fields = TYPE_FIELDS (block_struct_type); + /* APPLE LOCAL begin radar 6230297 */ + if (!current_function_decl || + (block_impl->block_ref_decl_list == NULL_TREE && + block_impl->block_byref_decl_list == NULL_TREE)) + /* APPLE LOCAL end radar 6230297 */ + { + /* This is a global block. */ + /* Find an existing declaration for _NSConcreteGlobalBlock or declare + extern void *_NSConcreteGlobalBlock; */ + if (NSConcreteGlobalBlock_decl == NULL_TREE) + { + tree name_id = get_identifier("_NSConcreteGlobalBlock"); + NSConcreteGlobalBlock_decl = lookup_name (name_id); + if (!NSConcreteGlobalBlock_decl) + { + NSConcreteGlobalBlock_decl = build_decl (VAR_DECL, name_id, ptr_type_node); + DECL_EXTERNAL (NSConcreteGlobalBlock_decl) = 1; + TREE_PUBLIC (NSConcreteGlobalBlock_decl) = 1; + pushdecl_top_level (NSConcreteGlobalBlock_decl); + rest_of_decl_compilation (NSConcreteGlobalBlock_decl, 0, 0); + } + } + /* APPLE LOCAL begin radar 6457359 */ + initlist = build_tree_list (fields, + convert (ptr_type_node, + build_fold_addr_expr (NSConcreteGlobalBlock_decl))); + /* APPLE LOCAL end radar 6457359 */ + flags |= BLOCK_IS_GLOBAL; + } + else + { + /* Find an existing declaration for _NSConcreteStackBlock or declare + extern void *_NSConcreteStackBlock; */ + if (NSConcreteStackBlock_decl == NULL_TREE) + { + tree name_id = get_identifier("_NSConcreteStackBlock"); + NSConcreteStackBlock_decl = lookup_name (name_id); + if (!NSConcreteStackBlock_decl) + { + NSConcreteStackBlock_decl = build_decl (VAR_DECL, name_id, ptr_type_node); + DECL_EXTERNAL (NSConcreteStackBlock_decl) = 1; + TREE_PUBLIC (NSConcreteStackBlock_decl) = 1; + pushdecl_top_level (NSConcreteStackBlock_decl); + rest_of_decl_compilation (NSConcreteStackBlock_decl, 0, 0); + } + } + /* APPLE LOCAL begin radar 6457359 */ + initlist = build_tree_list (fields, + convert (ptr_type_node, + build_fold_addr_expr (NSConcreteStackBlock_decl))); + /* APPLE LOCAL end radar 6457359 */ + } + fields = TREE_CHAIN (fields); + + /* __flags */ + initlist = tree_cons (fields, + build_int_cst (integer_type_node, flags), + initlist); + fields = TREE_CHAIN (fields); + + /* __reserved */ + initlist = tree_cons (fields, + build_int_cst (integer_type_node, 0), + initlist); + fields = TREE_CHAIN (fields); + + /* __FuncPtr */ + helper_addr = build_fold_addr_expr (block_impl->helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + initlist = tree_cons (fields, helper_addr, initlist); + fields = TREE_CHAIN (fields); + + /* __descriptor */ + /* APPLE LOCAL begin radar 6457359 */ + initlist = tree_cons (fields, + build_fold_addr_expr (descriptor_block_decl), + initlist); + /* APPLE LOCAL end radar 6457359 */ + for (chain = block_impl->block_original_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + { + tree y = TREE_VALUE (chain); + TREE_USED (y) = 1; + fields = TREE_CHAIN (fields); + initlist = tree_cons (fields, y, initlist); + } + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + { + tree y = lookup_name (DECL_NAME (TREE_VALUE (chain))); + tree forwarding_expr; + gcc_assert (y); + TREE_USED (y) = 1; + if (COPYABLE_BYREF_LOCAL_VAR (y)) + { + /* For variables declared __block, either the original one + at the point of declaration or the imported version (which is + initialized in the helper function's prologue) is used to + initilize the byref variable field in the temporary. */ + if (TREE_CODE (TREE_TYPE (y)) != RECORD_TYPE) + y = build_indirect_ref (y, "unary *"); + /* We will be using the __block_struct_variable.__forwarding as the + initializer. */ + forwarding_expr = build_component_ref (y, get_identifier ("__forwarding")); + } + else + /* Global variable is always assumed passed by its address. */ + forwarding_expr = build_fold_addr_expr (y); + fields = TREE_CHAIN (fields); + initlist = tree_cons (fields, forwarding_expr, initlist); + } + return initlist; +} + +/** + build_block_literal_tmp - This routine: + + 1) builds block type: + struct __block_literal_n { + void *__isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int __flags; + int __reserved; + void *__FuncPtr + struct __block_descriptor { + unsigned long int reserved; // NULL + unsigned long int Size; // sizeof(struct Block_literal_1) + + // optional helper functions + void *CopyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + } *__descriptor; + + // imported variables + int x; // ref variable list ... + int *y; // byref variable list + }; + + 2) build function prototype: + double helper_1(struct __block_literal_n *ii, int z); + + 3) build the temporary initialization: + struct __block_literal_n I = { + &_NSConcreteStackBlock or &_NSConcreteGlobalBlock // __isa, + BLOCK_USE_STRET | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL // __flags, + 0, // __reserved + &helper_1, // __FuncPtr + &static_descriptor_variable // __descriptor, + x, // user variables. + &y + ... + }; +It return the temporary. +*/ + +static tree +build_block_literal_tmp (const char *name, + struct block_sema_info * block_impl) +{ + extern tree create_tmp_var_raw (tree, const char *); + tree block_holder_tmp_decl; + tree constructor, initlist; + tree exp, bind; + tree block_struct_type = TREE_TYPE (block_impl->block_arg_ptr_type); + /* APPLE LOCAL begin radar 6230297 */ + bool staticBlockTmp = (block_impl->block_ref_decl_list == NULL_TREE && + block_impl->block_byref_decl_list == NULL_TREE); + + + block_holder_tmp_decl = create_tmp_var_raw (block_struct_type, name); + /* Context will not be known until when the literal is synthesized. + This is more so in the case of nested block literal blocks. */ + DECL_CONTEXT (block_holder_tmp_decl) = staticBlockTmp ? NULL_TREE + : current_function_decl; + /* In the new ABI, helper function decl. is the initializer for the + descriptor variable which is always declared static. So, it must + have no context; otherwise, gcc thinks that it requires trampoline! when + address of this function is used as initializer. */ + DECL_CONTEXT (block_impl->helper_func_decl) = NULL_TREE; + /* APPLE LOCAL end radar 6230297 */ + DECL_ARTIFICIAL (block_holder_tmp_decl) = 1; + + initlist = build_block_struct_initlist (block_struct_type, + block_impl); + initlist = nreverse (initlist); + constructor = build_constructor_from_list (block_struct_type, + initlist); + TREE_CONSTANT (constructor) = 1; + TREE_STATIC (constructor) = 1; + TREE_READONLY (constructor) = 1; + DECL_INITIAL (block_holder_tmp_decl) = constructor; + exp = build_stmt (DECL_EXPR, block_holder_tmp_decl); + bind = build3 (BIND_EXPR, void_type_node, block_holder_tmp_decl, exp, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + /* Temporary representing a global block is made global static. */ + /* APPLE LOCAL radar 6230297 */ + if (staticBlockTmp || global_bindings_p ()) { + TREE_PUBLIC (block_holder_tmp_decl) = 0; + TREE_STATIC (block_holder_tmp_decl) = 1; + finish_decl (block_holder_tmp_decl, constructor, NULL_TREE); + } + return block_holder_tmp_decl; +} +/* APPLE LOCAL end radar 5847213 - radar 6329245 */ + +static tree +clean_and_exit (tree block) +{ + pop_function_context (); + free (finish_block (block)); + return error_mark_node; +} + +/** synth_copy_helper_block_func - This function synthesizes + void copy_helper_block (struct block* _dest, struct block *_src) function. +*/ + +static void +synth_copy_helper_block_func (struct block_sema_info * block_impl) +{ + tree stmt, chain, fnbody; + tree dst_arg, src_arg; + struct c_arg_info * arg_info; + /* Set up: (struct block* _dest, struct block *_src) parameters. */ + dst_arg = build_decl (PARM_DECL, get_identifier ("_dst"), + block_impl->block_arg_ptr_type); + DECL_CONTEXT (dst_arg) = cur_block->copy_helper_func_decl; + TREE_USED (dst_arg) = 1; + DECL_ARG_TYPE (dst_arg) = block_impl->block_arg_ptr_type; + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + block_impl->block_arg_ptr_type); + /* APPLE LOCAL radar 5847213 */ + DECL_CONTEXT (src_arg) = cur_block->copy_helper_func_decl; + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = block_impl->block_arg_ptr_type; + arg_info = xcalloc (1, sizeof (struct c_arg_info)); + TREE_CHAIN (dst_arg) = src_arg; + arg_info->parms = dst_arg; + arg_info->types = tree_cons (NULL_TREE, block_impl->block_arg_ptr_type, + tree_cons (NULL_TREE, + block_impl->block_arg_ptr_type, + NULL_TREE)); + /* function header synthesis. */ + push_function_context (); + start_block_helper_function (cur_block->copy_helper_func_decl); + store_parm_decls_from (arg_info); + + /* Body of the function. */ + stmt = c_begin_compound_stmt (true); + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (block_requires_copying (TREE_VALUE (chain))) + { + /* APPLE LOCAL begin radar 6175959 */ + int flag; + tree call_exp; + tree p = TREE_VALUE (chain); + tree dst_block_component, src_block_component; + dst_block_component = build_component_ref (build_indirect_ref (dst_arg, "->"), + DECL_NAME (p)); + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + if (TREE_CODE (TREE_TYPE (p)) == BLOCK_POINTER_TYPE) + /* _Block_object_assign(&_dest->myImportedBlock, _src->myImportedClosure, BLOCK_FIELD_IS_BLOCK) */ + flag = BLOCK_FIELD_IS_BLOCK; + else + /* _Block_object_assign(&_dest->myImportedBlock, _src->myImportedClosure, BLOCK_FIELD_IS_OBJECT) */ + flag = BLOCK_FIELD_IS_OBJECT; + dst_block_component = build_fold_addr_expr (dst_block_component); + call_exp = build_block_object_assign_call_exp (dst_block_component, src_block_component, flag); + add_stmt (call_exp); + /* APPLE LOCAL end radar 6175959 */ + } + + /* For each __block declared variable must generate call to: + _Block_object_assign(&_dest->myImportedBlock, _src->myImportedBlock, BLOCK_FIELD_IS_BYREF [|BLOCK_FIELD_IS_WEAK]) + */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + int flag = BLOCK_FIELD_IS_BYREF; + tree call_exp; + tree p = TREE_VALUE (chain); + tree dst_block_component, src_block_component; + dst_block_component = build_component_ref (build_indirect_ref (dst_arg, "->"), + DECL_NAME (p)); + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + /* _Block_object_assign(&_dest->myImportedClosure, _src->myImportedClosure, BLOCK_FIELD_IS_BYREF [|BLOCK_FIELD_IS_WEAK]) */ + if (COPYABLE_WEAK_BLOCK (p)) + flag |= BLOCK_FIELD_IS_WEAK; + + dst_block_component = build_fold_addr_expr (dst_block_component); + call_exp = build_block_object_assign_call_exp (dst_block_component, src_block_component, flag); + add_stmt (call_exp); + } + + fnbody = c_end_compound_stmt (stmt, true); + add_stmt (fnbody); + finish_function (); + pop_function_context (); + free (arg_info); +} + +static void +synth_destroy_helper_block_func (struct block_sema_info * block_impl) +{ + tree stmt, chain, fnbody; + tree src_arg; + struct c_arg_info * arg_info; + /* Set up: (struct block *_src) parameter. */ + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + block_impl->block_arg_ptr_type); + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = block_impl->block_arg_ptr_type; + arg_info = xcalloc (1, sizeof (struct c_arg_info)); + arg_info->parms = src_arg; + arg_info->types = tree_cons (NULL_TREE, block_impl->block_arg_ptr_type, + NULL_TREE); + + /* function header synthesis. */ + push_function_context (); + start_block_helper_function (cur_block->destroy_helper_func_decl); + store_parm_decls_from (arg_info); + + /* Body of the function. */ + stmt = c_begin_compound_stmt (true); + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (block_requires_copying (TREE_VALUE (chain))) + { + int flag; + tree rel_exp; + tree p = TREE_VALUE (chain); + tree src_block_component; + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + if (TREE_CODE (TREE_TYPE (p)) == BLOCK_POINTER_TYPE) + /* _Block_object_dispose(_src->imported_object_0, BLOCK_FIELD_IS_BLOCK); */ + flag = BLOCK_FIELD_IS_BLOCK; + else + /* _Block_object_dispose(_src->imported_object_0, BLOCK_FIELD_IS_OBJECT); */ + flag = BLOCK_FIELD_IS_OBJECT; + rel_exp = build_block_object_dispose_call_exp (src_block_component, flag); + add_stmt (rel_exp); + } + + /* For each __block declared variable must generate call to: + _Block_object_dispose(_src->myImportedClosure, BLOCK_FIELD_IS_BYREF[|BLOCK_FIELD_IS_WEAK]) + */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + tree call_exp; + int flag = BLOCK_FIELD_IS_BYREF; + tree p = TREE_VALUE (chain); + tree src_block_component; + + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + if (COPYABLE_WEAK_BLOCK (p)) + flag |= BLOCK_FIELD_IS_WEAK; + /* _Block_object_dispose(_src->myImportedClosure, BLOCK_FIELD_IS_BYREF[|BLOCK_FIELD_IS_WEAK]) */ + call_exp = build_block_object_dispose_call_exp (src_block_component, flag); + add_stmt (call_exp); + } + + fnbody = c_end_compound_stmt (stmt, true); + add_stmt (fnbody); + finish_function (); + pop_function_context (); + free (arg_info); +} + +/* Parse a block-id. + + GNU Extension: + + block-id: + specifier-qualifier-list block-declarator + + Returns the DECL specified or implied. */ + +static tree +c_parser_block_id (c_parser* parser) +{ + struct c_declspecs *specs = build_null_declspecs (); + struct c_declarator *declarator; + bool dummy = false; + + c_parser_declspecs (parser, specs, false, true, true); + if (!specs->declspecs_seen_p) + { + c_parser_error (parser, "expected specifier-qualifier-list"); + return NULL; + } + pending_xref_error (); + finish_declspecs (specs); + declarator = c_parser_declarator (parser, specs->type_seen_p, + C_DTR_BLOCK, &dummy); + if (declarator == NULL) + return NULL; + + return grokblockdecl (specs, declarator); +} + +/* Parse a block-literal-expr. + + GNU Extension: + + block-literal-expr: + ^ parameter-declation-clause exception-specification [opt] compound-statement + ^ block-id compound-statement + + It synthesizes the helper function for later generation and builds + the necessary data to represent the block literal where it is + declared. */ +static tree +c_parser_block_literal_expr (c_parser* parser) +{ + char name [32]; + static int global_unique_count; + int unique_count = ++global_unique_count; + tree block_helper_function_decl; + tree expr, body, type, arglist = void_list_node, ftype; + tree self_arg, stmt; + struct c_arg_info *args = NULL; + tree arg_type = void_list_node; + struct block_sema_info *block_impl; + tree tmp; + bool open_paren_seen = false; + tree restype; + tree fnbody, typelist; + tree helper_function_type; + tree block; + /* APPLE LOCAL radar 6185344 */ + tree declared_block_return_type = NULL_TREE; + /* APPLE LOCAL radar 6237713 */ + tree attributes = NULL_TREE; + + c_parser_consume_token (parser); /* eat '^' */ + + /* APPLE LOCAL begin radar 6237713 */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + attributes = c_parser_attributes (parser); + /* APPLE LOCAL end radar 6237713 */ + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + /* Parse the optional argument list */ + c_parser_consume_token (parser); + /* Open the scope to collect parameter decls */ + push_scope (); + args = c_parser_parms_declarator (parser, true, NULL_TREE); + /* Check for args as it might be NULL due to error. */ + if (args) + { + arglist = args->parms; + arg_type = args->types; + } + else + { + pop_scope (); + return error_mark_node; + } + open_paren_seen = true; + pop_scope (); + } + else if (c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) + { + /* Parse user declared return type. */ + tree decl; + + /* APPLE LOCAL begin radar 6237713 */ + if (attributes) + { + warning (0, "attributes before block type are ignored"); + attributes = NULL_TREE; + } + /* APPLE LOCAL end radar 6237713 */ + + decl = c_parser_block_id (parser); + + if (decl && decl != error_mark_node) + { + arg_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); + arglist = DECL_ARGUMENTS (decl); + declared_block_return_type = TREE_TYPE (TREE_TYPE (decl)); + } + } + + block = begin_block (); + + cur_block->arg_info = NULL; + if (declared_block_return_type) + { + cur_block->return_type = TYPE_MAIN_VARIANT (declared_block_return_type); + cur_block->block_has_return_type = true; + } + else + cur_block->return_type = NULL_TREE; + + if (args) + cur_block->arg_info = args; + else + cur_block->arg_info = xcalloc (1, sizeof (struct c_arg_info)); + + if (declared_block_return_type) + { + cur_block->arg_info->parms = arglist; + cur_block->arg_info->types = arg_type; + } + + /* Must also build hidden parameter .block_descriptor added to the helper + function, even though we do not know its type yet. */ + /* APPLE LOCAL radar 6404979 */ + self_arg = build_decl (PARM_DECL, get_identifier (".block_descriptor"), + ptr_type_node); + TREE_USED (self_arg) = 1; /* Prevent unused parameter '.block_descriptor' warning. */ + TREE_CHAIN (self_arg) = cur_block->arg_info->parms; + cur_block->arg_info->types = tree_cons (NULL_TREE, ptr_type_node, arg_type); + cur_block->arg_info->parms = self_arg; + + /* APPLE LOCAL begin radar 6185344 */ + /* Build the declaration of the helper function (if we do not know its result + type yet, assume it is 'void'. If user provided it, use it). + Treat this as a nested function and use nested function infrastructure for + its generation. */ + + ftype = build_function_type ((!cur_block->block_has_return_type + ? void_type_node : cur_block->return_type), + cur_block->arg_info->types); + /* APPLE LOCAL end radar 6185344 */ + /* APPLE LOCAL radar 6160536 - radar 6411649 */ + block_helper_function_decl = build_helper_func_decl (build_block_helper_name (0), + ftype); + DECL_CONTEXT (block_helper_function_decl) = current_function_decl; + cur_block->helper_func_decl = block_helper_function_decl; + + push_function_context (); + start_block_helper_function (cur_block->helper_func_decl); + /* Set block's scope to the scope of the helper function's main body. + This is primarily used when nested blocks are declared. */ + /* FIXME: Name of objc_get_current_scope needs to get changed. */ + cur_block->the_scope = (struct c_scope*)objc_get_current_scope (); + + /* Enter parameter list to the scope of the helper function. */ + store_parm_decls_from (cur_block->arg_info); + + /* APPLE LOCAL begin radar 6237713 */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + attributes = c_parser_attributes (parser); + /* APPLE LOCAL radar 6246527 */ + any_recognized_block_attribute (attributes); + decl_attributes (&cur_block->helper_func_decl, attributes, 0); + /* APPLE LOCAL end radar 6237713 */ + + /* Start parsing body or expression part of the block literal. */ + if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { + tree save_c_break_label = c_break_label; + tree save_c_cont_label = c_cont_label; + /* Indicate no valid break/continue context by setting these variables + to some non-null, non-label value. We'll notice and emit the proper + error message in c_finish_bc_stmt. */ + c_break_label = c_cont_label = size_zero_node; + c_parser_consume_token (parser); /* Consure '{'. */ + stmt = c_begin_compound_stmt (true); + c_parser_compound_statement_nostart (parser); + c_cont_label = save_c_cont_label; + c_break_label = save_c_break_label; + } + else + { + struct c_expr expr; + stmt = c_begin_compound_stmt (true); + error ("blocks require { }"); + expr = c_parser_cast_expression (parser, NULL); + body = expr.value; + if (body == error_mark_node) + return clean_and_exit (block); + + if (cur_block->return_type) + { + error ("return not allowed in block expression literal"); + return clean_and_exit (block); + } + else if (!open_paren_seen) + { + error ("argument list is required for block expression literals"); + return clean_and_exit (block); + } + else + { + tree restype = TYPE_MAIN_VARIANT (TREE_TYPE (body)); + + add_stmt (body); + TREE_TYPE (current_function_decl) + = build_function_type (restype, + TYPE_ARG_TYPES (TREE_TYPE (current_function_decl))); + TREE_TYPE (DECL_RESULT (current_function_decl)) = restype; + relayout_decl (DECL_RESULT (current_function_decl)); + cur_block->return_type = restype; + } + } + + cur_block->block_arg_ptr_type = + build_pointer_type (build_block_struct_type (cur_block)); + + restype = !cur_block->return_type ? void_type_node + : cur_block->return_type; + if (restype == error_mark_node) + return clean_and_exit (block); + + /* Now that we know type of the hidden .block_descriptor argument, fix its type. */ + TREE_TYPE (self_arg) = cur_block->block_arg_ptr_type; + DECL_ARG_TYPE (self_arg) = cur_block->block_arg_ptr_type; + + /* The DECL_RESULT should already have the correct type by now. */ + gcc_assert (TREE_TYPE (DECL_RESULT (current_function_decl)) + == restype); + + cur_block->block_body = stmt; + block_build_prologue (cur_block); + + fnbody = c_end_compound_stmt (stmt, true); + add_stmt (fnbody); + + /* We are done parsing of the block body. Return type of block is now known. + We also know all we need to know about the helper function. So, fix its + type here. */ + /* We moved this here because for global blocks, helper function body is + not nested and is gimplified in call to finish_function() and return type + of the function must be correct. */ + ftype = build_function_type (restype, arg_type); + /* Declare helper function; as in: + double helper_1(struct block_1 *ii, int z); */ + typelist = TYPE_ARG_TYPES (ftype); + /* (struct block_1 *ii, int z, ...) */ + typelist = tree_cons (NULL_TREE, cur_block->block_arg_ptr_type, + typelist); + helper_function_type = build_function_type (TREE_TYPE (ftype), typelist); + TREE_TYPE (cur_block->helper_func_decl) = helper_function_type; + finish_function (); + pop_function_context (); + + /* Build the declaration for copy_helper_block and destroy_helper_block + helper functions for later use. */ + + if (cur_block->BlockHasCopyDispose) + { + /* void copy_helper_block (struct block*, struct block *); */ + tree s_ftype = build_function_type (void_type_node, + tree_cons (NULL_TREE, cur_block->block_arg_ptr_type, + tree_cons (NULL_TREE, + cur_block->block_arg_ptr_type, + void_list_node))); + sprintf (name, "__copy_helper_block_%d", unique_count); + cur_block->copy_helper_func_decl = + build_helper_func_decl (get_identifier (name), s_ftype); + synth_copy_helper_block_func (cur_block); + + /* void destroy_helper_block (struct block*); */ + s_ftype = build_function_type (void_type_node, + tree_cons (NULL_TREE, + cur_block->block_arg_ptr_type, void_list_node)); + sprintf (name, "__destroy_helper_block_%d", unique_count); + cur_block->destroy_helper_func_decl = + build_helper_func_decl (get_identifier (name), s_ftype); + synth_destroy_helper_block_func (cur_block); + } + + block_impl = finish_block (block); + + /* Build unqiue name of the temporary used in code gen. */ + sprintf (name, "__block_holder_tmp_%d", unique_count); + tmp = build_block_literal_tmp (name, block_impl); + tmp = build_fold_addr_expr (tmp); + type = build_block_pointer_type (ftype); + expr = convert (type, convert (ptr_type_node, tmp)); + free (block_impl); + return expr; +} +/* APPLE LOCAL end radar 5732232 - blocks (C++ ce) */ + #include "gt-c-parser.h" diff --git a/contrib/gcc/c-pretty-print.c b/contrib/gcc/c-pretty-print.c index 5225ea3dd96b..ee60864c52bd 100644 --- a/contrib/gcc/c-pretty-print.c +++ b/contrib/gcc/c-pretty-print.c @@ -137,6 +137,15 @@ pp_c_star (c_pretty_printer *pp) pp_base (pp)->padding = pp_none; } +/* APPLE LOCAL begin blocks */ +void +pp_c_caret (c_pretty_printer *pp) +{ + pp_carret (pp); + pp_base (pp)->padding = pp_none; +} +/* APPLE LOCAL end blocks */ + void pp_c_arrow (c_pretty_printer *pp) { @@ -260,6 +269,12 @@ pp_c_pointer (c_pretty_printer *pp, tree t) pp_c_ampersand (pp); pp_c_type_qualifier_list (pp, t); break; + /* APPLE LOCAL begin blocks */ + case BLOCK_POINTER_TYPE: + pp_c_caret (pp); + pp_c_type_qualifier_list (pp, t); + break; + /* APPLE LOCAL end blocks */ /* ??? This node is now in GENERIC and so shouldn't be here. But we'll fix that later. */ @@ -405,6 +420,8 @@ pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t) { case REFERENCE_TYPE: case POINTER_TYPE: + /* APPLE LOCAL blocks */ + case BLOCK_POINTER_TYPE: { /* Get the types-specifier of this type. */ tree pointee = strip_pointer_operator (TREE_TYPE (t)); @@ -487,7 +504,10 @@ pp_c_parameter_type_list (c_pretty_printer *pp, tree t) static void pp_c_abstract_declarator (c_pretty_printer *pp, tree t) { - if (TREE_CODE (t) == POINTER_TYPE) + /* APPLE LOCAL begin blocks */ + if (TREE_CODE (t) == POINTER_TYPE || + TREE_CODE (t) == BLOCK_POINTER_TYPE) + /* APPLE LOCAL end blocks */ { if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) @@ -510,6 +530,8 @@ pp_c_direct_abstract_declarator (c_pretty_printer *pp, tree t) switch (TREE_CODE (t)) { case POINTER_TYPE: + /* APPLE LOCAL blocks */ + case BLOCK_POINTER_TYPE: pp_abstract_declarator (pp, t); break; @@ -635,6 +657,8 @@ pp_c_direct_declarator (c_pretty_printer *pp, tree t) case ARRAY_TYPE: case POINTER_TYPE: + /* APPLE LOCAL blocks */ + case BLOCK_POINTER_TYPE: pp_abstract_declarator (pp, TREE_TYPE (t)); break; diff --git a/contrib/gcc/c-pretty-print.h b/contrib/gcc/c-pretty-print.h index 6a4086b4fc2c..2cb8c0644421 100644 --- a/contrib/gcc/c-pretty-print.h +++ b/contrib/gcc/c-pretty-print.h @@ -167,6 +167,8 @@ void pp_c_right_bracket (c_pretty_printer *); void pp_c_dot (c_pretty_printer *); void pp_c_ampersand (c_pretty_printer *); void pp_c_star (c_pretty_printer *); +/* APPLE LOCAL blocks */ +void pp_c_caret (c_pretty_printer *); void pp_c_arrow (c_pretty_printer *); void pp_c_semicolon (c_pretty_printer *); void pp_c_complement (c_pretty_printer *); diff --git a/contrib/gcc/c-tree.h b/contrib/gcc/c-tree.h index af2e798f2bf2..75c20936970c 100644 --- a/contrib/gcc/c-tree.h +++ b/contrib/gcc/c-tree.h @@ -298,6 +298,8 @@ enum c_declarator_kind { cdk_array, /* A pointer. */ cdk_pointer, + /* APPLE LOCAL blocks (C++ ch) */ + cdk_block_pointer, /* Parenthesized declarator with nested attributes. */ cdk_attrs }; @@ -468,6 +470,8 @@ extern tree finish_struct (tree, tree, tree); extern struct c_arg_info *get_parm_info (bool); extern tree grokfield (struct c_declarator *, struct c_declspecs *, tree); extern tree groktypename (struct c_type_name *); +/* APPLE LOCAL blocks 6339747 */ +extern tree grokblockdecl (struct c_declspecs *, struct c_declarator *); extern tree grokparm (const struct c_parm *); extern tree implicitly_declare (tree); extern void keep_next_level (void); @@ -501,6 +505,10 @@ extern struct c_declarator *build_function_declarator (struct c_arg_info *, extern struct c_declarator *build_id_declarator (tree); extern struct c_declarator *make_pointer_declarator (struct c_declspecs *, struct c_declarator *); +/* APPLE LOCAL begin radar 5814025 - blocks (C++ cg) */ +extern struct c_declarator *make_block_pointer_declarator (struct c_declspecs *, + struct c_declarator *); +/* APPLE LOCAL end radar 5814025 - blocks (C++ cg) */ extern struct c_declspecs *build_null_declspecs (void); extern struct c_declspecs *declspecs_add_qual (struct c_declspecs *, tree); extern struct c_declspecs *declspecs_add_type (struct c_declspecs *, @@ -627,6 +635,8 @@ extern bool c_eh_initialized_p; extern void c_finish_incomplete_decl (tree); extern void c_write_global_declarations (void); +/* APPLE LOCAL radar 5741070 */ +extern tree c_return_interface_record_type (tree); /* In order for the format checking to accept the C frontend diagnostic framework extensions, you must include this file before toplev.h, not after. */ diff --git a/contrib/gcc/c-typeck.c b/contrib/gcc/c-typeck.c index c60aa26bdc94..0101176c0bf7 100644 --- a/contrib/gcc/c-typeck.c +++ b/contrib/gcc/c-typeck.c @@ -75,6 +75,10 @@ static int missing_braces_mentioned; static int require_constant_value; static int require_constant_elements; +/* APPLE LOCAL begin radar 5732232 - blocks (C++ cm) */ +static bool types_are_block_compatible (tree lhptee, tree rhptee); +static tree build_block_call (tree, tree, tree); +/* APPLE LOCAL end radar 5732232 - blocks (C++ cm) */ static bool null_pointer_constant_p (tree); static tree qualify_type (tree, tree); static int tagged_types_tu_compatible_p (tree, tree); @@ -542,8 +546,12 @@ common_pointer_type (tree t1, tree t2) if (t2 == error_mark_node) return t1; - gcc_assert (TREE_CODE (t1) == POINTER_TYPE - && TREE_CODE (t2) == POINTER_TYPE); + /* APPLE LOCAL begin blocks 6065211 */ + gcc_assert ((TREE_CODE (t1) == POINTER_TYPE + && TREE_CODE (t2) == POINTER_TYPE) + || (TREE_CODE (t1) == BLOCK_POINTER_TYPE + && TREE_CODE (t2) == BLOCK_POINTER_TYPE)); + /* APPLE LOCAL end blocks 6065211 */ /* Merge the attributes. */ attributes = targetm.merge_type_attributes (t1, t2); @@ -558,10 +566,15 @@ common_pointer_type (tree t1, tree t2) if (TREE_CODE (mv2) != ARRAY_TYPE) mv2 = TYPE_MAIN_VARIANT (pointed_to_2); target = composite_type (mv1, mv2); - t1 = build_pointer_type (c_build_qualified_type - (target, - TYPE_QUALS (pointed_to_1) | - TYPE_QUALS (pointed_to_2))); + /* APPLE LOCAL begin blocks 6065211 */ + t1 = c_build_qualified_type (target, + TYPE_QUALS (pointed_to_1) | + TYPE_QUALS (pointed_to_2)); + if (TREE_CODE (t2) == BLOCK_POINTER_TYPE) + t1 = build_block_pointer_type (t1); + else + t1 = build_pointer_type (t1); + /* APPLE LOCAL end blocks 6065211 */ return build_type_attribute_variant (t1, attributes); } @@ -845,6 +858,13 @@ comptypes_internal (tree type1, tree type2) switch (TREE_CODE (t1)) { + /* APPLE LOCAL begin radar 5795493 */ + case BLOCK_POINTER_TYPE: + val = (TREE_CODE (t2) == BLOCK_POINTER_TYPE) && + types_are_block_compatible (TREE_TYPE (t1), TREE_TYPE (t2)); + break; + + /* APPLE LOCAL end radar 5795493 */ case POINTER_TYPE: /* Do not remove mode or aliasing information. */ if (TYPE_MODE (t1) != TYPE_MODE (t2) @@ -937,6 +957,15 @@ comp_target_types (tree ttl, tree ttr) int val; tree mvl, mvr; + /* APPLE LOCAL begin blocks 6065211 */ + if (TREE_CODE (ttl) == BLOCK_POINTER_TYPE + && TREE_CODE (ttr) == BLOCK_POINTER_TYPE) + return types_are_block_compatible (TREE_TYPE (ttl), + TREE_TYPE (ttr)); + if (TREE_CODE (ttl) != TREE_CODE (ttr)) + return 0; + /* APPLE LOCAL end blocks 6065211 */ + /* Do not lose qualifiers on element types of array types that are pointer targets by taking their TYPE_MAIN_VARIANT. */ mvl = TREE_TYPE (ttl); @@ -1485,7 +1514,8 @@ decl_constant_value_for_broken_optimization (tree decl) } /* Convert the array expression EXP to a pointer. */ -static tree +/* APPLE LOCAL radar 6212722 */ +tree array_to_pointer_conversion (tree exp) { tree orig_exp = exp; @@ -1526,7 +1556,8 @@ array_to_pointer_conversion (tree exp) } /* Convert the function expression EXP to a pointer. */ -static tree +/* APPLE LOCAL radar 6212722 */ +tree function_to_pointer_conversion (tree exp) { tree orig_exp = exp; @@ -1803,6 +1834,12 @@ build_component_ref (tree datum, tree component) if (!objc_is_public (datum, component)) return error_mark_node; + /* APPLE LOCAL begin C* property (Radar 4436866) */ + /* APPLE LOCAL radar 5285911 */ + if ((ref = objc_build_property_reference_expr (datum, component))) + return ref; + /* APPLE LOCAL end C* property (Radar 4436866) */ + /* See if there is a field or component with name COMPONENT. */ if (code == RECORD_TYPE || code == UNION_TYPE) @@ -1841,6 +1878,8 @@ build_component_ref (tree datum, tree component) ref = build3 (COMPONENT_REF, subtype, datum, subdatum, NULL_TREE); + /* APPLE LOCAL radar 4697411 */ + objc_volatilize_component_ref (ref, TREE_TYPE (subdatum)); if (TREE_READONLY (datum) || TREE_READONLY (subdatum)) TREE_READONLY (ref) = 1; if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum)) @@ -2073,9 +2112,62 @@ build_external_ref (tree id, int fun, location_t loc) /* In Objective-C, an instance variable (ivar) may be preferred to whatever lookup_name() found. */ decl = objc_lookup_ivar (decl, id); - + /* APPLE LOCAL begin radar 5732232 - blocks (C++ ci) */ if (decl && decl != error_mark_node) - ref = decl; + { + if (cur_block + && (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL) + && !lookup_name_in_block (id, &decl)) + { + /* APPLE LOCAL begin radar 5803005 (C++ ci) */ + bool gdecl; + /* We are referencing a variable inside a block whose declaration + is outside. */ + gcc_assert (decl && + (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL)); + gdecl = (TREE_CODE (decl) == VAR_DECL && + /* APPLE LOCAL radar 6177162 */ + (DECL_EXTERNAL (decl) || TREE_STATIC (decl))); + /* Treat all 'global' variables as 'byref' by default. */ + /* APPLE LOCAL begin radar 6014138 (C++ ci) */ + if (gdecl || (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl))) + /* APPLE LOCAL end radar 6014138 (C++ ci) */ + { + /* APPLE LOCAL begin radar 5803600 (C++ ci) */ + /* byref globals are directly accessed. */ + /* APPLE LOCAL begin radar 7760213 */ + if (!gdecl) { + if (HasByrefArray(TREE_TYPE (decl))) + error ("cannot access __block variable of array type inside block"); + /* build a decl for the byref variable. */ + decl = build_block_byref_decl (id, decl, decl); + } + /* APPLE LOCAL end radar 7760213 */ + else + add_block_global_byref_list (decl); + } + else + { + /* 'byref' globals are never copied-in. So, do not add + them to the copied-in list. */ + if (!in_block_global_byref_list (decl)) { + /* APPLE LOCAL begin radar 7721728 */ + if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) + error ("cannot access copied-in variable of array type inside block"); + /* APPLE LOCAL end radar 7721728 */ + /* build a new decl node. set its type to 'const' type + of the old decl. */ + decl = build_block_ref_decl (id, decl); + } + /* APPLE LOCAL end radar 5803600 (C++ ci) */ + /* APPLE LOCAL end radar 5803005 (C++ ci) */ + } + } + ref = decl; + } + /* APPLE LOCAL end radar 5732232 - blocks (C++ ci) */ else if (fun) /* Implicit function declaration. */ ref = implicitly_declare (id); @@ -2285,8 +2377,10 @@ build_function_call (tree function, tree params) if (TREE_CODE (fntype) == ERROR_MARK) return error_mark_node; - - if (!(TREE_CODE (fntype) == POINTER_TYPE + /* APPLE LOCAL begin radar 5732232 - blocks */ + if (!((TREE_CODE (fntype) == POINTER_TYPE + || TREE_CODE (fntype) == BLOCK_POINTER_TYPE) + /* APPLE LOCAL end radar 5732232 - blocks */ && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE)) { error ("called object %qE is not a function", function); @@ -2353,6 +2447,11 @@ build_function_call (tree function, tree params) check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params, TYPE_ARG_TYPES (fntype)); + /* APPLE LOCAL begin radar 5732232 - blocks */ + if (TREE_CODE (TREE_TYPE (function)) == BLOCK_POINTER_TYPE) + result = build_block_call (fntype, function, coerced_params); + else + /* APPLE LOCAL end radar 5732232 - blocks */ if (require_constant_value) { result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype), @@ -2424,7 +2523,17 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) if (type == void_type_node) { - error ("too many arguments to function %qE", function); + /* APPLE LOCAL begin radar 5732232 - blocks */ + if (TREE_CODE (TREE_TYPE (function)) == BLOCK_POINTER_TYPE) + { + error ("too many arguments to block call"); + break; + } + /* APPLE LOCAL end radar 5732232 - blocks */ + /* APPLE LOCAL begin radar 4491608 */ + error ("too many arguments to function %qE", selector ? selector + : function); + /* APPLE LOCAL end radar 4491608 */ break; } @@ -2607,7 +2716,12 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) { - error ("too few arguments to function %qE", function); + /* APPLE LOCAL begin radar 5732232 - blocks */ + if (TREE_CODE (TREE_TYPE (function)) == BLOCK_POINTER_TYPE) + error ("too few arguments to block %qE", function); + else + error ("too few arguments to function %qE", function); + /* APPLE LOCAL end radar 5732232 - blocks */ return error_mark_node; } @@ -2870,6 +2984,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) case TRUTH_NOT_EXPR: if (typecode != INTEGER_TYPE + /* APPLE LOCAL radar 5732232 - blocks */ + && typecode != BLOCK_POINTER_TYPE && typecode != REAL_TYPE && typecode != POINTER_TYPE && typecode != COMPLEX_TYPE) { @@ -3321,7 +3437,12 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) pedwarn ("ISO C forbids conditional expr with only one void side"); result_type = void_type_node; } - else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) + /* APPLE LOCAL begin blocks 6065211 */ + else if ((code1 == POINTER_TYPE + || code1 == BLOCK_POINTER_TYPE) + && (code2 == POINTER_TYPE + || code2 == BLOCK_POINTER_TYPE)) + /* APPLE LOCAL end blocks 6065211 */ { if (comp_target_types (type1, type2)) result_type = common_pointer_type (type1, type2); @@ -3329,6 +3450,14 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) result_type = qualify_type (type2, type1); else if (null_pointer_constant_p (orig_op2)) result_type = qualify_type (type1, type2); + /* APPLE LOCAL begin blocks 6065211 */ + else if (code2 == BLOCK_POINTER_TYPE + && VOID_TYPE_P (TREE_TYPE (type1))) + result_type = type2; + else if (code1 == BLOCK_POINTER_TYPE + && VOID_TYPE_P (TREE_TYPE (type2))) + result_type = type1; + /* APPLE LOCAL end blocks 6065211 */ else if (VOID_TYPE_P (TREE_TYPE (type1))) { if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE) @@ -3371,7 +3500,31 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) } result_type = type2; } - + /* APPLE LOCAL begin radar 5732232 - blocks (C++ co) */ + /* APPLE LOCAL radar 5957801 */ + else if (code1 == BLOCK_POINTER_TYPE && code2 == INTEGER_TYPE) + { + if (!null_pointer_constant_p (orig_op2)) + error ("block pointer/integer type mismatch in conditional expression"); + else + { + op2 = convert (type1, null_pointer_node); + } + result_type = type1; + } + /* APPLE LOCAL radar 5957801 */ + else if (code2 == BLOCK_POINTER_TYPE && code1 == INTEGER_TYPE) + { + if (!null_pointer_constant_p (orig_op1)) + error ("block pointer/integer type mismatch in conditional expression"); + else + { + op1 = convert (type2, null_pointer_node); + } + result_type = type2; + } + + /* APPLE LOCAL end radar 5732232 - blocks (C++ co) */ if (!result_type) { if (flag_cond_mismatch) @@ -3510,6 +3663,12 @@ build_c_cast (tree type, tree expr) otype = TREE_TYPE (value); + /* APPLE LOCAL begin radar 5732232 - blocks */ + if (TREE_CODE (otype) == BLOCK_POINTER_TYPE && + TREE_CODE (type) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (type))) + return build1 (NOP_EXPR, type, value); + /* APPLE LOCAL end radar 5732232 - blocks */ + /* Optionally warn about potentially worrisome casts. */ if (warn_cast_qual @@ -3613,6 +3772,13 @@ build_c_cast (tree type, tree expr) pedwarn ("ISO C forbids conversion of object pointer to function pointer type"); ovalue = value; + /* APPLE LOCAL begin don't sign-extend pointers cast to integers */ + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (otype) == POINTER_TYPE + && TYPE_PRECISION (type) > TYPE_PRECISION (otype) + && TYPE_UNSIGNED (type)) + value = convert (c_common_type_for_size (POINTER_SIZE, 1), value); + /* APPLE LOCAL end don't sign-extend pointers cast to integers */ value = convert (type, value); /* Ignore any integer overflow caused by the cast. */ @@ -3641,6 +3807,78 @@ build_c_cast (tree type, tree expr) return value; } +/* APPLE LOCAL begin radar 5732232 - blocks (C++ cm) */ +static bool +functiontypes_are_block_compatible (tree f1, tree f2) +{ + tree arg1, arg2; + if (!types_are_block_compatible (TREE_TYPE (f1), TREE_TYPE (f2))) + return false; + arg1 = TYPE_ARG_TYPES (f1); + arg2 = TYPE_ARG_TYPES (f2); + /* APPLE LOCAL radar 6246965, 6196572 */ + return (!arg1) || (type_lists_compatible_p (arg1, arg2) == 1); +} + +static bool +types_are_block_compatible (tree lhptee, tree rhptee) +{ + if (TYPE_MAIN_VARIANT (lhptee) == TYPE_MAIN_VARIANT (rhptee)) + return true; + if (TREE_CODE (lhptee) == FUNCTION_TYPE && TREE_CODE (rhptee) == FUNCTION_TYPE) + return functiontypes_are_block_compatible (lhptee, rhptee); + /* APPLE LOCAL begin radar 5882266 (C++ cm) */ + if (TREE_CODE (lhptee) == POINTER_TYPE && TREE_CODE (rhptee) == POINTER_TYPE) + return types_are_block_compatible (TREE_TYPE (lhptee), TREE_TYPE (rhptee)); + /* APPLE LOCAL end radar 5882266 (C++ cm) */ + /* APPLE LOCAL begin radar 5988995 (C++ cm) */ + if (TREE_CODE (lhptee) == BLOCK_POINTER_TYPE + && TREE_CODE (rhptee) == BLOCK_POINTER_TYPE) + return types_are_block_compatible (TREE_TYPE (lhptee), TREE_TYPE (rhptee)); + /* APPLE LOCAL end radar 5988995 (C++ cm) */ + return false; +} + +/* APPLE LOCAL begin radar 5847213 - radar 6329245 */ +/** + build_block_call - Routine to build a block call; as in: + ((double(*)(void *, int))(BLOCK_PTR_EXP->__FuncPtr))(I, 42); + FNTYPE is the original function type derived from the syntax. + BLOCK_PTR_EXP is the block pointer variable. + PARAMS is the parameter list. +*/ +static tree +build_block_call (tree fntype, tree block_ptr_exp, tree params) +{ + tree function_ptr_exp; + tree typelist; + bool block_ptr_exp_side_effect = TREE_SIDE_EFFECTS (block_ptr_exp); + + /* First convert BLOCK_PTR_EXP to 'void *'. */ + block_ptr_exp = convert (ptr_type_node, block_ptr_exp); + gcc_assert (generic_block_literal_struct_type); + block_ptr_exp = convert (build_pointer_type (generic_block_literal_struct_type), + block_ptr_exp); + if (block_ptr_exp_side_effect) + block_ptr_exp = save_expr (block_ptr_exp); + + /* BLOCK_PTR_VAR->__FuncPtr */ + function_ptr_exp = build_component_ref (build_indirect_ref (block_ptr_exp, "->"), + get_identifier ("__FuncPtr")); + gcc_assert (function_ptr_exp); + + /* Build: result_type(*)(void *, function-arg-type-list) */ + typelist = TYPE_ARG_TYPES (fntype); + typelist = tree_cons (NULL_TREE, ptr_type_node, typelist); + fntype = build_function_type (TREE_TYPE (fntype), typelist); + function_ptr_exp = convert (build_pointer_type (fntype), function_ptr_exp); + params = tree_cons (NULL_TREE, block_ptr_exp, params); + return fold_build3 (CALL_EXPR, TREE_TYPE (fntype), + function_ptr_exp, params, NULL_TREE); +} +/* APPLE LOCAL end radar 5847213 - radar 6329245 */ +/* APPLE LOCAL end radar 5732232 - blocks (C++ cm) */ + /* Interpret a cast of expression EXPR to type TYPE. */ tree c_cast_expr (struct c_type_name *type_name, tree expr) @@ -3670,6 +3908,18 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) tree newrhs; tree lhstype = TREE_TYPE (lhs); tree olhstype = lhstype; + /* APPLE LOCAL __block assign sequence point 6639533 */ + bool insert_sequence_point = false; + + /* APPLE LOCAL begin radar 4426814 */ + if (c_dialect_objc () && flag_objc_gc) + { + /* APPLE LOCAL radar 5276085 */ + objc_weak_reference_expr (&lhs); + lhstype = TREE_TYPE (lhs); + olhstype = lhstype; + } + /* APPLE LOCAL end radar 4426814 */ /* Types that aren't fully specified cannot be used in assignments. */ lhs = require_complete_type (lhs); @@ -3678,11 +3928,46 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; + /* APPLE LOCAL radar 5285911 */ if (!lvalue_or_else (lhs, lv_assign)) return error_mark_node; STRIP_TYPE_NOPS (rhs); + /* APPLE LOCAL begin __block assign sequence point 6639533 */ + /* For byref = x;, we have to transform this into {( typeof(x) x' = + x; byref = x`; )} to ensure there is a sequence point before the + evaluation of the byref, inorder to ensure that the access + expression for byref doesn't start running before x is evaluated, + as it will access the __forwarding pointer and that must be done + after x is evaluated. */ + /* First we check to see if lhs is a byref... byrefs look like: + __Block_byref_X.__forwarding->x */ + if (TREE_CODE (lhs) == COMPONENT_REF) + { + tree inner = TREE_OPERAND (lhs, 0); + /* now check for -> */ + if (TREE_CODE (inner) == INDIRECT_REF) + { + inner = TREE_OPERAND (inner, 0); + if (TREE_CODE (inner) == COMPONENT_REF) + { + inner = TREE_OPERAND (inner, 0); + if (TREE_CODE (inner) == VAR_DECL + && COPYABLE_BYREF_LOCAL_VAR (inner)) + { + tree old_rhs = rhs; + /* then we save the rhs. */ + rhs = save_expr (rhs); + if (rhs != old_rhs) + /* And arrange for the sequence point to be inserted. */ + insert_sequence_point = true; + } + } + } + } + /* APPLE LOCAL end __block assign sequence point 6639533 */ + newrhs = rhs; /* If a binary op has been requested, combine the old LHS value with the RHS @@ -3694,6 +3979,21 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) newrhs = build_binary_op (modifycode, lhs, rhs, 1); } + /* APPLE LOCAL begin C* property (Radar 4436866) */ + if (c_dialect_objc ()) + { + result = objc_build_setter_call (lhs, newrhs); + if (result) + /* APPLE LOCAL begin __block assign sequence point 6639533 */ + { + if (insert_sequence_point) + result = build2 (COMPOUND_EXPR, TREE_TYPE (result), build1 (NOP_EXPR, void_type_node, rhs), result); + return result; + } + /* APPLE LOCAL end __block assign sequence point 6639533 */ + } + /* APPLE LOCAL end C* property (Radar 4436866) */ + /* Give an error for storing in something that is 'const'. */ if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype) @@ -3738,7 +4038,13 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { result = objc_generate_write_barrier (lhs, modifycode, newrhs); if (result) - return result; + /* APPLE LOCAL begin __block assign sequence point 6639533 */ + { + if (insert_sequence_point) + result = build2 (COMPOUND_EXPR, TREE_TYPE (result), build1 (NOP_EXPR, void_type_node, rhs), result); + return result; + } + /* APPLE LOCAL end __block assign sequence point 6639533 */ } /* Scan operands. */ @@ -3746,6 +4052,11 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs); TREE_SIDE_EFFECTS (result) = 1; + /* APPLE LOCAL begin __block assign sequence point 6639533 */ + if (insert_sequence_point) + result = build2 (COMPOUND_EXPR, TREE_TYPE (result), build1 (NOP_EXPR, void_type_node, rhs), result); + /* APPLE LOCAL end __block assign sequence point 6639533 */ + /* If we got the LHS in a different type for storing in, convert the result back to the nominal type of LHS so that the value we return always has the same type @@ -3859,7 +4170,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, break; } - objc_ok = objc_compare_types (type, rhstype, parmno, rname); + /* APPLE LOCAL radar 6231433 */ + objc_ok = objc_compare_types (type, rhstype, parmno, rname, "comparison"); } if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) @@ -3879,7 +4191,10 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, This code doesn't fully support references, it's just for the special case of va_start and va_copy. */ if (codel == REFERENCE_TYPE - && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1) + /* APPLE LOCAL begin radar 4502186 */ + && comptypes (objc_non_volatilized_type (TREE_TYPE (type)), + objc_non_volatilized_type (TREE_TYPE (rhs))) == 1) + /* APPLE LOCAL end radar 4502186 */ { if (!lvalue_p (rhs)) { @@ -4030,8 +4345,13 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE) && (coder == codel)) { - tree ttl = TREE_TYPE (type); - tree ttr = TREE_TYPE (rhstype); + /* APPLE LOCAL begin radar 4193359 */ + /* Types differing only by the presence of the 'volatile' + qualifier are acceptable if the 'volatile' has been added + in by the Objective-C EH machinery. */ + tree ttl = objc_non_volatilized_type (TREE_TYPE (type)); + tree ttr = objc_non_volatilized_type (TREE_TYPE (rhstype)); + /* APPLE LOCAL end radar 4193359 */ tree mvl = ttl; tree mvr = ttr; bool is_opaque_pointer; @@ -4123,10 +4443,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, { if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) { - /* Types differing only by the presence of the 'volatile' - qualifier are acceptable if the 'volatile' has been added - in by the Objective-C EH machinery. */ - if (!objc_type_quals_match (ttl, ttr)) + /* APPLE LOCAL begin radar 4193359 */ WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards " "qualifiers from pointer target type"), G_("assignment discards qualifiers " @@ -4207,6 +4524,43 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, return convert (type, rhs); } + /* APPLE LOCAL begin radar 5732232 - blocks */ + else if (codel == BLOCK_POINTER_TYPE && coder == INTEGER_TYPE) + { + if (!null_pointer_constant_p (rhs)) + { + error("invalid conversion %s integer 'int', expected block pointer", + errtype == ic_assign ? "assigning" : "initializing"); + return error_mark_node; + } + return build_int_cst (type, 0); + } + else if (codel == BLOCK_POINTER_TYPE && coder == codel) + { + tree lhptee = TREE_TYPE (type); + tree rhptee = TREE_TYPE(rhstype); + if (lhptee == rhptee) + return rhs; + if (!types_are_block_compatible (lhptee, rhptee)) + { + error ("incompatible block pointer types %s %qT, expected %qT", + errtype == ic_assign ? "assigning" : "initializing", + rhstype, type); + return error_mark_node; + } + return rhs; + } + /* APPLE LOCAL begin radar 5831855 */ + /* APPLE LOCAL radar 5878380 */ + else if (codel == BLOCK_POINTER_TYPE && POINTER_TYPE_P (rhstype) && + (VOID_TYPE_P (TREE_TYPE (rhstype)) || objc_is_id (rhstype))) + return convert (type, rhs); + /* APPLE LOCAL radar 5878380 */ + else if (coder == BLOCK_POINTER_TYPE && POINTER_TYPE_P (type) && + (VOID_TYPE_P (TREE_TYPE (type)) || objc_is_id (type))) + /* APPLE LOCAL end radar 5831855 */ + return convert (type, rhs); + /* APPLE LOCAL end radar 5732232 - blocks */ else if (codel == INTEGER_TYPE && coder == POINTER_TYPE) { WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes integer " @@ -4228,7 +4582,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, case ic_argpass_nonproto: /* ??? This should not be an error when inlining calls to unprototyped functions. */ - error ("incompatible type for argument %d of %qE", parmnum, rname); + error ("convert_for_assignment: incompatible type for argument %d of %qE", parmnum, rname); break; case ic_assign: error ("incompatible types in assignment"); @@ -4541,6 +4895,13 @@ maybe_warn_string_init (tree type, struct c_expr expr) pedwarn_init ("array initialized from parenthesized string constant"); } +/* APPLE LOCAL begin radar 5932809 - copyable byref blocks */ +tree do_digest_init (tree type, tree init) +{ + return digest_init (type, init, true, false); +} +/* APPLE LOCAL end radar 5932809 - copyable byref blocks */ + /* Digest the parser output INIT as an initializer for type TYPE. Return a C expression of type TYPE to represent the initial value. @@ -4750,7 +5111,10 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) } /* Added to enable additional -Wmissing-format-attribute warnings. */ - if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE) + /* APPLE LOCAL begin radar 5822844 */ + if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE || + TREE_CODE (TREE_TYPE (inside_init)) == BLOCK_POINTER_TYPE) + /* APPLE LOCAL end radar 5822844 */ inside_init = convert_for_assignment (type, inside_init, ic_init, NULL_TREE, NULL_TREE, 0); return inside_init; @@ -4759,6 +5123,8 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) /* Handle scalar types, including conversions. */ if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE + /* APPLE LOCAL radar 5732232 - blocks */ + || code == BLOCK_POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE || code == VECTOR_TYPE) { @@ -5475,6 +5841,16 @@ pop_init_level (int implicit) { if (constructor_erroneous) ret.value = error_mark_node; + /* APPLE LOCAL begin radar 4188876 */ + else if (!constructor_constant + && TREE_CODE (constructor_type) == VECTOR_TYPE && constructor_decl + && (TREE_CODE (TREE_TYPE (constructor_decl)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (constructor_decl)) == UNION_TYPE)) + { + error ("Initializer is a non-const vector type"); + ret.value = error_mark_node; + } + /* APPLE LOCAL end radar 4188876 */ else { ret.value = build_constructor (constructor_type, @@ -6943,14 +7319,85 @@ c_finish_goto_ptr (tree expr) return add_stmt (build1 (GOTO_EXPR, void_type_node, expr)); } +/* APPLE LOCAL begin radar 5732232 - blocks (C++ cm) */ +/** c_finish_block_return_stmt - Utilty routine to figure out block's return + type. + */ +static tree +c_finish_block_return_stmt (tree retval) +{ + tree valtype; + /* If this is the first return we've seen in the block, infer the type of + the block from it. */ + if (cur_block->return_type == NULL_TREE) + { + tree restype; + if (retval) + { + restype = TYPE_MAIN_VARIANT (TREE_TYPE (retval)); + TREE_TYPE (current_function_decl) + = build_function_type (restype, + TYPE_ARG_TYPES (TREE_TYPE (current_function_decl))); + TREE_TYPE (DECL_RESULT (current_function_decl)) = restype; + relayout_decl (DECL_RESULT (current_function_decl)); + } + else + restype = void_type_node; + + cur_block->return_type = restype; + } + + /* Verify that this result type matches the previous one. We are + pickier with blocks than for normal functions because this is a + new feature and we set the rules. */ + if (TREE_CODE (cur_block->return_type) == VOID_TYPE) + { + if (retval) + { + error ("void block should not return a value"); + retval = NULL_TREE; + } + return retval; + } + + if (!retval) + { + error ("non-void block should return a value"); + return error_mark_node; + } + + /* We have a non-void block with an expression, continue checking. */ + valtype = TREE_TYPE (retval); + + /* For now, restrict multiple return statements in a block to have + strict compatible types only. */ + if (!types_are_block_compatible (cur_block->return_type, valtype)) + error ("incompatible type returning %qT, expected %qT", + valtype, cur_block->return_type); + return retval; +} +/* APPLE LOCAL end radar 5732232 - blocks (C++ cm) */ + /* Generate a C `return' statement. RETVAL is the expression for what to return, or a null pointer for `return;' with no value. */ tree c_finish_return (tree retval) { - tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt; + /* APPLE LOCAL begin radar 5732232 - blocks */ + tree valtype, ret_stmt; bool no_warning = false; + + /* APPLE LOCAL radar 5822844 - radar 6185344 */ + if (cur_block && !cur_block->block_has_return_type) + { + retval = c_finish_block_return_stmt (retval); + if (retval == error_mark_node) + return NULL_TREE; + } + + valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); + /* APPLE LOCAL end radar 5732232 - blocks */ if (TREE_THIS_VOLATILE (current_function_decl)) warning (0, "function declared % has a % statement"); @@ -7027,7 +7474,15 @@ c_finish_return (tree retval) && !DECL_EXTERNAL (inner) && !TREE_STATIC (inner) && DECL_CONTEXT (inner) == current_function_decl) - warning (0, "function returns address of local variable"); + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cn) */ + { + if (TREE_CODE (valtype) == BLOCK_POINTER_TYPE) + /* APPLE LOCAL radar 6048570 */ + error ("returning block that lives on the local stack"); + else + warning (0, "function returns address of local variable"); + } + /* APPLE LOCAL end radar 5732232 - blocks (C++ cn) */ break; default: @@ -7295,6 +7750,11 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body, then we just build a jump back to the top. */ exit = build_and_jump (&LABEL_EXPR_LABEL (top)); +/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ + /* Add the attributes to the 'top' label. */ + decl_attributes (&LABEL_EXPR_LABEL (top), attrs, 0); + +/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ if (cond && !integer_nonzerop (cond)) { /* Canonicalize the loop condition to the end. This means @@ -7840,7 +8300,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, return error_mark_node; } - objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE); + objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE, "comparison"); switch (code) { @@ -7941,8 +8401,12 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case TRUTH_OR_EXPR: case TRUTH_XOR_EXPR: if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE + /* APPLE LOCAL radar 5928316 */ + || code0 == BLOCK_POINTER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE) && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE + /* APPLE LOCAL radar 5928316 */ + || code1 == BLOCK_POINTER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE)) { /* Result of these operations is always an int, @@ -8023,7 +8487,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE)) short_compare = 1; - else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) + /* APPLE LOCAL begin blocks 6065211 */ + else if ((code0 == POINTER_TYPE || code0 == BLOCK_POINTER_TYPE) + && (code1 == POINTER_TYPE || code1 == BLOCK_POINTER_TYPE)) + /* APPLE LOCAL end blocks 6065211 */ { tree tt0 = TREE_TYPE (type0); tree tt1 = TREE_TYPE (type1); @@ -8032,6 +8499,12 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, and both must be object or both incomplete. */ if (comp_target_types (type0, type1)) result_type = common_pointer_type (type0, type1); + /* APPLE LOCAL begin blocks 6065211 */ + else if (code1 == BLOCK_POINTER_TYPE && VOID_TYPE_P (tt0)) + ; + else if (code0 == BLOCK_POINTER_TYPE && VOID_TYPE_P (tt1)) + ; + /* APPLE LOCAL end blocks 6065211 */ else if (VOID_TYPE_P (tt0)) { /* op0 != orig_op0 detects the case of something @@ -8051,7 +8524,14 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, else /* Avoid warning about the volatile ObjC EH puts on decls. */ if (!objc_ok) - pedwarn ("comparison of distinct pointer types lacks a cast"); + /* APPLE LOCAL begin blocks 6065211 */ + { + if (code0 == BLOCK_POINTER_TYPE || code1 == BLOCK_POINTER_TYPE) + pedwarn ("comparison of distinct block types lacks a cast"); + else + pedwarn ("comparison of distinct pointer types lacks a cast"); + } + /* APPLE LOCAL end blocks 6065211 */ if (result_type == NULL_TREE) result_type = ptr_type_node; @@ -8088,6 +8568,12 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, result_type = type1; pedwarn ("comparison between pointer and integer"); } + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cl) */ + else if (code0 == BLOCK_POINTER_TYPE && null_pointer_constant_p (orig_op1)) + result_type = type0; + else if (code1 == BLOCK_POINTER_TYPE && null_pointer_constant_p (orig_op0)) + result_type = type1; + /* APPLE LOCAL end radar 5732232 - blocks (C++ cl) */ break; case LE_EXPR: diff --git a/contrib/gcc/c.opt b/contrib/gcc/c.opt index 1281794caab0..37885bcaa456 100644 --- a/contrib/gcc/c.opt +++ b/contrib/gcc/c.opt @@ -610,6 +610,12 @@ C++ ObjC++ Joined fnew-abi C++ ObjC++ +; APPLE LOCAL begin nested functions 4258406 4357979 +fnested-functions +C ObjC Var(flag_nested_functions) +Allow nested functions. +; APPLE LOCAL end nested functions 4258406 4357979 + fnext-runtime ObjC ObjC++ Generate code for NeXT (Apple Mac OS X) runtime environment @@ -644,6 +650,12 @@ fobjc-gc ObjC ObjC++ Var(flag_objc_gc) Enable garbage collection (GC) in Objective-C/Objective-C++ programs +; APPLE LOCAL begin radar 5811887 - blocks +fblocks +C ObjC C++ ObjC++ Var(flag_blocks) Init(-1) +Program supports c/objc extension blocks +; APPLE LOCAL end radar 5811887 - blocks + ; Nonzero means that we generate NeXT setjmp based exceptions. fobjc-sjlj-exceptions ObjC ObjC++ Var(flag_objc_sjlj_exceptions) Init(-1) diff --git a/contrib/gcc/calls.c b/contrib/gcc/calls.c index aa272dfdad26..ffed41dfe8a7 100644 --- a/contrib/gcc/calls.c +++ b/contrib/gcc/calls.c @@ -2051,7 +2051,8 @@ expand_call (tree exp, rtx target, int ignore) /* Operand 0 is a pointer-to-function; get the type of the function. */ funtype = TREE_TYPE (addr); - gcc_assert (POINTER_TYPE_P (funtype)); + /* APPLE LOCAL blocks */ + gcc_assert (POINTER_TYPE_P (funtype) || TREE_CODE (funtype) == BLOCK_POINTER_TYPE); funtype = TREE_TYPE (funtype); /* Munge the tree to split complex arguments into their imaginary diff --git a/contrib/gcc/cgraph.h b/contrib/gcc/cgraph.h index dccf3ff0223d..1e208ded9de4 100644 --- a/contrib/gcc/cgraph.h +++ b/contrib/gcc/cgraph.h @@ -302,6 +302,8 @@ struct cgraph_node *cgraph_master_clone (struct cgraph_node *); void cgraph_add_new_function (tree); /* In cgraphunit.c */ +/* APPLE LOCAL radar 6305545 */ +void lower_if_nested_functions (tree); bool cgraph_assemble_pending_functions (void); bool cgraph_varpool_assemble_pending_decls (void); void cgraph_finalize_function (tree, bool); diff --git a/contrib/gcc/cgraphunit.c b/contrib/gcc/cgraphunit.c index cc8b98f5480c..6beb42e9ba06 100644 --- a/contrib/gcc/cgraphunit.c +++ b/contrib/gcc/cgraphunit.c @@ -458,6 +458,19 @@ cgraph_lower_function (struct cgraph_node *node) node->lowered = true; } +/* APPLE LOCAL begin radar 6305545 */ +/** lower_if_nested_functions - This routine is called from cplus side only. + Its purpose is to lower block helper (or any other nested function) + which may have been nested in a constructor or destructor. We have to + do this because structors are cloned and are not lowered themselves (which + is the only way to lower the nested functions). */ +void +lower_if_nested_functions (tree decl) +{ + lower_nested_functions (decl, true); +} +/* APPLE LOCAL end radar 6305545 */ + /* DECL has been parsed. Take it, queue it, compile it at the whim of the logic in effect. If NESTED is true, then our caller cannot stand to have the garbage collector run at the moment. We would need to either create @@ -476,7 +489,8 @@ cgraph_finalize_function (tree decl, bool nested) node->local.finalized = true; node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; if (node->nested) - lower_nested_functions (decl); + /* APPLE LOCAL radar 6305545 */ + lower_nested_functions (decl, false); gcc_assert (!node->nested); /* If not unit at a time, then we need to create the call graph diff --git a/contrib/gcc/convert.c b/contrib/gcc/convert.c index 96bdf5d21bb4..897e01cfc69e 100644 --- a/contrib/gcc/convert.c +++ b/contrib/gcc/convert.c @@ -64,17 +64,66 @@ convert_to_pointer (tree type, tree expr) case BOOLEAN_TYPE: if (TYPE_PRECISION (TREE_TYPE (expr)) != POINTER_SIZE) expr = fold_build1 (NOP_EXPR, - lang_hooks.types.type_for_size (POINTER_SIZE, 0), + lang_hooks.types.type_for_size (POINTER_SIZE, 0), expr); return fold_build1 (CONVERT_EXPR, type, expr); - - default: - error ("cannot convert to a pointer type"); - return convert_to_pointer (type, integer_zero_node); + /* APPLE LOCAL begin blocks (C++ ck) */ + case BLOCK_POINTER_TYPE: + /* APPLE LOCAL begin radar 5809099 */ + if (objc_is_id (type) + || (TREE_CODE (type) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (type)))) + /* APPLE LOCAL end radar 5809099 */ + return fold_build1 (NOP_EXPR, type, expr); + /* APPLE LOCAL end blocks (C++ ck) */ + default: + error ("cannot convert to a pointer type"); + return convert_to_pointer (type, integer_zero_node); } } +/* APPLE LOCAL begin blocks (C++ ck) */ +tree +convert_to_block_pointer (tree type, tree expr) +{ + if (TREE_TYPE (expr) == type) + return expr; + + if (integer_zerop (expr)) + { + tree t = build_int_cst (type, 0); + if (TREE_OVERFLOW (expr) || TREE_CONSTANT_OVERFLOW (expr)) + t = force_fit_type (t, 0, TREE_OVERFLOW (expr), + TREE_CONSTANT_OVERFLOW (expr)); + return t; + } + + switch (TREE_CODE (TREE_TYPE (expr))) + { + case BLOCK_POINTER_TYPE: + return fold_build1 (NOP_EXPR, type, expr); + + case INTEGER_TYPE: + if (TYPE_PRECISION (TREE_TYPE (expr)) != POINTER_SIZE) + expr = fold_build1 (NOP_EXPR, + lang_hooks.types.type_for_size (POINTER_SIZE, 0), + expr); + return fold_build1 (CONVERT_EXPR, type, expr); + + case POINTER_TYPE: + /* APPLE LOCAL radar 5809099 */ + if (objc_is_id (TREE_TYPE (expr)) || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (expr)))) + return build1 (NOP_EXPR, type, expr); + /* fall thru */ + + default: + error ("cannot convert to a block pointer type"); + return convert_to_block_pointer (type, integer_zero_node); + } +} + +/* APPLE LOCAL end blocks (C++ ck) */ + /* Avoid any floating point extensions from EXP. */ tree strip_float_extensions (tree exp) @@ -459,6 +508,8 @@ convert_to_integer (tree type, tree expr) { case POINTER_TYPE: case REFERENCE_TYPE: + /* APPLE LOCAL radar 6035389 */ + case BLOCK_POINTER_TYPE: if (integer_zerop (expr)) return build_int_cst (type, 0); diff --git a/contrib/gcc/convert.h b/contrib/gcc/convert.h index 77722e4c40f3..5839afd297e9 100644 --- a/contrib/gcc/convert.h +++ b/contrib/gcc/convert.h @@ -26,5 +26,7 @@ extern tree convert_to_pointer (tree, tree); extern tree convert_to_real (tree, tree); extern tree convert_to_complex (tree, tree); extern tree convert_to_vector (tree, tree); +/* APPLE LOCAL blocks */ +extern tree convert_to_block_pointer (tree, tree); #endif /* GCC_CONVERT_H */ diff --git a/contrib/gcc/cp/ChangeLog.apple b/contrib/gcc/cp/ChangeLog.apple index a3eb8125a508..bd928a2ec612 100644 --- a/contrib/gcc/cp/ChangeLog.apple +++ b/contrib/gcc/cp/ChangeLog.apple @@ -1,9 +1,661 @@ +2008-11-07 Fariborz Jahanian + + Radar 5847976 + * decl.c (synth_block_byref_id_object_copy_func): Takes new 'flag' argument + and produces the new much simplified API. + (synth_block_byref_id_object_dispose_func): Ditto. + (new_block_byref_decl): Turn off -fobjc-gc so we don't get + bogus warning on field declared as __weak. + (init_byref_decl): Takes a new 'flag' argument and passes + it down to synth_block_byref_id_object_copy_func and + synth_block_byref_id_object_dispose_func. + (cp_finish_decl): Calculates the flag for the block + variable declaration and passes it down to init_byref_decl. + * parser.c (build_block_struct_initlist): Removes call to + copy_in_object (not needed). + (synth_copy_helper_block_func): Produce the new, simplified + API. + (synth_destroy_helper_block_func): Ditto. + (build_block_byref_decl): Copy over COPYABLE_WEAK_BLOCK flag. + +2008-10-31 Fariborz Jahanian + + Radar 6175959 + * parser.c (synth_copy_helper_block_func): Use the new API + _Block_object_assign for ObjC object copying. + (block_object_dispose): New + (synth_destroy_helper_block_func): Call block_object_dispose + to use new _Block_object_dispose API for ObjC object release. + +2008-10-27 Fariborz Jahanian + + Radar 6231433 + * typeck.c (objc_compare_types, objc_have_common_type): + Take an extra argument for better diagnostics. + * call.c: Ditto + +2010-03-16 Fariborz Jahanian + + Radar 7760213 + * semantics.c (get_final_block_variable): Diagnose + access of __block array. + +2010-03-12 Fariborz Jahanian + + Radar 7735196 + * cp/parser.c (build_block_struct_initlist): + Set BLOCK_USE_STRET flag in block descriptor for + blocks which return their aggregate value in memory. + +2010-03-05 Fariborz Jahanian + + Radar 7721728 + * semantics.c (get_final_block_variable): Diagnose + importation of copied-in variables. + +2009-02-11 Fariborz Jahanian + + Radar 6573923 + * decl.c (synth_block_byref_id_object_copy_func, + synth_block_byref_id_object_dispose_func): Set BLOCK_BYREF_CALLER + flag in call to copy/dispose helper functions. + +2009-02-11 Fariborz Jahanian + + Radar 6545782 + * semantics.c (get_final_block_variable): New + (finish_id_expression): Call get_final_block_variable. + +2008-10-27 Fariborz Jahanian + + Radar 6302949 + * parser.c (objc_cp_parser_at_property): Warn on missing + ',' separator for property attribute list. + +2008-10-24 Fariborz Jahanian + + Radar 6305545 + * semantics.c (expand_or_defer_fn): Lower nested function + of the structors. + +2008-10-24 Fariborz Jahanian + + Radar 5847213 (minor tweak) + * parser.c (build_block_descriptor_type): + Make descriptor_ptr_type and descriptor_ptr_type_with_copydispose + visible to pch. + +2008-10-17 Fariborz Jahanian + + Radar 6289031 + * decl.c: Removed all code related to + radar 6083129 (byref escapes). + +2008-10-15 Fariborz Jahanian + + Radar 6271728 + * parser.c (cp_parser_objc_method_definition_list): Method + definition always start with '{', or it is error. + +2008-10-14 Fariborz Jahanian + + Radar 6275956 + * semantics.c (finish_this_expr): Reference to "this" in a block + must be looked up. + +2008-10-10 Fariborz Jahanian + + Radar 5847213 - New Block ABI + + * typeck.c (build_block_call): New code gen for block call. + * parser.c (build_descriptor_block_decl) New + (build_block_struct_type): New block literal type. + (build_block_struct_initlist): New block literal initializers. + (build_block_literal_tmp): New block literal variable initialization. + (synth_copy_helper_block_func): Fixed a minor bug (unrelated to this radar). + (build_block_internal_types): Removed. + (build_block_descriptor_type): New routine to build build descriptor type. + (make_block_pointer_declarator): Unnecessary code is removed. + +2008-10-02 Fariborz Jahanian + + Radar 6246527 + * parser.c (cp_parser_block_literal_expr): Call to do the delta + on printf attribute. + +2008-09-30 Fariborz Jahanian + + Radar 6230297 + * c-parser.c (build_block_struct_initlist): 'trivial' + block temporary can be static as well. + (build_block_literal_tmp): Accomodate 'trivial' block + literal temporary variable as static. + +2008-09-30 Fariborz Jahanian + + Radar 6230297 + * parser.c (build_block_struct_initlist): 'trivial' + block temporary can be static as well. + (build_block_literal_tmp): Accomodate 'trivial' block + literal temporary variable as static. + +2008-09-30 Fariborz Jahanian + + Radar 6225809 + * parser.c (build_block_byref_decl): Add __block vaiables + to intervening blocks. + +2008-09-29 Fariborz Jahanian + + Radar 6154598 + tree.c (maybe_dummy_object): Build expression for + copied in "this" in the block. + +2008-09-26 Fariborz Jahanian + + Radar 6243400 + * parser.c (build_block_struct_type): Mostly rewritten + to use C++'s API for building block's main struct so structors + for those data members requiring them are synthesized and + used. + +2008-09-25 Fariborz Jahanian + + Radar 6244520 + * decl.c (new_block_byref_decl): New field added to + struct __Block_byref_x. + (init_byref_decl): Above field initialized to NULL. + +2008-09-25 Fariborz Jahanian + + Radar 6237713 + * parser.c (cp_parser_block_literal_expr): Parse + and set attribute on block literals. + +2008-09-16 Fariborz Jahanian + + Radar 6214617 + * parser.c (cp_block_requires_copying): New + (build_block_struct_type): Set BlockImportsCxxObjects flag. + (build_block_struct_initlist): Set BLOCK_HAS_CXX_OBJ if need be. + (synth_copy_helper_block_func): Call copy ctor if copied in object has one. + (synth_destroy_helper_block_func): Call dtor on cxx object. + +2008-09-12 Fariborz Jahanian + + Radar 6212722 (tweak) + * parser.c (build_block_ref_decl): Use decay_conversion. + +2008-09-09 Fariborz Jahanian + + Radar 6169580 + * decl.c (synth_block_byref_id_object_copy_func): Pass new flag + to finish_function. + (synth_block_byref_id_object_): Ditto. + (finish_function): Don't pop the nested class when synthesizing + block helpers. + * semantics.c (finish_id_expression): Added logic to attach + copied-in "this" to stand-alone field reference in a block. + * parser.c (synth_copy_helper_block_func, synth_destroy_helper_block_func): + Pass new flag to finish_function. + (cp_parser_block_literal_expr): When block is in non-static member + function, need to import "this" as a read-only copied in variable. + +2008-09-05 Fariborz Jahanian + + Radar 6169527 + * parser.c (build_block_struct_type): Set CLASSTYPE_AS_BASE. + (build_block_internal_types): Ditto. + (build_block_struct_initlist): Rewritten. + (build_block_literal_tmp): Rewritten. + (build_block_ref_decl): Just add copied-in variable to + the scope. + (declare_block_prologue_local_vars): Rewritten. + (declare_block_prologue_local_byref_vars): New + (block_build_prologue): Call declare_block_prologue_local_byref_vars + for byref variables. + +2008-09-03 Fariborz Jahanian + + Radar 6185344 + * typeck.c (check_return_expr): Added extra check + for return type checking. + * parser.c (cp_parser_direct_declarator): Added + extra check for type used as block return type. + (cp_parser_block_literal_expr): Parse and handle + user provided block return type syntax. + +2008-08-28 Fariborz Jahanian + + Radar 6160536 + * parser.c (cp_parser_block_literal_expr): Call build_block_helper_name + to get pretty name for block helper function. + +2008-08-28 Fariborz Jahanian + + Radar 6180456 + * decl.c (synth_block_byref_id_object_copy_func): Use different + API when copying __block object in c language. + (synth_block_byref_id_object_dispose_func): Use different + API when releasing a __block object in c. + * parser.c (synth_copy_helper_block_func): Refactored to + call build_block_byref_assign_copy_decl(). + +2008-08-27 Fariborz Jahanian + + Radar 6087117 + * typeck.c (convert_arguments): Takes an extra argument + for distiguinsing block call to function calls. + (build_function_call): Tell convert_arguments if we + are calling a block. + +2008-08-24 Caroline Tice + + Radar 6029624 + * call.c (objcp_reference_related_p): New + * cp-tree.h (objcp_reference_related_p): New decl. + +2008-06-05 Fariborz Jahanian + + Radar 5982990 + * parser.c (cp_parser_compound_statement): Take a new + argument which is used to call objc_mark_locals_volatile. + (cp_parser_primary_expression, cp_parser_statement, + etc.): add extra argument in calling cp_parser_compound_statement. + (cp_parser_objc_synchronized_statement): Passes + flag_objc_sjlj_exceptions as last argument in calling + cp_parser_compound_statement. + +2008-03-20 Fariborz Jahanian + + Radar 5802025 + * typeck.c (finish_class_member_access_expr): Generate getter call + from an OBJC_PROPERTY_REFERENCE_EXPR. + +2008-03-19 Fariborz Jahanian + + Radar 5733674 + * decl.c (expand_static_init): Generate write barrier for + static initialization in objective-c++ mode. + +2008-02-20 Fariborz Jahanian + + Radar 5732232 - code gen part 2. + * cp-lang.c (c_finish_return): Defined these + templates to get a clean compile. + +2007-08-22 Fariborz Jahanian + + Radar 4947311 + * parser.c (cp_parser_objc_protocol_declaration): Takes attribute list + as extra argument and passes it down to + objc_declare_protocols/objc_start_protocol. + (cp_parser_objc_class_interface): Now receives attribute list as input. + (cp_parser_objc_declaration): Parses attribute list and passes it down + to cp_parser_objc_class_interface/cp_parser_objc_protocol_declaration. + +2007-07-24 Fariborz Jahanian + + Radar 5355344 + * cp-tree.h (cp_objc_protocol_id_list): New declaration + * cp-lang.c (cp_objc_protocol_id_list): New stub + * parser.c (cp_parser_type_name): Added code to disambiguate + conditional from a protocol type. + (cp_parser_objc_tentative_protocol_refs_opt): New + +2007-07-13 Fariborz Jahanian + + Radar 5277239 + * parser.c (cp_parser_objc_reference_expression): New routine to + build a property reference expression. + (cp_objc_property_reference_prefix): New routine to recognize a + property dot syntax. + (cp_parser_primary_expression): Build a property reference expression + when a property dot-syntax is recognized. + (cp_parser_type_name): Exclude property dot-syntax from being recognized + as a type name. + (cp_parser_class_name): Exclude property dot-syntax from being recognized + as a class name. + +2007-07-10 Fariborz Jahanian + + Radar 5285911 + * typeck.c (finish_class_member_access_expr): Call + objc_build_property_reference_expr instead of objc_build_getter_call. + +2007-06-29 Fariborz Jahanian + + Radar 5276085 + * typeck.c (build_modify_expr): Call objc_weak_reference_expr + instead of objc_remove_weak_read. + * parser.c (cp_parser_cast_expression): Call + objc_build_weak_reference_tree instead of objc_generate_weak_read. + (cp_parser_cast_expression): Ditto. + +2007-05-18 Fariborz Jahanian + + Radar 5202926 + * mangle.c (write_mangled_name): Removed suppression in last patch. + +2007-04-20 Fariborz Jahanian + + Radar 5130983 + * c-common.h (enum lvalue_use): New enumerator lv_foreach + added. + * c-common.c (lvalue_error): Diagnose on lv_foreach. + +2007-04-20 Fariborz Jahanian + + Radar 5130983 + * parser.c (cp_parser_parse_foreach_stmt): Parse selector expression + as an expression. + (objc_foreach_stmt): Issue diagnostic on non-lavlue selector + expression. + +2007-03-29 Fariborz Jahanian + + Radar 4947014 - objc atomic property + * lex.c (RID_NONATOMIC): Add + * parser.c (objc_cp_parser_at_property): Recognize 'nonatomic' as + new property attribute. + +2007-03-29 Fariborz Jahanian + + Radar 4564694 + * lex.c (RID_AT_PACKAGE): Add + * parser.c (cp_lexer_get_preprocessor_token): Parse @package. + +2006-12-14 Fariborz Jahanian + + Radar 4854605 + * parser.c (objc_foreach_stmt): Set iterator + to nil. + +2006-09-01 Fariborz Jahanian + + Radar 4712269 + * typeck.c (build_unary_op): Call objc_build_incr_decr_setter_call + for potential ince/decr pre/post expressions involving properties. + +2006-07-21 Fariborz Jahanian + + Radar 4631818 + * parser.c (cp_parser_parse_foreach_stmt): New. + (cp_parser_iteration_statement): Remove old code. + Replace it with call to cp_parser_parse_foreach_stmt. + (cp_parser_simple_declaration): Remove old code. + (cp_parser_init_declarator): Remove old code. + +2006-08-31 Fariborz Jahanian + + Radar 4697411 + * typeck.c (build_class_member_access_expr): Call + objc_volatilize_component_ref. + +2006-07-18 Fariborz Jahanian + + Radar 4592503 + * class.c (layout_class_type): Check on illegal use of __weak + on struct fields. + * decl.c (start_decl): Check on illegal use of __weak on + variable declarations. + +2006-07-14 Fariborz Jahanian + + Radar 4621020 + * lex.c (reswords): Added entry for 'weak' attribute keyword. + * parser.c (objc_cp_parser_at_property): Recorgnize 'weak'attribute. + +2006-06-26 Fariborz Jahanian + + Radar 4591909 + * lex.c (reswords): New entry for 'dynamic' attribute. + * parser.c (objc_cp_parser_at_property): Change to parse new + attribute syntax. + +2006-05-18 Fariborz Jahanian + + Radar 4548636 (objc attributes on class) + * parser.c (objc_attr_follwed_by_at_keyword): New routine to disambiguate + attribute before a type and attribute before an @interface declaration.. + (cp_parser_declaration): Handle case of attribute list which can be + followed by an @interface. + (cp_parser_objc_class_interface): Parse possible attribute list before + parsing @interface. + (cp_parser_objc_declaration): Recognize 'attribute' as a valid token which + can start an @interface declaration. + +2006-05-16 Fariborz Jahanian + + Radar 4547045 + * parser.c (objc_foreach_stmt): Fix a thinko. + +2006-04-12 Fariborz Jahanian + + Radar 4507230 + * parser.c (objc_foreach_stmt): Check for valid objc + objects in foreach header. + +2006-04-06 Fariborz Jahanian + + Radar 4436866 + (Missing copies attribute) + * lex.c (reswords): New keyword 'copies' added. + * parser.c (objc_cp_parser_at_property): Parse 'copies' + attribute. + 2006-02-15 Fariborz Jahanian Radar 4445586 * semantics.c (begin_do_stmt): DO_STMT nodes take an extra argument to build. +2005-11-08 Fariborz Jahanian + + Radar 4330422 + + * typeck.c (comp_ptr_ttypes_real): Remove the hack. un-volatize the + artificially 'volatized' type before doing pointer comparison. + +2005-08-15 Ziemowit Laski + + Radar 4093475 + * parser.c (cp_parser_objc_interstitial_code): Catch stray + '{' and '}' tokens and issue appropriate errors. + (cp_parser_objc_method_prototype_list, + cp_parser_objc_method_definition_list): Bail out if end-of-file + is seen; issue error if trailing '@end' is not seen. + +2008-08-06 Fariborz Jahanian + + Radar 6040305 - work in progress. + * parser.c (clean_and_exit): Clean up if inside + a function. + (cp_parser_block_literal_expr): Set DECL_NO_STATIC_CHAIN + if inside a function. + +2008-08-05 Fariborz Jahanian + + Radar 6040305 - work in progress. + * decl.c (init_byref_decl): Generate c-style helper + functions for compose/dispose helpers. + +2008-08-04 Fariborz Jahanian + + Radar 6040305 - work in progress. + * decl.c (synth_block_byref_id_object_copy_func, + synth_block_byref_id_object_dispose_func, + block_start_struct, block_finish_struct, + new_block_byref_decl, init_byref_decl): New routines. + (cp_finish_decl): Build the APIed version of + a __byref local vriable. + * semantics.c (finish_id_expression): Add a __byref + variable to the list of such variables for current + block. + * parser.c (build_component_ref): Fix to make it work. + (cp_parser_block_literal_expr): Push/pop language-c, + set context of the helper function. + (declare_block_prologue_local_vars): Mend tree for + the built-in local variables in the helper prologue. + +2008-07-30 Fariborz Jahanian + + Radar 6040305 + * call.c (standard_conversion): Allow conversion of 'id' + type to a block pointer. + +2008-07-30 Fariborz Jahanian + + Radar 6040305 + * typeck.c (build_block_call): New + (build_function_call): Call build_block_call + for block calls. + * call.c (standard_conversion): Remove "void *" to + block pointer conversion. + +2008-07-29 Fariborz Jahanian + + Radar 6040305 + * call.c (standard_conversion): Allow assignment of + "void *" to block pointer object. + +2008-07-28 Fariborz Jahanian + + Radar 6040305 + * typeck.c (comptypes): block-pointer types' + return type get special treatment. + +2008-07-16 Eugene Marinelli + + Radar 5559195 + * decl.c (cxx_maybe_build_cleanup): When considering whether to + build a cleanup for a class type, use + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY and + CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE instead of + TYPE_HAS_NONTRIVIAL_DESTRUCTOR to determine whether it must be + output. + +2008-07-15 Eugene Marinelli + + Radar 5559195 + * cp-tree.h (struct lang_type_class): Add destructor_triviality_final + flag to mark when has_nontrivial_destructor_body and + destructor_nontrivial_because_of_base are final. Add accessor for + this flag. + * parser.c (cp_parser_statement_seq_opt): Use + CLASSTYPE_DESTRUCTOR_TRIVIALITY_FINAL to determine if + destructor should be checked for being empty, and set it if + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY is changed. + +2008-07-10 Eugene Marinelli + + Radar 5559195 + * init.c (push_base_cleanups): Check flags indicating whether + destructor of base class has a nontrivial body, has a base destructor + that must be called, or is private to determine whether it should be + called by the derived class. Set + CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE to 1 if it has + members that must be deleted. + * class.c (check_bases, finish_struct_bits, + add_implicitly_declared_members): Set + CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE and + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY based on base classes. + (check_methods): Set CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY to 1 + whenever a user-declared destructor is seen as a conservative + assumption. + * cp-tree.h (struct lang_type_class): Add + has_nontrivial_destructor_body and + destructor_nontrivial_because_of_base flags. Decrement remaining + dummy bits. Add accessors for these flags. + * parser.c (cp_parser_statement_seq_opt): Unmark + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY and then set it again only if + a statement is parsed. + +2007-05-07 Fariborz Jahanian + + Radar 4157812 + * parser.c (cp_parser_objc_method_keyword_params): Recognize optional + method argument attribute. + +2007-03-21 Fariborz Jahanian + + Radar 2848255 + * except.c (do_begin_catch): Take a new argument to decide + to call objc_begin_catch for objc exceptions. + (objcp_build_eh_type_type): New. + (do_end_catch): Call objc_end_catch for objc type + exceptions. + (expand_start_catch_block): Add new argument to do_begin_catch call. + (build_throw): Call objc_throw_exception for throwing objc type objects. + * cp-tree.h (objc2_valid_objc_catch_type, objcp_build_eh_type_type): + New extern decl. + * parser.c (cp_parser_objc_try_catch_finally_stateme): Add syntax for + @catch(...). + +2006-04-26 Fariborz Jahanian + + Radar 3803157 (method attributes) + * parser.c (cp_parser_objc_maybe_attributes): New. + (cp_parser_objc_method_keyword_params): Parse attributes at end + of method declaration. + (cp_parser_objc_method_tail_params_opt): Parse attributes after + '...'. + (cp_parser_objc_method_signature): Retreive method attribute for + the caller. + (cp_parser_objc_method_prototype_list): Pass new arg. to + cp_parser_objc_method_signature and pass attributes to + objc_add_method_declaration. + (cp_parser_objc_method_definition_list): Pass new arg. to + cp_parser_objc_method_signature and pass attributes to + objc_start_method_definition. + +2006-03-27 Fariborz Jahanian + + Radar 4133425 + * lex.c (unqualified_name_lookup_error): Issue diagnostic + for private 'ivar' access. + +2006-02-02 Fariborz Jahanian + + Radar 4426814 + * typeck.c (build_modify_expr): Undo call to objc_read_weak + on LHS of the assignment. + * parser.c (cp_parser_cast_expression): Central place to add + objc_read_weak call on expressions of __weak objects. + +2005-12-15 Fariborz Jahanian + + Radar 4229905 + * typeck.c (composite_pointer_type): Call objc_have_common_type + when comparing two objective-c pointer types. + +2005-10-17 Fariborz Jahanian + + Radar 4290840 + + * parser.c (cp_parser_objc_method_keyword_params): Check for valid + method parameters and issue error. + (cp_parser_objc_method_definition_list): Check for invalid tokens + which cannot start a function definition. + +2005-08-02 Ziemowit Laski + + Radar 4185810 + * parser.c (cp_parser_compound_statement): Continue + parsing even if the initial '{' is missing; an error + message is already being produced. + (cp_parser_statement_seq_opt): In addition to '}' and + end-of-file, a statement sequence may also be terminated + by a stray 'else' or '@end'. + # APPLE LOCAL begin for-fsf-4_4 3274130 5295549 2007-08-03 Geoffrey Keating diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c index 24b5d1fc3ec2..1de6a4748ab7 100644 --- a/contrib/gcc/cp/call.c +++ b/contrib/gcc/cp/call.c @@ -281,7 +281,8 @@ build_call (tree function, tree parms) function = build_addr_func (function); - gcc_assert (TYPE_PTR_P (TREE_TYPE (function))); + /* APPLE LOCAL blocks 6040305 */ + gcc_assert (TYPE_PTR_P (TREE_TYPE (function)) || TREE_CODE (TREE_TYPE (function)) == BLOCK_POINTER_TYPE); fntype = TREE_TYPE (TREE_TYPE (function)); gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE || TREE_CODE (fntype) == METHOD_TYPE); @@ -657,7 +658,8 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, if (same_type_p (from, to)) return conv; - if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to)) + /* APPLE LOCAL blocks 6040305 (ck) */ + if ((tcode == POINTER_TYPE || tcode == BLOCK_POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to)) && expr && null_ptr_cst_p (expr)) conv = build_conv (ck_std, to, conv); else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE) @@ -810,6 +812,8 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, if (ARITHMETIC_TYPE_P (from) || fcode == ENUMERAL_TYPE || fcode == POINTER_TYPE + /* APPLE LOCAL blocks 6040305 (cl) */ + || fcode == BLOCK_POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (from)) { conv = build_conv (ck_std, to, conv); @@ -877,6 +881,15 @@ reference_related_p (tree t1, tree t2) && DERIVED_FROM_P (t1, t2))); } +/* APPLE LOCAL begin radar 6029624 */ +/* Used in objective-c++, same as reference_related_p */ +bool +objcp_reference_related_p (tree t1, tree t2) +{ + return reference_related_p (t1, t2); +} +/* APPLE LOCAL end radar 6029624 */ + /* Returns nonzero if T1 is reference-compatible with T2. */ static bool @@ -3520,10 +3533,19 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) cv-qualification of either the second or the third operand. The result is of the common type. */ else if ((null_ptr_cst_p (arg2) - && (TYPE_PTR_P (arg3_type) || TYPE_PTR_TO_MEMBER_P (arg3_type))) + /* APPLE LOCAL begin blocks 6040305 (co) */ + && (TYPE_PTR_P (arg3_type) || TYPE_PTR_TO_MEMBER_P (arg3_type) + || TREE_CODE (arg3_type) == BLOCK_POINTER_TYPE)) + /* APPLE LOCAL end blocks 6040305 (co) */ || (null_ptr_cst_p (arg3) - && (TYPE_PTR_P (arg2_type) || TYPE_PTR_TO_MEMBER_P (arg2_type))) - || (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type)) + /* APPLE LOCAL begin blocks 6040305 (co) */ + && (TYPE_PTR_P (arg2_type) || TYPE_PTR_TO_MEMBER_P (arg2_type) + || TREE_CODE (arg2_type) == BLOCK_POINTER_TYPE)) + || ((TYPE_PTR_P (arg2_type) + || TREE_CODE (arg2_type) == BLOCK_POINTER_TYPE) + && (TYPE_PTR_P (arg3_type) + || TREE_CODE (arg3_type) == BLOCK_POINTER_TYPE)) + /* APPLE LOCAL end blocks 6040305 (co) */ || (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type)) || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type))) { diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c index 1f30524acf80..047ce1791742 100644 --- a/contrib/gcc/cp/class.c +++ b/contrib/gcc/cp/class.c @@ -1282,6 +1282,12 @@ check_bases (tree t, TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype); + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + if (CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (basetype) + || CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE (basetype)) + CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE (t) = 1; + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ + TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype); TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype); @@ -1440,6 +1446,13 @@ finish_struct_bits (tree t) TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants) = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t); + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (variants) = + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (t); + CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE (variants) = + CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE (t); + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ + TYPE_POLYMORPHIC_P (variants) = TYPE_POLYMORPHIC_P (t); TYPE_BINFO (variants) = TYPE_BINFO (t); @@ -2540,6 +2553,13 @@ add_implicitly_declared_members (tree t, { bool lazy_p = true; + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + /* Since this is an empty destructor, it can only be nontrivial + because one of its base classes has a destructor that must be + called. */ + CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE (t) = 1; + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ + if (TYPE_FOR_JAVA (t)) /* If this a Java class, any non-trivial destructor is invalid, even if compiler-generated. Therefore, if the @@ -3729,7 +3749,16 @@ check_methods (tree t) } /* All user-declared destructors are non-trivial. */ if (DECL_DESTRUCTOR_P (x)) - TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1; + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + { + TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1; + + /* Conservatively assume that destructor body is nontrivial. Will + be unmarked during parsing of function body if it happens to be + trivial. */ + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (t) = 1; + } + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ } } diff --git a/contrib/gcc/cp/cp-gimplify.c b/contrib/gcc/cp/cp-gimplify.c index 08d4ca02fbcc..879356a628e9 100644 --- a/contrib/gcc/cp/cp-gimplify.c +++ b/contrib/gcc/cp/cp-gimplify.c @@ -200,8 +200,20 @@ gimplify_cp_loop (tree cond, tree body, tree incr, tree attrs, stmt_list = NULL_TREE; entry = NULL_TREE; - break_block = begin_bc_block (bc_break); - cont_block = begin_bc_block (bc_continue); + /* APPLE LOCAL begin C* language */ + /* Order of label addition to stack is important for objc's foreach-stmt. */ + /* APPLE LOCAL radar 4667060 */ + if (inner_foreach == integer_zero_node) + { + cont_block = begin_bc_block (bc_continue); + break_block = begin_bc_block (bc_break); + } + else + { + break_block = begin_bc_block (bc_break); + cont_block = begin_bc_block (bc_continue); + } + /* APPLE LOCAL end C* language */ /* If condition is zero don't generate a loop construct. */ if (cond && integer_zerop (cond)) @@ -252,10 +264,19 @@ gimplify_cp_loop (tree cond, tree body, tree incr, tree attrs, } } + /* APPLE LOCAL begin radar 4547045 */ + /* Pop foreach's inner loop break label so outer loop's + break label becomes target of inner loop body's break statements. + */ + t = NULL_TREE; gimplify_stmt (&body); gimplify_stmt (&incr); body = finish_bc_block (bc_continue, cont_block, body); + /* APPLE LOCAL begin radar 4547045 */ + /* Push back inner loop's own 'break' label so rest + of code works seemlessly. */ + /* APPLE LOCAL radar 4667060 */ append_to_statement_list (top, &stmt_list); append_to_statement_list (body, &stmt_list); diff --git a/contrib/gcc/cp/cp-objcp-common.c b/contrib/gcc/cp/cp-objcp-common.c index f40be9696956..d42a735aef09 100644 --- a/contrib/gcc/cp/cp-objcp-common.c +++ b/contrib/gcc/cp/cp-objcp-common.c @@ -259,5 +259,37 @@ init_shadowed_var_for_decl (void) tree_map_eq, 0); } +/* APPLE LOCAL begin radar 5741070 */ +/* Given an IDENTIFIER tree for a class interface, find (if possible) and + return the record type for the class interface. */ + +tree +c_return_interface_record_type (tree typename) +{ + enum tree_code_class class; + enum tree_code code; + tree retval = NULL; + + if (typename == NULL) + return retval; + + code = TREE_CODE (typename); + class = TREE_CODE_CLASS (code); + + if (code != IDENTIFIER_NODE + || class != tcc_exceptional) + return retval; + + if (TREE_TYPE (typename) + && TREE_CODE (TREE_TYPE (typename)) == RECORD_TYPE) + retval = TREE_TYPE (typename); + + if (retval + && TREE_CODE (retval) != RECORD_TYPE) + retval = NULL; + + return retval; +} +/* APPLE LOCAL end radar 5741070 */ #include "gt-cp-cp-objcp-common.h" diff --git a/contrib/gcc/cp/cp-objcp-common.h b/contrib/gcc/cp/cp-objcp-common.h index f420d93b191f..5800d3493dde 100644 --- a/contrib/gcc/cp/cp-objcp-common.h +++ b/contrib/gcc/cp/cp-objcp-common.h @@ -166,4 +166,10 @@ extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t, #undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE #define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE cxx_omp_privatize_by_reference +/* APPLE LOCAL begin radar 6353006 */ +#undef LANG_HOOKS_BUILD_GENERIC_BLOCK_STRUCT_TYPE +#define LANG_HOOKS_BUILD_GENERIC_BLOCK_STRUCT_TYPE \ + c_build_generic_block_struct_type +/* APPLE LOCAL end radar 6353006 */ + #endif /* GCC_CP_OBJCP_COMMON */ diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h index 6593832c6d70..1dafeb99e0c3 100644 --- a/contrib/gcc/cp/cp-tree.h +++ b/contrib/gcc/cp/cp-tree.h @@ -1052,6 +1052,13 @@ struct lang_type_class GTY(()) unsigned has_complex_assign_ref : 1; unsigned non_aggregate : 1; + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + unsigned has_nontrivial_destructor_body : 1; + unsigned destructor_nontrivial_because_of_base : 1; + unsigned destructor_triviality_final : 1; + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ + + /* When adding a flag here, consider whether or not it ought to apply to a template instance if it applies to the template. If so, make sure to copy it in instantiate_class_template! */ @@ -1059,7 +1066,9 @@ struct lang_type_class GTY(()) /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 12; + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + unsigned dummy : 10; + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ tree primary_base; VEC(tree_pair_s,gc) *vcall_indices; @@ -2439,6 +2448,8 @@ extern void decl_shadowed_for_var_insert (tree, tree); || TREE_CODE (TYPE) == ENUMERAL_TYPE \ || ARITHMETIC_TYPE_P (TYPE) \ || TYPE_PTR_P (TYPE) \ + /* APPLE LOCAL blocks 6040305 */ \ + || TREE_CODE (TYPE) == BLOCK_POINTER_TYPE \ || TYPE_PTRMEMFUNC_P (TYPE)) /* [dcl.init.aggr] @@ -2520,6 +2531,20 @@ extern void decl_shadowed_for_var_insert (tree, tree); #define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \ (TYPE_LANG_FLAG_4 (NODE)) +/* APPLE LOCAL begin omit calls to empty destructors 5559195 */ +/* One if the body of the destructor of class type NODE has been shown to do + nothing, else zero. */ +#define CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_nontrivial_destructor_body) + +/* One if destructor of this type must be called by its base classes because + one of its base classes' destructors must be called. */ +#define CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->destructor_nontrivial_because_of_base) + +/* One if the values of CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE + and CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY are final. */ +#define CLASSTYPE_DESTRUCTOR_TRIVIALITY_FINAL(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->destructor_triviality_final) +/* APPLE LOCAL end omit calls to empty destructors 5559195 */ + /* Nonzero for class type means that copy initialization of this type can use a bitwise copy. */ #define TYPE_HAS_TRIVIAL_INIT_REF(NODE) \ @@ -3704,6 +3729,8 @@ typedef enum cp_declarator_kind { cdk_pointer, cdk_reference, cdk_ptrmem, + /* APPLE LOCAL blocks 6040305 (ch) */ + cdk_block_pointer, cdk_error } cp_declarator_kind; @@ -3772,6 +3799,13 @@ struct cp_declarator { /* For cdk_ptrmem, the class type containing the member. */ tree class_type; } pointer; + /* APPLE LOCAL begin blocks 6040305 (ch) */ + /* For cdk_block_pointer. */ + struct { + /* The cv-qualifiers for the pointer. */ + cp_cv_quals qualifiers; + } block_pointer; + /* APPLE LOCAL end blocks 6040305 (ch) */ } u; }; @@ -3922,6 +3956,8 @@ extern tree push_throw_library_fn (tree, tree); extern tree check_tag_decl (cp_decl_specifier_seq *); extern tree shadow_tag (cp_decl_specifier_seq *); extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *); +/* APPLE LOCAL 6339747 */ +extern tree grokblockdecl (cp_decl_specifier_seq *, const cp_declarator *); extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *); extern void start_decl_1 (tree, bool); extern void cp_finish_decl (tree, tree, bool, tree, int); @@ -4600,5 +4636,11 @@ extern void cp_genericize (tree); extern void cp_cpp_error (cpp_reader *, int, const char *, va_list *) ATTRIBUTE_GCC_CXXDIAG(3,0); +/* APPLE LOCAL radar 5741070 */ +extern tree c_return_interface_record_type (tree); +/* APPLE LOCAL begin blocks 6040305 (cg) */ +extern cp_declarator* make_block_pointer_declarator (tree, cp_cv_quals, + cp_declarator *); +/* APPLE LOCAL end blocks 6040305 (cg) */ #endif /* ! GCC_CP_TREE_H */ diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c index 40e6c9221c9f..e7cb9726cd5d 100644 --- a/contrib/gcc/cp/decl.c +++ b/contrib/gcc/cp/decl.c @@ -52,7 +52,8 @@ Boston, MA 02110-1301, USA. */ #include "timevar.h" #include "tree-flow.h" -static tree grokparms (cp_parameter_declarator *, tree *); +/* APPLE LOCAL blocks 6040305 (ce) */ +tree grokparms (cp_parameter_declarator *, tree *); static const char *redeclaration_error_message (tree, tree); static int decl_jump_unsafe (tree); @@ -3800,7 +3801,26 @@ shadow_tag (cp_decl_specifier_seq *declspecs) return t; } - + +/* APPLE LOCAL begin blocks 6339747 */ +/* Decode a block literal type, such as "int **", returning a ...FUNCTION_DECL node. */ + +tree +grokblockdecl (cp_decl_specifier_seq *type_specifiers, + const cp_declarator *declarator) +{ + tree decl; + tree attrs = type_specifiers->attributes; + + type_specifiers->attributes = NULL_TREE; + + decl = grokdeclarator (declarator, type_specifiers, BLOCKDEF, 0, &attrs); + if (attrs) + cplus_decl_attributes (&decl, attrs, 0); + return decl; +} +/* APPLE LOCAL end blocks 6339747 */ + /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ tree @@ -5002,10 +5022,15 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec) if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl)) { gcc_assert (TREE_STATIC (decl)); + /* APPLE LOCAL begin templated static data 6298605 */ /* An in-class declaration of a static data member should be - external; it is only a declaration, and not a definition. */ - if (init == NULL_TREE && DECL_INITIAL (decl) == NULL_TREE) + external if the decl is accessible from outside this + translation unit (eg something not in an anonymous + namespace); it is only a declaration, and not a + definition. */ + if (init == NULL_TREE && TREE_PUBLIC (decl)) gcc_assert (DECL_EXTERNAL (decl)); + /* APPLE LOCAL end templated static data 6298605 */ } /* We don't create any RTL for local variables. */ @@ -5160,6 +5185,367 @@ value_dependent_init_p (tree init) return false; } +/* APPLE LOCAL begin blocks 6040305 (cr) */ +#define BLOCK_ALIGN_MAX 18 +static tree block_byref_id_object_copy[BLOCK_BYREF_CURRENT_MAX*(BLOCK_ALIGN_MAX+1)]; +static tree block_byref_id_object_dispose[BLOCK_BYREF_CURRENT_MAX*(BLOCK_ALIGN_MAX+1)]; + +/** + This routine builds: + + void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, + struct Block_byref_id_object *src) { + _Block_object_assign (&_dest->object, _src->object, BLOCK_FIELD_IS_OBJECT[|BLOCK_FIELD_IS_WEAK]) // objects + _Block_object_assign(&_dest->object, _src->object, BLOCK_FIELD_IS_BLOCK[|BLOCK_FIELD_IS_WEAK]) // blocks + } */ +static void +synth_block_byref_id_object_copy_func (int flag, int kind) +{ + tree stmt; + tree dst_arg, src_arg; + tree dst_obj, src_obj; + tree call_exp; + + gcc_assert (block_byref_id_object_copy[kind]); + /* Set up: (void* _dest, void*_src) parameters. */ + dst_arg = build_decl (PARM_DECL, get_identifier ("_dst"), + ptr_type_node); + TREE_USED (dst_arg) = 1; + DECL_ARG_TYPE (dst_arg) = ptr_type_node; + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + ptr_type_node); + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = ptr_type_node; + /* arg_info = xcalloc (1, sizeof (struct c_arg_info)); */ + TREE_CHAIN (dst_arg) = src_arg; + /* arg_info->parms = dst_arg; */ + /* arg_info->types = tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, + ptr_type_node, + NULL_TREE)); */ + DECL_ARGUMENTS (block_byref_id_object_copy[kind]) = dst_arg; + /* function header synthesis. */ + push_function_context (); + /* start_block_helper_function (block_byref_id_object_copy[kind], true); */ + /* store_parm_decls_from (arg_info); */ + start_preparsed_function (block_byref_id_object_copy[kind], + /*attrs*/NULL_TREE, + SF_PRE_PARSED); + + /* Body of the function. */ + stmt = begin_compound_stmt (BCS_FN_BODY); + /* Build dst->object */ + dst_obj = build_indirect_object_id_exp (dst_arg); + + + /* src_obj is: _src->object. */ + src_obj = build_indirect_object_id_exp (src_arg); + /* APPLE LOCAL begin radar 6180456 */ + /* _Block_object_assign (&_dest->object, _src->object, BLOCK_FIELD_IS_OBJECT) or: + _Block_object_assign (&_dest->object, _src->object, BLOCK_FIELD_IS_BLOCK) */ + /* APPLE LOCAL begin radar 6573923 */ + /* Also add the new flag when calling _Block_object_dispose + from byref dispose helper. */ + flag |= BLOCK_BYREF_CALLER; + /* APPLE LOCAL end radar 6573923 */ + call_exp = build_block_object_assign_call_exp (build_fold_addr_expr (dst_obj), src_obj, flag); + add_stmt (call_exp); + /* APPLE LOCAL end radar 6180456 */ + + finish_compound_stmt (stmt); + /* APPLE LOCAL radar 6169580 */ + finish_function (4); + pop_function_context (); +} + +/** + This routine builds: + + void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { + _Block_object_dispose(_src->object, BLOCK_FIELD_IS_OBJECT[|BLOCK_FIELD_IS_WEAK]) // objects + _Block_object_dispose(_src->object, BLOCK_FIELD_IS_BLOCK[|BLOCK_FIELD_IS_WEAK]) // blocks + } */ +static void synth_block_byref_id_object_dispose_func (int flag, int kind) +{ + tree stmt; + tree src_arg, src_obj, rel_exp; + + gcc_assert (block_byref_id_object_dispose[kind]); + /* Set up: (void *_src) parameter. */ + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + ptr_type_node); + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = ptr_type_node; + /* arg_info = xcalloc (1, sizeof (struct c_arg_info)); + arg_info->parms = src_arg; + arg_info->types = tree_cons (NULL_TREE, ptr_type_node, + NULL_TREE); */ + DECL_ARGUMENTS (block_byref_id_object_dispose[kind]) = src_arg; + /* function header synthesis. */ + push_function_context (); + /* start_block_helper_function (block_byref_id_object_dispose[kind], true); */ + /* store_parm_decls_from (arg_info); */ + start_preparsed_function (block_byref_id_object_dispose[kind], + /*attrs*/NULL_TREE, + SF_PRE_PARSED); + + /* Body of the function. */ + stmt = begin_compound_stmt (BCS_FN_BODY); + src_obj = build_indirect_object_id_exp (src_arg); + + /* APPLE LOCAL begin radar 6180456 */ + /* _Block_object_dispose(_src->object, BLOCK_FIELD_IS_OBJECT) or: + _Block_object_dispose(_src->object, BLOCK_FIELD_IS_BLOCK) */ + /* APPLE LOCAL begin radar 6573923 */ + /* Also add the new flag when calling _Block_object_dispose + from byref dispose helper. */ + flag |= BLOCK_BYREF_CALLER; + /* APPLE LOCAL end radar 6573923 */ + rel_exp = build_block_object_dispose_call_exp (src_obj, flag); + /* APPLE LOCAL end radar 6180456 */ + add_stmt (rel_exp); + + finish_compound_stmt (stmt); + /* APPLE LOCAL radar 6169580 */ + finish_function (4); + pop_function_context (); +} + +static tree +block_start_struct (tree name) +{ + tree s; + /* The idea here is to mimic the actions that the C++ parser takes when + constructing 'extern "C" struct NAME {'. */ + push_lang_context (lang_name_c); + + s = xref_tag (record_type, name, ts_global, 0); + CLASSTYPE_DECLARED_CLASS (s) = 0; /* this is a 'struct', not a 'class'. */ + xref_basetypes (s, NULL_TREE); /* no base classes here! */ + + return begin_class_definition (s, NULL_TREE); +} + +static tree +block_finish_struct (tree t, tree fieldlist) +{ + tree field, next_field; + + for (field = fieldlist; field; field = next_field) + { + next_field = TREE_CHAIN (field); /* insert one field at a time; */ + TREE_CHAIN (field) = NULL_TREE; /* otherwise, grokfield croaks. */ + finish_member_declaration (field); + } + t = finish_struct (t, NULL); + pop_lang_context (); + + return t; +} + +/* new_block_byref_decl - This routine changes a 'typex x' declared variable into: + + struct __Block_byref_x { + // APPLE LOCAL radar 6244520 + void *__isa; // NULL for everything except __weak pointers + struct Block_byref_x *__forwarding; + int32_t __flags; + int32_t __size; + void *__ByrefKeepFuncPtr; // Only if variable is __block ObjC object + void *__ByrefDestroyFuncPtr; // Only if variable is __block ObjC object + typex x; + } x; +*/ + +static tree +new_block_byref_decl (tree decl) +{ + static int unique_count; + /* APPLE LOCAL radar 5847976 */ + int save_flag_objc_gc; + tree Block_byref_type; + tree fields = NULL_TREE, field; + const char *prefix = "__Block_byref_"; + char *string = (char*)alloca (strlen (IDENTIFIER_POINTER (DECL_NAME (decl))) + + strlen (prefix) + 8 /* to hold the count */); + + sprintf (string, "%s%d_%s", prefix, ++unique_count, + IDENTIFIER_POINTER (DECL_NAME (decl))); + + push_to_top_level (); + + /* Block_byref_type = start_struct (RECORD_TYPE, get_identifier (string)); */ + Block_byref_type = block_start_struct (get_identifier (string)); + + /* APPLE LOCAL begin radar 6244520 */ + /* void *__isa; */ + field = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node); + fields = field; + /* APPLE LOCAL end radar 6244520 */ + + /* struct Block_byref_x *__forwarding; */ + field = build_decl (FIELD_DECL, get_identifier ("__forwarding"), + build_pointer_type (Block_byref_type)); + /* APPLE LOCAL radar 6244520 */ + chainon (fields, field); + + /* int32_t __flags; */ + field = build_decl (FIELD_DECL, get_identifier ("__flags"), + unsigned_type_node); + chainon (fields, field); + + /* int32_t __size; */ + field = build_decl (FIELD_DECL, get_identifier ("__size"), + unsigned_type_node); + chainon (fields, field); + + if (COPYABLE_BYREF_LOCAL_NONPOD (decl)) + { + /* void *__ByrefKeepFuncPtr; */ + field = build_decl (FIELD_DECL, get_identifier ("__ByrefKeepFuncPtr"), + ptr_type_node); + chainon (fields, field); + + /* void *__ByrefDestroyFuncPtr; */ + field = build_decl (FIELD_DECL, get_identifier ("__ByrefDestroyFuncPtr"), + ptr_type_node); + chainon (fields, field); + } + + /* typex x; */ + field = build_decl (FIELD_DECL, DECL_NAME (decl), TREE_TYPE (decl)); + chainon (fields, field); + + /* APPLE LOCAL begin radar 5847976 */ + /* Hack so we don't issue warning on a field_decl having __weak attribute */ + save_flag_objc_gc = flag_objc_gc; + flag_objc_gc = 0; + /* finish_struct (Block_byref_type, field_decl_chain, NULL_TREE); */ + block_finish_struct (Block_byref_type, fields); + flag_objc_gc = save_flag_objc_gc; + /* APPLE LOCAL end radar 5847976 */ + pop_from_top_level (); + + TREE_TYPE (decl) = Block_byref_type; + /* Force layout_decl to recompute these fields. */ + DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0; + layout_decl (decl, 0); + return decl; +} + +/* init_byref_decl - This routine builds the initializer for the __Block_byref_x + type in the form of: + { NULL, &x, 0, sizeof(struct __Block_byref_x), initializer-expr}; + + or: + { NULL, &x, 0, sizeof(struct __Block_byref_x)}; + when INIT is NULL_TREE + + For __block ObjC objects, it also adds "byref_keep" and "byref_destroy" + Funtion pointers. So the most general initializers would be: + + { NULL, &x, 0, sizeof(struct __Block_byref_x), &byref_keep, &byref_destroy, + &initializer-expr}; + */ +static tree +init_byref_decl (tree decl, tree init, int flag) +{ + tree initlist; + tree block_byref_type = TREE_TYPE (decl); + int size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (block_byref_type)); + unsigned flags = 0; + tree fields; + + if (COPYABLE_BYREF_LOCAL_NONPOD (decl)) + flags = BLOCK_HAS_COPY_DISPOSE; + + fields = TYPE_FIELDS (block_byref_type); + /* APPLE LOCAL begin radar 6244520 */ + initlist = tree_cons (fields, fold_convert (ptr_type_node, ((flag & BLOCK_FIELD_IS_WEAK) != 0) ? integer_one_node + : integer_zero_node), + 0); + fields = TREE_CHAIN (fields); + + initlist = tree_cons (fields, + build_unary_op (ADDR_EXPR, decl, 0), initlist); + /* APPLE LOCAL end radar 6244520 */ + fields = TREE_CHAIN (fields); + + initlist = tree_cons (fields, build_int_cst (TREE_TYPE (fields), flags), + initlist); + fields = TREE_CHAIN (fields); + initlist = tree_cons (fields, build_int_cst (TREE_TYPE (fields), size), + initlist); + fields = TREE_CHAIN (fields); + + if (COPYABLE_BYREF_LOCAL_NONPOD (decl)) + { + char name[64]; + int align = exact_log2 ((DECL_ALIGN (decl)+TYPE_ALIGN (ptr_type_node)-1) / TYPE_ALIGN (ptr_type_node)); + int kind; + if (align == -1 || align > BLOCK_ALIGN_MAX) { + error ("invalid alignment for __block variable"); + kind = 0; + } else + kind = align*BLOCK_BYREF_CURRENT_MAX + flag; + /* Add &__Block_byref_id_object_copy, &__Block_byref_id_object_dispose + initializers. */ + if (!block_byref_id_object_copy[kind]) + { + tree func_type; + push_lang_context (lang_name_c); + /* Build a void __Block_byref_id_object_copy(void*, void*) type. */ + func_type = + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node))); + sprintf (name, "__Block_byref_id_object_copy%d", kind); + block_byref_id_object_copy[kind] = build_helper_func_decl (get_identifier (name), + func_type); + DECL_CONTEXT (block_byref_id_object_copy[kind]) = current_function_decl; + /* Synthesize function definition. */ + synth_block_byref_id_object_copy_func (flag, kind); + pop_lang_context (); + } + initlist = tree_cons (fields, + build_fold_addr_expr (block_byref_id_object_copy[kind]), + initlist); + fields = TREE_CHAIN (fields); + + if (!block_byref_id_object_dispose[kind]) + { + tree func_type; + push_lang_context (lang_name_c); + /* Synthesize void __Block_byref_id_object_dispose (void*) and + build &__Block_byref_id_object_dispose. */ + func_type = + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, void_list_node)); + sprintf (name, "__Block_byref_id_object_dispose%d", kind); + block_byref_id_object_dispose[kind] = build_helper_func_decl (get_identifier (name), + func_type); + DECL_CONTEXT (block_byref_id_object_dispose[kind]) = current_function_decl; + /* Synthesize function definition. */ + synth_block_byref_id_object_dispose_func (flag, kind); + pop_lang_context (); + } + initlist = tree_cons (fields, + build_fold_addr_expr (block_byref_id_object_dispose[kind]), + initlist); + fields = TREE_CHAIN (fields); + } + + if (init) + { + init = digest_init (TREE_TYPE (fields), init); + initlist = tree_cons (fields, init, initlist); + } + init = build_constructor_from_list (block_byref_type, nreverse (initlist)); + return init; +} +/* APPLE LOCAL end blocks 6040305 (cr) */ + /* Finish processing of a declaration; install its line number and initial value. If the length of an array type is not known before, @@ -5295,6 +5681,17 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (DECL_THREAD_LOCAL_P (decl) && !pod_type_p (TREE_TYPE (decl))) error ("%qD cannot be thread-local because it has non-POD type %qT", decl, TREE_TYPE (decl)); + /* APPLE LOCAL begin blocks 6040305 (cq) */ + if (COPYABLE_BYREF_LOCAL_VAR (decl)) { + if (DECL_EXTERNAL (decl) || TREE_STATIC (decl)) + { + error ("__block attribute on %q+D not allowed, only allowed on local variables", decl); + COPYABLE_BYREF_LOCAL_VAR (decl) = 0; + COPYABLE_BYREF_LOCAL_NONPOD (decl) = 0; + } + } + /* APPLE LOCAL end blocks 6040305 (cq) */ + /* If this is a local variable that will need a mangled name, register it now. We must do this before processing the initializer for the variable, since the initialization might @@ -5760,6 +6157,16 @@ expand_static_init (tree decl, tree init) && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) return; + /* APPLE LOCAL begin radar 5733674 */ + if (c_dialect_objc () && flag_objc_gc && init && TREE_CODE (init) == INIT_EXPR) + { + tree result = objc_generate_write_barrier (TREE_OPERAND (init, 0), + INIT_EXPR, TREE_OPERAND (init, 1)); + if (result) + init = result; + } + /* APPLE LOCAL end radar 5733674 */ + if (DECL_FUNCTION_SCOPE_P (decl)) { /* Emit code to perform this initialization but once. */ @@ -7235,6 +7642,8 @@ grokdeclarator (const cp_declarator *declarator, case cdk_pointer: case cdk_reference: case cdk_ptrmem: + /* APPLE LOCAL blocks 6040305 */ + case cdk_block_pointer: break; case cdk_error: @@ -7930,6 +8339,33 @@ grokdeclarator (const cp_declarator *declarator, ctype = NULL_TREE; break; + /* APPLE LOCAL begin blocks 6040305 (cj) */ + case cdk_block_pointer: + if (TREE_CODE (type) != FUNCTION_TYPE) + { + error ("block pointer to non-function type is invalid"); + type = error_mark_node; + } + else + { + /* We now know that the TYPE_QUALS don't apply to the decl, + but to the target of the pointer. */ + type_quals = TYPE_UNQUALIFIED; + + type = build_block_pointer_type (type); + + if (declarator->u.pointer.qualifiers) + { + type + = cp_build_qualified_type (type, + declarator->u.pointer.qualifiers); + type_quals = cp_type_quals (type); + } + } + ctype = NULL_TREE; + break; + /* APPLE LOCAL end blocks 6040305 (cj) */ + case cdk_error: break; @@ -8121,6 +8557,38 @@ grokdeclarator (const cp_declarator *declarator, } } + /* APPLE LOCAL begin blocks 6339747 */ + if (decl_context == BLOCKDEF) + { + tree decl; + + if (type == error_mark_node) + return error_mark_node; + + if (TREE_CODE (type) != FUNCTION_TYPE) + { + tree t = make_node (FUNCTION_TYPE); + + if (TREE_CODE (type) == ARRAY_TYPE) + { + error ("block declared as returning an array"); + return error_mark_node; + } + + TYPE_ARG_TYPES (t) = void_list_node; + TREE_TYPE (t) = type; + type = t; + parms = NULL_TREE; + } + + if (raises) + type = build_exception_variant (type, raises); + decl = build_lang_decl (FUNCTION_DECL, NULL_TREE, type); + DECL_ARGUMENTS (decl) = parms; + return decl; + } + /* APPLE LOCAL end blocks 6339747 */ + /* If this is declaring a typedef name, return a TYPE_DECL. */ if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME) { @@ -8973,7 +9441,8 @@ check_default_argument (tree decl, tree arg) *PARMS is set to the chain of PARM_DECLs created. */ -static tree +/* APPLE LOCAL blocks 6040305 (ce) */ +tree grokparms (cp_parameter_declarator *first_parm, tree *parms) { tree result = NULL_TREE; @@ -10909,6 +11378,82 @@ start_preparsed_function (tree decl1, tree attrs, int flags) } +/* APPLE LOCAL begin warn missing prototype 6261539 */ +static bool +fn_previously_found (tree decl, tree olddecl) +{ + int types_match; + + if (olddecl == 0) + return false; + + if (TREE_CODE (olddecl) == OVERLOAD) + { + if (OVL_CHAIN (olddecl) == NULL_TREE) + olddecl = OVL_CURRENT (olddecl); + else + { + tree match; + for (match = olddecl; match; match = OVL_NEXT (match)) + { + if (fn_previously_found (decl, OVL_CURRENT (match))) + return true; + } + return false; + } + } + + /* Don't warn about previously erroneous things that have the same + name. */ + if (TREE_TYPE (olddecl) == error_mark_node) + return true; + + /* Internally defined things still need a prototype to escape the + warning. */ + if (DECL_ARTIFICIAL (olddecl)) + return false; + + if (TREE_CODE (olddecl) != FUNCTION_DECL) + return false; + + /* These will match or error, don't also spew prototype warnings. */ + if (DECL_EXTERN_C_P (olddecl) + && DECL_EXTERN_C_P (decl)) + return true; + + /* These will match or error, don't also spew prototype warnings. */ + if (compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)), + TYPE_ARG_TYPES (TREE_TYPE (olddecl)))) + return true; + + types_match = decls_match (decl, olddecl); + + if (types_match) + return true; + + return false; +} + +inline static void +check_missing_prototype (tree decl) +{ + if (warn_missing_prototypes + && namespace_bindings_p () + && TREE_PUBLIC (decl) + && !DECL_MAIN_P (decl) + && DECL_NON_THUNK_FUNCTION_P (decl) + && ! DECL_FUNCTION_MEMBER_P (decl) + && DECL_NAMESPACE_SCOPE_P (decl) + && ! decl_anon_ns_mem_p (decl) + && ! DECL_DECLARED_INLINE_P (decl)) + { + tree olddecl = namespace_binding (DECL_NAME (decl), DECL_CONTEXT (decl)); + if (!fn_previously_found (decl, olddecl)) + warning (OPT_Wmissing_prototypes, "no previous prototype for %q+D", decl); + } +} +/* APPLE LOCAL end warn missing prototype 6261539 */ + /* Like start_preparsed_function, except that instead of a FUNCTION_DECL, this function takes DECLSPECS and DECLARATOR. @@ -11253,6 +11798,8 @@ finish_function (int flags) tree fndecl = current_function_decl; tree fntype, ctype = NULL_TREE; int inclass_inline = (flags & 2) != 0; + /* APPLE LOCAL radar 6169580 */ + int in_blocks_helper_function = (flags & 4) != 0; int nested; /* When we get some parse errors, we can end up without a @@ -11446,7 +11993,8 @@ finish_function (int flags) maybe_end_member_template_processing (); /* Leave the scope of the class. */ - if (ctype) + /* APPLE LOCAL radar 6169580 */ + if (ctype && !in_blocks_helper_function) pop_nested_class (); --function_depth; @@ -11672,13 +12220,32 @@ cxx_maybe_build_cleanup (tree decl) { tree type = TREE_TYPE (decl); - if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + tree dtor = NULL_TREE; + bool build_cleanup = false; + + if (TREE_CODE (type) == RECORD_TYPE) + dtor = CLASSTYPE_DESTRUCTORS (type); + + if (type != error_mark_node) { + if (TREE_CODE (type) == RECORD_TYPE) + /* For RECORD_TYPEs, we can refer to more precise flags than + TYPE_HAS_NONTRIVIAL_DESTRUCTOR. */ + build_cleanup = (dtor && TREE_PRIVATE (dtor)) + || CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (type) + || CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE (type); + else + build_cleanup = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type); + } + + if (build_cleanup) + { + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR; tree rval; bool has_vbases = (TREE_CODE (type) == RECORD_TYPE && CLASSTYPE_VBASECLASSES (type)); - if (TREE_CODE (type) == ARRAY_TYPE) rval = decl; else diff --git a/contrib/gcc/cp/decl.h b/contrib/gcc/cp/decl.h index dd2357a47f32..179d8a86ef89 100644 --- a/contrib/gcc/cp/decl.h +++ b/contrib/gcc/cp/decl.h @@ -27,6 +27,8 @@ enum decl_context FIELD, /* Declaration inside struct or union */ BITFIELD, /* Likewise but with specified width */ TYPENAME, /* Typename (inside cast or sizeof) */ + /* APPLE LOCAL blocks 6339747 */ + BLOCKDEF, /* Declaratin of block literal */ MEMFUNCDEF /* Member function definition */ }; @@ -34,3 +36,7 @@ enum decl_context extern tree grokdeclarator (const cp_declarator *, const cp_decl_specifier_seq *, enum decl_context, int, tree*); +/* APPLE LOCAL radar 4721858 */ +extern void emit_instantiate_pending_templates (location_t *); +/* APPLE LOCAL blocks 6040305 (ce) */ +extern tree grokparms (cp_parameter_declarator *first_parm, tree *parms); diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c index 69cdb990f9d4..8c31bb9d0249 100644 --- a/contrib/gcc/cp/decl2.c +++ b/contrib/gcc/cp/decl2.c @@ -1904,6 +1904,27 @@ constrain_class_visibility (tree type) } } +/* APPLE LOCAL begin weak types 5954418 */ +static bool +typeinfo_comdat (tree type) +{ + tree binfo, base_binfo; + int j; + + if (lookup_attribute ("weak", TYPE_ATTRIBUTES (type))) + return true; + + for (binfo = TYPE_BINFO (type), j = 0; + BINFO_BASE_ITERATE (binfo, j, base_binfo); ++j) + { + if (typeinfo_comdat (BINFO_TYPE (base_binfo))) + return true; + } + + return false; +} +/* APPLE LOCAL end weak types 5954418 */ + /* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage for DECL has not already been determined, do so now by setting DECL_EXTERNAL, DECL_COMDAT and other related flags. Until this @@ -2100,7 +2121,10 @@ import_export_decl (tree decl) { comdat_p = (targetm.cxx.class_data_always_comdat () || (CLASSTYPE_KEY_METHOD (type) - && DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type)))); + /* APPLE LOCAL begin weak types 5954418 */ + && DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type))) + || typeinfo_comdat (type)); + /* APPLE LOCAL end weak types 5954418 */ mark_needed (decl); if (!flag_weak) { @@ -3043,6 +3067,10 @@ build_java_method_aliases (void) } } +/* APPLE LOCAL begin radar 4721858 */ +static void emit_deferred (location_t *); +/* APPLE LOCAL end radar 4721858 */ + /* This routine is called from the last rule in yyparse (). Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -3051,14 +3079,10 @@ build_java_method_aliases (void) void cp_finish_file (void) { - tree vars; - bool reconsider; - size_t i; + /* APPLE LOCAL begin radar 4721858 */ location_t locus; - unsigned ssdf_count = 0; - int retries = 0; - tree decl; - + /* APPLE LOCAL end radar 4721858 */ + locus = input_location; at_eof = 1; @@ -3066,8 +3090,8 @@ cp_finish_file (void) if (! global_bindings_p () || current_class_type || decl_namespace_list) return; - if (pch_file) - c_common_write_pch (); + /* APPLE LOCAL radar 4874613 */ + /* dump of pch file moved to c_parse_file (). */ #ifdef USE_MAPPED_LOCATION /* FIXME - huh? */ @@ -3097,6 +3121,29 @@ cp_finish_file (void) emit_support_tinfos (); + /* APPLE LOCAL begin radar 4721858 */ + emit_instantiate_pending_templates (&locus); + + emit_deferred (&locus); +} + +/* This routine emits pending functions and instatiates pending templates + as more opportunities arises. */ + +void +emit_instantiate_pending_templates (location_t *locusp) +{ + tree vars; + bool reconsider; + size_t i; + unsigned ssdf_count = 0; + int retries = 0; + + /* APPLE LOCAL radar 4874626 */ + /* initialization removed. */ + at_eof = 1; +/* APPLE LOCAL end radar 4721858 */ + do { tree t; @@ -3174,7 +3221,8 @@ cp_finish_file (void) /* Set the line and file, so that it is obviously not from the source file. */ - input_location = locus; + /* APPLE LOCAL radar 4721858 */ + input_location = *locusp; ssdf_body = start_static_storage_duration_function (ssdf_count); /* Make sure the back end knows about all the variables. */ @@ -3200,7 +3248,8 @@ cp_finish_file (void) /* Finish up the static storage duration function for this round. */ - input_location = locus; + /* APPLE LOCAL radar 4721858 */ + input_location = *locusp; finish_static_storage_duration_function (ssdf_body); /* All those initializations and finalizations might cause @@ -3211,7 +3260,8 @@ cp_finish_file (void) #ifdef USE_MAPPED_LOCATION /* ??? */ #else - locus.line++; + /* APPLE LOCAL radar 4721858 */ + locusp->line++; #endif } @@ -3309,27 +3359,36 @@ cp_finish_file (void) retries++; } while (reconsider); +/* APPLE LOCAL begin radar 4721858 */ +} +static void +emit_deferred (location_t *locusp) +{ + size_t i; + tree decl; + bool reconsider = false; + /* APPLE LOCAL end radar 4721858 */ /* All used inline functions must have a definition at this point. */ for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i) { if (/* Check online inline functions that were actually used. */ - TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl) - /* If the definition actually was available here, then the - fact that the function was not defined merely represents - that for some reason (use of a template repository, - #pragma interface, etc.) we decided not to emit the - definition here. */ - && !DECL_INITIAL (decl) - /* An explicit instantiation can be used to specify - that the body is in another unit. It will have - already verified there was a definition. */ - && !DECL_EXPLICIT_INSTANTIATION (decl)) - { - warning (0, "inline function %q+D used but never defined", decl); - /* Avoid a duplicate warning from check_global_declaration_1. */ - TREE_NO_WARNING (decl) = 1; - } + TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl) + /* If the definition actually was available here, then the + fact that the function was not defined merely represents + that for some reason (use of a template repository, + #pragma interface, etc.) we decided not to emit the + definition here. */ + && !DECL_INITIAL (decl) + /* An explicit instantiation can be used to specify + that the body is in another unit. It will have + already verified there was a definition. */ + && !DECL_EXPLICIT_INSTANTIATION (decl)) + { + warning (0, "inline function %q+D used but never defined", decl); + /* Avoid a duplicate warning from check_global_declaration_1. */ + TREE_NO_WARNING (decl) = 1; + } } /* We give C linkage to static constructors and destructors. */ @@ -3340,17 +3399,20 @@ cp_finish_file (void) if (priority_info_map) splay_tree_foreach (priority_info_map, generate_ctor_and_dtor_functions_for_priority, - /*data=*/&locus); + /* APPLE LOCAL radar 4721858 */ + /*data=*/locusp); else { /* If we have a ctor or this is obj-c++ and we need a static init, call generate_ctor_or_dtor_function. */ if (static_ctors || (c_dialect_objc () && objc_static_init_needed_p ())) generate_ctor_or_dtor_function (/*constructor_p=*/true, - DEFAULT_INIT_PRIORITY, &locus); + /* APPLE LOCAL radar 4721858 */ + DEFAULT_INIT_PRIORITY, locusp); if (static_dtors) generate_ctor_or_dtor_function (/*constructor_p=*/false, - DEFAULT_INIT_PRIORITY, &locus); + /* APPLE LOCAL radar 4721858 */ + DEFAULT_INIT_PRIORITY, locusp); } /* We're done with the splay-tree now. */ @@ -3403,7 +3465,8 @@ cp_finish_file (void) dump_tree_statistics (); dump_time_statistics (); } - input_location = locus; + /* APPLE LOCAL radar 4721858 */ + input_location = *locusp; #ifdef ENABLE_CHECKING validate_conversion_obstack (); diff --git a/contrib/gcc/cp/error.c b/contrib/gcc/cp/error.c index c169cabedb64..f90096a462fa 100644 --- a/contrib/gcc/cp/error.c +++ b/contrib/gcc/cp/error.c @@ -342,6 +342,8 @@ dump_type (tree t, int flags) reduces code size. */ case ARRAY_TYPE: case POINTER_TYPE: + /* APPLE LOCAL blocks 6040305 */ + case BLOCK_POINTER_TYPE: case REFERENCE_TYPE: case OFFSET_TYPE: offset_type: @@ -497,6 +499,8 @@ dump_type_prefix (tree t, int flags) switch (TREE_CODE (t)) { case POINTER_TYPE: + /* APPLE LOCAL blocks 6040305 */ + case BLOCK_POINTER_TYPE: case REFERENCE_TYPE: { tree sub = TREE_TYPE (t); @@ -507,7 +511,10 @@ dump_type_prefix (tree t, int flags) pp_cxx_whitespace (cxx_pp); pp_cxx_left_paren (cxx_pp); } - pp_character (cxx_pp, "&*"[TREE_CODE (t) == POINTER_TYPE]); + /* APPLE LOCAL begin blocks 6040305 */ + pp_character (cxx_pp, "&*^"[(TREE_CODE (t) == POINTER_TYPE) + + (TREE_CODE (t) == BLOCK_POINTER_TYPE)*2]); + /* APPLE LOCAL end blocks 6040305 */ pp_base (cxx_pp)->padding = pp_before; pp_cxx_cv_qualifier_seq (cxx_pp, t); } @@ -593,6 +600,8 @@ dump_type_suffix (tree t, int flags) switch (TREE_CODE (t)) { case POINTER_TYPE: + /* APPLE LOCAL blocks 6040305 */ + case BLOCK_POINTER_TYPE: case REFERENCE_TYPE: case OFFSET_TYPE: if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c index fbdd609497b9..0d67fef47fd2 100644 --- a/contrib/gcc/cp/init.c +++ b/contrib/gcc/cp/init.c @@ -2905,7 +2905,13 @@ push_base_cleanups (void) for (binfo = TYPE_BINFO (current_class_type), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { - if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)) + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + tree dtor = CLASSTYPE_DESTRUCTORS (BINFO_TYPE (base_binfo)); + + if ((!CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE (BINFO_TYPE (base_binfo)) + && !CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (BINFO_TYPE (base_binfo)) + && !(dtor && (TREE_PRIVATE (dtor)))) + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ || BINFO_VIRTUAL_P (base_binfo)) continue; @@ -2935,6 +2941,12 @@ push_base_cleanups (void) LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); finish_decl_cleanup (NULL_TREE, expr); + + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + /* Even if body of current class's destructor was found to be empty, + it must now be called because it must delete its members. */ + CLASSTYPE_DESTRUCTOR_NONTRIVIAL_BECAUSE_OF_BASE (current_class_type) = 1; + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ } } } diff --git a/contrib/gcc/cp/mangle.c b/contrib/gcc/cp/mangle.c index 8bfdc20ef7a0..c6147f7ed9ea 100644 --- a/contrib/gcc/cp/mangle.c +++ b/contrib/gcc/cp/mangle.c @@ -1634,6 +1634,13 @@ write_type (tree type) write_type (TREE_TYPE (type)); break; + /* APPLE LOCAL begin blocks 6040305 */ + case BLOCK_POINTER_TYPE: + write_string ("U13block_pointer"); + write_type (TREE_TYPE (type)); + break; + /* APPLE LOCAL end blocks 6040305 */ + case REFERENCE_TYPE: write_char ('R'); write_type (TREE_TYPE (type)); diff --git a/contrib/gcc/cp/name-lookup.c b/contrib/gcc/cp/name-lookup.c index 4d08174a4be8..e587bfe54953 100644 --- a/contrib/gcc/cp/name-lookup.c +++ b/contrib/gcc/cp/name-lookup.c @@ -364,6 +364,8 @@ push_binding (tree id, tree decl, cxx_scope* level) { binding = cxx_binding_make (decl, NULL_TREE); binding->scope = level; + /* APPLE LOCAL blocks 6040305 (ch) */ + binding->declared_in_block = cur_block != 0; } else binding = new_class_binding (id, decl, /*type=*/NULL_TREE, level); @@ -1822,6 +1824,8 @@ binding_for_name (cxx_scope *scope, tree name) result->scope = scope; result->is_local = false; result->value_is_inherited = false; + /* APPLE LOCAL blocks 6040305 (ch) */ + result->declared_in_block = 0; IDENTIFIER_NAMESPACE_BINDINGS (name) = result; return result; } @@ -4581,6 +4585,8 @@ arg_assoc_type (struct arg_lookup *k, tree type) return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type)); return arg_assoc_class (k, type); case POINTER_TYPE: + /* APPLE LOCAL blocks 6040305 */ + case BLOCK_POINTER_TYPE: case REFERENCE_TYPE: case ARRAY_TYPE: return arg_assoc_type (k, TREE_TYPE (type)); diff --git a/contrib/gcc/cp/name-lookup.h b/contrib/gcc/cp/name-lookup.h index 0d99f9beafa8..f604f874a08d 100644 --- a/contrib/gcc/cp/name-lookup.h +++ b/contrib/gcc/cp/name-lookup.h @@ -76,6 +76,8 @@ struct cxx_binding GTY(()) cxx_scope *scope; unsigned value_is_inherited : 1; unsigned is_local : 1; + /* APPLE LOCAL blocks 6040305 (ch) */ + unsigned declared_in_block : 1; }; /* Datatype used to temporarily save C++ bindings (for implicit diff --git a/contrib/gcc/cp/parser.c b/contrib/gcc/cp/parser.c index 94f90783fed8..90e49f063600 100644 --- a/contrib/gcc/cp/parser.c +++ b/contrib/gcc/cp/parser.c @@ -38,6 +38,8 @@ #include "target.h" #include "cgraph.h" #include "c-common.h" +/* APPLE LOCAL C* language */ +#include "tree-iterator.h" /* The lexer. */ @@ -1120,6 +1122,10 @@ typedef enum cp_parser_flags typedef enum cp_parser_declarator_kind { + /* APPLE LOCAL begin blocks 6339747 */ + /* We want a block declarator. */ + CP_PARSER_DECLARATOR_BLOCK, + /* APPLE LOCAL end blocks 6339747 */ /* We want an abstract declarator. */ CP_PARSER_DECLARATOR_ABSTRACT, /* We want a named declarator. */ @@ -1539,6 +1545,23 @@ static tree cp_parser_constant_expression (cp_parser *, bool, bool *); static tree cp_parser_builtin_offsetof (cp_parser *); +/* APPLE LOCAL begin blocks 6040305 (ca) */ +static tree cp_parser_block_literal_expr (cp_parser *); +/* APPLE LOCAL end blocks 6040305 (ca) */ +/* APPLE LOCAL begin C* language */ +static void objc_foreach_stmt + (cp_parser *, tree); +/* APPLE LOCAL end C* language */ +/* APPLE LOCAL begin C* property (Radar 4436866) */ +static void objc_cp_parser_at_property + (cp_parser *); +static void objc_cp_parse_property_decl + (cp_parser *); +/* APPLE LOCAL end C* property (Radar 4436866) */ +/* APPLE LOCAL begin radar 4548636 */ +static bool objc_attr_follwed_by_at_keyword + (cp_parser *); +/* APPLE LOCAL end radar 4548636 */ /* Statements [gram.stmt.stmt] */ @@ -1549,7 +1572,8 @@ static void cp_parser_label_for_labeled_statement static tree cp_parser_expression_statement (cp_parser *, tree); static tree cp_parser_compound_statement - (cp_parser *, tree, bool); + /* APPLE LOCAL radar 5982990 */ + (cp_parser *, tree, bool, bool); static void cp_parser_statement_seq_opt (cp_parser *, tree); static tree cp_parser_selection_statement @@ -1777,6 +1801,10 @@ static tree cp_parser_objc_message_args (cp_parser *); static tree cp_parser_objc_message_expression (cp_parser *); +/* APPLE LOCAL begin radar 5277239 */ +static tree cp_parser_objc_reference_expression + (cp_parser *, tree); +/* APPLE LOCAL end radar 5277239 */ static tree cp_parser_objc_encode_expression (cp_parser *); static tree cp_parser_objc_defs_expression @@ -1791,8 +1819,18 @@ static bool cp_parser_objc_selector_p (enum cpp_ttype); static tree cp_parser_objc_selector (cp_parser *); +/* APPLE LOCAL begin radar 3803157 - objc attribute */ +static void cp_parser_objc_maybe_attributes +(cp_parser *, tree *); +static tree cp_parser_objc_identifier_list +(cp_parser *); +/* APPLE LOCAL end radar 3803157 - objc attribute */ static tree cp_parser_objc_protocol_refs_opt (cp_parser *); +/* APPLE LOCAL begin radar 5355344 */ +static bool cp_parser_objc_tentative_protocol_refs_opt + (cp_parser *, tree *); +/* APPLE LOCAL end radar 5355344 */ static void cp_parser_objc_declaration (cp_parser *); static tree cp_parser_objc_statement @@ -2443,6 +2481,141 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser) } } +/* APPLE LOCAL begin radar 5277239 */ +/* This routine checks that type_decl is a class or class object followed by a '.' + which is an alternative syntax to class-method messaging [class-name class-method] + */ + +static bool +cp_objc_property_reference_prefix (cp_parser *parser, tree type) +{ + return c_dialect_objc () && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT + && (objc_is_id (type) || objc_is_class_name (type)); +} +/* APPLE LOCAL end radar 5277239 */ +/* APPLE LOCAL begin C* property (Radar 4436866, 4591909) */ +/* This routine parses the propery declarations. */ + +static void +objc_cp_parse_property_decl (cp_parser *parser) +{ + int declares_class_or_enum; + cp_decl_specifier_seq declspecs; + + cp_parser_decl_specifier_seq (parser, + CP_PARSER_FLAGS_NONE, + &declspecs, + &declares_class_or_enum); + /* Keep going until we hit the `;' at the end of the declaration. */ + while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) + { + tree property; + cp_token *token; + cp_declarator *declarator + = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, + NULL, NULL, false); + property = grokdeclarator (declarator, &declspecs, NORMAL,0, NULL); + /* Revover from any kind of error in property declaration. */ + if (property == error_mark_node || property == NULL_TREE) + return; + /* Add to property list. */ + objc_add_property_variable (copy_node (property)); + if (token->type == CPP_COMMA) + { + cp_lexer_consume_token (parser->lexer); /* Eat ','. */ + continue; + } + else if (token->type == CPP_EOF) + return; + } + cp_lexer_consume_token (parser->lexer); /* Eat ';'. */ +} + +/* This function parses a @property declaration inside an objective class + or its implementation. */ + +static void +objc_cp_parser_at_property (cp_parser *parser) +{ + cp_token *token; + + objc_set_property_attr (0, NULL_TREE); + /* Consume @property */ + cp_lexer_consume_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_OPEN_PAREN) + { + cp_lexer_consume_token (parser->lexer); + while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF) + { + tree node; + /* property has attribute list. */ + /* Consume '(' */ + node = cp_parser_identifier (parser); + if (node == ridpointers [(int) RID_READONLY]) + { + /* Do the readyonly thing. */ + objc_set_property_attr (1, NULL_TREE); + } + else if (node == ridpointers [(int) RID_GETTER] + || node == ridpointers [(int) RID_SETTER]) + { + /* Do the getter/setter attribute. */ + token = cp_lexer_consume_token (parser->lexer); + if (token->type == CPP_EQ) + { + /* APPLE LOCAL radar 4675792 */ + tree attr_ident = cp_parser_objc_selector (parser); + int num; + if (node == ridpointers [(int) RID_GETTER]) + num = 2; + else + { + num = 3; + /* Consume the ':' which must always follow the setter name. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + cp_lexer_consume_token (parser->lexer); + } + objc_set_property_attr (num, attr_ident); + } + else + { + error ("getter/setter attribute must be followed by '='"); + break; + } + } + /* APPLE LOCAL begin radar 4947014 - objc atomic property */ + else if (node == ridpointers [(int) RID_NONATOMIC]) + { + objc_set_property_attr (13, NULL_TREE); + } + /* APPLE LOCAL end radar 4947014 - objc atomic property */ + else + { + error ("unknown property attribute"); + break; + } + /* APPLE LOCAL begin radar 6302949 */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA) + && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN) + && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)) + warning (0, "property attributes must be separated by a comma"); + /* APPLE LOCAL end radar 6302949 */ + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); + } + if (token->type != CPP_CLOSE_PAREN) + { + error ("syntax error in @property's attribute declaration"); + } + /* Consume ')' */ + cp_lexer_consume_token (parser->lexer); + } + objc_cp_parse_property_decl (parser); +} +/* APPLE LOCAL end C* property (Radar 4436866, 4591909) */ + /* This function is called at the end of a statement or declaration. If the next token is a semicolon, it is consumed; otherwise, error recovery is attempted. */ @@ -2901,6 +3074,8 @@ cp_parser_translation_unit (cp_parser* parser) ( compound-statement ) __builtin_va_arg ( assignment-expression , type-id ) __builtin_offsetof ( type-id , offsetof-expression ) + APPLE LOCAL blocks 6040305 (cf) + block-literal-expr Objective-C++ Extension: @@ -2934,6 +3109,16 @@ cp_parser_primary_expression (cp_parser *parser, token = cp_lexer_peek_token (parser->lexer); switch (token->type) { + /* APPLE LOCAL begin blocks 6040305 (cf) */ + case CPP_XOR: + if (flag_blocks) + { + tree expr = cp_parser_block_literal_expr (parser); + return expr; + } + cp_parser_error (parser, "expected primary-expression"); + return error_mark_node; + /* APPLE LOCAL end blocks 6040305 (cf) */ /* literal: integer-literal character-literal @@ -3027,7 +3212,8 @@ cp_parser_primary_expression (cp_parser *parser, /* Start the statement-expression. */ expr = begin_stmt_expr (); /* Parse the compound-statement. */ - cp_parser_compound_statement (parser, expr, false); + /* APPLE LOCAL radar 5982990 */ + cp_parser_compound_statement (parser, expr, false, false); /* Finish up. */ expr = finish_stmt_expr (expr, false); } @@ -3197,6 +3383,11 @@ cp_parser_primary_expression (cp_parser *parser, if (ambiguous_decls) return error_mark_node; + /* APPLE LOCAL begin radar 5277239 */ + if (TREE_CODE (decl) == TYPE_DECL + && cp_objc_property_reference_prefix (parser, TREE_TYPE (decl))) + return cp_parser_objc_reference_expression (parser, decl); + /* APPLE LOCAL end radar 5277239 */ /* In Objective-C++, an instance variable (ivar) may be preferred to whatever cp_parser_lookup_name() found. */ decl = objc_lookup_ivar (decl, id_expression); @@ -6329,7 +6520,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, } /* Anything that starts with a `{' must be a compound-statement. */ else if (token->type == CPP_OPEN_BRACE) - statement = cp_parser_compound_statement (parser, NULL, false); + /* APPLE LOCAL radar 5982990 */ + statement = cp_parser_compound_statement (parser, NULL, false, false); /* CPP_PRAGMA is a #pragma inside a function body, which constitutes a statement all its own. */ else if (token->type == CPP_PRAGMA) @@ -6503,7 +6695,8 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) static tree cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, - bool in_try) + /* APPLE LOCAL radar 5982990 */ + bool in_try, bool objc_sjlj_exceptions) { tree compound_stmt; @@ -6514,6 +6707,10 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0); /* Parse an (optional) statement-seq. */ cp_parser_statement_seq_opt (parser, in_statement_expr); + /* APPLE LOCAL begin radar 5982990 */ + if (objc_sjlj_exceptions) + objc_mark_locals_volatile (NULL); + /* APPLE LOCAL end radar 5982990 */ /* Finish the compound-statement. */ finish_compound_stmt (compound_stmt); /* Consume the `}'. */ @@ -6531,17 +6728,45 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, static void cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) { + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + tree class_type = DECL_CONTEXT (current_function_decl); + + bool determine_destructor_triviality = + DECL_DESTRUCTOR_P (current_function_decl) && class_type != NULL_TREE + && !CLASSTYPE_DESTRUCTOR_TRIVIALITY_FINAL (class_type); + + /* Assume that the destructor is trivial at first, and mark nontrivial if + any statement is parsed. */ + if (determine_destructor_triviality) + { + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (class_type) = 0; + CLASSTYPE_DESTRUCTOR_TRIVIALITY_FINAL (class_type) = 1; + } + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ + /* Scan statements until there aren't any more. */ while (true) { cp_token *token = cp_lexer_peek_token (parser->lexer); - /* If we're looking at a `}', then we've run out of statements. */ + /* APPLE LOCAL begin ObjC++ 4185810 */ + /* If we're looking at a `}', then we've run out of + statements; the same is true if we have reached the end + of file, or have stumbled upon a stray 'else' or '@end'. */ if (token->type == CPP_CLOSE_BRACE || token->type == CPP_EOF - || token->type == CPP_PRAGMA_EOL) + || token->type == CPP_PRAGMA_EOL + || (token->type == CPP_KEYWORD + && (token->keyword == RID_ELSE + || token->keyword == RID_AT_END))) + /* APPLE LOCAL end ObjC++ 4185810 */ break; + /* APPLE LOCAL begin omit calls to empty destructors 5559195 */ + if (determine_destructor_triviality) + CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (class_type) = 1; + /* APPLE LOCAL end omit calls to empty destructors 5559195 */ + /* Parse the statement. */ cp_parser_statement (parser, in_statement_expr, true, NULL); } @@ -6779,11 +7004,119 @@ cp_parser_condition (cp_parser* parser) return cp_parser_expression (parser, /*cast_p=*/false); } +/* APPLE LOCAL begin radar 4631818 */ +/* This routine looks for objective-c++'s foreach statement by scanning for-loop + header looking for either 1) 'for (type selector in...)' or 2) 'for (selector in...)' + where selector is already declared in outer scope. If it failed, it undoes the lexical + look-ahead and returns false. If it succeeded, it adds the 'selector' to the statement + list and returns true. At success, lexer points to token following the 'in' keyword. +*/ + +static bool +cp_parser_parse_foreach_stmt (cp_parser *parser) +{ + int decl_spec_declares_class_or_enum; + bool is_cv_qualifier; + tree type_spec; + cp_decl_specifier_seq decl_specs; + tree node; + cp_token *token; + bool is_legit_foreach = false; + cp_declarator *declarator; + + /* Exclude class/struct/enum type definition in for-loop header, which is + aparently legal in c++. Otherwise, it causes side-effect (type is enterred + in function's scope) when type is re-parsed. */ + token = cp_lexer_peek_token (parser->lexer); + if (cp_parser_token_is_class_key (token) || token->keyword == RID_ENUM) + return false; + + cp_parser_parse_tentatively (parser); + clear_decl_specs (&decl_specs); + type_spec + = cp_parser_type_specifier (parser, CP_PARSER_FLAGS_OPTIONAL, + &decl_specs, + /*is_declaration=*/true, + &decl_spec_declares_class_or_enum, + &is_cv_qualifier); + declarator + = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, + NULL, + /*parenthesized_p=*/NULL, + /*member_p=*/false); + if (declarator == cp_error_declarator) + { + cp_parser_abort_tentative_parse (parser); + return false; + } + + token = cp_lexer_peek_token (parser->lexer); + + node = token->u.value; + if (node && TREE_CODE (node) == IDENTIFIER_NODE + && node == ridpointers [(int) RID_IN]) + { + enum cpp_ttype nt = cp_lexer_peek_nth_token (parser->lexer, 2)->type; + switch (nt) + { + case CPP_NAME: + case CPP_OPEN_PAREN: + case CPP_MULT: + case CPP_PLUS: case CPP_PLUS_PLUS: + case CPP_MINUS: case CPP_MINUS_MINUS: + case CPP_OPEN_SQUARE: + is_legit_foreach = true; + default: + break; + } + } + if (is_legit_foreach) + { + tree pushed_scope = NULL; + tree decl; + if (type_spec) + { + /* we have: 'for (type selector in...)' */ + cp_parser_commit_to_tentative_parse (parser); + decl = start_decl (declarator, &decl_specs, + false /*is_initialized*/, + NULL_TREE /*attributes*/, + NULL_TREE /*prefix_attributes*/, + &pushed_scope); + /* APPLE LOCAL begin radar 5130983 */ + if (!decl || decl == error_mark_node) + { + error ("selector is undeclared"); + is_legit_foreach = false; + } + else + cp_finish_decl (decl, + NULL_TREE /*initializer*/, + false /*init_const_expr_p=*/, + NULL_TREE /*asm_specification*/, + 0 /*flags */); + } + else { + tree statement; + /* we have: 'for (selector in...)' */ + /* Parse it as an expression. */ + cp_parser_abort_tentative_parse (parser); + statement = cp_parser_expression (parser, /*cast_p=*/false); + add_stmt (statement); + } + /* APPLE LOCAL end radar 5130983 */ + /* Consume the 'in' token */ + cp_lexer_consume_token (parser->lexer); + } + else + cp_parser_abort_tentative_parse (parser); + return is_legit_foreach; +} +/* APPLE LOCAL end radar 4631818 */ + /* Parse an iteration-statement. iteration-statement: - while ( condition ) statement - do statement while ( expression ) ; for ( for-init-statement condition [opt] ; expression [opt] ) statement @@ -7050,6 +7383,10 @@ cp_parser_jump_statement (cp_parser* parser) break; case RID_GOTO: + /* APPLE LOCAL begin blocks 6040305 (cb) */ + if (cur_block) + error ("goto not allowed in block literal"); + /* APPLE LOCAL end blocks 6040305 (cb) */ /* Create the goto-statement. */ if (cp_lexer_next_token_is (parser->lexer, CPP_MULT)) { @@ -7130,7 +7467,8 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p) } /* if a compound is opened, we simply parse the statement directly. */ else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) - statement = cp_parser_compound_statement (parser, NULL, false); + /* APPLE LOCAL radar 5982990 */ + statement = cp_parser_compound_statement (parser, NULL, false, false); /* If the token is not a `{', then we must take special action. */ else { @@ -11453,6 +11791,37 @@ cp_parser_init_declarator (cp_parser* parser, return decl; } +/* APPLE LOCAL begin blocks 6040305 (cc) */ +static cp_cv_quals +cp_parser_cv_qualifier_or_attribute_seq_opt (cp_parser *parser, tree *attrs_p) +{ + cp_cv_quals quals = TYPE_UNQUALIFIED; + cp_cv_quals q; + cp_token *token; + + *attrs_p = NULL_TREE; + while (true) + { + /* Peek at the next token. */ + token = cp_lexer_peek_token (parser->lexer); + /* Handle attributes. */ + if (token->keyword == RID_ATTRIBUTE) + { + /* Parse the attributes. */ + *attrs_p = chainon (*attrs_p, + cp_parser_attributes_opt (parser)); + continue; + } + + q = cp_parser_cv_qualifier_seq_opt (parser); + if (q == TYPE_UNQUALIFIED) + break; + quals |= q; + } + return quals; +} +/* APPLE LOCAL end blocks 6040305 (cc) */ + /* Parse a declarator. declarator: @@ -11473,6 +11842,12 @@ cp_parser_init_declarator (cp_parser* parser, attributes [opt] ptr-operator abstract-declarator [opt] attributes [opt] direct-abstract-declarator + APPLE LOCAL begin blocks 6339747 + block-declarator: + attributes [opt] ptr-operator block-declarator [opt] + attributes [opt] direct-block-declarator + APPLE LOCAL end blocks 6339747 + If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to detect constructor, destructor or conversion operators. It is set to -1 if the declarator is a name, and +1 if it is a @@ -11517,6 +11892,28 @@ cp_parser_declarator (cp_parser* parser, /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); + /* APPLE LOCAL begin blocks 6040305 (cc) */ + if (flag_blocks && token->type == CPP_XOR) + { + cp_cv_quals quals; + cp_declarator *inner; + tree attrs; + + cp_lexer_consume_token (parser->lexer); + + /* cp_parse_declspecs (parser, quals_attrs, false, false, true); */ + quals = cp_parser_cv_qualifier_or_attribute_seq_opt (parser, &attrs); + + inner = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER, + /*ctor_dtor_or_conv_p=*/NULL, + /*parenthesized_p=*/NULL, + /*member_p=*/false); + if (inner == cp_error_declarator) + return inner; + return make_block_pointer_declarator (attrs, quals, inner); + } + /* APPLE LOCAL end blocks 6040305 (cc) */ + /* Check for the ptr-operator production. */ cp_parser_parse_tentatively (parser); /* Parse the ptr-operator. */ @@ -11592,6 +11989,17 @@ cp_parser_declarator (cp_parser* parser, direct-abstract-declarator [opt] [ constant-expression [opt] ] ( abstract-declarator ) + APPLE LOCAL begin blocks 6339747 + GNU Extensions: + + direct-block-declarator: + direct-block-declarator [opt] + ( parameter-declaration-clause ) [opt] + exception-specification [opt] + direct-block-declarator [opt] [ constant-expression [opt] ] + ( block-declarator ) + APPLE LOCAL end blocks 6339747 + Returns a representation of the declarator. DCL_KIND is CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a direct-abstract-declarator. It is CP_PARSER_DECLARATOR_NAMED, if @@ -11708,8 +12116,16 @@ cp_parser_direct_declarator (cp_parser* parser, /* Consume the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); - /* Parse the cv-qualifier-seq. */ - cv_quals = cp_parser_cv_qualifier_seq_opt (parser); + /* APPLE LOCAL begin blocks 6339747 */ + if (dcl_kind != BLOCKDEF) + { + /* Parse the cv-qualifier-seq. */ + cv_quals = cp_parser_cv_qualifier_seq_opt (parser); + } + else + cv_quals = TYPE_UNQUALIFIED; + /* APPLE LOCAL end blocks 6339747 */ + /* And the exception-specification. */ exception_specification = cp_parser_exception_specification_opt (parser); @@ -11809,7 +12225,10 @@ cp_parser_direct_declarator (cp_parser* parser, declarator = make_array_declarator (declarator, bounds); } - else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT) + /* APPLE LOCAL begin blocks 6339747 */ + else if (first && (dcl_kind == CP_PARSER_DECLARATOR_NAMED + || dcl_kind == CP_PARSER_DECLARATOR_EITHER)) + /* APPLE LOCAL end blocks 6339747 */ { tree qualifying_scope; tree unqualified_name; @@ -11970,7 +12389,8 @@ cp_parser_direct_declarator (cp_parser* parser, /* For an abstract declarator, we might wind up with nothing at this point. That's an error; the declarator is not optional. */ - if (!declarator) + /* APPLE LOCAL blocks 6339747 */ + if (!declarator && dcl_kind != CP_PARSER_DECLARATOR_BLOCK) cp_parser_error (parser, "expected declarator"); /* If we entered a scope, we must exit it now. */ @@ -11994,6 +12414,8 @@ cp_parser_direct_declarator (cp_parser* parser, ptr-operator: & cv-qualifier-seq [opt] + APPLE LOCAL blocks 6040305 (cc) + ^ Returns INDIRECT_REF if a pointer, or pointer-to-member, was used. Returns ADDR_EXPR if a reference was used. In the case of a @@ -12776,7 +13198,8 @@ cp_parser_parameter_declaration (cp_parser *parser, static void cp_parser_function_body (cp_parser *parser) { - cp_parser_compound_statement (parser, NULL, false); + /* APPLE LOCAL radar 5982990 */ + cp_parser_compound_statement (parser, NULL, false, false); } /* Parse a ctor-initializer-opt followed by a function-body. Return @@ -14533,7 +14956,8 @@ cp_parser_try_block (cp_parser* parser) cp_parser_require_keyword (parser, RID_TRY, "`try'"); try_block = begin_try_block (); - cp_parser_compound_statement (parser, NULL, true); + /* APPLE LOCAL radar 5982990 */ + cp_parser_compound_statement (parser, NULL, true, false); finish_try_block (try_block); cp_parser_handler_seq (parser); finish_handler_sequence (try_block); @@ -14610,7 +15034,8 @@ cp_parser_handler (cp_parser* parser) declaration = cp_parser_exception_declaration (parser); finish_handler_parms (declaration, handler); cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); - cp_parser_compound_statement (parser, NULL, false); + /* APPLE LOCAL radar 5982990 */ + cp_parser_compound_statement (parser, NULL, false, false); finish_handler (handler); } @@ -15395,6 +15820,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser, case cdk_pointer: case cdk_reference: case cdk_ptrmem: + /* APPLE LOCAL blocks 6040305 */ + case cdk_block_pointer: return (cp_parser_check_declarator_template_parameters (parser, declarator->declarator)); @@ -17103,6 +17530,25 @@ cp_parser_objc_message_expression (cp_parser* parser) return objc_build_message_expr (build_tree_list (receiver, messageargs)); } +/* APPLE LOCAL begin radar 5277239 */ +/* Parse an Objective-C dot-syntax class expression. + + objc-message-expression: + class-name '.' class-method-name + + Returns an objc_property_reference expression. */ + +static tree +cp_parser_objc_reference_expression (cp_parser* parser, tree type_decl) +{ + tree receiver, component; + receiver = objc_get_class_reference (TREE_TYPE (type_decl)); + cp_lexer_consume_token (parser->lexer); /* Eact '.' */ + component = cp_parser_objc_message_args (parser); + return objc_build_property_reference_expr (receiver, TREE_PURPOSE (component)); +} +/* APPLE LOCAL end radar 5277239 */ + /* Parse an objc-message-receiver. objc-message-receiver: @@ -17421,6 +17867,32 @@ cp_parser_objc_protocol_refs_opt (cp_parser* parser) return protorefs; } +/* APPLE LOCAL begin radar 5355344 */ +/* This routine also parses a list of Objective-C protocol references; except that + if list is not valid, it returns FALSE and back-tracks parsing. */ + +static bool +cp_parser_objc_tentative_protocol_refs_opt (cp_parser* parser, tree *protorefs) +{ + *protorefs = NULL_TREE; + if(cp_lexer_next_token_is (parser->lexer, CPP_LESS)) + { + cp_parser_parse_tentatively (parser); + cp_lexer_consume_token (parser->lexer); /* Eat '<'. */ + *protorefs = cp_parser_objc_identifier_list (parser); + if (!cp_objc_protocol_id_list (*protorefs)) + { + cp_parser_abort_tentative_parse (parser); + return false; + } + if (cp_parser_parse_definitely (parser)) + cp_parser_require (parser, CPP_GREATER, "`>'"); + } + + return true; +} +/* APPLE LOCAL end radar 5355344 */ + /* Parse a Objective-C visibility specification. */ static void @@ -17554,10 +18026,25 @@ cp_parser_objc_selector (cp_parser* parser) } } +/* APPLE LOCAL begin radar 3803157 - objc attribute */ +static void +cp_parser_objc_maybe_attributes (cp_parser* parser, tree* attributes) +{ + cp_token *token = cp_lexer_peek_token (parser->lexer); + if (*attributes != NULL_TREE) + { + error ("method attributes must be specified at the end only"); + *attributes = NULL_TREE; + } + if (token->keyword == RID_ATTRIBUTE) + *attributes = cp_parser_attributes_opt (parser); +} + /* Parse an Objective-C params list. */ static tree -cp_parser_objc_method_keyword_params (cp_parser* parser) +cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes) +/* APPLE LOCAL end radar 3803157 - objc attribute */ { tree params = NULL_TREE; bool maybe_unary_selector_p = true; @@ -17566,36 +18053,58 @@ cp_parser_objc_method_keyword_params (cp_parser* parser) while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON) { tree selector = NULL_TREE, typename, identifier; + /* APPLE LOCAL radar 4157812 */ + tree attr = NULL_TREE; if (token->type != CPP_COLON) selector = cp_parser_objc_selector (parser); /* Detect if we have a unary selector. */ if (maybe_unary_selector_p - && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) - return selector; + && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) + /* APPLE LOCAL begin radar 3803157 - objc attribute */ + { + cp_parser_objc_maybe_attributes (parser, attributes); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) + return selector; + } + /* APPLE LOCAL end radar 3803157 - objc attribute */ maybe_unary_selector_p = false; cp_parser_require (parser, CPP_COLON, "`:'"); typename = cp_parser_objc_typename (parser); + /* APPLE LOCAL radar 4157812 */ + cp_parser_objc_maybe_attributes (parser, &attr); identifier = cp_parser_identifier (parser); + /* APPLE LOCAL radar 3803157 - objc attribute */ + cp_parser_objc_maybe_attributes (parser, attributes); params = chainon (params, objc_build_keyword_decl (selector, typename, - identifier)); + /* APPLE LOCAL radar 4157812 */ + identifier, attr)); token = cp_lexer_peek_token (parser->lexer); } + /* APPLE LOCAL begin radar 4290840 */ + if (params == NULL_TREE) + { + cp_parser_error (parser, "objective-c++ method declaration is expected"); + return error_mark_node; + } + /* APPLE LOCAL end radar 4290840 */ + return params; } /* Parse the non-keyword Objective-C params. */ static tree -cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp) +/* APPLE LOCAL radar 3803157 - objc attribute */ +cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, tree* attributes) { tree params = make_node (TREE_LIST); cp_token *token = cp_lexer_peek_token (parser->lexer); @@ -17610,11 +18119,13 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp) token = cp_lexer_peek_token (parser->lexer); if (token->type == CPP_ELLIPSIS) - { - cp_lexer_consume_token (parser->lexer); /* Eat '...'. */ - *ellipsisp = true; - break; - } + { + cp_lexer_consume_token (parser->lexer); /* Eat '...'. */ + *ellipsisp = true; + /* APPLE LOCAL radar 3803157 - objc attribute */ + cp_parser_objc_maybe_attributes (parser, attributes); + break; + } parmdecl = cp_parser_parameter_declaration (parser, false, NULL); parm = grokdeclarator (parmdecl->declarator, @@ -17655,15 +18166,19 @@ cp_parser_objc_interstitial_code (cp_parser* parser) /* Parse a method signature. */ static tree -cp_parser_objc_method_signature (cp_parser* parser) +/* APPLE LOCAL radar 3803157 - objc attribute */ +cp_parser_objc_method_signature (cp_parser* parser, tree* attributes) { tree rettype, kwdparms, optparms; bool ellipsis = false; cp_parser_objc_method_type (parser); rettype = cp_parser_objc_typename (parser); - kwdparms = cp_parser_objc_method_keyword_params (parser); - optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis); + /* APPLE LOCAL begin radar 3803157 - objc attribute */ + *attributes = NULL_TREE; + kwdparms = cp_parser_objc_method_keyword_params (parser, attributes); + optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes); + /* APPLE LOCAL end radar 3803157 - objc attribute */ return objc_build_method_signature (rettype, kwdparms, optparms, ellipsis); } @@ -17675,22 +18190,31 @@ cp_parser_objc_method_prototype_list (cp_parser* parser) { cp_token *token = cp_lexer_peek_token (parser->lexer); - while (token->keyword != RID_AT_END) + /* APPLE LOCAL 4093475 */ + while (token->keyword != RID_AT_END && token->type != CPP_EOF) { if (token->type == CPP_PLUS || token->type == CPP_MINUS) - { - objc_add_method_declaration - (cp_parser_objc_method_signature (parser)); - cp_parser_consume_semicolon_at_end_of_statement (parser); - } + { + /* APPLE LOCAL begin radar 3803157 - objc attribute */ + tree attributes, sig; + sig = cp_parser_objc_method_signature (parser, &attributes); + objc_add_method_declaration (sig, attributes); + /* APPLE LOCAL end radar 3803157 - objc attribute */ + cp_parser_consume_semicolon_at_end_of_statement (parser); + } + /* APPLE LOCAL begin C* interface */ + else if (token->keyword == RID_AT_PROPERTY) + objc_cp_parser_at_property (parser); + /* APPLE LOCAL end C* interface */ else - /* Allow for interspersed non-ObjC++ code. */ + /* Allow for interspersed non-ObjC++ code. */ cp_parser_objc_interstitial_code (parser); token = cp_lexer_peek_token (parser->lexer); } - cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */ + /* APPLE LOCAL 4093475 */ + cp_parser_require_keyword (parser, RID_AT_END, "`@end'"); objc_finish_interface (); } @@ -17701,27 +18225,49 @@ cp_parser_objc_method_definition_list (cp_parser* parser) { cp_token *token = cp_lexer_peek_token (parser->lexer); - while (token->keyword != RID_AT_END) + /* APPLE LOCAL 4093475 */ + while (token->keyword != RID_AT_END && token->type != CPP_EOF) { tree meth; if (token->type == CPP_PLUS || token->type == CPP_MINUS) - { - push_deferring_access_checks (dk_deferred); - objc_start_method_definition - (cp_parser_objc_method_signature (parser)); + { + /* APPLE LOCAL radar 4290840 */ + cp_token *ptk; + /* APPLE LOCAL begin radar 3803157 - objc attribute */ + tree sig, attribute; + push_deferring_access_checks (dk_deferred); + sig = cp_parser_objc_method_signature (parser, &attribute); + objc_start_method_definition (sig, attribute); + /* APPLE LOCAL end radar 3803157 - objc attribute */ /* For historical reasons, we accept an optional semicolon. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) cp_lexer_consume_token (parser->lexer); - perform_deferred_access_checks (); - stop_deferring_access_checks (); - meth = cp_parser_function_definition_after_declarator (parser, - false); - pop_deferring_access_checks (); - objc_finish_method_definition (meth); + /* APPLE LOCAL begin radar 4290840 */ + /* Check for all possibilities of illegal lookahead tokens. */ + ptk = cp_lexer_peek_token (parser->lexer); + /* APPLE LOCAL radar 6271728 */ + if (ptk->type == CPP_OPEN_BRACE) + { + perform_deferred_access_checks (); + stop_deferring_access_checks (); + meth = cp_parser_function_definition_after_declarator (parser, + false); + pop_deferring_access_checks (); + objc_finish_method_definition (meth); } + /* APPLE LOCAL begin radar 6271728 */ + else + cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); + /* APPLE LOCAL end radar 6271728 */ + /* APPLE LOCAL end radar 4290840 */ + } + /* APPLE LOCAL begin C* interface */ + else if (token->keyword == RID_AT_PROPERTY) + objc_cp_parser_at_property (parser); + /* APPLE LOCAL end C* interface */ else /* Allow for interspersed non-ObjC++ code. */ cp_parser_objc_interstitial_code (parser); @@ -17729,7 +18275,8 @@ cp_parser_objc_method_definition_list (cp_parser* parser) token = cp_lexer_peek_token (parser->lexer); } - cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */ + /* APPLE LOCAL 4093475 */ + cp_parser_require_keyword (parser, RID_AT_END, "`@end'"); objc_finish_implementation (); } @@ -17855,7 +18402,8 @@ cp_parser_objc_class_ivars (cp_parser* parser) /* Parse an Objective-C protocol declaration. */ static void -cp_parser_objc_protocol_declaration (cp_parser* parser) +/* APPLE LOCAL radar 4947311 */ +cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes) { tree proto, protorefs; cp_token *tok; @@ -17873,8 +18421,9 @@ cp_parser_objc_protocol_declaration (cp_parser* parser) /* Try a forward declaration first. */ if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON) { - objc_declare_protocols (cp_parser_objc_identifier_list (parser)); - finish: + /* APPLE LOCAL radar 4947311 */ + objc_declare_protocols (cp_parser_objc_identifier_list (parser), attributes); + finish: cp_parser_consume_semicolon_at_end_of_statement (parser); } @@ -17883,20 +18432,23 @@ cp_parser_objc_protocol_declaration (cp_parser* parser) { proto = cp_parser_identifier (parser); protorefs = cp_parser_objc_protocol_refs_opt (parser); - objc_start_protocol (proto, protorefs); + /* APPLE LOCAL radar 4947311 */ + objc_start_protocol (proto, protorefs, attributes); cp_parser_objc_method_prototype_list (parser); } } /* Parse an Objective-C superclass or category. */ +/* APPLE LOCAL begin radar 4965989 */ static void cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super, - tree *categ) + tree *categ, bool *is_category) { cp_token *next = cp_lexer_peek_token (parser->lexer); *super = *categ = NULL_TREE; + *is_category = false; if (next->type == CPP_COLON) { cp_lexer_consume_token (parser->lexer); /* Eat ':'. */ @@ -17905,29 +18457,47 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super, else if (next->type == CPP_OPEN_PAREN) { cp_lexer_consume_token (parser->lexer); /* Eat '('. */ - *categ = cp_parser_identifier (parser); + /* APPLE LOCAL begin radar 4965989 */ + next = cp_lexer_peek_token (parser->lexer); + *categ = (next->type == CPP_CLOSE_PAREN) ? NULL_TREE : cp_parser_identifier (parser); + *is_category = true; + /* APPLE LOCAL end radar 4965989 */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); } } +/* APPLE LOCAL end radar 4965989 */ /* Parse an Objective-C class interface. */ static void -cp_parser_objc_class_interface (cp_parser* parser) +/* APPLE LOCAL radar 4947311 */ +cp_parser_objc_class_interface (cp_parser* parser, tree attributes) { tree name, super, categ, protos; - + /* APPLE LOCAL radar 4965989 */ + bool is_categ; + /* APPLE LOCAL radar 4947311 */ + /* Code for radar 4548636 removed. */ cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */ name = cp_parser_identifier (parser); - cp_parser_objc_superclass_or_category (parser, &super, &categ); + /* APPLE LOCAL radar 4965989 */ + cp_parser_objc_superclass_or_category (parser, &super, &categ, &is_categ); protos = cp_parser_objc_protocol_refs_opt (parser); - + /* We have either a class or a category on our hands. */ - if (categ) - objc_start_category_interface (name, categ, protos); + /* APPLE LOCAL radar 4965989 */ + if (is_categ) + /* APPLE LOCAL begin radar 4548636 */ + { + if (attributes) + error ("attributes may not be specified on a category"); + objc_start_category_interface (name, categ, protos); + } + /* APPLE LOCAL end radar 4548636 */ else { - objc_start_class_interface (name, super, protos); + /* APPLE LOCAL radar 4548636 */ + objc_start_class_interface (name, super, protos, attributes); /* Handle instance variable declarations, if any. */ cp_parser_objc_class_ivars (parser); objc_continue_interface (); @@ -17942,14 +18512,25 @@ static void cp_parser_objc_class_implementation (cp_parser* parser) { tree name, super, categ; - + /* APPLE LOCAL radar 4965989 */ + bool is_categ; cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */ name = cp_parser_identifier (parser); - cp_parser_objc_superclass_or_category (parser, &super, &categ); + /* APPLE LOCAL radar 4965989 */ + cp_parser_objc_superclass_or_category (parser, &super, &categ, &is_categ); /* We have either a class or a category on our hands. */ - if (categ) - objc_start_category_implementation (name, categ); + /* APPLE LOCAL begin radar 4965989 */ + if (is_categ) + { + if (categ == NULL_TREE) + { + error ("cannot implement anonymous category"); + return; + } + objc_start_category_implementation (name, categ); + } + /* APPLE LOCAL end radar 4965989 */ else { objc_start_class_implementation (name, super); @@ -17987,10 +18568,24 @@ cp_parser_objc_declaration (cp_parser* parser) cp_parser_objc_class_declaration (parser); break; case RID_AT_PROTOCOL: - cp_parser_objc_protocol_declaration (parser); + /* APPLE LOCAL radar 4947311 */ + cp_parser_objc_protocol_declaration (parser, NULL_TREE); break; + /* APPLE LOCAL begin radar 4548636 - radar 4947311 */ + case RID_ATTRIBUTE: + { + tree attributes = NULL_TREE; + cp_parser_objc_maybe_attributes (parser, &attributes); + if (cp_lexer_peek_token (parser->lexer)->keyword == RID_AT_INTERFACE) + cp_parser_objc_class_interface (parser, attributes); + else if (cp_lexer_peek_token (parser->lexer)->keyword == RID_AT_PROTOCOL) + cp_parser_objc_protocol_declaration (parser, attributes); + break; + } + /* APPLE LOCAL end radar 4548636 - radar 4947311 */ case RID_AT_INTERFACE: - cp_parser_objc_class_interface (parser); + /* APPLE LOCAL radar 4947311 */ + cp_parser_objc_class_interface (parser, NULL_TREE); break; case RID_AT_IMPLEMENTATION: cp_parser_objc_class_implementation (parser); @@ -18031,7 +18626,8 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) { /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false); + /* APPLE LOCAL radar 5982990 */ + cp_parser_compound_statement (parser, NULL, false, false); objc_begin_try_stmt (location, pop_stmt_list (stmt)); while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH)) @@ -18041,14 +18637,10 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) { cp_lexer_consume_token (parser->lexer); cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); - parmdecl = cp_parser_parameter_declaration (parser, false, NULL); - parm = grokdeclarator (parmdecl->declarator, - &parmdecl->decl_specifiers, - PARM, /*initialized=*/0, - /*attrlist=*/NULL); cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); objc_begin_catch_clause (parm); - cp_parser_compound_statement (parser, NULL, false); + /* APPLE LOCAL radar 5982990 */ + cp_parser_compound_statement (parser, NULL, false, false); objc_finish_catch_clause (); } @@ -18059,7 +18651,8 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) { /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false); + /* APPLE LOCAL radar 5982990 */ + cp_parser_compound_statement (parser, NULL, false, false); objc_build_finally_clause (location, pop_stmt_list (stmt)); } @@ -18088,7 +18681,8 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) { /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false); + /* APPLE LOCAL radar 5982990 */ + cp_parser_compound_statement (parser, NULL, false, flag_objc_sjlj_exceptions); return objc_build_synchronized (location, lock, pop_stmt_list (stmt)); } @@ -18136,7 +18730,1735 @@ cp_parser_objc_statement (cp_parser * parser) { return error_mark_node; } - + +/* APPLE LOCAL begin C* language */ +/* Routine closes up the C*'s foreach statement. +*/ + +static void +objc_finish_foreach_stmt (tree for_stmt) +{ + if (flag_new_for_scope > 0) + { + tree scope = TREE_CHAIN (for_stmt); + TREE_CHAIN (for_stmt) = NULL; + add_stmt (do_poplevel (scope)); + } + + finish_stmt (); +} + +/* + Synthesizer routine for C*'s feareach statement. + + It synthesizes: + for ( type elem in collection) { stmts; } + + Into: + { + type elem; + __objcFastEnumerationState enumState = { 0 }; + id items[16]; + + unsigned long limit = [collection countByEnumeratingWithState:&enumState objects:items count:16]; + if (limit) { + unsigned long startMutations = *enumState.mutationsPtr; + do { + unsigned long counter = 0; + do { + if (startMutations != *enumState.mutationsPtr) objc_enumerationMutation(collection); + elem = enumState.itemsPtr[counter++]; + stmts; + } while (counter < limit); + } while (limit = [collection countByEnumeratingWithState:&enumState objects:items count:16]); + } + else + elem = nil; radar 4854605, 5128402 + +*/ + +static void +objc_foreach_stmt (cp_parser* parser, tree statement) +{ + unsigned char in_statement; + tree enumerationMutation_call_exp; + tree countByEnumeratingWithState; + tree receiver; + tree exp, bind; + tree enumState_decl, items_decl; + tree limit_decl, limit_decl_assign_expr; + tree outer_if_stmt, inner_if_stmt, if_condition, startMutations_decl; + tree outer_do_stmt, inner_do_stmt, do_condition; + tree counter_decl; + tree_stmt_iterator i = tsi_start (TREE_CHAIN (statement)); + tree t = tsi_stmt (i); + /* APPLE LOCAL radar 5130983 */ + tree elem_decl = TREE_CODE (t) == DECL_EXPR ? DECL_EXPR_DECL (t) : t; + + receiver = cp_parser_condition (parser); + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + + /* APPLE LOCAL begin radar 4507230 */ + if (!objc_type_valid_for_messaging (TREE_TYPE (elem_decl))) + { + error ("selector element does not have a valid object type"); + return; + } + + if (!objc_type_valid_for_messaging (TREE_TYPE (receiver))) + { + error ("expression does not have a valid object type"); + return; + } + /* APPLE LOCAL end radar 4507230 */ + + enumerationMutation_call_exp = objc_build_foreach_components (receiver, &enumState_decl, + &items_decl, &limit_decl, + &startMutations_decl, &counter_decl, + &countByEnumeratingWithState); + + /* __objcFastEnumerationState enumState = { 0 }; */ + exp = build_stmt (DECL_EXPR, enumState_decl); + bind = build3 (BIND_EXPR, void_type_node, enumState_decl, exp, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + + /* id items[16]; */ + bind = build3 (BIND_EXPR, void_type_node, items_decl, NULL, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + + /* Generate this statement and add it to the list. */ + /* limit = [collection countByEnumeratingWithState:&enumState objects:items count:16] */ + limit_decl_assign_expr = build2 (MODIFY_EXPR, TREE_TYPE (limit_decl), limit_decl, + countByEnumeratingWithState); + bind = build3 (BIND_EXPR, void_type_node, limit_decl, NULL, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + + /* if (limit) { */ + outer_if_stmt = begin_if_stmt (); + /* APPLE LOCAL radar 4547045 */ + if_condition = build_binary_op (NE_EXPR, limit_decl_assign_expr, + fold_convert (TREE_TYPE (limit_decl), integer_zero_node), + 1); + + finish_if_stmt_cond (if_condition, outer_if_stmt); + + /* unsigned long startMutations = *enumState.mutationsPtr; */ + exp = objc_build_component_ref (enumState_decl, get_identifier("mutationsPtr")); + exp = build_indirect_ref (exp, "unary *"); + exp = build2 (MODIFY_EXPR, void_type_node, startMutations_decl, exp); + bind = build3 (BIND_EXPR, void_type_node, startMutations_decl, exp, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + + /* do { */ +/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ + outer_do_stmt = begin_do_stmt (NULL_TREE); + +/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ + /* Body of the outer do-while loop */ + /* unsigned int counter = 0; */ + exp = build2 (MODIFY_EXPR, void_type_node, counter_decl, + fold_convert (TREE_TYPE (counter_decl), integer_zero_node)); + bind = build3 (BIND_EXPR, void_type_node, counter_decl, exp, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + + /* do { */ +/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ + inner_do_stmt = begin_do_stmt (NULL_TREE); + +/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ + /* Body of the inner do-while loop */ + + /* if (startMutations != *enumState.mutationsPtr) objc_enumerationMutation (collection); */ + inner_if_stmt = begin_if_stmt (); + exp = objc_build_component_ref (enumState_decl, get_identifier("mutationsPtr")); + exp = build_indirect_ref (exp, "unary *"); + if_condition = build_binary_op (NE_EXPR, startMutations_decl, exp, 1); + finish_if_stmt_cond (if_condition, inner_if_stmt); + + add_stmt (enumerationMutation_call_exp); + finish_then_clause (inner_if_stmt); + finish_if_stmt (inner_if_stmt); + + /* elem = enumState.itemsPtr [counter]; */ + exp = objc_build_component_ref (enumState_decl, get_identifier("itemsPtr")); + exp = build_array_ref (exp, counter_decl); + add_stmt (build2 (MODIFY_EXPR, void_type_node, elem_decl, exp)); + /* APPLE LOCAL radar 4538105 */ + TREE_USED (elem_decl) = 1; + + /* counter++; */ + exp = build2 (PLUS_EXPR, TREE_TYPE (counter_decl), counter_decl, + build_int_cst (NULL_TREE, 1)); + add_stmt (build2 (MODIFY_EXPR, void_type_node, counter_decl, exp)); + + /* ADD << stmts >> from the foreach loop. */ + /* Parse the body of the for-statement. */ + in_statement = parser->in_statement; + parser->in_statement = IN_ITERATION_STMT; + cp_parser_already_scoped_statement (parser); + parser->in_statement = in_statement; + + finish_do_body (inner_do_stmt); + + /* } while (counter < limit ); */ + do_condition = build_binary_op (LT_EXPR, counter_decl, limit_decl, 1); + finish_do_stmt (do_condition, inner_do_stmt); + DO_FOREACH (inner_do_stmt) = integer_zero_node; + /* APPLE LOCAL radar 4667060 */ + DO_FOREACH (outer_do_stmt) = elem_decl; + + finish_do_body (outer_do_stmt); + + /* } while (limit = [collection countByEnumeratingWithState:&enumState objects:items count:16]); */ + + exp = unshare_expr (limit_decl_assign_expr); + do_condition = build_binary_op (NE_EXPR, exp, + fold_convert (TREE_TYPE (limit_decl), integer_zero_node), + 1); + finish_do_stmt (do_condition, outer_do_stmt); + + + finish_then_clause (outer_if_stmt); + + /* } */ + /* APPLE LOCAL begin radar 4854605 - radar 5128402 */ + begin_else_clause (outer_if_stmt); + add_stmt (build2 (MODIFY_EXPR, void_type_node, elem_decl, + fold_convert (TREE_TYPE (elem_decl), integer_zero_node))); + finish_else_clause (outer_if_stmt); + /* APPLE LOCAL end radar 4854605 - radar 5128402 */ + + finish_if_stmt (outer_if_stmt); + + objc_finish_foreach_stmt (statement); +} +/* APPLE LOCAL end C* language */ +/* APPLE LOCAL begin blocks 6040305 (ce) */ +#define I_SYMBOL_BINDING(t) IDENTIFIER_BINDING(t) + +tree build_component_ref (tree e, tree member); +tree +build_component_ref (tree e, tree member) +{ + if (!DECL_P (member)) + member = lookup_member (TREE_TYPE (e), member, 0, 0); + if (processing_template_decl) + return build3 (COMPONENT_REF, TREE_TYPE (member), e, DECL_NAME (member), NULL_TREE); + return build_class_member_access_expr (e, member, + NULL_TREE, false); +} + +/* APPLE LOCAL begin radar 6214617 */ +static bool +cp_block_requires_copying (tree exp) +{ + return (block_requires_copying (exp) + || TYPE_HAS_CONSTRUCTOR (TREE_TYPE (exp)) + || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp))); +} +/* APPLE LOCAL end radar 6214617 */ + +/* APPLE LOCAL begin radar 5847213 - radar 6329245 */ +/** build_descriptor_block_decl - + This routine builds a static block_descriptior variable of type: + struct __block_descriptor; and initializes it to: + {0, sizeof(struct literal_block_n), + copy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE + destroy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE + } + */ +static tree +build_descriptor_block_decl (tree block_struct_type, struct block_sema_info *block_impl) +{ + extern tree create_tmp_var_raw (tree, const char *); + static int desc_unique_count; + int size; + tree helper_addr; + tree decl, constructor; + char name [32]; + VEC(constructor_elt,gc) *impl_v = NULL; + tree descriptor_type = + TREE_TYPE (build_block_descriptor_type (block_impl->BlockHasCopyDispose)); + + sprintf (name, "__block_descriptor_tmp_%d", ++desc_unique_count); + decl = create_tmp_var_raw (descriptor_type, name); + DECL_CONTEXT (decl) = NULL_TREE; + + /* Initialize "reserved" field to 0 for now. */ + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, build_int_cst (long_unsigned_type_node, 0)); + + /* Initialize "Size" field. */ + size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (block_struct_type)); + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, build_int_cst (long_unsigned_type_node, size)); + + if (block_impl->BlockHasCopyDispose) + { + /* Initialize "CopyFuncPtr" and "DestroyFuncPtr" fields. */ + /* Helpers were previously generated completeley as a nested + function (and context was required for code gen.) But they are not, + so context must be set to NULL so initialization logic does not complain. */ + DECL_CONTEXT (block_impl->copy_helper_func_decl) = NULL_TREE; + helper_addr = build_fold_addr_expr (block_impl->copy_helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, helper_addr); + + DECL_CONTEXT (block_impl->destroy_helper_func_decl) = NULL_TREE; + helper_addr = build_fold_addr_expr (block_impl->destroy_helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, helper_addr); + } + /* Create a CONSTRUCTOR to represent the braced-initializer. */ + constructor = make_node (CONSTRUCTOR); + CONSTRUCTOR_ELTS (constructor) = impl_v; + TREE_PUBLIC (decl) = 0; + TREE_STATIC (decl) = 1; + cp_finish_decl (decl, constructor, 0, 0, LOOKUP_ONLYCONVERTING); + return decl; +} + +/* APPLE LOCAL begin radar 6300081 */ +/* This function builds a "generic" block struct type, to be passed + into the debug information for blocks pointers, to allow gdb to + find the actual function pointer for the block. Any time the Blocks + structure layout changes, this may also need to change. + + Currently a block pointer is a pointer to a __block_literal_n struct, + the third field of which is a pointer to a __block_descriptor struct, + whose third field is the function pointer. There are other fields as + well, but these are the ones gdb needs to know about to find the + function pointer. Therefore a generic block struct currently looks + like this: + + struct __block_literal_generic + { + void * __isa; + int __flags; + int __reserved; + void *__FuncPtr; + struct __block_descriptor + { + unsigned long int reserved; + unsigned long int Size; + } *__descriptor; + }; + + IF AT ANY TIME THE STRUCTURE OF A __BLOCK_LITERAL_N CHANGES, THIS + MUST BE CHANGED ALSO!! + + */ + +tree +/* APPLE LOCAL radar 6353006 */ +c_build_generic_block_struct_type (void) +{ + tree fields = NULL_TREE; + tree field; + tree block_struct_type; + + push_to_top_level (); + block_struct_type = xref_tag (record_type, + get_identifier ("__block_literal_generic"), + ts_current, false); + xref_basetypes (block_struct_type, NULL_TREE); + CLASSTYPE_DECLARED_CLASS (block_struct_type) = 0; + pushclass (block_struct_type); + + field = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node); + TREE_CHAIN (field) = fields; + fields = field; + + field = build_decl (FIELD_DECL, get_identifier ("__flags"), + integer_type_node); + TREE_CHAIN (field) = fields; + fields = field; + + field = build_decl (FIELD_DECL, get_identifier ("__reserved"), + integer_type_node); + TREE_CHAIN (field) = fields; + fields = field; + + field = build_decl (FIELD_DECL, get_identifier ("__FuncPtr"), + ptr_type_node); + TREE_CHAIN (field) = fields; + fields = field; + + field = build_decl (FIELD_DECL, get_identifier ("__descriptor"), + build_block_descriptor_type (false)); + TREE_CHAIN (field) = fields; + fields = field; + + TYPE_FIELDS (block_struct_type) = fields; + TYPE_NAME (block_struct_type) = build_decl (TYPE_DECL, + get_identifier ("__block_literal_generic"), + block_struct_type); + TYPE_STUB_DECL (block_struct_type) = TYPE_NAME (block_struct_type); + TYPE_BLOCK_IMPL_STRUCT (block_struct_type) = 1; + finish_struct (block_struct_type, NULL_TREE); + pop_from_top_level (); + + return block_struct_type; +} +/* APPLE LOCAL end radar 6300081 */ + +/** build_block_struct_type - + struct __block_literal_n { + void *__isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int __flags; + int __reserved; + void *__FuncPtr; + + struct __block_descriptor { + unsigned long int reserved; // NULL + unsigned long int Size; // sizeof(struct __block_literal_n) + + // optional helper functions + void *CopyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + } *__descriptor; + + // imported variables + int x; // ref variable list ... + int *y; // byref variable list + }; + */ +static tree +build_block_struct_type (struct block_sema_info * block_impl) +{ + tree fields = NULL_TREE, field, chain; + char buffer[32]; + static int unique_count; + tree block_struct_type; + + /* Check and see if this block is required to have a Copy/Dispose + helper function. If yes, set BlockHasCopyDispose to TRUE. */ + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + /* APPLE LOCAL begin radar 6214617 */ + if (cp_block_requires_copying (TREE_VALUE (chain))) + { + tree type = TREE_TYPE (TREE_VALUE (chain)); + block_impl->BlockHasCopyDispose = TRUE; + if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type)) + { + block_impl->BlockImportsCxxObjects = TRUE; + break; + } + /* APPLE LOCAL end radar 6214617 */ + } + + /* Further check to see that we have __block variables which require + Copy/Dispose helpers. */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + block_impl->BlockHasCopyDispose = TRUE; + break; + } + + sprintf(buffer, "__block_literal_%d", ++unique_count); + push_to_top_level (); + /* APPLE LOCAL begin radar 6243400 */ + block_struct_type = xref_tag (record_type, get_identifier (buffer), ts_current, false); + xref_basetypes (block_struct_type, NULL_TREE); + CLASSTYPE_DECLARED_CLASS (block_struct_type) = 0; + pushclass (block_struct_type); + /* APPLE LOCAL end radar 6243400 */ + /* void * __isa; */ + field = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node); + TREE_CHAIN (field) = fields; + fields = field; + + /* int __flags. */ + field = build_decl (FIELD_DECL, get_identifier ("__flags"), integer_type_node); + TREE_CHAIN (field) = fields; + fields = field; + + /* int __reserved. */ + field = build_decl (FIELD_DECL, get_identifier ("__reserved"), integer_type_node); + TREE_CHAIN (field) = fields; + fields = field; + + /* void *__FuncPtr. */ + field = build_decl (FIELD_DECL, get_identifier ("__FuncPtr"), + ptr_type_node); + TREE_CHAIN (field) = fields; + fields = field; + + /* struct __block_descriptor *__descriptor */ + field = build_decl (FIELD_DECL, get_identifier ("__descriptor"), + build_block_descriptor_type (block_impl->BlockHasCopyDispose)); + TREE_CHAIN (field) = fields; + fields = field; + + if (block_impl->BlockHasCopyDispose) + { + /* If inner block of a nested block has BlockHasCopyDispose, so + does its outer block. */ + if (block_impl->prev_block_info) + block_impl->prev_block_info->BlockHasCopyDispose = TRUE; + } + + /* int x; // ref variable list ... */ + for (chain = block_impl->block_ref_decl_list; chain; chain = TREE_CHAIN (chain)) + { + tree p = TREE_VALUE (chain); + /* Note! const-ness of copied in variable must not be carried over to the + type of the synthesized struct field. It prevents to assign to this + field when copy constructor is synthesized. */ + field = build_decl (FIELD_DECL, DECL_NAME (p), + c_build_qualified_type (TREE_TYPE (p), + TYPE_UNQUALIFIED)); + TREE_CHAIN (field) = fields; + fields = field; + } + + /* int *y; // byref variable list */ + for (chain = block_impl->block_byref_decl_list; chain; chain = TREE_CHAIN (chain)) + { + tree p = TREE_VALUE (chain); + field = build_decl (FIELD_DECL, DECL_NAME (p), + TREE_TYPE (p)); + TREE_CHAIN (field) = fields; + fields = field; + } + + /* APPLE LOCAL begin radar 6243400 */ + TYPE_FIELDS (block_struct_type) = fields; + TYPE_NAME (block_struct_type) = + build_decl (TYPE_DECL, get_identifier (buffer), block_struct_type); + TYPE_STUB_DECL (block_struct_type) = TYPE_NAME (block_struct_type); + finish_struct (block_struct_type, NULL_TREE); + pop_from_top_level (); + /* APPLE LOCAL end radar 6243400 */ + return block_struct_type; +} + +/** + build_block_struct_initlist - builds the initializer list: + { &_NSConcreteStackBlock or &_NSConcreteGlobalBlock // __isa, + BLOCK_USE_STRET | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL // __flags, + 0, // __reserved, + &helper_1, // __FuncPtr, + &static_descriptor_variable // __descriptor, + x, // user variables. + &y + ... + } +*/ +/* APPLE LOCAL begin radar 6169527 */ +/* This routine is entirely rewritten as we now have to deal with full-blown + c++ classes with fields which may require construction. */ +static VEC(constructor_elt,gc) * +build_block_struct_initlist (tree block_struct_type, + struct block_sema_info *block_impl) +{ + tree expr, chain, helper_addr; + /* APPLE LOCAL radar 7735196 */ + unsigned flags = 0; + static tree NSConcreteStackBlock_decl = NULL_TREE; + static tree NSConcreteGlobalBlock_decl = NULL_TREE; + VEC(constructor_elt,gc) *impl_v = NULL; + tree descriptor_block_decl = build_descriptor_block_decl (block_struct_type, block_impl); + + if (block_impl->BlockHasCopyDispose) + /* Note! setting of this flag merely indicates to the runtime that + we have destroy_helper_block/copy_helper_block helper + routines. */ + flags |= BLOCK_HAS_COPY_DISPOSE; + /* APPLE LOCAL begin radar 6214617 */ + /* Set BLOCK_HAS_CXX_OBJ if block is importing a cxx object. */ + if (block_impl->BlockImportsCxxObjects) + flags |= BLOCK_HAS_CXX_OBJ; + /* APPLE LOCAL end radar 6214617 */ +/* APPLE LOCAL begin radar 7735196 */ + if (block_impl->return_type && aggregate_value_p(block_impl->return_type, 0)) + flags |= BLOCK_USE_STRET; + /* APPLE LOCAL end 7735196 */ + /* APPLE LOCAL begin radar 6230297 */ + if (!current_function_decl || + (block_impl->block_ref_decl_list == NULL_TREE && + block_impl->block_byref_decl_list == NULL_TREE)) + /* APPLE LOCAL end radar 6230297 */ + { + /* This is a global block. */ + /* Find an existing declaration for _NSConcreteGlobalBlock or declare + extern void *_NSConcreteGlobalBlock; */ + if (NSConcreteGlobalBlock_decl == NULL_TREE) + { + tree name_id = get_identifier("_NSConcreteGlobalBlock"); + NSConcreteGlobalBlock_decl = lookup_name (name_id); + if (!NSConcreteGlobalBlock_decl) + { + NSConcreteGlobalBlock_decl = build_decl (VAR_DECL, name_id, ptr_type_node); + DECL_EXTERNAL (NSConcreteGlobalBlock_decl) = 1; + TREE_PUBLIC (NSConcreteGlobalBlock_decl) = 1; + pushdecl_top_level (NSConcreteGlobalBlock_decl); + rest_of_decl_compilation (NSConcreteGlobalBlock_decl, 0, 0); + } + } + /* APPLE LOCAL begin radar 6457359 */ + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, + convert (ptr_type_node, + build_fold_addr_expr (NSConcreteGlobalBlock_decl))); + /* APPLE LOCAL end radar 6457359 */ + flags |= BLOCK_IS_GLOBAL; + } + else + { + /* Find an existing declaration for _NSConcreteStackBlock or declare + extern void *_NSConcreteStackBlock; */ + if (NSConcreteStackBlock_decl == NULL_TREE) + { + tree name_id = get_identifier("_NSConcreteStackBlock"); + NSConcreteStackBlock_decl = lookup_name (name_id); + if (!NSConcreteStackBlock_decl) + { + NSConcreteStackBlock_decl = build_decl (VAR_DECL, name_id, ptr_type_node); + DECL_EXTERNAL (NSConcreteStackBlock_decl) = 1; + TREE_PUBLIC (NSConcreteStackBlock_decl) = 1; + pushdecl_top_level (NSConcreteStackBlock_decl); + rest_of_decl_compilation (NSConcreteStackBlock_decl, 0, 0); + } + } + /* APPLE LOCAL begin radar 6457359 */ + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, + convert (ptr_type_node, + build_fold_addr_expr (NSConcreteStackBlock_decl))); + /* APPLE LOCAL end radar 6457359 */ + } + + /* __flags */ + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, build_int_cst (integer_type_node, flags)); + /* __reserved */ + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, build_int_cst (integer_type_node, 0)); + /* __FuncPtr */ + helper_addr = build_fold_addr_expr (block_impl->helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, helper_addr); + + /* &static_descriptor_variable initializer */ + expr = build_fold_addr_expr (descriptor_block_decl); + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, expr); + + for (chain = block_impl->block_original_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + { + tree y = TREE_VALUE (chain); + TREE_USED (y) = 1; + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, y); + } + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + { + tree y = lookup_name (DECL_NAME (TREE_VALUE (chain))); + tree forwarding_expr; + gcc_assert (y); + TREE_USED (y) = 1; + if (COPYABLE_BYREF_LOCAL_VAR (y)) + { + /* For variables declared __block, either the original one + at the point of declaration or the imported version (which is + initialized in the helper function's prologue) is used to + initilize the byref variable field in the temporary. */ + if (TREE_CODE (TREE_TYPE (y)) != RECORD_TYPE) + y = build_indirect_ref (y, "unary *"); + /* We will be using the __block_struct_variable.__forwarding as the + initializer. */ + forwarding_expr = build_component_ref (y, get_identifier ("__forwarding")); + } + else + /* Global variable is always assumed passed by its address. */ + forwarding_expr = build_fold_addr_expr (y); + + CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, forwarding_expr); + } + return impl_v; +} +/* APPLE LOCAL end radar 6169527 */ +/* APPLE LOCAL end radar 5847213 - radar 6329245 */ + +/** + build_block_literal_tmp - This routine: + + 1) builds block type: + struct __block_literal_n { + void *__isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int __flags; + int __reserved; + void *__FuncPtr; + + struct __block_descriptor { + unsigned long int reserved; // NULL + unsigned long int Size; // sizeof(struct Block_literal_1) + + // optional helper functions + void *CopyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + } *__descriptor; + + // imported variables + int x; // ref variable list ... + int *y; // byref variable list + }; + + 2) build function prototype: + double helper_1(struct block_1 *ii, int z); + + 3) build the temporary initialization: + struct block_1 I = { + { &_NSConcreteStackBlock or &_NSConcreteGlobalBlock // isa, + BLOCK_HAS_CXX_OBJ | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL // flags, + 0, // reserved, + &helper_1, + &{ + NULL, + sizeof(struct block_1), + copy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE + destroy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE + }, + x, + &y +}; + +It return the temporary. +*/ +/* APPLE LOCAL begin radar 6169527 */ +static tree +build_block_literal_tmp (const char *name, + struct block_sema_info * block_impl) +{ + extern tree create_tmp_var_raw (tree, const char *); + tree block_holder_tmp_decl; + tree constructor; + tree block_struct_type = TREE_TYPE (block_impl->block_arg_ptr_type); + /* APPLE LOCAL begin radar 6230297 */ + bool staticBlockTmp = (block_impl->block_ref_decl_list == NULL_TREE && + block_impl->block_byref_decl_list == NULL_TREE); + + block_holder_tmp_decl = create_tmp_var_raw (block_struct_type, name); + /* Context will not be known until when the literal is synthesized. + This is more so in the case of nested block literal blocks. */ + maybe_push_decl (block_holder_tmp_decl); + DECL_CONTEXT (block_holder_tmp_decl) = staticBlockTmp ? NULL_TREE + : current_function_decl; + if (staticBlockTmp) + DECL_CONTEXT (block_impl->helper_func_decl) = NULL_TREE; + /* APPLE LOCAL end radar 6230297 */ + DECL_ARTIFICIAL (block_holder_tmp_decl) = 1; + + /* Create a CONSTRUCTOR to represent the braced-initializer. */ + constructor = make_node (CONSTRUCTOR); + + CONSTRUCTOR_ELTS (constructor) = build_block_struct_initlist (block_struct_type, + block_impl); + /* Temporary representing a global block is made global static. */ + /* APPLE LOCAL radar 6230297 */ + if (staticBlockTmp || global_bindings_p ()) { + TREE_PUBLIC (block_holder_tmp_decl) = 0; + TREE_STATIC (block_holder_tmp_decl) = 1; + } + cp_finish_decl (block_holder_tmp_decl, constructor, 0, 0, LOOKUP_ONLYCONVERTING); + return block_holder_tmp_decl; +} +/* APPLE LOCAL end radar 6169527 */ + +static tree +clean_and_exit (tree block) +{ + pop_function_context (); + pop_lang_context (); + if (current_function_decl) + free (finish_block (block)); + return error_mark_node; +} + +/** synth_copy_helper_block_func - This function synthesizes + void copy_helper_block (struct block* _dest, struct block *_src) function. + */ + +static void +synth_copy_helper_block_func (struct block_sema_info * block_impl) +{ + tree stmt, chain; + tree dst_arg, src_arg; + /* struct c_arg_info * arg_info; */ + /* Set up: (struct block* _dest, struct block *_src) parameters. */ + dst_arg = build_decl (PARM_DECL, get_identifier ("_dst"), + block_impl->block_arg_ptr_type); + DECL_CONTEXT (dst_arg) = cur_block->copy_helper_func_decl; + TREE_USED (dst_arg) = 1; + DECL_ARG_TYPE (dst_arg) = block_impl->block_arg_ptr_type; + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + block_impl->block_arg_ptr_type); + DECL_CONTEXT (src_arg) = cur_block->copy_helper_func_decl; + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = block_impl->block_arg_ptr_type; + /* arg_info = xcalloc (1, sizeof (struct c_arg_info)); */ + TREE_CHAIN (dst_arg) = src_arg; + + pushdecl (cur_block->copy_helper_func_decl); + /* arg_info->parms = dst_arg; */ + /* arg_info->types = tree_cons (NULL_TREE, block_impl->block_arg_ptr_type, + tree_cons (NULL_TREE, + block_impl->block_arg_ptr_type, + NULL_TREE)); */ + DECL_ARGUMENTS (cur_block->copy_helper_func_decl) = dst_arg; + /* function header synthesis. */ + push_function_context (); + /* start_block_helper_function (cur_block->copy_helper_func_decl, true); */ + /* store_parm_decls (arg_info); */ + start_preparsed_function (cur_block->copy_helper_func_decl, + /*attrs*/NULL_TREE, + SF_PRE_PARSED); + + /* Body of the function. */ + stmt = begin_compound_stmt (BCS_FN_BODY); + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + /* APPLE LOCAL radar 6214617 */ + if (cp_block_requires_copying (TREE_VALUE (chain))) + { + /* APPLE LOCAL begin radar 6175959 */ + int flag = 0; + tree p = TREE_VALUE (chain); + tree dst_block_component, src_block_component; + dst_block_component = build_component_ref (build_indirect_ref (dst_arg, "->"), + DECL_NAME (p)); + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + if (TREE_CODE (TREE_TYPE (p)) == BLOCK_POINTER_TYPE) + /* _Block_object_assign(&_dest->myImportedBlock, _src->myImportedClosure, BLOCK_FIELD_IS_BLOCK) */ + flag = BLOCK_FIELD_IS_BLOCK; + /* APPLE LOCAL begin radar 6214617 */ + else if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (p)) + || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p))) + { + tree call_exp = build_aggr_init (dst_block_component, src_block_component, + LOOKUP_ONLYCONVERTING); + add_stmt (call_exp); + } + /* APPLE LOCAL end radar 6214617 */ + else + /* _Block_object_assign(&_dest->myImportedBlock, _src->myImportedClosure, BLOCK_FIELD_IS_OBJECT) */ + flag = BLOCK_FIELD_IS_OBJECT; + if (flag) + { + tree call_exp; + dst_block_component = build_fold_addr_expr (dst_block_component); + call_exp = build_block_object_assign_call_exp (dst_block_component, src_block_component, flag); + add_stmt (call_exp); + } + /* APPLE LOCAL end radar 6175959 */ + } + + /* For each __block declared variable used in |...| Must generate call to: + _Block_object_assign(&_dest->myImportedBlock, _src->myImportedBlock, BLOCK_FIELD_IS_BYREF [|BLOCK_FIELD_IS_WEAK]) + */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + int flag = BLOCK_FIELD_IS_BYREF; + tree call_exp; + tree p = TREE_VALUE (chain); + tree dst_block_component, src_block_component; + dst_block_component = build_component_ref (build_indirect_ref (dst_arg, "->"), + DECL_NAME (p)); + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + /* _Block_object_assign(&_dest->myImportedClosure, _src->myImportedClosure, BLOCK_FIELD_IS_BYREF [|BLOCK_FIELD_IS_WEAK]) */ + if (COPYABLE_WEAK_BLOCK (p)) + flag |= BLOCK_FIELD_IS_WEAK; + + dst_block_component = build_fold_addr_expr (dst_block_component); + call_exp = build_block_object_assign_call_exp (dst_block_component, src_block_component, flag); + add_stmt (call_exp); + } + + finish_compound_stmt (stmt); + /* APPLE LOCAL radar 6169580 */ + finish_function (4); + /* Hum, would be nice if someone else did this for us. */ + if (global_bindings_p ()) + cgraph_finalize_function (block_impl->copy_helper_func_decl, false); + pop_function_context (); + /* free (arg_info); */ +} + +static void +synth_destroy_helper_block_func (struct block_sema_info * block_impl) +{ + tree stmt, chain; + tree src_arg; + /* struct c_arg_info * arg_info; */ + /* Set up: (struct block *_src) parameter. */ + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + block_impl->block_arg_ptr_type); + DECL_CONTEXT (src_arg) = cur_block->destroy_helper_func_decl; + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = block_impl->block_arg_ptr_type; + /* arg_info = xcalloc (1, sizeof (struct c_arg_info)); */ + + pushdecl (cur_block->destroy_helper_func_decl); + /* arg_info->parms = src_arg; */ + /* arg_info->types = tree_cons (NULL_TREE, block_impl->block_arg_ptr_type, + NULL_TREE); */ + DECL_ARGUMENTS (cur_block->destroy_helper_func_decl) = src_arg; + + /* function header synthesis. */ + push_function_context (); + /* start_block_helper_function (cur_block->destroy_helper_func_decl, true); */ + /* store_parm_decls_from (arg_info); */ + start_preparsed_function (cur_block->destroy_helper_func_decl, + /*attrs*/NULL_TREE, + SF_PRE_PARSED); + + /* Body of the function. */ + stmt = begin_compound_stmt (BCS_FN_BODY); + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + /* APPLE LOCAL begin radar 6214617 */ + if (block_requires_copying (TREE_VALUE (chain)) + || (TREE_CODE (TREE_TYPE (TREE_VALUE (chain))) == RECORD_TYPE + && CLASSTYPE_DESTRUCTORS (TREE_TYPE (TREE_VALUE (chain))))) + /* APPLE LOCAL end radar 6214617 */ + { + int flag = 0; + tree rel_exp; + tree p = TREE_VALUE (chain); + tree src_block_component; + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + if (TREE_CODE (TREE_TYPE (p)) == BLOCK_POINTER_TYPE) + /* _Block_object_dispose(_src->imported_object_0, BLOCK_FIELD_IS_BLOCK); */ + flag = BLOCK_FIELD_IS_BLOCK; + /* APPLE LOCAL begin radar 6214617 */ + else if (TREE_CODE (TREE_TYPE (p)) == RECORD_TYPE + && CLASSTYPE_DESTRUCTORS (TREE_TYPE (p))) + { + tree call_exp = cxx_maybe_build_cleanup (src_block_component); + gcc_assert (call_exp); + add_stmt (call_exp); + } + /* APPLE LOCAL end radar 6214617 */ + else + /* _Block_object_dispose(_src->imported_object_0, BLOCK_FIELD_IS_OBJECT); */ + flag = BLOCK_FIELD_IS_OBJECT; + if (flag) + { + rel_exp = build_block_object_dispose_call_exp (src_block_component, flag); + add_stmt (rel_exp); + } + } + + /* For each __block declared variable used in |...| Must generate call to: + _Block_object_dispose(_src->myImportedClosure, BLOCK_FIELD_IS_BYREF[|BLOCK_FIELD_IS_WEAK]) + */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + tree call_exp; + int flag = BLOCK_FIELD_IS_BYREF; + tree p = TREE_VALUE (chain); + tree src_block_component; + + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + if (COPYABLE_WEAK_BLOCK (p)) + flag |= BLOCK_FIELD_IS_WEAK; + /* _Block_object_dispose(_src->myImportedClosure, BLOCK_FIELD_IS_BYREF[|BLOCK_FIELD_IS_WEAK]) */ + call_exp = build_block_object_dispose_call_exp (src_block_component, flag); + add_stmt (call_exp); + } + + finish_compound_stmt (stmt); + /* APPLE LOCAL radar 6169580 */ + finish_function (4); + /* Hum, would be nice if someone else did this for us. */ + if (global_bindings_p ()) + cgraph_finalize_function (block_impl->destroy_helper_func_decl, false); + pop_function_context (); +} + +/* Parse a block-id. + + GNU Extension: + + block-id: + type-specifier-seq block-declarator + + Returns the DECL specified or implied. */ + +static tree +cp_parser_block_id (cp_parser* parser) +{ + cp_decl_specifier_seq type_specifier_seq; + cp_declarator *declarator; + + /* Parse the type-specifier-seq. */ + cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + &type_specifier_seq); + if (type_specifier_seq.type == error_mark_node) + return error_mark_node; + + /* Look for the block-declarator. */ + declarator + = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_BLOCK, NULL, + /*parenthesized_p=*/NULL, + /*member_p=*/false); + + return grokblockdecl (&type_specifier_seq, declarator); +} + +/* Parse a block-literal-expr. + + GNU Extension: + + block-literal-expr: + ^ parameter-declation-clause exception-specification [opt] compound-statement + ^ block-id compound-statement + + It synthesizes the helper function for later generation and builds + the necessary data to represent the block literal where it is + declared. */ +static tree +cp_parser_block_literal_expr (cp_parser* parser) +{ + char name [32]; + static int global_unique_count; + int unique_count = ++global_unique_count; + tree block_helper_function_decl; + tree expr, type, arglist = NULL_TREE, ftype; + tree self_arg, stmt; + /* struct c_arg_info *args = NULL; */ + cp_parameter_declarator *args = NULL; + tree arg_type = void_list_node; + struct block_sema_info *block_impl; + tree tmp; + tree restype; + tree typelist; + tree helper_function_type; + tree block; + /* APPLE LOCAL radar 6185344 */ + tree declared_block_return_type = NULL_TREE; + /* APPLE LOCAL radar 6237713 */ + tree attributes = NULL_TREE; + /* APPLE LOCAL radar 6169580 */ + int context_is_nonstatic_method; + tree raises = NULL_TREE; + + cp_lexer_consume_token (parser->lexer); /* eat '^' */ + + /* APPLE LOCAL begin radar 6237713 */ + if (cp_lexer_peek_token (parser->lexer)->keyword == RID_ATTRIBUTE) + attributes = cp_parser_attributes_opt (parser); + /* APPLE LOCAL end radar 6237713 */ + + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + { + /* Parse the optional argument list */ + cp_lexer_consume_token (parser->lexer); + /* Open the scope to collect parameter decls */ + /* push_scope (); */ + /* args = c_parser_parms_declarator (parser, true, NULL_TREE); */ + /* Parse the parameter-declaration-clause. */ + args = cp_parser_parameter_declaration_clause (parser); + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + arg_type = grokparms (args, &arglist); + /* Check for args as it might be NULL due to error. */ + if (! args) + { + return error_mark_node; + } + raises = cp_parser_exception_specification_opt (parser); + } + /* APPLE LOCAL begin radar 6185344 */ + else if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) + { + /* Parse user declared return type. */ + tree decl; + + /* APPLE LOCAL begin radar 6237713 */ + if (attributes) + { + warning (0, "attributes before block type are ignored"); + attributes = NULL_TREE; + } + /* APPLE LOCAL end radar 6237713 */ + + decl = cp_parser_block_id (parser); + + if (decl && decl != error_mark_node) + { + arg_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); + arglist = DECL_ARGUMENTS (decl); + raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)); + declared_block_return_type = TREE_TYPE (TREE_TYPE (decl)); + } + } + /* APPLE LOCAL end radar 6185344 */ + + block = begin_block (); + /* APPLE LOCAL begin radar 6169580 */ + context_is_nonstatic_method = (current_function_decl + && DECL_NONSTATIC_MEMBER_FUNCTION_P (current_function_decl)); + /* APPLE LOCAL end radar 6169580 */ + + /* cur_block->arg_info = NULL; */ + /* APPLE LOCAL begin radar 6185344 */ + if (declared_block_return_type) + { + cur_block->return_type = TYPE_MAIN_VARIANT (declared_block_return_type); + cur_block->block_has_return_type = true; + } + else + cur_block->return_type = NULL_TREE; + /* APPLE LOCAL end radar 6185344 */ + + /* Must also build hidden parameter .block_descriptor added to the helper + function, even though we do not know its type yet. */ + /* APPLE LOCAL radar 6404979 */ + self_arg = build_artificial_parm (get_identifier (".block_descriptor"), ptr_type_node); + + /* TREE_CHAIN (self_arg) = cur_block->arg_info->parms; */ + TREE_CHAIN (self_arg) = arglist; + arg_type = tree_cons (NULL_TREE, ptr_type_node, arg_type); + arglist = self_arg; + + /* APPLE LOCAL begin radar 6185344 */ + /* Build the declaration of the helper function (if we do not know its result + type yet, assume it is 'void'. If user provided it, use it). + Treat this as a nested function and use nested function infrastructure for + its generation. */ + + push_lang_context (lang_name_c); + + ftype = build_function_type ((!cur_block->block_has_return_type + ? void_type_node : cur_block->return_type), + arg_type); + /* APPLE LOCAL end radar 6185344 */ + if (raises) + ftype = build_exception_variant (ftype, raises); + /* APPLE LOCAL radar 6160536 */ + block_helper_function_decl = build_helper_func_decl (build_block_helper_name (unique_count), + ftype); + DECL_CONTEXT (block_helper_function_decl) = current_function_decl; + cur_block->helper_func_decl = block_helper_function_decl; + + DECL_ARGUMENTS (block_helper_function_decl) = arglist; + + push_function_context (); + /* start_block_helper_function (cur_block->helper_func_decl, false); */ + /* Enter parameter list to the scope of the helper function. */ + /* store_parm_decls_from (cur_block->arg_info); */ + start_preparsed_function (cur_block->helper_func_decl, + /*attrs*/NULL_TREE, + SF_PRE_PARSED); + /* APPLE LOCAL begin radar 6237713 */ + if (cp_lexer_peek_token (parser->lexer)->keyword == RID_ATTRIBUTE) + attributes = cp_parser_attributes_opt (parser); + /* APPLE LOCAL radar 6246527 */ + any_recognized_block_attribute (attributes); + decl_attributes (&cur_block->helper_func_decl, attributes, 0); + /* APPLE LOCAL end radar 6237713 */ + + /* Start parsing body or expression part of the block literal. */ + { + unsigned save = parser->in_statement; + /* Indicate no valid break/continue context. We'll notice and + emit the proper error message in c_finish_bc_stmt. */ + parser->in_statement = 0; + stmt = begin_compound_stmt (BCS_FN_BODY); + /* Set block's scope to the scope of the helper function's main body. + This is primarily used when nested blocks are declared. */ + cur_block->cp_the_scope = current_binding_level; + /* APPLE LOCAL begin radar 6169580 */ + if (context_is_nonstatic_method) + { + tree this_decl = lookup_name (this_identifier); + gcc_assert (this_decl); + build_block_ref_decl (this_identifier, this_decl); + } + /* APPLE LOCAL end radar 6169580 */ + cp_parser_compound_statement (parser, NULL, false, false); + parser->in_statement = save; + } + + cur_block->block_arg_ptr_type = + build_pointer_type (build_block_struct_type (cur_block)); + + restype = !cur_block->return_type ? void_type_node + : cur_block->return_type; + if (restype == error_mark_node) + return clean_and_exit (block); + + /* Now that we know type of the hidden .block_descriptor argument, fix its type. */ + TREE_TYPE (self_arg) = cur_block->block_arg_ptr_type; + DECL_ARG_TYPE (self_arg) = cur_block->block_arg_ptr_type; + + /* The DECL_RESULT should already have the correct type by now. */ + gcc_assert (TREE_TYPE (DECL_RESULT (current_function_decl)) + == restype); + + cur_block->block_body = stmt; + block_build_prologue (cur_block); + + finish_compound_stmt (stmt); + /* add_stmt (fnbody); */ + + /* We are done parsing of the block body. Return type of block is now known. + We also know all we need to know about the helper function. So, fix its + type here. */ + /* We moved this here because for global blocks, helper function body is + not nested and is gimplified in call to finish_function() and return type + of the function must be correct. */ + ftype = build_function_type (restype, TREE_CHAIN (arg_type)); + if (raises) + ftype = build_exception_variant (ftype, raises); + /* Declare helper function; as in: + double helper_1(struct block_1 *ii, int z); */ + typelist = TYPE_ARG_TYPES (ftype); + /* (struct block_1 *ii, int z, ...) */ + typelist = tree_cons (NULL_TREE, cur_block->block_arg_ptr_type, + typelist); + helper_function_type = build_function_type (TREE_TYPE (ftype), typelist); + if (raises) + helper_function_type = build_exception_variant (helper_function_type, raises); + TREE_TYPE (cur_block->helper_func_decl) = helper_function_type; + finish_function (4); + pop_function_context (); + /* Hum, would be nice if someone else did this for us. */ + if (global_bindings_p ()) + cgraph_finalize_function (cur_block->helper_func_decl, false); + pop_lang_context (); + + /* Build the declaration for copy_helper_block and destroy_helper_block + helper functions for later use. */ + + if (cur_block->BlockHasCopyDispose) + { + tree s_ftype; + + push_lang_context (lang_name_c); + /* void copy_helper_block (struct block*, struct block *); */ + s_ftype = build_function_type (void_type_node, + tree_cons (NULL_TREE, cur_block->block_arg_ptr_type, + tree_cons (NULL_TREE, + cur_block->block_arg_ptr_type, + void_list_node))); + sprintf (name, "__copy_helper_block_%d", unique_count); + cur_block->copy_helper_func_decl = + build_helper_func_decl (get_identifier (name), s_ftype); + DECL_CONTEXT (cur_block->copy_helper_func_decl) = current_function_decl; + synth_copy_helper_block_func (cur_block); + + /* void destroy_helper_block (struct block*); */ + s_ftype = build_function_type (void_type_node, + tree_cons (NULL_TREE, + cur_block->block_arg_ptr_type, void_list_node)); + sprintf (name, "__destroy_helper_block_%d", unique_count); + cur_block->destroy_helper_func_decl = + build_helper_func_decl (get_identifier (name), s_ftype); + DECL_CONTEXT (cur_block->destroy_helper_func_decl) = current_function_decl; + synth_destroy_helper_block_func (cur_block); + pop_lang_context (); + } + + block_impl = finish_block (block); + + /* Build unqiue name of the temporary used in code gen. */ + sprintf (name, "__block_holder_tmp_%d", unique_count); + tmp = build_block_literal_tmp (name, block_impl); + tmp = build_fold_addr_expr (tmp); + type = build_block_pointer_type (ftype); + expr = convert (type, convert (ptr_type_node, tmp)); + free (block_impl); + return expr; +} +/* APPLE LOCAL end blocks 6040305 (ce) */ + +/* APPLE LOCAL begin blocks 6040305 (ch) */ +/* build_byref_local_var_access - converts EXPR to: + EXPR.__forwarding->. + */ +tree +build_byref_local_var_access (tree expr, tree decl_name) +{ + tree exp = build_component_ref (expr, get_identifier ("__forwarding")); + exp = build_indirect_ref (exp, "unary *"); + exp = build_component_ref (exp, decl_name); + return exp; +} + +#define BINDING_VALUE(b) ((b)->value) + +/** + build_block_byref_decl - This routine inserts a variable declared as a + 'byref' variable using the |...| syntax in helper function's outer-most scope. + */ +tree +build_block_byref_decl (tree name, tree decl, tree exp) +{ + tree ptr_type, byref_decl; + /* APPLE LOCAL begin radar 6225809 */ + if (cur_block->prev_block_info) { + /* Traverse enclosing blocks. Insert a __block variable in + each enclosing block which has no declaration of this + variable. This is to ensure that the current (inner) block + gets the __block version of the variable; */ + struct block_sema_info *cb = cur_block->prev_block_info; + while (cb) { + struct cxx_binding *b = I_SYMBOL_BINDING (name); + gcc_assert (b); + gcc_assert (BINDING_VALUE (b)); + gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL); + /* Find the first declaration not in current block. */ + while (b && BINDING_VALUE (b) + && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL) + && DECL_CONTEXT (BINDING_VALUE (b)) == cur_block->helper_func_decl) + { + /* FIXME: This can't happen?! */ + abort (); + /* b = b->previous; */ + } + + gcc_assert (b); + gcc_assert (BINDING_VALUE (b)); + gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL); + + /* Is the next declaration not in the enclosing block? */ + if (b && BINDING_VALUE (b) + && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL) + && DECL_CONTEXT (BINDING_VALUE (b)) != cb->helper_func_decl) + { + /* No declaration of variable seen in the block. Must insert one. */ + /* FIXME: does this push enough? scope? */ + struct cp_binding_level *save_scope = current_binding_level; + struct block_sema_info *save_current_block = cur_block; + tree save_current_function_decl = current_function_decl; + current_binding_level = cb->cp_the_scope; + cur_block = cb; + current_function_decl = cb->helper_func_decl; + decl = build_block_byref_decl (name, decl, exp); + cur_block = save_current_block; + current_binding_level = save_scope; + current_function_decl = save_current_function_decl; + } + cb = cb->prev_block_info; + } + } + /* APPLE LOCAL end radar 6225809 */ + + /* If it is already a byref declaration, do not add the pointer type + because such declarations already have the pointer type + added. This happens when we have two nested byref declarations in + nested blocks. */ + ptr_type = (TREE_CODE (decl) == VAR_DECL && BLOCK_DECL_BYREF (decl)) + ? TREE_TYPE (decl) : build_pointer_type (TREE_TYPE (decl)); + byref_decl = build_decl (VAR_DECL, name, ptr_type); + DECL_CONTEXT (byref_decl) = current_function_decl; + BLOCK_DECL_BYREF (byref_decl) = 1; + + if (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl)) + { + COPYABLE_BYREF_LOCAL_VAR (byref_decl) = 1; + COPYABLE_BYREF_LOCAL_NONPOD (byref_decl) = COPYABLE_BYREF_LOCAL_NONPOD (decl); + /* APPLE LOCAL radar 5847976 */ + COPYABLE_WEAK_BLOCK (byref_decl) = COPYABLE_WEAK_BLOCK (decl); + } + + /* Current scope must be that of the main function body. */ + /* FIXME gcc_assert (current_scope->function_body);*/ + pushdecl (byref_decl); + mark_used (byref_decl); + /* APPLE LOCAL begin radar 6083129 - byref escapes (cp) */ + /* FIXME: finish this off, ensure the decl is scoped appropriately + for when we want the cleanup to run. */ + /* APPLE LOCAL end radar 6083129 - byref escapes (cp) */ + cur_block->block_byref_decl_list = + tree_cons (NULL_TREE, byref_decl, cur_block->block_byref_decl_list); + /* APPLE LOCAL radar 5847213 */ + /* build of block_original_byref_decl_list us removed. */ + /* APPLE LOCAL begin radar 6144664 */ + DECL_SOURCE_LOCATION (byref_decl) + = DECL_SOURCE_LOCATION (cur_block->helper_func_decl); + /* APPLE LOCAL end radar 6144664 */ + return byref_decl; +} + +/** + build_block_ref_decl - This routine inserts a copied-in variable (a variable + referenced in the block but whose scope is outside the block) in helper + function's outer-most scope. It also sets its type to 'const' as such + variables are read-only. + */ +tree +build_block_ref_decl (tree name, tree decl) +{ + /* FIXME - Broken, should be found via objc runtime testcases. */ + /* FIXME - Don't use DECL_CONTEXT on any helpers */ + tree ref_decl; + /* APPLE LOCAL radar 6212722 */ + tree type, exp; + /* 'decl' was previously declared as __block. Simply, copy the value + embedded in the above variable. */ + if (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl)) + decl = build_byref_local_var_access (decl, DECL_NAME (decl)); + else { + if (cur_block->prev_block_info) { + /* Traverse enclosing blocks. Insert a copied-in variable in + each enclosing block which has no declaration of this + variable. This is to ensure that the current (inner) block + has the 'frozen' value of the copied-in variable; which means + the value of the copied in variable is at the point of the + block declaration and *not* when the inner block is + invoked. */ + struct block_sema_info *cb = cur_block->prev_block_info; + while (cb) { + struct cxx_binding *b = I_SYMBOL_BINDING (name); + gcc_assert (b); + gcc_assert (BINDING_VALUE (b)); + gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL); + /* Find the first declaration not in current block. */ + while (b && BINDING_VALUE (b) + && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL) + && DECL_CONTEXT (BINDING_VALUE (b)) == cur_block->helper_func_decl) + { + /* FIXME: This can't happen?! */ + abort (); + /* b = b->previous; */ + } + + gcc_assert (b); + gcc_assert (BINDING_VALUE (b)); + gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL); + + /* Is the next declaration not in the enclosing block? */ + if (b && BINDING_VALUE (b) + && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL) + && DECL_CONTEXT (BINDING_VALUE (b)) != cb->helper_func_decl) + { + /* No declaration of variable seen in the block. Must + insert one, so it 'freezes' the variable in this + block. */ + /* FIXME: does this push enough? scope? */ + struct cp_binding_level *save_scope = current_binding_level; + struct block_sema_info *save_current_block = cur_block; + tree save_current_function_decl = current_function_decl; + current_binding_level = cb->cp_the_scope; + cur_block = cb; + current_function_decl = cb->helper_func_decl; + decl = build_block_ref_decl (name, decl); + cur_block = save_current_block; + current_binding_level = save_scope; + current_function_decl = save_current_function_decl; + } + cb = cb->prev_block_info; + } + } + } + /* APPLE LOCAL begin radar 6212722 */ + exp = decl; + type = TREE_TYPE (exp); + if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == FUNCTION_TYPE) { + exp = decay_conversion (exp); + type = TREE_TYPE (exp); + } + ref_decl = build_decl (VAR_DECL, name, + build_qualified_type (type, TYPE_QUAL_CONST)); + /* APPLE LOCAL end radar 6212722 */ + /* APPLE LOCAL begin radar 6144664 */ + DECL_SOURCE_LOCATION (ref_decl) = DECL_SOURCE_LOCATION + (cur_block->helper_func_decl); + /* APPLE LOCAL end radar 6144664 */ + DECL_CONTEXT (ref_decl) = current_function_decl; + DECL_INITIAL (ref_decl) = error_mark_node; + c_apply_type_quals_to_decl (TYPE_QUAL_CONST, ref_decl); + BLOCK_DECL_COPIED (ref_decl) = 1; + + /* Find the scope for function body (outer-most scope) and insert + this variable in that scope. This is to avoid duplicate + declaration of the save variable. */ + { + struct cp_binding_level *b = current_binding_level; + while (b->level_chain->kind != sk_function_parms) + b = b->level_chain; + pushdecl_with_scope (ref_decl, b, /*is_friend=*/false); + /* APPLE LOCAL radar 6169527 */ + add_decl_expr (ref_decl); + } + cur_block->block_ref_decl_list = + tree_cons (NULL_TREE, ref_decl, cur_block->block_ref_decl_list); + cur_block->block_original_ref_decl_list = + /* APPLE LOCAL radar 6212722 */ + tree_cons (NULL_TREE, exp, cur_block->block_original_ref_decl_list); + return ref_decl; +} + +/* APPLE LOCAL begin radar 5847213 - radar 6329245 */ +static GTY (()) tree descriptor_ptr_type; +static GTY (()) tree descriptor_ptr_type_with_copydispose; +/** build_block_descriptor_type - This routine builds following internal type: + struct __block_descriptor { + unsigned long int reserved; // NULL + unsigned long int Size; // sizeof(struct Block_literal_1) + + // optional helper functions + void *CopyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE is set (withCopyDispose true) + void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE is set (withCopyDispose true) + } *descriptor_ptr_type; + + Objects of this type will always be static. This is one main component of abi change. + */ +tree +build_block_descriptor_type (bool withCopyDispose) +{ + tree field_decl_chain = NULL_TREE, field_decl; + tree main_type; + + if (withCopyDispose && descriptor_ptr_type_with_copydispose) + return descriptor_ptr_type_with_copydispose; + if (!withCopyDispose && descriptor_ptr_type) + return descriptor_ptr_type; + + main_type = make_aggr_type (RECORD_TYPE); + xref_basetypes (main_type, NULL_TREE); + + /* unsigned long int reserved; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("reserved"), long_unsigned_type_node); + TREE_CHAIN (field_decl) = field_decl_chain; + field_decl_chain = field_decl; + + /* unsigned long int Size; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("Size"), long_unsigned_type_node); + TREE_CHAIN (field_decl) = field_decl_chain; + field_decl_chain = field_decl; + + if (withCopyDispose) + { + /* void *CopyFuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("CopyFuncPtr"), ptr_type_node); + TREE_CHAIN (field_decl) = field_decl_chain; + field_decl_chain = field_decl; + /* void *DestroyFuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("DestroyFuncPtr"), ptr_type_node); + TREE_CHAIN (field_decl) = field_decl_chain; + field_decl_chain = field_decl; + } + + /* Mark this struct as being a block struct rather than a 'normal' + struct. */ + TYPE_BLOCK_IMPL_STRUCT (main_type) = 1; + if (withCopyDispose) + finish_builtin_struct (main_type, "__block_descriptor_withcopydispose", field_decl_chain, NULL_TREE); + else + finish_builtin_struct (main_type, "__block_descriptor", field_decl_chain, NULL_TREE); + CLASSTYPE_AS_BASE (main_type) = main_type; + + main_type = build_pointer_type (main_type); + if (withCopyDispose) + descriptor_ptr_type_with_copydispose = main_type; + else + descriptor_ptr_type = main_type; + return main_type; +} +/* APPLE LOCAL end radar 5847213 - radar 6329245 */ + +cp_declarator * +make_block_pointer_declarator (tree attributes, + cp_cv_quals quals, + cp_declarator *target) +{ + struct cp_declarator *itarget = target; + struct cp_declarator *ret = make_declarator (cdk_block_pointer); + + /* APPLE LOCAL radar 5847213 */ + /* code removed */ + + + ret->attributes = attributes; + ret->declarator = itarget; + ret->u.block_pointer.qualifiers = quals; + return ret; +} + +/* This routine returns 'true' if 'name' has a declaration inside the + current block, 'false' otherwise. If 'name' has no declaration in + the current block, it returns in DECL the user declaration for + 'name' found in the enclosing scope. Note that if it is declared + in current declaration, it can be either a user declaration or a + byref/copied-in declaration added in current block's scope by the + compiler. */ +bool +lookup_name_in_block (tree name, tree *decl) +{ + /* FIXME - Broken, should be found via objc runtime testcases. */ + /* FIXME - Don't use DECL_CONTEXT on any helpers */ + cxx_binding *b = I_SYMBOL_BINDING (name); + if (b && b->declared_in_block + && DECL_CONTEXT (BINDING_VALUE (b)) == current_function_decl) + return true; + + /* Check for variables only, as we may have parameters, such as + 'self' */ + /* Note that if a copied-in variable (BLOCK_DECL_COPIED) in the + enclosing block is found, it must be returned as this is + where the variable in current (nested block) will have to get + its value. */ + while (b + && TREE_CODE (BINDING_VALUE (b)) == VAR_DECL + && (BLOCK_DECL_BYREF (BINDING_VALUE (b)))) + b = b->previous; + if (b) + *decl = BINDING_VALUE (b); + return false; +} + +/** + build_helper_func_decl - This routine builds a FUNCTION_DECL for + a block helper function. + */ +tree +build_helper_func_decl (tree ident, tree type) +{ + tree func_decl = build_decl (FUNCTION_DECL, ident, type); + DECL_EXTERNAL (func_decl) = 0; + TREE_PUBLIC (func_decl) = 0; + TREE_USED (func_decl) = 1; + TREE_NOTHROW (func_decl) = 0; + /* APPLE LOCAL radar 6172148 */ + BLOCK_SYNTHESIZED_FUNC (func_decl) = 1; + retrofit_lang_decl (func_decl); + if (current_function_decl) + DECL_NO_STATIC_CHAIN (current_function_decl) = 0; + return func_decl; +} + +/** + declare_block_prologue_local_vars - utility routine to do the actual + declaration and initialization for each referecned block variable. + */ +/* APPLE LOCAL begin radar 6169527 */ +/* This routine is mostly rewritten for c++ because initialization of variables + may involve copy construction. */ +static void +declare_block_prologue_local_vars (tree self_parm, tree component, + tree stmt) +{ + tree decl, block_component; + tree_stmt_iterator i; + tree initialization_stmt; + /* APPLE LOCAL radar 6163705 */ + int save_line = LOCATION_LINE (input_location); + + decl = component; + block_component = build_component_ref (build_indirect_ref (self_parm, "->"), + DECL_NAME (component)); + gcc_assert (block_component); + /* APPLE LOCAL radar 6163705 */ + LOCATION_LINE (input_location) = DECL_SOURCE_LINE (decl) - 1; + DECL_EXTERNAL (decl) = 0; + TREE_STATIC (decl) = 0; + TREE_USED (decl) = 1; + DECL_CONTEXT (decl) = current_function_decl; + DECL_ARTIFICIAL (decl) = 1; + initialization_stmt = push_stmt_list(); + cp_finish_decl (decl, block_component, 0, 0, LOOKUP_ONLYCONVERTING); + initialization_stmt = pop_stmt_list (initialization_stmt); + /* APPLE LOCAL radar 6163705 */ + LOCATION_LINE (input_location) = save_line; + /* Prepend a initialization_stmt statement to the statement list. */ + i = tsi_start (stmt); + tsi_link_before (&i, initialization_stmt, TSI_SAME_STMT); +} + +/** + declare_block_prologue_local_byref_vars - utility routine to do the actual + declaration and initialization for each __block referenced block variable. + */ +static void +declare_block_prologue_local_byref_vars (tree self_parm, tree component, + tree stmt) +{ + tree decl, block_component; + tree_stmt_iterator i; + tree decl_stmt; + + decl = component; + block_component = build_component_ref (build_indirect_ref (self_parm, "->"), + DECL_NAME (component)); + gcc_assert (block_component); + DECL_EXTERNAL (decl) = 0; + TREE_STATIC (decl) = 0; + TREE_USED (decl) = 1; + DECL_CONTEXT (decl) = current_function_decl; + DECL_ARTIFICIAL (decl) = 1; + DECL_INITIAL (decl) = block_component; + /* Prepend a DECL_EXPR statement to the statement list. */ + i = tsi_start (stmt); + decl_stmt = build_stmt (DECL_EXPR, decl); + SET_EXPR_LOCATION (decl_stmt, DECL_SOURCE_LOCATION (decl)); + /* APPLE LOCAL begin radar 6163705, Blocks prologues */ + /* Give the prologue statements a line number of one before the beginning of + the function, to make them easily identifiable later. */ + EXPR_LINENO (decl_stmt) = DECL_SOURCE_LINE (decl) - 1; + /* APPLE LOCAL end radar 6163705, Blocks prologues */ + decl_stmt = build3 (BIND_EXPR, void_type_node, decl, decl_stmt, NULL); + TREE_SIDE_EFFECTS (decl_stmt) = 1; + + tsi_link_before (&i, decl_stmt, TSI_SAME_STMT); +} +/* APPLE LOCAL end radar 6169527 */ + +/** + block_build_prologue + - This routine builds the declarations for the + variables referenced in the block; as in: + int *y = .block_descriptor->y; + int x = .block_descriptor->x; + + The decl_expr declaration for each initialization is enterred at the + beginning of the helper function's statement-list which is passed + in block_impl->block_body. + */ +void +block_build_prologue (struct block_sema_info *block_impl) +{ + tree chain; + tree self_parm = lookup_name (get_identifier (".block_descriptor")); + gcc_assert (self_parm); + + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + declare_block_prologue_local_vars (self_parm, TREE_VALUE (chain), + block_impl->block_body); + /* APPLE LOCAL begin radar 6169527 */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + declare_block_prologue_local_byref_vars (self_parm, TREE_VALUE (chain), + block_impl->block_body); + /* APPLE LOCAL end radar 6169527 */ +} +/* APPLE LOCAL end blocks 6040305 (ch) */ + /* OpenMP 2.5 parsing routines. */ /* All OpenMP clauses. OpenMP 2.5. */ @@ -18875,6 +21197,7 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok) return c_finish_omp_critical (stmt, name); } + /* OpenMP 2.5: # pragma omp flush flush-vars[opt] new-line diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c index 008f8f9be3c7..38a82198af66 100644 --- a/contrib/gcc/cp/pt.c +++ b/contrib/gcc/cp/pt.c @@ -7835,6 +7835,11 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) complain); } + /* APPLE LOCAL begin blocks 6204446 */ + case BLOCK_POINTER_TYPE: + return t; + /* APPLE LOCAL end blocks 6204446 */ + default: sorry ("use of %qs in template", tree_code_name [(int) TREE_CODE (t)]); diff --git a/contrib/gcc/cp/semantics.c b/contrib/gcc/cp/semantics.c index c234e250142b..d377ad79c3b9 100644 --- a/contrib/gcc/cp/semantics.c +++ b/contrib/gcc/cp/semantics.c @@ -1943,6 +1943,18 @@ finish_this_expr (void) error ("% is unavailable for static member functions"); result = error_mark_node; } + /* APPLE LOCAL begin radar 6275956 */ + else if (cur_block && current_function_decl + && BLOCK_SYNTHESIZED_FUNC (current_function_decl)) + { + result = lookup_name (this_identifier); + if (!result) + { + error ("invalid use of % in a block"); + result = error_mark_node; + } + } + /* APPLE LOCAL end radar 6275956 */ else { if (current_function_decl) @@ -2470,6 +2482,82 @@ baselink_for_fns (tree fns) return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE); } +/* APPLE LOCAL begin blocks 6040305 */ +static bool +block_var_ok_for_context (tree context) +{ + /* FIXME - local classes inside blocks, templates, etc */ + struct block_sema_info *b = cur_block; + tree decl = current_function_decl; + + /* If in a block helper, only variables from the context of the helper + are ok. */ + while (b && b->helper_func_decl == decl) + { + if (context == DECL_CONTEXT (decl)) + return true; + decl = DECL_CONTEXT (decl); + b = b->prev_block_info; + } + + return false; +} + +/* APPLE LOCAL begin radar 6545782 */ +/** This routine does all the work on use of variables in a block. */ +static tree get_final_block_variable (tree name, tree var) { + tree decl = var; + + if (cur_block + && (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL) + && !lookup_name_in_block (name, &decl)) + { + bool gdecl; + /* We are referencing a variable inside a block whose + declaration is outside. */ + gcc_assert (decl && + (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL)); + gdecl = (TREE_CODE (decl) == VAR_DECL && + (DECL_EXTERNAL (decl) || TREE_STATIC (decl))); + /* Treat all 'global' variables as 'byref' by default. */ + if (gdecl + || (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl))) + { + /* byref globals are directly accessed. */ + /* APPLE LOCAL begin radar 7760213 */ + if (!gdecl) { + if (HasByrefArray(TREE_TYPE (decl))) + error ("cannot access __block variable of array type inside block"); + /* build a decl for the byref variable. */ + decl = build_block_byref_decl (name, decl, decl); + } + /* APPLE LOCAL end radar 7760213 */ + else + add_block_global_byref_list (decl); + } + else + { + /* 'byref' globals are never copied-in. So, do not add + them to the copied-in list. */ + if (!in_block_global_byref_list (decl)) { + /* APPLE LOCAL begin radar 7721728 */ + if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) + error ("cannot access copied-in variable of array type inside block"); + /* APPLE LOCAL end radar 7721728 */ + /* build a new decl node. set its type to 'const' type + of the old decl. */ + decl = build_block_ref_decl (name, decl); + } + } + } + return decl; +} +/* APPLE LOCAL end radar 6545782 */ + +/* APPLE LOCAL end blocks 6040305 */ + /* ID_EXPRESSION is a representation of parsed, but unprocessed, id-expression. (See cp_parser_id_expression for details.) SCOPE, if non-NULL, is the type or namespace used to explicitly qualify @@ -2536,6 +2624,7 @@ finish_id_expression (tree id_expression, if (decl == error_mark_node) { /* Name lookup failed. */ + if (scope && (!TYPE_P (scope) || (!dependent_type_p (scope) @@ -2576,7 +2665,10 @@ finish_id_expression (tree id_expression, { tree context = decl_function_context (decl); if (context != NULL_TREE && context != current_function_decl - && ! TREE_STATIC (decl)) + /* APPLE LOCAL begin blocks 6040305 */ + && ! TREE_STATIC (decl) + && !block_var_ok_for_context (context)) + /* APPLE LOCAL end blocks 6040305 */ { error (TREE_CODE (decl) == VAR_DECL ? "use of % variable from containing function" @@ -2852,8 +2944,21 @@ finish_id_expression (tree id_expression, Access checking has been performed during name lookup already. Turn off checking to avoid duplicate errors. */ push_deferring_access_checks (dk_no_check); - decl = finish_non_static_data_member (decl, current_class_ref, - /*qualifying_scope=*/NULL_TREE); + /* APPLE LOCAL begin radar 6169580 */ + if (cur_block) + { + tree exp; + tree this_copiedin_var = lookup_name (this_identifier); + gcc_assert (!current_class_ref); + gcc_assert (this_copiedin_var); + exp = build_x_arrow (this_copiedin_var); + decl = build_class_member_access_expr (exp, decl, TREE_TYPE (exp), + /*preserve_reference=*/false); + } + else + decl = finish_non_static_data_member (decl, current_class_ref, + /*qualifying_scope=*/NULL_TREE); + /* APPLE LOCAL end radar 6169580 */ pop_deferring_access_checks (); } else if (is_overloaded_fn (decl)) @@ -2894,7 +2999,8 @@ finish_id_expression (tree id_expression, path = currently_open_derived_class (DECL_CONTEXT (decl)); perform_or_defer_access_check (TYPE_BINFO (path), decl, decl); } - + /* APPLE LOCAL radar 6545782 */ + decl = get_final_block_variable (id_expression, decl); decl = convert_from_reference (decl); } } @@ -2902,6 +3008,30 @@ finish_id_expression (tree id_expression, if (TREE_DEPRECATED (decl)) warn_deprecated_use (decl); + /* APPLE LOCAL begin blocks 6040305 (cd) */ + if (TREE_CODE (decl) == VAR_DECL) + { + if (BLOCK_DECL_BYREF (decl)) + { + tree orig_decl = decl; + decl = build_indirect_ref (decl, "unary *"); + if (COPYABLE_BYREF_LOCAL_VAR (orig_decl)) + { + /* What we have is an expression which is of type + struct __Block_byref_X. Must get to the value of the variable + embedded in this structure. It is at: + __Block_byref_X.__forwarding->x */ + decl = build_byref_local_var_access (decl, + DECL_NAME (orig_decl)); + } + } + else + if (COPYABLE_BYREF_LOCAL_VAR (decl)) + decl = build_byref_local_var_access (decl, + DECL_NAME (decl)); + } + /* APPLE LOCAL end blocks 6040305 (cd) */ + return decl; } @@ -3173,6 +3303,11 @@ expand_or_defer_fn (tree fn) it. */ if (maybe_clone_body (fn)) { + /* APPLE LOCAL begin radar 6305545 */ + /* Must lower the nested functions which could be, among other + things, block helper functions. */ + lower_if_nested_functions (fn); + /* APPLE LOCAL end radar 6305545 */ /* We don't want to process FN again, so pretend we've written it out, even though we haven't. */ TREE_ASM_WRITTEN (fn) = 1; @@ -3965,6 +4100,42 @@ cxx_omp_predetermined_sharing (tree decl) return OMP_CLAUSE_DEFAULT_UNSPECIFIED; } + +/* APPLE LOCAL begin blocks 6040305 (ch) */ +tree +begin_block (void) +{ + struct block_sema_info *csi; + tree block; + /* push_scope (); */ + current_stmt_tree ()->stmts_are_full_exprs_p = 1; +#if 0 + block = do_pushlevel (sk_block); +#else + block = NULL_TREE; +#endif + csi = (struct block_sema_info*)xcalloc (1, sizeof (struct block_sema_info)); + csi->prev_block_info = cur_block; + cur_block = csi; + return block; +} + +struct block_sema_info * +finish_block (tree block) +{ + struct block_sema_info *csi = cur_block; + cur_block = cur_block->prev_block_info; + /* pop_scope (); */ +#if 0 + if (block) + do_poplevel (block); +#else + block = 0; +#endif + return csi; +} +/* APPLE LOCAL end blocks 6040305 (ch) */ + void init_cp_semantics (void) diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c index eee91514bf24..5575097f71b1 100644 --- a/contrib/gcc/cp/tree.c +++ b/contrib/gcc/cp/tree.c @@ -1717,6 +1717,15 @@ maybe_dummy_object (tree type, tree* binfop) && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)), current_class_type)) decl = current_class_ref; + /* APPLE LOCAL begin radar 6154598 */ + else if (cur_block) + { + tree this_copiedin_var = lookup_name (this_identifier); + gcc_assert (!current_class_ref); + gcc_assert (this_copiedin_var); + decl = build_x_arrow (this_copiedin_var); + } + /* APPLE LOCAL end radar 6154598 */ else decl = build_dummy_object (context); diff --git a/contrib/gcc/cp/typeck.c b/contrib/gcc/cp/typeck.c index 925511b50702..c184a1fb69ba 100644 --- a/contrib/gcc/cp/typeck.c +++ b/contrib/gcc/cp/typeck.c @@ -57,7 +57,8 @@ static void casts_away_constness_r (tree *, tree *); static bool casts_away_constness (tree, tree); static void maybe_warn_about_returning_address_of_local (tree); static tree lookup_destructor (tree, tree, tree); -static tree convert_arguments (tree, tree, tree, int); +/* APPLE LOCAL radar 6087117 */ +static tree convert_arguments (tree, tree, tree, int, int); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) @@ -406,7 +407,8 @@ composite_pointer_type_r (tree t1, tree t2, const char* location) tree attributes; /* Determine the types pointed to by T1 and T2. */ - if (TREE_CODE (t1) == POINTER_TYPE) + /* APPLE LOCAL blocks 6040305 */ + if (TREE_CODE (t1) == POINTER_TYPE || TREE_CODE (t1) == BLOCK_POINTER_TYPE) { pointee1 = TREE_TYPE (t1); pointee2 = TREE_TYPE (t2); @@ -453,8 +455,13 @@ composite_pointer_type_r (tree t1, tree t2, const char* location) result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1), result_type); } + /* APPLE LOCAL begin blocks 6065211 */ + else if (TREE_CODE (t1) == BLOCK_POINTER_TYPE + && result_type != void_type_node) + result_type = build_block_pointer_type (result_type); else result_type = build_pointer_type (result_type); + /* APPLE LOCAL end blocks 6065211 */ /* Merge the attributes. */ attributes = (*targetm.merge_type_attributes) (t1, t2); @@ -524,8 +531,10 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, if (c_dialect_objc () && TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE) { - if (objc_compare_types (t1, t2, -3, NULL_TREE)) - return t1; + /* APPLE LOCAL radar 4229905 - radar 6231433 */ + if (objc_have_common_type (t1, t2, -3, NULL_TREE, location)) + /* APPLE LOCAL 4154928 */ + return objc_common_type (t1, t2); } /* [expr.eq] permits the application of a pointer conversion to @@ -572,6 +581,14 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, return error_mark_node; } } + /* APPLE LOCAL begin blocks 6065211 */ + else if (TREE_CODE (t1) != TREE_CODE (t2)) + { + error ("%s between distinct pointer types %qT and %qT " + "lacks a cast", location, t1, t2); + return error_mark_node; + } + /* APPLE LOCAL end blocks 6065211 */ return composite_pointer_type_r (t1, t2, location); } @@ -1039,6 +1056,21 @@ comptypes (tree t1, tree t2, int strict) return false; break; + /* APPLE LOCAL begin blocks 6040305 */ + case BLOCK_POINTER_TYPE: + if (TREE_CODE (t2) == BLOCK_POINTER_TYPE) + { + tree pt1 = TREE_TYPE (t1); + tree pt2 = TREE_TYPE (t2); + if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (pt1), + TREE_TYPE (pt2))) + return false; + if (!compparms (TYPE_ARG_TYPES (pt1), TYPE_ARG_TYPES (pt2))) + return false; + break; + } + /* APPLE LOCAL end blocks 6040305 */ + case POINTER_TYPE: case REFERENCE_TYPE: if (TYPE_MODE (t1) != TYPE_MODE (t2) @@ -2662,6 +2694,53 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) return function; } +/* APPLE LOCAL begin blocks 6040305 (cm) */ +/* APPLE LOCAL begin radar 5847213 - radar 6329245 */ +/** + build_block_call - Routine to build a block call; as in: + ((double(*)(void *, int))(BLOCK_PTR_EXP->__FuncPtr))(I, 42); + FNTYPE is the original function type derived from the syntax. + BLOCK_PTR_EXP is the block pointer variable. + PARAMS is the parameter list. +*/ +static tree +build_block_call (tree fntype, tree block_ptr_exp, tree params) +{ + tree function_ptr_exp; + tree typelist; + tree result; + /* APPLE LOCAL radar 6396238 */ + bool block_ptr_exp_side_effect = TREE_SIDE_EFFECTS (block_ptr_exp); + + /* First convert it to 'void *'. */ + block_ptr_exp = convert (ptr_type_node, block_ptr_exp); + gcc_assert (generic_block_literal_struct_type); + block_ptr_exp = convert (build_pointer_type (generic_block_literal_struct_type), + block_ptr_exp); + if (block_ptr_exp_side_effect) + block_ptr_exp = save_expr (block_ptr_exp); + + /* BLOCK_PTR_VAR->__FuncPtr */ + function_ptr_exp = + finish_class_member_access_expr (build_indirect_ref (block_ptr_exp, "->"), + get_identifier ("__FuncPtr"), false); + gcc_assert (function_ptr_exp); + + /* Build: result_type(*)(void *, function-arg-type-list) */ + typelist = TYPE_ARG_TYPES (fntype); + typelist = tree_cons (NULL_TREE, ptr_type_node, typelist); + fntype = build_function_type (TREE_TYPE (fntype), typelist); + function_ptr_exp = convert (build_pointer_type (fntype), function_ptr_exp); + params = tree_cons (NULL_TREE, block_ptr_exp, params); + result = build3 (CALL_EXPR, TREE_TYPE (fntype), + function_ptr_exp, params, NULL_TREE); + /* FIXME: should do more from build_cxx_call */ + result = convert_from_reference (result); + return result; +} +/* APPLE LOCAL end radar 5847213 - radar 6329245 */ +/* APPLE LOCAL end blocks 6040305 (cm) */ + tree build_function_call (tree function, tree params) { @@ -2724,7 +2803,8 @@ build_function_call (tree function, tree params) is_method = (TREE_CODE (fntype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (fntype)) == METHOD_TYPE); - if (!((TREE_CODE (fntype) == POINTER_TYPE + /* APPLE LOCAL blocks 6040305 */ + if (!(((TREE_CODE (fntype) == POINTER_TYPE || TREE_CODE (fntype) == BLOCK_POINTER_TYPE) && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE) || is_method || TREE_CODE (function) == TEMPLATE_ID_EXPR)) @@ -2739,8 +2819,11 @@ build_function_call (tree function, tree params) /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ + /* APPLE LOCAL begin radar 6087117 */ coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype), - params, fndecl, LOOKUP_NORMAL); + params, fndecl, LOOKUP_NORMAL, + (TREE_CODE (TREE_TYPE (function)) == BLOCK_POINTER_TYPE)); + /* APPLE LOCAL end radar 6087117 */ if (coerced_params == error_mark_node) return error_mark_node; @@ -2749,10 +2832,14 @@ build_function_call (tree function, tree params) check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params, TYPE_ARG_TYPES (fntype)); + /* APPLE LOCAL begin blocks 6040305 */ + if (TREE_CODE (TREE_TYPE (function)) == BLOCK_POINTER_TYPE) + return build_block_call (fntype, function, coerced_params); + /* APPLE LOCAL end blocks 6040305 */ return build_cxx_call (function, coerced_params); } - + /* Convert the actual parameter expressions in the list VALUES to the types in the list TYPELIST. If parmdecls is exhausted, or when an element has NULL as its type, @@ -2771,7 +2858,8 @@ build_function_call (tree function, tree params) default arguments, if such were specified. Do so here. */ static tree -convert_arguments (tree typelist, tree values, tree fndecl, int flags) +/* APPLE LOCAL radar 6087117 */ +convert_arguments (tree typelist, tree values, tree fndecl, int flags, int block_call) { tree typetail, valtail; tree result = NULL_TREE; @@ -2813,7 +2901,8 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) error ("at this point in file"); } else - error ("too many arguments to function"); + /* APPLE LOCAL radar 6087117 */ + error ("too many arguments to %s", (block_call ? "block call" : "function")); /* In case anybody wants to know if this argument list is valid. */ if (result) @@ -2915,7 +3004,8 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) error ("at this point in file"); } else - error ("too few arguments to function"); + /* APPLE LOCAL radar 6087117 */ + error ("too few arguments to %s", (block_call ? "block call" : "function")); return error_mark_node; } } @@ -3314,22 +3404,29 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE)) short_compare = 1; - else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE) + /* APPLE LOCAL begin blocks 6040305 */ + else if (((code0 == POINTER_TYPE || code0 == BLOCK_POINTER_TYPE) + && (code1 == POINTER_TYPE || code1 == BLOCK_POINTER_TYPE)) || (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1))) + /* APPLE LOCAL end blocks 6040305 */ result_type = composite_pointer_type (type0, type1, op0, op1, "comparison"); - else if ((code0 == POINTER_TYPE || TYPE_PTRMEM_P (type0)) + /* APPLE LOCAL blocks 6040305 (cl) */ + else if ((code0 == POINTER_TYPE || code0 == BLOCK_POINTER_TYPE || TYPE_PTRMEM_P (type0)) && null_ptr_cst_p (op1)) result_type = type0; - else if ((code1 == POINTER_TYPE || TYPE_PTRMEM_P (type1)) + /* APPLE LOCAL blocks 6040305 (cl) */ + else if ((code1 == POINTER_TYPE || code1 == BLOCK_POINTER_TYPE || TYPE_PTRMEM_P (type1)) && null_ptr_cst_p (op0)) result_type = type1; - else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) + /* APPLE LOCAL blocks 6040305 (cl) */ + else if ((code0 == POINTER_TYPE || code0 == BLOCK_POINTER_TYPE) && code1 == INTEGER_TYPE) { result_type = type0; error ("ISO C++ forbids comparison between pointer and integer"); } - else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) + /* APPLE LOCAL blocks 6040305 (cl) */ + else if (code0 == INTEGER_TYPE && (code1 == POINTER_TYPE || code1 == BLOCK_POINTER_TYPE)) { result_type = type1; error ("ISO C++ forbids comparison between pointer and integer"); @@ -5247,6 +5344,30 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, else if (TYPE_PTR_P (type) && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)) /* OK */ ; + /* APPLE LOCAL begin blocks 6040305 (ck) */ + else if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) == BLOCK_POINTER_TYPE) + { + if (TYPE_PRECISION (type) < TYPE_PRECISION (intype)) + pedwarn ("cast from %qT to %qT loses precision", + intype, type); + } + else if (TREE_CODE (type) == BLOCK_POINTER_TYPE && TREE_CODE (intype) == INTEGER_TYPE) + /* OK */ + ; + else if (TREE_CODE (type) == BLOCK_POINTER_TYPE && TREE_CODE (intype) == BLOCK_POINTER_TYPE) + /* OK */ + ; + else if (TREE_CODE (intype) == BLOCK_POINTER_TYPE + && (objc_is_id (type) + || (TREE_CODE (type) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (type))))) + /* OK */ + ; + else if (TREE_CODE (type) == BLOCK_POINTER_TYPE + && TREE_CODE (intype) == POINTER_TYPE + && (objc_is_id (intype) || VOID_TYPE_P (TREE_TYPE (intype)))) + /* OK */ + ; + /* APPLE LOCAL end blocks 6040305 (ck) */ else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype)) || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) return fold_if_not_in_template (build_nop (type, expr)); @@ -5300,6 +5421,14 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, return error_mark_node; } + /* APPLE LOCAL begin don't sign-extend pointers cast to integers */ + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (intype) == POINTER_TYPE + && TYPE_PRECISION (type) > TYPE_PRECISION (intype) + && TYPE_UNSIGNED (type)) + expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 1), expr); + /* APPLE LOCAL end don't sign-extend pointers cast to integers */ + return cp_convert (type, expr); } @@ -5713,6 +5842,19 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (modifycode == NOP_EXPR) { + /* `operator=' is not an inheritable operator. */ + if (! IS_AGGR_TYPE (lhstype)) + /* Do the default thing. */; + else + { + result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, + lhs, rhs, make_node (NOP_EXPR), + /*overloaded_p=*/NULL); + if (result == NULL_TREE) + return error_mark_node; + return result; + } + /* APPLE LOCAL end C* property (Radar 4436866) */ /* `operator=' is not an inheritable operator. */ if (! IS_AGGR_TYPE (lhstype)) /* Do the default thing. */; @@ -5745,6 +5887,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) /* Now it looks like a plain assignment. */ modifycode = NOP_EXPR; + lhstype = olhstype; } gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE); gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE); @@ -5898,10 +6041,47 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) tree build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { + /* APPLE LOCAL __block assign sequence point 6639533 */ + bool insert_sequence_point = false; + if (processing_template_decl) return build_min_nt (MODOP_EXPR, lhs, build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs); + /* APPLE LOCAL begin __block assign sequence point 6639533 */ + /* For byref = x;, we have to transform this into ({ typeof(x) x' = + x; byref = x`; )} to ensure there is a sequence point before the + evaluation of the byref, inorder to ensure that the access + expression for byref doesn't start running before x is evaluated, + as it will access the __forwarding pointer and that must be done + after x is evaluated. */ + /* First we check to see if lhs is a byref... byrefs look like: + __Block_byref_X.__forwarding->x */ + if (TREE_CODE (lhs) == COMPONENT_REF) + { + tree inner = TREE_OPERAND (lhs, 0); + /* now check for -> */ + if (TREE_CODE (inner) == INDIRECT_REF) + { + inner = TREE_OPERAND (inner, 0); + if (TREE_CODE (inner) == COMPONENT_REF) + { + inner = TREE_OPERAND (inner, 0); + if (TREE_CODE (inner) == VAR_DECL + && COPYABLE_BYREF_LOCAL_VAR (inner)) + { + tree old_rhs = rhs; + /* then we save the rhs. */ + rhs = save_expr (rhs); + if (rhs != old_rhs) + /* And arrange for the sequence point to be inserted. */ + insert_sequence_point = true; + } + } + } + } + /* APPLE LOCAL end __block assign sequence point 6639533 */ + if (modifycode != NOP_EXPR) { tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, @@ -5909,11 +6089,20 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) /*overloaded_p=*/NULL); if (rval) { + /* APPLE LOCAL begin __block assign sequence point 6639533 */ + if (insert_sequence_point) + rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), rhs, rval); + /* APPLE LOCAL end __block assign sequence point 6639533 */ TREE_NO_WARNING (rval) = 1; return rval; } } - return build_modify_expr (lhs, modifycode, rhs); + lhs = build_modify_expr (lhs, modifycode, rhs); + /* APPLE LOCAL begin __block assign sequence point 6639533 */ + if (insert_sequence_point) + lhs = build2 (COMPOUND_EXPR, TREE_TYPE (lhs), rhs, lhs); + /* APPLE LOCAL end __block assign sequence point 6639533 */ + return lhs; } @@ -6220,6 +6409,8 @@ convert_for_assignment (tree type, tree rhs, { tree rhstype; enum tree_code coder; + /* APPLE LOCAL radar 4874632 */ + tree new_rhs = NULL_TREE; /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ if (TREE_CODE (rhs) == NON_LVALUE_EXPR) @@ -6270,8 +6461,10 @@ convert_for_assignment (tree type, tree rhs, } } - if (objc_compare_types (type, rhstype, parmno, rname)) - return convert (type, rhs); + /* APPLE LOCAL file radar 6231433 */ + if (objc_compare_types (type, rhstype, parmno, rname, "comparison")) + /* APPLE LOCAL radar 4874632 */ + new_rhs = convert (type, rhs); } /* [expr.ass] @@ -6477,6 +6670,10 @@ maybe_warn_about_returning_address_of_local (tree retval) if (TREE_CODE (valtype) == REFERENCE_TYPE) warning (0, "reference to local variable %q+D returned", whats_returned); + /* APPLE LOCAL begin blocks 6040305 (cn) */ + else if (TREE_CODE (valtype) == BLOCK_POINTER_TYPE) + error ("returning block that lives on the local stack"); + /* APPLE LOCAL end blocks 6040305 (cn) */ else warning (0, "address of local variable %q+D returned", whats_returned); @@ -6484,6 +6681,14 @@ maybe_warn_about_returning_address_of_local (tree retval) } } +/* APPLE LOCAL begin blocks 6040305 (cm) */ +static bool +types_are_block_compatible (tree t1, tree t2) +{ + return comptypes (t1, t2, COMPARE_STRICT); +} +/* APPLE LOCAL end blocks 6040305 (cm) */ + /* Check that returning RETVAL from the current function is valid. Return an expression explicitly showing all conversions required to change RETVAL into the function return type, and to assign it to @@ -6527,6 +6732,64 @@ check_return_expr (tree retval, bool *no_warning) return NULL_TREE; } + /* APPLE LOCAL begin blocks 6040305 (cm) */ + /* APPLE LOCAL radar 6185344 */ + if (cur_block && !cur_block->block_has_return_type) + { + /* If this is the first return we've seen in the block, infer the type of + the block from it. */ + if (cur_block->return_type == NULL_TREE) + { + if (retval) + { + tree restype; + retval = decay_conversion (retval); + restype = TYPE_MAIN_VARIANT (TREE_TYPE (retval)); + TREE_TYPE (current_function_decl) + = build_function_type (restype, + TYPE_ARG_TYPES (TREE_TYPE (current_function_decl))); + TREE_TYPE (DECL_RESULT (current_function_decl)) = restype; + relayout_decl (DECL_RESULT (current_function_decl)); + cur_block->return_type = restype; + } + else + cur_block->return_type = void_type_node; + } + + /* Verify that this result type matches the previous one. We + are pickier with blocks than for normal functions because + this is a new feature and we set the rules. */ + if (TREE_CODE (cur_block->return_type) == VOID_TYPE) + { + if (retval) + { + error ("void block should not return a value"); + return error_mark_node; + } + } + else if (!retval) + { + error ("non-void block should return a value"); + return error_mark_node; + } + + if (retval) + { + /* We have a non-void block with an expression, continue checking. */ + valtype = TREE_TYPE (retval); + + /* For now, restrict multiple return statements in a block to have + strict compatible types only. */ + if (!types_are_block_compatible (cur_block->return_type, valtype)) + { + error ("incompatible type returning %qT, expected %qT", + valtype, cur_block->return_type); + return error_mark_node; + } + } + } + /* APPLE LOCAL end blocks 6040305 (cm) */ + if (processing_template_decl) { current_function_returns_value = 1; diff --git a/contrib/gcc/dbxout.c b/contrib/gcc/dbxout.c index 5732427f46c2..deabf893df18 100644 --- a/contrib/gcc/dbxout.c +++ b/contrib/gcc/dbxout.c @@ -1825,6 +1825,8 @@ dbxout_type (tree type, int full) { case VOID_TYPE: case LANG_TYPE: + /* APPLE LOCAL blocks 6034272 */ + case BLOCK_POINTER_TYPE: /* For a void type, just define it as itself; i.e., "5=5". This makes us consider it defined without saying what it is. The debugger will make it diff --git a/contrib/gcc/doc/extend.texi b/contrib/gcc/doc/extend.texi index db6f1bd892a1..caf0be0542f4 100644 --- a/contrib/gcc/doc/extend.texi +++ b/contrib/gcc/doc/extend.texi @@ -85,6 +85,8 @@ extensions, accepted by GCC in C89 mode and in C++. * Unnamed Fields:: Unnamed struct/union fields within structs/unions. * Thread-Local:: Per-thread variables. * Binary constants:: Binary constants using the @samp{0b} prefix. +@c APPLE LOCAL blocks 7205047 5811887 +* Blocks:: Anonymous functions (closures). @end menu @node Statement Exprs @@ -378,9 +380,14 @@ allows the data to be read-only. @cindex thunks A @dfn{nested function} is a function defined inside another function. -(Nested functions are not supported for GNU C++.) The nested function's -name is local to the block where it is defined. For example, here we -define a nested function named @code{square}, and call it twice: +@c APPLE LOCAL begin nested functions 4357979 +Nested functions are not supported for GNU C++ and are disable by +default on FreeBSD. The @option{-fnested-functions} and +@option{-fno-nested-functions} options can be used to enable and +disable nested function suppport. The nested function's name is local +to the block where it is defined. For example, here we define a +nested function named @code{square}, and call it twice: +@c APPLE LOCAL end nested functions 4357979 @smallexample @group @@ -3786,6 +3793,22 @@ and caught in another, the class must have default visibility. Otherwise the two shared objects will be unable to use the same typeinfo node and exception handling will break. +@c APPLE LOCAL begin weak types 5954418 +@item weak +In C++, attribute weak can be applied to a class to ensure that all +non-hidden instances of the type are treated as the same type across +shared library boundaries on platforms (such as darwin and arm aapcs) +that can emit vtables and the type info meta data as non-comdat +symbols. This is useful when the class has a key method and the +translation unit that contains the key method is used in more than one +shared library or in a shared library and the application. Doing this +results in more expensive startup times. This attribute is inherited +by subclasses, so it is only necessary to mark a base type. The +typical use would be to mark any types used for throwing across shared +library boundaries or those used in dynamic_cast operations across a +shared library boundary. +@c APPLE LOCAL end weak types 5954418 + @subsection ARM Type Attributes On those ARM targets that support @code{dllimport} (such as Symbian @@ -10534,6 +10557,18 @@ Non-@code{static} members shall not be @code{__thread}. @end quotation @end itemize +@c APPLE LOCAL begin blocks 7205047 5811887 +@node Blocks +@section Blocks +@cindex Blocks +@cindex __block + +Blocks is a language feature that allows one to create anonymous +functions. The feature is also known as lambdas or closures in other +languages. The feature is controlled by @option{-fblocks}. +See @uref{http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html} for additional details. +@c APPLE LOCAL end blocks 7205047 5811887 + @node Binary constants @section Binary constants using the @samp{0b} prefix @cindex Binary constants using the @samp{0b} prefix diff --git a/contrib/gcc/doc/invoke.texi b/contrib/gcc/doc/invoke.texi index dd9a3675f4ce..0eaf2e32a5d2 100644 --- a/contrib/gcc/doc/invoke.texi +++ b/contrib/gcc/doc/invoke.texi @@ -164,10 +164,13 @@ in the following sections. @xref{C Dialect Options,,Options Controlling C Dialect}. @gccoptlist{-ansi -std=@var{standard} -fgnu89-inline @gol -aux-info @var{filename} @gol --fno-asm -fno-builtin -fno-builtin-@var{function} @gol +@c APPLE LOCAL blocks 7205047 5811887 +-fno-asm -fno-blocks -fno-builtin -fno-builtin-@var{function} @gol -fhosted -ffreestanding -fopenmp -fms-extensions @gol -trigraphs -no-integrated-cpp -traditional -traditional-cpp @gol -fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol +@c APPLE LOCAL nested functions 4357979 */ +-fno-nested-functions @gol -fsigned-bitfields -fsigned-char @gol @c APPLE LOCAL -Wnewline-eof 2001-08-23 --sts ** -Wnewline-eof (Apple compatible) @gol @@ -1230,6 +1233,16 @@ effect. In C99 mode (@option{-std=c99} or @option{-std=gnu99}), this switch only affects the @code{asm} and @code{typeof} keywords, since @code{inline} is a standard keyword in ISO C99. +@c APPLE LOCAL begin blocks 7205047 5811887 +@item -fno-blocks +@opindex fno-blocks +Disable the use of blocks. In @option{-std=c99} mode, blocks are +turned off by default. @option{-fblocks} can be used to re-enable the +feature, if off. Runtime support for blocks first appeared in Mac OS +X 10.6. When targeting 10.6 (see @option{-mmacosx-version-min}) and +later, the extension is on by default. +@c APPLE LOCAL end blocks 7205047 5811887 + @item -fno-builtin @itemx -fno-builtin-@var{function} @opindex fno-builtin @@ -1336,6 +1349,13 @@ C compiler. They are now only supported with the @option{-E} switch. The preprocessor continues to support a pre-standard mode. See the GNU CPP manual for details. +@c APPLE LOCAL begin nested functions 4357979 +@item -fno-nested-functions +@opindex fno-nested-functions +Disable nested functions. This option is not supported for C++ or +Objective-C++. On FreeBSD, nested functions are disabled by default. +@c APPLE LOCAL end nested functions 4357979 + @item -fcond-mismatch @opindex fcond-mismatch Allow conditional expressions with mismatched types in the second and diff --git a/contrib/gcc/dwarf2.h b/contrib/gcc/dwarf2.h index 311883727877..524d2bdb404e 100644 --- a/contrib/gcc/dwarf2.h +++ b/contrib/gcc/dwarf2.h @@ -376,7 +376,14 @@ enum dwarf_attribute /* PGI (STMicroelectronics) extensions. */ DW_AT_PGI_lbase = 0x3a00, DW_AT_PGI_soffset = 0x3a01, - DW_AT_PGI_lstride = 0x3a02 + /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to blocks */ + DW_AT_PGI_lstride = 0x3a02, + /* APPLE LOCAL begin radar 6386976 */ + DW_AT_APPLE_block = 0x3fe4, + /* APPLE LOCAL end radar 5811943 - Fix type of pointers to blocks */ + DW_AT_APPLE_major_runtime_vers = 0x3fe5, + DW_AT_APPLE_runtime_class = 0x3fe6 + /* APPLE LOCAL end radar 6386976 */ }; #define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */ diff --git a/contrib/gcc/dwarf2out.c b/contrib/gcc/dwarf2out.c index 81fd0227f927..3300bdecbe2b 100644 --- a/contrib/gcc/dwarf2out.c +++ b/contrib/gcc/dwarf2out.c @@ -4731,6 +4731,11 @@ dwarf_attr_name (unsigned int attr) case DW_AT_VMS_rtnbeg_pd_address: return "DW_AT_VMS_rtnbeg_pd_address"; + /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to Blocks */ + case DW_AT_APPLE_block: + return "DW_AT_APPLE_block"; + /* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks */ + default: return "DW_AT_"; } @@ -8298,6 +8303,8 @@ root_type (tree type) case ERROR_MARK: return error_mark_node; + /* APPLE LOCAL radar 5732232 - blocks */ + case BLOCK_POINTER_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: return type_main_variant (root_type (TREE_TYPE (type))); @@ -8330,6 +8337,8 @@ is_base_type (tree type) case ENUMERAL_TYPE: case FUNCTION_TYPE: case METHOD_TYPE: + /* APPLE LOCAL radar 5732232 - blocks */ + case BLOCK_POINTER_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: case OFFSET_TYPE: @@ -8517,7 +8526,8 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type, mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die, type); sub_die = modified_type_die (type, 0, 0, context_die); } - else if (code == POINTER_TYPE) + /* APPLE LOCAL radar 5732232 - blocks */ + else if (code == POINTER_TYPE || code == BLOCK_POINTER_TYPE) { mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type); add_AT_unsigned (mod_type_die, DW_AT_byte_size, @@ -11170,6 +11180,19 @@ add_type_attribute (dw_die_ref object_die, tree type, int decl_const, enum tree_code code = TREE_CODE (type); dw_die_ref type_die = NULL; +/* APPLE LOCAL begin radar 5847213 */ + /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to blocks */ + /* APPLE LOCAL - radar 6113240 */ + /* APPLE LOCAL begin radar 6300081 */ + if (code == BLOCK_POINTER_TYPE && generic_block_literal_struct_type) + { + type = build_pointer_type (generic_block_literal_struct_type); + code = TREE_CODE (type); + } + /* APPLE LOCAL end radar 6300081 */ + /* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks */ +/* APPLE LOCAL end radar 5847213 */ + /* ??? If this type is an unnamed subrange type of an integral or floating-point type, use the inner type. This is because we have no support for unnamed types in base_type_die. This can happen if this is @@ -12555,7 +12578,11 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die, add_AT_specification (type_die, old_die); else add_name_attribute (type_die, type_tag (type)); - } + /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to Blocks */ + if (TYPE_BLOCK_IMPL_STRUCT (type)) + add_AT_flag (type_die, DW_AT_APPLE_block, 1); + /* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks */ + } else remove_AT (type_die, DW_AT_declaration); @@ -12704,7 +12731,8 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, { case ERROR_MARK: break; - + /* APPLE LOCAL radar 5732232 - blocks */ + case BLOCK_POINTER_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: /* We must set TREE_ASM_WRITTEN in case this is a recursive type. This diff --git a/contrib/gcc/expmed.c b/contrib/gcc/expmed.c index 6a0d3532ca7d..b30301e5512c 100644 --- a/contrib/gcc/expmed.c +++ b/contrib/gcc/expmed.c @@ -2616,16 +2616,12 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, do_alg_addsub_t_m2: for (w = 1; (w & t) != 0; w <<= 1) ; - /* If T was -1, then W will be zero after the loop. This is another - case where T ends with ...111. Handling this with (T + 1) and - subtract 1 produces slightly better code and results in algorithm - selection much faster than treating it like the ...0111 case - below. */ - if (w == 0 - || (w > 2 + /* APPLE LOCAL begin 7744816 DImode multiply by 0xffffffffULL */ + if (w > 2 /* Reject the case where t is 3. Thus we prefer addition in that case. */ - && t != 3)) + && t != 3) + /* APPLE LOCAL end 7744816 DImode multiply by 0xffffffffULL */ { /* T ends with ...111. Multiply by (T + 1) and subtract 1. */ diff --git a/contrib/gcc/expr.c b/contrib/gcc/expr.c index 16e43aa3d742..5a679001d617 100644 --- a/contrib/gcc/expr.c +++ b/contrib/gcc/expr.c @@ -4770,6 +4770,8 @@ count_type_elements (tree type, bool allow_flexarr) case ENUMERAL_TYPE: case BOOLEAN_TYPE: case POINTER_TYPE: + /* APPLE LOCAL radar 5732232 - blocks */ + case BLOCK_POINTER_TYPE: case OFFSET_TYPE: case REFERENCE_TYPE: return 1; diff --git a/contrib/gcc/fold-const.c b/contrib/gcc/fold-const.c index a060bc930508..84be621394ff 100644 --- a/contrib/gcc/fold-const.c +++ b/contrib/gcc/fold-const.c @@ -2150,6 +2150,8 @@ fold_convert (tree type, tree arg) { case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: + /* APPLE LOCAL blocks 5862465 */ + case BLOCK_POINTER_TYPE: case OFFSET_TYPE: if (TREE_CODE (arg) == INTEGER_CST) { diff --git a/contrib/gcc/function.c b/contrib/gcc/function.c index 59970c4bafb4..301e8e615ce7 100644 --- a/contrib/gcc/function.c +++ b/contrib/gcc/function.c @@ -116,6 +116,10 @@ int current_function_uses_only_leaf_regs; post-instantiation libcalls. */ int virtuals_instantiated; +/* APPLE LOCAL begin radar 5732232 - blocks */ +struct block_sema_info *cur_block; +/* APPLE LOCAL end radar 5732232 - blocks */ + /* Assign unique numbers to labels generated for profiling, debugging, etc. */ static GTY(()) int funcdef_no; @@ -214,6 +218,8 @@ static void prepare_function_start (tree); static void do_clobber_return_reg (rtx, void *); static void do_use_return_reg (rtx, void *); static void set_insn_locators (rtx, int) ATTRIBUTE_UNUSED; +/* APPLE LOCAL radar 6163705, Blocks prologues */ +static rtx find_block_prologue_insns (void); /* Pointer to chain of `struct function' for containing functions. */ struct function *outer_function_chain; @@ -3813,17 +3819,23 @@ allocate_struct_function (tree fndecl) DECL_STRUCT_FUNCTION (fndecl) = cfun; cfun->decl = fndecl; - result = DECL_RESULT (fndecl); - if (aggregate_value_p (result, fndecl)) + /* APPLE LOCAL begin radar 5732232 - blocks */ + /* We cannot support blocks which return aggregates because at this + point we do not have info on the return type. */ + if (!cur_block) + { + result = DECL_RESULT (fndecl); + if (aggregate_value_p (result, fndecl)) { #ifdef PCC_STATIC_STRUCT_RETURN current_function_returns_pcc_struct = 1; #endif current_function_returns_struct = 1; } - - current_function_returns_pointer = POINTER_TYPE_P (TREE_TYPE (result)); - + /* This code is not used anywhere ! */ + current_function_returns_pointer = POINTER_TYPE_P (TREE_TYPE (result)); + } + /* APPLE LOCAL end radar 5732232 - blocks */ current_function_stdarg = (fntype && TYPE_ARG_TYPES (fntype) != 0 @@ -5060,6 +5072,140 @@ emit_equiv_load (struct epi_info *p) } #endif +/* APPLE LOCAL begin radar 6163705, Blocks prologues */ + +/* The function should only be called for Blocks functions. + + On being called, the main instruction list for the Blocks function + may contain instructions for setting up the ref_decl and byref_decl + variables in the Block. Those isns really need to go before the + function prologue note rather than after. If such instructions are + present, they are identifiable by their source line number, which + will be one line preceding the declaration of the function. If + they are present, there will also be a source line note instruction + for that line. + + This function does a set of things: + - It finds the first such prologue insn. + - It finds the last such prologue insn. + - It changes the insn locator of all such prologue insns to + the prologue locator. + - It finds the source line note for the bogus location and + removes it. + - It decides if it is safe to place the prolgoue end note + after the last prologue insn it finds, and if so, returns + the last prologue insn (otherwise it returns NULL). + + This function makes the following checks to determine if it is + safe to move the prologue end note to just below the last + prologue insn it finds. If ALL of the checks succeed then it + is safe. If any check fails, this function returns NULL. The + checks it makes are: + + - There were no INSN_P instructions that occurred before the + first prologue insn. + - If there are any non-prologue insns between the first & last + prologue insn, the non-prologue insns do not outnumber the + prologue insns. + - The first prologue insn & the last prologue insn are in the + same basic block. +*/ + +static rtx +find_block_prologue_insns (void) +{ + rtx first_prologue_insn = NULL; + rtx last_prologue_insn = NULL; + rtx line_number_note = NULL; + rtx tmp_insn; + int num_prologue_insns = 0; + int total_insns = 0; + int prologue_line = DECL_SOURCE_LINE (cfun->decl) - 1; + bool other_insns_before_prologue = false; + bool start_of_fnbody_found = false; + + /* Go through all the insns and find the first prologue insn, the + last prologue insn, the source line location note, and whether or + not there are any "real" insns that occur before the first + prologue insn. Re-set the insn locator for prologue insns to the + prologue locator. */ + + for (tmp_insn = get_insns(); tmp_insn; tmp_insn = NEXT_INSN (tmp_insn)) + { + if (INSN_P (tmp_insn)) + { + if (insn_line (tmp_insn) == prologue_line) + { + if (!first_prologue_insn) + first_prologue_insn = tmp_insn; + num_prologue_insns++; + last_prologue_insn = tmp_insn; + INSN_LOCATOR (tmp_insn) = prologue_locator; + } + else if (!first_prologue_insn + && start_of_fnbody_found) + other_insns_before_prologue = true; + } + else if (NOTE_P (tmp_insn) + && NOTE_LINE_NUMBER (tmp_insn) == NOTE_INSN_FUNCTION_BEG) + start_of_fnbody_found = true; + else if (NOTE_P (tmp_insn) + && (XINT (tmp_insn, 5) == prologue_line)) + line_number_note = tmp_insn; + } + + /* If there were no prologue insns, return now. */ + + if (!first_prologue_insn) + return NULL; + + /* If the source location note for the line before the beginning of the + function was found, remove it. */ + + if (line_number_note) + remove_insn (line_number_note); + + /* If other real insns got moved above the prologue insns, we can't + pull out the prologue insns, so return now. */ + + if (other_insns_before_prologue && (optimize > 0)) + return NULL; + + /* Count the number of insns between the first prologue insn and the + last prologue insn; also count the number of non-prologue insns + between the first prologue insn and the last prologue insn. */ + + tmp_insn = first_prologue_insn; + while (tmp_insn != last_prologue_insn) + { + total_insns++; + tmp_insn = NEXT_INSN (tmp_insn); + } + total_insns++; + + /* If more than half of the insns between the first & last prologue + insns are not prologue insns, then there is too much code that + got moved in between prologue insns (by optimizations), so we + will not try to pull it out. */ + + if ((num_prologue_insns * 2) <= total_insns) + return NULL; + + /* Make sure all the prologue insns are within one basic block. + If the insns cross a basic block boundary, then there is a chance + that moving them will cause incorrect code, so don't do it. */ + + gcc_assert (first_prologue_insn != NULL); + gcc_assert (last_prologue_insn != NULL); + + if (BLOCK_FOR_INSN (first_prologue_insn) != + BLOCK_FOR_INSN (last_prologue_insn)) + return NULL; + + return last_prologue_insn; +} +/* APPLE LOCAL end radar 6163705, Blocks prologues */ + /* Generate the prologue and epilogue RTL if the machine supports it. Thread this into place with notes indicating where the prologue ends and where the epilogue begins. Update the basic block information when possible. */ @@ -5083,13 +5229,23 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED) #ifdef HAVE_prologue if (HAVE_prologue) { + /* APPLE LOCAL begin radar 6163705, Blocks prologues */ + rtx last_prologue_insn = NULL; + + if (BLOCK_SYNTHESIZED_FUNC (cfun->decl)) + last_prologue_insn = find_block_prologue_insns(); + /* APPLE LOCAL end radar 6163705, Blocks prologues */ + start_sequence (); seq = gen_prologue (); emit_insn (seq); /* Retain a map of the prologue insns. */ record_insns (seq, &prologue); - prologue_end = emit_note (NOTE_INSN_PROLOGUE_END); + /* APPLE LOCAL begin radar 6163705, Blocks prologues */ + if (!last_prologue_insn) + prologue_end = emit_note (NOTE_INSN_PROLOGUE_END); + /* APPLE LOCAL end radar 6163705, Blocks prologues */ #ifndef PROFILE_BEFORE_PROLOGUE /* Ensure that instructions are not moved into the prologue when @@ -5110,7 +5266,11 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED) insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR)); inserted = 1; - } + + /* APPLE LOCAL begin radar 6163705, Blocks prologues */ + if (last_prologue_insn) + emit_note_after (NOTE_INSN_PROLOGUE_END, last_prologue_insn); + /* APPLE LOCAL end radar 6163705, Blocks prologues */ } #endif /* If the exit block has no non-fake predecessors, we don't need diff --git a/contrib/gcc/function.h b/contrib/gcc/function.h index 1903b165f419..a2b9cb2148dc 100644 --- a/contrib/gcc/function.h +++ b/contrib/gcc/function.h @@ -264,6 +264,12 @@ struct function GTY(()) needed by inner routines. */ rtx x_arg_pointer_save_area; + /* APPLE LOCAL begin radar 6411649 */ + /* Holds a unique number for this function. It is used to + generate block number for block names. */ + int unqiue_block_number; + /* APPLE LOCAL end radar 6411649 */ + /* Offset to end of allocated area of stack frame. If stack grows down, this is the address of the last stack slot allocated. If stack grows up, this is the address for the next slot. */ @@ -579,4 +585,6 @@ extern bool reference_callee_copied (CUMULATIVE_ARGS *, enum machine_mode, extern void used_types_insert (tree); +/* APPLE LOCAL radar 5732232 - blocks */ +extern struct block_sema_info *cur_block; #endif /* GCC_FUNCTION_H */ diff --git a/contrib/gcc/ggc-common.c b/contrib/gcc/ggc-common.c index fe75320bdb1c..0c9a33f75f6a 100644 --- a/contrib/gcc/ggc-common.c +++ b/contrib/gcc/ggc-common.c @@ -716,10 +716,12 @@ ggc_min_expand_heuristic (void) min_expand = ggc_rlimit_bound (min_expand); /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding - a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */ + APPLE LOCAL retune gc params 6124839 + a lower bound of 30% and an upper bound of 150% (when RAM >= 1.7GB). */ min_expand /= 1024*1024*1024; min_expand *= 70; - min_expand = MIN (min_expand, 70); + /* APPLE LOCAL retune gc params 6124839 */ + min_expand = MIN (min_expand, 120); min_expand += 30; return min_expand; @@ -727,7 +729,8 @@ ggc_min_expand_heuristic (void) /* Heuristic to set a default for GGC_MIN_HEAPSIZE. */ int -ggc_min_heapsize_heuristic (void) +/* APPLE LOCAL retune gc params 6124839 */ +ggc_min_heapsize_heuristic (bool optimize) { double phys_kbytes = physmem_total(); double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2); @@ -739,6 +742,13 @@ ggc_min_heapsize_heuristic (void) bound of 128M (when RAM >= 1GB). */ phys_kbytes /= 8; + /* APPLE LOCAL begin retune gc params 6124839 */ + + /* Additionally, on a multicore machine, we assume that we share the + memory with others reasonably equally. */ + phys_kbytes /= (double)ncpu_available() / (2 - optimize); + /* APPLE LOCAL end retune gc params 6124839 */ + #if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS) /* Try not to overrun the RSS limit while doing garbage collection. The RSS limit is only advisory, so no margin is subtracted. */ @@ -765,11 +775,13 @@ ggc_min_heapsize_heuristic (void) } void -init_ggc_heuristics (void) +/* APPLE LOCAL retune gc params 6124839 */ +init_ggc_heuristics (bool optimize ATTRIBUTE_UNUSED) { #if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT set_param_value ("ggc-min-expand", ggc_min_expand_heuristic()); - set_param_value ("ggc-min-heapsize", ggc_min_heapsize_heuristic()); + /* APPLE LOCAL retune gc params 6124839 */ + set_param_value ("ggc-min-heapsize", ggc_min_heapsize_heuristic(optimize)); #endif } diff --git a/contrib/gcc/ggc.h b/contrib/gcc/ggc.h index d6e2303de812..e51b75392d1d 100644 --- a/contrib/gcc/ggc.h +++ b/contrib/gcc/ggc.h @@ -290,8 +290,10 @@ extern void stringpool_statistics (void); /* Heuristics. */ extern int ggc_min_expand_heuristic (void); -extern int ggc_min_heapsize_heuristic (void); -extern void init_ggc_heuristics (void); +/* APPLE LOCAL begin retune gc params 6124839 */ +extern int ggc_min_heapsize_heuristic (bool); +extern void init_ggc_heuristics (bool); +/* APPLE LOCAL end retune gc params 6124839 */ /* Zone collection. */ #if defined (GGC_ZONE) && !defined (GENERATOR_FILE) diff --git a/contrib/gcc/langhooks-def.h b/contrib/gcc/langhooks-def.h index 633642ca31cc..6be4232c09b5 100644 --- a/contrib/gcc/langhooks-def.h +++ b/contrib/gcc/langhooks-def.h @@ -95,6 +95,13 @@ struct gimplify_omp_ctx; extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, tree); +/* APPLE LOCAL begin 6353006 */ +extern tree lhd_build_generic_block_struct_type (void); +/* APPLE LOCAL end 6353006 */ + +/* APPLE LOCAL radar 6386976 */ +extern bool lhd_is_runtime_specific_type (tree); + #define LANG_HOOKS_NAME "GNU unknown" #define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier) #define LANG_HOOKS_INIT hook_bool_void_false @@ -141,6 +148,11 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, #define LANG_HOOKS_FUNCTION_LEAVE_NESTED lhd_do_nothing_f #define LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P hook_bool_tree_true +/* APPLE LOCAL begin radar 6353006 */ +#define LANG_HOOKS_BUILD_GENERIC_BLOCK_STRUCT_TYPE \ +lhd_build_generic_block_struct_type +/* APPLE LOCAL end radar 6353006 */ + /* Attribute hooks. */ #define LANG_HOOKS_ATTRIBUTE_TABLE NULL #define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE NULL @@ -223,6 +235,8 @@ extern tree lhd_make_node (enum tree_code); #define LANG_HOOKS_TYPE_MAX_SIZE lhd_return_null_tree #define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \ lhd_omp_firstprivatize_type_sizes +/* APPLE LOCAL radar 6386976 */ +#define LANG_HOOKS_IS_RUNTIME_SPECIFIC_TYPE lhd_is_runtime_specific_type #define LANG_HOOKS_HASH_TYPES true #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \ @@ -238,6 +252,8 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \ LANG_HOOKS_TYPE_MAX_SIZE, \ LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \ + /* APPLE LOCAL radar 6386976 */ \ + LANG_HOOKS_IS_RUNTIME_SPECIFIC_TYPE, \ LANG_HOOKS_HASH_TYPES \ } @@ -333,6 +349,8 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_BUILTIN_FUNCTION, \ LANG_HOOKS_INIT_TS, \ LANG_HOOKS_EXPR_TO_DECL, \ +/* APPLE LOCAL radar 6353006 */ \ + LANG_HOOKS_BUILD_GENERIC_BLOCK_STRUCT_TYPE, \ } #endif /* GCC_LANG_HOOKS_DEF_H */ diff --git a/contrib/gcc/langhooks.c b/contrib/gcc/langhooks.c index 4c736d054be1..ea2550bc7caa 100644 --- a/contrib/gcc/langhooks.c +++ b/contrib/gcc/langhooks.c @@ -588,3 +588,19 @@ lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *c ATTRIBUTE_UNUSED, tree t ATTRIBUTE_UNUSED) { } + +/* APPLE LOCAL begin radar 6353006 */ +tree +lhd_build_generic_block_struct_type (void) +{ + return NULL_TREE; +} +/* APPLE LOCAL end radar 6353006 */ + +/* APPLE LOCAL begin radar 6386976 */ +bool +lhd_is_runtime_specific_type (tree type ATTRIBUTE_UNUSED) +{ + return false; +} +/* APPLE LOCAL end radar 6386976 */ diff --git a/contrib/gcc/langhooks.h b/contrib/gcc/langhooks.h index 1254c63992a2..65365ff29db7 100644 --- a/contrib/gcc/langhooks.h +++ b/contrib/gcc/langhooks.h @@ -152,6 +152,12 @@ struct lang_hooks_for_types firstprivate variables. */ void (*omp_firstprivatize_type_sizes) (struct gimplify_omp_ctx *, tree); + /* APPLE LOCAL begin radar 6386976 */ + /* Determine whether the type-tree passed in is specific to the + language/runtime definitions, e.g. is an Objective-C class... */ + bool (*is_runtime_specific_type) (tree); + /* APPLE LOCAL end radar 6386976 */ + /* Nonzero if types that are identical are to be hashed so that only one copy is kept. If a language requires unique types for each user-specified type, such as Ada, this should be set to TRUE. */ @@ -468,6 +474,12 @@ struct lang_hooks TREE_SIDE_EFFECTS need updating. */ tree (*expr_to_decl) (tree expr, bool *tc, bool *ti, bool *se); + /* APPLE LOCAL begin radar 6353006 */ + /* For c-based languages, builds a generic type for Blocks pointers (for + emitting debug information. For other languages, returns NULL. */ + tree (*build_generic_block_struct_type) (void); + /* APPLE LOCAL end radar 6353006 */ + /* Whenever you add entries here, make sure you adjust langhooks-def.h and langhooks.c accordingly. */ }; diff --git a/contrib/gcc/stor-layout.c b/contrib/gcc/stor-layout.c index 147ff37a4bc4..2a1d328d9922 100644 --- a/contrib/gcc/stor-layout.c +++ b/contrib/gcc/stor-layout.c @@ -1684,6 +1684,8 @@ layout_type (tree type) case POINTER_TYPE: case REFERENCE_TYPE: + /* APPLE LOCAL blocks */ + case BLOCK_POINTER_TYPE: { enum machine_mode mode = ((TREE_CODE (type) == REFERENCE_TYPE diff --git a/contrib/gcc/stub-objc.c b/contrib/gcc/stub-objc.c index 0cd6017fd1a3..0277289aeeec 100644 --- a/contrib/gcc/stub-objc.c +++ b/contrib/gcc/stub-objc.c @@ -45,6 +45,13 @@ objc_is_object_ptr (tree ARG_UNUSED (arg)) return 0; } +/* APPLE LOCAL begin radar 4133425 */ +bool objc_diagnose_private_ivar (tree ARG_UNUSED (arg)) +{ + return false; +} +/* APPLE LOCAL end radar 4133425 */ + tree objc_lookup_ivar (tree other, tree ARG_UNUSED (arg)) { @@ -56,6 +63,28 @@ void objc_check_decl (tree ARG_UNUSED (decl)) { } + +/* APPLE LOCAL begin radar 4281748 */ +void +objc_check_global_decl (tree ARG_UNUSED (decl)) +{ +} +/* APPLE LOCAL end radar 4281748 */ + +/* APPLE LOCAL begin radar 4330422 */ +tree +objc_non_volatilized_type (tree type) +{ + return type; +} +/* APPLE LOCAL end radar 4330422 */ + +/* APPLE LOCAL begin radar 4697411 */ +void +objc_volatilize_component_ref (tree ARG_UNUSED (cref), tree ARG_UNUSED (type)) +{ +} +/* APPLE LOCAL end radar 4697411 */ int objc_is_reserved_word (tree ARG_UNUSED (ident)) @@ -63,12 +92,33 @@ objc_is_reserved_word (tree ARG_UNUSED (ident)) return 0; } -bool -objc_compare_types (tree ARG_UNUSED (ltyp), tree ARG_UNUSED (rtyp), - int ARG_UNUSED (argno), tree ARG_UNUSED (callee)) +/* APPLE LOCAL begin 4154928 */ +tree +objc_common_type (tree ARG_UNUSED (type1), tree ARG_UNUSED (type2)) { return false; } +/* APPLE LOCAL end 4154928 */ + +bool +objc_compare_types (tree ARG_UNUSED (ltyp), tree ARG_UNUSED (rtyp), + /* APPLE LOCAL begin radar 6231433 */ + int ARG_UNUSED (argno), tree ARG_UNUSED (callee), + const char * ARG_UNUSED (message)) + /* APPLE LOCAL end radar 6231433 */ +{ + return false; +} + +/* APPLE LOCAL begin radar 4229905 - radar 6231433 */ +bool +objc_have_common_type (tree ARG_UNUSED (ltyp), tree ARG_UNUSED (rtyp), + int ARG_UNUSED (argno), tree ARG_UNUSED (callee), + const char * ARG_UNUSED (message)) +{ + return false; +} +/* APPLE LOCAL end radar 4229905 - radar 6231433 */ void objc_volatilize_decl (tree ARG_UNUSED (decl)) @@ -104,20 +154,26 @@ objc_declare_class (tree ARG_UNUSED (list)) } void -objc_declare_protocols (tree ARG_UNUSED (list)) +/* APPLE LOCAL begin radar 4947311 - protocol attributes */ +objc_declare_protocols (tree ARG_UNUSED (list), tree ARG_UNUSED (attributes)) { } void objc_start_protocol (tree ARG_UNUSED (proto), - tree ARG_UNUSED (protorefs)) + tree ARG_UNUSED (protorefs), + tree ARG_UNUSED (attributes)) { } +/* APPLE LOCAL end radar 4947311 - protocol attributes */ void objc_start_class_interface (tree ARG_UNUSED (name), tree ARG_UNUSED (super), - tree ARG_UNUSED (protos)) +/* APPLE LOCAL begin radar 4548636 */ + tree ARG_UNUSED (protos), + tree ARG_UNUSED (attributes)) +/* APPLE LOCAL end radar 4548636 */ { } @@ -181,12 +237,18 @@ objc_finish_implementation (void) } void -objc_add_method_declaration (tree ARG_UNUSED (signature)) +/* APPLE LOCAL begin radar 3803157 - objc attribute */ +objc_add_method_declaration (tree ARG_UNUSED (signature), + tree ARG_UNUSED (attribute)) +/* APPLE LOCAL end radar 3803157 - objc attribute */ { } void -objc_start_method_definition (tree ARG_UNUSED (signature)) +/* APPLE LOCAL begin radar 3803157 - objc attribute */ +objc_start_method_definition (tree ARG_UNUSED (signature), + tree ARG_UNUSED (attribute)) +/* APPLE LOCAL end radar 3803157 - objc attribute */ { } @@ -198,7 +260,10 @@ objc_finish_method_definition (tree ARG_UNUSED (fndecl)) tree objc_build_keyword_decl (tree ARG_UNUSED (selector), tree ARG_UNUSED (typename), - tree ARG_UNUSED (identifier)) + /* APPLE LOCAL begin radar 4157812 */ + tree ARG_UNUSED (identifier), + tree ARG_UNUSED (attribute)) + /* APPLE LOCAL end radar 4157812 */ { return 0; } @@ -248,6 +313,18 @@ objc_get_class_reference (tree ARG_UNUSED (name)) return 0; } +/* APPLE LOCAL begin radar 4291785 */ +tree +objc_get_interface_ivars (tree ARG_UNUSED (fieldlist)) +{ + return 0; +} +void +objc_detect_field_duplicates (tree ARG_UNUSED (fieldlist)) +{ +} +/* APPLE LOCAL end radar 4291785 */ + tree objc_get_protocol_qualified_type (tree ARG_UNUSED (name), tree ARG_UNUSED (protos)) @@ -273,6 +350,49 @@ objc_is_public (tree ARG_UNUSED (expr), tree ARG_UNUSED (identifier)) return 1; } +/* APPLE LOCAL begin C* language */ +void +objc_set_method_opt (int ARG_UNUSED (opt)) +{ +} + +tree +objc_build_component_ref (tree ARG_UNUSED (datum), tree ARG_UNUSED (component)) +{ + return 0; +} + +tree +objc_build_foreach_components (tree ARG_UNUSED (receiver), + tree *ARG_UNUSED (enumState_decl), + tree *ARG_UNUSED (items_decl), + tree *ARG_UNUSED (limit_decl), + tree *ARG_UNUSED (startMutations_decl), + tree *ARG_UNUSED (counter_decl), + tree *ARG_UNUSED (countByEnumeratingWithState)) +{ + return 0; +} +/* APPLE LOCAL end C* language */ + +/* APPLE LOCAL begin C* property (Radar 4436866) */ +void +objc_set_property_attr (int ARG_UNUSED (code), tree ARG_UNUSED (identifier)) +{ +} +void +objc_add_property_variable (tree ARG_UNUSED (prop)) +{ +} +/* APPLE LOCAL radar 5285911 */ +/* Stub for objc_build_getter_call is removed. */ +tree +objc_build_setter_call (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs)) +{ + return 0; +} +/* APPLE LOCAL end C* property (Radar 4436866) */ + tree objc_get_class_ivars (tree ARG_UNUSED (name)) { @@ -326,3 +446,143 @@ objc_generate_write_barrier (tree ARG_UNUSED (lhs), { return 0; } +/* APPLE LOCAL begin radar 5276085 */ +void objc_weak_reference_expr (tree* ARG_UNUSED (expr)) +{ +} + +tree +objc_build_weak_reference_tree (tree expr) +{ + return expr; +} +/* APPLE LOCAL end radar 5276085 */ + +/* APPLE LOCAL begin C* warnings to easy porting to new abi */ +void +diagnose_selector_cast (tree ARG_UNUSED (cast_type), tree ARG_UNUSED (sel_exp)) +{ +} +/* APPLE LOCAL end C* warnings to easy porting to new abi */ + +/* APPLE LOCAL begin radar 4441049 */ +tree +objc_v2_component_ref_field_offset (tree ARG_UNUSED (exp)) +{ + return 0; +} + +tree +objc_v2_bitfield_ivar_bitpos (tree ARG_UNUSED (exp)) +{ + return 0; +} +/* APPLE LOCAL end radar 4441049 */ +/* APPLE LOCAL begin radar 4507230 */ +bool +objc_type_valid_for_messaging (tree ARG_UNUSED (exp)) +{ + return false; +} +/* APPLE LOCAL end radar 4507230 */ +/* APPLE LOCAL begin radar 3803157 - objc attribute */ +bool +objc_method_decl (enum tree_code ARG_UNUSED (opcode)) +{ + return false; +} +/* APPLE LOCAL end radar 3803157 - objc attribute */ + +/* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ +void +objc_finish_foreach_loop (location_t ARG_UNUSED (location), tree ARG_UNUSED (cond), + tree ARG_UNUSED (for_body), tree ARG_UNUSED (blab), + tree ARG_UNUSED (clab)) +{ + return; +} +/* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ +/* APPLE LOCAL begin radar 5847976 */ +int +objc_is_gcable_type (tree ARG_UNUSED (type)) +{ + return 0; +} +/* APPLE LOCAL end radar 5847976 */ +/* APPLE LOCAL begin radar 4592503 */ +void +objc_checkon_weak_attribute (tree ARG_UNUSED (decl)) +{ + return; +} +/* APPLE LOCAL end radar 4592503 */ +/* APPLE LOCAL begin radar 4712269 */ +tree +objc_build_incr_decr_setter_call (enum tree_code ARG_UNUSED (code), + tree ARG_UNUSED (lhs), + tree ARG_UNUSED (inc)) +{ + return NULL_TREE; +} +/* APPLE LOCAL end radar 4712269 */ +/* APPLE LOCAL begin objc new property */ +void objc_declare_property_impl (int ARG_UNUSED (code), + tree ARG_UNUSED (tree_list)) +{ +} +/* APPLE LOCAL begin radar 5285911 */ +tree +objc_build_property_reference_expr (tree ARG_UNUSED (datum), + tree ARG_UNUSED (component)) +{ + return 0; +} +bool +objc_property_reference_expr (tree ARG_UNUSED (exp)) +{ + return false; +} +/* APPLE LOCAL end radar 5285911 */ +/* APPLE LOCAL end objc new property */ +/* APPLE LOCAL begin radar 4985544 */ +bool +objc_check_format_nsstring (tree ARG_UNUSED (argument), + unsigned HOST_WIDE_INT ARG_UNUSED (format_num), + bool * ARG_UNUSED(no_add_attrs)) +{ + return false; +} +/* APPLE LOCAL end radar 4985544 */ +/* APPLE LOCAL begin radar 5202926 */ +bool +objc_anonymous_local_objc_name (const char * ARG_UNUSED (name)) +{ + return false; +} +/* APPLE LOCAL begin radar 5195402 */ +bool +objc_check_nsstring_pointer_type (tree ARG_UNUSED (type)) +{ + return false; +} +/* APPLE LOCAL end radar 5195402 */ +/* APPLE LOCAL end radar 5202926 */ + +/* APPLE LOCAL begin radar 5782740 - blocks */ +bool block_requires_copying (tree exp) +{ + /* APPLE LOCAL begin radar 6175959 */ + tree type = TREE_TYPE (exp); + return TREE_CODE (type) == BLOCK_POINTER_TYPE + || (POINTER_TYPE_P (type) + && lookup_attribute ("NSObject", TYPE_ATTRIBUTES (type))); + /* APPLE LOCAL end radar 6175959 */ +} +/* APPLE LOCAL end radar 5782740 - blocks */ + +/* APPLE LOCAL begin radar 5802025 */ +tree objc_build_property_getter_func_call (tree object) +{ + return object; +} +/* APPLE LOCAL end radar 5802025 */ diff --git a/contrib/gcc/targhooks.c b/contrib/gcc/targhooks.c index 796bd2d6f3dc..acfa0804dbab 100644 --- a/contrib/gcc/targhooks.c +++ b/contrib/gcc/targhooks.c @@ -95,6 +95,18 @@ default_return_in_memory (tree type, #endif } +/* APPLE LOCAL begin radar 4781080 */ +bool +default_objc_fpreturn_msgcall (tree type, bool no_long_double) +{ +#ifndef OBJC_FPRETURN_MSGCALL + return type == NULL_TREE && no_long_double; +#else + return OBJC_FPRETURN_MSGCALL (type, no_long_double); +#endif +} +/* APPLE LOCAL end radar 4781080 */ + rtx default_expand_builtin_saveregs (void) { diff --git a/contrib/gcc/toplev.c b/contrib/gcc/toplev.c index 786ec128977b..6944eaefa955 100644 --- a/contrib/gcc/toplev.c +++ b/contrib/gcc/toplev.c @@ -1566,8 +1566,19 @@ general_init (const char *argv0) /* Register the language-independent parameters. */ add_params (lang_independent_params, LAST_PARAM); - /* This must be done after add_params but before argument processing. */ - init_ggc_heuristics(); + /* APPLE LOCAL begin retune gc params 6124839 */ + { int i = 0; + bool opt = false; + while (save_argv[++i]) + { + if (strncmp (save_argv[i], "-O", 2) == 0 + && strcmp (save_argv[i], "-O0") != 0) + opt = true; + } + /* This must be done after add_params but before argument processing. */ + init_ggc_heuristics(opt); + } + /* APPLE LOCAL end retune gc params 6124839 */ init_optimization_passes (); } diff --git a/contrib/gcc/tree-gimple.h b/contrib/gcc/tree-gimple.h index 60fde4ec9ff6..b3a4d501e821 100644 --- a/contrib/gcc/tree-gimple.h +++ b/contrib/gcc/tree-gimple.h @@ -140,7 +140,8 @@ extern void diagnose_omp_structured_block_errors (tree); extern tree omp_reduction_init (tree, tree); /* In tree-nested.c. */ -extern void lower_nested_functions (tree); +/* APPLE LOCAL radar 6305545 */ +extern void lower_nested_functions (tree, bool); extern void insert_field_into_struct (tree, tree); /* Convenience routines to walk all statements of a gimple function. diff --git a/contrib/gcc/tree-nested.c b/contrib/gcc/tree-nested.c index 9efcd98f0141..75927121a807 100644 --- a/contrib/gcc/tree-nested.c +++ b/contrib/gcc/tree-nested.c @@ -1970,7 +1970,8 @@ static GTY(()) struct nesting_info *root; subroutines and turn them into something less tightly bound. */ void -lower_nested_functions (tree fndecl) +/* APPLE LOCAL radar 6305545 */ +lower_nested_functions (tree fndecl, bool skip_outermost_fndecl) { struct cgraph_node *cgn; @@ -1980,6 +1981,13 @@ lower_nested_functions (tree fndecl) return; root = create_nesting_tree (cgn); + /* APPLE LOCAL begin radar 6305545 */ + /* If skip_outermost_fndecl is true, we are lowering nested functions of + a constructor/destructor which are cloned and thrown away. But we + still have to lower their nested functions, but not the outermost function. */ + if (skip_outermost_fndecl) + root = root->inner; + /* APPLE LOCAL end radar 6305545 */ walk_all_functions (convert_nonlocal_reference, root); walk_all_functions (convert_local_reference, root); walk_all_functions (convert_nl_goto_reference, root); diff --git a/contrib/gcc/tree.c b/contrib/gcc/tree.c index 8e0b801725d7..a020bb1bd26c 100644 --- a/contrib/gcc/tree.c +++ b/contrib/gcc/tree.c @@ -69,6 +69,10 @@ const char *const tree_code_class_strings[] = "expression", }; +/* APPLE LOCAL begin 6353006 */ +tree generic_block_literal_struct_type; +/* APPLE LOCAL end 6353006 */ + /* obstack.[ch] explicitly declined to prototype this. */ extern int _obstack_allocated_p (struct obstack *h, void *obj); @@ -5016,6 +5020,31 @@ build_pointer_type (tree to_type) return build_pointer_type_for_mode (to_type, ptr_mode, false); } +/* APPLE LOCAL begin radar 5732232 - blocks */ +tree +build_block_pointer_type (tree to_type) +{ + tree t; + + /* APPLE LOCAL begin radar 6300081 & 6353006 */ + if (!generic_block_literal_struct_type) + generic_block_literal_struct_type = + lang_hooks.build_generic_block_struct_type (); + /* APPLE LOCAL end radar 6300081 & 6353006 */ + + t = make_node (BLOCK_POINTER_TYPE); + + TREE_TYPE (t) = to_type; + TYPE_MODE (t) = ptr_mode; + + /* Lay out the type. This function has many callers that are concerned + with expression-construction, and this simplifies them all. */ + layout_type (t); + + return t; +} +/* APPLE LOCAL end radar 5732232 - blocks */ + /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE. */ tree @@ -7771,4 +7800,5 @@ empty_body_p (tree stmt) return true; } + #include "gt-tree.h" diff --git a/contrib/gcc/tree.def b/contrib/gcc/tree.def index d3106a1fcb4d..d8eb14aa43af 100644 --- a/contrib/gcc/tree.def +++ b/contrib/gcc/tree.def @@ -177,6 +177,11 @@ DEFTREECODE (POINTER_TYPE, "pointer_type", tcc_type, 0) automatically to the value it points to. Used in C++. */ DEFTREECODE (REFERENCE_TYPE, "reference_type", tcc_type, 0) +/* APPLE LOCAL begin radar 5732232 - blocks */ +/* All pointer-to-block types have code BLOCK_POINTER_TYPE. + The TREE_TYPE points to the node for the type pointed to. */ +DEFTREECODE (BLOCK_POINTER_TYPE, "block_pointer_type", tcc_type, 0) +/* APPLE LOCAL end radar 5732232 - blocks */ /* The ordering of the following codes is optimized for the checking macros in tree.h. Changing the order will degrade the speed of the compiler. COMPLEX_TYPE, VECTOR_TYPE, ARRAY_TYPE. */ diff --git a/contrib/gcc/tree.h b/contrib/gcc/tree.h index e8870f0ef6e3..541cb83f0376 100644 --- a/contrib/gcc/tree.h +++ b/contrib/gcc/tree.h @@ -869,7 +869,8 @@ extern void omp_clause_range_check_failed (const tree, const char *, int, #define CST_CHECK(T) TREE_CLASS_CHECK (T, tcc_constant) #define STMT_CHECK(T) TREE_CLASS_CHECK (T, tcc_statement) #define FUNC_OR_METHOD_CHECK(T) TREE_CHECK2 (T, FUNCTION_TYPE, METHOD_TYPE) -#define PTR_OR_REF_CHECK(T) TREE_CHECK2 (T, POINTER_TYPE, REFERENCE_TYPE) +/* APPLE LOCAL blocks 5862465 */ +#define PTR_OR_REF_CHECK(T) TREE_CHECK3 (T, POINTER_TYPE, REFERENCE_TYPE, BLOCK_POINTER_TYPE) #define RECORD_OR_UNION_CHECK(T) \ TREE_CHECK3 (T, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE) @@ -998,8 +999,12 @@ extern void omp_clause_range_check_failed (const tree, const char *, int, (It should be renamed to INDIRECT_TYPE_P.) Keep these checks in ascending code order. */ +/* APPLE LOCAL begin blocks 5862465 */ #define POINTER_TYPE_P(TYPE) \ - (TREE_CODE (TYPE) == POINTER_TYPE || TREE_CODE (TYPE) == REFERENCE_TYPE) + (TREE_CODE (TYPE) == POINTER_TYPE \ + || TREE_CODE (TYPE) == REFERENCE_TYPE \ + || TREE_CODE (TYPE) == BLOCK_POINTER_TYPE) +/* APPLE LOCAL end blocks 5862465 */ /* Nonzero if this type is a complete type. */ #define COMPLETE_TYPE_P(NODE) (TYPE_SIZE (NODE) != NULL_TREE) @@ -2102,6 +2107,17 @@ struct tree_block GTY(()) #define TYPE_CONTAINS_PLACEHOLDER_INTERNAL(NODE) \ (TYPE_CHECK (NODE)->type.contains_placeholder_bits) +/* APPLE LOCAL begin radar 5811943 - Fix type of pointers to blocks */ +/* Indicates that the struct type is a block struct, rather than + a 'normal' struct, i.e. one of its fields is a function that can + be called. This uses the existing bit-field lang_flag_2 in the + struct tree_type, rather than creating a new bit field, as + lang_flag_2 is currently unused and we don't want to increase the + size of trees if we can avoid it. */ +#define TYPE_BLOCK_IMPL_STRUCT(NODE) \ +(TYPE_CHECK (NODE)->type.lang_flag_2) +/* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks */ + struct die_struct; struct tree_type GTY(()) @@ -2126,6 +2142,14 @@ struct tree_type GTY(()) unsigned lang_flag_0 : 1; unsigned lang_flag_1 : 1; + /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to Blocks */ + /* Since it is currently completely unused, and in the interest of + not making trees any bigger than they already are, lang_flag_2 + in the tree_type struct will be used to indicate that a struct is a + block struct. The macro used for these purposes is + TYPE_BLOCK_IMPL_STRUCT, rather than TYPE_LANG_FLAG_2, in order to make + its uses in the code more clear. */ + /* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks */ unsigned lang_flag_2 : 1; unsigned lang_flag_3 : 1; unsigned lang_flag_4 : 1; @@ -2595,6 +2619,9 @@ struct tree_decl_common GTY(()) unsigned gimple_reg_flag : 1; unsigned call_clobbered_flag : 1; + /* APPLE LOCAL duplicate decls in multiple files. */ + unsigned duplicate_decl : 1; + unsigned int align : 24; /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */ unsigned int off_align : 8; @@ -2776,6 +2803,9 @@ struct tree_parm_decl GTY(()) so it should not be output now. */ #define DECL_DEFER_OUTPUT(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.defer_output) +/* APPLE LOCAL duplicate decls in multiple files. */ +#define DECL_DUPLICATE_DECL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.duplicate_decl) + /* Nonzero for a given ..._DECL node means that no warnings should be generated just because this node is unused. */ #define DECL_IN_SYSTEM_HEADER(NODE) \ @@ -2919,7 +2949,21 @@ struct tree_decl_with_vis GTY(()) /* Belongs to VAR_DECL exclusively. */ ENUM_BITFIELD(tls_model) tls_model : 3; - /* 11 unused bits. */ + + /* APPLE LOCAL begin radar 5732232 - blocks */ + /* Belong to VAR_DECL exclusively. */ + unsigned block_decl_byref : 1; + unsigned block_decl_copied : 1; + /* APPLE LOCAL begin radar 5932809 - copyable byref blocks */ + unsigned copyable_byref_local_var : 1; + unsigned copyable_byref_local_nonpod : 1; + /* APPLE LOCAL radar 6172148 */ + unsigned block_synthesized_function : 1; + /* APPLE LOCAL radar 5847976 */ + unsigned block_weak : 1; + /* 5 unused bits. */ + /* APPLE LOCAL end radar 5932809 - copyable byref blocks */ + /* APPLE LOCAL end radar 5732232 - blocks */ }; /* In a VAR_DECL that's static, @@ -2965,6 +3009,19 @@ extern void decl_init_priority_insert (tree, unsigned short); thread-local storage. */ #define DECL_TLS_MODEL(NODE) (VAR_DECL_CHECK (NODE)->decl_with_vis.tls_model) +/* APPLE LOCAL begin radar 5732232 - blocks */ +#define BLOCK_DECL_BYREF(NODE) (VAR_DECL_CHECK (NODE)->decl_with_vis.block_decl_byref) +#define BLOCK_DECL_COPIED(NODE) (VAR_DECL_CHECK (NODE)->decl_with_vis.block_decl_copied) +/* APPLE LOCAL end radar 5732232 - blocks */ +/* APPLE LOCAL radar 6172148 */ +#define BLOCK_SYNTHESIZED_FUNC(NODE) (FUNCTION_DECL_CHECK (NODE)->decl_with_vis.block_synthesized_function) +/* APPLE LOCAL begin radar 5932809 - copyable byref blocks */ +#define COPYABLE_BYREF_LOCAL_VAR(NODE) (VAR_DECL_CHECK (NODE)->decl_with_vis.copyable_byref_local_var) +#define COPYABLE_BYREF_LOCAL_NONPOD(NODE) (VAR_DECL_CHECK (NODE)->decl_with_vis.copyable_byref_local_nonpod) +/* APPLE LOCAL radar 5847976 */ +#define COPYABLE_WEAK_BLOCK(NODE) (VAR_DECL_CHECK (NODE)->decl_with_vis.block_weak) +/* APPLE LOCAL end radar 5932809 - copyable byref blocks */ + /* In a VAR_DECL, nonzero if the data should be allocated from thread-local storage. */ #define DECL_THREAD_LOCAL_P(NODE) \ @@ -3615,6 +3672,8 @@ extern void set_sizetype (tree); extern void fixup_unsigned_type (tree); extern tree build_pointer_type_for_mode (tree, enum machine_mode, bool); extern tree build_pointer_type (tree); +/* APPLE LOCAL radar 5732232 - blocks */ +extern tree build_block_pointer_type (tree); extern tree build_reference_type_for_mode (tree, enum machine_mode, bool); extern tree build_reference_type (tree); extern tree build_vector_type_for_mode (tree, enum machine_mode); @@ -4661,4 +4720,8 @@ extern unsigned HOST_WIDE_INT compute_builtin_object_size (tree, int); /* In expr.c. */ extern unsigned HOST_WIDE_INT highest_pow2_factor (tree); +/* APPLE LOCAL begin radar 6300081 */ +extern GTY(()) tree generic_block_literal_struct_type; +/* APPLE LOCAL end radar 6300081 */ + #endif /* GCC_TREE_H */ diff --git a/contrib/gcc/varasm.c b/contrib/gcc/varasm.c index ef3a83a9990d..7c3edcdc0e30 100644 --- a/contrib/gcc/varasm.c +++ b/contrib/gcc/varasm.c @@ -4071,6 +4071,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) case ENUMERAL_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: + /* APPLE LOCAL radar 5822844 */ + case BLOCK_POINTER_TYPE: case OFFSET_TYPE: if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER), diff --git a/contrib/gcclibs/include/libiberty.h b/contrib/gcclibs/include/libiberty.h index c25667cc9572..c0f5151fb241 100644 --- a/contrib/gcclibs/include/libiberty.h +++ b/contrib/gcclibs/include/libiberty.h @@ -296,6 +296,10 @@ extern char *xstrndup (const char *, size_t) ATTRIBUTE_MALLOC; extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC; +/* APPLE LOCAL begin retune gc params 6124839 */ +extern unsigned int ncpu_available (void); +/* APPLE LOCAL end retune gc params 6124839 */ + /* Physical memory routines. Return values are in BYTES. */ extern double physmem_total (void); extern double physmem_available (void); diff --git a/contrib/gcclibs/libiberty/physmem.c b/contrib/gcclibs/libiberty/physmem.c index 09fbf3f8c83e..3c181694d8db 100644 --- a/contrib/gcclibs/libiberty/physmem.c +++ b/contrib/gcclibs/libiberty/physmem.c @@ -182,6 +182,36 @@ physmem_total (void) return 0; } +/* APPLE LOCAL begin retune gc params 6124839 */ +unsigned int +ncpu_available (void) +{ +#if HAVE_SYSCTL && defined HW_AVAILCPU + { /* This works on *bsd and darwin. */ + unsigned int ncpu; + size_t len = sizeof ncpu; + static int mib[2] = { CTL_HW, HW_AVAILCPU }; + + if (sysctl (mib, ARRAY_SIZE (mib), &ncpu, &len, NULL, 0) == 0 + && len == sizeof (ncpu)) + return ncpu; + } +#endif +#if HAVE_SYSCTL && defined HW_NCPU + { /* This works on *bsd and darwin. */ + unsigned int ncpu; + size_t len = sizeof ncpu; + static int mib[2] = { CTL_HW, HW_NCPU }; + + if (sysctl (mib, ARRAY_SIZE (mib), &ncpu, &len, NULL, 0) == 0 + && len == sizeof (ncpu)) + return ncpu; + } +#endif + return 1; +} +/* APPLE LOCAL end retune gc params 6124839 */ + /* Return the amount of physical memory available. */ double physmem_available (void)