📄 decl.c
字号:
{ if (DECL_NAME (link) != NULL_TREE) { /* 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)) = NULL_TREE; } } /* 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); /* suspend a level. */ suspend_binding_level ();#endif}/* Subroutines for reverting temporarily to top-level for instantiation of templates and such. We actually need to clear out the class- and local-value slots of all identifiers, so that only the global values are at all visible. Simply setting current_binding_level to the global scope isn't enough, because more binding levels may be pushed. */struct saved_scope { struct binding_level *old_binding_level; tree old_bindings; struct saved_scope *prev; tree class_name, class_type, function_decl; struct binding_level *class_bindings; tree *lang_base, *lang_stack, lang_name; int lang_stacksize; int minimal_parse_mode; tree last_function_parms; tree template_parms; HOST_WIDE_INT processing_template_decl; tree previous_class_type, previous_class_values;};static struct saved_scope *current_saved_scope;static treestore_bindings (names, old_bindings) tree names, old_bindings;{ tree t; for (t = names; t; t = TREE_CHAIN (t)) { tree binding, t1, id; if (TREE_CODE (t) == TREE_LIST) id = TREE_PURPOSE (t); else id = DECL_NAME (t); if (!id || (!IDENTIFIER_LOCAL_VALUE (id) && !IDENTIFIER_CLASS_VALUE (id))) continue; for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1)) if (TREE_VEC_ELT (t1, 0) == id) goto skip_it; binding = make_tree_vec (4); if (id) { my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135); TREE_VEC_ELT (binding, 0) = id; TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id); TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id); TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id); IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE; IDENTIFIER_CLASS_VALUE (id) = NULL_TREE; } TREE_CHAIN (binding) = old_bindings; old_bindings = binding; skip_it: ; } return old_bindings;}voidmaybe_push_to_top_level (pseudo) int pseudo;{ extern int current_lang_stacksize; struct saved_scope *s = (struct saved_scope *) xmalloc (sizeof (struct saved_scope)); struct binding_level *b = inner_binding_level; tree old_bindings = NULL_TREE; if (current_function_decl) push_cp_function_context (NULL_TREE); if (previous_class_type) old_bindings = store_bindings (previous_class_values, old_bindings); /* Have to include global_binding_level, because class-level decls aren't listed anywhere useful. */ for (; b; b = b->level_chain) { tree t; if (b == global_binding_level || (pseudo && b->pseudo_global)) break; old_bindings = store_bindings (b->names, old_bindings); /* We also need to check class_shadowed to save class-level type bindings, since pushclass doesn't fill in b->names. */ if (b->parm_flag == 2) old_bindings = store_bindings (b->class_shadowed, old_bindings); /* Unwind type-value slots back to top level. */ for (t = b->type_shadowed; t; t = TREE_CHAIN (t)) SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t)); } s->old_binding_level = current_binding_level; current_binding_level = b; s->class_name = current_class_name; s->class_type = current_class_type; s->function_decl = current_function_decl; s->class_bindings = class_binding_level; s->lang_stack = current_lang_stack; s->lang_base = current_lang_base; s->lang_stacksize = current_lang_stacksize; s->lang_name = current_lang_name; s->minimal_parse_mode = minimal_parse_mode; s->last_function_parms = last_function_parms; s->template_parms = current_template_parms; s->processing_template_decl = processing_template_decl; s->previous_class_type = previous_class_type; s->previous_class_values = previous_class_values; current_class_name = current_class_type = NULL_TREE; current_function_decl = NULL_TREE; class_binding_level = (struct binding_level *)0; current_lang_stacksize = 10; current_lang_stack = current_lang_base = (tree *) xmalloc (current_lang_stacksize * sizeof (tree)); current_lang_name = lang_name_cplusplus; strict_prototype = strict_prototypes_lang_cplusplus; named_labels = NULL_TREE; minimal_parse_mode = 0; previous_class_type = previous_class_values = NULL_TREE; if (!pseudo) { current_template_parms = NULL_TREE; processing_template_decl = 0; } s->prev = current_saved_scope; s->old_bindings = old_bindings; current_saved_scope = s; push_obstacks (&permanent_obstack, &permanent_obstack);}voidpush_to_top_level (){ maybe_push_to_top_level (0);}voidpop_from_top_level (){ extern int current_lang_stacksize; struct saved_scope *s = current_saved_scope; tree t; /* Clear out class-level bindings cache. */ if (previous_class_type) { popclass (-1); previous_class_type = NULL_TREE; } pop_obstacks (); current_binding_level = s->old_binding_level; current_saved_scope = s->prev; for (t = s->old_bindings; t; t = TREE_CHAIN (t)) { tree id = TREE_VEC_ELT (t, 0); if (id) { IDENTIFIER_TYPE_VALUE (id) = TREE_VEC_ELT (t, 1); IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2); IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3); } } current_class_name = s->class_name; current_class_type = s->class_type; current_function_decl = s->function_decl; class_binding_level = s->class_bindings; free (current_lang_base); current_lang_base = s->lang_base; current_lang_stack = s->lang_stack; current_lang_name = s->lang_name; current_lang_stacksize = s->lang_stacksize; if (current_lang_name == lang_name_cplusplus) strict_prototype = strict_prototypes_lang_cplusplus; else if (current_lang_name == lang_name_c) strict_prototype = strict_prototypes_lang_c; minimal_parse_mode = s->minimal_parse_mode; last_function_parms = s->last_function_parms; current_template_parms = s->template_parms; processing_template_decl = s->processing_template_decl; previous_class_type = s->previous_class_type; previous_class_values = s->previous_class_values; free (s); if (current_function_decl) pop_cp_function_context (NULL_TREE);}/* Push a definition of struct, union or enum tag "name". into binding_level "b". "type" should be the type node, We assume that the tag "name" is not already defined. Note that the definition may really be just a forward reference. In that case, the TYPE_SIZE will be a NULL_TREE. C++ gratuitously puts all these tags in the name space. *//* When setting the IDENTIFIER_TYPE_VALUE field of an identifier ID, record the shadowed value for this binding contour. TYPE is the type that ID maps to. */static voidset_identifier_type_value_with_scope (id, type, b) tree id; tree type; struct binding_level *b;{ if (b != global_binding_level) { tree old_type_value = IDENTIFIER_TYPE_VALUE (id); b->type_shadowed = tree_cons (id, old_type_value, b->type_shadowed); } SET_IDENTIFIER_TYPE_VALUE (id, type);}/* As set_identifier_type_value_with_scope, but using inner_binding_level. */voidset_identifier_type_value (id, type) tree id; tree type;{ set_identifier_type_value_with_scope (id, type, inner_binding_level);}/* Pop off extraneous binding levels left over due to syntax errors. We don't pop past namespaces, as they might be valid. */voidpop_everything (){#ifdef DEBUG_CP_BINDING_LEVELS fprintf (stderr, "XXX entering pop_everything ()\n");#endif while (! toplevel_bindings_p () && ! pseudo_global_level_p ()) { if (class_binding_level) pop_nested_class (1); else poplevel (0, 0, 0); }#ifdef DEBUG_CP_BINDING_LEVELS fprintf (stderr, "XXX leaving pop_everything ()\n");#endif}/* Push a tag name NAME for struct/class/union/enum type TYPE. Normally put into into the inner-most non-tag-transparent scope, but if GLOBALIZE is true, put it in the inner-most non-class scope. The latter is needed for implicit declarations. */voidpushtag (name, type, globalize) tree name, type; int globalize;{ register struct binding_level *b; tree context = 0; tree c_decl = 0; b = inner_binding_level; while (b->tag_transparent || (globalize && b->parm_flag == 2)) b = b->level_chain; if (toplevel_bindings_p ()) b->tags = perm_tree_cons (name, type, b->tags); else b->tags = saveable_tree_cons (name, type, b->tags); if (name) { context = type ? TYPE_CONTEXT (type) : NULL_TREE; if (! context && ! globalize) context = current_scope (); if (context) c_decl = TREE_CODE (context) == FUNCTION_DECL ? context : TYPE_MAIN_DECL (context); /* Do C++ gratuitous typedefing. */ if (IDENTIFIER_TYPE_VALUE (name) != type) { register tree d; int newdecl = 0; if (b->parm_flag != 2 || TYPE_SIZE (current_class_type) != NULL_TREE) { d = lookup_nested_type (type, c_decl); if (d == NULL_TREE) { newdecl = 1; d = build_decl (TYPE_DECL, name, type); SET_DECL_ARTIFICIAL (d); set_identifier_type_value_with_scope (name, type, b); } else d = TYPE_MAIN_DECL (d); TYPE_NAME (type) = d; DECL_CONTEXT (d) = context; if (! globalize && processing_template_decl && IS_AGGR_TYPE (type)) push_template_decl (d); if (b->parm_flag == 2) d = pushdecl_class_level (d); else d = pushdecl_with_scope (d, b); } else { /* Make nested declarations go into class-level scope. */ newdecl = 1; d = build_decl (TYPE_DECL, name, type); SET_DECL_ARTIFICIAL (d); TYPE_NAME (type) = d; DECL_CONTEXT (d) = context; if (! globalize && processing_template_decl && IS_AGGR_TYPE (type)) push_template_decl (d); d = pushdecl_class_level (d); } if (newdecl) { if (ANON_AGGRNAME_P (name)) DECL_IGNORED_P (d) = 1; TYPE_CONTEXT (type) = DECL_CONTEXT (d); DECL_ASSEMBLER_NAME (d) = DECL_NAME (d); DECL_ASSEMBLER_NAME (d) = get_identifier (build_overload_name (type, 1, 1)); } } if (b->parm_flag == 2) { TREE_NONLOCAL_FLAG (type) = 1; if (TYPE_SIZE (current_class_type) == NULL_TREE) CLASSTYPE_TAGS (current_class_type) = b->tags; } } if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) /* Use the canonical TYPE_DECL for this node. */ TYPE_STUB_DECL (type) = TYPE_NAME (type); else { /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the tagged type we just added to the current binding level. This fake NULL-named TYPE_DECL node helps dwarfout.c to know when it needs to output a representation of a tagged type, and it also gives us a convenient place to record the "scope start" address for the tagged type. */ tree d = build_decl (TYPE_DECL, NULL_TREE, type); TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b); }}/* Counter used to create anonymous type names. */static int anon_cnt = 0;/* Return an IDENTIFIER which can be used as a name for anonymous structs and unions. */treemake_anon_name (){ char buf[32]; sprintf (buf, ANON_AGGRNAME_FORMAT, anon_cnt++); return get_identifier (buf);}/* Clear the TREE_PURPOSE slot of tags which have anonymous typenames. This keeps dbxout from getting confused. */voidclear_anon_tags (){ register struct binding_level *b; register tree tags; static int last_cnt = 0; /* Fast out if no new anon names were declared. */ if (last_cnt == anon_cnt) return; b = current_binding_level; while (b->tag_transparent) b = b->level_chain; tags = b->tags; while (tags) { /* A NULL purpose means we have already processed all tags from here to the end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -