📄 decl.c
字号:
/* Resume the variable caches. */ decls = current_binding_level->names; /* Restore the meanings of the local variables of this level. */ for (link = decls; link; link = TREE_CHAIN (link)) { /* If it doesn't have a name, there is nothing left to do with it. */ if (DECL_NAME (link) == NULL_TREE) continue; IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = link; /* If this is a TYPE_DECL, push it into the type value slot. */ if (TREE_CODE (link) == TYPE_DECL) SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (link), TREE_TYPE (link)); }}/* Delete the node BLOCK from the current binding level. This is used for the block inside a stmt expr ({...}) so that the block can be reinserted where appropriate. */voiddelete_block (block) tree block;{ tree t; if (current_binding_level->blocks == block) current_binding_level->blocks = TREE_CHAIN (block); for (t = current_binding_level->blocks; t;) { if (TREE_CHAIN (t) == block) TREE_CHAIN (t) = TREE_CHAIN (block); else t = TREE_CHAIN (t); } TREE_CHAIN (block) = NULL_TREE; /* Clear TREE_USED which is always set by poplevel. The flag is set again if insert_block is called. */ TREE_USED (block) = 0;}/* Insert BLOCK at the end of the list of subblocks of the current binding level. This is used when a BIND_EXPR is expanded, to handle the BLOCK node inside the BIND_EXPR. */voidinsert_block (block) tree block;{ TREE_USED (block) = 1; current_binding_level->blocks = chainon (current_binding_level->blocks, block);}/* Add BLOCK to the current list of blocks for this binding contour. */voidadd_block_current_level (block) tree block;{ current_binding_level->blocks = chainon (current_binding_level->blocks, block);}/* Set the BLOCK node for the innermost scope (the one we are currently in). */voidset_block (block) register tree block;{ current_binding_level->this_block = block;}/* Do a pushlevel for class declarations. */voidpushlevel_class (){ register struct binding_level *newlevel; /* 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 (); }#if defined(DEBUG_CP_BINDING_LEVELS) is_class_level = 1;#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ push_binding_level (newlevel, 0, 0); decl_stack = push_decl_level (decl_stack, &decl_obstack); class_binding_level = current_binding_level; class_binding_level->parm_flag = 2; /* We have just pushed into a new binding level. Now, fake out the rest of the compiler. Set the `current_binding_level' back to point to the most closely containing non-class binding level. */ do { current_binding_level = current_binding_level->level_chain; } while (current_binding_level->parm_flag == 2);}/* ...and a poplevel for class declarations. FORCE is used to force clearing out of CLASS_VALUEs after a class definition. */treepoplevel_class (force) int force;{ register struct binding_level *level = class_binding_level; tree block = NULL_TREE; tree shadowed; my_friendly_assert (level != 0, 354); decl_stack = pop_stack_level (decl_stack); for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed); /* If we're leaving a toplevel class, don't bother to do the setting of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot shouldn't even be used when current_class_type isn't set, and second, if we don't touch it here, we're able to use the cache effect if the next time we're entering a class scope, it is the same class. */ if (current_class_depth != 1 || force) for (shadowed = level->class_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed); else /* Remember to save what IDENTIFIER's were bound in this scope so we can recover from cache misses. */ { previous_class_type = current_class_type; previous_class_values = class_binding_level->class_shadowed; } for (shadowed = level->type_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed); GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level, (HOST_WIDE_INT) class_binding_level->level_chain, class_binding_level->parm_flag, class_binding_level->keep); if (class_binding_level->parm_flag != 2) class_binding_level = (struct binding_level *)0; /* Now, pop out of the the binding level which we created up in the `pushlevel_class' routine. */#if defined(DEBUG_CP_BINDING_LEVELS) is_class_level = 1;#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ pop_binding_level (); return block;}/* For debugging. */static int no_print_functions = 0;static int no_print_builtins = 0;voidprint_binding_level (lvl) struct binding_level *lvl;{ tree t; int i = 0, len; fprintf (stderr, " blocks="); fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks); fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d", list_length (lvl->incomplete), lvl->parm_flag, lvl->keep); if (lvl->tag_transparent) fprintf (stderr, " tag-transparent"); if (lvl->more_cleanups_ok) fprintf (stderr, " more-cleanups-ok"); if (lvl->have_cleanups) fprintf (stderr, " have-cleanups"); fprintf (stderr, "\n"); if (lvl->names) { fprintf (stderr, " names:\t"); /* We can probably fit 3 names to a line? */ for (t = lvl->names; t; t = TREE_CHAIN (t)) { if (no_print_functions && (TREE_CODE (t) == FUNCTION_DECL)) continue; if (no_print_builtins && (TREE_CODE (t) == TYPE_DECL) && (!strcmp (DECL_SOURCE_FILE (t),"<built-in>"))) continue; /* Function decls tend to have longer names. */ if (TREE_CODE (t) == FUNCTION_DECL) len = 3; else len = 2; i += len; if (i > 6) { fprintf (stderr, "\n\t"); i = len; } print_node_brief (stderr, "", t, 0); if (t == error_mark_node) break; } if (i) fprintf (stderr, "\n"); } if (lvl->tags) { fprintf (stderr, " tags:\t"); i = 0; for (t = lvl->tags; t; t = TREE_CHAIN (t)) { if (TREE_PURPOSE (t) == NULL_TREE) len = 3; else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t))) len = 2; else len = 4; i += len; if (i > 5) { fprintf (stderr, "\n\t"); i = len; } if (TREE_PURPOSE (t) == NULL_TREE) { print_node_brief (stderr, "<unnamed-typedef", TREE_VALUE (t), 0); fprintf (stderr, ">"); } else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t))) print_node_brief (stderr, "", TREE_VALUE (t), 0); else { print_node_brief (stderr, "<typedef", TREE_PURPOSE (t), 0); print_node_brief (stderr, "", TREE_VALUE (t), 0); fprintf (stderr, ">"); } } if (i) fprintf (stderr, "\n"); } if (lvl->shadowed) { fprintf (stderr, " shadowed:"); for (t = lvl->shadowed; t; t = TREE_CHAIN (t)) { fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t))); } fprintf (stderr, "\n"); } if (lvl->class_shadowed) { fprintf (stderr, " class-shadowed:"); for (t = lvl->class_shadowed; t; t = TREE_CHAIN (t)) { fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t))); } fprintf (stderr, "\n"); } if (lvl->type_shadowed) { fprintf (stderr, " type-shadowed:"); for (t = lvl->type_shadowed; t; t = TREE_CHAIN (t)) { fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t))); } fprintf (stderr, "\n"); }}voidprint_other_binding_stack (stack) struct binding_level *stack;{ struct binding_level *level; for (level = stack; level != global_binding_level; level = level->level_chain) { fprintf (stderr, "binding level "); fprintf (stderr, HOST_PTR_PRINTF, level); fprintf (stderr, "\n"); print_binding_level (level); }}voidprint_binding_stack (){ struct binding_level *b; fprintf (stderr, "current_binding_level="); fprintf (stderr, HOST_PTR_PRINTF, current_binding_level); fprintf (stderr, "\nclass_binding_level="); fprintf (stderr, HOST_PTR_PRINTF, class_binding_level); fprintf (stderr, "\nglobal_binding_level="); fprintf (stderr, HOST_PTR_PRINTF, global_binding_level); fprintf (stderr, "\n"); if (class_binding_level) { for (b = class_binding_level; b; b = b->level_chain) if (b == current_binding_level) break; if (b) b = class_binding_level; else b = current_binding_level; } else b = current_binding_level; print_other_binding_stack (b); fprintf (stderr, "global:\n"); print_binding_level (global_binding_level);}extern char * first_global_object_name;/* Get a unique name for each call to this routine for unnamed namespaces. Mostly copied from get_file_function_name. */static treeget_unique_name (){ static int temp_name_counter = 0; char *buf; register char *p; if (first_global_object_name) p = first_global_object_name; else if (main_input_filename) p = main_input_filename; else p = input_filename;#define UNNAMED_NAMESPACE_FORMAT "__%s_%d" buf = (char *) alloca (sizeof (UNNAMED_NAMESPACE_FORMAT) + strlen (p)); sprintf (buf, UNNAMED_NAMESPACE_FORMAT, p, temp_name_counter++); /* Don't need to pull weird characters out of global names. */ if (p != first_global_object_name) { for (p = buf+11; *p; p++) if (! ((*p >= '0' && *p <= '9')#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */ || *p == '$'#endif#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */ || *p == '.'#endif || (*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z'))) *p = '_'; } return get_identifier (buf);}/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we select a name that is unique to this compilation unit. */voidpush_namespace (name) tree name;{#if 1 static int warned; if (! warned) sorry ("namespace"); warned = 1;#else extern tree current_namespace; tree old_id = get_namespace_id (); char *buf; tree d; if (! name) { /* Create a truly ugly name! */ name = get_unique_name (); } d = build_lang_decl (NAMESPACE_DECL, name, void_type_node); /* Mark them as external, so redeclaration_error_message doesn't think they are duplicates. */ DECL_EXTERNAL (d) = 1; d = pushdecl (d); if (NAMESPACE_LEVEL (d) == 0) { /* This is new for this compilation unit. */ pushlevel (0); declare_namespace_level (); NAMESPACE_LEVEL (d) = current_binding_level; } else resume_level (NAMESPACE_LEVEL (d)); /* This code is just is bit old now... */ current_namespace = tree_cons (NULL_TREE, name, current_namespace); buf = (char *) alloca (4 + (old_id ? IDENTIFIER_LENGTH (old_id) : 0) + IDENTIFIER_LENGTH (name)); sprintf (buf, "%s%s", old_id ? IDENTIFIER_POINTER (old_id) : "", IDENTIFIER_POINTER (name)); TREE_PURPOSE (current_namespace) = get_identifier (buf);#endif}/* Pop from the scope of the current namespace. */voidpop_namespace (){#if 0 extern tree current_namespace; tree decls, link; current_namespace = TREE_CHAIN (current_namespace); /* 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))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -