FreeBSD/contrib/gcc/cp/decl.c
/* Finish up a function declaration and compile that function
   all the way to assembler language output.  The free the storage
   for the function definition.

   FLAGS is a bitwise or of the following values:
     2 - INCLASS_INLINE
       We just finished processing the body of an in-class inline
       function definition.  (This processing will have taken place
       after the class definition is complete.)  */
Finish up a function declaration and compile that function
all the way to assembler language output.  The free the storage
for the function definition.

FLAGS is a bitwise or of the following values:
2 - INCLASS_INLINE
We just finished processing the body of an in-class inline
function definition.  (This processing will have taken place
after the class definition is complete.)
Finish up a function declaration and compile that function all the way to assembler language output . The free the storage for the function definition . FLAGS is a bitwise or of the following values : 2 - INCLASS_INLINE We just finished processing the body of an in - class inline function definition . ( This processing will have taken place after the class definition is complete . )
tree
finish_function (int flags)
{
  tree fndecl = current_function_decl;
  tree fntype, ctype = NULL_TREE;
  int inclass_inline = (flags & 2) != 0;
  int in_blocks_helper_function = (flags & 4) != 0;
  int nested;
  if (fndecl == NULL_TREE)
    return error_mark_node;
  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
      && DECL_VIRTUAL_P (fndecl)
      && !processing_template_decl)
    {
      tree fnclass = DECL_CONTEXT (fndecl);
      if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
	keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
    }
  nested = function_depth > 1;
  fntype = TREE_TYPE (fndecl);
  gcc_assert (building_stmt_tree ());
  gcc_assert (DECL_INITIAL (fndecl) == error_mark_node);
  if (!DECL_CLONED_FUNCTION_P (fndecl))
    {
      if (DECL_MAIN_P (current_function_decl))
	{
	  tree stmt;
#if VMS_TARGET
	  stmt = finish_return_stmt (integer_one_node);
#else
	  stmt = finish_return_stmt (integer_zero_node);
#endif
#ifdef USE_MAPPED_LOCATION
	  SET_EXPR_LOCATION (stmt, UNKNOWN_LOCATION);
#else
	  annotate_with_file_line (stmt, input_filename, 0);
#endif
	}
      if (use_eh_spec_block (current_function_decl))
	finish_eh_spec_block (TYPE_RAISES_EXCEPTIONS
			      (TREE_TYPE (current_function_decl)),
			      current_eh_spec_block);
    }
  DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
  finish_fname_decls ();
  if (!processing_template_decl
      && !cp_function_chain->can_throw
      && !flag_non_call_exceptions
      && !DECL_REPLACEABLE_P (fndecl))
    TREE_NOTHROW (fndecl) = 1;
  if (current_binding_level->kind != sk_function_parms)
    {
      gcc_assert (errorcount);
      DECL_SAVED_TREE (fndecl) = alloc_stmt_list ();
      while (current_binding_level->kind != sk_function_parms)
	{
	  if (current_binding_level->kind == sk_class)
	    pop_nested_class ();
	  else
	    poplevel (0, 0, 0);
	}
    }
  poplevel (1, 0, 1);
  gcc_assert (stmts_are_full_exprs_p ());
  if (current_function_return_value)
    {
      tree r = current_function_return_value;
      tree outer;
      if (r != error_mark_node
	  && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)), fndecl)
	  && (outer = outer_curly_brace_block (fndecl))
	  && chain_member (r, BLOCK_VARS (outer)))
	finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
      current_function_return_value = NULL_TREE;
    }
  if (current_class_name)
    ctype = current_class_type;
  DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
  BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
  if (!processing_template_decl)
    save_function_data (fndecl);
  if (warn_return_type
      && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
      && !dependent_type_p (TREE_TYPE (fntype))
      && !current_function_returns_value && !current_function_returns_null
      && !current_function_returns_abnormally
      && !DECL_NAME (DECL_RESULT (fndecl))
      && (DECL_INLINE (fndecl) || processing_template_decl)
      && !DECL_CONSTRUCTOR_P (fndecl)
      && !DECL_DESTRUCTOR_P (fndecl))
    warning (OPT_Wreturn_type, "no return statement in function returning non-void");
  cfun->function_end_locus = input_location;
  if (!processing_template_decl)
    {
      struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
      cp_genericize (fndecl);
      f->x_current_class_ptr = NULL;
      f->x_current_class_ref = NULL;
      f->x_eh_spec_block = NULL;
      f->x_in_charge_parm = NULL;
      f->x_vtt_parm = NULL;
      f->x_return_value = NULL;
      f->bindings = NULL;
      f->extern_decl_map = NULL;
      c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
    }
  local_names = NULL;
  cfun = NULL;
  current_function_decl = NULL;
  if (inclass_inline)
    maybe_end_member_template_processing ();
  if (ctype && !in_blocks_helper_function)
    pop_nested_class ();
  --function_depth;
  if (! nested)
    current_function_decl = NULL_TREE;
  return fndecl;
}
tree finish_function ( int flags ) { tree fndecl = current_function_decl ; tree fntype , ctype = NULL_TREE ; int inclass_inline = ( flags & 2 ) != 0 ; int in_blocks_helper_function = ( flags & 4 ) != 0 ; int nested ; if ( fndecl == NULL_TREE ) return error_mark_node ; if ( DECL_NONSTATIC_MEMBER_FUNCTION_P ( fndecl ) && DECL_VIRTUAL_P ( fndecl ) && ! processing_template_decl ) { tree fnclass = DECL_CONTEXT ( fndecl ) ; if ( fndecl == CLASSTYPE_KEY_METHOD ( fnclass ) ) keyed_classes = tree_cons ( NULL_TREE , fnclass , keyed_classes ) ; } nested = function_depth > 1 ; fntype = TREE_TYPE ( fndecl ) ; gcc_assert ( building_stmt_tree ( ) ) ; gcc_assert ( DECL_INITIAL ( fndecl ) == error_mark_node ) ; if ( ! DECL_CLONED_FUNCTION_P ( fndecl ) ) { if ( DECL_MAIN_P ( current_function_decl ) ) { tree stmt ; #if VMS_TARGET stmt = finish_return_stmt ( integer_one_node ) ; #else stmt = finish_return_stmt ( integer_zero_node ) ; #endif #ifdef USE_MAPPED_LOCATION SET_EXPR_LOCATION ( stmt , UNKNOWN_LOCATION ) ; #else annotate_with_file_line ( stmt , input_filename , 0 ) ; #endif } if ( use_eh_spec_block ( current_function_decl ) ) finish_eh_spec_block ( TYPE_RAISES_EXCEPTIONS ( TREE_TYPE ( current_function_decl ) ) , current_eh_spec_block ) ; } DECL_SAVED_TREE ( fndecl ) = pop_stmt_list ( DECL_SAVED_TREE ( fndecl ) ) ; finish_fname_decls ( ) ; if ( ! processing_template_decl && ! cp_function_chain -> can_throw && ! flag_non_call_exceptions && ! DECL_REPLACEABLE_P ( fndecl ) ) TREE_NOTHROW ( fndecl ) = 1 ; if ( current_binding_level -> kind != sk_function_parms ) { gcc_assert ( errorcount ) ; DECL_SAVED_TREE ( fndecl ) = alloc_stmt_list ( ) ; while ( current_binding_level -> kind != sk_function_parms ) { if ( current_binding_level -> kind == sk_class ) pop_nested_class ( ) ; else poplevel ( 0 , 0 , 0 ) ; } } poplevel ( 1 , 0 , 1 ) ; gcc_assert ( stmts_are_full_exprs_p ( ) ) ; if ( current_function_return_value ) { tree r = current_function_return_value ; tree outer ; if ( r != error_mark_node && aggregate_value_p ( TREE_TYPE ( TREE_TYPE ( fndecl ) ) , fndecl ) && ( outer = outer_curly_brace_block ( fndecl ) ) && chain_member ( r , BLOCK_VARS ( outer ) ) ) finalize_nrv ( & DECL_SAVED_TREE ( fndecl ) , r , DECL_RESULT ( fndecl ) ) ; current_function_return_value = NULL_TREE ; } if ( current_class_name ) ctype = current_class_type ; DECL_CONTEXT ( DECL_RESULT ( fndecl ) ) = fndecl ; BLOCK_SUPERCONTEXT ( DECL_INITIAL ( fndecl ) ) = fndecl ; if ( ! processing_template_decl ) save_function_data ( fndecl ) ; if ( warn_return_type && TREE_CODE ( TREE_TYPE ( fntype ) ) != VOID_TYPE && ! dependent_type_p ( TREE_TYPE ( fntype ) ) && ! current_function_returns_value && ! current_function_returns_null && ! current_function_returns_abnormally && ! DECL_NAME ( DECL_RESULT ( fndecl ) ) && ( DECL_INLINE ( fndecl ) || processing_template_decl ) && ! DECL_CONSTRUCTOR_P ( fndecl ) && ! DECL_DESTRUCTOR_P ( fndecl ) ) warning ( OPT_Wreturn_type , " " ) ; cfun -> function_end_locus = input_location ; if ( ! processing_template_decl ) { struct language_function * f = DECL_SAVED_FUNCTION_DATA ( fndecl ) ; cp_genericize ( fndecl ) ; f -> x_current_class_ptr = NULL ; f -> x_current_class_ref = NULL ; f -> x_eh_spec_block = NULL ; f -> x_in_charge_parm = NULL ; f -> x_vtt_parm = NULL ; f -> x_return_value = NULL ; f -> bindings = NULL ; f -> extern_decl_map = NULL ; c_warn_unused_result ( & DECL_SAVED_TREE ( fndecl ) ) ; } local_names = NULL ; cfun = NULL ; current_function_decl = NULL ; if ( inclass_inline ) maybe_end_member_template_processing ( ) ; if ( ctype && ! in_blocks_helper_function ) pop_nested_class ( ) ; -- function_depth ; if ( ! nested ) current_function_decl = NULL_TREE ; return fndecl ; }
Finish up a function declaration and compile that function
all the way to assembler language output.
Finish up a function declaration and compile that function all the way to assembler language output .
/* APPLE LOCAL radar 6169580 */ /* When we get some parse errors, we can end up without a
     current_function_decl, so cope.  */ /*  TREE_READONLY (fndecl) = 1;
      This caused &foo to be of type ptr-to-const-function
      which then got a warning when stored in a ptr-to-function variable.  */ /* The current function is being defined, so its DECL_INITIAL should
     be set, and unless there's a multiple definition, it should be
     error_mark_node.  */ /* For a cloned function, we've already got all the code we need;
     there's no need to add any extra bits.  */ /* Make it so that `main' always returns 0 by default (or
	     1 for VMS).  */ /* Hack.  We don't want the middle-end to warn that this
	     return is unreachable, so put the statement on the
	     special line 0.  */ /* If we're saving up tree structure, tie off the function now.  */ /* If this function can't throw any exceptions, remember that.  */ /* This must come after expand_function_end because cleanups might
     have declarations (from inline functions) that need to go into
     this function's blocks.  */ /* If the current binding level isn't the outermost binding level
     for this function, either there is a bug, or we have experienced
     syntax errors and the statement tree is malformed.  */ /* Make sure we have already experienced errors.  */ /* Throw away the broken statement tree and extra binding
	 levels.  */ /* Statements should always be full-expressions at the outermost set
     of curly braces for a function.  */ /* Set up the named return value optimization, if we can.  Candidate
     variables are selected in check_return_expr.  */ /* This is only worth doing for fns that return in memory--and
	     simpler, since we don't have to worry about promoted modes.  */ /* Only allow this for variables declared in the outer scope of
	     the function so we know that their lifetime always ends with a
	     return; see g++.dg/opt/nrv6.C.  We could be more flexible if
	     we were to do this optimization in tree-ssa.  */ /* Remember that we were in class scope.  */ /* Must mark the RESULT_DECL as being in this function.  */ /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point
     to the FUNCTION_DECL node itself.  */ /* Save away current state, if appropriate.  */ /* Complain if there's just no return statement.  */ /* Don't complain if we abort or throw.  */ /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
	 inline function, as we might never be compiled separately.  */ /* Structor return values (if any) are set by the compiler.  */ /* Store the end of the function, so that we get good line number
     info for the epilogue.  */ /* Genericize before inlining.  */ /* Clear out the bits we don't need.  */ /* Handle attribute((warn_unused_result)).  Relies on gimple input.  */ /* Clear out the bits we don't need.  */ /* We're leaving the context of this function, so zap cfun.  It's still in
     DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation.  */ /* If this is an in-class inline definition, we may have to pop the
     bindings for the template parameters that we added in
     maybe_begin_member_template_processing when start_function was
     called.  */ /* Leave the scope of the class.  */ /* APPLE LOCAL radar 6169580 */ /* Clean up.  */ /* Let the error reporting routines know that we're outside a
       function.  For a nested function, this value is used in
       cxx_pop_function_context and then reset via pop_function_context.  */