📄 decl.c
字号:
}static voidresume_binding_level (b) struct binding_level *b;{ /* Resuming binding levels is meant only for namespaces, and those cannot nest into classes. */ my_friendly_assert(!class_binding_level, 386); /* Also, resuming a non-directly nested namespace is a no-no. */ my_friendly_assert(b->level_chain == current_binding_level, 386); current_binding_level = b;#if defined(DEBUG_CP_BINDING_LEVELS) b->binding_depth = binding_depth; indent (); fprintf (stderr, "resume %s level 0x%08x line %d\n", (is_class_level) ? "class" : "block", b, lineno); is_class_level = 0; binding_depth++;#endif /* defined(DEBUG_CP_BINDING_LEVELS) */}/* 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;}/* Return the innermost binding level that is not for a class scope. */static struct binding_level *innermost_nonclass_level (){ struct binding_level *b; b = current_binding_level; while (b->parm_flag == 2) b = b->level_chain; return b;}/* Nonzero if we are currently in a toplevel binding level. This means either the global binding level or a namespace in a toplevel binding level. Since there are no non-toplevel namespace levels, this really means any namespace or pseudo-global level. We also include a class whose context is toplevel. */inttoplevel_bindings_p (){ struct binding_level *b = innermost_nonclass_level (); return b->namespace_p || b->pseudo_global;}/* Nonzero if this is a namespace scope, or if we are defining a class which is itself at namespace scope, or whose enclosing class is such a class, etc. */intnamespace_bindings_p (){ struct binding_level *b = innermost_nonclass_level (); return b->namespace_p;}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->blocks != NULL_TREE || current_binding_level->keep || current_binding_level->names != NULL_TREE || (current_binding_level->tags != NULL_TREE && !current_binding_level->tag_transparent));}/* Identify this binding level as a level of parameters. */voiddeclare_parm_level (){ current_binding_level->parm_flag = 1;}voiddeclare_pseudo_global_level (){ current_binding_level->pseudo_global = 1;}static voiddeclare_namespace_level (){ current_binding_level->namespace_p = 1;}intpseudo_global_level_p (){ struct binding_level *b = innermost_nonclass_level (); return b->pseudo_global;}voidset_class_shadows (shadows) tree shadows;{ class_binding_level->class_shadowed = shadows;}/* 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. They should have been set to 0 at the end of the previous function. */ if (current_binding_level == global_binding_level) my_friendly_assert (named_labels == NULL_TREE, 134); /* Reuse or create a struct for this binding level. */#if defined(DEBUG_CP_BINDING_LEVELS) if (0)#else /* !defined(DEBUG_CP_BINDING_LEVELS) */ if (free_binding_level)#endif /* !defined(DEBUG_CP_BINDING_LEVELS) */ { newlevel = free_binding_level; free_binding_level = free_binding_level->level_chain; } else { newlevel = make_binding_level (); } push_binding_level (newlevel, tag_transparent, keep_next_level_flag); GNU_xref_start_scope ((HOST_WIDE_INT) newlevel); keep_next_level_flag = 0;}voidnote_level_for_for (){ current_binding_level->is_for_scope = 1;}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);}/* For a binding between a name and an entity at a block scope, this is the `struct binding_level' for the block. */#define BINDING_LEVEL(NODE) \ (((struct tree_binding*)NODE)->scope.level)/* These are currently unused, but permanent, CPLUS_BINDING nodes. They are kept here because they are allocated from the permanent obstack and cannot be easily freed. */static tree free_binding_nodes;/* Make DECL the innermost binding for ID. The LEVEL is the binding level at which this declaration is being bound. */static voidpush_binding (id, decl, level) tree id; tree decl; struct binding_level* level;{ tree binding; if (!free_binding_nodes) { /* There are no free nodes, so we must build one here. */ push_obstacks_nochange (); end_temporary_allocation (); binding = make_node (CPLUS_BINDING); pop_obstacks (); } else { /* There are nodes on the free list. Grab the first one. */ binding = free_binding_nodes; /* And update the free list. */ free_binding_nodes = TREE_CHAIN (free_binding_nodes); } /* Now, fill in the binding information. */ BINDING_VALUE (binding) = decl; BINDING_TYPE (binding) = NULL_TREE; BINDING_LEVEL (binding) = level; INHERITED_VALUE_BINDING_P (binding) = 0; LOCAL_BINDING_P (binding) = (level != class_binding_level); /* And put it on the front of the list of bindings for ID. */ TREE_CHAIN (binding) = IDENTIFIER_BINDING (id); IDENTIFIER_BINDING (id) = binding;}/* ID is already bound in the current scope. But, DECL is an additional binding for ID in the same scope. This is the `struct stat' hack whereby a non-typedef class-name or enum-name can be bound at the same level as some other kind of entity. It's the responsibility of the caller to check that inserting this name is legal here. Returns nonzero if the new binding was successful. */static intadd_binding (id, decl) tree id; tree decl;{ tree binding = IDENTIFIER_BINDING (id); int ok = 1; if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)) /* The new name is the type name. */ BINDING_TYPE (binding) = decl; else if (!BINDING_VALUE (binding)) /* This situation arises when push_class_level_binding moves an inherited type-binding out of the way to make room for a new value binding. */ BINDING_VALUE (binding) = decl; else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL && DECL_ARTIFICIAL (BINDING_VALUE (binding))) { /* The old binding was a type name. It was placed in BINDING_VALUE because it was thought, at the point it was declared, to be the only entity with such a name. Move the type name into the type slot; it is now hidden by the new binding. */ BINDING_TYPE (binding) = BINDING_VALUE (binding); BINDING_VALUE (binding) = decl; INHERITED_VALUE_BINDING_P (binding) = 0; } else { cp_error ("declaration of `%#D'", decl); cp_error_at ("conflicts with previous declaration `%#D'", BINDING_VALUE (binding)); ok = 0; } return ok;}/* Bind DECL to ID in the current_binding_level. If PUSH_USING is set in FLAGS, we know that DECL doesn't really belong to this binding level, that it got here through a using-declaration. */voidpush_local_binding (id, decl, flags) tree id; tree decl; int flags;{ struct binding_level *b; /* Skip over any local classes. This makes sense if we call push_local_binding with a friend decl of a local class. */ b = current_binding_level; while (b->parm_flag == 2) b = b->level_chain; if (lookup_name_current_level (id)) { /* Supplement the existing binding. */ if (!add_binding (id, decl)) /* It didn't work. Something else must be bound at this level. Do not add DECL to the list of things to pop later. */ return; } else /* Create a new binding. */ push_binding (id, decl, b); if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING)) /* We must put the OVERLOAD into a TREE_LIST since the TREE_CHAIN of an OVERLOAD is already used. Similarly for decls that got here through a using-declaration. */ decl = build_tree_list (NULL_TREE, decl); /* And put DECL on the list of things declared by the current binding level. */ TREE_CHAIN (decl) = b->names; b->names = decl;}/* Bind DECL to ID in the class_binding_level. Returns nonzero if the binding was successful. */intpush_class_binding (id, decl) tree id; tree decl;{ int result = 1; tree binding = IDENTIFIER_BINDING (id); tree context; /* Note that we declared this value so that we can issue an error if this an illegal redeclaration of a name already used for some other purpose. */ note_name_declared_in_class (id, decl); if (binding && BINDING_LEVEL (binding) == class_binding_level) /* Supplement the existing binding. */ result = add_binding (id, decl); else /* Create a new binding. */ push_binding (id, decl, class_binding_level); /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the class-level declaration. Note that we do not use DECL here because of the possibility of the `struct stat' hack; if DECL is a class-name or enum-name we might prefer a field-name, or some such. */ IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id)); /* If this is a binding from a base class, mark it as such. */ binding = IDENTIFIER_BINDING (id); if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST) { /* Any implicit typename must be from a base-class. The context for an implicit typename declaration is always the derived class in which the lookup was done, so the checks based on the context of DECL below will not trigger. */ if (TREE_CODE (decl) == TYPE_DECL && IMPLICIT_TYPENAME_P (TREE_TYPE (decl))) INHERITED_VALUE_BINDING_P (binding) = 1; else { if (TREE_CODE (decl) == OVERLOAD) context = DECL_REAL_CONTEXT (OVL_CURRENT (decl)); else { my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 0); context = DECL_REAL_CONTEXT (decl); } if (is_properly_derived_from (current_class_type, context)) INHERITED_VALUE_BINDING_P (binding) = 1; else INHERITED_VALUE_BINDING_P (binding) = 0; } } else if (BINDING_VALUE (binding) == decl) /* We only encounter a TREE_LIST when push_class_decls detects an ambiguity. Such an ambiguity can be overridden by a definition in this class. */ INHERITED_VALUE_BINDING_P (binding) = 1; return result;}/* Remove the binding for DECL which should be the innermost binding for ID. */static void pop_binding (id, decl) tree id; tree decl;{ tree binding; if (id == NULL_TREE) /* It's easiest to write the loops that call this function without checking whether or not the entities involved have names. We get here for such an entity. */ return; /* Get the innermost binding for ID. */ binding = IDENTIFIER_BINDING (id); /* The name should be bound. */ my_friendly_assert (binding != NULL_TREE, 0); /* The DECL will be either the ordinary binding or the type binding for this identifier. Remove that binding. */ if (BINDING_VALUE (binding) == decl) BINDING_VALUE (binding) = NULL_TREE; else if (BINDING_TYPE (binding) == decl) BINDING_TYPE (binding) = NULL_TREE; else my_friendly_abort (0); if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding)) { /* We're completely done with the innermost binding for this identifier. Unhook it from the list of bindings. */ IDENTIFIER_BINDING (id) = TREE_CHAIN (binding); /* And place it on the free list. */ TREE_CHAIN (binding) = free_binding_nodes; free_binding_nodes = binding; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -