📄 decl.c
字号:
/* Pointers to the base and current top of the language name stack. */extern tree *current_lang_base, *current_lang_stack;/* C and C++ flags are in decl2.c. *//* Set to 0 at beginning of a constructor, set to 1 if that function does an allocation before referencing its instance variable. */int current_function_assigns_this;int current_function_just_assigned_this;/* Set to 0 at beginning of a function. Set non-zero when store_parm_decls is called. Don't call store_parm_decls if this flag is non-zero! */int current_function_parms_stored;/* Current end of entries in the gc obstack for stack pointer variables. */int current_function_obstack_index;/* Flag saying whether we have used the obstack in this function or not. */int current_function_obstack_usage;/* Flag used when debugging spew.c */extern int spew_debug;/* This is a copy of the class_shadowed list of the previous class binding contour when at global scope. It's used to reset IDENTIFIER_CLASS_VALUEs when entering another class scope (i.e. a cache miss). */extern tree previous_class_values;/* Allocate a level of searching. */struct stack_level *push_decl_level (stack, obstack) struct stack_level *stack; struct obstack *obstack;{ struct stack_level tem; tem.prev = stack; return push_stack_level (obstack, (char *)&tem, sizeof (tem));}/* For each binding contour we allocate a binding_level structure * which records the names defined in that contour. * Contours include: * 0) the global one * 1) one for each function definition, * where internal declarations of the parameters appear. * 2) one for each compound statement, * to record its declarations. * * The current meaning of a name can be found by searching the levels from * the current one out to the global one. * * Off to the side, may be the class_binding_level. This exists * only to catch class-local declarations. It is otherwise * nonexistent. * * Also there may be binding levels that catch cleanups that * must be run when exceptions occur. *//* Note that the information in the `names' component of the global contour is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */struct binding_level { /* A chain of _DECL nodes for all variables, constants, functions, * and typedef types. These are in the reverse of the order supplied. */ tree names; /* A list of structure, union and enum definitions, * for looking up tag names. * It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name, * or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE, * or ENUMERAL_TYPE node. * * C++: the TREE_VALUE nodes can be simple types for component_bindings. * */ tree tags; /* For each level, a list of shadowed outer-level local definitions to be restored when this level is popped. Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and whose TREE_VALUE is its old definition (a kind of ..._DECL node). */ tree shadowed; /* Same, for IDENTIFIER_CLASS_VALUE. */ tree class_shadowed; /* Same, for IDENTIFIER_TYPE_VALUE. */ tree type_shadowed; /* For each level (except not the global one), a chain of BLOCK nodes for all the levels that were entered and exited one level down. */ tree blocks; /* The BLOCK node for this level, if one has been preallocated. If 0, the BLOCK is allocated (if needed) when the level is popped. */ tree this_block; /* The binding level which this one is contained in (inherits from). */ struct binding_level *level_chain; /* List of decls in `names' that have incomplete structure or union types. */ tree incomplete; /* List of VAR_DECLS saved from a previous for statement. These would be dead in ANSI-conforming code, but might be referenced in traditional code. */ tree dead_vars_from_for; /* 1 for the level that holds the parameters of a function. 2 for the level that holds a class declaration. 3 for levels that hold parameter declarations. */ unsigned parm_flag : 4; /* 1 means make a BLOCK for this level regardless of all else. 2 for temporary binding contours created by the compiler. */ unsigned keep : 3; /* Nonzero if this level "doesn't exist" for tags. */ unsigned tag_transparent : 1; /* Nonzero if this level can safely have additional cleanup-needing variables added to it. */ unsigned more_cleanups_ok : 1; unsigned have_cleanups : 1; /* Nonzero if we should accept any name as an identifier in this scope. This happens in some template definitions. */ unsigned accept_any : 1; /* Nonzero if this level is for completing a template class definition inside a binding level that temporarily binds the parameters. This means that definitions here should not be popped off when unwinding this binding level. (Not actually implemented this way, unfortunately.) */ unsigned pseudo_global : 1; /* This is set for a namespace binding level. */ unsigned namespace_p : 1; /* True if this level is that of a for-statement. */ unsigned is_for_scope : 1; /* One bit left for this word. */#if defined(DEBUG_CP_BINDING_LEVELS) /* Binding depth at which this level began. */ unsigned binding_depth;#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ };#define NULL_BINDING_LEVEL ((struct binding_level *) NULL) /* The (non-class) binding level currently in effect. */static struct binding_level *current_binding_level;/* The binding level of the current class, if any. */static struct binding_level *class_binding_level;/* The current (class or non-class) binding level currently in effect. */#define inner_binding_level \ (class_binding_level ? class_binding_level : current_binding_level)/* A chain of binding_level structures awaiting reuse. */static struct binding_level *free_binding_level;/* The outermost binding level, for names of file scope. This is created when the compiler is started and exists through the entire run. */static struct binding_level *global_binding_level;/* Binding level structures are initialized by copying this one. */static struct binding_level clear_binding_level;/* Nonzero means unconditionally make a BLOCK for the next level pushed. */static int keep_next_level_flag;#if defined(DEBUG_CP_BINDING_LEVELS)static int binding_depth = 0;static int is_class_level = 0;static voidindent (){ register unsigned i; for (i = 0; i < binding_depth*2; i++) putc (' ', stderr);}#endif /* defined(DEBUG_CP_BINDING_LEVELS) */static tree pushdecl_with_scope PROTO((tree, struct binding_level *));static voidpush_binding_level (newlevel, tag_transparent, keep) struct binding_level *newlevel; int tag_transparent, keep;{ /* Add this level to the front of the chain (stack) of levels that are active. */ *newlevel = clear_binding_level; if (class_binding_level) { newlevel->level_chain = class_binding_level; class_binding_level = (struct binding_level *)0; } else { newlevel->level_chain = current_binding_level; } current_binding_level = newlevel; newlevel->tag_transparent = tag_transparent; newlevel->more_cleanups_ok = 1; newlevel->keep = keep;#if defined(DEBUG_CP_BINDING_LEVELS) newlevel->binding_depth = binding_depth; indent (); fprintf (stderr, "push %s level 0x%08x line %d\n", (is_class_level) ? "class" : "block", newlevel, lineno); is_class_level = 0; binding_depth++;#endif /* defined(DEBUG_CP_BINDING_LEVELS) */}static voidpop_binding_level (){ if (class_binding_level) current_binding_level = class_binding_level; if (global_binding_level) { /* cannot pop a level, if there are none left to pop. */ if (current_binding_level == global_binding_level) my_friendly_abort (123); } /* Pop the current level, and free the structure for reuse. */#if defined(DEBUG_CP_BINDING_LEVELS) binding_depth--; indent (); fprintf (stderr, "pop %s level 0x%08x line %d\n", (is_class_level) ? "class" : "block", current_binding_level, lineno); if (is_class_level != (current_binding_level == class_binding_level))#if 0 /* XXX Don't abort when we're watching how things are being managed. */ abort ();#else { indent (); fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); }#endif is_class_level = 0;#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ { register struct binding_level *level = current_binding_level; current_binding_level = current_binding_level->level_chain; level->level_chain = free_binding_level;#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */ if (level->binding_depth != binding_depth) abort ();#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ free_binding_level = level; class_binding_level = current_binding_level; if (class_binding_level->parm_flag != 2) class_binding_level = 0; while (current_binding_level->parm_flag == 2) current_binding_level = current_binding_level->level_chain; }}static voidsuspend_binding_level (){ if (class_binding_level) current_binding_level = class_binding_level; if (global_binding_level) { /* cannot suspend a level, if there are none left to suspend. */ if (current_binding_level == global_binding_level) my_friendly_abort (123); } /* Suspend the current level. */#if defined(DEBUG_CP_BINDING_LEVELS) binding_depth--; indent (); fprintf (stderr, "suspend %s level 0x%08x line %d\n", (is_class_level) ? "class" : "block", current_binding_level, lineno); if (is_class_level != (current_binding_level == class_binding_level))#if 0 /* XXX Don't abort when we're watching how things are being managed. */ abort ();#else { indent (); fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); }#endif is_class_level = 0;#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ { register struct binding_level *level = current_binding_level; current_binding_level = current_binding_level->level_chain;#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */ if (level->binding_depth != binding_depth) abort ();#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ class_binding_level = current_binding_level; if (class_binding_level->parm_flag != 2) class_binding_level = 0; while (current_binding_level->parm_flag == 2) current_binding_level = current_binding_level->level_chain; }}voidresume_binding_level (b) struct binding_level *b;{ if (class_binding_level) {#if 1 /* These are here because we cannot deal with shadows yet. */ sorry ("cannot resume a namespace inside class"); return;#else b->level_chain = class_binding_level; class_binding_level = (struct binding_level *)0;#endif } else {#if 1 /* These are here because we cannot deal with shadows yet. */ if (b->level_chain != current_binding_level) { sorry ("cannot resume a namespace inside a different namespace"); return; }#endif b->level_chain = current_binding_level; } 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) */}/* Nonzero if we are currently in the global binding level. */intglobal_bindings_p (){ return current_binding_level == global_binding_level;}/* 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. */inttoplevel_bindings_p (){ struct binding_level *b = current_binding_level; while (1) { if (b == global_binding_level) return 1; if (! b->namespace_p) return 0; b=b->level_chain; }}/* Nonzero if this is a namespace scope. */intnamespace_bindings_p (){ return current_binding_level->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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -