📄 decl.c
字号:
decl_stack = pop_stack_level (decl_stack); /* 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) { struct binding_level* b; /* Clear out our IDENTIFIER_CLASS_VALUEs. */ for (shadowed = level->class_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE; /* Find the next enclosing class, and recreate IDENTIFIER_CLASS_VALUEs appropriate for that class. */ b = level->level_chain; while (b && b->parm_flag != 2) b = b->level_chain; if (b) for (shadowed = b->class_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) { tree t; t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed)); while (t && BINDING_LEVEL (t) != b) t = TREE_CHAIN (t); if (t) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = BINDING_VALUE (t); } } 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)) SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed)); /* Remove the bindings for all of the class-level declarations. */ for (shadowed = level->class_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed)) pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (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); /* Now, pop out of 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 NULL_TREE;}/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE for any names in enclosing classes. */voidclear_identifier_class_values (){ tree t; if (!class_binding_level) return; for (t = class_binding_level->class_shadowed; t; t = TREE_CHAIN (t)) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;}/* Returns non-zero if T is a virtual function table. */intvtable_decl_p (t, data) tree t; void *data ATTRIBUTE_UNUSED;{ return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));}/* Returns non-zero if T is a TYPE_DECL for a type with virtual functions. */intvtype_decl_p (t, data) tree t; void *data ATTRIBUTE_UNUSED;{ return (TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) != error_mark_node && TYPE_LANG_SPECIFIC (TREE_TYPE (t)) && CLASSTYPE_VSIZE (TREE_TYPE (t)));}/* Returns non-zero if T is a signature table. */int sigtable_decl_p (t, data) tree t; void *data ATTRIBUTE_UNUSED;{ return (TREE_CODE (t) == VAR_DECL && TREE_TYPE (t) != error_mark_node && IS_SIGNATURE (TREE_TYPE (t)));}/* Walk all the namespaces contained NAMESPACE, including NAMESPACE itself, calling F for each. The DATA is passed to F as well. */static intwalk_namespaces_r (namespace, f, data) tree namespace; walk_namespaces_fn f; void *data;{ tree current; int result = 0; result |= (*f) (namespace, data); for (current = NAMESPACE_LEVEL (namespace)->names; current; current = TREE_CHAIN (current)) { if (TREE_CODE (current) != NAMESPACE_DECL || DECL_NAMESPACE_ALIAS (current)) continue; if (!DECL_LANG_SPECIFIC (current)) { /* Hmm. std. */ my_friendly_assert (current == std_node, 393); continue; } /* We found a namespace. */ result |= walk_namespaces_r (current, f, data); } return result;}/* Walk all the namespaces, calling F for each. The DATA is passed to F as well. */intwalk_namespaces (f, data) walk_namespaces_fn f; void *data;{ return walk_namespaces_r (global_namespace, f, data);}struct walk_globals_data { walk_globals_pred p; walk_globals_fn f; void *data;};/* Walk the global declarations in NAMESPACE. Whenever one is found for which P returns non-zero, call F with its address. If any call to F returns a non-zero value, return a non-zero value. */static int walk_globals_r (namespace, data) tree namespace; void *data;{ struct walk_globals_data* wgd = (struct walk_globals_data *) data; walk_globals_pred p = wgd->p; walk_globals_fn f = wgd->f; void *d = wgd->data; tree *t; int result = 0; t = &NAMESPACE_LEVEL (namespace)->names; while (*t) { tree glbl = *t; if ((*p) (glbl, d)) result |= (*f) (t, d); /* If F changed *T, then *T still points at the next item to examine. */ if (*t == glbl) t = &TREE_CHAIN (*t); } return result;}/* Walk the global declarations. Whenever one is found for which P returns non-zero, call F with its address. If any call to F returns a non-zero value, return a non-zero value. */intwalk_globals (p, f, data) walk_globals_pred p; walk_globals_fn f; void *data;{ struct walk_globals_data wgd; wgd.p = p; wgd.f = f; wgd.data = data; return walk_namespaces (walk_globals_r, &wgd);}/* Call wrapup_globals_declarations for the globals in NAMESPACE. If DATA is non-NULL, this is the last time we will call wrapup_global_declarations for this NAMESPACE. */intwrapup_globals_for_namespace (namespace, data) tree namespace; void *data;{ tree globals = NAMESPACE_LEVEL (namespace)->names; int len = list_length (globals); tree *vec = (tree *) alloca (sizeof (tree) * len); int i; int result; tree decl; int last_time = (data != 0); if (last_time && namespace == global_namespace) /* Let compile_file handle the global namespace. */ return 0; /* Process the decls in reverse order--earliest first. Put them into VEC from back to front, then take out from front. */ for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) vec[len - i - 1] = decl; if (last_time) { check_global_declarations (vec, len); return 0; } /* Temporarily mark vtables as external. That prevents wrapup_global_declarations from writing them out; we must process them ourselves in finish_vtable_vardecl. */ for (i = 0; i < len; ++i) if (vtable_decl_p (vec[i], /*data=*/0) && !DECL_EXTERNAL (vec[i])) { DECL_NOT_REALLY_EXTERN (vec[i]) = 1; DECL_EXTERNAL (vec[i]) = 1; } /* Write out any globals that need to be output. */ result = wrapup_global_declarations (vec, len); /* Undo the hack to DECL_EXTERNAL above. */ for (i = 0; i < len; ++i) if (vtable_decl_p (vec[i], /*data=*/0) && DECL_NOT_REALLY_EXTERN (vec[i])) { DECL_NOT_REALLY_EXTERN (vec[i]) = 0; DECL_EXTERNAL (vec[i]) = 0; } return result;}/* 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->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);}/* Namespace binding access rou
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -