This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH to decl.c: Factor debug code
- From: Gabriel Dos Reis <gdr at integrable-solutions dot net>
- To: gcc-patches at gcc dot gnu dot org
- Cc: mark at codesourcery dot com, jason at redhat dot com
- Date: 30 May 2003 03:12:26 +0200
- Subject: C++ PATCH to decl.c: Factor debug code
- Organization: Integrable Solutions
Hi,
This is another fall out of the name-lookup performance work, when debugging.
This patches
1) factors out code duplicated in pushlevel and pushlevel_class;
2) factors out code duplicated in push_namespace and
cxx_init_decl_processing for handling global scope and
constructing ordinary namespace.
There were a comment in push_namespace saying that
global_namespace is contructed elsewhere. This patch makes that
much more appearant in push_namespace.
3) improves the debugging facilities for binding contours. Now
scopes other than class-scope or block-scope are accurately reported.
Bootstrapped and resgtested on an i686-pc-linux-gnu.
OK for mainline?
OK for branch?
-- Gaby
2003-05-30 Gabriel Dos Reis <gdr@integrable-solutions.net>
* decl.c (cp_binding_level::this_entity): Rename from this_class.
(cxx_scope_descriptor): New function.
(cxx_scope_debug): Likewise.
(push_binding_level): Use it.
(pop_binding_level): Likewise.
(suspend_binding_level): Likewise.
(resume_binding_level): Likewise.
(pushlevel_class): Adjust use of this_class.
(pushtag): Likewise.
(lookup_name_real): Likewise.
(global_scope_name): New variable.
(initialize_predefined_identifiers): Initialize it.
(push_namespace): Use it.
(cxx_scope_make): New function.
(pushlevel): Use it.
(pushlevel_class): Likewise.
(push_binding_level): Simplify. Loose the last two arguments.
(make_binding_level): Remove.
(cxx_original_namespace_scope_push): New function.
(push_namespace): Use it. Simplify.
(cxx_init_decl_processing): Likewise.
(declare_namespace_level): Remove.
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.776.2.20
diff -p -r1.776.2.20 cp-tree.h
*** cp-tree.h 19 May 2003 23:29:36 -0000 1.776.2.20
--- cp-tree.h 30 May 2003 00:58:34 -0000
*************** struct diagnostic_context;
*** 218,223 ****
--- 218,224 ----
(flag_abi_version == 0 || flag_abi_version >= (N))
+ typedef struct cp_binding_level cxx_scope;
/* Datatype used to temporarily save C++ bindings (for implicit
instantiations purposes and like). Implemented in decl.c. */
typedef struct cxx_saved_binding cxx_saved_binding;
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.965.2.46
diff -p -r1.965.2.46 decl.c
*** decl.c 29 May 2003 19:10:01 -0000 1.965.2.46
--- decl.c 30 May 2003 00:58:42 -0000
*************** Boston, MA 02111-1307, USA. */
*** 54,66 ****
static tree grokparms PARAMS ((tree));
static const char *redeclaration_error_message PARAMS ((tree, tree));
! static void push_binding_level PARAMS ((struct cp_binding_level *, int,
! int));
static void pop_binding_level PARAMS ((void));
static void suspend_binding_level PARAMS ((void));
static void resume_binding_level PARAMS ((struct cp_binding_level *));
- static struct cp_binding_level *make_binding_level PARAMS ((void));
- static void declare_namespace_level PARAMS ((void));
static int decl_jump_unsafe PARAMS ((tree));
static void storedecls PARAMS ((tree));
static void require_complete_types_for_parms PARAMS ((tree));
--- 54,63 ----
static tree grokparms PARAMS ((tree));
static const char *redeclaration_error_message PARAMS ((tree, tree));
! static void push_binding_level (cxx_scope *);
static void pop_binding_level PARAMS ((void));
static void suspend_binding_level PARAMS ((void));
static void resume_binding_level PARAMS ((struct cp_binding_level *));
static int decl_jump_unsafe PARAMS ((tree));
static void storedecls PARAMS ((tree));
static void require_complete_types_for_parms PARAMS ((tree));
*************** tree cp_global_trees[CPTI_MAX];
*** 203,208 ****
--- 200,208 ----
static GTY(()) tree global_type_node;
+ /* The node that holds the "name" of the global scope. */
+ static GTY(()) tree global_scope_name;
+
/* Expect only namespace names now. */
static int only_namespace_names;
*************** struct cp_binding_level GTY(())
*** 604,611 ****
that were entered and exited one level down. */
tree blocks;
! /* The _TYPE node for this level, if parm_flag == 2. */
! tree this_class;
/* The binding level which this one is contained in (inherits from). */
struct cp_binding_level *level_chain;
--- 604,612 ----
that were entered and exited one level down. */
tree blocks;
! /* The entity (namespace, class, function) the scope of which this
! binding contour corresponds to. Otherwise NULL. */
! tree this_entity;
/* The binding level which this one is contained in (inherits from). */
struct cp_binding_level *level_chain;
*************** indent (unsigned depth)
*** 712,740 ****
putc (' ', stderr);
}
static tree pushdecl_with_scope PARAMS ((tree, struct cp_binding_level *));
static void
! push_binding_level (newlevel, tag_transparent, keep)
! struct cp_binding_level *newlevel;
! int tag_transparent, keep;
{
/* Add this level to the front of the chain (stack) of levels that
are active. */
- memset ((char*) newlevel, 0, sizeof (struct cp_binding_level));
newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
- newlevel->tag_transparent = tag_transparent;
- newlevel->more_cleanups_ok = 1;
- newlevel->keep = keep;
if (ENABLE_SCOPE_CHECKING)
{
newlevel->binding_depth = binding_depth;
indent (binding_depth);
! verbatim ("push %s level %p line %d\n",
! (is_class_level) ? "class" : "block",
! (void *) newlevel, lineno);
is_class_level = 0;
binding_depth++;
}
--- 713,798 ----
putc (' ', stderr);
}
+ /* Return a string describing the kind of SCOPE we have. */
+ static const char *
+ cxx_scope_descriptor (cxx_scope *scope)
+ {
+ const char *desc;
+
+ if (scope->namespace_p)
+ desc = "namespace-scope";
+ else if (scope->parm_flag == 1)
+ desc = "function-prototype-scope";
+ else if (scope->parm_flag == 2)
+ desc = "class-scope";
+ else if (scope->is_for_scope)
+ desc = "for-scope";
+ else if (scope->is_try_scope)
+ desc = "try-scope";
+ else if (scope->is_catch_scope)
+ desc = "catch-scope";
+ else if (scope->template_spec_p)
+ desc = "template-explicit-spec-scope";
+ else if (scope->template_parms_p)
+ desc = "template-prototype-scope";
+ else
+ desc = "block-scope";
+
+ return desc;
+ }
+
+ /* Output a debugging information about SCOPE when performning
+ ACTION at LINE. */
+ static void
+ cxx_scope_debug (cxx_scope *scope, int line, const char *action)
+ {
+ const char *desc = cxx_scope_descriptor (scope);
+ if (scope->this_entity)
+ verbatim ("%s %s(%E) %p %d\n", action, desc,
+ scope->this_entity, (void *) scope, line);
+ else
+ 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 *
+ cxx_scope_make (bool tag_transparent, int keep)
+ {
+ cxx_scope *scope;
+
+ /* Reuse or create a struct for this binding level. */
+ if (!ENABLE_SCOPE_CHECKING && free_binding_level)
+ {
+ scope = free_binding_level;
+ free_binding_level = scope->level_chain;
+ }
+ else
+ scope = ggc_alloc (sizeof (cxx_scope));
+
+ memset (scope, 0, sizeof (cxx_scope));
+ scope->tag_transparent = tag_transparent;
+ scope->keep = keep;
+ scope->more_cleanups_ok = true;
+
+ return scope;
+ }
+
static tree pushdecl_with_scope PARAMS ((tree, struct cp_binding_level *));
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;
if (ENABLE_SCOPE_CHECKING)
{
newlevel->binding_depth = binding_depth;
indent (binding_depth);
! cxx_scope_debug (newlevel, lineno, "push");
is_class_level = 0;
binding_depth++;
}
*************** pop_binding_level ()
*** 766,774 ****
if (ENABLE_SCOPE_CHECKING)
{
indent (--binding_depth);
! verbatim ("pop %s level %p line %d\n",
! (is_class_level) ? "class" : "block",
! (void *) current_binding_level, lineno);
if (is_class_level != (current_binding_level == class_binding_level))
{
indent (binding_depth);
--- 824,830 ----
if (ENABLE_SCOPE_CHECKING)
{
indent (--binding_depth);
! cxx_scope_debug (current_binding_level, lineno, "pop");
if (is_class_level != (current_binding_level == class_binding_level))
{
indent (binding_depth);
*************** suspend_binding_level ()
*** 804,812 ****
if (ENABLE_SCOPE_CHECKING)
{
indent (--binding_depth);
! verbatim("suspend %s level %p line %d\n",
! (is_class_level) ? "class" : "block",
! (void *) current_binding_level, lineno);
if (is_class_level != (current_binding_level == class_binding_level))
{
indent (binding_depth);
--- 860,866 ----
if (ENABLE_SCOPE_CHECKING)
{
indent (--binding_depth);
! cxx_scope_debug (current_binding_level, lineno, "suspend");
if (is_class_level != (current_binding_level == class_binding_level))
{
indent (binding_depth);
*************** resume_binding_level (b)
*** 833,855 ****
{
b->binding_depth = binding_depth;
indent (binding_depth);
! verbatim ("resume %s level %p line %d\n",
! (is_class_level) ? "class" : "block", (void *) b, lineno);
is_class_level = 0;
binding_depth++;
}
}
- /* Create a new `struct cp_binding_level'. */
-
- static
- struct cp_binding_level *
- make_binding_level ()
- {
- /* NOSTRICT */
- return (struct cp_binding_level *) ggc_alloc (sizeof (struct cp_binding_level));
- }
-
/* Nonzero if we are currently in the global binding level. */
int
--- 887,898 ----
{
b->binding_depth = binding_depth;
indent (binding_depth);
! cxx_scope_debug (b, lineno, "resume");
is_class_level = 0;
binding_depth++;
}
}
/* Nonzero if we are currently in the global binding level. */
int
*************** kept_level_p ()
*** 921,932 ****
&& !current_binding_level->tag_transparent));
}
- static void
- declare_namespace_level ()
- {
- current_binding_level->namespace_p = 1;
- }
-
/* Returns nonzero if this scope was created to store template
parameters. */
--- 964,969 ----
*************** void
*** 1040,1060 ****
pushlevel (tag_transparent)
int tag_transparent;
{
- struct cp_binding_level *newlevel;
-
if (cfun && !doing_semantic_analysis_p ())
return;
! /* Reuse or create a struct for this binding level. */
! if (!ENABLE_SCOPE_CHECKING && free_binding_level)
! {
! 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);
keep_next_level_flag = 0;
}
--- 1077,1086 ----
pushlevel (tag_transparent)
int tag_transparent;
{
if (cfun && !doing_semantic_analysis_p ())
return;
! push_binding_level (cxx_scope_make (tag_transparent, keep_next_level_flag));
keep_next_level_flag = 0;
}
*************** set_block (block)
*** 1865,1889 ****
void
pushlevel_class ()
{
- register struct cp_binding_level *newlevel;
-
- /* Reuse or create a struct for this binding level. */
- if (!ENABLE_SCOPE_CHECKING && free_binding_level)
- {
- newlevel = free_binding_level;
- free_binding_level = free_binding_level->level_chain;
- }
- else
- newlevel = make_binding_level ();
-
if (ENABLE_SCOPE_CHECKING)
is_class_level = 1;
! push_binding_level (newlevel, 0, 0);
class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2;
! class_binding_level->this_class = current_class_type;
}
/* ...and a poplevel for class declarations. */
--- 1891,1904 ----
void
pushlevel_class ()
{
if (ENABLE_SCOPE_CHECKING)
is_class_level = 1;
! push_binding_level (cxx_scope_make (false, 0));
class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2;
! class_binding_level->this_entity = current_class_type;
}
/* ...and a poplevel for class declarations. */
*************** set_namespace_binding (name, scope, val)
*** 2428,2433 ****
--- 2443,2470 ----
timevar_pop (TV_NAME_LOOKUP);
}
+ static void
+ cxx_original_namespace_scope_push (tree ns)
+ {
+ tree name = DECL_NAME (ns);
+ cxx_scope *scope;
+
+ pushlevel (0);
+ scope = current_binding_level;
+ scope->namespace_p = true;
+ 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. */
*************** push_namespace (name)
*** 2438,2454 ****
tree d = NULL_TREE;
int need_new = 1;
int implicit_use = 0;
- int global = 0;
timevar_push (TV_NAME_LOOKUP);
!
! if (!global_namespace)
! {
! /* This must be ::. */
! my_friendly_assert (name == get_identifier ("::"), 377);
! global = 1;
! }
! else if (!name)
{
/* The name of anonymous namespace is unique for the translation
unit. */
--- 2475,2489 ----
tree d = NULL_TREE;
int need_new = 1;
int implicit_use = 0;
timevar_push (TV_NAME_LOOKUP);
!
! /* We should not get here if the global_namespace is not yet constructed
! nor if NAME designates the global namespace: The global scope is
! constructed elsewhere. */
! my_friendly_assert (global_namespace != NULL && name != global_scope_name,
! 20030529);
! if (!name)
{
/* The name of anonymous namespace is unique for the translation
unit. */
*************** push_namespace (name)
*** 2481,2503 ****
{
/* Make a new namespace, binding the name to it. */
d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
! /* The global namespace is not pushed, and the global binding
! level is set elsewhere. */
! if (!global)
! {
! DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
! d = pushdecl (d);
! pushlevel (0);
! declare_namespace_level ();
! NAMESPACE_LEVEL (d) = current_binding_level;
! current_binding_level->type_decls =
! binding_table_new (name == std_identifier
! ? NAMESPACE_STD_HT_SIZE
! : NAMESPACE_ORDINARY_HT_SIZE);
! VARRAY_TREE_INIT (current_binding_level->static_decls,
! name != std_identifier ? 10 : 200,
! "Static declarations");
! }
}
else
resume_binding_level (NAMESPACE_LEVEL (d));
--- 2516,2524 ----
{
/* Make a new namespace, binding the name to it. */
d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
! DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
! d = pushdecl (d);
! cxx_original_namespace_scope_push (d);
}
else
resume_binding_level (NAMESPACE_LEVEL (d));
*************** pushtag (name, type, globalize)
*** 2975,2981 ****
of a static member variable. We allow this when
not pedantic, and it is particularly useful for
type punning via an anonymous union. */
! || COMPLETE_TYPE_P (b->this_class))))
b = b->level_chain;
if (b->type_decls == NULL)
--- 2996,3002 ----
of a static member variable. We allow this when
not pedantic, and it is particularly useful for
type punning via an anonymous union. */
! || COMPLETE_TYPE_P (b->this_entity))))
b = b->level_chain;
if (b->type_decls == NULL)
*************** lookup_name_real (name, prefer_type, non
*** 6480,6486 ****
/* Handle access control on types from enclosing or base classes. */
if (binding && ! yylex
&& BINDING_LEVEL (iter) && BINDING_LEVEL (iter)->parm_flag == 2)
! type_access_control (BINDING_LEVEL (iter)->this_class, binding);
if (binding
&& (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
--- 6501,6507 ----
/* Handle access control on types from enclosing or base classes. */
if (binding && ! yylex
&& BINDING_LEVEL (iter) && BINDING_LEVEL (iter)->parm_flag == 2)
! type_access_control (BINDING_LEVEL (iter)->this_entity, binding);
if (binding
&& (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
*************** initialize_predefined_identifiers ()
*** 6794,6799 ****
--- 6815,6821 ----
{ VTABLE_PFN_NAME, &pfn_identifier, 0 },
{ "_vptr", &vptr_identifier, 0 },
{ "__vtt_parm", &vtt_parm_identifier, 0 },
+ { "::", &global_scope_name, 0 },
{ "std", &std_identifier, 0 },
{ NULL, NULL, 0 }
};
*************** cxx_init_decl_processing ()
*** 6826,6835 ****
/* Create the global variables. */
push_to_top_level ();
/* Enter the global namespace. */
my_friendly_assert (global_namespace == NULL_TREE, 375);
! push_namespace (get_identifier ("::"));
! global_namespace = current_namespace;
current_lang_name = NULL_TREE;
/* Adjust various flags based on command-line settings. */
--- 6848,6862 ----
/* Create the global variables. */
push_to_top_level ();
+ current_function_decl = NULL_TREE;
+ current_binding_level = NULL_BINDING_LEVEL;
+ free_binding_level = NULL_BINDING_LEVEL;
/* Enter the global namespace. */
my_friendly_assert (global_namespace == NULL_TREE, 375);
! global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
! void_type_node);
! cxx_original_namespace_scope_push (global_namespace);
!
current_lang_name = NULL_TREE;
/* Adjust various flags based on command-line settings. */
*************** cxx_init_decl_processing ()
*** 6855,6879 ****
/* Initially, C. */
current_lang_name = lang_name_c;
- current_function_decl = NULL_TREE;
- current_binding_level = NULL_BINDING_LEVEL;
- free_binding_level = NULL_BINDING_LEVEL;
-
build_common_tree_nodes (flag_signed_char);
error_mark_list = build_tree_list (error_mark_node, error_mark_node);
TREE_TYPE (error_mark_list) = error_mark_node;
-
- /* Make the binding_level structure for global names. */
- pushlevel (0);
- current_binding_level->type_decls = binding_table_new (GLOBAL_SCOPE_HT_SIZE);
- /* The global level is the namespace level of ::. */
- NAMESPACE_LEVEL (global_namespace) = current_binding_level;
- declare_namespace_level ();
-
- VARRAY_TREE_INIT (current_binding_level->static_decls,
- 200,
- "Static declarations");
/* Create the `std' namespace. */
push_namespace (std_identifier);
--- 6882,6891 ----