From e880f232c9e7adf629dfba9807fc624be2ec79ce Mon Sep 17 00:00:00 2001 From: gdr Date: Tue, 23 Sep 2003 15:42:21 +0000 Subject: [PATCH] * cp-tree.h (scope_kind): Add new enumerator. (keep_next_level): Change parameter type to bool. (begin_scope): Change prototype. (pushlevel): Remove declaration. * decl.c (push_binding_level): Fold in begin_scope. Remove. (struct cp_binding_level): Remove tag_tranparent field. Make keep of bitsize one. (keep_next_level_flag): Make a bool. (cxx_scope_descriptor): Update scope names table (make_cxx_scope): Fold in begin_scope. Remove.. (namespace_scope_ht_size): New function. (begin_scope): Change prototype. Return a scope. Tidy. (kept_level_p): Update. (pushlevel): Remove. (maybe_push_cleanup_level): Simplify. (poplevel): Update for sk_cleanup and keep change. (print_binding_level): Likewise. (initial_push_namespace_scope): Fold in begin_scope. Remove. (push_namespace): Update. (pushtag): Likewise. (lookup_tag): Likewise. (lookup_name_current_level): Likewise. (lookup_type_current_level): Likewise. (cxx_init_decl_processing): Likewise. (start_function): Likewise. (begin_function_body): Likewise. (start_method): Likewise. * pt.c (push_inline_template_parms_recursive): Likewise. (begin_template_parm_list): Likewise. (begin_specialization): Likewise. * semantics.c (do_pushlevel): Likewise. (begin_compound_stmt): Likewise. (begin_stmt_expr): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71683 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 36 ++++++++++ gcc/cp/cp-tree.h | 8 ++- gcc/cp/decl.c | 204 +++++++++++++++++++++++++---------------------------- gcc/cp/pt.c | 7 +- gcc/cp/semantics.c | 6 +- 5 files changed, 146 insertions(+), 115 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7f85eaf..5804f9f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,39 @@ +2003-09-22 Gabriel Dos Reis + + * cp-tree.h (scope_kind): Add new enumerator. + (keep_next_level): Change parameter type to bool. + (begin_scope): Change prototype. + (pushlevel): Remove declaration. + * decl.c (push_binding_level): Fold in begin_scope. Remove. + (struct cp_binding_level): Remove tag_tranparent field. Make keep + of bitsize one. + (keep_next_level_flag): Make a bool. + (cxx_scope_descriptor): Update scope names table + (make_cxx_scope): Fold in begin_scope. Remove.. + (namespace_scope_ht_size): New function. + (begin_scope): Change prototype. Return a scope. Tidy. + (kept_level_p): Update. + (pushlevel): Remove. + (maybe_push_cleanup_level): Simplify. + (poplevel): Update for sk_cleanup and keep change. + (print_binding_level): Likewise. + (initial_push_namespace_scope): Fold in begin_scope. Remove. + (push_namespace): Update. + (pushtag): Likewise. + (lookup_tag): Likewise. + (lookup_name_current_level): Likewise. + (lookup_type_current_level): Likewise. + (cxx_init_decl_processing): Likewise. + (start_function): Likewise. + (begin_function_body): Likewise. + (start_method): Likewise. + * pt.c (push_inline_template_parms_recursive): Likewise. + (begin_template_parm_list): Likewise. + (begin_specialization): Likewise. + * semantics.c (do_pushlevel): Likewise. + (begin_compound_stmt): Likewise. + (begin_stmt_expr): Likewise. + 2003-09-21 Richard Henderson * class.c, cp-tree.h, decl.c, decl2.c, error.c, init.c, diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ef38d55..5118b78 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2935,6 +2935,9 @@ typedef enum scope_kind { is initialized by using "memset" to set the contents to zero, and the default scope kind is "sk_block". */ + sk_cleanup, /* A scope for (pseudo-)scope for cleanup. It is + peusdo in that it is transparent to name lookup + activities. */ sk_try, /* A try-block. */ sk_catch, /* A catch-block. */ sk_for, /* The scope of the variable declared in a @@ -3609,7 +3612,6 @@ extern void adjust_clone_args (tree); extern int global_bindings_p (void); extern int kept_level_p (void); extern tree getdecls (void); -extern void pushlevel (int); extern void insert_block (tree); extern void set_block (tree); extern tree pushdecl (tree); @@ -3622,12 +3624,12 @@ extern void cxx_pop_function_context (struct function *); extern void cxx_mark_function_context (struct function *); extern int toplevel_bindings_p (void); extern int namespace_bindings_p (void); -extern void keep_next_level (int); +extern void keep_next_level (bool); extern scope_kind innermost_scope_kind (void); extern int template_parm_scope_p (void); extern void set_class_shadows (tree); extern void maybe_push_cleanup_level (tree); -extern void begin_scope (scope_kind); +extern cxx_scope *begin_scope (scope_kind, tree); extern void finish_scope (void); extern void resume_level (struct cp_binding_level *); extern void delete_block (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 892affa..9538a1e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA. */ static tree grokparms (tree); static const char *redeclaration_error_message (tree, tree); -static void push_binding_level (cxx_scope *); static void pop_binding_level (void); static void suspend_binding_level (void); static void resume_binding_level (struct cp_binding_level *); @@ -382,19 +381,15 @@ struct cp_binding_level GTY(()) only valid if KIND == SK_TEMPLATE_PARMS. */ bool explicit_spec_p : 1; - /* 1 means make a BLOCK for this level regardless of all else. - 2 for temporary binding contours created by the compiler. */ - unsigned keep : 2; + /* true means make a BLOCK for this level regardless of all else. */ + unsigned keep : 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 this level "doesn't exist" for tags. */ - unsigned tag_transparent : 1; - - /* 20 bits left to fill a 32-bit word. */ + /* 22 bits left to fill a 32-bit word. */ }; #define NULL_BINDING_LEVEL ((struct cp_binding_level *) NULL) @@ -414,9 +409,9 @@ struct cp_binding_level GTY(()) static GTY((deletable (""))) struct cp_binding_level *free_binding_level; -/* Nonzero means unconditionally make a BLOCK for the next level pushed. */ +/* true means unconditionally make a BLOCK for the next level pushed. */ -static int keep_next_level_flag; +static bool keep_next_level_flag; /* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the @@ -452,6 +447,7 @@ cxx_scope_descriptor (cxx_scope *scope) enumerators. */ static const char* scope_kind_names[] = { "block-scope", + "cleanup-scope", "try-scope", "catch-scope", "for-scope", @@ -461,8 +457,10 @@ cxx_scope_descriptor (cxx_scope *scope) "template-parameter-scope", "template-explicit-spec-scope" }; + const scope_kind kind = scope->explicit_spec_p + ? sk_template_spec : scope->kind; - return scope_kind_names[scope->kind]; + return scope_kind_names[kind]; } /* Output a debugging information about SCOPE when performning @@ -478,10 +476,27 @@ cxx_scope_debug (cxx_scope *scope, int line, const char *action) verbatim ("%s %s %p %d\n", action, desc, (void *) scope, line); } -/* Construct a scope that may be TAG-TRANSPARENT, the sub-blocks of - which may be KEPT. */ -static inline cxx_scope * -make_cxx_scope (bool tag_transparent, int keep) +/* Return the estimated initial size of the hashtable of a NAMESPACE + scope. */ + +static inline size_t +namespace_scope_ht_size (tree ns) +{ + tree name = DECL_NAME (ns); + + return name == std_identifier + ? NAMESPACE_STD_HT_SIZE + : (name == global_scope_name + ? GLOBAL_SCOPE_HT_SIZE + : NAMESPACE_ORDINARY_HT_SIZE); +} + +/* Create a new KIND scope and make it the top of the active scopes stack. + ENTITY is the scope of the associated C++ entity (namespace, class, + function); it is NULL otherwise. */ + +cxx_scope * +begin_scope (scope_kind kind, tree entity) { cxx_scope *scope; @@ -493,31 +508,62 @@ make_cxx_scope (bool tag_transparent, int keep) } else scope = ggc_alloc (sizeof (cxx_scope)); - memset (scope, 0, sizeof (cxx_scope)); - scope->tag_transparent = tag_transparent; - scope->keep = keep; + + scope->this_entity = entity; scope->more_cleanups_ok = true; + switch (kind) + { + case sk_cleanup: + scope->keep = true; + break; + + case sk_template_spec: + scope->explicit_spec_p = true; + kind = sk_template_parms; + /* fall through */ + case sk_template_parms: + case sk_block: + case sk_try: + case sk_catch: + case sk_for: + case sk_class: + case sk_function_parms: + scope->keep = keep_next_level_flag; + break; - return scope; -} + case sk_namespace: + scope->type_decls = binding_table_new (namespace_scope_ht_size (entity)); + NAMESPACE_LEVEL (entity) = scope; + VARRAY_TREE_INIT (scope->static_decls, + DECL_NAME (entity) == std_identifier + || DECL_NAME (entity) == global_scope_name + ? 200 : 10, + "Static declarations"); + break; -static void -push_binding_level (cxx_scope *newlevel) -{ - /* Add this level to the front of the chain (stack) of levels that - are active. */ - newlevel->level_chain = current_binding_level; - current_binding_level = newlevel; + default: + /* Should not happen. */ + my_friendly_assert (false, 20030922); + break; + } + scope->kind = kind; + + /* Add it to the front of currently active scopes stack. */ + scope->level_chain = current_binding_level; + current_binding_level = scope; + keep_next_level_flag = false; if (ENABLE_SCOPE_CHECKING) { - newlevel->binding_depth = binding_depth; + scope->binding_depth = binding_depth; indent (binding_depth); - cxx_scope_debug (newlevel, input_location.line, "push"); + cxx_scope_debug (scope, input_location.line, "push"); is_class_level = 0; binding_depth++; } + + return scope; } /* Find the innermost enclosing class scope, and reset @@ -664,12 +710,12 @@ namespace_bindings_p (void) return b->kind == sk_namespace; } -/* If KEEP is nonzero, make a BLOCK node for the next binding level, +/* If KEEP is true, make a BLOCK node for the next binding level, unconditionally. Otherwise, use the normal logic to decide whether or not to create a BLOCK. */ void -keep_next_level (int keep) +keep_next_level (bool keep) { keep_next_level_flag = keep; } @@ -681,9 +727,9 @@ kept_level_p (void) { return (current_binding_level->blocks != NULL_TREE || current_binding_level->keep + || current_binding_level->kind == sk_cleanup || current_binding_level->names != NULL_TREE - || (current_binding_level->type_decls != NULL - && !current_binding_level->tag_transparent)); + || current_binding_level->type_decls != NULL); } /* Returns the kind of the innermost scope. */ @@ -799,17 +845,6 @@ set_class_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. */ - -void -pushlevel (int tag_transparent) -{ - push_binding_level (make_cxx_scope (tag_transparent, keep_next_level_flag)); - keep_next_level_flag = 0; -} - /* We're defining an object of type TYPE. If it needs a cleanup, but we're not allowed to add any more objects with cleanups to the current scope, create a new binding level. */ @@ -820,27 +855,11 @@ maybe_push_cleanup_level (tree type) if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) && current_binding_level->more_cleanups_ok == 0) { - keep_next_level (2); - pushlevel (1); + begin_scope (sk_cleanup, NULL); clear_last_expr (); add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1); } } - -/* Enter a new scope. The KIND indicates what kind of scope is being - created. */ - -void -begin_scope (scope_kind sk) -{ - pushlevel (0); - if (sk == sk_template_spec) - { - current_binding_level->explicit_spec_p = true; - sk = sk_template_parms; - } - current_binding_level->kind = sk; -} /* Exit the current scope. */ @@ -1116,12 +1135,13 @@ poplevel (int keep, int reverse, int functionbody) tree block = NULL_TREE; tree decl; int leaving_for_scope; + scope_kind kind; timevar_push (TV_NAME_LOOKUP); my_friendly_assert (current_binding_level->kind != sk_class, 19990916); - real_functionbody = (current_binding_level->keep == 2 + real_functionbody = (current_binding_level->kind == sk_cleanup ? ((functionbody = 0), tmp) : functionbody); subblocks = functionbody >= 0 ? current_binding_level->blocks : 0; @@ -1133,7 +1153,7 @@ poplevel (int keep, int reverse, int functionbody) rather than the end. This hack is no longer used. */ my_friendly_assert (keep == 0 || keep == 1, 0); - if (current_binding_level->keep == 1) + if (current_binding_level->keep) keep = 1; /* Any uses of undefined labels, and any defined labels, now operate @@ -1365,7 +1385,7 @@ poplevel (int keep, int reverse, int functionbody) pop_labels (block); } - tmp = current_binding_level->keep; + kind = current_binding_level->kind; pop_binding_level (); if (functionbody) @@ -1390,7 +1410,7 @@ poplevel (int keep, int reverse, int functionbody) TREE_USED (block) = 1; /* Take care of compiler's internal binding structures. */ - if (tmp == 2) + if (kind == sk_cleanup) { tree scope_stmts; @@ -1461,9 +1481,7 @@ pushlevel_class (void) if (ENABLE_SCOPE_CHECKING) is_class_level = 1; - begin_scope (sk_class); - class_binding_level = current_binding_level; - class_binding_level->this_entity = current_class_type; + class_binding_level = begin_scope (sk_class, current_class_type); } /* ...and a poplevel for class declarations. */ @@ -1770,8 +1788,6 @@ print_binding_level (struct cp_binding_level* lvl) tree t; int i = 0, len; fprintf (stderr, " blocks=" HOST_PTR_PRINTF, (void *) lvl->blocks); - if (lvl->tag_transparent) - fprintf (stderr, " tag-transparent"); if (lvl->more_cleanups_ok) fprintf (stderr, " more-cleanups-ok"); if (lvl->have_cleanups) @@ -1877,30 +1893,6 @@ print_binding_stack (void) the identifier is polymorphic, with three possible values: NULL_TREE, a list of "cxx_binding"s. */ - -/* Push the initial binding contour of NAMESPACE-scope. Any subsequent - push of NS is actually a resume. */ -static void -initial_push_namespace_scope (tree ns) -{ - tree name = DECL_NAME (ns); - cxx_scope *scope; - - begin_scope (sk_namespace); - scope = current_binding_level; - scope->type_decls = binding_table_new (name == std_identifier - ? NAMESPACE_STD_HT_SIZE - : (name == global_scope_name - ? GLOBAL_SCOPE_HT_SIZE - : NAMESPACE_ORDINARY_HT_SIZE)); - VARRAY_TREE_INIT (scope->static_decls, - name == std_identifier || name == global_scope_name - ? 200 : 10, - "Static declarations"); - scope->this_entity = ns; - NAMESPACE_LEVEL (ns) = scope; -} - /* 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. */ @@ -1954,7 +1946,7 @@ push_namespace (tree name) d = build_lang_decl (NAMESPACE_DECL, name, void_type_node); DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace); d = pushdecl (d); - initial_push_namespace_scope (d); + begin_scope (sk_namespace, d); } else resume_binding_level (NAMESPACE_LEVEL (d)); @@ -2400,7 +2392,7 @@ push_local_name (tree decl) } /* Push a tag name NAME for struct/class/union/enum type TYPE. - Normally put it into the inner-most non-tag-transparent scope, + Normally put it into the inner-most non-sk_cleanup scope, but if GLOBALIZE is true, put it in the inner-most non-class scope. The latter is needed for implicit declarations. */ @@ -2411,7 +2403,7 @@ pushtag (tree name, tree type, int globalize) timevar_push (TV_NAME_LOOKUP); b = current_binding_level; - while (b->tag_transparent + while (b->kind == sk_cleanup || (b->kind == sk_class && (globalize /* We may be defining a new type in the initializer @@ -2553,7 +2545,7 @@ clear_anon_tags (void) return; b = current_binding_level; - while (b->tag_transparent) + while (b->kind == sk_cleanup) b = b->level_chain; if (b->type_decls != NULL) binding_table_remove_anonymous_types (b->type_decls); @@ -5015,7 +5007,7 @@ follow_tag_typedef (tree type) return the structure (or union or enum) definition for that name. Searches binding levels from BINDING_SCOPE up to the global level. If THISLEVEL_ONLY is nonzero, searches only the specified context - (but skips any tag-transparent contexts to find one that is + (but skips any sk_cleanup contexts to find one that is meaningful for tags). FORM says which kind of type the caller wants; it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE. @@ -5103,7 +5095,7 @@ lookup_tag (enum tree_code form, tree name, POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type); } } - if (thislevel_only && ! level->tag_transparent) + if (thislevel_only && level->kind != sk_cleanup) { if (level->kind == sk_template_parms && allow_template_parms_p) { @@ -5869,7 +5861,7 @@ lookup_name_current_level (tree name) if (BINDING_SCOPE (IDENTIFIER_BINDING (name)) == b) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name)); - if (b->keep == 2) + if (b->kind == sk_cleanup) b = b->level_chain; else break; @@ -5899,7 +5891,7 @@ lookup_type_current_level (tree name) if (purpose_member (name, b->type_shadowed)) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (name)); - if (b->keep == 2) + if (b->kind == sk_cleanup) b = b->level_chain; else break; @@ -6100,7 +6092,7 @@ cxx_init_decl_processing (void) my_friendly_assert (global_namespace == NULL_TREE, 375); global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name, void_type_node); - initial_push_namespace_scope (global_namespace); + begin_scope (sk_namespace, global_namespace); current_lang_name = NULL_TREE; @@ -13582,7 +13574,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags) DECL_INTERFACE_KNOWN (decl1) = 1; } - begin_scope (sk_function_parms); + begin_scope (sk_function_parms, decl1); ++function_depth; @@ -13834,7 +13826,7 @@ begin_function_body (void) /* Always keep the BLOCK node associated with the outermost pair of curly braces of a function. These are needed for correct operation of dwarfout.c. */ - keep_next_level (1); + keep_next_level (true); stmt = begin_compound_stmt (/*has_no_scope=*/false); COMPOUND_STMT_BODY_BLOCK (stmt) = 1; @@ -14159,7 +14151,7 @@ start_method (tree declspecs, tree declarator, tree attrlist) cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0); /* Make a place for the parms */ - begin_scope (sk_function_parms); + begin_scope (sk_function_parms, fndecl); DECL_IN_AGGR_P (fndecl) = 1; return fndecl; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 12baea1..aad6c60 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -352,7 +352,8 @@ push_inline_template_parms_recursive (tree parmlist, int levels) parms, current_template_parms); TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1; - pushlevel (0); + begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec, + NULL); for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) { tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); @@ -609,7 +610,7 @@ begin_template_parm_list (void) pushtag contains special code to call pushdecl_with_scope on the TEMPLATE_DECL for S2. */ - begin_scope (sk_template_parms); + begin_scope (sk_template_parms, NULL); ++processing_template_decl; ++processing_template_parmlist; note_template_header (0); @@ -653,7 +654,7 @@ check_specialization_scope (void) void begin_specialization (void) { - begin_scope (sk_template_spec); + begin_scope (sk_template_spec, NULL); note_template_header (1); check_specialization_scope (); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ef42579..6650bff 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -360,7 +360,7 @@ do_pushlevel (scope_kind sk) { if (!processing_template_decl) add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0); - begin_scope (sk); + begin_scope (sk, NULL); } } @@ -1004,7 +1004,7 @@ begin_compound_stmt (bool has_no_scope) statement-expression. But, if it's a statement-expression with a scopeless block, there's nothing to keep, and we don't want to accidentally keep a block *inside* the scopeless block. */ - keep_next_level (0); + keep_next_level (false); return r; } @@ -1408,7 +1408,7 @@ begin_stmt_expr (void) last_expr_type = NULL_TREE; - keep_next_level (1); + keep_next_level (true); return last_tree; } -- 2.7.4