[llvm-commits] [llvm-gcc-4.2] r54196 - in /llvm-gcc-4.2/trunk/gcc: c-common.c c-decl.c c-parser.c c-typeck.c config/rs6000/rs6000.c cp/call.c cp/decl.c cp/error.c cp/mangle.c cp/name-lookup.c cp/parser.c cp/semantics.c cp/typeck.c dwarf2out.c expr.c function.c objc/objc-act.c tree.h

Bill Wendling isanbard at gmail.com
Tue Jul 29 21:41:35 PDT 2008


Author: void
Date: Tue Jul 29 23:41:34 2008
New Revision: 54196

URL: http://llvm.org/viewvc/llvm-project?rev=54196&view=rev
Log:
Merges from Apple's GCC 4.2 r148430

Modified:
    llvm-gcc-4.2/trunk/gcc/c-common.c
    llvm-gcc-4.2/trunk/gcc/c-decl.c
    llvm-gcc-4.2/trunk/gcc/c-parser.c
    llvm-gcc-4.2/trunk/gcc/c-typeck.c
    llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.c
    llvm-gcc-4.2/trunk/gcc/cp/call.c
    llvm-gcc-4.2/trunk/gcc/cp/decl.c
    llvm-gcc-4.2/trunk/gcc/cp/error.c
    llvm-gcc-4.2/trunk/gcc/cp/mangle.c
    llvm-gcc-4.2/trunk/gcc/cp/name-lookup.c
    llvm-gcc-4.2/trunk/gcc/cp/parser.c
    llvm-gcc-4.2/trunk/gcc/cp/semantics.c
    llvm-gcc-4.2/trunk/gcc/cp/typeck.c
    llvm-gcc-4.2/trunk/gcc/dwarf2out.c
    llvm-gcc-4.2/trunk/gcc/expr.c
    llvm-gcc-4.2/trunk/gcc/function.c
    llvm-gcc-4.2/trunk/gcc/objc/objc-act.c
    llvm-gcc-4.2/trunk/gcc/tree.h

Modified: llvm-gcc-4.2/trunk/gcc/c-common.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/c-common.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/c-common.c (original)
+++ llvm-gcc-4.2/trunk/gcc/c-common.c Tue Jul 29 23:41:34 2008
@@ -202,6 +202,11 @@
 
 */
 
+/* APPLE LOCAL begin radar 5811943 - Fix type of pointers to Blocks  */
+/* Move declaration of invoke_impl_ptr_type from c-typeck.c  */
+tree invoke_impl_ptr_type;
+/* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks  */
+
 tree c_global_trees[CTI_MAX];
 
 /* Switches common to the C front ends.  */
@@ -626,6 +631,8 @@
 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 *);
 
 /* LLVM LOCAL begin */
 #ifdef ENABLE_LLVM
@@ -744,6 +751,8 @@
 			      handle_gcroot_attribute },
   #endif
   /* LLVM LOCAL end */
+  /* APPLE LOCAL radar 5932809 - copyable byref blocks */
+  { "blocks", 1, 1, true, false, false, handle_blocks_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
@@ -6047,6 +6056,119 @@
   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;
+  *no_add_attrs = true;
+  if (!(*node) || TREE_CODE (*node) != VAR_DECL)
+    {
+      warning (OPT_Wattributes, "byref attribute can be specified on variables only - ignored");
+      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;
+    }
+
+  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 */
+static tree block_byref_release_decl;
+
+/* Build a: void _Block_byref_release (void *) if not done
+  already. */
+tree
+build_block_byref_release_decl (void)
+{
+  if (!block_byref_release_decl &&
+      !(block_byref_release_decl =
+        lookup_name (get_identifier ("_Block_byref_release"))))
+  {
+    tree func_type =
+    build_function_type (void_type_node,
+                         tree_cons (NULL_TREE, ptr_type_node, void_list_node));
+
+    block_byref_release_decl =
+      builtin_function ("_Block_byref_release", func_type, 0, NOT_BUILT_IN, 
+			0, NULL_TREE);
+
+    TREE_NOTHROW (block_byref_release_decl) = 0;
+  }
+  return block_byref_release_decl;
+}
+
+/* This routine builds call to:
+ _Block_byref_release(VAR_DECL.forwarding);
+ and adds it to the statement list.
+ */
+tree
+build_block_byref_release_exp (tree var_decl)
+{
+  tree exp = var_decl, call_exp, func_params;
+  tree type = TREE_TYPE (var_decl);
+  /* __block variables imported into Blocks are not _Block_byref_released()
+   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_byref_release(void*) if not done already. */
+  exp = build_component_ref (exp, get_identifier ("forwarding"));
+  func_params = tree_cons (NULL_TREE, exp, NULL_TREE);
+  call_exp = build_function_call (build_block_byref_release_decl (), func_params);
+  return call_exp;
+}
+/* APPLE LOCAL begin 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 */
+
 /* Handle a "sentinel" attribute.  */
 
 static tree

Modified: llvm-gcc-4.2/trunk/gcc/c-decl.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/c-decl.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/c-decl.c (original)
+++ llvm-gcc-4.2/trunk/gcc/c-decl.c Tue Jul 29 23:41:34 2008
@@ -61,8 +61,11 @@
 #include "except.h"
 #include "langhooks-def.h"
 #include "pointer-set.h"
-/* LLVM LOCAL */
+/* LLVM LOCAL - begin */
+#ifdef ENABLE_LLVM
 #include "llvm.h"
+#endif
+/* LLVM LOCAL - end */
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -323,6 +326,14 @@
   tree blocks;
   tree blocks_last;
 
+  /* APPLE LOCAL begin radar 6083129 -  byref escapes (C++ cp) */
+  /* None-zero if outermost block of a statement which can have a 
+     break/continue stmt; such as while, switch, etc. This cannot be
+     a boolen field because the same scope can be used for a nested
+     while/for statement; as in, while(...) while (...). */
+  unsigned int  bc_stmt_body;
+  /* APPLE LOCAL end radar 6083129 -  byref escapes (C++ cp) */
+
   /* The depth of this scope.  Used to keep the ->shadowed chain of
      bindings sorted innermost to outermost.  */
   unsigned int depth : 28;
@@ -348,6 +359,12 @@
 
   /* True means make a BLOCK for this scope no matter what.  */
   BOOL_BITFIELD keep : 1;
+
+  /* APPLE LOCAL begin radar 6083129 -  byref escapes (C++ cp) */
+  /* When true, current scope has at least one local __block variable
+     in its scope. This flag is used for compile-time performance. */
+  BOOL_BITFIELD byref_in_current_scope : 1;
+  /* APPLE LOCAL end radar 6083129 -  byref escapes (C++ cp) */
 };
 
 /* The scope currently in effect.  */
@@ -671,6 +688,10 @@
       scope->keep          = keep_next_level_flag;
       scope->outer         = current_scope;
       scope->depth	   = current_scope ? (current_scope->depth + 1) : 0;
+      /* APPLE LOCAL begin radar 6083129 -  byref escapes (C++ cp) */
+      scope->byref_in_current_scope = 
+        current_scope ? current_scope->byref_in_current_scope : false;
+      /* APPLE LOCAL end radar 6083129 -  byref escapes (C++ cp) */
 
       /* Check for scope depth overflow.  Unlikely (2^28 == 268,435,456) but
 	 possible.  */
@@ -695,6 +716,107 @@
     TYPE_CONTEXT (type) = context;
 }
 
+/* APPLE LOCAL begin radar 6083129 -  byref escapes (C++ cp) */
+/* This routine is called at the begining of parsing of a while/for, etc.
+   statement and sets bc_stmt_body in current scope to say that outer scope 
+   is for such a statement. */
+void in_bc_stmt_block (void)
+{
+  gcc_assert (current_scope);
+  ++current_scope->bc_stmt_body;
+}
+
+/*  This routine resets the bc_stmt_body flag before exiting the top-most
+    block of while/for, etc. statement. */
+void outof_bc_stmt_block (void)
+{
+  gcc_assert (current_scope && current_scope->bc_stmt_body > 0);
+  --current_scope->bc_stmt_body;
+}
+
+/* This routine generates calls of _Block_byref_release(VAR_DECL.forwarding);
+   for all byref variables seen in the scope of the return statement.
+*/
+void release_all_local_byrefs_at_return (void)
+{
+  struct c_scope *scope;
+  struct c_binding *b;
+  
+  gcc_assert (current_scope);
+  if (flag_objc_gc_only || !current_scope->byref_in_current_scope)
+    return;
+  
+  scope = current_scope;
+  while (scope && scope != file_scope)
+  {
+    for (b = scope->bindings; b; b = b->prev)
+    {
+      tree p = b->decl;
+      if (p && TREE_CODE (p) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (p))
+	gen_block_byref_release_exp (p);
+    }
+    /* Release up to scope of the block. */
+    if (cur_block && cur_block->the_scope == scope)
+      break;
+    scope = scope->outer;
+  }
+}
+
+/* This routine issues a diagnostic if a __block variable is seen in
+   the current scope.  This is for now called from a goto statement.  */
+void
+diagnose_byref_var_in_current_scope (void)
+{
+  struct c_scope *scope;
+  struct c_binding *b;
+  
+  gcc_assert (current_scope);
+  if (flag_objc_gc_only || !current_scope->byref_in_current_scope)
+    return;
+  
+  scope = current_scope;
+  while (scope && scope != file_scope)
+  {
+    for (b = scope->bindings; b; b = b->prev)
+    {
+      tree p = b->decl;
+      if (p && TREE_CODE (p) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (p)) {
+        error ("local byref variable %s is in the scope of this goto",
+               IDENTIFIER_POINTER (DECL_NAME (p)));
+        return;
+      }
+    }
+    scope = scope->outer;
+  }
+}
+
+/* This routine generates call to _Block_byref_release(VAR_DECL.forwarding);
+   for all __block variables which go out of scope when 'break' is executed.
+*/
+void release_local_byrefs_at_break (void)
+{
+  struct c_scope *scope;
+  struct c_binding *b;
+  
+  gcc_assert (current_scope);
+  if (flag_objc_gc_only || !current_scope->byref_in_current_scope)
+    return;
+  
+  scope = current_scope;
+  while (scope && !scope->bc_stmt_body)
+  {
+    for (b = scope->bindings; b; b = b->prev)
+    {
+      tree p = b->decl;
+      if (p && TREE_CODE (p) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (p))
+	gen_block_byref_release_exp (p);
+    }
+    scope = scope->outer;
+  }
+}
+
+/* APPLE LOCAL end radar 6083129 -  byref escapes (C++ cp) */
+
 /* Exit a scope.  Restore the state of the identifier-decl mappings
    that were in effect when this scope was entered.  Return a BLOCK
    node containing all the DECLs in this scope that are of interest
@@ -825,6 +947,11 @@
 	  goto common_symbol;
 
 	case VAR_DECL:
+         /* APPLE LOCAL begin radar 6083129 -  byref escapes (C++ cp) */
+            if (!flag_objc_gc_only && COPYABLE_BYREF_LOCAL_VAR (p))
+              gen_block_byref_release_exp (p);
+         /* APPLE LOCAL end radar 6083129 -  byref escapes (C++ cp) */
+
 	  /* Warnings for unused variables.  */
 	  if (!TREE_USED (p)
 	      && !TREE_NO_WARNING (p)
@@ -3552,16 +3679,316 @@
     return;
 
   c_eh_initialized_p = true;
-  /* LLVM local begin */
+  /* LLVM LOCAL - begin */
+#ifdef ENABLE_LLVM
   llvm_eh_personality_libfunc
     = llvm_init_one_libfunc (USING_SJLJ_EXCEPTIONS
                              ? "__gcc_personality_sj0"
                              : "__gcc_personality_v0");
-  /* LLVM local end */
+#else
+  eh_personality_libfunc
+    = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+			? "__gcc_personality_sj0"
+			: "__gcc_personality_v0");
+#endif
+  /* LLVM LOCAL - end */
   default_init_unwind_resume_libfunc ();
   using_eh_for_cleanups ();
 }
 
+/* APPLE LOCAL begin radar 5932809 - copyable byref blocks */
+static tree block_byref_id_object_copy;
+static tree block_byref_id_object_dispose;
+
+/* This routine builds:
+   *(id *)(EXP+20) expression which references the object id pointer.
+*/
+static tree
+build_indirect_object_id_exp (tree exp)
+{
+  tree dst_obj;
+  int offset;
+
+  /* dst->object = [src->object retail]; In thid case 'object' is the field
+   of the object passed offset by: void* + int + int + void* + void *
+   This must match definition of Block_byref structs. */
+  offset = GET_MODE_SIZE (Pmode) + sizeof (unsigned_type_node) +
+           sizeof (unsigned_type_node) + GET_MODE_SIZE (Pmode) +
+           GET_MODE_SIZE (Pmode);
+  dst_obj = build2 (PLUS_EXPR, ptr_type_node, exp,
+                    build_int_cst (NULL_TREE, offset));
+  /* Type case to: 'id *' */
+  dst_obj = cast_to_pointer_to_id (dst_obj);
+  dst_obj = build_indirect_ref (dst_obj, "unary *");
+  return dst_obj;
+}
+
+
+/**
+ This routine builds:
+
+ void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
+                                   struct Block_byref_id_object *src) {
+   dst->object = [src->object retain];
+ }
+*/
+static void synth_block_byref_id_object_copy_func (void)
+{
+  tree stmt, fnbody;
+  tree dst_arg, src_arg;
+  tree dst_obj, src_obj, retain_exp, store;
+  struct c_arg_info * arg_info;
+
+  gcc_assert (block_byref_id_object_copy);
+  /* 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, true);
+  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);
+
+  retain_exp = retain_block_component (src_obj);
+
+  /* dst->object = [src->object retain]; */
+  store = build_modify_expr (dst_obj, NOP_EXPR, retain_exp);
+
+  add_stmt (store);
+
+  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) {
+   [_src->object release];
+ }
+*/
+static void synth_block_byref_id_object_dispose_func (void)
+{
+  tree stmt, fnbody;
+  tree src_arg, src_obj, rel_exp;
+  struct c_arg_info * arg_info;
+
+  gcc_assert (block_byref_id_object_dispose);
+  /* 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, true);
+  store_parm_decls_from (arg_info);
+
+  /* Body of the function. */
+  stmt = c_begin_compound_stmt (true);
+  /* [_src->object release]; */
+  src_obj = build_indirect_object_id_exp (src_arg);
+
+  rel_exp = release_block_component (src_obj);
+  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 {
+ 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;
+  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));
+
+  /* struct Block_byref_x *forwarding; */
+  field_decl = build_decl (FIELD_DECL, get_identifier ("forwarding"),
+                           build_pointer_type (Block_byref_type));
+  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 ();
+  finish_struct (Block_byref_type, field_decl_chain, NULL_TREE);
+
+  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:
+   { &x, 0, sizeof(struct __Block_byref_x), initializer-expr};
+
+   or:
+   { &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:
+
+   { &x, 0, sizeof(struct __Block_byref_x), &byref_keep, &byref_destroy,
+     &initializer-expr};
+
+*/
+static tree
+init_byref_decl (tree decl, tree init)
+{
+  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);
+  initlist = tree_cons (fields,
+                        build_unary_op (ADDR_EXPR, decl, 0), 0);
+  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];
+      /* Add &__Block_byref_id_object_copy, &__Block_byref_id_object_dispose
+	 initializers. */
+      if (!block_byref_id_object_copy)
+	{
+	  /* 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)));
+	  strcpy (name, "__Block_byref_id_object_copy");
+	  block_byref_id_object_copy = build_helper_func_decl (get_identifier (name),
+							       func_type);
+	  /* Synthesize function definition. */
+	  synth_block_byref_id_object_copy_func ();
+	}
+      initlist = tree_cons (fields,
+			    build_fold_addr_expr (block_byref_id_object_copy),
+			    initlist);
+      fields = TREE_CHAIN (fields);
+
+      if (!block_byref_id_object_dispose)
+	{
+	  /* 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));
+	  strcpy (name, "__Block_byref_id_object_dispose");
+	  block_byref_id_object_dispose = build_helper_func_decl (get_identifier (name),
+								  func_type);
+	  /* Synthesize function definition. */
+	  synth_block_byref_id_object_dispose_func ();
+	}
+      initlist = tree_cons (fields,
+			    build_fold_addr_expr (block_byref_id_object_dispose),
+			    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 */
+
 /* Finish processing of a declaration;
    install its initial value.
    If the length of an array type is not known before,
@@ -3588,7 +4015,28 @@
   /* Don't crash if parm is initialized.  */
   if (TREE_CODE (decl) == PARM_DECL)
     init = 0;
-
+  /* APPLE LOCAL begin radar 5932809 - copyable byref blocks */
+  /* 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))
+	{
+	  warning (0,
+		   "__block attribute is only allowed on local variables - ignored");
+	  COPYABLE_BYREF_LOCAL_VAR (decl) = 0;
+	  COPYABLE_BYREF_LOCAL_NONPOD (decl) = 0;
+	}
+      else
+	{
+	  decl = new_block_byref_decl (decl);
+	  init = init_byref_decl (decl, init);
+          /* Mark that current scope has a __block local variable. */
+          current_scope->byref_in_current_scope = true;
+	}
+    }
+  /* APPLE LOCAL end radar 5932809 - copyable byref blocks */
+  
   if (init)
     store_init_value (decl, init);
 
@@ -4151,6 +4599,8 @@
 	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;
@@ -4775,6 +5225,29 @@
 	    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 ();
 	}
@@ -7268,7 +7741,10 @@
 {
   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.  */
@@ -7453,6 +7929,489 @@
   return ret;
 }
 
+/* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ ch) */
+/* build_byref_local_var_access - converts EXPR to:
+   EXPR.forwarding-><decl-name>.
+*/
+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)
+{
+  /* 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. */
+  tree ptr_type = (TREE_CODE (decl) == VAR_DECL && BLOCK_DECL_BYREF (decl))
+                   ? TREE_TYPE (decl) : build_pointer_type (TREE_TYPE (decl));
+  tree byref_decl = build_decl (VAR_DECL, name, ptr_type);
+  DECL_CONTEXT (byref_decl) = current_function_decl;
+  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 end radar 5932809 - copyable byref blocks (C++ ch) */
+
+  /* Current scope must be that of the main function body. */
+  gcc_assert (current_scope->function_body);
+  bind (name, byref_decl,
+        current_scope, /*invisible=*/false, /*nested=*/false);
+  cur_block->block_byref_decl_list =
+    tree_cons (NULL_TREE, byref_decl, cur_block->block_byref_decl_list);
+  cur_block->block_original_byref_decl_list =
+    tree_cons (NULL_TREE, exp, cur_block->block_original_byref_decl_list);
+  return byref_decl;
+}
+
+#define BINDING_VALUE(b) ((b)->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 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);
+        gcc_assert (b);
+	gcc_assert (BINDING_VALUE (b));
+	gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+		    || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL);
+	gcc_assert ((b->depth >= cur_block->the_scope->depth)
+		    == (DECL_CONTEXT (BINDING_VALUE (b)) == cur_block->helper_func_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->shadowed;
+	  }
+        
+	gcc_assert (b);
+	gcc_assert (BINDING_VALUE (b));
+	gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL 
+		    || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL);
+	gcc_assert ((b->depth < cb->the_scope->depth)
+		    == (DECL_CONTEXT (BINDING_VALUE (b)) != cb->helper_func_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. */
+	    struct c_scope *save_scope = current_scope;
+	    struct block_sema_info *save_current_block = cur_block;
+	    tree save_current_function_decl = current_function_decl;
+	    current_scope = cb->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_scope = save_scope;
+	    current_function_decl = save_current_function_decl;
+	  }
+        cb = cb->prev_block_info; 
+      }
+    }
+    /* APPLE LOCAL end radar 5988451 (C++ ch) */
+  }
+  /* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ ch) */
+
+  ref_decl = build_decl (VAR_DECL, name,
+                         build_qualified_type (TREE_TYPE (decl),
+                                               TYPE_QUAL_CONST));
+  DECL_CONTEXT (ref_decl) = current_function_decl;
+  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 =
+    tree_cons (NULL_TREE, decl, cur_block->block_original_ref_decl_list);
+  return ref_decl;
+}
+
+/* APPLE LOCAL begin radar 5939894 (C++ ch) */
+/** build_block_internal_types - This routine builds the block type:
+ struct __invoke_impl {
+ void   *isa;
+ int32_t Flags;
+ int32_t Size;
+ void *FuncPtr;
+ } *invoke_impl_ptr_type;
+ */
+void
+build_block_internal_types (void)
+{
+  tree field_decl_chain, field_decl;
+  tree invoke_impl_type;
+
+  /* APPLE LOCAL begin radar 5939894 (C++ ch) */
+  /* If a user-declaration of "struct __invoke_impl" is seen, use it. */
+  invoke_impl_type = lookup_tag (RECORD_TYPE, get_identifier ("__invoke_impl"), 0);
+  if (invoke_impl_type)
+  {
+    invoke_impl_ptr_type = build_pointer_type (invoke_impl_type);
+    return;
+  }
+  /* APPLE LOCAL end radar 5939894 (C++ ch) */
+
+  push_to_top_level ();
+  invoke_impl_type = start_struct (RECORD_TYPE, get_identifier ("__invoke_impl"));
+
+  /* APPLE LOCAL begin radar 5811599 (C++ ch) */
+  /* void *isa; */
+  field_decl = build_decl (FIELD_DECL, get_identifier ("isa"), ptr_type_node);
+  /* APPLE LOCAL end radar 5811599 (C++ ch) */
+  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);
+
+  /* void *FuncPtr; */
+  field_decl = build_decl (FIELD_DECL, get_identifier ("FuncPtr"), ptr_type_node);
+  chainon (field_decl_chain, field_decl);
+
+  /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to Blocks (C++ ch) */
+  /* Mark this struct as being a block struct rather than a 'normal'
+   struct.  */
+  TYPE_BLOCK_IMPL_STRUCT (invoke_impl_type) = 1;
+  /* APPLE LOCAL end  radar 5811943 - Fix type of pointers to Blocks (C++ ch) */
+  finish_struct (invoke_impl_type, field_decl_chain, NULL_TREE);
+  pop_from_top_level ();
+  invoke_impl_ptr_type = build_pointer_type (invoke_impl_type);
+}
+/* APPLE LOCAL end radar 5939894 (C++ ch) */
+
+/* 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);
+
+  /* APPLE LOCAL begin radar 5732232 - blocks (C++ ch) */
+  /* Closure contructs seen -- generate supporting types.  */
+  if (!invoke_impl_ptr_type)
+    build_block_internal_types ();
+  /* APPLE LOCAL end radar 5732232 - blocks (C++ ch) */
+
+  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;
+  push_scope ();
+  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;
+  pop_scope ();
+  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);
+      gcc_assert ((b->depth >= cur_block->the_scope->depth)
+		  == (DECL_CONTEXT (BINDING_VALUE (b)) == current_function_decl));
+      if (DECL_CONTEXT (BINDING_VALUE (b)) == current_function_decl)
+	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 && BINDING_VALUE (b) 
+	     && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL)
+             && BLOCK_DECL_BYREF (BINDING_VALUE (b)))
+        b = b->shadowed;
+	/* APPLE LOCAL end radar 5988451 (C++ ch) */
+      if (b && BINDING_VALUE (b))
+	*decl = BINDING_VALUE (b);
+    }
+  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;
+  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, bool add_result_decl)
+{
+  struct c_label_context_se *nstack_se;
+  struct c_label_context_vm *nstack_vm;
+
+  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);
+
+  /* APPLE LOCAL begin optimization pragmas 3124235/3420242 (C++ ch) */
+  /* Build a mapping between this decl and the per-function options in
+   effect at this point.  */
+
+  record_func_cl_pf_opts_mapping (current_function_decl);
+  /* APPLE LOCAL end optimization pragmas 3124235/3420242 (C++ ch) */
+
+  push_scope ();
+  declare_parm_level ();
+
+  if (add_result_decl)
+  {
+    tree restype = TREE_TYPE (TREE_TYPE (current_function_decl));
+    tree 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));
+  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 = _self->y;
+ int x = _self->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 ("_self"));
+  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.  */
 

Modified: llvm-gcc-4.2/trunk/gcc/c-parser.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/c-parser.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/c-parser.c (original)
+++ llvm-gcc-4.2/trunk/gcc/c-parser.c Tue Jul 29 23:41:34 2008
@@ -1131,6 +1131,10 @@
 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 *);
+static bool c_parser_block_byref_declarations (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 *);
@@ -2515,6 +2519,20 @@
       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);
@@ -3622,6 +3640,8 @@
 {
   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);
@@ -3736,6 +3756,14 @@
 	  else
 	    goto statement;
 	}
+      /* APPLE LOCAL begin radar 5732232 - blocks (not in C++) */
+      else if (flag_blocks && first_stmt &&
+               c_parser_next_token_is (parser, CPP_OR) &&
+	       c_parser_block_byref_declarations (parser))
+        {
+          ;
+        }
+      /* APPLE LOCAL end radar 5732232 - blocks (not in C++) */
       else if (c_parser_next_token_is (parser, CPP_PRAGMA))
 	{
 	  /* External pragmas, and some omp pragmas, are not associated
@@ -3767,6 +3795,8 @@
       if (flag_iasm_blocks) iasm_in_decl = false;      
       /* APPLE LOCAL end CW asm blocks (in 4.2 al) */
       parser->error = false;
+      /* APPLE LOCAL radar 5732232 - blocks (not in C++) */
+      first_stmt = false;
     }
   /* APPLE LOCAL begin CW asm blocks (in 4.2 am) */
   if (flag_iasm_blocks)
@@ -3986,6 +4016,10 @@
 	  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))
 	    {
@@ -4517,18 +4551,18 @@
 	{
 	  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
 	  c_parser_error (parser, "asm blocks not enabled, use `-fasm-blocks'");
- 	  iasm_state = iasm_none;
+	  iasm_state = iasm_none;
 	}
       return NULL_TREE;
     }
   if (quals == NULL_TREE
       && (c_parser_next_token_is (parser, CPP_DOT)
- 	  || c_parser_next_token_is (parser, CPP_ATSIGN)
- 	  || c_parser_next_token_is (parser, CPP_NAME)
- 	  || c_parser_next_token_is_keyword (parser, RID_ASM)
- 	  || c_parser_next_token_is (parser, CPP_SEMICOLON)
- 	  || (c_parser_iasm_bol (parser)
- 	      && ! c_parser_next_token_is (parser, CPP_OPEN_PAREN))))
+	  || c_parser_next_token_is (parser, CPP_ATSIGN)
+	  || c_parser_next_token_is (parser, CPP_NAME)
+	  || c_parser_next_token_is_keyword (parser, RID_ASM)
+	  || c_parser_next_token_is (parser, CPP_SEMICOLON)
+	  || (c_parser_iasm_bol (parser)
+	      && ! c_parser_next_token_is (parser, CPP_OPEN_PAREN))))
     {
       if (flag_iasm_blocks)
 	c_parser_iasm_top_statement (parser);
@@ -5529,6 +5563,35 @@
 	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
+            && !building_block_byref_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;
@@ -5864,6 +5927,18 @@
 	  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:
       /* APPLE LOCAL begin CW asm blocks */
       if (inside_iasm_block)
@@ -9294,5 +9369,798 @@
   c_parser_iasm_maybe_skip_comments (parser);
 }
 /* APPLE LOCAL end CW asm blocks */
+/* APPLE LOCAL begin radar 5732232 - blocks (C++ ce) */
+static tree block_copy_assign_decl;
+static tree block_destroy_decl;
+/* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ ce) */
+static tree block_byref_assign_copy_decl;
+/* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ ce) */
+
+/* APPLE LOCAL begin radar 6083129 - byref escapes (C++ ce) */
+void
+gen_block_byref_release_exp (tree var_decl)
+{
+  tree cleanup = build_block_byref_release_exp (var_decl);
+  if (cleanup)
+    add_stmt (cleanup);
+}
+/* APPLE LOCAL end radar 6083129 - byref escapes (C++ ce) */
+
+bool building_block_byref_decl = false;
+static bool
+c_parser_block_byref_declarations (c_parser* parser)
+{
+  if (!in_imm_block ())
+    return false;
+  warning (0, "| x | has been deprecated in blocks");
+  do {
+    struct c_expr byref_decl_expr;
+    c_parser_consume_token (parser); /* consume '|' or ',' */
+    if (!c_parser_next_token_is (parser, CPP_NAME))
+      {
+	error ("expected identifier in block by-reference variable list");
+	return false;
+      }
+    building_block_byref_decl = true;
+    byref_decl_expr = c_parser_cast_expression (parser, NULL);
+    building_block_byref_decl = false;
+    if (byref_decl_expr.value != error_mark_node &&
+        !(TREE_CODE (byref_decl_expr.value) == VAR_DECL &&
+          /* APPLE LOCAL begin radar 5803600 (C++ ce) */
+          (BLOCK_DECL_BYREF (byref_decl_expr.value) ||
+           in_block_global_byref_list (byref_decl_expr.value))))
+          /* APPLE LOCAL end radar 5803600 (C++ ce) */
+      error (
+        "only a visible variable may be used in a block byref declaration");
+  } while (c_parser_next_token_is (parser, CPP_COMMA));
+
+  if (!c_parser_next_token_is (parser, CPP_OR))
+    {
+      error ("expected identifier or '|' at end of block by-reference variable list");
+      return false;
+    }
+  c_parser_consume_token (parser); /* consume '|' */
+  return true;
+}
+
+/** build_block_struct_type -
+ struct block_1 {
+ struct invok_impl impl;
+ void *CopyFuncPtr;   // only if BLOCK_HAS_COPY_DISPOSE is set
+ void *DestroyFuncPtr;  // only if BLOCK_HAS_COPY_DISPOSE is set
+ 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;
+  /* build struct invok_impl */
+  if (!invoke_impl_ptr_type)
+    build_block_internal_types ();
+
+  /* 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;
+    }
+
+  /* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ ce) */
+  /* 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;
+	block_impl->BlockHasByrefVar = TRUE;
+	break;
+      }
+  /* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ ce) */
+
+  sprintf(buffer, "__block_%d", ++unique_count);
+  push_to_top_level ();
+  block_struct_type = start_struct (RECORD_TYPE, get_identifier (buffer));
+  /* struct invok_impl impl; */
+  field_decl = build_decl (FIELD_DECL, get_identifier ("impl"),
+                           TREE_TYPE (invoke_impl_ptr_type));
+  field_decl_chain = field_decl;
+  /* APPLE LOCAL radar 5932809 - copyable byref blocks (C++ ce) */
+  if (block_impl->BlockHasCopyDispose)
+  {
+    /* 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);
+    /* APPLE LOCAL begin radar 5988451 (C++ ce) */
+    /* 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;
+    /* APPLE LOCAL end radar 5988451 (C++ ce) */
+  }
+
+  /* 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_block_struct_initlist - builds the initializer list:
+ { &_NSConcreteStackBlock // isa,
+ BLOCK_NO_COPY | BLOCK_HAS_COPY_DISPOSE // flags,
+ sizeof(struct block_1),
+ helper_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
+ }
+*/
+static tree
+build_block_struct_initlist (tree block_struct_type,
+			     struct block_sema_info *block_impl)
+{
+  tree initlist;
+  int size;
+  tree helper_addr, chain, fields;
+  unsigned flags = 0;
+  /* APPLE LOCAL radar 5811599 (C++ ce) */
+  static tree NSConcreteStackBlock_decl = NULL_TREE;
+
+  /* APPLE LOCAL radar 5932809 - copyable byref blocks (C++ ce) */
+  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;
+  /* Set BLOCK_NO_COPY flag only if we are using the old byref,
+     indirect reference byref variables. */
+  if (block_impl->block_byref_decl_list && !block_impl->BlockHasByrefVar)
+    flags |= BLOCK_NO_COPY;
+
+  fields = TYPE_FIELDS (TREE_TYPE (invoke_impl_ptr_type));
+
+  /* APPLE LOCAL begin radar 5811599 (C++ ce) */
+  /* 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);
+	}
+    }
+  initlist = build_tree_list (fields,
+			      build_fold_addr_expr (NSConcreteStackBlock_decl));
+  /* APPLE LOCAL end radar 5811599 (C++ ce) */
+  fields = TREE_CHAIN (fields);
+
+  initlist = tree_cons (fields,
+                        build_int_cst (unsigned_type_node, flags),
+                        initlist);
+  fields = TREE_CHAIN (fields);
+  size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (block_struct_type));
+  initlist = tree_cons (fields,
+                        build_int_cst (unsigned_type_node, size),
+                        initlist);
+  fields = TREE_CHAIN (fields);
+  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);
+  gcc_assert (invoke_impl_ptr_type);
+  initlist = build_constructor_from_list (TREE_TYPE (invoke_impl_ptr_type),
+                                          nreverse (initlist));
+  fields = TYPE_FIELDS (block_struct_type);
+  initlist = build_tree_list (fields, initlist);
+  /* APPLE LOCAL radar 5932809 - copyable byref blocks (C++ ce) */
+  if (block_impl->BlockHasCopyDispose)
+    {
+      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);
+      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);
+    }
+  for (chain = block_impl->block_original_ref_decl_list; chain;
+       chain = TREE_CHAIN (chain))
+    {
+      /* APPLE LOCAL begin radar 5834569 (C++ ce) */
+      tree y = TREE_VALUE (chain);
+      TREE_USED (y) = 1;
+      fields = TREE_CHAIN (fields);
+      initlist = tree_cons (fields, copy_in_object (y), initlist);
+      /* APPLE LOCAL end radar 5834569 (C++ ce) */
+    }
+  for (chain = block_impl->block_original_byref_decl_list; chain;
+       chain = TREE_CHAIN (chain))
+    {
+      tree y = TREE_VALUE (chain);
+      /* APPLE LOCAL radar 5834569 (C++ ce) */
+      TREE_USED (y) = 1;
+      fields = TREE_CHAIN (fields);
+      y = build_fold_addr_expr (y);
+      initlist = tree_cons (fields, y, initlist);
+    }
+  return initlist;
+}
+
+/**
+ build_block_literal_tmp - This routine:
+
+ 1) builds block type:
+ struct block_1 {
+ struct invok_impl impl;
+ void *CopyFuncPtr;    // only if block BLOCK_HAS_COPY_DISPOSE
+ void *DestroyFuncPtr; // only if block BLOCK_HAS_COPY_DISPOSE
+ 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 // isa,
+   BLOCK_NO_COPY | BLOCK_HAS_COPY_DISPOSE // flags,
+   sizeof(struct block_1),
+   helper_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.
+*/
+
+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);
+
+
+  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) = current_function_decl;
+  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);
+  return block_holder_tmp_decl;
+}
+
+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);
+  DECL_CONTEXT (dst_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, true);
+  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)))
+    {
+      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)
+      {
+        tree func_params, call_exp;
+        /* _Block_copy_assign(&_dest->myImportedBlock, _src->myImportedClosure) */
+        /* Build a: void _Block_copy_assign (void *, void *) if not done
+           already. */
+        if (!block_copy_assign_decl)
+        {
+          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)));
+
+          block_copy_assign_decl = builtin_function ("_Block_copy_assign", func_type,
+						     0, NOT_BUILT_IN, 0, NULL_TREE);
+          TREE_NOTHROW (block_copy_assign_decl) = 0;
+        }
+        dst_block_component = build_fold_addr_expr (dst_block_component);
+        func_params = tree_cons (NULL_TREE, dst_block_component,
+                                 tree_cons (NULL_TREE, src_block_component,
+                                            NULL_TREE));
+        call_exp = build_function_call (block_copy_assign_decl, func_params);
+        add_stmt (call_exp);
+      }
+      else
+      {
+        /* _dest-> imported_object_x = [_src->imported_object_x retain] */
+        tree rhs, store;
+        /* [_src->imported_object_x retain] */
+        rhs = retain_block_component (src_block_component);
+        store = build_modify_expr (dst_block_component, NOP_EXPR, rhs);
+        add_stmt (store);
+      }
+    }
+
+  /* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ ce) */
+  /* For each __block declared variable used in |...| Must generate call to:
+     _Block_byref_assign_copy(&_dest->myImportedBlock, _src->myImportedBlock)
+  */
+  for (chain = block_impl->block_byref_decl_list; chain;
+         chain = TREE_CHAIN (chain))
+    if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain)))
+      {
+	tree func_params, 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_byref_assign_copy(&_dest->myImportedClosure, _src->myImportedClosure) */
+	/* Build a: void _Block_byref_assign_copy (void *, void *) if
+	   not done already. */
+	if (!block_byref_assign_copy_decl
+	    && !(block_byref_assign_copy_decl
+		 = lookup_name (get_identifier ("_Block_byref_assign_copy"))))
+	  {
+	    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)));
+
+	    block_byref_assign_copy_decl
+	      = builtin_function ("_Block_byref_assign_copy", func_type,
+				  0, NOT_BUILT_IN, 0, NULL_TREE);
+	    TREE_NOTHROW (block_byref_assign_copy_decl) = 0;
+	  }
+	dst_block_component = build_fold_addr_expr (dst_block_component);
+	func_params = tree_cons (NULL_TREE, dst_block_component,
+				 tree_cons (NULL_TREE, src_block_component,
+					    NULL_TREE));
+	call_exp = build_function_call (block_byref_assign_copy_decl, func_params);
+	add_stmt (call_exp);
+      }
+  /* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ ce) */
+
+  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, true);
+  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)))
+    {
+      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)
+      {
+        tree func_params, call_exp;
+        /* _Block_destroy(_src->myImportedClosure); */
+        /* _Block_destroy (void *); */
+        /* Build a: void _Block_destroy (void *) if not done already. */
+	/* APPLE LOCAL begin radar 5992047 (C++ ce) */
+        if (!block_destroy_decl &&
+	    !(block_destroy_decl = lookup_name (get_identifier ("_Block_destroy"))))
+	/* APPLE LOCAL end radar 5992047 (C++ ce) */
+        {
+          tree func_type =
+          build_function_type (void_type_node,
+                               tree_cons (NULL_TREE, ptr_type_node, void_list_node));
+
+          block_destroy_decl = builtin_function ("_Block_destroy", func_type,
+						 0, NOT_BUILT_IN, 0, NULL_TREE);
+          TREE_NOTHROW (block_destroy_decl) = 0;
+        }
+        func_params = tree_cons (NULL_TREE, src_block_component, NULL_TREE);
+        call_exp = build_function_call (block_destroy_decl, func_params);
+        add_stmt (call_exp);
+      }
+      else
+      {
+        tree rel_exp;
+        /* [_src->imported_object_0 release]; */
+        rel_exp = release_block_component (src_block_component);
+        add_stmt (rel_exp);
+      }
+    }
+
+  /* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ ce) */
+  /* For each __block declared variable used in |...| Must generate call to:
+   _Block_byref_release(_src->myImportedClosure)
+   */
+  for (chain = block_impl->block_byref_decl_list; chain;
+       chain = TREE_CHAIN (chain))
+    if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain)))
+      {
+	tree func_params, call_exp;
+	tree p = TREE_VALUE (chain);
+	tree src_block_component;
+
+	src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"),
+						   DECL_NAME (p));
+      /* _Block_byref_release(_src->myImportedClosure) */
+      /* Build a: void _Block_byref_release (void *) if not done
+	 already. */
+      func_params = tree_cons (NULL_TREE, src_block_component, NULL_TREE);
+      call_exp = build_function_call (build_block_byref_release_decl (), func_params);
+      add_stmt (call_exp);
+    }
+  /* APPLE LOCAL end radar 5932809 - copyable byref blocks (C++ ce) */
+
+  fnbody = c_end_compound_stmt (stmt, true);
+  add_stmt (fnbody);
+  finish_function ();
+  pop_function_context ();
+  free (arg_info);
+}
+
+/** c_parser_block_literal_expr - Main routine to process a block literal
+    with the syntax of ^arg-list[OPT] block or ^()expression. 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, 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, resdecl;
+  tree fnbody, typelist;
+  tree helper_function_type;
+  /* APPLE LOCAL radar 5824092 (C++ ce) */
+  bool at_file_scope = global_bindings_p ();
+  tree block;
+
+  c_parser_consume_token (parser); /* eat '^' */
+
+  /* Parse the optional argument list */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      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
+    arglist = build_tree_list (NULL_TREE, void_type_node);
+
+  block = begin_block ();
+
+  cur_block->arg_info = NULL;
+  cur_block->return_type = NULL_TREE;
+
+  if (args)
+    {
+      tree list = NULL_TREE;
+      cur_block->arg_info = args;
+      if (arg_type)
+	{
+	  cur_block->hasPrototype = true;
+	  /* This is the only way in gcc to know if argument list ends with ... */
+	  for (list = arg_type; TREE_CHAIN (list); list = TREE_CHAIN (list))
+	    ;
+	  cur_block->isVariadic = (list != void_list_node);
+	}
+      else
+	{
+	  /* K&R syle () argument list. */
+	  cur_block->hasPrototype = false;
+	  cur_block->isVariadic = true;
+	}
+    }
+  else
+    {
+      cur_block->hasPrototype = false;
+      cur_block->isVariadic = false;
+      cur_block->arg_info = xcalloc (1, sizeof (struct c_arg_info));
+    }
+
+  /* Must also build hidden parameter _self added to the helper
+   function, even though we do not know its type yet. */
+  self_arg = build_decl (PARM_DECL, get_identifier ("_self"),
+                         ptr_type_node);
+  /* APPLE LOCAL radar 5925784 (C++ ce) */
+  TREE_USED (self_arg) = 1;  /* Prevent unused parameter '_self' 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;
+
+  /* Build the declaration of the helper function (we do not know its result
+     type yet, so assume it is 'void'). Treat this as a nested function and use
+     nested function infrastructure for its generation. */
+  sprintf (name, "__helper_%d", unique_count);
+
+  ftype = build_function_type (void_type_node, cur_block->arg_info->types);
+  block_helper_function_decl = build_helper_func_decl (get_identifier (name),
+                                                         ftype);
+  DECL_CONTEXT (block_helper_function_decl) = current_function_decl;
+  BLOCK_HELPER_FUNC (block_helper_function_decl) = 1;
+  cur_block->helper_func_decl = block_helper_function_decl;
+
+  push_function_context ();
+  start_block_helper_function (cur_block->helper_func_decl, false);
+  /* APPLE LOCAL begin radar 5988451 (C++ ce) */
+  /* 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 ();
+  /* APPLE LOCAL end radar 5988451 (C++ ce) */
+
+  /* Enter parameter list to the scope of the helper function. */
+  store_parm_decls_from (cur_block->arg_info);
+
+  /* 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);
+    /* APPLE LOCAL radar 6034839 */
+    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 {
+      add_stmt (body);
+      cur_block->return_type = TREE_TYPE (body);
+    }
+  }
+
+  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;
+  /* APPLE LOCAL begin radar 5824092 (C++ ce) */
+  if (at_file_scope)
+  {
+    error ("block literal cannot be declared at global scope");
+    return clean_and_exit (block);
+  }
+  /* APPLE LOCAL end radar 5824092 (C++ ce) */
+  if (restype == error_mark_node)
+    return clean_and_exit (block);
+
+  /* Now that we know type of the hidden _self 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;
+
+  /* Now that we know helper's result type, fix its result variable decl. */
+  resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
+  DECL_ARTIFICIAL (resdecl) = 1;
+  DECL_IGNORED_P (resdecl) = 1;
+  DECL_RESULT (current_function_decl) = resdecl;
+
+  cur_block->block_body = stmt;
+  block_build_prologue (cur_block);
+
+  fnbody = c_end_compound_stmt (stmt, true);
+  add_stmt (fnbody);
+  finish_function ();
+  pop_function_context ();
+
+  /* Build the declaration for copy_helper_block and destroy_helper_block
+   helper functions for later use. */
+
+  /* APPLE LOCAL radar 5932809 - copyable byref blocks (C++ ce) */
+  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);
+  }
+
+
+  /* We are out of helper function scope and back in its enclosing scope.
+     We also know all we need to know about the helper function. So, fix its
+     type here. */
+  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;
+
+  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"

Modified: llvm-gcc-4.2/trunk/gcc/c-typeck.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/c-typeck.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/c-typeck.c (original)
+++ llvm-gcc-4.2/trunk/gcc/c-typeck.c Tue Jul 29 23:41:34 2008
@@ -75,6 +75,13 @@
 static int require_constant_value;
 static int require_constant_elements;
 
+/* APPLE LOCAL begin radar 5732232 - blocks */
+/* APPLE LOCAL begin radar 5811943 - Fix type of pointers to Blocks  */
+/* Move declaration of invoke_impl_ptr_type to c-common.c  */
+/* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks  */
+static bool types_are_block_compatible (tree lhptee, tree rhptee);
+static tree build_block_call (tree, tree, tree);
+/* APPLE LOCAL end radar 5732232 - blocks */
 static bool null_pointer_constant_p (tree);
 static tree qualify_type (tree, tree);
 static int tagged_types_tu_compatible_p (tree, tree);
@@ -2136,9 +2143,54 @@
   /* 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 && 
+		   (DECL_EXTERNAL (decl)
+		    || (TREE_STATIC (decl) && !DECL_CONTEXT (decl))));
+	  /* Treat all 'global' variables as 'byref' by default. */
+          /* APPLE LOCAL begin radar 6014138 */
+	  if (building_block_byref_decl || gdecl 
+              || (TREE_CODE (decl) == VAR_DECL 
+                  && COPYABLE_BYREF_LOCAL_VAR (decl)))
+          /* APPLE LOCAL end radar 6014138 */
+	    {
+	      /* APPLE LOCAL begin radar 5803600 (C++ ci) */
+	      /* byref globals are directly accessed. */
+	      if (!gdecl)
+		/* build a decl for the byref variable. */
+		decl = build_block_byref_decl (id, decl, decl);
+	      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))
+		/* 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);
@@ -2366,8 +2418,10 @@
 
   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);
@@ -2434,6 +2488,11 @@
   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),
@@ -2505,6 +2564,13 @@
 
       if (type == void_type_node)
 	{
+          /* 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);
@@ -2691,7 +2757,12 @@
 
   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;
     }
 
@@ -2868,12 +2939,14 @@
       if ((code1 == STRING_CST && !integer_zerop (arg2.value))
 	  || (code2 == STRING_CST && !integer_zerop (arg1.value)))
 	warning (OPT_Waddress, 
-                 "comparison with string literal results in unspecified behaviour");
+		 /* APPLE LOCAL mainline 5808469 */
+                 "comparison with string literal results in unspecified behavior");
     }
   else if (TREE_CODE_CLASS (code) == tcc_comparison
 	   && (code1 == STRING_CST || code2 == STRING_CST))
     warning (OPT_Waddress, 
-             "comparison with string literal results in unspecified behaviour");
+	     /* APPLE LOCAL mainline 5808469 */
+             "comparison with string literal results in unspecified behavior");
 
   overflow_warning (result.value);
 
@@ -3069,6 +3142,8 @@
 
     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)
 	{
@@ -3600,7 +3675,31 @@
 	}
       result_type = type2;
     }
-
+  /* APPLE LOCAL begin radar 5732232 - blocks (C++ co) */
+  /* APPLE LOCAL radar 5957801 */
+  else if (code1 == BLOCK_POINTER_TYPE && (code2 == INTEGER_TYPE || code2 == POINTER_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 || code1 == POINTER_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)
@@ -3755,6 +3854,12 @@
 
       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
@@ -3892,6 +3997,88 @@
   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);
+  while (arg1 && arg2)
+    {
+      tree a1, a2;
+      a1 = TREE_VALUE (arg1);
+      a2 = TREE_VALUE (arg2);
+      if (TREE_CODE (a1) == BLOCK_POINTER_TYPE
+	  && TREE_CODE (a2) == BLOCK_POINTER_TYPE)
+	{
+	  a1 = TREE_TYPE (a1);
+	  a2 = TREE_TYPE (a2);
+	}
+      if (!types_are_block_compatible (a1, a2))
+	return false;
+      arg1 = TREE_CHAIN (arg1);
+      arg2 = TREE_CHAIN (arg2);
+    }
+  return !arg1 && !arg2;
+}
+
+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 */
+  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 */
+  /* APPLE LOCAL begin radar 5988995 */
+  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 */
+  return false;
+}
+
+/**
+ build_block_call - Routine to build a block call; as in:
+  ((double(*)(struct invok_impl *, int))(BLOCK_PTR_VAR->FuncPtr))(I, 42);
+ FNTYPE is the original function type derived from the syntax.
+ FUNCTION is the4 block pointer variable.
+ PARAMS is the parameter list.
+*/
+static tree
+build_block_call (tree fntype, tree function, tree params)
+{
+  tree block_ptr_exp;
+  tree function_ptr_exp;
+  tree typelist;
+
+  /* (struct invok_impl *)BLOCK_PTR_VAR */
+  /* First convert it to 'void *'. */
+  block_ptr_exp = convert (ptr_type_node, function);
+  gcc_assert (invoke_impl_ptr_type);
+  block_ptr_exp = convert (invoke_impl_ptr_type, block_ptr_exp);
+  params = tree_cons (NULL_TREE, block_ptr_exp, params);
+  /* BLOCK_PTR_VAR->FuncPtr */
+  function_ptr_exp =
+    build_component_ref (build_indirect_ref (block_ptr_exp, "->"),
+                         get_identifier ("FuncPtr"));
+
+  /* Build: result_type(*)(struct invok_impl *, function-arg-type-list) */
+  typelist = TYPE_ARG_TYPES (fntype);
+  typelist = tree_cons (NULL_TREE, invoke_impl_ptr_type, typelist);
+  fntype = build_function_type (TREE_TYPE (fntype), typelist);
+  function_ptr_exp = convert (build_pointer_type (fntype), function_ptr_exp);
+  return fold_build3 (CALL_EXPR, TREE_TYPE (fntype),
+                      function_ptr_exp, params, NULL_TREE);
+}
+/* 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)
@@ -4494,6 +4681,43 @@
 
       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 "
@@ -4828,6 +5052,13 @@
     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.
 
@@ -5095,6 +5326,8 @@
   /* 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)
     {
@@ -7275,7 +7508,8 @@
       nlist->label = decl;
       label_context_stack_vm->labels_used = nlist;
     }
-
+  /* APPLE LOCAL radar 6083129 - byref escapes (C++ cp) */
+  diagnose_byref_var_in_current_scope ();
   TREE_USED (decl) = 1;
   return add_stmt (build1 (GOTO_EXPR, void_type_node, decl));
 }
@@ -7421,16 +7655,77 @@
   return error_mark_node;
 }
 /* APPLE LOCAL end CW asm blocks */
-
+/* 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)
+    {
+      if (retval)
+	cur_block->return_type = TYPE_MAIN_VARIANT (TREE_TYPE (retval));
+      else
+	cur_block->return_type = void_type_node;
+      return retval;
+    }
+
+  /* Otherwise, 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 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 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;
-
+  
+  if (cur_block) {
+    /* APPLE LOCAL radar 6083129 - byref escapes (C++ cp) */
+    release_all_local_byrefs_at_return ();
+    retval = c_finish_block_return_stmt (retval);
+    ret_stmt = build_stmt (RETURN_EXPR, retval);
+    return add_stmt (ret_stmt);
+  }
+  
+  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 %<noreturn%> has a %<return%> statement");
 
@@ -7515,7 +7810,15 @@
 		  && !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:
@@ -7527,7 +7830,14 @@
 
       retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
     }
-
+  /* APPLE LOCAL begin radar 5732232 - blocks */
+  /* When this routine is called for the helper function, during gimplification,
+     we are only interested in the actual return expression. */
+  if (current_function_decl && BLOCK_HELPER_FUNC (current_function_decl))
+    return retval;
+  /* APPLE LOCAL end radar 5732232 - blocks */
+  /* APPLE LOCAL radar 6083129 - byref escapes (C++ cp) */
+  release_all_local_byrefs_at_return ();
   ret_stmt = build_stmt (RETURN_EXPR, retval);
   TREE_NO_WARNING (ret_stmt) |= no_warning;
   return add_stmt (ret_stmt);
@@ -7873,6 +8183,11 @@
 
   if (skip)
     return NULL_TREE;
+  /* APPLE LOCAL begin radar 6083129 - byref escapes (C++ cp) */
+  /* Before breaking out or on continue, release all local __block
+     variables which go out of scope. */
+  release_local_byrefs_at_break ();
+  /* APPLE LOCAL end radar 6083129 - byref escapes  (C++ cp) */
 
   return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
 }
@@ -8581,6 +8896,32 @@
 	  result_type = type1;
 	  pedwarn ("comparison between pointer and integer");
 	}
+      /* APPLE LOCAL begin radar 5732232 - blocks (C++ cl) */
+      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;
+      else if (code0 == BLOCK_POINTER_TYPE && code1 == BLOCK_POINTER_TYPE)
+	{
+	  if (!types_are_block_compatible (TREE_TYPE(type0), TREE_TYPE(type1)))
+	    error ("comparison of distinct block types (%qT and %qT)",
+		   type0, type1);
+	  result_type = type0;
+	}
+      else if (code0 == BLOCK_POINTER_TYPE && code1 == INTEGER_TYPE)
+	{
+	  result_type = type0;
+	  error ("comparison between pointer and integer (%qT and %qT)",
+		 type0, type1);
+	}
+      else if (code0 == INTEGER_TYPE && code1 == BLOCK_POINTER_TYPE)
+	{
+	  result_type = type1;
+	  error ("comparison between integer and pointer (%qT and %qT)",
+		 type0, type1);
+	}
+      /* APPLE LOCAL end radar 5732232 - blocks (C++ cl) */
       break;
 
     case LE_EXPR:

Modified: llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.c (original)
+++ llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.c Tue Jul 29 23:41:34 2008
@@ -152,7 +152,9 @@
 /* Target cpu type */
 
 /* LLVM LOCAL begin */
+#ifdef ENABLE_LLVM
 const char *rs6000_cpu_target = "ppc";
+#endif
 /* LLVM LOCAL end */
 
 enum processor_type rs6000_cpu;
@@ -164,6 +166,10 @@
   { (const char *)0,	"-mtune=",		1,	0 },
 };
 
+/* APPLE LOCAL begin 5774356 */
+static int debug_sp_offset = 0;
+static int debug_vrsave_offset = 0;
+/* APPLE LOCAL end 5774356 */
 /* Always emit branch hint bits.  */
 static GTY(()) bool rs6000_always_hint;
 
@@ -703,7 +709,6 @@
 static int redefine_groups (FILE *, int, rtx, rtx);
 static int pad_groups (FILE *, int, rtx, rtx);
 static void rs6000_sched_finish (FILE *, int);
-
 static int rs6000_use_sched_lookahead (void);
 /* LLVM LOCAL - Disable scheduler. */
 #endif
@@ -977,6 +982,7 @@
 #define TARGET_SCHED_IS_COSTLY_DEPENDENCE rs6000_is_costly_dependence
 #undef TARGET_SCHED_FINISH
 #define TARGET_SCHED_FINISH rs6000_sched_finish
+
 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD rs6000_use_sched_lookahead
 /* LLVM LOCAL - Disable scheduler. */
@@ -1440,7 +1446,9 @@
   rs6000_cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT;
 
   /* LLVM LOCAL begin */
+#ifdef ENABLE_LLVM
   rs6000_cpu_target = TARGET_POWERPC64 ? "ppc64" : "ppc";
+#endif
   /* LLVM LOCAL end */
 
   /* APPLE LOCAL begin -fast or -fastf or -fastcp */
@@ -1471,12 +1479,13 @@
 		    target_flags &= ~set_masks;
 		    target_flags |= (processor_target_table[j].target_enable
 				     & set_masks);
-		    /* APPLE LOCAL begin -fast */
+		    /* APPLE LOCAL begin -fast or -fastf or -fastcp */
 		    mcpu_cpu = processor_target_table[j].processor;
-		    /* APPLE LOCAL end -fast */
-        
+		    /* APPLE LOCAL end -fast or -fastf or -fastcp */
 		    /* LLVM LOCAL begin */
-        rs6000_cpu_target = processor_target_table[j].name;
+#ifdef ENABLE_LLVM
+                    rs6000_cpu_target = processor_target_table[j].name;
+#endif
 		    /* LLVM LOCAL end */
 		  }
 		break;
@@ -1507,11 +1516,10 @@
 	{
 	  flag_disable_opts_for_faltivec = 1;
 	  /* APPLE LOCAL radar 4161346 */
-/* LLVM LOCAL begin handle -mpim-altivec correctly */
 	  target_flags |= MASK_ALTIVEC;
 	}
+      /* APPLE LOCAL radar 5822514 */
       target_flags |= MASK_PIM_ALTIVEC;
-/* LLVM LOCAL begin handle -mpim-altivec correctly */
     }
   /* APPLE LOCAL end AltiVec */
 
@@ -4899,6 +4907,7 @@
 rs6000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
 {
   /* LLVM LOCAL begin struct return check */
+#ifdef ENABLE_LLVM
   /* FIXME darwin ppc64 often returns structs partly in memory and partly
      in regs.  The binary interface of return_in_memory (which does the
      work for aggregate_value_p) is not a good match for this; in fact
@@ -4910,6 +4919,7 @@
       TREE_CODE(TYPE_SIZE_UNIT(type)) == INTEGER_CST &&
       TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) > 8)
     return true;
+#endif
   /* LLVM LOCAL end struct return check */  
 
   /* In the darwin64 abi, try to use registers for larger structs
@@ -9340,7 +9350,11 @@
     if (d->code == fcode)
       return rs6000_expand_ternop_builtin (d->icode, arglist, target);
 
-  gcc_unreachable ();
+  /* APPLE LOCAL begin 5774356 */
+  /* It looks like a builtin call, but there is something wrong;
+     maybe the wrong number of arguments.  Return failure.  */
+  return NULL_RTX;
+  /* APPLE LOCAL end 5774356 */
 }
 
 static tree
@@ -9409,7 +9423,6 @@
   bool_V4SI_type_node = build_vector_type (bool_int_type_node, 4);
   pixel_V8HI_type_node = build_vector_type (pixel_type_node, 8);
 
-
   /* APPLE LOCAL begin LLVM */
 #ifdef ENABLE_LLVM
   /* LLVM doesn't initialize the RTL backend, so build_vector_type will assign
@@ -17183,6 +17196,10 @@
         {
           /* Save VRSAVE.  */
           offset = info->vrsave_save_offset + sp_offset;
+	  /* APPLE LOCAL begin 5774356 */
+	  debug_vrsave_offset = offset;
+	  debug_sp_offset = sp_offset;
+	  /* APPLE LOCAL end 5774356 */
           mem = gen_frame_mem (SImode,
                                gen_rtx_PLUS (Pmode, frame_reg_rtx,
                                              GEN_INT (offset)));
@@ -17486,7 +17503,10 @@
 
   /* APPLE LOCAL begin mainline */
   /* Set sp_offset based on the stack push from the prologue.  */
-  if ((DEFAULT_ABI == ABI_V4 || current_function_calls_eh_return)
+  /* APPLE LOCAL begin 5774356 */
+  if (info->push_p
+      && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN || current_function_calls_eh_return)
+      /* APPLE LOCAL end 5664356 */
       && info->total_size < 32767)
 	sp_offset = info->total_size;
 
@@ -17520,6 +17540,10 @@
     {
       rtx addr, mem, reg;
 
+      /* APPLE LOCAL begin 5774356 */
+      gcc_assert (debug_sp_offset == sp_offset);
+      gcc_assert (debug_vrsave_offset == (info->vrsave_save_offset + sp_offset));
+      /* APPLE LOCAL end 5774356 */
       addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
 			   GEN_INT (info->vrsave_save_offset + sp_offset));
       mem = gen_frame_mem (SImode, addr);
@@ -19064,9 +19088,9 @@
       break;
     }
 }
+
 /* LLVM LOCAL - Disable scheduler. */
 #ifndef ENABLE_LLVM
-
 
 /* Power4 load update and store update instructions are cracked into a
    load or store and an integer insn which are executed in the same cycle.
@@ -19292,6 +19316,7 @@
    INSN earlier, reduce the priority to execute INSN later.  Do not
    define this macro if you do not need to adjust the scheduling
    priorities of insns.  */
+
 static int
 rs6000_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
 {
@@ -19394,7 +19419,6 @@
   return 0;
 }
 
-
 /* Determine is PAT refers to memory.  */
 
 static bool
@@ -19981,6 +20005,7 @@
 
 /* LLVM LOCAL - Disable scheduler. */
 #endif ENABLE_LLVM
+
 /* Length in units of the trampoline for entering a nested function.  */
 
 int

Modified: llvm-gcc-4.2/trunk/gcc/cp/call.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cp/call.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cp/call.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cp/call.c Tue Jul 29 23:41:34 2008
@@ -281,7 +281,8 @@
 
   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 @@
   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)
@@ -675,6 +677,14 @@
       conv = build_conv (ck_std, to, conv);
       conv->bad_p = true;
     }
+  /* APPLE LOCAL begin blocks (ck) */
+  else if (tcode == POINTER_TYPE && fcode == BLOCK_POINTER_TYPE
+	   && (objc_is_id (to)
+	       || VOID_TYPE_P (TREE_TYPE (to))))
+    {
+      conv = build_conv (ck_ptr, to, conv);
+    }
+  /* APPLE LOCAL end blocks (ck) */
   else if ((tcode == POINTER_TYPE && fcode == POINTER_TYPE)
 	   || (TYPE_PTRMEM_P (to) && TYPE_PTRMEM_P (from)))
     {
@@ -827,6 +837,8 @@
       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);
@@ -3543,10 +3555,20 @@
        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)))
+	   /* 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))
+	   /* APPLE LOCAL end blocks 6040305 (co) */
 	   || (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type))
+	   /* APPLE LOCAL begin blocks 6040305 (co) */
+	   || (TREE_CODE (arg2_type) == BLOCK_POINTER_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)))
     {

Modified: llvm-gcc-4.2/trunk/gcc/cp/decl.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cp/decl.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cp/decl.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cp/decl.c Tue Jul 29 23:41:34 2008
@@ -54,7 +54,8 @@
 /* APPLE LOCAL optimization pragmas 3124235/3420242 */
 #include "opts.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);
@@ -9201,7 +9202,8 @@
 
    *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;

Modified: llvm-gcc-4.2/trunk/gcc/cp/error.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cp/error.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cp/error.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cp/error.c Tue Jul 29 23:41:34 2008
@@ -342,6 +342,8 @@
 	 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 @@
   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 @@
 	    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 @@
   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)

Modified: llvm-gcc-4.2/trunk/gcc/cp/mangle.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cp/mangle.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cp/mangle.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cp/mangle.c Tue Jul 29 23:41:34 2008
@@ -1649,6 +1649,13 @@
 	  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));

Modified: llvm-gcc-4.2/trunk/gcc/cp/name-lookup.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cp/name-lookup.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cp/name-lookup.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cp/name-lookup.c Tue Jul 29 23:41:34 2008
@@ -366,6 +366,8 @@
     {
       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);
@@ -1824,6 +1826,8 @@
   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;
 }
@@ -4560,6 +4564,8 @@
 	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));

Modified: llvm-gcc-4.2/trunk/gcc/cp/parser.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cp/parser.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cp/parser.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cp/parser.c Tue Jul 29 23:41:34 2008
@@ -1628,6 +1628,9 @@
   (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);
@@ -1656,7 +1659,8 @@
 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
@@ -3288,6 +3292,8 @@
      ( 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:
 
@@ -3323,6 +3329,16 @@
   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
@@ -3416,7 +3432,8 @@
 	    /* 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);
 	  }
@@ -6862,7 +6879,8 @@
     }
   /* 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)
@@ -7036,7 +7054,8 @@
 
 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;
 
@@ -7070,6 +7089,10 @@
   /* APPLE LOCAL end CW asm blocks */
   /* 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 `}'.  */
@@ -7772,6 +7795,10 @@
       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))
 	{
@@ -7844,7 +7871,8 @@
     }
   /* 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
     {
@@ -12298,6 +12326,37 @@
   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:
@@ -12362,6 +12421,28 @@
   /* 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.  */
@@ -12839,6 +12920,8 @@
 
    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
@@ -13621,7 +13704,8 @@
 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
@@ -15389,7 +15473,8 @@
 
   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);
@@ -15466,7 +15551,8 @@
   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);
 }
 
@@ -16251,6 +16337,8 @@
     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));
 
@@ -20024,7 +20112,8 @@
   /* 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))
@@ -20060,7 +20149,8 @@
       /* APPLE LOCAL end radar 2848255 */
       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 ();
     }
 
@@ -20071,7 +20161,8 @@
       /* 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));
     }
 
@@ -20100,7 +20191,8 @@
   /* 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));
 }
@@ -20363,6 +20455,1081 @@
   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)
+{
+  /* See declare_block_prologue_local_vars for code to find
+     FIELD_DECLs, if the below doesn't work.  */
+  return build_class_member_access_expr (e, member,
+					 NULL_TREE, false);
+}
+
+static tree block_copy_assign_decl;
+static tree block_destroy_decl;
+static tree block_byref_assign_copy_decl;
+
+/** build_block_struct_type -
+ struct block_1 {
+ struct invok_impl impl;
+ void *CopyFuncPtr;   // only if BLOCK_HAS_COPY_DISPOSE is set
+ void *DestroyFuncPtr;  // only if BLOCK_HAS_COPY_DISPOSE is set
+ 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;
+  /* build struct invok_impl */
+  if (!invoke_impl_ptr_type)
+    build_block_internal_types ();
+
+  /* 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 __byref 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;
+	block_impl->BlockHasByrefVar = TRUE;
+	break;
+      }
+
+  sprintf(buffer, "__block_%d", ++unique_count);
+  push_to_top_level ();
+  /* block_struct_type = start_struct (RECORD_TYPE, get_identifier (buffer)); */
+  block_struct_type = make_aggr_type (RECORD_TYPE);
+  xref_basetypes (block_struct_type, NULL_TREE);
+
+  /* struct invok_impl impl; */
+  field = build_decl (FIELD_DECL, get_identifier ("impl"),
+		      TREE_TYPE (invoke_impl_ptr_type));
+  TREE_CHAIN (field) = fields;
+  fields = field;
+  if (block_impl->BlockHasCopyDispose)
+  {
+    /* void *CopyFuncPtr; */
+    field = build_decl (FIELD_DECL, get_identifier ("CopyFuncPtr"),
+			ptr_type_node);
+    TREE_CHAIN (field) = fields;
+    fields = field;
+    /* void *DestroyFuncPtr; */
+    field = build_decl (FIELD_DECL, get_identifier ("DestroyFuncPtr"),
+			ptr_type_node);
+    TREE_CHAIN (field) = fields;
+    fields = field;
+    /* 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;
+  }
+
+  pop_from_top_level ();
+  /* finish_struct (block_struct_type, field_decl_chain, NULL_TREE); */
+  finish_builtin_struct (block_struct_type, buffer,
+			 fields, NULL_TREE);
+
+  /* Zap out the name so that the back-end will give us the debugging
+     information for this anonymous RECORD_TYPE.  */
+  TYPE_NAME (block_struct_type) = NULL_TREE;
+
+  return block_struct_type;
+}
+
+/**
+ build_block_struct_initlist - builds the initializer list:
+ { &_NSConcreteStackBlock // isa,
+ BLOCK_NO_COPY | BLOCK_HAS_COPY_DISPOSE // flags,
+ sizeof(struct block_1),
+ helper_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
+ }
+*/
+static tree
+build_block_struct_initlist (tree block_struct_type,
+			     struct block_sema_info *block_impl)
+{
+  tree initlist;
+  int size;
+  tree helper_addr, chain, fields;
+  unsigned flags = 0;
+  static tree NSConcreteStackBlock_decl = NULL_TREE;
+
+  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;
+  /* Set BLOCK_NO_COPY flag only if we are using the old byref,
+     indirect reference byref variables. */
+  if (block_impl->block_byref_decl_list && !block_impl->BlockHasByrefVar)
+    flags |= BLOCK_NO_COPY;
+
+  fields = TYPE_FIELDS (TREE_TYPE (invoke_impl_ptr_type));
+
+  /* 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);
+	}
+    }
+  initlist = build_tree_list (fields,
+			      build_fold_addr_expr (NSConcreteStackBlock_decl));
+  fields = TREE_CHAIN (fields);
+
+  initlist = tree_cons (fields,
+                        build_int_cst (unsigned_type_node, flags),
+                        initlist);
+  fields = TREE_CHAIN (fields);
+  size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (block_struct_type));
+  initlist = tree_cons (fields,
+                        build_int_cst (unsigned_type_node, size),
+                        initlist);
+  fields = TREE_CHAIN (fields);
+  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);
+  gcc_assert (invoke_impl_ptr_type);
+  initlist = build_constructor_from_list (TREE_TYPE (invoke_impl_ptr_type),
+                                          nreverse (initlist));
+  fields = TYPE_FIELDS (block_struct_type);
+  initlist = build_tree_list (fields, initlist);
+
+  if (block_impl->BlockHasCopyDispose)
+    {
+      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);
+      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);
+    }
+  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, copy_in_object (y), initlist);
+    }
+  for (chain = block_impl->block_original_byref_decl_list; chain;
+       chain = TREE_CHAIN (chain))
+    {
+      tree y = TREE_VALUE (chain);
+      TREE_USED (y) = 1;
+      fields = TREE_CHAIN (fields);
+      y = build_fold_addr_expr (y);
+      initlist = tree_cons (fields, y, initlist);
+    }
+  return initlist;
+}
+
+/**
+ build_block_literal_tmp - This routine:
+
+ 1) builds block type:
+ struct block_1 {
+ struct invok_impl impl;
+ void *CopyFuncPtr;    // only if block BLOCK_HAS_COPY_DISPOSE
+ void *DestroyFuncPtr; // only if block BLOCK_HAS_COPY_DISPOSE
+ 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 // isa,
+   BLOCK_NO_COPY | BLOCK_HAS_COPY_DISPOSE // flags,
+   sizeof(struct block_1),
+   helper_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.
+*/
+
+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);
+
+
+  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) = current_function_decl;
+  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);
+  return block_holder_tmp_decl;
+}
+
+static tree
+clean_and_exit (tree block)
+{
+  pop_function_context ();
+  pop_lang_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;
+  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 (dst_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))
+    if (block_requires_copying (TREE_VALUE (chain)))
+    {
+      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)
+      {
+        tree func_params, call_exp;
+        /* _Block_copy_assign(&_dest->myImportedBlock, _src->myImportedClosure) */
+        /* Build a: void _Block_copy_assign (void *, void *) if not done
+           already. */
+        if (!block_copy_assign_decl)
+        {
+          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)));
+
+          block_copy_assign_decl = builtin_function ("_Block_copy_assign", func_type,
+						     0, NOT_BUILT_IN, 0, NULL_TREE);
+          TREE_NOTHROW (block_copy_assign_decl) = 0;
+        }
+        dst_block_component = build_fold_addr_expr (dst_block_component);
+        func_params = tree_cons (NULL_TREE, dst_block_component,
+                                 tree_cons (NULL_TREE, src_block_component,
+                                            NULL_TREE));
+        call_exp = build_function_call (block_copy_assign_decl, func_params);
+        add_stmt (call_exp);
+      }
+      else
+      {
+        /* _dest-> imported_object_x = [_src->imported_object_x retain] */
+        tree rhs, store;
+        /* [_src->imported_object_x retain] */
+        rhs = retain_block_component (src_block_component);
+        store = build_modify_expr (dst_block_component, NOP_EXPR, rhs);
+        add_stmt (store);
+      }
+    }
+
+  /* For each __block declared variable used in |...| Must generate call to:
+     _Block_byref_assign_copy(&_dest->myImportedBlock, _src->myImportedBlock)
+  */
+  for (chain = block_impl->block_byref_decl_list; chain;
+         chain = TREE_CHAIN (chain))
+    if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain)))
+      {
+	tree func_params, 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_byref_assign_copy(&_dest->myImportedClosure, _src->myImportedClosure) */
+	/* Build a: void _Block_byref_assign_copy (void *, void *) if
+	   not done already. */
+	if (!block_byref_assign_copy_decl
+	    && !(block_byref_assign_copy_decl
+		 = lookup_name (get_identifier ("_Block_byref_assign_copy"))))
+	  {
+	    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)));
+
+	    block_byref_assign_copy_decl
+	      = builtin_function ("_Block_byref_assign_copy", func_type,
+				  0, NOT_BUILT_IN, 0, NULL_TREE);
+	    TREE_NOTHROW (block_byref_assign_copy_decl) = 0;
+	  }
+	dst_block_component = build_fold_addr_expr (dst_block_component);
+	func_params = tree_cons (NULL_TREE, dst_block_component,
+				 tree_cons (NULL_TREE, src_block_component,
+					    NULL_TREE));
+	call_exp = build_function_call (block_byref_assign_copy_decl, func_params);
+	add_stmt (call_exp);
+      }
+
+  finish_compound_stmt (stmt);
+  finish_function (0);
+  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))
+    if (block_requires_copying (TREE_VALUE (chain)))
+    {
+      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)
+      {
+        tree func_params, call_exp;
+        /* _Block_destroy(_src->myImportedClosure); */
+        /* _Block_destroy (void *); */
+        /* Build a: void _Block_destroy (void *) if not done already. */
+        if (!block_destroy_decl &&
+	    !(block_destroy_decl = lookup_name (get_identifier ("_Block_destroy"))))
+        {
+          tree func_type =
+          build_function_type (void_type_node,
+                               tree_cons (NULL_TREE, ptr_type_node, void_list_node));
+
+          block_destroy_decl = builtin_function ("_Block_destroy", func_type,
+                                                     0, NOT_BUILT_IN, 0, NULL_TREE);
+          TREE_NOTHROW (block_destroy_decl) = 0;
+        }
+        func_params = tree_cons (NULL_TREE, src_block_component, NULL_TREE);
+        call_exp = build_function_call (block_destroy_decl, func_params);
+        add_stmt (call_exp);
+      }
+      else
+      {
+        tree rel_exp;
+        /* [_src->imported_object_0 release]; */
+        rel_exp = release_block_component (src_block_component);
+        add_stmt (rel_exp);
+      }
+    }
+
+  /* For each __byref declared variable used in |...| Must generate call to:
+   _Block_byref_release(_src->myImportedClosure)
+   */
+  for (chain = block_impl->block_byref_decl_list; chain;
+       chain = TREE_CHAIN (chain))
+    if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain)))
+      {
+	tree func_params, call_exp;
+	tree p = TREE_VALUE (chain);
+	tree src_block_component;
+
+	src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"),
+						   DECL_NAME (p));
+      /* _Block_byref_release(_src->myImportedClosure) */
+      /* Build a: void _Block_byref_release (void *) if not done
+	 already. */
+      func_params = tree_cons (NULL_TREE, src_block_component, NULL_TREE);
+      call_exp = build_function_call (build_block_byref_release_decl (), func_params);
+      add_stmt (call_exp);
+    }
+
+  finish_compound_stmt (stmt);
+  finish_function (0);
+  pop_function_context ();
+}
+
+/** cp_parser_block_literal_expr - Main routine to process a block literal
+    with the syntax of ^arg-list[OPT] block or ^()expression. 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, resdecl;
+  tree typelist;
+  tree helper_function_type;
+  bool at_file_scope = global_bindings_p ();
+  tree block;
+
+  cp_lexer_consume_token (parser->lexer); /* eat '^' */
+
+  /* Parse the optional argument list */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      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)
+	{
+	  /* pop_scope (); */
+	  return error_mark_node;
+	}
+      /* pop_scope (); */
+    }
+#if 0
+  else
+    arglist = build_tree_list (NULL_TREE, void_type_node);
+#endif
+
+  block = begin_block ();
+
+  /* cur_block->arg_info = NULL; */
+  cur_block->return_type = NULL_TREE;
+
+  if (args)
+    {
+      /* cur_block->arg_info = args; */
+      if (arg_type)
+	{
+	  cur_block->hasPrototype = true;
+	  /* This is the only way in gcc to know if argument list ends with ... */
+	  cur_block->isVariadic = args->ellipsis_p;
+	}
+      else
+	{
+	  /* K&R syle () argument list. */
+	  cur_block->hasPrototype = false;
+	  cur_block->isVariadic = true;
+	}
+    }
+  else
+    {
+      cur_block->hasPrototype = false;
+      cur_block->isVariadic = false;
+      /* cur_block->arg_info = xcalloc (1, sizeof (struct c_arg_info)); */
+    }
+
+  /* Must also build hidden parameter _self added to the helper
+     function, even though we do not know its type yet. */
+  self_arg = build_artificial_parm (get_identifier ("_self"), 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;
+
+  /* Build the declaration of the helper function (we do not know its result
+     type yet, so assume it is 'void'). Treat this as a nested function and use
+     nested function infrastructure for its generation. */
+  sprintf (name, "__helper_%d", unique_count);
+
+  push_lang_context (lang_name_c);
+  ftype = build_function_type (void_type_node, arg_type);
+  block_helper_function_decl = build_helper_func_decl (get_identifier (name),
+						       ftype);
+  DECL_NO_STATIC_CHAIN (current_function_decl) = 0;
+  DECL_CONTEXT (block_helper_function_decl) = current_function_decl;
+  BLOCK_HELPER_FUNC (block_helper_function_decl) = 1;
+  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);
+
+  /* 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;
+
+  /* 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);
+    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 (at_file_scope)
+  {
+    error ("block literal cannot be declared at global scope");
+    return clean_and_exit (block);
+  }
+  if (restype == error_mark_node)
+    return clean_and_exit (block);
+
+  /* Now that we know type of the hidden _self 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;
+
+  /* Now that we know helper's result type, fix its result variable decl. */
+  resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
+  DECL_ARTIFICIAL (resdecl) = 1;
+  DECL_IGNORED_P (resdecl) = 1;
+  DECL_RESULT (current_function_decl) = resdecl;
+
+  cur_block->block_body = stmt;
+  block_build_prologue (cur_block);
+
+  finish_compound_stmt (stmt);
+  /* add_stmt (fnbody); */
+  finish_function (0);
+  pop_function_context ();
+  pop_lang_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);
+  }
+
+
+  /* We are out of helper function scope and back in its enclosing scope.
+     We also know all we need to know about the helper function. So, fix its
+     type here. */
+  ftype = build_function_type (restype, TREE_CHAIN (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;
+
+  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-><decl-name>.
+*/
+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;
+}
+
+/**
+  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)
+{
+  /* 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. */
+  tree ptr_type = (TREE_CODE (decl) == VAR_DECL && BLOCK_DECL_BYREF (decl))
+                   ? TREE_TYPE (decl) : build_pointer_type (TREE_TYPE (decl));
+  tree 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);
+    }
+
+  /* Current scope must be that of the main function body. */
+  /* FIXME gcc_assert (current_scope->function_body);*/
+  pushdecl (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.  */
+  if (! flag_objc_gc_only)
+    push_cleanup (byref_decl, build_block_byref_release_exp (byref_decl), false);
+  /* 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);
+  cur_block->block_original_byref_decl_list =
+    tree_cons (NULL_TREE, exp, cur_block->block_original_byref_decl_list);
+  return byref_decl;
+}
+
+#define BINDING_VALUE(b) ((b)->value)
+
+/**
+  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)
+{
+  tree ref_decl;
+  /* '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; 
+      }
+    }
+  }
+
+  ref_decl = build_decl (VAR_DECL, name,
+                         build_qualified_type (TREE_TYPE (decl),
+                                               TYPE_QUAL_CONST));
+  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);
+    cp_finish_decl (ref_decl, NULL_TREE, /*init_const_expr_p=*/false, NULL_TREE,
+		    LOOKUP_ONLYCONVERTING);
+  }
+  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 =
+    tree_cons (NULL_TREE, decl, cur_block->block_original_ref_decl_list);
+  return ref_decl;
+}
+
+/** build_block_internal_types - This routine builds the block type:
+ struct __invoke_impl {
+ void   *isa;
+ int32_t Flags;
+ int32_t Size;
+ void *FuncPtr;
+ } *invoke_impl_ptr_type;
+ */
+void
+build_block_internal_types (void)
+{
+  tree fields = NULL_TREE, field_decl;
+  tree invoke_impl_type;
+
+  /* If a user-declaration of "struct __invoke_impl" is seen, use it. */
+  invoke_impl_type = lookup_name_prefer_type (get_identifier ("__invoke_impl"), 2);
+  if (invoke_impl_type)
+  {
+    invoke_impl_ptr_type = build_pointer_type (invoke_impl_type);
+    return;
+  }
+
+  push_to_top_level ();
+
+  /* invoke_impl_type = start_struct (RECORD_TYPE, get_identifier ("__invoke_impl")); */
+  invoke_impl_type = make_aggr_type (RECORD_TYPE);
+  xref_basetypes (invoke_impl_type, NULL_TREE);
+
+  /* void *isa; */
+  field_decl = build_decl (FIELD_DECL, get_identifier ("isa"), ptr_type_node);
+  TREE_CHAIN (field_decl) = fields;
+  fields = field_decl;
+
+  /* int32_t Flags; */
+  field_decl = build_decl (FIELD_DECL, get_identifier ("Flags"), unsigned_type_node);
+  TREE_CHAIN (field_decl) = fields;
+  fields = field_decl;
+
+  /* int32_t Size */
+  field_decl = build_decl (FIELD_DECL, get_identifier ("Size"), unsigned_type_node);
+  TREE_CHAIN (field_decl) = fields;
+  fields = field_decl;
+
+  /* void *FuncPtr; */
+  field_decl = build_decl (FIELD_DECL, get_identifier ("FuncPtr"), ptr_type_node);
+  TREE_CHAIN (field_decl) = fields;
+  fields = field_decl;
+
+  /* Mark this struct as being a block struct rather than a 'normal'
+   struct.  */
+  TYPE_BLOCK_IMPL_STRUCT (invoke_impl_type) = 1;
+  /* finish_struct (invoke_impl_type, field_decl_chain, NULL_TREE); */
+  finish_builtin_struct (invoke_impl_type, "__invoke_impl", fields, NULL_TREE);
+  pop_from_top_level ();
+  invoke_impl_ptr_type = build_pointer_type (invoke_impl_type);
+}
+
+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);
+
+  /* Closure contructs seen -- generate supporting types.  */
+  if (!invoke_impl_ptr_type)
+    build_block_internal_types ();
+
+  ret->attributes = attributes;
+  ret->declarator = itarget;
+  ret->u.block_pointer.qualifiers = quals;
+  return ret;
+}
+
+bool in_imm_block (void)
+{
+  return (cur_block && cur_block->cp_the_scope == current_binding_level);
+}
+
+/* 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)
+{
+  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;
+  retrofit_lang_decl (func_decl);
+  return func_decl;
+}
+
+/**
+ 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;
+  component = lookup_member (TREE_TYPE (TREE_TYPE (self_parm)),
+			     DECL_NAME (component), 0, 0);
+  block_component = build_component_ref (build_indirect_ref (self_parm, "->"),
+					 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));
+  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 = _self->y;
+ int x = _self->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 ("_self"));
+  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 blocks 6040305 (ch) */
 
 /* OpenMP 2.5 parsing routines.  */
 
@@ -21748,12 +22915,8 @@
   /* Bad parse errors.  Just forget about it.  */
   if (! global_bindings_p () || current_class_type || decl_namespace_list)
     return;
-  /* LLVM LOCAL begin */
-  if (pch_file) {
+  if (pch_file)
     c_common_write_pch ();
-    return;
-  }
-  /* LLVM LOCAL end */
   /* APPLE LOCAL end radar 4874613 */
 }
 

Modified: llvm-gcc-4.2/trunk/gcc/cp/semantics.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cp/semantics.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cp/semantics.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cp/semantics.c Tue Jul 29 23:41:34 2008
@@ -2455,6 +2455,28 @@
   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 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
@@ -2566,7 +2588,10 @@
 	{
 	  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 %<auto%> variable from containing function"
@@ -2898,9 +2923,72 @@
 	}
     }
 
+  /* APPLE LOCAL begin blocks 6040305 (ci) */
+  if (cur_block
+      && (TREE_CODE (decl) == VAR_DECL
+	  || TREE_CODE (decl) == PARM_DECL)
+      && !lookup_name_in_block (id_expression, &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)
+		    && (!DECL_CONTEXT (decl)
+			|| DECL_NAMESPACE_SCOPE_P (decl)))));
+      /* Treat all 'global' variables as 'byref' by default. */
+      if (gdecl)
+	{
+	  /* byref globals are directly accessed. */
+	  if (!gdecl)
+	    /* build a decl for the byref variable. */
+	    decl = build_block_byref_decl (id_expression, decl, decl);
+	  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))
+	    /* build a new decl node. set its type to 'const' type
+	       of the old decl. */
+	    decl = build_block_ref_decl (id_expression, decl);
+	}
+    }
+  /* APPLE LOCAL end blocks 6040305 (ci) */
+
   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;
 }
 
@@ -3971,6 +4059,32 @@
 
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 }
+
+/* APPLE LOCAL begin blocks 6040305 (ch) */
+tree
+begin_block (void)
+{
+  struct block_sema_info *csi;
+  tree block;
+  /* push_scope (); */
+  block = do_pushlevel (sk_block);
+  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 (); */
+  do_poplevel (block);
+  return csi;
+}
+/* APPLE LOCAL end blocks 6040305 (ch) */
+
 
 void
 init_cp_semantics (void)

Modified: llvm-gcc-4.2/trunk/gcc/cp/typeck.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cp/typeck.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cp/typeck.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cp/typeck.c Tue Jul 29 23:41:34 2008
@@ -406,7 +406,8 @@
   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);
@@ -1040,7 +1041,22 @@
       if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
 	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)
@@ -1048,7 +1064,7 @@
 	  || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
 	return false;
       break;
-
+                
     case METHOD_TYPE:
     case FUNCTION_TYPE:
       if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
@@ -2784,7 +2800,8 @@
   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))
@@ -3367,7 +3384,8 @@
       if ((TREE_CODE (orig_op0) == STRING_CST && !integer_zerop (op1))
 	  || (TREE_CODE (orig_op1) == STRING_CST && !integer_zerop (op0)))
 	warning (OPT_Waddress, 
-                 "comparison with string literal results in unspecified behaviour");
+		 /* APPLE LOCAL spelling 5808469 */
+                 "comparison with string literal results in unspecified behavior");
 
       build_type = boolean_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
@@ -3379,18 +3397,27 @@
 	       || (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1)))
 	result_type = composite_pointer_type (type0, type1, op0, op1,
 					      "comparison");
-      else if ((code0 == POINTER_TYPE || TYPE_PTRMEM_P (type0))
+      /* APPLE LOCAL begin blocks 6040305 */
+      else if (code0 == BLOCK_POINTER_TYPE && code1 == BLOCK_POINTER_TYPE)
+	result_type = composite_pointer_type (type0, type1, op0, op1,
+					      "comparison");
+      /* APPLE LOCAL end blocks 6040305 */
+      /* 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");
@@ -5362,6 +5389,30 @@
   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));
@@ -6787,6 +6838,10 @@
       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);
@@ -6794,6 +6849,50 @@
     }
 }
 
+/* APPLE LOCAL begin blocks 6040305 (cm) */
+static bool
+types_are_block_compatible (tree t1, tree t2)
+{
+  return comptypes (t1, t2, COMPARE_STRICT);
+}
+
+#if 0
+/**
+ build_block_call - Routine to build a block call; as in:
+  ((double(*)(struct invok_impl *, int))(BLOCK_PTR_VAR->FuncPtr))(I, 42);
+ FNTYPE is the original function type derived from the syntax.
+ FUNCTION is the4 block pointer variable.
+ PARAMS is the parameter list.
+*/
+static tree
+build_block_call (tree fntype, tree function, tree params)
+{
+  tree block_ptr_exp;
+  tree function_ptr_exp;
+  tree typelist;
+
+  /* (struct invok_impl *)BLOCK_PTR_VAR */
+  /* First convert it to 'void *'. */
+  block_ptr_exp = convert (ptr_type_node, function);
+  gcc_assert (invoke_impl_ptr_type);
+  block_ptr_exp = convert (invoke_impl_ptr_type, block_ptr_exp);
+  params = tree_cons (NULL_TREE, block_ptr_exp, params);
+  /* BLOCK_PTR_VAR->FuncPtr */
+  function_ptr_exp =
+    build_component_ref (build_indirect_ref (block_ptr_exp, "->"),
+                         get_identifier ("FuncPtr"));
+
+  /* Build: result_type(*)(struct invok_impl *, function-arg-type-list) */
+  typelist = TYPE_ARG_TYPES (fntype);
+  typelist = tree_cons (NULL_TREE, invoke_impl_ptr_type, typelist);
+  fntype = build_function_type (TREE_TYPE (fntype), typelist);
+  function_ptr_exp = convert (build_pointer_type (fntype), function_ptr_exp);
+  return fold_build3 (CALL_EXPR, TREE_TYPE (fntype),
+                      function_ptr_exp, params, NULL_TREE);
+}
+#endif
+/* 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
@@ -6843,6 +6942,50 @@
       return retval;
     }
 
+  /* APPLE LOCAL begin blocks 6040305 (cm) */
+  if (cur_block)
+    {
+      if (cur_block->return_type == NULL_TREE)
+	{
+	  if (retval)
+	    cur_block->return_type = TYPE_MAIN_VARIANT (TREE_TYPE (retval));
+	  else
+	    cur_block->return_type = void_type_node;
+	  /* FIXME - is this copy ctor safe? */
+	  return retval;
+	}
+
+      /* Otherwise, 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 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 retval;
+    }
+  /* APPLE LOCAL end blocks 6040305 (cm) */
+
   /* When no explicit return-value is given in a function with a named
      return value, the named return value is used.  */
   result = DECL_RESULT (current_function_decl);

Modified: llvm-gcc-4.2/trunk/gcc/dwarf2out.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/dwarf2out.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/dwarf2out.c (original)
+++ llvm-gcc-4.2/trunk/gcc/dwarf2out.c Tue Jul 29 23:41:34 2008
@@ -8418,6 +8418,8 @@
     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)));
@@ -8450,6 +8452,8 @@
     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:
@@ -8637,7 +8641,8 @@
       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,
@@ -12986,6 +12991,8 @@
     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

Modified: llvm-gcc-4.2/trunk/gcc/expr.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/expr.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/expr.c (original)
+++ llvm-gcc-4.2/trunk/gcc/expr.c Tue Jul 29 23:41:34 2008
@@ -160,6 +160,8 @@
 static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx);
 static rtx const_vector_from_tree (tree);
 static void write_complex_part (rtx, rtx, bool);
+/* APPLE LOCAL bswap uxtb16 support */
+static rtx look_for_bytemanip (tree, rtx);
 
 /* Record for each mode whether we can move a register directly to or
    from an object of that mode in memory.  If we can't, we won't try
@@ -4811,6 +4813,8 @@
     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;
@@ -6771,7 +6775,7 @@
 
 rtx
 expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
-                  enum expand_modifier modifier, rtx *alt_rtl)
+		  enum expand_modifier modifier, rtx *alt_rtl)
 {
   int rn = -1;
   rtx ret, last = NULL;
@@ -7857,6 +7861,26 @@
 	  return REDUCE_BIT_FIELD (op0);
 	}
 
+/* APPLE LOCAL begin ARM improve (int) (longlong >> 32) */
+#ifdef TARGET_ARM
+      /* Look for (int) (longlong  >> 32).  This is just subreg:SI (longlong).
+	 This is not a great place to do this.  Signedness of shift does not
+	 matter.  */
+      if (mode == SImode
+	  && TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == DImode
+	  && TREE_CODE (TREE_OPERAND (exp, 0)) == RSHIFT_EXPR
+	  && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
+	  && TREE_INT_CST_HIGH (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == 0
+	  && TREE_INT_CST_LOW (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == 32)
+	{
+	  op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), NULL_RTX,
+			     DImode, 0);
+	  op0 = simplify_gen_subreg (SImode, op0, DImode, 4);
+	}
+      else
+#endif
+/* APPLE LOCAL end ARM improve (int) (longlong >> 32) */
+
       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode,
 			 modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
       if (GET_MODE (op0) == mode)
@@ -8496,12 +8520,23 @@
 
     case TRUTH_AND_EXPR:
       code = BIT_AND_EXPR;
+/* APPLE LOCAL begin bswap uxtb16 support */
+      goto binop;
+
     case BIT_AND_EXPR:
+      temp = look_for_bytemanip (exp, subtarget);
+      if (temp)
+	return REDUCE_BIT_FIELD (temp);
       goto binop;
 
     case TRUTH_OR_EXPR:
       code = BIT_IOR_EXPR;
+      goto binop;
+
     case BIT_IOR_EXPR:
+      temp = look_for_bytemanip (exp, subtarget);
+      if (temp)
+	return REDUCE_BIT_FIELD (temp);
       goto binop;
 
     case TRUTH_XOR_EXPR:
@@ -8511,6 +8546,11 @@
 
     case LSHIFT_EXPR:
     case RSHIFT_EXPR:
+      temp = look_for_bytemanip (exp, subtarget);
+      if (temp)
+	return REDUCE_BIT_FIELD (temp);
+      /* fall through */
+/* APPLE LOCAL end bswap uxtb16 support */
     case LROTATE_EXPR:
     case RROTATE_EXPR:
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
@@ -9588,4 +9628,391 @@
 
   return gen_rtx_CONST_VECTOR (mode, v);
 }
+
+/* APPLE LOCAL begin bswap uxtb16 support */
+
+/* This struct represents one shift-and-and sequence that moves one
+   or more bytes from input to output.
+   Shift may be 0, and mask may be all 1 bits.
+   In these cases the parent operator may be missing as well.  */
+
+#if defined (HAVE_bswapsi2) || defined (HAVE_bswapdi2) || defined (HAVE_uxtb16)
+struct bytemanip 
+{
+  int shiftcount;   /* negative left, positive right, 0 none, 
+		       666 ending sentinel */
+  HOST_WIDE_INT andmask_high;	    /* both ffffffff if none */
+  HOST_WIDE_INT andmask_low;	    /* both ffffffff if none */
+  int bitmask;			    /* insn dependent, see below */
+};
+#endif
+
+#ifdef HAVE_bswapsi2
+/* Tables for bswapsi2.  Bitmask values:
+   1 =   0x00000000 000000ff used 
+   2 =   0x00000000 0000ff00 used 
+   4 =   0x00000000 00ff0000 used
+   8 =   0x00000000 ff000000 used */
+
+/* This table is for when the shift is done before the mask:
+      (x >> shift) & mask */
+
+static struct bytemanip bswap32_shift_first[] =
+  {
+    { -24, 0x00000000, 0xff000000, 8 },
+    {  -8, 0x00000000, 0x00ff0000, 4 },
+    {   8, 0x00000000, 0x0000ff00, 2 },
+    {  24, 0x00000000, 0x000000ff, 1 },
+    { -24, 0xffffffff, 0xffffffff, 8 },
+    {  24, 0xffffffff, 0xffffffff, 1 },
+    { 666,          0,          0, 0 }
+  };
+
+/* This table is for when the shift is done after the mask:
+      (x & mask) >> shift */
+
+static struct bytemanip bswap32_and_first[] =
+  {
+    { -24, 0x00000000, 0x000000ff, 8 },
+    {  -8, 0x00000000, 0x0000ff00, 4 },
+    {   8, 0x00000000, 0x00ff0000, 2 },
+    {  24, 0x00000000, 0xff000000, 1 },
+    { 666,          0,          0, 0 }
+  };
+#endif /* HAVE_bswapsi2 */
+
+#ifdef HAVE_bswapdi2
+/* Tables for bswapdi2, analogous to the above.  Bitmask values:
+   1 =   0x00000000 000000ff used 
+   2 =   0x00000000 0000ff00 used 
+   4 =   0x00000000 00ff0000 used
+   8 =   0x00000000 ff000000 used
+   16 =  0x000000ff 00000000 used
+   32 =  0x0000ff00 00000000 used
+   64 =  0x00ff0000 00000000 used
+   128 = 0xff000000 00000000 used */
+
+static struct bytemanip bswap64_shift_first[] =
+  {
+    { -56, 0xff000000, 0x00000000, 128 },
+    { -40, 0x00ff0000, 0x00000000,  64 },
+    { -24, 0x0000ff00, 0x00000000,  32 },
+    {  -8, 0x000000ff, 0x00000000,  16 },
+    {   8, 0x00000000, 0xff000000,   8 },
+    {  24, 0x00000000, 0x00ff0000,   4 },
+    {  40, 0x00000000, 0x0000ff00,   2 },
+    {  56, 0x00000000, 0x000000ff,   1 },
+    { -56, 0xffffffff, 0xffffffff, 128 },
+    {  56, 0xffffffff, 0xffffffff,   1 },
+    { 666,          0,          0,   0 }
+  };
+
+static struct bytemanip bswap64_and_first[] =
+  {
+    { -56, 0x00000000, 0x000000ff, 128 },
+    { -40, 0x00000000, 0x0000ff00,  64 },
+    { -24, 0x00000000, 0x00ff0000,  32 },
+    {  -8, 0x00000000, 0xff000000,  16 },
+    {   8, 0x000000ff, 0x00000000,   8 },
+    {  24, 0x0000ff00, 0x00000000,   4 },
+    {  40, 0x00ff0000, 0x00000000,   2 },
+    {  56, 0xff000000, 0x00000000,   1 },
+    { 666,          0,          0,   0 }
+  };
+#endif /* HAVE_bswapdi2 */
+
+#ifdef HAVE_uxtb16
+/* A uxtb16 instruction is currently only supported on the ARM
+   architecture.  It zero-extends two selected bytes, at 16-bit
+   offsets from each other, into the two halfwords of the
+   destination register.  */
+/* Tables for uxtb16, analogous to the above.  Bitmask values:
+   1 =   000000ff used ROR 0
+   2 =   00ff0000 used ROR 0
+   4 =   000000ff used ROR 8
+   8 =   00ff0000 used ROR 8
+   16 =  000000ff used ROR 16
+   32 =  00ff0000 used ROR 16
+   64 =  000000ff used ROR 24
+   128 = 00ff0000 used ROR 24 
+  Note that some of the table entries represent a 2-byte operation. */
+
+static struct bytemanip uxtb16_shift_first[] =
+  {
+    {   0, 0x00000000, 0x00ff00ff,   3 },
+    {   8, 0x00000000, 0x000000ff,   4 },
+    {   8, 0x00000000, 0x00ff0000,   8 },
+    {   8, 0x00000000, 0x00ff00ff,  12 },
+    {  16, 0x00000000, 0x000000ff,  16 },
+    { -16, 0x00000000, 0x00ff0000,  32 },
+    {  24, 0x00000000, 0x000000ff,  64 },
+    {  -8, 0x00000000, 0x00ff0000, 128 }, 
+    {  24, 0xffffffff, 0xffffffff,  64 },
+    { 666,          0,          0,   0 }
+  };
+
+static struct bytemanip uxtb16_and_first[] =
+  {
+    {   8, 0x00000000, 0x0000FF00,   4 },
+    {   8, 0x00000000, 0xFF000000,   8 },
+    {   8, 0x00000000, 0xFF00FF00,  12 },
+    {  16, 0x00000000, 0x00FF0000,  16 },
+    { -16, 0x00000000, 0x000000FF,  32 },
+    {  24, 0x00000000, 0xFF000000,  64 },
+    {  -8, 0x00000000, 0x0000FF00, 128 },
+    { 666,          0,          0,   0 }
+  };
+#endif /* HAVE_uxtb16 */
+
+#if defined (HAVE_bswapsi2) || defined (HAVE_bswapdi2) || defined (HAVE_uxtb16)
+/* Examine one operand (expected to handle 1 or more bytes of the whole)
+   to see if the shift count and mask match one of the valid pairs.  A table
+   to look in is provided.  */
+
+static bool 
+find_and_record_values (tree lhs, HOST_WIDE_INT shiftcount,
+			    HOST_WIDE_INT andmask_low, HOST_WIDE_INT andmask_high,
+			    struct bytemanip *table, tree *operand, int *bitmask)
+{
+  int i;
+  /* All lhs's must be the same (pointer equality).  Function calls, ++, etc. are not shared,
+     so won't match. */
+  if (*operand != NULL_TREE && *operand != lhs)
+    return false;
+  *operand = lhs;
+ 
+  for (i = 0; table[i].shiftcount != 666; i++)
+    {
+      if (shiftcount == table[i].shiftcount
+	  && andmask_low == table[i].andmask_low
+	  && andmask_high == table[i].andmask_high)
+	{
+	  if ((*bitmask) & table[i].bitmask)
+	    return false;
+	  *bitmask |= table[i].bitmask;
+	  return true;
+	}
+    }
+  return false;
+}
+
+/* For ORs, just recurse to analyzing the operands.
+   For ANDs, look for ((x shift const) and const),
+     also for just (x and const)
+   For shifts, look for ((x & const) shift const),
+     also for just (x shift const)
+*/
+
+static bool
+analyze_leg (tree t, int *bitmask, tree *operand, enum machine_mode mode,
+		 struct bytemanip *shift_first, 
+		 struct bytemanip *and_first)
+{
+  HOST_WIDE_INT count;
+  bool m64_p;
+
+  gcc_assert (HOST_BITS_PER_WIDE_INT == 32 || HOST_BITS_PER_WIDE_INT == 64);
+  m64_p = (HOST_BITS_PER_WIDE_INT == 64);
+
+  if (!TYPE_UNSIGNED (TREE_TYPE (t)) || TYPE_MODE (TREE_TYPE (t)) != mode)
+    return false;
+  if (TREE_CODE (t) == BIT_IOR_EXPR)
+    {
+      if (!analyze_leg (TREE_OPERAND (t, 0), bitmask, operand, mode,
+			    shift_first, and_first)
+          || !analyze_leg (TREE_OPERAND (t, 1), bitmask, operand, mode,
+			    shift_first, and_first))
+	return false;
+    }
+  else if (TREE_CODE (t) == BIT_AND_EXPR)
+    {
+      if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST)
+	return false;
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == LSHIFT_EXPR
+	  || TREE_CODE (TREE_OPERAND (t, 0)) == RSHIFT_EXPR)
+	{
+	  if (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) != INTEGER_CST)
+	    return false;
+	  if (!TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t, 0)))
+	      || TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))) != mode)
+	    return false;
+	  count = TREE_INT_CST_LOW (TREE_OPERAND (TREE_OPERAND (t, 0), 1));
+	  if (TREE_CODE (TREE_OPERAND (t, 0)) == LSHIFT_EXPR)
+	    count = -count;
+	  if (!find_and_record_values (
+		TREE_OPERAND (TREE_OPERAND (t, 0), 0),
+		count,
+		m64_p ? TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) & 0xffffffff
+		      : TREE_INT_CST_LOW (TREE_OPERAND (t, 1)),
+		/* I'd really like ">> 32" here, but that generates a warning
+		   when HOST_BITS_PER_WIDE_INT == 32 */
+		m64_p ? TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) / 0x100000000ll
+		      : (unsigned HOST_WIDE_INT)
+			TREE_INT_CST_HIGH (TREE_OPERAND (t, 1)),
+		shift_first,
+		operand,
+		bitmask))
+	    return false;
+	}
+      else
+	if (!find_and_record_values (
+	      TREE_OPERAND (t, 0),
+	      (HOST_WIDE_INT)0,
+	      m64_p ? TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) & 0xffffffff
+		    : TREE_INT_CST_LOW (TREE_OPERAND (t, 1)),
+	      /* I'd really like ">> 32" here, but that generates a warning
+		 when HOST_BITS_PER_WIDE_INT == 32 */
+	      m64_p ? TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) / 0x100000000ll
+		    : (unsigned HOST_WIDE_INT)
+		      TREE_INT_CST_HIGH (TREE_OPERAND (t, 1)),
+	      shift_first,
+	      operand,
+	      bitmask))
+	  return false;
+    }
+  else if (TREE_CODE (t) == RSHIFT_EXPR
+	   || TREE_CODE (t) == LSHIFT_EXPR)
+    {
+      if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST)
+	return false;
+      count = TREE_INT_CST_LOW (TREE_OPERAND (t, 1));
+      if (TREE_CODE (t) == LSHIFT_EXPR)
+	count = -count;
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == BIT_AND_EXPR
+	  && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST)
+	{
+	  if (!TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t, 0)))
+	      || TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))) != mode)
+	    return false;
+	  if (!find_and_record_values (
+		TREE_OPERAND (TREE_OPERAND (t, 0), 0),
+		count,
+		m64_p ? TREE_INT_CST_LOW (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) & 0xffffffff
+		      : TREE_INT_CST_LOW (TREE_OPERAND (TREE_OPERAND (t, 0), 1)),
+		/* I'd really like ">> 32" here, but that generates a warning
+		   when HOST_BITS_PER_WIDE_INT == 32 */
+		m64_p ? TREE_INT_CST_LOW (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) / 0x100000000ll
+		      : (unsigned HOST_WIDE_INT)
+			TREE_INT_CST_HIGH (TREE_OPERAND (TREE_OPERAND (t, 0), 1)),
+		and_first,
+		operand,
+		bitmask))
+	    return false;
+	}
+     else
+      if (!find_and_record_values (
+	    TREE_OPERAND (t, 0),
+	    count,
+	    (HOST_WIDE_INT) 0xffffffff,
+	    (HOST_WIDE_INT) 0xffffffff,
+	    shift_first,
+	    operand,
+	    bitmask))
+	return false;
+    }
+  else
+    return false;
+
+  return true;
+}
+#endif /* defined (HAVE_bswapsi2) || defined (HAVE_bswapdi2) || defined (HAVE_uxtb16) */
+
+/* This is called for OR, AND, and SHIFT trees.
+   We look for the trees used to represent various byte manipulation
+   operations for which we have insn patterns on the target architecture.
+   Currently, these include: 
+   32-bit bswap:
+	 (x<<24) | ((x & 0x0000ff00) << 8)
+	 | ((x & 0x00ff0000) >> 8) | (x >> 24)
+      or alternatively
+	 ((x <<24) & 0xff000000) | ((x << 8)  & 0x00ff0000))
+	 | ((x >> 8) & 0x0000ff00) >> 8) | ((x >> 24) & 0x000000ff)
+      etc.
+   64 bit bswap
+   uxtb16
+   The table-driven code here is intended to handle arbitrary combinations
+   of byte movements like the above, provided all the bytes involved
+   are handled exactly once each.
+   If a match is found, the result is returned in a register.  */
+
+static rtx
+look_for_bytemanip (tree t, rtx subtarget ATTRIBUTE_UNUSED)
+{
+  enum machine_mode mode;
+
+  gcc_assert (TREE_CODE (t) == BIT_IOR_EXPR
+	      || TREE_CODE (t) == BIT_AND_EXPR
+	      || TREE_CODE (t) == LSHIFT_EXPR
+	      || TREE_CODE (t) == RSHIFT_EXPR);
+
+  if (!TYPE_UNSIGNED (TREE_TYPE (t)))
+    return NULL_RTX;
+  mode = TYPE_MODE (TREE_TYPE (t));
+  if (mode != SImode && mode != DImode)
+    return NULL_RTX;
+
+#ifdef HAVE_bswapsi2
+  if (HAVE_bswapsi2)
+    {
+      int bitmask = 0;
+      tree operand = NULL_TREE;
+      if (mode == SImode
+	  && analyze_leg (t, &bitmask, &operand, mode,
+			  bswap32_shift_first, bswap32_and_first)
+	  && bitmask == 0xf)
+	{
+	  /* This expression matches.  Now generate RTL. */
+	  rtx x = expand_expr (operand, subtarget, VOIDmode, 0);
+	  return expand_simple_unop (mode, BSWAP, x, NULL_RTX, 1);
+	}
+    }
+#endif
+
+#ifdef HAVE_bswapdi2
+  if (HAVE_bswapdi2)
+    {
+      int bitmask = 0;
+      tree operand = NULL_TREE;
+      if (mode == DImode
+	  && analyze_leg (t, &bitmask, &operand, mode,
+			  bswap64_shift_first, bswap64_and_first)
+	  && bitmask == 0xff)
+	{
+	  /* This expression matches.  Now generate RTL. */
+	  rtx x = expand_expr (operand, subtarget, VOIDmode, 0);
+	  return expand_simple_unop (mode, BSWAP, x, NULL_RTX, 1);
+	}
+    }
+#endif
+
+#ifdef HAVE_uxtb16
+  if (HAVE_uxtb16)
+    {
+      int bitmask = 0;
+      tree operand = NULL_TREE;
+      if (mode == SImode
+	  && analyze_leg (t, &bitmask, &operand, mode,
+			  uxtb16_shift_first, uxtb16_and_first)
+	  && (bitmask == 0x3 || bitmask == 0xc || bitmask == 0x30 || bitmask == 0xc0))
+	{
+	  /* This expression matches.  Now generate RTL. */
+	  rtx x = expand_expr (operand, subtarget, VOIDmode, 0);
+	  x = force_reg (SImode, x);
+	  x = gen_rtx_UNSPEC (SImode,
+			      gen_rtvec (2, x, bitmask == 0x3 ? const0_rtx :
+					       bitmask == 0xc ? gen_rtx_CONST_INT (SImode, 8) :
+					       bitmask == 0x30 ? gen_rtx_CONST_INT (SImode, 16) :
+					       /*bitmask == 0xc0*/ gen_rtx_CONST_INT (SImode, 24)),
+			      UNSPEC_UXTB16);
+	  x = force_reg (SImode, x);
+	  return x;
+	}
+    }
+#endif /* HAVE_uxtb16 */
+
+  /* Not an instruction we recognize. */
+  return NULL_RTX;
+}
+/* APPLE LOCAL end bswap uxtb16 support */
+
 #include "gt-expr.h"

Modified: llvm-gcc-4.2/trunk/gcc/function.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/function.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/function.c (original)
+++ llvm-gcc-4.2/trunk/gcc/function.c Tue Jul 29 23:41:34 2008
@@ -114,6 +114,10 @@
    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;
 
@@ -3869,17 +3873,23 @@
   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

Modified: llvm-gcc-4.2/trunk/gcc/objc/objc-act.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/objc/objc-act.c?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/objc/objc-act.c (original)
+++ llvm-gcc-4.2/trunk/gcc/objc/objc-act.c Tue Jul 29 23:41:34 2008
@@ -76,9 +76,11 @@
 #include "langhooks-def.h"
 /* APPLE LOCAL optimization pragmas 3124235/3420242 */
 #include "opts.h"
+/* LLVM LOCAL begin */
 #ifdef ENABLE_LLVM
 #include "llvm.h"               /* for reset_initializer_llvm */
 #endif
+/* LLVM LOCAL end */
 
 #define OBJC_VOID_AT_END	void_list_node
 
@@ -482,6 +484,8 @@
 static const char *default_constant_string_class_name;
 /* APPLE LOCAL radar 4666559 */
 static const struct gcc_debug_hooks *save_default_debug_hooks;
+/* APPLE LOCAL radar 5932809 - copyable byref blocks */
+static int donot_warn_missing_methods;
 
 /* Runtime metadata flags.  */
 #define CLS_FACTORY			0x0001L
@@ -1841,7 +1845,7 @@
          and in accordance with C99 rules we generate: type temp;
          (temp = rhs, [lhs Setter:temp], temp) */
       /* APPLE LOCAL begin radar 5279122 */
-      rhs = default_conversion(rhs);
+      rhs = default_conversion (rhs);
       temp = objc_create_named_tmp_var (TREE_TYPE (rhs), "prop");
       /* APPLE LOCAL end radar 5279122 */
       bind = build3 (BIND_EXPR, void_type_node, temp, NULL, NULL);
@@ -1855,7 +1859,7 @@
     {
       comma_exp = objc_setter_func_call (receiver, prop_ident, rhs);
       /* APPLE LOCAL radar 5279122 */
-      rhs = default_conversion(rhs);
+      rhs = default_conversion (rhs);
       /* APPLE LOCAL radar 5140757 */
       temp = save_expr (rhs);
       /* APPLE LOCAL begin radar 4727191 */
@@ -4005,7 +4009,6 @@
   var = build_decl (VAR_DECL, get_identifier (name), type);
   /* LLVM LOCAL end */
   objc_set_global_decl_fields (var);
-
   return var;
 }
 
@@ -5011,6 +5014,7 @@
 			      build_int_cst (long_integer_type_node, 0));
 
   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
+
   if (flag_next_runtime || ! sel_ref_chain)
     /* APPLE LOCAL LLVM - begin NUL pointer */
     initlist = tree_cons (NULL_TREE,
@@ -5905,6 +5909,7 @@
 
   sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
   decl = start_var_decl (objc_class_type, buf);
+
   return decl;
 }
 
@@ -6198,13 +6203,13 @@
   decl = build_objc_string_decl (section);
 
   type = build_array_type
-    (char_type_node,
-     build_index_type
-     (build_int_cst (NULL_TREE,
-                     IDENTIFIER_LENGTH (ident))));
+	 (char_type_node,
+	  build_index_type
+	  (build_int_cst (NULL_TREE,
+			  IDENTIFIER_LENGTH (ident))));
   decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
   string_expr = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
-                                 IDENTIFIER_POINTER (ident));
+				 IDENTIFIER_POINTER (ident));
   finish_var_decl (decl, string_expr);
 
   /* LLVM LOCAL begin */
@@ -6247,6 +6252,7 @@
   else if (section == prop_names_attr)
     sprintf (buf, "_OBJC_PROP_NAME_ATTR_%d", property_name_attr_idx++);
   /* APPLE LOCAL end C* property metadata (Radar 4498373) */
+
   /* LLVM LOCAL begin */
 #ifdef ENABLE_LLVM
   {
@@ -6262,7 +6268,6 @@
 #endif
   /* LLVM LOCAL end */
 
-
   decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 0;
@@ -6566,6 +6571,7 @@
 /* APPLE LOCAL end radar 4982951 */
 
 /* LLVM LOCAL - begin pointer arithmetic */
+#ifdef ENABLE_LLVM
 /* llvm-gcc intentionally preserves array notation &array[i] and avoids
    pointer arithmetic.
 
@@ -6585,6 +6591,7 @@
   base = TREE_OPERAND(expr, 0);
   return base && TREE_CODE(TREE_TYPE(base)) == ARRAY_TYPE;
 }
+#endif
 /* LLVM LOCAL - end pointer arithmetic */
 
 static tree
@@ -6602,7 +6609,15 @@
 				    newexpr),
 	      DECL_NAME (TREE_OPERAND (expr, 1)));
     /* LLVM LOCAL - begin pointer arithmetic */
+#ifndef ENABLE_LLVM
+    case ARRAY_REF:
+      return build_array_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
+						    oldexpr,
+						    newexpr),
+			      TREE_OPERAND (expr, 1));
+#else
     /* Moved ARRAY_REF to "default" case */
+#endif
     /* LLVM LOCAL - end pointer arithmetic */
     case INDIRECT_REF:
       /* APPLE LOCAL begin radar 4982951 */
@@ -6618,13 +6633,14 @@
 						       newexpr), "->");
     default:
       /* LLVM LOCAL - begin pointer arithmetic */
+#ifdef ENABLE_LLVM
       if (objc_is_really_array_ref(expr))
         return build_array_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
                                                       oldexpr,
                                                       newexpr),
                                 TREE_OPERAND (expr, 1));
+#endif
       /* LLVM LOCAL - end pointer arithmetic */
-
       return expr;
     }
 }
@@ -6906,7 +6922,11 @@
 
   /* Zero in on the variable/parameter being assigned to.  */
   /* LLVM LOCAL - begin pointer arithmetic */
+#ifdef ENABLE_LLVM
   while (TREE_CODE (expr) == COMPONENT_REF || objc_is_really_array_ref(expr))
+#else
+  while (TREE_CODE (expr) == COMPONENT_REF || TREE_CODE (expr) == ARRAY_REF)
+#endif
   /* LLVM LOCAL - end pointer arithmetic */
     expr = TREE_OPERAND (expr, 0);
 
@@ -6959,8 +6979,13 @@
 static int
 objc_is_ivar_reference_p (tree expr)
 {
-  /* LLVM LOCAL pointer arithmetic */
+  /* LLVM LOCAL - begin pointer arithmetic */
+#ifdef ENABLE_LLVM
   return (objc_is_really_array_ref(expr) == 1 
+#else
+  return (TREE_CODE (expr) == ARRAY_REF
+#endif
+  /* LLVM LOCAL - end pointer arithmetic */
 	  ? objc_is_ivar_reference_p (TREE_OPERAND (expr, 0))
 	  : TREE_CODE (expr) == COMPONENT_REF
 	  ? TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL
@@ -7033,8 +7058,13 @@
   /* APPLE LOCAL end radar 4591756 */
   while (outer
 	 && (TREE_CODE (outer) == COMPONENT_REF
-             /* LLVM LOCAL pointer arithmetic */
+             /* LLVM LOCAL - begin pointer arithmetic */
+#ifdef ENABLE_LLVM
              || objc_is_really_array_ref(outer)))
+#else
+	     || TREE_CODE (outer) == ARRAY_REF))
+#endif
+             /* LLVM LOCAL - end pointer arithmetic */
     outer = TREE_OPERAND (outer, 0);
 
   /* APPLE LOCAL objc2 */
@@ -7107,9 +7137,11 @@
     return NULL_TREE;
   /* APPLE LOCAL end radar 4426814 */
 
-  /* LLVM LOCAL 5541393 */
+  /* LLVM LOCAL - begin 5541393 */
+#ifdef ENABLE_LLVM
   if (TREE_CODE(TREE_TYPE(lhs)) != POINTER_TYPE) return NULL_TREE;  
-
+#endif
+  /* LLVM LOCAL - end 5541393 */
   /* APPLE LOCAL begin ObjC GC */
   /* Use the strong-cast write barrier as a last resort.  */
   if (warn_assign_intercept)
@@ -7819,8 +7851,13 @@
       /* APPPLE LOCAL radar 5023725 */
       OBJC_FLAG_ZEROCOST_EXCEPTIONS; 
       /* LLVM local begin */
+#ifdef ENABLE_LLVM
       llvm_eh_personality_libfunc
         = llvm_init_one_libfunc ("__objc_personality_v0");
+#else
+      eh_personality_libfunc
+        = init_one_libfunc ("__objc_personality_v0");
+#endif
       /* LLVM local end */
       default_init_unwind_resume_libfunc ();
       using_eh_for_cleanups ();
@@ -7834,10 +7871,17 @@
     {
       c_eh_initialized_p = true;
       /* LLVM local begin */
+#ifdef ENABLE_LLVM
       llvm_eh_personality_libfunc
 	= llvm_init_one_libfunc (USING_SJLJ_EXCEPTIONS
                                  ? "__gnu_objc_personality_sj0"
                                  : "__gnu_objc_personality_v0");
+#else
+      eh_personality_libfunc
+	= init_one_libfunc (USING_SJLJ_EXCEPTIONS
+			    ? "__gnu_objc_personality_sj0"
+			    : "__gnu_objc_personality_v0");
+#endif
       /* LLVM local end */
       default_init_unwind_resume_libfunc ();
       using_eh_for_cleanups ();
@@ -9394,9 +9438,9 @@
 
       /* APPLE LOCAL LLVM - begin NUL pointer */
       if (refs_decl)
-        refs_expr =
-          convert (build_pointer_type (build_pointer_type (objc_protocol_template)),
-                   build_unary_op (ADDR_EXPR, refs_decl, 0));
+	refs_expr = convert (build_pointer_type (build_pointer_type
+						 (objc_protocol_template)),
+			     build_unary_op (ADDR_EXPR, refs_decl, 0));
       else
         refs_expr =
           convert (build_pointer_type (build_pointer_type (objc_protocol_template)),
@@ -9451,7 +9495,11 @@
       /* Force 4 byte alignment for protocols */
       DECL_ALIGN(decl) = 32;
       DECL_USER_ALIGN(decl) = 1;
+#endif
+
       finish_var_decl (decl, initlist);
+
+#ifdef ENABLE_LLVM
       /* At -O0, we may have emitted references to the decl earlier. */
       if (!optimize)
         reset_initializer_llvm(decl);
@@ -9474,8 +9522,10 @@
   /* APPLE LOCAL begin radar 4533974 - ObjC newprotocol - radar 4695109 */
   /* APPLE LOCAL LLVM - begin NUL pointer */
   if (newabi)
-    /* 'isa' is NULL in the new ObjC abi */
-    expr = convert (objc_object_type, build_int_cst (NULL_TREE, 0));
+    {
+      /* 'isa' is NULL in the new ObjC abi */
+      expr = convert (objc_object_type, build_int_cst (NULL_TREE, 0));
+    }
   /* APPLE LOCAL end radar 4533974 - ObjC newprotocol - radar 4695109 */
   /* APPLE LOCAL begin radar 4585769 - Objective-C 1.0 extensions */
   /* "isa" field now points to struct _objc_protocol_extension * */
@@ -9491,9 +9541,8 @@
                      build_int_cst (NULL_TREE, 0));
         }
       else
-        expr = convert (build_pointer_type (objc_protocol_extension_template),
-                        build_unary_op (ADDR_EXPR,
-                                        objc_protocol_or_opt_ins_meth, 0));
+	expr = convert (build_pointer_type (objc_protocol_extension_template),
+			build_unary_op (ADDR_EXPR, objc_protocol_or_opt_ins_meth, 0));	
     }
   /* APPLE LOCAL LLVM - end NUL pointer */
   /* APPLE LOCAL end radar 4585769 - Objective-C 1.0 extensions */
@@ -9544,24 +9593,24 @@
                               initlist);
         /* APPLE LOCAL LLVM - end NUL pointer */
       else
-        {
-          expr = convert (objc_method_proto_list_ptr,
-                          build_unary_op (ADDR_EXPR, objc_protocol_or_opt_ins_meth, 0));
-          initlist = tree_cons (NULL_TREE, expr, initlist);
-        }
+	{
+	  expr = convert (objc_method_proto_list_ptr,
+			  build_unary_op (ADDR_EXPR, objc_protocol_or_opt_ins_meth, 0));
+	  initlist = tree_cons (NULL_TREE, expr, initlist);
+	}
       if (!opt_cls_meth)
         /* APPLE LOCAL LLVM - begin NUL pointer */
         initlist = tree_cons (NULL_TREE,
                               convert (objc_method_proto_list_ptr,
                                        build_int_cst (NULL_TREE, 0)),
                               initlist);
-         /* APPLE LOCAL LLVM - end NUL pointer */
+        /* APPLE LOCAL LLVM - end NUL pointer */
       else
-        {
-          expr = convert (objc_method_proto_list_ptr,
-                          build_unary_op (ADDR_EXPR, opt_cls_meth, 0));
-          initlist = tree_cons (NULL_TREE, expr, initlist);
-        }
+	{
+	  expr = convert (objc_method_proto_list_ptr,
+			  build_unary_op (ADDR_EXPR, opt_cls_meth, 0));
+	  initlist = tree_cons (NULL_TREE, expr, initlist);
+	}
       /* APPLE LOCAL end radar 4695109 */
       if (!property_list)
         /* APPLE LOCAL LLVM - begin NUL pointer */
@@ -9571,11 +9620,11 @@
                               initlist);
         /* APPLE LOCAL LLVM - end NUL pointer */
       else
-        {
-          expr = convert (objc_prop_list_ptr,
-                          build_unary_op (ADDR_EXPR, property_list, 0));
-          initlist = tree_cons (NULL_TREE, expr, initlist);
-        }
+	{
+	  expr = convert (objc_prop_list_ptr,
+			  build_unary_op (ADDR_EXPR, property_list, 0));
+	  initlist = tree_cons (NULL_TREE, expr, initlist);
+	}
       /* APPLE LOCAL begin radar 5192466 */
       /* const uint32_t size;  = sizeof(struct protocol_t) */
       expr = build_int_cst (
@@ -10578,11 +10627,8 @@
     /* Unnamed bitfields are ignored. */
     if (!DECL_NAME (field_decl))
       {
-        /* LLVM LOCAL begin make sizes add up right */
-        do {
+        do
           field_decl = TREE_CHAIN (field_decl);
-        }
-        /* LLVM LOCAL end */
         while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
         continue;
       }
@@ -10616,7 +10662,7 @@
     obstack_free (&util_obstack, util_firstobj);
 
     /* Set alignment */
-    /* APPLE LOCAL radar 5724385 */
+    /* APPLE LOCAL begin radar 5724385 */
     val = TYPE_ALIGN_UNIT (
             DECL_BIT_FIELD_TYPE (field_decl) ? DECL_BIT_FIELD_TYPE (field_decl) : 
             TREE_TYPE (field_decl));
@@ -10683,10 +10729,10 @@
       obstack_free (&util_obstack, util_firstobj);
 
       /* Set offset.  */
-/* LLVM LOCAL begin make initializer size match type size */
+/* LLVM LOCAL - begin make initializer size match type size */
       ivar = tree_cons (NULL_TREE, convert (integer_type_node,
                                             byte_position (field_decl)), ivar);
-/* LLVM LOCAL end */
+/* LLVM LOCAL - end */
       initlist = tree_cons (NULL_TREE,
 			    objc_build_constructor (type, nreverse (ivar)),
 			    initlist);
@@ -10972,7 +11018,7 @@
   decl = start_var_decl (type, synth_id_with_class_suffix
 			       (name, objc_implementation_context));
 
-  /* LLVM LOCAL begin make initializer size match type size */
+  /* LLVM LOCAL - begin make initializer size match type size */
   /* APPLE LOCAL ObjC new abi */
 #ifdef OBJCPLUS
   initlist = build_tree_list (NULL_TREE,
@@ -10982,7 +11028,7 @@
                               build_int_cst (newabi ? NULL_TREE : ptr_type_node,
 					     init_val));
 #endif
-  /* LLVM LOCAL end */
+  /* LLVM LOCAL - end make initializer size match type size */
   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, size), initlist);
   initlist = tree_cons (NULL_TREE, list, initlist);
 
@@ -11930,7 +11976,7 @@
   else
     {
       expr = convert (objc_v2_ivar_list_ptr,
-		      build_unary_op (ADDR_EXPR, ivars, 0));
+                      build_unary_op (ADDR_EXPR, ivars, 0));
       initlist = tree_cons (NULL_TREE, expr, initlist);
     }
 
@@ -11959,7 +12005,7 @@
   else
     {
       expr = convert (objc_prop_list_ptr,
-		      build_unary_op (ADDR_EXPR, property_list, 0));
+                      build_unary_op (ADDR_EXPR, property_list, 0));
       initlist = tree_cons (NULL_TREE, expr, initlist);
     }
   /* APPLE LOCAL end C* property metadata (Radar 4498373) */
@@ -12030,6 +12076,7 @@
       gcc_assert (TREE_CODE (expr) == PROTOCOL_INTERFACE_TYPE);
       /* APPLE LOCAL begin radar 4695109 */
       /* APPLE LOCAL begin - LLVM radar 5476262 */
+#ifdef ENABLE_LLVM
       /* LLVM LOCAL - add 'L' prefix */
       sprintf (string, "L_OBJC_PROTOCOL_$_%s", 
 	       IDENTIFIER_POINTER (PROTOCOL_NAME (expr)));
@@ -12037,6 +12084,11 @@
       if (expr == NULL_TREE)
         /* LLVM LOCAL - &string[1] because of 'L' prefix */
 	expr = start_var_decl (objc_v2_protocol_template, &string[1]);
+#else
+      sprintf (string, "_OBJC_PROTOCOL_$_%s", 
+	       IDENTIFIER_POINTER (PROTOCOL_NAME (expr)));
+      expr = start_var_decl (objc_v2_protocol_template, string);
+#endif
       /* APPLE LOCAL end - LLVM radar 5476262 */
       /* APPLE LOCAL end radar 4695109 */
       expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
@@ -13311,12 +13363,13 @@
       /* If we are messaging an 'id' or 'Class' object and made it here,
 	 then we have failed to find _any_ instance or class method,
 	 respectively.  */
-      else
+       /* APPLE LOCAL radar 5932809 - copyable byref blocks */
+      else if (!donot_warn_missing_methods)
 	warning (0, "no %<%c%s%> method found",
 		 (class_tree ? '+' : '-'),
 		 IDENTIFIER_POINTER (sel_name));
-
-      if (!warn_missing_methods)
+      /* APPLE LOCAL radar 5932809 - copyable byref blocks */
+      if (!warn_missing_methods && !donot_warn_missing_methods)
 	{
 	  warning (0, "(Messages without a matching method signature");
 	  warning (0, "will be assumed to return %<id%> and accept");
@@ -13352,8 +13405,19 @@
 	      && TREE_TYPE (receiver) == objc_class_type))
 	check_for_nil = false;
 
-      /* LLVM LOCAL pr 1654 */
+      /* LLVM LOCAL - begin PR1654 */
+#ifdef ENABLE_LLVM
       if (aggregate_value_p (ret_type, 0))
+#else
+      if (!targetm.calls.struct_value_rtx (0, 0)
+          && (TREE_CODE (ret_type) == RECORD_TYPE 
+       	      || TREE_CODE (ret_type) == UNION_TYPE)
+          /* APPLE LOCAL begin radar 5080710 */
+          && (TREE_ADDRESSABLE (ret_type)
+              || targetm.calls.return_in_memory (ret_type, 0)))
+          /* APPLE LOCAL end radar 5080710 */
+#endif
+      /* LLVM LOCAL - end PR1654 */
 	{
 	  if (super)
 	    message_func_decl = umsg_id_super2_stret_fixup_decl;
@@ -13633,7 +13697,11 @@
   proto_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL_$", p);
   decl = start_var_decl (objc_v2_protocol_template, proto_name);
   PROTOCOL_V2_FORWARD_DECL (p) = decl;
+  /* APPLE LOCAL begin - LLVM radar 5476262 */
+#ifdef ENABLE_LLVM
   pushdecl_top_level(decl);
+#endif
+  /* APPLE LOCAL end - LLVM radar 5476262 */
 }
 /* APPLE LOCAL end radar 4695109 */
 
@@ -13780,11 +13848,12 @@
   proto_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
   decl = start_var_decl (objc_protocol_template, proto_name);
   /* LLVM LOCAL begin */
+#ifdef ENABLE_LLVM
   /* Force 4 byte alignment for protocols */
   DECL_ALIGN(decl) = 32;
   DECL_USER_ALIGN(decl) = 1;
+#endif
   /* LLVM LOCAL end */
-
   PROTOCOL_FORWARD_DECL (p) = decl;
 }
 
@@ -13974,7 +14043,8 @@
   base = build_indirect_ref (self_decl, "->");
   if ((ivar = objc_v2_build_ivar_ref (base, id)))
     return ivar;
-  return objc_build_component_ref (base, id);
+  else
+    return objc_build_component_ref (base, id);
   /* APPLE LOCAL end ObjC new abi */
 }
 
@@ -18482,7 +18552,6 @@
   DECL_PRESERVE_P (decl) = 1;
 #endif
   /* LLVM LOCAL end */
-
   pushdecl (decl);
   rest_of_decl_compilation (decl, 0, 0);
 
@@ -19487,6 +19556,7 @@
 /* APPLE LOCAL end radar 4985544 - 5195402 */
 
 /* LLVM LOCAL begin */
+#ifdef ENABLE_LLVM
 /* APPLE LOCAL begin radar 2996215 */
 /* Objc wrapper to call libcpp's conversion routine. */
 static bool
@@ -19532,6 +19602,7 @@
   finish_var_decl (decl,  init);
   return decl;
 }
+#endif
 /* APPLE LOCAL end radar 2996215 */
 
 /* APPLE LOCAL begin radar 5202926 */
@@ -19599,5 +19670,64 @@
   return;
 }
 /* APPLE LOCAL end radar 5376125 */
+/* APPLE LOCAL begin radar 5782740 - blocks */
+tree retain_block_component (tree exp)
+{
+  /* APPLE LOCAL begin radar 5932809 - copyable byref blocks */
+  /* We do not want to warn on [id retain] message because we know what we
+   are doing. */
+  tree ret_exp;
+  donot_warn_missing_methods = 1;
+  ret_exp =  objc_finish_message_expr (exp, get_identifier ("retain"), NULL_TREE);
+  donot_warn_missing_methods = 0;
+  return ret_exp;
+  /* APPLE LOCAL end radar 5932809 - copyable byref blocks */
+}
+
+tree release_block_component (tree exp)
+{
+  /* APPLE LOCAL begin radar 5932809 - copyable byref blocks */
+  /* We do not want to warn on [id release] message because we know what we
+     are doing. */
+  tree ret_exp;
+  donot_warn_missing_methods = 1;
+  ret_exp =  objc_finish_message_expr (exp, get_identifier ("release"), NULL_TREE);
+  donot_warn_missing_methods = 0;
+  return ret_exp;
+  /* APPLE LOCAL end radar 5932809 - copyable byref blocks */
+}
+
+/** copy_in_object - This routine for objective-c object pointers, returns
+    [ [EXP retain] autorelease ] expression which is used in initialization
+    of copied in variable used to set up a block literal struct.
+*/
+tree copy_in_object (tree exp)
+{
+/* APPLE LOCAL begin radar 5808305 */
+  return exp;
+#if 0
+  tree msg_exp;
+  tree type = TREE_TYPE (exp);  
+  if (!objc_is_object_ptr (type))
+    return exp;
+  msg_exp = retain_block_component (exp);
+  msg_exp = objc_finish_message_expr (msg_exp, get_identifier ("autorelease"), NULL_TREE);
+  return msg_exp;
+#endif
+/* APPLE LOCAL end radar 5808305 */
+}
 
+bool block_requires_copying (tree exp)
+{
+  return TREE_CODE (TREE_TYPE (exp)) == BLOCK_POINTER_TYPE ||
+	 objc_is_object_ptr (TREE_TYPE (exp));
+}
+/* APPLE LOCAL end radar 5782740 - blocks */
+/* APPLE LOCAL begin radar 5932809 - copyable byref blocks */
+tree cast_to_pointer_to_id (tree exp)
+{
+  tree type = build_pointer_type (objc_object_type);
+  return build_c_cast (type, exp);
+}
+/* APPLE LOCAL end radar 5932809 - copyable byref blocks */
 #include "gt-objc-objc-act.h"

Modified: llvm-gcc-4.2/trunk/gcc/tree.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/tree.h?rev=54196&r1=54195&r2=54196&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/tree.h (original)
+++ llvm-gcc-4.2/trunk/gcc/tree.h Tue Jul 29 23:41:34 2008
@@ -3780,6 +3780,8 @@
 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);





More information about the llvm-commits mailing list