📄 decl.c
字号:
/* Just in case we get out of sync. */ if (! namespace_bindings_p ()) poplevel (0, 0, 0); decls = current_binding_level->names; /* Clear out the meanings of the local variables of this level. */ for (link = decls; link; link = TREE_CHAIN (link)) { 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 ();}/* 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; tree base_init_list, member_init_list; struct binding_level *class_bindings; tree previous_class_type; tree *lang_base, *lang_stack, lang_name; int lang_stacksize; tree named_labels;};static struct saved_scope *current_saved_scope;extern tree prev_class_type;voidpush_to_top_level (){ extern int current_lang_stacksize; struct saved_scope *s = (struct saved_scope *) xmalloc (sizeof (struct saved_scope)); struct binding_level *b = current_binding_level; tree old_bindings = NULL_TREE; /* 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) continue; for (t = b->names; t; t = TREE_CHAIN (t)) { tree binding, t1, t2 = t; tree id = DECL_ASSEMBLER_NAME (t2); 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: ; } /* 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)); } /* Clear out class-level bindings cache. */ if (current_binding_level == global_binding_level && previous_class_type != NULL_TREE) { popclass (-1); previous_class_type = NULL_TREE; } s->old_binding_level = current_binding_level; current_binding_level = global_binding_level; s->class_name = current_class_name; s->class_type = current_class_type; s->function_decl = current_function_decl; s->base_init_list = current_base_init_list; s->member_init_list = current_member_init_list; s->class_bindings = class_binding_level; s->previous_class_type = previous_class_type; 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->named_labels = named_labels; current_class_name = current_class_type = NULL_TREE; current_function_decl = NULL_TREE; class_binding_level = (struct binding_level *)0; previous_class_type = NULL_TREE; 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; s->prev = current_saved_scope; s->old_bindings = old_bindings; current_saved_scope = s;}voidpop_from_top_level (){ extern int current_lang_stacksize; struct saved_scope *s = current_saved_scope; tree t; if (previous_class_type) previous_class_type = NULL_TREE; 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_base_init_list = s->base_init_list; current_member_init_list = s->member_init_list; current_function_decl = s->function_decl; class_binding_level = s->class_bindings; previous_class_type = s->previous_class_type; 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; named_labels = s->named_labels; free (s);}/* 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);}/* Subroutine "set_nested_typename" builds the nested-typename of the type decl in question. (Argument CLASSNAME can actually be a function as well, if that's the smallest containing scope.) */static voidset_nested_typename (decl, classname, name, type) tree decl, classname, name, type;{ char *buf; my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136); /* No need to do this for anonymous names, since they're unique. */ if (ANON_AGGRNAME_P (name)) { DECL_NESTED_TYPENAME (decl) = name; return; } if (classname == NULL_TREE) classname = get_identifier (""); my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137); my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138); buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname) + IDENTIFIER_LENGTH (name)); sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname), IDENTIFIER_POINTER (name)); DECL_NESTED_TYPENAME (decl) = get_identifier (buf); TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1; /* Create an extra decl so that the nested name will have a type value where appropriate. */ { tree nested, type_decl; nested = DECL_NESTED_TYPENAME (decl); type_decl = build_decl (TYPE_DECL, nested, type); DECL_NESTED_TYPENAME (type_decl) = nested; SET_DECL_ARTIFICIAL (type_decl); /* Mark the TYPE_DECL node created just above as a gratuitous one so that dwarfout.c will know not to generate a TAG_typedef DIE for it, and sdbout.c won't try to output a .def for "::foo". */ DECL_IGNORED_P (type_decl) = 1; /* Remove this when local classes are fixed. */ SET_IDENTIFIER_TYPE_VALUE (nested, type); pushdecl_nonclass_level (type_decl); }}/* 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}#if 0 /* not yet, should get fixed properly later *//* Create a TYPE_DECL node with the correct DECL_ASSEMBLER_NAME. Other routines shouldn't use build_decl directly; they'll produce incorrect results with `-g' unless they duplicate this code. This is currently needed mainly for dbxout.c, but we can make use of it in method.c later as well. */treemake_type_decl (name, type) tree name, type;{ tree decl, id; decl = build_decl (TYPE_DECL, name, type); if (TYPE_NAME (type) == name) /* Class/union/enum definition, or a redundant typedef for same. */ { id = get_identifier (build_overload_name (type, 1, 1)); DECL_ASSEMBLER_NAME (decl) = id; } else if (TYPE_NAME (type) != NULL_TREE) /* Explicit typedef, or implicit typedef for template expansion. */ DECL_ASSEMBLER_NAME (decl) = DECL_ASSEMBLER_NAME (TYPE_NAME (type)); else { /* XXX: Typedef for unnamed struct; some other situations. TYPE_NAME is null; what's right here? */ } return decl;}#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);#if 0 /* Record the identifier as the type's name if it has none. */ if (TYPE_NAME (type) == NULL_TREE) TYPE_NAME (type) = name;#endif /* 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;#if 0 /* not yet, should get fixed properly later */ d = make_type_decl (name, type);#else d = build_decl (TYPE_DECL, name, type); DECL_ASSEMBLER_NAME (d) = current_namespace_id (DECL_ASSEMBLER_NAME (d));#endif SET_DECL_ARTIFICIAL (d);#ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) { /* Mark the TYPE_DECL node we created just above as an gratuitous one. We need to do this so that dwarfout.c will understand that it is not supposed to output a TAG_typedef DIE for it. */ DECL_IGNORED_P (d) = 1; }#endif /* DWARF_DEBUGGING_INFO */ set_identifier_type_value_with_scope (name, type, b); } else d = TYPE_NAME (d); TYPE_NAME (type) = d; /* If it is anonymous, then we are called from pushdecl, and we don't want to infinitely recurse. */ if (! ANON_AGGRNAME_P (name)) { 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);#ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) { /* Mark the TYPE_DECL node we created just above as an gratuitous one. We need to do this so that dwarfout.c will understand that it is not supposed to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -