FreeBSD/contrib/gcc/cp/parser.c
/* Parse a block-literal-expr.

 GNU Extension:

 block-literal-expr:
 ^ parameter-declation-clause exception-specification [opt] compound-statement
 ^ block-id compound-statement

 It synthesizes the helper function for later generation and builds
 the necessary data to represent the block literal where it is
 declared.  */
Parse a block-literal-expr.
GNU Extension.



It synthesizes the helper function for later generation and builds
the necessary data to represent the block literal where it is
declared.
Parse a block - literal - expr . GNU Extension . 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;
  cp_parameter_declarator *args = NULL;
  tree arg_type = void_list_node;
  struct block_sema_info *block_impl;
  tree tmp;
  tree restype;
  tree typelist;
  tree helper_function_type;
  tree block;
  tree declared_block_return_type = NULL_TREE;
  tree attributes = NULL_TREE;
  int context_is_nonstatic_method;
  tree raises = NULL_TREE;
  cp_lexer_consume_token (parser->lexer); 
  if (cp_lexer_peek_token (parser->lexer)->keyword == RID_ATTRIBUTE)
      attributes = cp_parser_attributes_opt (parser);
  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
    {
      cp_lexer_consume_token (parser->lexer);
      args = cp_parser_parameter_declaration_clause (parser);
      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
      arg_type = grokparms (args, &arglist);
      if (! args)
      {
	return error_mark_node;
      }
      raises = cp_parser_exception_specification_opt (parser);
    }
  else if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
    {
      tree decl;
      if (attributes)
      {
	warning (0, "attributes before block type are ignored");
	attributes = NULL_TREE;
      }
      decl = cp_parser_block_id (parser);
      if (decl && decl != error_mark_node)
      {
	arg_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
	arglist = DECL_ARGUMENTS (decl);
	raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl));
	declared_block_return_type = TREE_TYPE (TREE_TYPE (decl));
      }
    }
  block = begin_block ();
  context_is_nonstatic_method = (current_function_decl 
				   && DECL_NONSTATIC_MEMBER_FUNCTION_P (current_function_decl));
  if (declared_block_return_type)
    {
      cur_block->return_type  = TYPE_MAIN_VARIANT (declared_block_return_type);
      cur_block->block_has_return_type = true;
    }
  else
      cur_block->return_type = NULL_TREE;
  self_arg = build_artificial_parm (get_identifier (".block_descriptor"), ptr_type_node);
  TREE_CHAIN (self_arg) = arglist;
  arg_type = tree_cons (NULL_TREE, ptr_type_node, arg_type);
  arglist = self_arg;
  push_lang_context (lang_name_c);
  ftype = build_function_type ((!cur_block->block_has_return_type
				  ? void_type_node : cur_block->return_type),
				 arg_type);
  if (raises)
      ftype = build_exception_variant (ftype, raises);
  block_helper_function_decl = build_helper_func_decl (build_block_helper_name (unique_count),
							 ftype);
  DECL_CONTEXT (block_helper_function_decl) = current_function_decl;
  cur_block->helper_func_decl = block_helper_function_decl;
  DECL_ARGUMENTS (block_helper_function_decl) = arglist;
  push_function_context ();
  start_preparsed_function (cur_block->helper_func_decl,
			     NULL_TREE,
			     SF_PRE_PARSED);
  if (cp_lexer_peek_token (parser->lexer)->keyword == RID_ATTRIBUTE)
      attributes = cp_parser_attributes_opt (parser);
  any_recognized_block_attribute (attributes);
  decl_attributes (&cur_block->helper_func_decl, attributes, 0);
  {
      unsigned save = parser->in_statement;
      parser->in_statement = 0;
      stmt = begin_compound_stmt (BCS_FN_BODY);
      cur_block->cp_the_scope = current_binding_level;
      if (context_is_nonstatic_method)
      {
	tree this_decl = lookup_name (this_identifier);
	gcc_assert (this_decl);
	build_block_ref_decl (this_identifier, this_decl);
      }
      cp_parser_compound_statement (parser, NULL, false, false);
      parser->in_statement = save;
  }
  cur_block->block_arg_ptr_type =
    build_pointer_type (build_block_struct_type (cur_block));
  restype = !cur_block->return_type ? void_type_node
  : cur_block->return_type;
  if (restype == error_mark_node)
      return clean_and_exit (block);
  TREE_TYPE (self_arg) = cur_block->block_arg_ptr_type;
  DECL_ARG_TYPE (self_arg) = cur_block->block_arg_ptr_type;
  gcc_assert (TREE_TYPE (DECL_RESULT (current_function_decl))
		== restype);
  cur_block->block_body = stmt;
  block_build_prologue (cur_block);
  finish_compound_stmt (stmt);
  ftype = build_function_type (restype, TREE_CHAIN (arg_type));
  if (raises)
      ftype = build_exception_variant (ftype, raises);
  typelist = TYPE_ARG_TYPES (ftype);
  typelist = tree_cons (NULL_TREE, cur_block->block_arg_ptr_type,
				  typelist);
  helper_function_type = build_function_type (TREE_TYPE (ftype), typelist);
  if (raises)
      helper_function_type = build_exception_variant (helper_function_type, raises);
  TREE_TYPE (cur_block->helper_func_decl) = helper_function_type;
  finish_function (4);
  pop_function_context ();
  if (global_bindings_p ())
      cgraph_finalize_function (cur_block->helper_func_decl, false);
  pop_lang_context ();
  if (cur_block->BlockHasCopyDispose)
  {
      tree s_ftype;
      push_lang_context (lang_name_c);
      s_ftype = build_function_type (void_type_node,
				      tree_cons (NULL_TREE, cur_block->block_arg_ptr_type,
						 tree_cons (NULL_TREE,
							    cur_block->block_arg_ptr_type,
							    void_list_node)));
      sprintf (name, "__copy_helper_block_%d", unique_count);
      cur_block->copy_helper_func_decl =
      build_helper_func_decl (get_identifier (name), s_ftype);
      DECL_CONTEXT (cur_block->copy_helper_func_decl) = current_function_decl;
      synth_copy_helper_block_func (cur_block);
      s_ftype = build_function_type (void_type_node,
					   tree_cons (NULL_TREE,
						      cur_block->block_arg_ptr_type, void_list_node));
      sprintf (name, "__destroy_helper_block_%d", unique_count);
      cur_block->destroy_helper_func_decl =
      build_helper_func_decl (get_identifier (name), s_ftype);
      DECL_CONTEXT (cur_block->destroy_helper_func_decl) = current_function_decl;
      synth_destroy_helper_block_func (cur_block);
      pop_lang_context ();
  }
  block_impl = finish_block (block);
  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;
}
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 ; cp_parameter_declarator * args = NULL ; tree arg_type = void_list_node ; struct block_sema_info * block_impl ; tree tmp ; tree restype ; tree typelist ; tree helper_function_type ; tree block ; tree declared_block_return_type = NULL_TREE ; tree attributes = NULL_TREE ; int context_is_nonstatic_method ; tree raises = NULL_TREE ; cp_lexer_consume_token ( parser -> lexer ) ; if ( cp_lexer_peek_token ( parser -> lexer ) -> keyword == RID_ATTRIBUTE ) attributes = cp_parser_attributes_opt ( parser ) ; if ( cp_lexer_next_token_is ( parser -> lexer , CPP_OPEN_PAREN ) ) { cp_lexer_consume_token ( parser -> lexer ) ; args = cp_parser_parameter_declaration_clause ( parser ) ; cp_parser_require ( parser , CPP_CLOSE_PAREN , " " ) ; arg_type = grokparms ( args , & arglist ) ; if ( ! args ) { return error_mark_node ; } raises = cp_parser_exception_specification_opt ( parser ) ; } else if ( cp_lexer_next_token_is_not ( parser -> lexer , CPP_OPEN_BRACE ) ) { tree decl ; if ( attributes ) { warning ( 0 , " " ) ; attributes = NULL_TREE ; } decl = cp_parser_block_id ( parser ) ; if ( decl && decl != error_mark_node ) { arg_type = TYPE_ARG_TYPES ( TREE_TYPE ( decl ) ) ; arglist = DECL_ARGUMENTS ( decl ) ; raises = TYPE_RAISES_EXCEPTIONS ( TREE_TYPE ( decl ) ) ; declared_block_return_type = TREE_TYPE ( TREE_TYPE ( decl ) ) ; } } block = begin_block ( ) ; context_is_nonstatic_method = ( current_function_decl && DECL_NONSTATIC_MEMBER_FUNCTION_P ( current_function_decl ) ) ; if ( declared_block_return_type ) { cur_block -> return_type = TYPE_MAIN_VARIANT ( declared_block_return_type ) ; cur_block -> block_has_return_type = true ; } else cur_block -> return_type = NULL_TREE ; self_arg = build_artificial_parm ( get_identifier ( " " ) , ptr_type_node ) ; TREE_CHAIN ( self_arg ) = arglist ; arg_type = tree_cons ( NULL_TREE , ptr_type_node , arg_type ) ; arglist = self_arg ; push_lang_context ( lang_name_c ) ; ftype = build_function_type ( ( ! cur_block -> block_has_return_type ? void_type_node : cur_block -> return_type ) , arg_type ) ; if ( raises ) ftype = build_exception_variant ( ftype , raises ) ; block_helper_function_decl = build_helper_func_decl ( build_block_helper_name ( unique_count ) , ftype ) ; DECL_CONTEXT ( block_helper_function_decl ) = current_function_decl ; cur_block -> helper_func_decl = block_helper_function_decl ; DECL_ARGUMENTS ( block_helper_function_decl ) = arglist ; push_function_context ( ) ; start_preparsed_function ( cur_block -> helper_func_decl , NULL_TREE , SF_PRE_PARSED ) ; if ( cp_lexer_peek_token ( parser -> lexer ) -> keyword == RID_ATTRIBUTE ) attributes = cp_parser_attributes_opt ( parser ) ; any_recognized_block_attribute ( attributes ) ; decl_attributes ( & cur_block -> helper_func_decl , attributes , 0 ) ; { unsigned save = parser -> in_statement ; parser -> in_statement = 0 ; stmt = begin_compound_stmt ( BCS_FN_BODY ) ; cur_block -> cp_the_scope = current_binding_level ; if ( context_is_nonstatic_method ) { tree this_decl = lookup_name ( this_identifier ) ; gcc_assert ( this_decl ) ; build_block_ref_decl ( this_identifier , this_decl ) ; } cp_parser_compound_statement ( parser , NULL , false , false ) ; parser -> in_statement = save ; } cur_block -> block_arg_ptr_type = build_pointer_type ( build_block_struct_type ( cur_block ) ) ; restype = ! cur_block -> return_type ? void_type_node : cur_block -> return_type ; if ( restype == error_mark_node ) return clean_and_exit ( block ) ; TREE_TYPE ( self_arg ) = cur_block -> block_arg_ptr_type ; DECL_ARG_TYPE ( self_arg ) = cur_block -> block_arg_ptr_type ; gcc_assert ( TREE_TYPE ( DECL_RESULT ( current_function_decl ) ) == restype ) ; cur_block -> block_body = stmt ; block_build_prologue ( cur_block ) ; finish_compound_stmt ( stmt ) ; ftype = build_function_type ( restype , TREE_CHAIN ( arg_type ) ) ; if ( raises ) ftype = build_exception_variant ( ftype , raises ) ; typelist = TYPE_ARG_TYPES ( ftype ) ; typelist = tree_cons ( NULL_TREE , cur_block -> block_arg_ptr_type , typelist ) ; helper_function_type = build_function_type ( TREE_TYPE ( ftype ) , typelist ) ; if ( raises ) helper_function_type = build_exception_variant ( helper_function_type , raises ) ; TREE_TYPE ( cur_block -> helper_func_decl ) = helper_function_type ; finish_function ( 4 ) ; pop_function_context ( ) ; if ( global_bindings_p ( ) ) cgraph_finalize_function ( cur_block -> helper_func_decl , false ) ; pop_lang_context ( ) ; if ( cur_block -> BlockHasCopyDispose ) { tree s_ftype ; push_lang_context ( lang_name_c ) ; 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 , " " , unique_count ) ; cur_block -> copy_helper_func_decl = build_helper_func_decl ( get_identifier ( name ) , s_ftype ) ; DECL_CONTEXT ( cur_block -> copy_helper_func_decl ) = current_function_decl ; synth_copy_helper_block_func ( cur_block ) ; s_ftype = build_function_type ( void_type_node , tree_cons ( NULL_TREE , cur_block -> block_arg_ptr_type , void_list_node ) ) ; sprintf ( name , " " , unique_count ) ; cur_block -> destroy_helper_func_decl = build_helper_func_decl ( get_identifier ( name ) , s_ftype ) ; DECL_CONTEXT ( cur_block -> destroy_helper_func_decl ) = current_function_decl ; synth_destroy_helper_block_func ( cur_block ) ; pop_lang_context ( ) ; } block_impl = finish_block ( block ) ; sprintf ( name , " " , 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 ; }
Parse a block-literal-expr.
Parse a block - literal - expr .
/* struct c_arg_info *args = NULL; */ /* APPLE LOCAL radar 6185344 */ /* APPLE LOCAL radar 6237713 */ /* APPLE LOCAL radar 6169580 */ /* eat '^' */ /* APPLE LOCAL begin radar 6237713 */ /* APPLE LOCAL end radar 6237713 */ /* Parse the optional argument list */ /* Open the scope to collect parameter decls */ /* push_scope (); */ /* args = c_parser_parms_declarator (parser, true, NULL_TREE); */ /* Parse the parameter-declaration-clause.  */ /* Check for args as it might be NULL due to error. */ /* APPLE LOCAL begin radar 6185344 */ /* Parse user declared return type. */ /* APPLE LOCAL begin radar 6237713 */ /* APPLE LOCAL end radar 6237713 */ /* APPLE LOCAL end radar 6185344 */ /* APPLE LOCAL begin radar 6169580 */ /* APPLE LOCAL end radar 6169580 */ /* cur_block->arg_info = NULL; */ /* APPLE LOCAL begin radar 6185344 */ /* APPLE LOCAL end radar 6185344 */ /* Must also build hidden parameter .block_descriptor added to the helper
     function, even though we do not know its type yet. */ /* APPLE LOCAL radar 6404979 */ /* TREE_CHAIN (self_arg) = cur_block->arg_info->parms; */ /* APPLE LOCAL begin radar 6185344 */ /* Build the declaration of the helper function (if we do not know its result
     type yet, assume it is 'void'. If user provided it, use it).
     Treat this as a nested function and use nested function infrastructure for
     its generation. */ /* APPLE LOCAL end radar 6185344 */ /* APPLE LOCAL radar 6160536 */ /* 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); */ /*attrs*/ /* APPLE LOCAL begin radar 6237713 */ /* APPLE LOCAL radar 6246527 */ /* APPLE LOCAL end radar 6237713 */ /* Start parsing body or expression part of the block literal. */ /* Indicate no valid break/continue context.  We'll notice and
	emit the proper error message in c_finish_bc_stmt.  */ /* Set block's scope to the scope of the helper function's main body.
	This is primarily used when nested blocks are declared. */ /* APPLE LOCAL begin radar 6169580 */ /* APPLE LOCAL end radar 6169580 */ /* Now that we know type of the hidden .block_descriptor argument, fix its type. */ /* The DECL_RESULT should already have the correct type by now.  */ /* add_stmt (fnbody); */ /* We are done parsing of the block body. Return type of block is now known.
     We also know all we need to know about the helper function. So, fix its
   type here. */ /* We moved this here because for global blocks, helper function body is
     not nested and is gimplified in call to finish_function() and return type 
     of the function must be correct. */ /* Declare helper function; as in:
     double helper_1(struct block_1 *ii, int z); */ /* (struct block_1 *ii, int z, ...) */ /* Hum, would be nice if someone else did this for us.  */ /* Build the declaration for copy_helper_block and destroy_helper_block
   helper functions for later use. */ /* void copy_helper_block (struct block*, struct block *); */ /* void destroy_helper_block (struct block*); */ /* Build unqiue name of the temporary used in code gen. */