This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[3.3] C++ PATCH: Improving compile-time performance 2/n


Hi,

This patch, against 3.3, continues my work on improving GCC/g++
compile-time performance.  This patch does not incorporate any
algorithmical change.  It does three things (I really did want it to
do _one_ thing):

   1) It reduces GC abuse by allocating some data on stack instead of
      heap.  The data in question are allocated each time we perform a
      name lookup (either unqualified or qualified); see
      cp/parse.y:parse_scoped_id, cp/decl.c:lookup_namespace_name(),
      cp/decl2.c:unqualified_namespace_lookup() and
      cp/decl2.c:do_nonmember_using_decl().

   2) It introduces more typeful programming by replacing the old
      'struct tree_binding' by a new 'cxx_binding' which is not a tree.

      At this time, the new datatype does not do space saving
      (although that was also a motivation). It has the same size as the
      old 'struct tree_binding'.  It does not do any space saving
      because I didn't change the way we're currently implementing
      name lookup (more on that in later patches).  However, I'll like
      to point out upfront that, currently we're not taking advantages
      of the structure of the different C++ notions of scope.
      For example, instead of having a union 

            union tree_binding_u {
              tree GTY ((tag ("0"))) scope;
              struct cp_binding_level * GTY ((tag ("1"))) level;
            } GTY ((desc ("%0.has_level"))) scope;

      along with bitfields "has_level", "is_local" for distinguishing
      a local binding that has a "level" of not, we may just have a
      field "scope" that implements the scope at which the binding was
      made and that knows whether it is "local" or not, i.e.
           - a block is a local scope
           - a for-scope is local
           - a namespace-scoppe is not local
           - a class-scope is not local

      We may then get rid of the gratuitous and confusing notion of
      "level" as well as the unnecessary bitfields "has_level",
      "is_local".  Once we figure out how to better implement the
      caching of INHERITED_VALUE_BINDING_P, we can reduce the size of
      cxx_binding from 20 to 16 (remember that such a datum is
      created for every single declaration).  Such changes in datatype
      and algorithms are being contemplated.
 

   3) It catches a latent bug in the logic of
      cp/decl2.c:qualified_lookup_using_namespace().  This arose as a
      consequence of use of more typeful datastructures.  See below
      for a detailed analysis.

Now, on the intial motives of this patch.  Running the resulting
compiler on Qt-3.1.1 sources exhibits a gain of 7%-10% of the
compile-time in the mean (my box is pentium 4, 2.2 Ghz runninng under
GNU/Linux). 

How non-typeful programming induces a logic error.

  cp/decl2.c:qualified_lookup_using_namespace():

Condiser the loop:

  while (scope && (result != error_mark_node))
    {
      seen = tree_cons (scope, NULL_TREE, seen);
      result = ambiguous_decl (name, result,
                               binding_for_name (name, scope), flags);
      if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
        /* Consider using directives.  */
        for (usings = DECL_NAMESPACE_USING (scope); usings;
             usings = TREE_CHAIN (usings))
          /* If this was a real directive, and we have not seen it.  */
          if (!TREE_INDIRECT_USING (usings)
              && !purpose_member (TREE_PURPOSE (usings), seen))
            todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
      if (todo)
        {
          scope = TREE_PURPOSE (todo);
          todo = TREE_CHAIN (todo);
        }
      else
        scope = NULL_TREE; /* If there never was a todo list.  */
    }

The only way in which the value of "result" gets changed in the above
loop is by storing the result of ambiguous_decl() in it.
However, ambiguous_decl() always returns its second argument and a
quick static type analysis reveals that "result" can never ever be
an error_mark_node.  Therefore the above loop was using an ill-formed
partial condition.  The condition we're looking for actually is

    while (scope && result->value != error_mark_node)

Ugh.

A note on "tree" abuse:  In many routines, a variable (formelly of
type tree) is used to designate a CPLU_BINDING, a _DECL or an
IDENTIFIER_NODE.  All that contributes to make the code in the C++
front-end unreadable at occasions.  This patch catches some of those
abuse in the part where cxx_binding was introduced. 

Bootstrapped and regtested on an i686-pc-linux-gnu.  Applied to 3.3.

A revised form of this patch will be applied to mainline.

-- Gaby

2003-03-10  Gabriel Dos Reis <gdr at integrable-solutions dot net>

	Compile-time improvement: 2/n.
	* cp-tree.h (struct cxx_binding): New datatype;
	(struct lang_identifier): Use it.
	(LOCAL_BINDING_P): Adjust definition.
	(INHERITED_VALUE_BINDING_P): Likewise.
	(BINDING_SCOPE): Likewise.
	(BINDING_HAS_LEVEL_P): Likewise.
	(BINDING_VALUE): Likewise.
	(BINDING_TYPE): Likewise.
	(IDENTIFIER_VALUE): Likewise.
	(struct tree_binding): Remove.
	(TS_CP_BINDING): Likewise.
	((union lang_tree_node): Remove field "binding".
	(cxx_binding_clear): New macro.
	(binding_for_name): Adjust return type.
	(qualified_lookup_using_namespace): Adjust prototype.
	(lookup_using_namespace): Adjust prototype.
	(cxx_scope_find_binding_for_name): Declare.
	* cp-tree.def: Remove CPLUS_BINDING definition.
	* parse.y (parse_scoped_id): Don't type-abuse of 'id'.  Allocate
	temporary cxx_binding on stack.  Simplify.
	* decl.c (push_binding): Adjust local variable type.
	(add_binding): Likewise.
	(push_class_binding): Likewise.
	(pop_binding): Likewise.
	(poplevel): Likewise.
	(poplevel_class): Likewise.
	(free_bindings):  Adjust type.
	(find_binding): Adjust return type, add a third parameter. Remove
	non-useful assertion now that we use static typing.  
	(cxx_scope_find_binding_for_name): New function.
	(binding_for_name): Use it.  Adjust local variable type. Simplify. 
	(namespace_binding):  Simplify.
	(set_namespace_binding): Likewise.
	(set_identifier_type_value_with_scope): Adjust local variable type.
	(lookup_tag): Don't type-abuse of local variable 'old'.
	(lookup_namespace_name): Likewise.  Allocate binding on stack.
	(select_decl): Adjust prototype.
	(unqualified_namespace_lookup):  Allocate binding on stack.
	Don't type-abuse of local variable 'val'.
	(lookup_name_real): Likewise.
	(maybe_inject_for_scope_var): Adjust local variable type.
	(cp_tree_node_structure): Remove CPLUS_BINDING case label.
	(namespace_binding): Adjust logic, simplify.
	(BINDING_LEVEL): Adjust definition.
	(push_class_level_binding): Adjust local variable type.
	(struct cxx_saved_binding): Adjust field 'binding' type.
	* decl2.c (ambiguous_decl): Adjust prototype.
	(lookup_using_namespace): Adjust local variable type.
	(qualified_lookup_using_namespace): Catch type error and correct
	ensueing logic error.
	(do_nonmember_using_decl): Adjust local variable type.  Allocate
	temporary cxx_binding on stack.
	(do_toplevel_using_decl): Adjust local variable type.
	* ptree.c (cxx_print_cxx_binding): New function.
	(cxx_print_identifier): Use it.
	(cxx_print_xnode): Delete CPLUS_BINDING case label.

Index: cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.66.4.1
diff -p -r1.66.4.1 cp-tree.def
*** cp-tree.def	7 Mar 2003 07:35:04 -0000	1.66.4.1
--- cp-tree.def	9 Mar 2003 20:46:39 -0000
*************** DEFTREECODE (DEFAULT_ARG, "default_arg",
*** 218,228 ****
     the template may be a LOOKUP_EXPR.  */
  DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
  
- /* An association between name and entity. Parameters are the scope
-    and the (non-type) value.  TREE_TYPE indicates the type bound to
-    the name. */
- DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
- 
  /* A list-like node for chaining overloading candidates. TREE_TYPE is 
     the original name, and the parameter is the FUNCTION_DECL.  */
  DEFTREECODE (OVERLOAD, "overload", 'x', 1)
--- 218,223 ----
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.776.2.10
diff -p -r1.776.2.10 cp-tree.h
*** cp-tree.h	9 Mar 2003 03:14:24 -0000	1.776.2.10
--- cp-tree.h	9 Mar 2003 20:46:39 -0000
*************** struct diagnostic_context;
*** 43,49 ****
        DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
        LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
        TREE_INDIRECT_USING (in NAMESPACE_DECL).
-       LOCAL_BINDING_P (in CPLUS_BINDING)
        ICS_USER_FLAG (in _CONV)
        CLEANUP_P (in TRY_BLOCK)
        AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
--- 43,48 ----
*************** struct diagnostic_context;
*** 55,68 ****
        DELETE_EXPR_USE_VEC (in DELETE_EXPR).
        (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
        TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
-       INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
        ICS_ELLIPSIS_FLAG (in _CONV)
        BINFO_ACCESS (in BINFO)
        DECL_INITIALIZED_P (in VAR_DECL)
     2: IDENTIFIER_OPNAME_P.
        TYPE_POLYMORPHIC_P (in _TYPE)
        ICS_THIS_FLAG (in _CONV)
-       BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
        BINFO_LOST_PRIMARY_P (in BINFO)
        TREE_PARMLIST (in TREE_LIST)
     3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
--- 54,65 ----
*************** struct diagnostic_context;
*** 224,237 ****
  /* 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;
  
  /* Language-dependent contents of an identifier.  */
  
  struct lang_identifier GTY(())
  {
    struct c_common_identifier c_common;
!   tree namespace_bindings;
!   tree bindings;
    tree class_value;
    tree class_template_info;
    struct lang_id2 *x;
--- 221,262 ----
  /* 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;
+ 
+ /* Datatype that represents binding established by a declaration between
+    a name and a C++ entity.  */
+ typedef struct cxx_binding cxx_binding;
+ 
+ /* (GC-)allocate a cxx_binding object.  */
+ #define cxx_binding_make() (ggc_alloc (sizeof (cxx_binding)))
+ 
+ /* Zero out a cxx_binding pointed to by B.  */
+ #define cxx_binding_clear(B) memset ((B), 0, sizeof (cxx_binding))
+ 
+ struct cxx_binding GTY(())
+ {
+   /* Link to chain together various bindings for this name.  */
+   cxx_binding *previous;
+   /* The non-type entity this name is bound to.  */
+   tree value;
+   /* The type entity this name is bound to.  */
+   tree type;
+   union tree_binding_u {
+     tree GTY ((tag ("0"))) scope;
+     struct cp_binding_level * GTY ((tag ("1"))) level;
+   } GTY ((desc ("%0.has_level"))) scope;
+   unsigned has_level : 1;
+   unsigned value_is_inherited : 1;
+   unsigned is_local : 1;
+ };
+ 
  
  /* Language-dependent contents of an identifier.  */
  
  struct lang_identifier GTY(())
  {
    struct c_common_identifier c_common;
!   cxx_binding *namespace_bindings;
!   cxx_binding *bindings;
    tree class_value;
    tree class_template_info;
    struct lang_id2 *x;
*************** typedef struct ptrmem_cst * ptrmem_cst_t
*** 284,313 ****
  
  /* Nonzero if this binding is for a local scope, as opposed to a class
     or namespace scope.  */
! #define LOCAL_BINDING_P(NODE) TREE_LANG_FLAG_0 (NODE)
  
  /* Nonzero if BINDING_VALUE is from a base class of the class which is
     currently being defined.  */
! #define INHERITED_VALUE_BINDING_P(NODE) TREE_LANG_FLAG_1 (NODE)
  
  /* For a binding between a name and an entity at a non-local scope,
     defines the scope where the binding is declared.  (Either a class
     _TYPE node, or a NAMESPACE_DECL.)  This macro should be used only
     for namespace-level bindings; on the IDENTIFIER_BINDING list
     BINDING_LEVEL is used instead.  */
! #define BINDING_SCOPE(NODE) \
!   (((struct tree_binding*)CPLUS_BINDING_CHECK (NODE))->scope.scope)
  
  /* Nonzero if NODE has BINDING_LEVEL, rather than BINDING_SCOPE.  */
! #define BINDING_HAS_LEVEL_P(NODE) TREE_LANG_FLAG_2 (NODE)
  
  /* This is the declaration bound to the name. Possible values:
     variable, overloaded function, namespace, template, enumerator.  */
! #define BINDING_VALUE(NODE) \
!   (((struct tree_binding*)CPLUS_BINDING_CHECK (NODE))->value)
  
  /* If name is bound to a type, this is the type (struct, union, enum).  */
! #define BINDING_TYPE(NODE)     TREE_TYPE (NODE)
  
  #define IDENTIFIER_GLOBAL_VALUE(NODE) \
    namespace_binding ((NODE), global_namespace)
--- 309,336 ----
  
  /* Nonzero if this binding is for a local scope, as opposed to a class
     or namespace scope.  */
! #define LOCAL_BINDING_P(NODE) ((NODE)->is_local)
  
  /* Nonzero if BINDING_VALUE is from a base class of the class which is
     currently being defined.  */
! #define INHERITED_VALUE_BINDING_P(NODE) ((NODE)->value_is_inherited)
  
  /* For a binding between a name and an entity at a non-local scope,
     defines the scope where the binding is declared.  (Either a class
     _TYPE node, or a NAMESPACE_DECL.)  This macro should be used only
     for namespace-level bindings; on the IDENTIFIER_BINDING list
     BINDING_LEVEL is used instead.  */
! #define BINDING_SCOPE(NODE) ((NODE)->scope.scope)
  
  /* Nonzero if NODE has BINDING_LEVEL, rather than BINDING_SCOPE.  */
! #define BINDING_HAS_LEVEL_P(NODE) ((NODE)->has_level)
  
  /* This is the declaration bound to the name. Possible values:
     variable, overloaded function, namespace, template, enumerator.  */
! #define BINDING_VALUE(NODE) ((NODE)->value)
  
  /* If name is bound to a type, this is the type (struct, union, enum).  */
! #define BINDING_TYPE(NODE)   ((NODE)->type)
  
  #define IDENTIFIER_GLOBAL_VALUE(NODE) \
    namespace_binding ((NODE), global_namespace)
*************** typedef struct ptrmem_cst * ptrmem_cst_t
*** 341,357 ****
      && DECL_NAME (NODE) != NULL_TREE			\
      && MAIN_NAME_P (DECL_NAME (NODE)))
  
- 
- struct tree_binding GTY(())
- {
-   struct tree_common common;
-   union tree_binding_u {
-     tree GTY ((tag ("0"))) scope;
-     struct cp_binding_level * GTY ((tag ("1"))) level;
-   } GTY ((desc ("BINDING_HAS_LEVEL_P ((tree)&%0)"))) scope;
-   tree value;
- };
- 
  /* The overloaded FUNCTION_DECL.  */
  #define OVL_FUNCTION(NODE) \
    (((struct tree_overload*)OVERLOAD_CHECK (NODE))->function)
--- 364,369 ----
*************** struct tree_srcloc GTY(())
*** 419,426 ****
  #define IDENTIFIER_TEMPLATE(NODE)	\
    (LANG_IDENTIFIER_CAST (NODE)->class_template_info)
  
! /* The IDENTIFIER_BINDING is the innermost CPLUS_BINDING for the
!     identifier.  It's TREE_CHAIN is the next outermost binding.  Each
      BINDING_VALUE is a DECL for the associated declaration.  Thus,
      name lookup consists simply of pulling off the node at the front
      of the list (modulo oddities for looking up the names of types,
--- 431,438 ----
  #define IDENTIFIER_TEMPLATE(NODE)	\
    (LANG_IDENTIFIER_CAST (NODE)->class_template_info)
  
! /* The IDENTIFIER_BINDING is the innermost cxx_binding for the
!     identifier.  It's PREVIOUS is the next outermost binding.  Each
      BINDING_VALUE is a DECL for the associated declaration.  Thus,
      name lookup consists simply of pulling off the node at the front
      of the list (modulo oddities for looking up the names of types,
*************** struct tree_srcloc GTY(())
*** 432,440 ****
  /* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or
     NULL_TREE if there is no binding.  */
  #define IDENTIFIER_VALUE(NODE)			\
!   (IDENTIFIER_BINDING (NODE)			\
!    ? BINDING_VALUE (IDENTIFIER_BINDING (NODE))	\
!    : NULL_TREE)
  
  /* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current
     class, and IDENTIFIER_CLASS_VALUE is the value binding.  This is
--- 444,450 ----
  /* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or
     NULL_TREE if there is no binding.  */
  #define IDENTIFIER_VALUE(NODE)			\
!   (IDENTIFIER_BINDING (NODE) ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) : 0)
  
  /* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current
     class, and IDENTIFIER_CLASS_VALUE is the value binding.  This is
*************** enum cp_tree_node_structure_enum {
*** 509,515 ****
    TS_CP_IDENTIFIER,
    TS_CP_TPI,
    TS_CP_PTRMEM,
-   TS_CP_BINDING,
    TS_CP_OVERLOAD,
    TS_CP_WRAPPER,
    TS_CP_SRCLOC,
--- 519,524 ----
*************** union lang_tree_node GTY((desc ("cp_tree
*** 525,531 ****
  			desc ("tree_node_structure (&%h)"))) generic;
    struct template_parm_index_s GTY ((tag ("TS_CP_TPI"))) tpi;
    struct ptrmem_cst GTY ((tag ("TS_CP_PTRMEM"))) ptrmem;
-   struct tree_binding GTY ((tag ("TS_CP_BINDING"))) binding;
    struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload;
    struct tree_wrapper GTY ((tag ("TS_CP_WRAPPER"))) wrapper;
    struct tree_srcloc GTY ((tag ("TS_CP_SRCLOC"))) srcloc;
--- 534,539 ----
*************** extern tree declare_local_label         
*** 3693,3699 ****
  extern tree define_label			PARAMS ((const char *, int, tree));
  extern void check_goto				PARAMS ((tree));
  extern void define_case_label			PARAMS ((void));
! extern tree binding_for_name                    PARAMS ((tree, tree));
  extern tree namespace_binding                   PARAMS ((tree, tree));
  extern void set_namespace_binding               PARAMS ((tree, tree, tree));
  extern tree lookup_namespace_name		PARAMS ((tree, tree));
--- 3701,3707 ----
  extern tree define_label			PARAMS ((const char *, int, tree));
  extern void check_goto				PARAMS ((tree));
  extern void define_case_label			PARAMS ((void));
! extern cxx_binding *binding_for_name (tree, tree);
  extern tree namespace_binding                   PARAMS ((tree, tree));
  extern void set_namespace_binding               PARAMS ((tree, tree, tree));
  extern tree lookup_namespace_name		PARAMS ((tree, tree));
*************** extern void end_only_namespace_names    
*** 3711,3718 ****
  extern tree namespace_ancestor			PARAMS ((tree, tree));
  extern tree unqualified_namespace_lookup	PARAMS ((tree, int, tree *));
  extern tree check_for_out_of_scope_variable     (tree);
! extern int  lookup_using_namespace              PARAMS ((tree, tree, tree, tree, int, tree *));
! extern int  qualified_lookup_using_namespace    PARAMS ((tree, tree, tree, int));
  extern tree build_library_fn			PARAMS ((tree, tree));
  extern tree build_library_fn_ptr		PARAMS ((const char *, tree));
  extern tree build_cp_library_fn_ptr		PARAMS ((const char *, tree));
--- 3719,3726 ----
  extern tree namespace_ancestor			PARAMS ((tree, tree));
  extern tree unqualified_namespace_lookup	PARAMS ((tree, int, tree *));
  extern tree check_for_out_of_scope_variable     (tree);
! extern bool lookup_using_namespace (tree, cxx_binding *, tree, tree, int, tree *);
! extern bool qualified_lookup_using_namespace (tree, tree, cxx_binding *, int);
  extern tree build_library_fn			PARAMS ((tree, tree));
  extern tree build_library_fn_ptr		PARAMS ((const char *, tree));
  extern tree build_cp_library_fn_ptr		PARAMS ((const char *, tree));
*************** extern int nonstatic_local_decl_p       
*** 3788,3793 ****
--- 3796,3802 ----
  extern tree declare_global_var                  PARAMS ((tree, tree));
  extern void register_dtor_fn                    PARAMS ((tree));
  extern tmpl_spec_kind current_tmpl_spec_kind    PARAMS ((int));
+ extern cxx_binding *cxx_scope_find_binding_for_name (tree, tree);
  extern tree cp_fname_init			PARAMS ((const char *));
  extern bool have_extern_spec;
  
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.965.2.28
diff -p -r1.965.2.28 decl.c
*** decl.c	9 Mar 2003 14:13:40 -0000	1.965.2.28
--- decl.c	9 Mar 2003 20:46:40 -0000
*************** static void push_binding PARAMS ((tree, 
*** 97,104 ****
  static int add_binding PARAMS ((tree, tree));
  static void pop_binding PARAMS ((tree, tree));
  static tree local_variable_p_walkfn PARAMS ((tree *, int *, void *));
! static tree find_binding PARAMS ((tree, tree));
! static tree select_decl PARAMS ((tree, int));
  static int lookup_flags PARAMS ((int, int));
  static tree qualify_lookup PARAMS ((tree, int));
  static tree record_builtin_java_type PARAMS ((const char *, int));
--- 97,104 ----
  static int add_binding PARAMS ((tree, tree));
  static void pop_binding PARAMS ((tree, tree));
  static tree local_variable_p_walkfn PARAMS ((tree *, int *, void *));
! static cxx_binding *find_binding (tree, tree, cxx_binding *);
! static tree select_decl (cxx_binding *, int);
  static int lookup_flags PARAMS ((int, int));
  static tree qualify_lookup PARAMS ((tree, int));
  static tree record_builtin_java_type PARAMS ((const char *, int));
*************** note_level_for_catch ()
*** 903,915 ****
  
  /* For a binding between a name and an entity at a block scope,
     this is the `struct cp_binding_level' for the block.  */
! #define BINDING_LEVEL(NODE) \
!   (((struct tree_binding*)(NODE))->scope.level)
  
! /* A free list of CPLUS_BINDING nodes, connected by their
!    TREE_CHAINs.  */
  
! static GTY((deletable (""))) tree free_bindings;
  
  /* Make DECL the innermost binding for ID.  The LEVEL is the binding
     level at which this declaration is being bound.  */
--- 903,913 ----
  
  /* For a binding between a name and an entity at a block scope,
     this is the `struct cp_binding_level' for the block.  */
! #define BINDING_LEVEL(NODE) ((NODE)->scope.level)
  
! /* A free list of "cxx_binding"s, connected by their PREVIOUS.  */
  
! static GTY((deletable (""))) cxx_binding *free_bindings;
  
  /* Make DECL the innermost binding for ID.  The LEVEL is the binding
     level at which this declaration is being bound.  */
*************** push_binding (id, decl, level)
*** 920,934 ****
       tree decl;
       struct cp_binding_level* level;
  {
!   tree binding;
  
    if (free_bindings)
      {
        binding = free_bindings;
!       free_bindings = TREE_CHAIN (binding);
      }
    else
!     binding = make_node (CPLUS_BINDING);
  
    /* Now, fill in the binding information.  */
    BINDING_VALUE (binding) = decl;
--- 918,932 ----
       tree decl;
       struct cp_binding_level* level;
  {
!   cxx_binding *binding;
  
    if (free_bindings)
      {
        binding = free_bindings;
!       free_bindings = binding->previous;
      }
    else
!     binding = cxx_binding_make ();
  
    /* Now, fill in the binding information.  */
    BINDING_VALUE (binding) = decl;
*************** push_binding (id, decl, level)
*** 939,945 ****
    BINDING_HAS_LEVEL_P (binding) = 1;
  
    /* And put it on the front of the list of bindings for ID.  */
!   TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
    IDENTIFIER_BINDING (id) = binding;
  }
  
--- 937,943 ----
    BINDING_HAS_LEVEL_P (binding) = 1;
  
    /* And put it on the front of the list of bindings for ID.  */
!   binding->previous = IDENTIFIER_BINDING (id);
    IDENTIFIER_BINDING (id) = binding;
  }
  
*************** add_binding (id, decl)
*** 954,960 ****
       tree id;
       tree decl;
  {
!   tree binding = IDENTIFIER_BINDING (id);
    int ok = 1;
  
    timevar_push (TV_NAME_LOOKUP);
--- 952,958 ----
       tree id;
       tree decl;
  {
!   cxx_binding *binding = IDENTIFIER_BINDING (id);
    int ok = 1;
  
    timevar_push (TV_NAME_LOOKUP);
*************** push_class_binding (id, decl)
*** 1104,1110 ****
       tree decl;
  {
    int result = 1;
!   tree binding = IDENTIFIER_BINDING (id);
    tree context;
  
    timevar_push (TV_NAME_LOOKUP);
--- 1102,1108 ----
       tree decl;
  {
    int result = 1;
!   cxx_binding *binding = IDENTIFIER_BINDING (id);
    tree context;
  
    timevar_push (TV_NAME_LOOKUP);
*************** pop_binding (id, decl)
*** 1170,1176 ****
       tree id;
       tree decl;
  {
!   tree binding;
  
    if (id == NULL_TREE)
      /* It's easiest to write the loops that call this function without
--- 1168,1174 ----
       tree id;
       tree decl;
  {
!   cxx_binding *binding;
  
    if (id == NULL_TREE)
      /* It's easiest to write the loops that call this function without
*************** pop_binding (id, decl)
*** 1182,1188 ****
    binding = IDENTIFIER_BINDING (id);
  
    /* The name should be bound.  */
!   my_friendly_assert (binding != NULL_TREE, 0);
  
    /* The DECL will be either the ordinary binding or the type
       binding for this identifier.  Remove that binding.  */
--- 1180,1186 ----
    binding = IDENTIFIER_BINDING (id);
  
    /* The name should be bound.  */
!   my_friendly_assert (binding != NULL, 0);
  
    /* The DECL will be either the ordinary binding or the type
       binding for this identifier.  Remove that binding.  */
*************** pop_binding (id, decl)
*** 1197,1206 ****
      {
        /* We're completely done with the innermost binding for this
  	 identifier.  Unhook it from the list of bindings.  */
!       IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
  
        /* Add it to the free list.  */
!       TREE_CHAIN (binding) = free_bindings;
        free_bindings = binding;
  
        /* Clear the BINDING_LEVEL so the garbage collector doesn't walk
--- 1195,1204 ----
      {
        /* We're completely done with the innermost binding for this
  	 identifier.  Unhook it from the list of bindings.  */
!       IDENTIFIER_BINDING (id) = binding->previous;
  
        /* Add it to the free list.  */
!       binding->previous = free_bindings;
        free_bindings = binding;
  
        /* Clear the BINDING_LEVEL so the garbage collector doesn't walk
*************** poplevel (keep, reverse, functionbody)
*** 1419,1426 ****
        if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
            && DECL_NAME (link))
  	{
! 	  tree outer_binding
! 	    = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
  	  tree ns_binding;
  
  	  if (!outer_binding)
--- 1417,1424 ----
        if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
            && DECL_NAME (link))
  	{
! 	  cxx_binding *outer_binding
! 	    = IDENTIFIER_BINDING (DECL_NAME (link))->previous;
  	  tree ns_binding;
  
  	  if (!outer_binding)
*************** poplevel (keep, reverse, functionbody)
*** 1475,1481 ****
  			     current_binding_level->level_chain->
  			     dead_vars_from_for);
  
! 	      /* Although we don't pop the CPLUS_BINDING, we do clear
  		 its BINDING_LEVEL since the level is going away now.  */
  	      BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
  		= 0;
--- 1473,1479 ----
  			     current_binding_level->level_chain->
  			     dead_vars_from_for);
  
! 	      /* Although we don't pop the cxx_binding, we do clear
  		 its BINDING_LEVEL since the level is going away now.  */
  	      BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
  		= 0;
*************** poplevel_class ()
*** 1704,1718 ****
  	     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
--- 1702,1716 ----
  	     shadowed;
  	     shadowed = TREE_CHAIN (shadowed))
  	  {
! 	    cxx_binding *binding;
  
! 	    binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
! 	    while (binding && BINDING_LEVEL (binding) != b)
! 	      binding = binding->previous;
  
! 	    if (binding)
  	      IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
! 		= BINDING_VALUE (binding);
  	  }
      }
    else
*************** print_binding_stack ()
*** 2093,2195 ****
    print_binding_level (global_binding_level);
  }
  
! /* Namespace binding access routines: The namespace_bindings field of
!    the identifier is polymorphic, with three possible values:
!    NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node
!    indicating the BINDING_VALUE of global_namespace.  */
  
  /* Check whether the a binding for the name to scope is known.
!    Assumes that the bindings of the name are already a list
!    of bindings. Returns the binding found, or NULL_TREE.  */
  
! static tree
! find_binding (name, scope)
!      tree name;
!      tree scope;
  {
!   tree iter, prev = NULL_TREE;
  
    timevar_push (TV_NAME_LOOKUP);
  
!   scope = ORIGINAL_NAMESPACE (scope);
! 
!   for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
!        iter = TREE_CHAIN (iter))
      {
-       my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
        if (BINDING_SCOPE (iter) == scope)
  	{
  	  /* Move binding found to the front of the list, so
               subsequent lookups will find it faster.  */
  	  if (prev)
  	    {
! 	      TREE_CHAIN (prev) = TREE_CHAIN (iter);
! 	      TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
  	      IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
  	    }
  	  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, iter);
  	}
        prev = iter;
      }
!   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
  }
  
! /* Always returns a binding for name in scope. If the
!    namespace_bindings is not a list, convert it to one first.
     If no binding is found, make a new one.  */
  
! tree
! binding_for_name (name, scope)
!      tree name;
!      tree scope;
  {
!   tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
!   tree result;
  
    scope = ORIGINAL_NAMESPACE (scope);
! 
!   if (b && TREE_CODE (b) != CPLUS_BINDING)
!     {
!       /* Get rid of optimization for global scope.  */
!       IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE;
!       BINDING_VALUE (binding_for_name (name, global_namespace)) = b;
!       b = IDENTIFIER_NAMESPACE_BINDINGS (name);
!     }
!   if (b && (result = find_binding (name, scope)))
      return result;
    /* Not found, make a new one.  */
!   result = make_node (CPLUS_BINDING);
!   TREE_CHAIN (result) = b;
!   IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
!   BINDING_SCOPE (result) = scope;
    BINDING_TYPE (result) = NULL_TREE;
    BINDING_VALUE (result) = NULL_TREE;
    return result;
  }
  
! /* Return the binding value for name in scope, considering that
!    namespace_binding may or may not be a list of CPLUS_BINDINGS.  */
  
  tree
! namespace_binding (name, scope)
!      tree name;
!      tree scope;
  {
!   tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
!   if (b == NULL_TREE)
!     return NULL_TREE;
!   if (scope == NULL_TREE)
!     scope = global_namespace;
!   if (TREE_CODE (b) != CPLUS_BINDING)
!     return (scope == global_namespace) ? b : NULL_TREE;
!   name = find_binding (name,scope);
!   if (name == NULL_TREE)
!     return name;
!   return BINDING_VALUE (name);
  }
  
! /* Set the binding value for name in scope. If modifying the binding
!    of global_namespace is attempted, try to optimize it.  */
  
  void
  set_namespace_binding (name, scope, val)
--- 2091,2182 ----
    print_binding_level (global_binding_level);
  }
  
! /* Namespace binding access routines.   */
  
  /* Check whether the a binding for the name to scope is known.
!    Returns the binding found, or NULL.  */
  
! static inline cxx_binding *
! find_binding (tree name, tree scope, cxx_binding *front)
  {
!   cxx_binding *iter;
!   cxx_binding *prev = NULL;
  
    timevar_push (TV_NAME_LOOKUP);
  
!   for (iter = front; iter; iter = iter->previous)
      {
        if (BINDING_SCOPE (iter) == scope)
  	{
  	  /* Move binding found to the front of the list, so
               subsequent lookups will find it faster.  */
  	  if (prev)
  	    {
! 	      prev->previous = iter->previous;
! 	      iter->previous = front;
  	      IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
  	    }
  	  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, iter);
  	}
        prev = iter;
      }
!   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL);
  }
  
! /* Return the binding for NAME in SCOPE, if any.  Otherwise, return NULL.  */
! cxx_binding *
! cxx_scope_find_binding_for_name (tree scope, tree name)
! {
!   cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name);
!   if (b)
!     {
!       scope = ORIGINAL_NAMESPACE (scope);
!       /* Fold-in case where NAME is used only once.  */
!       if (scope == BINDING_SCOPE (b) && b->previous == NULL)
!         return b;
!       return find_binding (name, scope, b);
!     }
!   return b;
! }
! 
! 
! /* Always returns a binding for name in scope.
     If no binding is found, make a new one.  */
  
! cxx_binding *
! binding_for_name (tree name, tree scope)
  {
!   cxx_binding *result;
  
    scope = ORIGINAL_NAMESPACE (scope);
!   result = cxx_scope_find_binding_for_name (scope, name);
!   if (result)
      return result;
    /* Not found, make a new one.  */
!   result = cxx_binding_make ();
!   result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
    BINDING_TYPE (result) = NULL_TREE;
    BINDING_VALUE (result) = NULL_TREE;
+   BINDING_SCOPE (result) = scope;
+   result->is_local = false;
+   result->value_is_inherited = false;
+   result->has_level = false;
+   IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
    return result;
  }
  
! /* Return the binding value for name in scope.  */
  
  tree
! namespace_binding (tree name, tree scope)
  {
!   cxx_binding *b =
!     cxx_scope_find_binding_for_name (scope ? scope : global_namespace, name);
! 
!   return b ? b->value : NULL_TREE;
  }
  
! /* Set the binding value for name in scope.  */
  
  void
  set_namespace_binding (name, scope, val)
*************** set_namespace_binding (name, scope, val)
*** 2197,2217 ****
       tree scope;
       tree val;
  {
!   tree b;
  
    timevar_push (TV_NAME_LOOKUP);
    if (scope == NULL_TREE)
      scope = global_namespace;
  
-   if (scope == global_namespace)
-     {
-       b = IDENTIFIER_NAMESPACE_BINDINGS (name);
-       if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
- 	{
- 	  IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
- 	}
-     }
    b = binding_for_name (name, scope);
    BINDING_VALUE (b) = val;
    timevar_pop (TV_NAME_LOOKUP);
--- 2184,2195 ----
       tree scope;
       tree val;
  {
!   cxx_binding *b;
  
    timevar_push (TV_NAME_LOOKUP);
    if (scope == NULL_TREE)
      scope = global_namespace;
  
    b = binding_for_name (name, scope);
    BINDING_VALUE (b) = val;
    timevar_pop (TV_NAME_LOOKUP);
*************** struct cxx_saved_binding GTY(())
*** 2352,2358 ****
    /* The name of the current binding.  */
    tree identifier;
    /* The binding we're saving.  */
!   tree binding;
    tree class_value;
    tree real_type_value;
  };
--- 2330,2336 ----
    /* The name of the current binding.  */
    tree identifier;
    /* The binding we're saving.  */
!   cxx_binding *binding;
    tree class_value;
    tree real_type_value;
  };
*************** store_bindings (tree names, cxx_saved_bi
*** 2400,2406 ****
        saved->binding = IDENTIFIER_BINDING (id);
        saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
        saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
!       IDENTIFIER_BINDING (id) = NULL_TREE;
        IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
        old_bindings = saved;
      skip_it:
--- 2378,2384 ----
        saved->binding = IDENTIFIER_BINDING (id);
        saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
        saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
!       IDENTIFIER_BINDING (id) = NULL;
        IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
        old_bindings = saved;
      skip_it:
*************** set_identifier_type_value_with_scope (id
*** 2544,2550 ****
      }
    else
      {
!       tree binding = binding_for_name (id, current_namespace);
        BINDING_TYPE (binding) = type;
        /* Store marker instead of real type.  */
        type = global_type_node;
--- 2522,2528 ----
      }
    else
      {
!       cxx_binding *binding = binding_for_name (id, current_namespace);
        BINDING_TYPE (binding) = type;
        /* Store marker instead of real type.  */
        type = global_type_node;
*************** push_class_level_binding (name, x)
*** 4439,4445 ****
       tree name;
       tree x;
  {
!   tree binding;
    
    timevar_push (TV_NAME_LOOKUP);
    /* The class_binding_level will be NULL if x is a template
--- 4417,4423 ----
       tree name;
       tree x;
  {
!   cxx_binding *binding;
    
    timevar_push (TV_NAME_LOOKUP);
    /* The class_binding_level will be NULL if x is a template
*************** push_overloaded_decl (decl, flags)
*** 4689,4695 ****
  		  *d = tree_cons (NULL_TREE, new_binding,
  				  TREE_CHAIN (*d));
  
! 		/* And update the CPLUS_BINDING node.  */
  		BINDING_VALUE (IDENTIFIER_BINDING (name))
  		  = new_binding;
  		POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
--- 4667,4673 ----
  		  *d = tree_cons (NULL_TREE, new_binding,
  				  TREE_CHAIN (*d));
  
! 		/* And update the cxx_binding node.  */
  		BINDING_VALUE (IDENTIFIER_BINDING (name))
  		  = new_binding;
  		POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
*************** lookup_tag (form, name, binding_level, t
*** 5409,5426 ****
  	/* Do namespace lookup.  */
  	for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
  	  {
! 	    tree old = binding_for_name (name, tail);
  
  	    /* If we just skipped past a template parameter level,
  	       even though THISLEVEL_ONLY, and we find a template
  	       class declaration, then we use the _TYPE node for the
  	       template.  See the example below.  */
  	    if (thislevel_only && !allow_template_parms_p
! 		&& old && BINDING_VALUE (old)
! 		&& DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
! 	      old = TREE_TYPE (BINDING_VALUE (old));
! 	    else
! 	      old = BINDING_TYPE (old);
  
  	    if (old)
  	      {
--- 5387,5408 ----
  	/* Do namespace lookup.  */
  	for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
  	  {
! 	    cxx_binding *binding =
!               cxx_scope_find_binding_for_name (tail, name);
!             tree old;
  
  	    /* If we just skipped past a template parameter level,
  	       even though THISLEVEL_ONLY, and we find a template
  	       class declaration, then we use the _TYPE node for the
  	       template.  See the example below.  */
  	    if (thislevel_only && !allow_template_parms_p
! 		&& binding && BINDING_VALUE (binding)
! 		&& DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
! 	      old = TREE_TYPE (BINDING_VALUE (binding));
! 	    else if (binding)
! 	      old = BINDING_TYPE (binding);
!             else
!               old = NULL;
  
  	    if (old)
  	      {
*************** lookup_namespace_name (namespace, name)
*** 5533,5538 ****
--- 5515,5521 ----
  {
    tree val;
    tree template_id = NULL_TREE;
+   cxx_binding binding;
  
    timevar_push (TV_NAME_LOOKUP);
  
*************** lookup_namespace_name (namespace, name)
*** 5563,5575 ****
  
    my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
  
!   val = make_node (CPLUS_BINDING);
!   if (!qualified_lookup_using_namespace (name, namespace, val, 0))
      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
  
!   if (BINDING_VALUE (val))
      {
!       val = BINDING_VALUE (val);
  
        if (template_id)
  	{
--- 5546,5558 ----
  
    my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
  
!   cxx_binding_clear (&binding);
!   if (!qualified_lookup_using_namespace (name, namespace, &binding, 0))
      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
  
!   if (binding.value)
      {
!       val = binding.value;
  
        if (template_id)
  	{
*************** make_unbound_class_template (context, na
*** 5906,5914 ****
  /* Select the right _DECL from multiple choices.  */
  
  static tree
! select_decl (binding, flags)
!      tree binding;
!      int flags;
  {
    tree val;
    
--- 5889,5895 ----
  /* Select the right _DECL from multiple choices.  */
  
  static tree
! select_decl (cxx_binding *binding, int flags)
  {
    tree val;
    
*************** unqualified_namespace_lookup (name, flag
*** 5949,5992 ****
       int flags;
       tree *spacesp;
  {
-   tree b = make_node (CPLUS_BINDING);
    tree initial = current_decl_namespace ();
    tree scope = initial;
    tree siter;
    struct cp_binding_level *level;
    tree val = NULL_TREE;
  
    timevar_push (TV_NAME_LOOKUP);
    if (spacesp)
      *spacesp = NULL_TREE;
  
    for (; !val; scope = CP_DECL_CONTEXT (scope))
      {
        if (spacesp)
  	*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
!       val = binding_for_name (name, scope);
  
        /* Ignore anticipated built-in functions.  */
!       if (val && BINDING_VALUE (val)
!           && DECL_P (BINDING_VALUE (val))
!           && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
!           && DECL_ANTICIPATED (BINDING_VALUE (val)))
!         {
!           BINDING_VALUE (b) = NULL_TREE;
!           BINDING_TYPE (b) = NULL_TREE;
!         }
!       else
          {
            /* Initialize binding for this context.  */
!           BINDING_VALUE (b) = BINDING_VALUE (val);
!           BINDING_TYPE (b) = BINDING_TYPE (val);
          }
  
        /* Add all _DECLs seen through local using-directives.  */
        for (level = current_binding_level;
  	   !level->namespace_p;
  	   level = level->level_chain)
! 	if (!lookup_using_namespace (name, b, level->using_directives,
                                       scope, flags, spacesp))
  	  /* Give up because of error.  */
  	  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
--- 5930,5971 ----
       int flags;
       tree *spacesp;
  {
    tree initial = current_decl_namespace ();
    tree scope = initial;
    tree siter;
    struct cp_binding_level *level;
    tree val = NULL_TREE;
+   cxx_binding binding;
  
    timevar_push (TV_NAME_LOOKUP);
+   cxx_binding_clear (&binding);
    if (spacesp)
      *spacesp = NULL_TREE;
  
    for (; !val; scope = CP_DECL_CONTEXT (scope))
      {
+       cxx_binding *b;
        if (spacesp)
  	*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
!       b = cxx_scope_find_binding_for_name (scope, name);
  
        /* Ignore anticipated built-in functions.  */
!       if (b && BINDING_VALUE (b) && DECL_P (BINDING_VALUE (b))
!           && DECL_LANG_SPECIFIC (BINDING_VALUE (b))
!           && DECL_ANTICIPATED (BINDING_VALUE (b)))
!         /* Keep binding cleared.  */;
!       else if (b)
          {
            /* Initialize binding for this context.  */
!           binding.value = BINDING_VALUE (b);
!           binding.type = BINDING_TYPE (b);
          }
  
        /* Add all _DECLs seen through local using-directives.  */
        for (level = current_binding_level;
  	   !level->namespace_p;
  	   level = level->level_chain)
! 	if (!lookup_using_namespace (name, &binding, level->using_directives,
                                       scope, flags, spacesp))
  	  /* Give up because of error.  */
  	  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
*************** unqualified_namespace_lookup (name, flag
*** 5996,6002 ****
        siter = initial;
        while (1)
  	{
! 	  if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
  				       scope, flags, spacesp))
  	    /* Give up because of error.  */
  	    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
--- 5975,5982 ----
        siter = initial;
        while (1)
  	{
! 	  if (!lookup_using_namespace (name, &binding,
!                                        DECL_NAMESPACE_USING (siter),
  				       scope, flags, spacesp))
  	    /* Give up because of error.  */
  	    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
*************** unqualified_namespace_lookup (name, flag
*** 6004,6010 ****
  	  siter = CP_DECL_CONTEXT (siter);
  	}
  
!       val = select_decl (b, flags);
        if (scope == global_namespace)
  	break;
      }
--- 5984,5990 ----
  	  siter = CP_DECL_CONTEXT (siter);
  	}
  
!       val = select_decl (&binding, flags);
        if (scope == global_namespace)
  	break;
      }
*************** lookup_name_real (name, prefer_type, non
*** 6159,6164 ****
--- 6139,6145 ----
    tree from_obj = NULL_TREE;
    int flags;
    int val_is_implicit_typename = 0;
+   cxx_binding *iter;
  
    timevar_push (TV_NAME_LOOKUP);
  
*************** lookup_name_real (name, prefer_type, non
*** 6198,6208 ****
  	    type = global_namespace;
  	  if (TREE_CODE (type) == NAMESPACE_DECL)
  	    {
! 	      val = make_node (CPLUS_BINDING);
  	      flags |= LOOKUP_COMPLAIN;
! 	      if (!qualified_lookup_using_namespace (name, type, val, flags))
  		POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
! 	      val = select_decl (val, flags);
  	    }
  	  else if (! IS_AGGR_TYPE (type)
  		   || TREE_CODE (type) == TEMPLATE_TYPE_PARM
--- 6179,6190 ----
  	    type = global_namespace;
  	  if (TREE_CODE (type) == NAMESPACE_DECL)
  	    {
!               cxx_binding b;
!               cxx_binding_clear (&b);
  	      flags |= LOOKUP_COMPLAIN;
! 	      if (!qualified_lookup_using_namespace (name, type, &b, flags))
  		POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
! 	      val = select_decl (&b, flags);
  	    }
  	  else if (! IS_AGGR_TYPE (type)
  		   || TREE_CODE (type) == TEMPLATE_TYPE_PARM
*************** lookup_name_real (name, prefer_type, non
*** 6255,6281 ****
    if (current_class_type == NULL_TREE)
      nonclass = 1;
  
!   for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
      {
        tree binding;
  
!       if (!LOCAL_BINDING_P (t) && nonclass)
  	/* We're not looking for class-scoped bindings, so keep going.  */
  	continue;
  
        /* If this is the kind of thing we're looking for, we're done.  */
!       if (qualify_lookup (BINDING_VALUE (t), flags))
! 	binding = BINDING_VALUE (t);
        else if ((flags & LOOKUP_PREFER_TYPES)
! 	       && qualify_lookup (BINDING_TYPE (t), flags))
! 	binding = BINDING_TYPE (t);
        else
  	binding = NULL_TREE;
  
        /* Handle access control on types from enclosing or base classes.  */
        if (binding && ! yylex
! 	  && BINDING_LEVEL (t) && BINDING_LEVEL (t)->parm_flag == 2)
! 	type_access_control (BINDING_LEVEL (t)->this_class, binding);
  
        if (binding
  	  && (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
--- 6237,6263 ----
    if (current_class_type == NULL_TREE)
      nonclass = 1;
  
!   for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous)
      {
        tree binding;
  
!       if (!LOCAL_BINDING_P (iter) && nonclass)
  	/* We're not looking for class-scoped bindings, so keep going.  */
  	continue;
  
        /* If this is the kind of thing we're looking for, we're done.  */
!       if (qualify_lookup (BINDING_VALUE (iter), flags))
! 	binding = BINDING_VALUE (iter);
        else if ((flags & LOOKUP_PREFER_TYPES)
! 	       && qualify_lookup (BINDING_TYPE (iter), flags))
! 	binding = BINDING_TYPE (iter);
        else
  	binding = NULL_TREE;
  
        /* 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)))
*************** maybe_inject_for_scope_var (decl)
*** 8347,8354 ****
  	 Otherwise, we need to preserve the temp slot for decl to last
  	 into the outer binding level.  */
  
!       tree outer_binding
! 	= TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
  
        if (outer_binding && BINDING_LEVEL (outer_binding) == outer
  	  && (TREE_CODE (BINDING_VALUE (outer_binding))
--- 8329,8336 ----
  	 Otherwise, we need to preserve the temp slot for decl to last
  	 into the outer binding level.  */
  
!       cxx_binding *outer_binding
! 	= IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
  
        if (outer_binding && BINDING_LEVEL (outer_binding) == outer
  	  && (TREE_CODE (BINDING_VALUE (outer_binding))
*************** cp_tree_node_structure (t)
*** 15031,15037 ****
      {
      case DEFAULT_ARG:		return TS_CP_IDENTIFIER;
      case IDENTIFIER_NODE:	return TS_CP_IDENTIFIER;
-     case CPLUS_BINDING:		return TS_CP_BINDING;
      case OVERLOAD:		return TS_CP_OVERLOAD;
      case TEMPLATE_PARM_INDEX:	return TS_CP_TPI;
      case PTRMEM_CST:		return TS_CP_PTRMEM;
--- 15013,15018 ----
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.575.2.11
diff -p -r1.575.2.11 decl2.c
*** decl2.c	9 Mar 2003 03:14:24 -0000	1.575.2.11
--- decl2.c	9 Mar 2003 20:46:40 -0000
*************** static void grok_function_init PARAMS ((
*** 64,70 ****
  static int maybe_emit_vtables (tree);
  static int is_namespace_ancestor PARAMS ((tree, tree));
  static void add_using_namespace PARAMS ((tree, tree, int));
! static tree ambiguous_decl PARAMS ((tree, tree, tree,int));
  static tree build_anon_union_vars PARAMS ((tree, tree*, int, int));
  static int acceptable_java_type PARAMS ((tree));
  static void output_vtable_inherit PARAMS ((tree));
--- 64,70 ----
  static int maybe_emit_vtables (tree);
  static int is_namespace_ancestor PARAMS ((tree, tree));
  static void add_using_namespace PARAMS ((tree, tree, int));
! static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *,int);
  static tree build_anon_union_vars PARAMS ((tree, tree*, int, int));
  static int acceptable_java_type PARAMS ((tree));
  static void output_vtable_inherit PARAMS ((tree));
*************** merge_functions (s1, s2)
*** 3759,3773 ****
     XXX In what way should I treat extern declarations?
     XXX I don't want to repeat the entire duplicate_decls here */
  
! static tree
! ambiguous_decl (name, old, new, flags)
!      tree name;
!      tree old;
!      tree new;
!      int flags;
  {
    tree val, type;
!   my_friendly_assert (old != NULL_TREE, 393);
    /* Copy the value.  */
    val = BINDING_VALUE (new);
    if (val)
--- 3759,3769 ----
     XXX In what way should I treat extern declarations?
     XXX I don't want to repeat the entire duplicate_decls here */
  
! static cxx_binding *
! ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)
  {
    tree val, type;
!   my_friendly_assert (old != NULL, 393);
    /* Copy the value.  */
    val = BINDING_VALUE (new);
    if (val)
*************** ambiguous_decl (name, old, new, flags)
*** 3852,3865 ****
     which have SCOPE as a common ancestor with the current scope.
     Returns zero on errors.  */
  
! int
! lookup_using_namespace (name, val, usings, scope, flags, spacesp)
!      tree name, val, usings, scope;
!      int flags;
!      tree *spacesp;
  {
    tree iter;
!   tree val1;
    timevar_push (TV_NAME_LOOKUP);
    /* Iterate over all used namespaces in current, searching for using
       directives of scope.  */
--- 3848,3859 ----
     which have SCOPE as a common ancestor with the current scope.
     Returns zero on errors.  */
  
! bool
! lookup_using_namespace (tree name, cxx_binding *val, tree usings,
!                         tree scope, int flags, tree *spacesp)
  {
    tree iter;
!   cxx_binding *val1;
    timevar_push (TV_NAME_LOOKUP);
    /* Iterate over all used namespaces in current, searching for using
       directives of scope.  */
*************** lookup_using_namespace (name, val, using
*** 3869,3877 ****
  	if (spacesp)
  	  *spacesp = tree_cons (TREE_PURPOSE (iter), NULL_TREE,
  				*spacesp);
! 	val1 = binding_for_name (name, TREE_PURPOSE (iter));
! 	/* Resolve ambiguities.  */
! 	val = ambiguous_decl (name, val, val1, flags);
        }
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
                            BINDING_VALUE (val) != error_mark_node);
--- 3863,3872 ----
  	if (spacesp)
  	  *spacesp = tree_cons (TREE_PURPOSE (iter), NULL_TREE,
  				*spacesp);
! 	val1 = cxx_scope_find_binding_for_name (TREE_PURPOSE (iter), name);
! 	/* Resolve possible ambiguities.  */
!         if (val1)
!           val = ambiguous_decl (name, val, val1, flags);
        }
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
                            BINDING_VALUE (val) != error_mark_node);
*************** lookup_using_namespace (name, val, using
*** 3879,3893 ****
  
  /* [namespace.qual]
     Accepts the NAME to lookup and its qualifying SCOPE.
!    Returns the name/type pair found into the CPLUS_BINDING RESULT,
     or 0 on error.  */
  
! int
! qualified_lookup_using_namespace (name, scope, result, flags)
!      tree name;
!      tree scope;
!      tree result;
!      int flags;
  {
    /* Maintain a list of namespaces visited...  */
    tree seen = NULL_TREE;
--- 3874,3885 ----
  
  /* [namespace.qual]
     Accepts the NAME to lookup and its qualifying SCOPE.
!    Returns the name/type pair found into the cxx_binding *RESULT,
     or 0 on error.  */
  
! bool
! qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result,
!                                   int flags)
  {
    /* Maintain a list of namespaces visited...  */
    tree seen = NULL_TREE;
*************** qualified_lookup_using_namespace (name, 
*** 3897,3907 ****
    timevar_push (TV_NAME_LOOKUP);
    /* Look through namespace aliases.  */
    scope = ORIGINAL_NAMESPACE (scope);
!   while (scope && (result != error_mark_node))
      {
!       seen = tree_cons (scope, NULL_TREE, seen);
!       result = ambiguous_decl (name, result,
!                                binding_for_name (name, scope), flags);
        if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
  	/* Consider using directives.  */
  	for (usings = DECL_NAMESPACE_USING (scope); usings;
--- 3889,3904 ----
    timevar_push (TV_NAME_LOOKUP);
    /* Look through namespace aliases.  */
    scope = ORIGINAL_NAMESPACE (scope);
!   while (scope && result->value != error_mark_node)
      {
!       cxx_binding *b = cxx_scope_find_binding_for_name (scope, name);
!       /* Record SCOPE and resolve declaration ambiguities if NAME was
!          bound in SCOPE.  */ 
!       if (b)
!         {
!           seen = tree_cons (scope, NULL_TREE, seen);
!           result = ambiguous_decl (name, result, b, flags);
!         }
        if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
  	/* Consider using directives.  */
  	for (usings = DECL_NAMESPACE_USING (scope); usings;
*************** qualified_lookup_using_namespace (name, 
*** 3918,3924 ****
        else
  	scope = NULL_TREE; /* If there never was a todo list.  */
      }
!   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result != error_mark_node);
  }
  
  /* [namespace.memdef]/2 */
--- 3915,3921 ----
        else
  	scope = NULL_TREE; /* If there never was a todo list.  */
      }
!   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
  }
  
  /* [namespace.memdef]/2 */
*************** do_nonmember_using_decl (scope, name, ol
*** 4503,4535 ****
       tree oldval, oldtype;
       tree *newval, *newtype;
  {
!   tree decls;
  
    *newval = *newtype = NULL_TREE;
!   decls = make_node (CPLUS_BINDING);
!   if (!qualified_lookup_using_namespace (name, scope, decls, 0))
      /* Lookup error */
      return;
  
!   if (!BINDING_VALUE (decls) && !BINDING_TYPE (decls))
      {
        error ("`%D' not declared", name);
        return;
      }
  
    /* Check for using functions.  */
!   if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
      {
        tree tmp, tmp1;
  
        if (oldval && !is_overloaded_fn (oldval))
  	{
! 	  duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval);
  	  oldval = NULL_TREE;
  	}
  
        *newval = oldval;
!       for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
  	{
  	  tree new_fn = OVL_CURRENT (tmp);
  
--- 4500,4532 ----
       tree oldval, oldtype;
       tree *newval, *newtype;
  {
!   cxx_binding decls;
  
    *newval = *newtype = NULL_TREE;
!   cxx_binding_clear (&decls);
!   if (!qualified_lookup_using_namespace (name, scope, &decls, 0))
      /* Lookup error */
      return;
  
!   if (!decls.value && !decls.type)
      {
        error ("`%D' not declared", name);
        return;
      }
  
    /* Check for using functions.  */
!   if (decls.value && is_overloaded_fn (decls.value))
      {
        tree tmp, tmp1;
  
        if (oldval && !is_overloaded_fn (oldval))
  	{
! 	  duplicate_decls (OVL_CURRENT (decls.value), oldval);
  	  oldval = NULL_TREE;
  	}
  
        *newval = oldval;
!       for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
  	{
  	  tree new_fn = OVL_CURRENT (tmp);
  
*************** do_nonmember_using_decl (scope, name, ol
*** 4583,4594 ****
      }
    else 
      {
!       *newval = BINDING_VALUE (decls);
        if (oldval)
  	duplicate_decls (*newval, oldval);
      } 
  
!   *newtype = BINDING_TYPE (decls);
    if (oldtype && *newtype && oldtype != *newtype)
      {
        error ("using declaration `%D' introduced ambiguous type `%T'",
--- 4580,4591 ----
      }
    else 
      {
!       *newval = decls.value;
        if (oldval)
  	duplicate_decls (*newval, oldval);
      } 
  
!   *newtype = decls.type;
    if (oldtype && *newtype && oldtype != *newtype)
      {
        error ("using declaration `%D' introduced ambiguous type `%T'",
*************** void
*** 4603,4615 ****
  do_toplevel_using_decl (decl)
       tree decl;
  {
!   tree scope, name, binding;
    tree oldval, oldtype, newval, newtype;
  
    decl = validate_nonmember_using_decl (decl, &scope, &name);
    if (decl == NULL_TREE)
      return;
!   
    binding = binding_for_name (name, current_namespace);
  
    oldval = BINDING_VALUE (binding);
--- 4600,4615 ----
  do_toplevel_using_decl (decl)
       tree decl;
  {
!   tree scope, name;
    tree oldval, oldtype, newval, newtype;
+   cxx_binding *binding;
  
    decl = validate_nonmember_using_decl (decl, &scope, &name);
    if (decl == NULL_TREE)
      return;
! 
!   /* A multiple using-declaration is valid, so we call binding_for_name,
!      not just cxx_binding_make.  */
    binding = binding_for_name (name, current_namespace);
  
    oldval = BINDING_VALUE (binding);
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/Attic/parse.y,v
retrieving revision 1.284.2.3
diff -p -r1.284.2.3 parse.y
*** parse.y	24 Dec 2002 22:44:40 -0000	1.284.2.3
--- parse.y	9 Mar 2003 20:46:40 -0000
*************** static tree
*** 4031,4047 ****
  parse_scoped_id (token)
       tree token;
  {
!   tree id;
! 
!   id = make_node (CPLUS_BINDING);
!   if (!qualified_lookup_using_namespace (token, global_namespace, id, 0))
!     id = NULL_TREE;
!   else
!     id = BINDING_VALUE (id);
    if (yychar == YYEMPTY)
      yychar = yylex();
  
!   return do_scoped_id (token, id);
  }
  
  /* AGGR may be either a type node (like class_type_node) or a
--- 4031,4045 ----
  parse_scoped_id (token)
       tree token;
  {
!   cxx_binding binding;
!  
!   cxx_binding_clear (&binding);
!   if (!qualified_lookup_using_namespace (token, global_namespace, &binding, 0))
!     binding.value = NULL;
    if (yychar == YYEMPTY)
      yychar = yylex();
  
!   return do_scoped_id (token, binding.value);
  }
  
  /* AGGR may be either a type node (like class_type_node) or a
Index: ptree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/ptree.c,v
retrieving revision 1.28
diff -p -r1.28 ptree.c
*** ptree.c	9 Nov 2001 23:30:28 -0000	1.28
--- ptree.c	9 Mar 2003 20:46:40 -0000
*************** cxx_print_type (file, node, indent)
*** 157,171 ****
      }
  }
  
  void
  cxx_print_identifier (file, node, indent)
       FILE *file;
       tree node;
       int indent;
  {
!   print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4);
    print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
!   print_node (file, "local bindings", IDENTIFIER_BINDING (node), indent + 4);
    print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
    print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
    print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
--- 157,179 ----
      }
  }
  
+ static void
+ cxx_print_binding (FILE *stream, cxx_binding *binding, const char *prefix)
+ {
+   fprintf (stream, "%s <", prefix);
+   fprintf (stream, HOST_PTR_PRINTF, (char *) binding);
+   fprintf (stream, ">");
+ }
+ 
  void
  cxx_print_identifier (file, node, indent)
       FILE *file;
       tree node;
       int indent;
  {
!   cxx_print_binding (file, IDENTIFIER_NAMESPACE_BINDINGS (node), "bindings");
    print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
!   cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings");
    print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
    print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
    print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
*************** cxx_print_xnode (file, node, indent)
*** 180,191 ****
  {
    switch (TREE_CODE (node))
      {
-     case CPLUS_BINDING:
-       fprintf (file, " scope ");
-       fprintf (file, HOST_PTR_PRINTF, BINDING_SCOPE (node));
-       print_node (file, "value", BINDING_VALUE (node), indent+4);
-       print_node (file, "chain", TREE_CHAIN (node), indent+4);
-       break;
      case OVERLOAD:
        print_node (file, "function", OVL_FUNCTION (node), indent+4);
        print_node (file, "chain", TREE_CHAIN (node), indent+4);
--- 188,193 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]