📄 decl.c
字号:
static treelookup_name_current_level (name) tree name;{ register tree t; if (current_binding_level == global_binding_level) return IDENTIFIER_GLOBAL_VALUE (name); if (IDENTIFIER_LOCAL_VALUE (name) == 0) return 0; for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) if (DECL_NAME (t) == name) break; return t;}/* Use a binding level to record a labeled block declaration */voidpush_labeled_block (lb) tree lb;{ register tree name = DECL_NAME (LABELED_BLOCK_LABEL (lb)); register struct binding_level *b = current_binding_level; tree oldlocal = IDENTIFIER_LOCAL_VALUE (name); if (oldlocal != 0) b->shadowed = tree_cons (name, oldlocal, b->shadowed); TREE_CHAIN (lb) = b->names; b->names = lb; IDENTIFIER_LOCAL_VALUE (name) = lb;}/* Pop the current binding level, reinstalling values for the previous labeled block */voidpop_labeled_block (){ struct binding_level *b = current_binding_level; tree label = b->names; IDENTIFIER_LOCAL_VALUE (DECL_NAME (LABELED_BLOCK_LABEL (label))) = NULL_TREE; if (b->shadowed) IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (b->shadowed)) = TREE_VALUE (b->shadowed); /* Pop the current level, and free the structure for reuse. */ current_binding_level = current_binding_level->level_chain; b->level_chain = free_binding_level; free_binding_level = b;}/* Record a decl-node X as belonging to the current lexical scope. Check for errors (such as an incompatible declaration for the same name already seen in the same scope). Returns either X or an old decl for the same name. If an old decl is returned, it may have been smashed to agree with what X says. */treepushdecl (x) tree x;{ register tree t; register tree name = DECL_NAME (x); register struct binding_level *b = current_binding_level; DECL_CONTEXT (x) = current_function_decl; if (name) { char *file; int line; t = lookup_name_current_level (name); if (t != 0 && t == error_mark_node) /* error_mark_node is 0 for a while during initialization! */ { t = 0; error_with_decl (x, "`%s' used prior to declaration"); } if (t != 0) { file = DECL_SOURCE_FILE (t); line = DECL_SOURCE_LINE (t); } /* If we're naming a hitherto-unnamed type, set its TYPE_NAME to point to the TYPE_DECL. Since Java does not have typedefs, a type can only have one (true) name, given by a class, interface, or builtin. */ if (TREE_CODE (x) == TYPE_DECL && TYPE_NAME (TREE_TYPE (x)) == 0 && TREE_TYPE (x) != error_mark_node) { TYPE_NAME (TREE_TYPE (x)) = x; TYPE_STUB_DECL (TREE_TYPE (x)) = x; } /* This name is new in its binding level. Install the new declaration and return it. */ if (b == global_binding_level) { /* Install a global value. */ IDENTIFIER_GLOBAL_VALUE (name) = x; } else { /* Here to install a non-global value. */ tree oldlocal = IDENTIFIER_LOCAL_VALUE (name); IDENTIFIER_LOCAL_VALUE (name) = x;#if 0 /* Warn if shadowing an argument at the top level of the body. */ if (oldlocal != 0 && !DECL_EXTERNAL (x) /* This warning doesn't apply to the parms of a nested fcn. */ && ! current_binding_level->parm_flag /* Check that this is one level down from the parms. */ && current_binding_level->level_chain->parm_flag /* Check that the decl being shadowed comes from the parm level, one level up. */ && chain_member (oldlocal, current_binding_level->level_chain->names)) { if (TREE_CODE (oldlocal) == PARM_DECL) pedwarn ("declaration of `%s' shadows a parameter", IDENTIFIER_POINTER (name)); else pedwarn ("declaration of `%s' shadows a symbol from the parameter list", IDENTIFIER_POINTER (name)); } /* Maybe warn if shadowing something else. */ else if (warn_shadow && !DECL_EXTERNAL (x) /* No shadow warnings for internally generated vars. */ && DECL_SOURCE_LINE (x) != 0 /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) { char *warnstring = 0; if (TREE_CODE (x) == PARM_DECL && current_binding_level->level_chain->parm_flag) /* Don't warn about the parm names in function declarator within a function declarator. It would be nice to avoid warning in any function declarator in a declaration, as opposed to a definition, but there is no way to tell it's not a definition. */ ; else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL) warnstring = "declaration of `%s' shadows a parameter"; else if (oldlocal != 0) warnstring = "declaration of `%s' shadows previous local"; else if (IDENTIFIER_GLOBAL_VALUE (name) != 0 && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node) warnstring = "declaration of `%s' shadows global declaration"; if (warnstring) warning (warnstring, IDENTIFIER_POINTER (name)); }#endif /* If storing a local value, there may already be one (inherited). If so, record it for restoration when this binding level ends. */ if (oldlocal != 0) b->shadowed = tree_cons (name, oldlocal, b->shadowed); } } /* Put decls on list in reverse order. We will reverse them later if necessary. */ TREE_CHAIN (x) = b->names; b->names = x; return x;}voidpushdecl_force_head (x) tree x;{ current_binding_level->names = x;}/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */treepushdecl_top_level (x) tree x;{ register tree t; register struct binding_level *b = current_binding_level; current_binding_level = global_binding_level; t = pushdecl (x); current_binding_level = b; return t;}/* Nonzero if we are currently in the global binding level. */intglobal_bindings_p (){ return current_binding_level == global_binding_level;}/* Return the list of declarations of the current level. Note that this list is in reverse order unless/until you nreverse it; and when you do nreverse it, you must store the result back using `storedecls' or you will lose. */treegetdecls (){ return current_binding_level->names;}/* Create a new `struct binding_level'. */staticstruct binding_level *make_binding_level (){ /* NOSTRICT */ return (struct binding_level *) xmalloc (sizeof (struct binding_level));}voidpushlevel (unused) int unused ATTRIBUTE_UNUSED;{ register struct binding_level *newlevel = NULL_BINDING_LEVEL;#if 0 /* 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;#endif /* 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->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;}/* 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 subblocks = current_binding_level->blocks; tree block = 0; tree decl; int block_previously_created; keep |= current_binding_level->keep; /* 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 { push_function_context (); output_inline_function (decl); pop_function_context (); } } /* If there were any declarations 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) = NULL_TREE; 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)) { tree name = DECL_NAME (link); if (name != 0 && IDENTIFIER_LOCAL_VALUE (name) == link) { /* 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 (name) = 1; if (TREE_ADDRESSABLE (link)) TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; } IDENTIFIER_LOCAL_VALUE (name) = 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) { /* 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. */#if 0 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -