📄 cp-decl.c
字号:
if (free_binding_level) { newlevel = free_binding_level; free_binding_level = free_binding_level->level_chain; } else { /* Create a new `struct binding_level'. */ newlevel = (struct binding_level *) xmalloc (sizeof (struct binding_level)); } push_binding_level (newlevel, tag_transparent, keep_next_level_flag); GNU_xref_start_scope (newlevel); keep_next_level_flag = 0;#ifdef DEBUG_CP_BINDING_LEVELS debug_bindings_indentation -= 4;#endif}voidpushlevel_temporary (tag_transparent) int tag_transparent;{ pushlevel (tag_transparent); current_binding_level->keep = 2; clear_last_expr (); /* Note we don't call push_momentary() here. Otherwise, it would cause cleanups to be allocated on the momentary obstack, and they will be overwritten by the next statement. */ expand_start_bindings (0);}/* 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 KEEP == 2, this level's subblocks go to the front, not the back of the current binding level. This happens, for instance, when code for constructors and destructors need to generate code at the end of a function which must be moved up to the front of the function. 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. */treepoplevel (keep, reverse, functionbody) int keep; int reverse; int functionbody;{ register tree link; /* The chain of decls was accumulated in reverse order. Put it into forward order, just for cleanliness. */ tree decls; int tmp = functionbody; int implicit_try_block = current_binding_level->parm_flag == 3; int real_functionbody = current_binding_level->keep == 2 ? ((functionbody = 0), tmp) : functionbody; tree tags = functionbody >= 0 ? current_binding_level->tags : 0; tree subblocks = functionbody >= 0 ? current_binding_level->blocks : 0; tree block = 0; tree decl; int block_previously_created;#ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); fprintf (stderr, "poplevel"); debug_bindings_indentation += 4;#endif binding_levels_sane(); GNU_xref_end_scope (current_binding_level, current_binding_level->level_chain, current_binding_level->parm_flag, current_binding_level->keep, current_binding_level->tag_transparent); if (current_binding_level->keep == 1) keep = 1; /* This warning is turned off because it causes warnings for declarations like `extern struct foo *x'. */#if 0 /* Warn about incomplete structure types in this level. */ for (link = tags; link; link = TREE_CHAIN (link)) if (TYPE_SIZE (TREE_VALUE (link)) == 0) { tree type = TREE_VALUE (link); char *errmsg; switch (TREE_CODE (type)) { case RECORD_TYPE: errmsg = "`struct %s' incomplete in scope ending here"; break; case UNION_TYPE: errmsg = "`union %s' incomplete in scope ending here"; break; case ENUMERAL_TYPE: errmsg = "`enum %s' incomplete in scope ending here"; break; } if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type))); else /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */ error (errmsg, TYPE_NAME_STRING (type)); }#endif /* 0 */ /* 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 (reverse) current_binding_level->names = decls = nreverse (current_binding_level->names); else decls = current_binding_level->names; /* Output any nested inline functions within this block if they weren't already output. */ for (decl = decls; decl; decl = TREE_CHAIN (decl)) if (TREE_CODE (decl) == FUNCTION_DECL && ! TREE_ASM_WRITTEN (decl) && DECL_INITIAL (decl) != 0 && TREE_ADDRESSABLE (decl)) output_inline_function (decl); /* 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. */ block = 0; block_previously_created = (current_binding_level->this_block != 0); if (block_previously_created) block = current_binding_level->this_block; else if (keep == 1 || functionbody) block = make_node (BLOCK); if (block != 0) { BLOCK_VARS (block) = decls; BLOCK_TYPE_TAGS (block) = tags; BLOCK_SUBBLOCKS (block) = subblocks; remember_end_note (block); } /* In each subblock, record that this is its superior. */ if (keep >= 0) for (link = subblocks; link; link = TREE_CHAIN (link)) BLOCK_SUPERCONTEXT (link) = block; /* Clear out the meanings of the local variables of this level. */ for (link = decls; link; link = TREE_CHAIN (link)) { if (DECL_NAME (link) != 0) { /* If the ident. was used or addressed via a local extern decl, don't forget that fact. */ if (DECL_EXTERNAL (link)) { if (TREE_USED (link)) TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1; if (TREE_ADDRESSABLE (link)) TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; } IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0; } } /* Restore all name-meanings of the outer levels that were shadowed by this level. */ for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); for (link = current_binding_level->class_shadowed; link; link = TREE_CHAIN (link)) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); for (link = current_binding_level->type_shadowed; link; link = TREE_CHAIN (link)) IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); /* If the level being exited is the top level of a function, check over all the labels. */ if (functionbody) { /* If 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. */ BLOCK_VARS (block) = 0; /* Clear out the definitions of all label names, since their scopes end here. */ for (link = named_labels; link; link = TREE_CHAIN (link)) { register tree label = TREE_VALUE (link); if (DECL_INITIAL (label) == 0) { error_with_decl (label, "label `%s' used but not defined"); /* Avoid crashing later. */ define_label (input_filename, 1, DECL_NAME (label)); } else if (warn_unused && !TREE_USED (label)) warning_with_decl (label, "label `%s' defined but not used"); SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), 0); /* Put the labels into the "variables" of the top-level block, so debugger can see them. */ TREE_CHAIN (label) = BLOCK_VARS (block); BLOCK_VARS (block) = label; } named_labels = 0; } /* Any uses of undefined labels now operate under constraints of next binding contour. */ { struct binding_level *level_chain; level_chain = current_binding_level->level_chain; if (level_chain) { tree labels; for (labels = named_label_uses; labels; labels = TREE_CHAIN (labels)) if (TREE_TYPE (labels) == (tree)current_binding_level) { TREE_TYPE (labels) = (tree)level_chain; TREE_PURPOSE (labels) = level_chain->names; } } } tmp = current_binding_level->keep; pop_binding_level (); if (functionbody) DECL_INITIAL (current_function_decl) = block; else if (block) { if (!block_previously_created) current_binding_level->blocks = chainon (current_binding_level->blocks, block); } /* 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. */ else if (subblocks) if (keep == 2) current_binding_level->blocks = chainon (subblocks, current_binding_level->blocks); else current_binding_level->blocks = chainon (current_binding_level->blocks, subblocks); /* Take care of compiler's internal binding structures. */ if (tmp == 2 && !implicit_try_block) {#if 0 /* We did not call push_momentary for this binding contour, so there is nothing to pop. */ pop_momentary ();#endif expand_end_bindings (getdecls (), keep, 1); block = poplevel (keep, reverse, real_functionbody); } if (block) TREE_USED (block) = 1; binding_levels_sane();#ifdef DEBUG_CP_BINDING_LEVELS debug_bindings_indentation -= 4;#endif return block;}/* Delete the node BLOCK from the current binding level. This is used for the block inside a stmt expr ({...}) so that the block can be reinserted where appropriate. */voiddelete_block (block) tree block;{ tree t; if (current_binding_level->blocks == block) current_binding_level->blocks = TREE_CHAIN (block); for (t = current_binding_level->blocks; t;) { if (TREE_CHAIN (t) == block) TREE_CHAIN (t) = TREE_CHAIN (block); else t = TREE_CHAIN (t); } TREE_CHAIN (block) = NULL; /* Clear TREE_USED which is always set by poplevel. The flag is set again if insert_block is called. */ TREE_USED (block) = 0;}/* Insert BLOCK at the end of the list of subblocks of the current binding level. This is used when a BIND_EXPR is expanded, to handle the BLOCK node inside the BIND_EXPR. */voidinsert_block (block) tree block;{ TREE_USED (block) = 1; current_binding_level->blocks = chainon (current_binding_level->blocks, block);}/* Add BLOCK to the current list of blocks for this binding contour. */voidadd_block_current_level (block) tree block;{ current_binding_level->blocks = chainon (current_binding_level->blocks, block);}/* Set the BLOCK node for the innermost scope (the one we are currently in). */voidset_block (block) register tree block;{ current_binding_level->this_block = block;}/* Do a pushlevel for class declarations. */voidpushlevel_class (){ binding_levels_sane();#ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); fprintf (stderr, "pushlevel_class"); debug_bindings_indentation += 4;#endif pushlevel (0); decl_stack = push_decl_level (decl_stack, &decl_obstack); class_binding_level = current_binding_level; class_binding_level->parm_flag = 2; do { current_binding_level = current_binding_level->level_chain; } while (current_binding_level->parm_flag == 2); binding_levels_sane();#ifdef DEBUG_CP_BINDING_LEVELS debug_bindings_indentation -= 4;#endif}/* ...and a poplevel for class declarations. */treepoplevel_class (){ register struct binding_level *level = class_binding_level; tree block = 0; tree shadowed;#ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); fprintf (stderr, "poplevel_class"); debug_bindings_indentation += 4;#endif binding_levels_sane(); if (level == 0) { while (current_binding_level && class_binding_level == 0) block = poplevel (0, 0, 0); if (current_binding_level == 0) fatal ("syntax error too serious"); level = class_binding_level; } decl_stack = pop_decl_level (decl_stack); for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed); for (shadowed = level->class_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed); for (shadowed = level->type_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed); GNU_xref_end_scope (class_binding_level, class_binding_level->level_chain, class_binding_level->parm_flag, class_binding_level->keep, class_binding_level->tag_transparent); class_binding_level = level->level_chain; if (class_binding_level->parm_flag != 2) class_binding_level = 0;#ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); fprintf (stderr, "popping class binding level "); fprintf (stderr, HOST_PTR_PRINTF, level); fprintf (stderr, "\n"); memset (level, 0x69, sizeof (*level)); debug_bindings_indentation -= 4;#else level->level_chain = free_binding_level; free_binding_level = level;#endif binding_levels_sane(); return block;}/* For debugging. */int no_print_functions = 0;int no_print_builtins = 0;void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -