📄 c-decl.c
字号:
print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4); print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4); print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4); print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4); print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);}/* Hook called at end of compilation to assume 1 elt for a top-level array decl that wasn't complete before. */ voidfinish_incomplete_decl (decl) tree decl;{ if (TREE_CODE (decl) == VAR_DECL) { tree type = TREE_TYPE (decl); if (type != error_mark_node && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0) { if (! DECL_EXTERNAL (decl)) warning_with_decl (decl, "array `%s' assumed to have one element"); complete_array_type (type, NULL_TREE, 1); layout_decl (decl, 0); } }}/* Create a new `struct binding_level'. */staticstruct binding_level *make_binding_level (){ /* NOSTRICT */ return (struct binding_level *) xmalloc (sizeof (struct binding_level));}/* Nonzero if we are currently in the global binding level. */intglobal_bindings_p (){ return current_binding_level == global_binding_level;}voidkeep_next_level (){ keep_next_level_flag = 1;}/* Nonzero if the current level needs to have a BLOCK made. */intkept_level_p (){ return ((current_binding_level->keep_if_subblocks && current_binding_level->blocks != 0) || current_binding_level->keep || current_binding_level->names != 0 || (current_binding_level->tags != 0 && !current_binding_level->tag_transparent));}/* Identify this binding level as a level of parameters. DEFINITION_FLAG is 1 for a definition, 0 for a declaration. But it turns out there is no way to pass the right value for DEFINITION_FLAG, so we ignore it. */voiddeclare_parm_level (definition_flag) int definition_flag;{ current_binding_level->parm_flag = 1;}/* Nonzero if currently making parm declarations. */intin_parm_level_p (){ return current_binding_level->parm_flag;}/* Enter a new binding level. If TAG_TRANSPARENT is nonzero, do so only for the name space of variables, not for that of tags. */voidpushlevel (tag_transparent) int tag_transparent;{ register struct binding_level *newlevel = NULL_BINDING_LEVEL; /* If this is the top level of a function, just make sure that NAMED_LABELS is 0. */ if (current_binding_level == global_binding_level) { named_labels = 0; } /* Reuse or create a struct for this binding level. */ if (free_binding_level) { newlevel = free_binding_level; free_binding_level = free_binding_level->level_chain; } else { newlevel = make_binding_level (); } /* Add this level to the front of the chain (stack) of levels that are active. */ *newlevel = clear_binding_level; newlevel->tag_transparent = (tag_transparent || (current_binding_level ? current_binding_level->subblocks_tag_transparent : 0)); newlevel->level_chain = current_binding_level; current_binding_level = newlevel; newlevel->keep = keep_next_level_flag; keep_next_level_flag = 0; newlevel->keep_if_subblocks = keep_next_if_subblocks; keep_next_if_subblocks = 0;}/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */static voidclear_limbo_values (block) tree block;{ tree tem; for (tem = BLOCK_VARS (block); tem; tem = TREE_CHAIN (tem)) if (DECL_NAME (tem) != 0) IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem)) = 0; for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem)) clear_limbo_values (tem);} /* 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 is nonzero, 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. */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; tree tags = current_binding_level->tags; tree subblocks = current_binding_level->blocks; tree block = 0; tree decl; int block_previously_created; keep |= current_binding_level->keep; /* 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, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (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)) { /* If this decl was copied from a file-scope decl on account of a block-scope extern decl, propagate TREE_ADDRESSABLE to the file-scope decl. DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is true, since then the decl goes through save_for_inline_copying. */ if (DECL_ABSTRACT_ORIGIN (decl) != 0 && DECL_ABSTRACT_ORIGIN (decl) != decl) TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; else if (DECL_SAVED_INSNS (decl) != 0) { push_function_context (); output_inline_function (decl); pop_function_context (); } } /* 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 || functionbody || (current_binding_level->keep_if_subblocks && subblocks != 0)) 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. */ 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_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); /* If the level being exited is the top level of a function, check over all the labels, and clear out the current (function local) meanings of their names. */ if (functionbody) { clear_limbo_values (block); /* 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, and add them to BLOCK_VARS. */ 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, lineno, DECL_NAME (label)); } else if (warn_unused && !TREE_USED (label)) warning_with_decl (label, "label `%s' defined but not used"); 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; } } /* Pop the current level, and free the structure for reuse. */ { register struct binding_level *level = current_binding_level; current_binding_level = current_binding_level->level_chain; level->level_chain = free_binding_level; free_binding_level = level; } /* Dispose of the block that we just made inside some higher 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) current_binding_level->blocks = chainon (current_binding_level->blocks, subblocks); /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this binding contour 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. */ if (functionbody) for (link = tags; link; link = TREE_CHAIN (link)) TYPE_CONTEXT (TREE_VALUE (link)) = current_function_decl; else if (block) for (link = tags; link; link = TREE_CHAIN (link)) TYPE_CONTEXT (TREE_VALUE (link)) = block; if (block) TREE_USED (block) = 1; 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -