FreeBSD/contrib/gcc/cp/decl.c
/* Exit a binding level.
   Pop the level off, and restore the state of the identifier-decl mappings
   that were in effect when this level was entered.

   If KEEP == 1, this level had explicit declarations, so
   and create a "block" (a BLOCK node) for the level
   to record its declarations and subblocks for symbol table output.

   If FUNCTIONBODY is nonzero, this level is the body of a function,
   so create a block as if KEEP were set and also clear out all
   label names.

   If REVERSE is nonzero, reverse the order of decls before putting
   them into the BLOCK.  */
Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.

If KEEP == 1, this level had explicit declarations, so
and create a "block" (a BLOCK node) for the level
to record its declarations and subblocks for symbol table output.

If FUNCTIONBODY is nonzero, this level is the body of a function,
so create a block as if KEEP were set and also clear out all
label names.

If REVERSE is nonzero, reverse the order of decls before putting
them into the BLOCK.
Exit a binding level . Pop the level off and restore the state of the identifier - decl mappings that were in effect when this level was entered . If KEEP == 1 this level had explicit declarations so and create a " block " ( a BLOCK node ) for the level to record its declarations and subblocks for symbol table output . If FUNCTIONBODY is nonzero this level is the body of a function so create a block as if KEEP were set and also clear out all label names . If REVERSE is nonzero reverse the order of decls before putting them into the BLOCK .
tree
poplevel (int keep, int reverse, int functionbody)
{
  tree link;
  tree decls;
  int tmp = functionbody;
  int real_functionbody;
  tree subblocks;
  tree block;
  tree decl;
  int leaving_for_scope;
  scope_kind kind;
  timevar_push (TV_NAME_LOOKUP);
 restart:
  block = NULL_TREE;
  gcc_assert (current_binding_level->kind != sk_class);
  real_functionbody = (current_binding_level->kind == sk_cleanup
		       ? ((functionbody = 0), tmp) : functionbody);
  subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
  gcc_assert (!VEC_length(cp_class_binding,
			  current_binding_level->class_shadowed));
  gcc_assert (keep == 0 || keep == 1);
  if (current_binding_level->keep)
    keep = 1;
  if (cfun && !functionbody && named_labels)
    htab_traverse (named_labels, poplevel_named_label_1,
		   current_binding_level);
  if (reverse)
    current_binding_level->names
      = decls = nreverse (current_binding_level->names);
  else
    decls = current_binding_level->names;
  block = NULL_TREE;
  if (keep == 1 || functionbody)
    block = make_node (BLOCK);
  if (block != NULL_TREE)
    {
      BLOCK_VARS (block) = decls;
      BLOCK_SUBBLOCKS (block) = subblocks;
    }
  if (keep >= 0)
    for (link = subblocks; link; link = TREE_CHAIN (link))
      BLOCK_SUPERCONTEXT (link) = block;
  leaving_for_scope
    = current_binding_level->kind == sk_for && flag_new_for_scope == 1;
  if (warn_unused_variable
      && !processing_template_decl)
    for (decl = getdecls (); decl; decl = TREE_CHAIN (decl))
      if (TREE_CODE (decl) == VAR_DECL
	  && ! TREE_USED (decl)
	  && ! DECL_IN_SYSTEM_HEADER (decl)
	  && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
	warning (OPT_Wunused_variable, "unused variable %q+D", decl);
  for (link = decls; link; link = TREE_CHAIN (link))
    {
      if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
	  && DECL_NAME (link))
	{
	  tree name = DECL_NAME (link);
	  cxx_binding *ob;
	  tree ns_binding;
	  ob = outer_binding (name,
			      IDENTIFIER_BINDING (name),
			      true);
	  if (!ob)
	    ns_binding = IDENTIFIER_NAMESPACE_VALUE (name);
	  else
	    ns_binding = NULL_TREE;
	  if (ob && ob->scope == current_binding_level->level_chain)
	    pop_binding (name, link);
	  else if ((ob && (TREE_CODE (ob->value) == TYPE_DECL))
		   || (ns_binding && TREE_CODE (ns_binding) == TYPE_DECL))
	    pop_binding (name, link);
	  else
	    {
	      DECL_DEAD_FOR_LOCAL (link) = 1;
	      if (ob && ob->value)
		{
		  SET_DECL_SHADOWED_FOR_VAR (link, ob->value);
		  DECL_HAS_SHADOWED_FOR_VAR_P (link) = 1;
		}
	      current_binding_level->level_chain->dead_vars_from_for
		= tree_cons (NULL_TREE, link,
			     current_binding_level->level_chain->
			     dead_vars_from_for);
	      IDENTIFIER_BINDING (name)->scope
		= current_binding_level->level_chain;
	    }
	}
      else
	{
	  tree name;
	  decl = link;
	  if (TREE_CODE (decl) == TREE_LIST)
	    decl = TREE_VALUE (decl);
	  name = decl;
	  if (TREE_CODE (name) == OVERLOAD)
	    name = OVL_FUNCTION (name);
	  gcc_assert (DECL_P (name));
	  pop_binding (DECL_NAME (name), decl);
	}
    }
  for (link = current_binding_level->dead_vars_from_for;
       link; link = TREE_CHAIN (link))
    pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
  for (link = current_binding_level->type_shadowed;
       link; link = TREE_CHAIN (link))
    SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
  for (link = current_binding_level->shadowed_labels;
       link;
       link = TREE_CHAIN (link))
    pop_local_label (TREE_VALUE (link), TREE_PURPOSE (link));
  if (block)
    {
      tree* d;
      for (d = &BLOCK_VARS (block); *d; )
	{
	  if (TREE_CODE (*d) == TREE_LIST)
	    *d = TREE_CHAIN (*d);
	  else
	    d = &TREE_CHAIN (*d);
	}
    }
  if (functionbody)
    {
      BLOCK_VARS (block) = 0;
      pop_labels (block);
    }
  kind = current_binding_level->kind;
  if (kind == sk_cleanup)
    {
      tree stmt;
      stmt = pop_stmt_list (current_binding_level->statement_list);
      stmt = c_build_bind_expr (block, stmt);
      add_stmt (stmt);
    }
  leave_scope ();
  if (functionbody)
    {
      gcc_assert (DECL_INITIAL (current_function_decl) == error_mark_node);
      DECL_INITIAL (current_function_decl) = block;
    }
  else if (block)
    current_binding_level->blocks
      = chainon (current_binding_level->blocks, block);
  else if (subblocks)
    current_binding_level->blocks
      = chainon (current_binding_level->blocks, subblocks);
  if (block)
    TREE_USED (block) = 1;
  if (kind == sk_cleanup)
    goto restart;
  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
tree poplevel ( int keep , int reverse , int functionbody ) { tree link ; tree decls ; int tmp = functionbody ; int real_functionbody ; tree subblocks ; tree block ; tree decl ; int leaving_for_scope ; scope_kind kind ; timevar_push ( TV_NAME_LOOKUP ) ; restart : block = NULL_TREE ; gcc_assert ( current_binding_level -> kind != sk_class ) ; real_functionbody = ( current_binding_level -> kind == sk_cleanup ? ( ( functionbody = 0 ) , tmp ) : functionbody ) ; subblocks = functionbody >= 0 ? current_binding_level -> blocks : 0 ; gcc_assert ( ! VEC_length ( cp_class_binding , current_binding_level -> class_shadowed ) ) ; gcc_assert ( keep == 0 || keep == 1 ) ; if ( current_binding_level -> keep ) keep = 1 ; if ( cfun && ! functionbody && named_labels ) htab_traverse ( named_labels , poplevel_named_label_1 , current_binding_level ) ; if ( reverse ) current_binding_level -> names = decls = nreverse ( current_binding_level -> names ) ; else decls = current_binding_level -> names ; block = NULL_TREE ; if ( keep == 1 || functionbody ) block = make_node ( BLOCK ) ; if ( block != NULL_TREE ) { BLOCK_VARS ( block ) = decls ; BLOCK_SUBBLOCKS ( block ) = subblocks ; } if ( keep >= 0 ) for ( link = subblocks ; link ; link = TREE_CHAIN ( link ) ) BLOCK_SUPERCONTEXT ( link ) = block ; leaving_for_scope = current_binding_level -> kind == sk_for && flag_new_for_scope == 1 ; if ( warn_unused_variable && ! processing_template_decl ) for ( decl = getdecls ( ) ; decl ; decl = TREE_CHAIN ( decl ) ) if ( TREE_CODE ( decl ) == VAR_DECL && ! TREE_USED ( decl ) && ! DECL_IN_SYSTEM_HEADER ( decl ) && DECL_NAME ( decl ) && ! DECL_ARTIFICIAL ( decl ) ) warning ( OPT_Wunused_variable , " " , decl ) ; for ( link = decls ; link ; link = TREE_CHAIN ( link ) ) { if ( leaving_for_scope && TREE_CODE ( link ) == VAR_DECL && DECL_NAME ( link ) ) { tree name = DECL_NAME ( link ) ; cxx_binding * ob ; tree ns_binding ; ob = outer_binding ( name , IDENTIFIER_BINDING ( name ) , true ) ; if ( ! ob ) ns_binding = IDENTIFIER_NAMESPACE_VALUE ( name ) ; else ns_binding = NULL_TREE ; if ( ob && ob -> scope == current_binding_level -> level_chain ) pop_binding ( name , link ) ; else if ( ( ob && ( TREE_CODE ( ob -> value ) == TYPE_DECL ) ) || ( ns_binding && TREE_CODE ( ns_binding ) == TYPE_DECL ) ) pop_binding ( name , link ) ; else { DECL_DEAD_FOR_LOCAL ( link ) = 1 ; if ( ob && ob -> value ) { SET_DECL_SHADOWED_FOR_VAR ( link , ob -> value ) ; DECL_HAS_SHADOWED_FOR_VAR_P ( link ) = 1 ; } current_binding_level -> level_chain -> dead_vars_from_for = tree_cons ( NULL_TREE , link , current_binding_level -> level_chain -> dead_vars_from_for ) ; IDENTIFIER_BINDING ( name ) -> scope = current_binding_level -> level_chain ; } } else { tree name ; decl = link ; if ( TREE_CODE ( decl ) == TREE_LIST ) decl = TREE_VALUE ( decl ) ; name = decl ; if ( TREE_CODE ( name ) == OVERLOAD ) name = OVL_FUNCTION ( name ) ; gcc_assert ( DECL_P ( name ) ) ; pop_binding ( DECL_NAME ( name ) , decl ) ; } } for ( link = current_binding_level -> dead_vars_from_for ; link ; link = TREE_CHAIN ( link ) ) pop_binding ( DECL_NAME ( TREE_VALUE ( link ) ) , TREE_VALUE ( link ) ) ; for ( link = current_binding_level -> type_shadowed ; link ; link = TREE_CHAIN ( link ) ) SET_IDENTIFIER_TYPE_VALUE ( TREE_PURPOSE ( link ) , TREE_VALUE ( link ) ) ; for ( link = current_binding_level -> shadowed_labels ; link ; link = TREE_CHAIN ( link ) ) pop_local_label ( TREE_VALUE ( link ) , TREE_PURPOSE ( link ) ) ; if ( block ) { tree * d ; for ( d = & BLOCK_VARS ( block ) ; * d ; ) { if ( TREE_CODE ( * d ) == TREE_LIST ) * d = TREE_CHAIN ( * d ) ; else d = & TREE_CHAIN ( * d ) ; } } if ( functionbody ) { BLOCK_VARS ( block ) = 0 ; pop_labels ( block ) ; } kind = current_binding_level -> kind ; if ( kind == sk_cleanup ) { tree stmt ; stmt = pop_stmt_list ( current_binding_level -> statement_list ) ; stmt = c_build_bind_expr ( block , stmt ) ; add_stmt ( stmt ) ; } leave_scope ( ) ; if ( functionbody ) { gcc_assert ( DECL_INITIAL ( current_function_decl ) == error_mark_node ) ; DECL_INITIAL ( current_function_decl ) = block ; } else if ( block ) current_binding_level -> blocks = chainon ( current_binding_level -> blocks , block ) ; else if ( subblocks ) current_binding_level -> blocks = chainon ( current_binding_level -> blocks , subblocks ) ; if ( block ) TREE_USED ( block ) = 1 ; if ( kind == sk_cleanup ) goto restart ; POP_TIMEVAR_AND_RETURN ( TV_NAME_LOOKUP , block ) ; }
Exit a binding level.
Exit a binding level .
/* The chain of decls was accumulated in reverse order.
     Put it into forward order, just for cleanliness.  */ /* We used to use KEEP == 2 to indicate that the new block should go
     at the beginning of the list of blocks at this binding level,
     rather than the end.  This hack is no longer used.  */ /* Any uses of undefined labels, and any defined labels, now operate
     under constraints of next binding contour.  */ /* Get the decls in the order they were written.
     Usually current_binding_level->names is in reverse order.
     But parameter decls were previously put in forward order.  */ /* If there were any declarations or structure tags in that level,
     or if this level is a function body,
     create a BLOCK to record them for the life of this function.  */ /* In each subblock, record that this is its superior.  */ /* We still support the old for-scope rules, whereby the variables
     in a for-init statement were in scope after the for-statement
     ended.  We only use the new rules if flag_new_for_scope is
     nonzero.  */ /* Before we remove the declarations first check for unused variables.  */ /* Remove declarations for all the DECLs in this level.  */ /*class_p=*/ /* We have something like:

		 int i;
		 for (int i; ;);

	       and we are leaving the `for' scope.  There's no reason to
	       keep the binding of the inner `i' in this case.  */ /* Here, we have something like:

		 typedef int I;

		 void f () {
		   for (int I; ;);
		 }

	       We must pop the for-scope binding so we know what's a
	       type and what isn't.  */ /* Mark this VAR_DECL as dead so that we can tell we left it
		 there only for backward compatibility.  */ /* Keep track of what should have happened when we
		 popped the binding.  */ /* Add it to the list of dead variables in the next
		 outermost binding to that we can remove these when we
		 leave that binding.  */ /* Although we don't pop the cxx_binding, we do clear
		 its SCOPE since the scope is going away now.  */ /* Remove the binding.  */ /* Remove declarations for any `for' variables from inner scopes
     that we kept around.  */ /* Restore the IDENTIFIER_TYPE_VALUEs.  */ /* Restore the IDENTIFIER_LABEL_VALUEs for local labels.  */ /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
     list if a `using' declaration put them there.  The debugging
     back-ends won't understand OVERLOAD, so we remove them here.
     Because the BLOCK_VARS are (temporarily) shared with
     CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
     popped all the bindings.  */ /* If the level being exited is the top level of a function,
     check over all the labels.  */ /* Since this is the top level block of a function, the vars are
	 the function's parameters.  Don't leave them in the BLOCK
	 because they are found in the FUNCTION_DECL instead.  */ /* If this is a temporary binding created for a cleanup, then we'll
	 have pushed a statement list level.  Pop that, create a new
	 BIND_EXPR for the block, and insert it into the stream.  */ /* The current function is being defined, so its DECL_INITIAL
	 should be error_mark_node.  */ /* If we did not make a block for the level just exited,
     any blocks made for inner levels
     (since they cannot be recorded as subblocks in that level)
     must be carried forward so they will later become subblocks
     of something else.  */ /* Each and every BLOCK node created here in `poplevel' is important
     (e.g. for proper debugging information) so if we created one
     earlier, mark it as "used".  */ /* All temporary bindings created for cleanups are popped silently.  */