summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/semantics.c')
-rw-r--r--contrib/gcc/cp/semantics.c179
1 files changed, 175 insertions, 4 deletions
diff --git a/contrib/gcc/cp/semantics.c b/contrib/gcc/cp/semantics.c
index c234e25..d377ad7 100644
--- a/contrib/gcc/cp/semantics.c
+++ b/contrib/gcc/cp/semantics.c
@@ -1943,6 +1943,18 @@ finish_this_expr (void)
error ("%<this%> is unavailable for static member functions");
result = error_mark_node;
}
+ /* APPLE LOCAL begin radar 6275956 */
+ else if (cur_block && current_function_decl
+ && BLOCK_SYNTHESIZED_FUNC (current_function_decl))
+ {
+ result = lookup_name (this_identifier);
+ if (!result)
+ {
+ error ("invalid use of %<this%> in a block");
+ result = error_mark_node;
+ }
+ }
+ /* APPLE LOCAL end radar 6275956 */
else
{
if (current_function_decl)
@@ -2470,6 +2482,82 @@ baselink_for_fns (tree fns)
return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE);
}
+/* APPLE LOCAL begin blocks 6040305 */
+static bool
+block_var_ok_for_context (tree context)
+{
+ /* FIXME - local classes inside blocks, templates, etc */
+ struct block_sema_info *b = cur_block;
+ tree decl = current_function_decl;
+
+ /* If in a block helper, only variables from the context of the helper
+ are ok. */
+ while (b && b->helper_func_decl == decl)
+ {
+ if (context == DECL_CONTEXT (decl))
+ return true;
+ decl = DECL_CONTEXT (decl);
+ b = b->prev_block_info;
+ }
+
+ return false;
+}
+
+/* APPLE LOCAL begin radar 6545782 */
+/** This routine does all the work on use of variables in a block. */
+static tree get_final_block_variable (tree name, tree var) {
+ tree decl = var;
+
+ if (cur_block
+ && (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == PARM_DECL)
+ && !lookup_name_in_block (name, &decl))
+ {
+ bool gdecl;
+ /* We are referencing a variable inside a block whose
+ declaration is outside. */
+ gcc_assert (decl &&
+ (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == PARM_DECL));
+ gdecl = (TREE_CODE (decl) == VAR_DECL &&
+ (DECL_EXTERNAL (decl) || TREE_STATIC (decl)));
+ /* Treat all 'global' variables as 'byref' by default. */
+ if (gdecl
+ || (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl)))
+ {
+ /* byref globals are directly accessed. */
+ /* APPLE LOCAL begin radar 7760213 */
+ if (!gdecl) {
+ if (HasByrefArray(TREE_TYPE (decl)))
+ error ("cannot access __block variable of array type inside block");
+ /* build a decl for the byref variable. */
+ decl = build_block_byref_decl (name, decl, decl);
+ }
+ /* APPLE LOCAL end radar 7760213 */
+ else
+ add_block_global_byref_list (decl);
+ }
+ else
+ {
+ /* 'byref' globals are never copied-in. So, do not add
+ them to the copied-in list. */
+ if (!in_block_global_byref_list (decl)) {
+ /* APPLE LOCAL begin radar 7721728 */
+ if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ error ("cannot access copied-in variable of array type inside block");
+ /* APPLE LOCAL end radar 7721728 */
+ /* build a new decl node. set its type to 'const' type
+ of the old decl. */
+ decl = build_block_ref_decl (name, decl);
+ }
+ }
+ }
+ return decl;
+}
+/* APPLE LOCAL end radar 6545782 */
+
+/* APPLE LOCAL end blocks 6040305 */
+
/* ID_EXPRESSION is a representation of parsed, but unprocessed,
id-expression. (See cp_parser_id_expression for details.) SCOPE,
if non-NULL, is the type or namespace used to explicitly qualify
@@ -2536,6 +2624,7 @@ finish_id_expression (tree id_expression,
if (decl == error_mark_node)
{
/* Name lookup failed. */
+
if (scope
&& (!TYPE_P (scope)
|| (!dependent_type_p (scope)
@@ -2576,7 +2665,10 @@ finish_id_expression (tree id_expression,
{
tree context = decl_function_context (decl);
if (context != NULL_TREE && context != current_function_decl
- && ! TREE_STATIC (decl))
+ /* APPLE LOCAL begin blocks 6040305 */
+ && ! TREE_STATIC (decl)
+ && !block_var_ok_for_context (context))
+ /* APPLE LOCAL end blocks 6040305 */
{
error (TREE_CODE (decl) == VAR_DECL
? "use of %<auto%> variable from containing function"
@@ -2852,8 +2944,21 @@ finish_id_expression (tree id_expression,
Access checking has been performed during name lookup
already. Turn off checking to avoid duplicate errors. */
push_deferring_access_checks (dk_no_check);
- decl = finish_non_static_data_member (decl, current_class_ref,
- /*qualifying_scope=*/NULL_TREE);
+ /* APPLE LOCAL begin radar 6169580 */
+ if (cur_block)
+ {
+ tree exp;
+ tree this_copiedin_var = lookup_name (this_identifier);
+ gcc_assert (!current_class_ref);
+ gcc_assert (this_copiedin_var);
+ exp = build_x_arrow (this_copiedin_var);
+ decl = build_class_member_access_expr (exp, decl, TREE_TYPE (exp),
+ /*preserve_reference=*/false);
+ }
+ else
+ decl = finish_non_static_data_member (decl, current_class_ref,
+ /*qualifying_scope=*/NULL_TREE);
+ /* APPLE LOCAL end radar 6169580 */
pop_deferring_access_checks ();
}
else if (is_overloaded_fn (decl))
@@ -2894,7 +2999,8 @@ finish_id_expression (tree id_expression,
path = currently_open_derived_class (DECL_CONTEXT (decl));
perform_or_defer_access_check (TYPE_BINFO (path), decl, decl);
}
-
+ /* APPLE LOCAL radar 6545782 */
+ decl = get_final_block_variable (id_expression, decl);
decl = convert_from_reference (decl);
}
}
@@ -2902,6 +3008,30 @@ finish_id_expression (tree id_expression,
if (TREE_DEPRECATED (decl))
warn_deprecated_use (decl);
+ /* APPLE LOCAL begin blocks 6040305 (cd) */
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ if (BLOCK_DECL_BYREF (decl))
+ {
+ tree orig_decl = decl;
+ decl = build_indirect_ref (decl, "unary *");
+ if (COPYABLE_BYREF_LOCAL_VAR (orig_decl))
+ {
+ /* What we have is an expression which is of type
+ struct __Block_byref_X. Must get to the value of the variable
+ embedded in this structure. It is at:
+ __Block_byref_X.__forwarding->x */
+ decl = build_byref_local_var_access (decl,
+ DECL_NAME (orig_decl));
+ }
+ }
+ else
+ if (COPYABLE_BYREF_LOCAL_VAR (decl))
+ decl = build_byref_local_var_access (decl,
+ DECL_NAME (decl));
+ }
+ /* APPLE LOCAL end blocks 6040305 (cd) */
+
return decl;
}
@@ -3173,6 +3303,11 @@ expand_or_defer_fn (tree fn)
it. */
if (maybe_clone_body (fn))
{
+ /* APPLE LOCAL begin radar 6305545 */
+ /* Must lower the nested functions which could be, among other
+ things, block helper functions. */
+ lower_if_nested_functions (fn);
+ /* APPLE LOCAL end radar 6305545 */
/* We don't want to process FN again, so pretend we've written
it out, even though we haven't. */
TREE_ASM_WRITTEN (fn) = 1;
@@ -3965,6 +4100,42 @@ cxx_omp_predetermined_sharing (tree decl)
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
+
+/* APPLE LOCAL begin blocks 6040305 (ch) */
+tree
+begin_block (void)
+{
+ struct block_sema_info *csi;
+ tree block;
+ /* push_scope (); */
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+#if 0
+ block = do_pushlevel (sk_block);
+#else
+ block = NULL_TREE;
+#endif
+ csi = (struct block_sema_info*)xcalloc (1, sizeof (struct block_sema_info));
+ csi->prev_block_info = cur_block;
+ cur_block = csi;
+ return block;
+}
+
+struct block_sema_info *
+finish_block (tree block)
+{
+ struct block_sema_info *csi = cur_block;
+ cur_block = cur_block->prev_block_info;
+ /* pop_scope (); */
+#if 0
+ if (block)
+ do_poplevel (block);
+#else
+ block = 0;
+#endif
+ return csi;
+}
+/* APPLE LOCAL end blocks 6040305 (ch) */
+
void
init_cp_semantics (void)
OpenPOWER on IntegriCloud