FreeBSD/contrib/gcc/c-decl.c
/* 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
   to debug info generation.  */
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
to debug info generation.
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 to debug info generation .
tree
pop_scope (void)
{
  struct c_scope *scope = current_scope;
  tree block, context, p;
  struct c_binding *b;
  bool functionbody = scope->function_body;
  bool keep = functionbody || scope->keep || scope->bindings;
  c_end_vm_scope (scope->depth);
  block = 0;
  if (keep)
    {
      block = make_node (BLOCK);
      BLOCK_SUBBLOCKS (block) = scope->blocks;
      TREE_USED (block) = 1;
      for (p = scope->blocks; p; p = TREE_CHAIN (p))
	BLOCK_SUPERCONTEXT (p) = block;
      BLOCK_VARS (block) = 0;
    }
  if (scope->function_body)
    context = current_function_decl;
  else if (scope == file_scope)
    {
      tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0);
      TREE_CHAIN (file_decl) = all_translation_units;
      all_translation_units = file_decl;
      context = file_decl;
    }
  else
    context = block;
  for (b = scope->bindings; b; b = free_binding_and_advance (b))
    {
      p = b->decl;
      switch (TREE_CODE (p))
	{
	case LABEL_DECL:
	  if (TREE_USED (p) && !DECL_INITIAL (p))
	    {
	      error ("label %q+D used but not defined", p);
	      DECL_INITIAL (p) = error_mark_node;
	    }
	  else if (!TREE_USED (p) && warn_unused_label)
	    {
	      if (DECL_INITIAL (p))
		warning (0, "label %q+D defined but not used", p);
	      else
		warning (0, "label %q+D declared but not defined", p);
	    }
	  TREE_CHAIN (p) = BLOCK_VARS (block);
	  BLOCK_VARS (block) = p;
	  gcc_assert (I_LABEL_BINDING (b->id) == b);
	  I_LABEL_BINDING (b->id) = b->shadowed;
	  break;
	case ENUMERAL_TYPE:
	case UNION_TYPE:
	case RECORD_TYPE:
	  set_type_context (p, context);
	  if (b->id)
	    {
	      gcc_assert (I_TAG_BINDING (b->id) == b);
	      I_TAG_BINDING (b->id) = b->shadowed;
	    }
	  break;
	case FUNCTION_DECL:
	  if (!TREE_ASM_WRITTEN (p)
	      && DECL_INITIAL (p) != 0
	      && TREE_ADDRESSABLE (p)
	      && DECL_ABSTRACT_ORIGIN (p) != 0
	      && DECL_ABSTRACT_ORIGIN (p) != p)
	    TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
	  if (!DECL_EXTERNAL (p)
	      && DECL_INITIAL (p) == 0
	      && scope != file_scope
	      && scope != external_scope)
	    {
	      error ("nested function %q+D declared but never defined", p);
	      undef_nested_function = true;
	    }
	  else if (DECL_DECLARED_INLINE_P (p)
		   && TREE_PUBLIC (p)
		   && !DECL_INITIAL (p)
		   && !flag_gnu89_inline)
	    pedwarn ("inline function %q+D declared but never defined", p);
	  goto common_symbol;
	case VAR_DECL:
	  if (!TREE_USED (p)
	      && !TREE_NO_WARNING (p)
	      && !DECL_IN_SYSTEM_HEADER (p)
	      && DECL_NAME (p)
	      && !DECL_ARTIFICIAL (p)
	      && scope != file_scope
	      && scope != external_scope)
	    warning (OPT_Wunused_variable, "unused variable %q+D", p);
	  if (b->inner_comp)
	    {
	      error ("type of array %q+D completed incompatibly with"
		     " implicit initialization", p);
	    }
	case TYPE_DECL:
	case CONST_DECL:
	common_symbol:
	  if (!b->nested)
	    {
	      TREE_CHAIN (p) = BLOCK_VARS (block);
	      BLOCK_VARS (block) = p;
	    }
	  if (scope == file_scope && num_in_fnames > 1)
	    {
	      DECL_CONTEXT (p) = context;
	      if (TREE_CODE (p) == TYPE_DECL)
		set_type_context (TREE_TYPE (p), context);
	    }
	case PARM_DECL:
	case ERROR_MARK:
	  if (b->id)
	    {
	      gcc_assert (I_SYMBOL_BINDING (b->id) == b);
	      I_SYMBOL_BINDING (b->id) = b->shadowed;
	      if (b->shadowed && b->shadowed->type)
		TREE_TYPE (b->shadowed->decl) = b->shadowed->type;
	    }
	  break;
	default:
	  gcc_unreachable ();
	}
    }
  if ((scope->function_body || scope == file_scope) && context)
    {
      DECL_INITIAL (context) = block;
      BLOCK_SUPERCONTEXT (block) = context;
    }
  else if (scope->outer)
    {
      if (block)
	SCOPE_LIST_APPEND (scope->outer, blocks, block);
      else if (scope->blocks)
	SCOPE_LIST_CONCAT (scope->outer, blocks, scope, blocks);
    }
  current_scope = scope->outer;
  if (scope->function_body)
    current_function_scope = scope->outer_function;
  memset (scope, 0, sizeof (struct c_scope));
  scope->outer = scope_freelist;
  scope_freelist = scope;
  return block;
}
tree pop_scope ( void ) { struct c_scope * scope = current_scope ; tree block , context , p ; struct c_binding * b ; bool functionbody = scope -> function_body ; bool keep = functionbody || scope -> keep || scope -> bindings ; c_end_vm_scope ( scope -> depth ) ; block = 0 ; if ( keep ) { block = make_node ( BLOCK ) ; BLOCK_SUBBLOCKS ( block ) = scope -> blocks ; TREE_USED ( block ) = 1 ; for ( p = scope -> blocks ; p ; p = TREE_CHAIN ( p ) ) BLOCK_SUPERCONTEXT ( p ) = block ; BLOCK_VARS ( block ) = 0 ; } if ( scope -> function_body ) context = current_function_decl ; else if ( scope == file_scope ) { tree file_decl = build_decl ( TRANSLATION_UNIT_DECL , 0 , 0 ) ; TREE_CHAIN ( file_decl ) = all_translation_units ; all_translation_units = file_decl ; context = file_decl ; } else context = block ; for ( b = scope -> bindings ; b ; b = free_binding_and_advance ( b ) ) { p = b -> decl ; switch ( TREE_CODE ( p ) ) { case LABEL_DECL : if ( TREE_USED ( p ) && ! DECL_INITIAL ( p ) ) { error ( " " , p ) ; DECL_INITIAL ( p ) = error_mark_node ; } else if ( ! TREE_USED ( p ) && warn_unused_label ) { if ( DECL_INITIAL ( p ) ) warning ( 0 , " " , p ) ; else warning ( 0 , " " , p ) ; } TREE_CHAIN ( p ) = BLOCK_VARS ( block ) ; BLOCK_VARS ( block ) = p ; gcc_assert ( I_LABEL_BINDING ( b -> id ) == b ) ; I_LABEL_BINDING ( b -> id ) = b -> shadowed ; break ; case ENUMERAL_TYPE : case UNION_TYPE : case RECORD_TYPE : set_type_context ( p , context ) ; if ( b -> id ) { gcc_assert ( I_TAG_BINDING ( b -> id ) == b ) ; I_TAG_BINDING ( b -> id ) = b -> shadowed ; } break ; case FUNCTION_DECL : if ( ! TREE_ASM_WRITTEN ( p ) && DECL_INITIAL ( p ) != 0 && TREE_ADDRESSABLE ( p ) && DECL_ABSTRACT_ORIGIN ( p ) != 0 && DECL_ABSTRACT_ORIGIN ( p ) != p ) TREE_ADDRESSABLE ( DECL_ABSTRACT_ORIGIN ( p ) ) = 1 ; if ( ! DECL_EXTERNAL ( p ) && DECL_INITIAL ( p ) == 0 && scope != file_scope && scope != external_scope ) { error ( " " , p ) ; undef_nested_function = true ; } else if ( DECL_DECLARED_INLINE_P ( p ) && TREE_PUBLIC ( p ) && ! DECL_INITIAL ( p ) && ! flag_gnu89_inline ) pedwarn ( " " , p ) ; goto common_symbol ; case VAR_DECL : if ( ! TREE_USED ( p ) && ! TREE_NO_WARNING ( p ) && ! DECL_IN_SYSTEM_HEADER ( p ) && DECL_NAME ( p ) && ! DECL_ARTIFICIAL ( p ) && scope != file_scope && scope != external_scope ) warning ( OPT_Wunused_variable , " " , p ) ; if ( b -> inner_comp ) { error ( " " " " , p ) ; } case TYPE_DECL : case CONST_DECL : common_symbol : if ( ! b -> nested ) { TREE_CHAIN ( p ) = BLOCK_VARS ( block ) ; BLOCK_VARS ( block ) = p ; } if ( scope == file_scope && num_in_fnames > 1 ) { DECL_CONTEXT ( p ) = context ; if ( TREE_CODE ( p ) == TYPE_DECL ) set_type_context ( TREE_TYPE ( p ) , context ) ; } case PARM_DECL : case ERROR_MARK : if ( b -> id ) { gcc_assert ( I_SYMBOL_BINDING ( b -> id ) == b ) ; I_SYMBOL_BINDING ( b -> id ) = b -> shadowed ; if ( b -> shadowed && b -> shadowed -> type ) TREE_TYPE ( b -> shadowed -> decl ) = b -> shadowed -> type ; } break ; default : gcc_unreachable ( ) ; } } if ( ( scope -> function_body || scope == file_scope ) && context ) { DECL_INITIAL ( context ) = block ; BLOCK_SUPERCONTEXT ( block ) = context ; } else if ( scope -> outer ) { if ( block ) SCOPE_LIST_APPEND ( scope -> outer , blocks , block ) ; else if ( scope -> blocks ) SCOPE_LIST_CONCAT ( scope -> outer , blocks , scope , blocks ) ; } current_scope = scope -> outer ; if ( scope -> function_body ) current_function_scope = scope -> outer_function ; memset ( scope , 0 , sizeof ( struct c_scope ) ) ; scope -> outer = scope_freelist ; scope_freelist = scope ; return block ; }
Exit a scope.
Exit a scope .
/* If appropriate, create a BLOCK to record the decls for the life
     of this function.  */ /* In each subblock, record that this is its superior.  */ /* The TYPE_CONTEXTs for all of the tagged types belonging to this
     scope must be set so that they point to the appropriate
     construct, i.e.  either to the current FUNCTION_DECL node, or
     else to the BLOCK node we just constructed.

     Note that for tagged types whose scope is just the formal
     parameter list for some function type specification, we can't
     properly set their TYPE_CONTEXTs here, because we don't have a
     pointer to the appropriate FUNCTION_TYPE node readily available
     to us.  For those cases, the TYPE_CONTEXTs of the relevant tagged
     type nodes get set in `grokdeclarator' as soon as we have created
     the FUNCTION_TYPE node which will represent the "scope" for these
     "parameter list local" tagged types.  */ /* Clear all bindings in this scope.  */ /* Warnings for unused labels, errors for undefined labels.  */ /* Labels go in BLOCK_VARS.  */ /* Types may not have tag-names, in which case the type
	     appears in the bindings list with b->id NULL.  */ /* Propagate TREE_ADDRESSABLE from nested functions to their
	     containing functions.  */ /* C99 6.7.4p6: "a function with external linkage... declared
	     with an inline function specifier ... shall also be defined in the
	     same translation unit."  */ /* Warnings for unused variables.  */ /* Fall through.  */ /* All of these go in BLOCK_VARS, but only if this is the
	     binding in the home scope.  */ /* If this is the file scope, and we are processing more
	     than one translation unit in this compilation, set
	     DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
	     This makes same_translation_unit_p work, and causes
	     static declarations to be given disambiguating suffixes.  */ /* Fall through.  */ /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
	     already been put there by store_parm_decls.  Unused-
	     parameter warnings are handled by function.c.
	     error_mark_node obviously does not go in BLOCK_VARS and
	     does not get unused-variable warnings.  */ /* It is possible for a decl not to have a name.  We get
	     here with b->id NULL in this case.  */ /* Dispose of the block that we just made inside some higher level.  */ /* If we did not make a block for the scope just exited, any
	 blocks made for inner scopes must be carried forward so they
	 will later become subblocks of something else.  */ /* Pop the current scope, and free the structure for reuse.  */