FreeBSD/contrib/gcc/cp/parser.c
/**
 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.
 */
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.
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;
  tree type, exp;
  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) {
	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);
		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)
		{
			abort ();
		}
		gcc_assert (b);
		gcc_assert (BINDING_VALUE (b));
		gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL 
					|| TREE_CODE (BINDING_VALUE (b)) == PARM_DECL);
		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)
		{
			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; 
	}
      }
  }
  exp = decl;
  type = TREE_TYPE (exp);
  if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == FUNCTION_TYPE) {
      exp = decay_conversion (exp);
      type = TREE_TYPE (exp);
  }
  ref_decl = build_decl (VAR_DECL, name,
			  build_qualified_type (type, TYPE_QUAL_CONST));
  DECL_SOURCE_LOCATION (ref_decl) = DECL_SOURCE_LOCATION 
  (cur_block->helper_func_decl);
  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;
  {
      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, false);
      add_decl_expr (ref_decl);
  }
  cur_block->block_ref_decl_list =
    tree_cons (NULL_TREE, ref_decl, cur_block->block_ref_decl_list);
  cur_block->block_original_ref_decl_list =
    tree_cons (NULL_TREE, exp, cur_block->block_original_ref_decl_list);
  return ref_decl;
}
tree build_block_ref_decl ( tree name , tree decl ) { tree ref_decl ; tree type , exp ; 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 ) { 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 ) ; 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 ) { abort ( ) ; } gcc_assert ( b ) ; gcc_assert ( BINDING_VALUE ( b ) ) ; gcc_assert ( TREE_CODE ( BINDING_VALUE ( b ) ) == VAR_DECL || TREE_CODE ( BINDING_VALUE ( b ) ) == PARM_DECL ) ; 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 ) { 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 ; } } } exp = decl ; type = TREE_TYPE ( exp ) ; if ( TREE_CODE ( type ) == ARRAY_TYPE || TREE_CODE ( type ) == FUNCTION_TYPE ) { exp = decay_conversion ( exp ) ; type = TREE_TYPE ( exp ) ; } ref_decl = build_decl ( VAR_DECL , name , build_qualified_type ( type , TYPE_QUAL_CONST ) ) ; DECL_SOURCE_LOCATION ( ref_decl ) = DECL_SOURCE_LOCATION ( cur_block -> helper_func_decl ) ; 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 ; { 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 , false ) ; add_decl_expr ( ref_decl ) ; } cur_block -> block_ref_decl_list = tree_cons ( NULL_TREE , ref_decl , cur_block -> block_ref_decl_list ) ; cur_block -> block_original_ref_decl_list = tree_cons ( NULL_TREE , exp , cur_block -> block_original_ref_decl_list ) ; return ref_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.
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 .
/* FIXME - Broken, should be found via objc runtime testcases.  */ /* FIXME - Don't use DECL_CONTEXT on any helpers */ /* APPLE LOCAL radar 6212722 */ /* 'decl' was previously declared as __block.  Simply, copy the value
     embedded in the above variable. */ /* 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.  */ /* Find the first declaration not in current block. */ /* FIXME: This can't happen?!  */ /* b = b->previous; */ /* Is the next declaration not in the enclosing block? */ /* 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?  */ /* APPLE LOCAL begin radar 6212722 */ /* APPLE LOCAL end radar 6212722 */ /* APPLE LOCAL begin radar 6144664  */ /* APPLE LOCAL end radar 6144664  */ /* 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. */ /*is_friend=*/ /* APPLE LOCAL radar 6169527 */ /* APPLE LOCAL radar 6212722 */