Here are a few cleanups, prior to landing the hidden decl changes.

1) Clear cxx_binding flags in the allocator, not at each user of the allocator.

2) Refactor update_binding.  The logic was getting too convoluted.

3) Set friendliness and anticipatedness before pushing a template decl (not after).

        gcc/cp/
        * name-lookup.c (create_local_binding): Do not clear
        INHERITED_VALUE_BINDING_P here.
        (name_lookup::process_binding): Move done hidden-decl triage to ...
        (name_lookup::search_namespace_only): ... here, its only caller.
        (cxx_binding_make): Clear flags here.
        (push_binding): Not here.
        (pop_local_binding): RAII.
        (update_binding): Refactor.
        (do_pushdecl): Assert we're never revealing a local binding.
        (do_pushdecl_with_scope): Directly call do_pushdecl.
        (get_class_binding): Do not clear LOCAL_BINDING_P here.
        * pt.c (push_template_decl): Set friend & anticipated before
        pushing.

pushing to trunk

nathan

--
Nathan Sidwell
diff --git i/gcc/cp/name-lookup.c w/gcc/cp/name-lookup.c
index f195e81280a..89f1a4c5d64 100644
--- i/gcc/cp/name-lookup.c
+++ w/gcc/cp/name-lookup.c
@@ -77,7 +77,6 @@ create_local_binding (cp_binding_level *level, tree name)
 {
   cxx_binding *binding = cxx_binding_make (NULL, NULL);
 
-  INHERITED_VALUE_BINDING_P (binding) = false;
   LOCAL_BINDING_P (binding) = true;
   binding->scope = level;
   binding->previous = IDENTIFIER_BINDING (name);
@@ -480,22 +479,17 @@ name_lookup::add_type (tree new_type)
 }
 
 /* Process a found binding containing NEW_VAL and NEW_TYPE.  Returns
-   true if we actually found something noteworthy.  */
+   true if we actually found something noteworthy.  Hiddenness has
+   already been handled in the caller.  */
 
 bool
 name_lookup::process_binding (tree new_val, tree new_type)
 {
   /* Did we really see a type? */
   if (new_type
-      && ((want & LOOK_want::TYPE_NAMESPACE) == LOOK_want::NAMESPACE
-	  || (!bool (want & LOOK_want::HIDDEN_FRIEND)
-	      && DECL_LANG_SPECIFIC (new_type)
-	      && DECL_ANTICIPATED (new_type))))
+      && (want & LOOK_want::TYPE_NAMESPACE) == LOOK_want::NAMESPACE)
     new_type = NULL_TREE;
 
-  if (new_val && !bool (want & LOOK_want::HIDDEN_FRIEND))
-    new_val = ovl_skip_hidden (new_val);
-
   /* Do we really see a value? */
   if (new_val)
     switch (TREE_CODE (new_val))
@@ -544,8 +538,25 @@ name_lookup::search_namespace_only (tree scope)
   bool found = false;
 
   if (tree *binding = find_namespace_slot (scope, name))
-    found |= process_binding (MAYBE_STAT_DECL (*binding),
-			      MAYBE_STAT_TYPE (*binding));
+    {
+      tree value = *binding, type = NULL_TREE;
+
+      if (STAT_HACK_P (value))
+	{
+	  type = STAT_TYPE (value);
+	  value = STAT_DECL (value);
+      
+	  if (!bool (want & LOOK_want::HIDDEN_FRIEND)
+	      && DECL_LANG_SPECIFIC (type)
+	      && DECL_ANTICIPATED (type))
+	    type = NULL_TREE;
+	}
+
+      if (!bool (want & LOOK_want::HIDDEN_FRIEND))
+	value = ovl_skip_hidden (value);
+
+      found |= process_binding (value, type);
+    }
 
   return found;
 }
@@ -1954,15 +1965,17 @@ cxx_binding_init (cxx_binding *binding, tree value, tree type)
 static cxx_binding *
 cxx_binding_make (tree value, tree type)
 {
-  cxx_binding *binding;
-  if (free_bindings)
-    {
-      binding = free_bindings;
-      free_bindings = binding->previous;
-    }
+  cxx_binding *binding = free_bindings;
+
+  if (binding)
+    free_bindings = binding->previous;
   else
     binding = ggc_alloc<cxx_binding> ();
 
+  /* Clear flags by default.  */
+  LOCAL_BINDING_P (binding) = false;
+  INHERITED_VALUE_BINDING_P (binding) = false;
+
   cxx_binding_init (binding, value, type);
 
   return binding;
@@ -2009,7 +2022,6 @@ push_binding (tree id, tree decl, cp_binding_level* level)
 
   /* Now, fill in the binding information.  */
   binding->previous = IDENTIFIER_BINDING (id);
-  INHERITED_VALUE_BINDING_P (binding) = 0;
   LOCAL_BINDING_P (binding) = (level != class_binding_level);
 
   /* And put it on the front of the list of bindings for ID.  */
@@ -2022,8 +2034,6 @@ push_binding (tree id, tree decl, cp_binding_level* level)
 void
 pop_local_binding (tree id, tree decl)
 {
-  cxx_binding *binding;
-
   if (id == NULL_TREE)
     /* It's easiest to write the loops that call this function without
        checking whether or not the entities involved have names.  We
@@ -2031,7 +2041,7 @@ pop_local_binding (tree id, tree decl)
     return;
 
   /* Get the innermost binding for ID.  */
-  binding = IDENTIFIER_BINDING (id);
+  cxx_binding *binding = IDENTIFIER_BINDING (id);
 
   /* The name should be bound.  */
   gcc_assert (binding != NULL);
@@ -2356,9 +2366,16 @@ static tree
 update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
 		tree old, tree decl, bool hiding = false)
 {
+  tree old_type = NULL_TREE;
+
+  if (!slot)
+    old_type = binding->type;
+  else if (STAT_HACK_P (*slot))
+      old_type = STAT_TYPE (*slot);
+
   tree to_val = decl;
-  tree old_type = slot ? MAYBE_STAT_TYPE (*slot) : binding->type;
   tree to_type = old_type;
+  bool local_overload = false;
 
   gcc_assert (level->kind == sk_namespace ? !binding
 	      : level->kind != sk_class && !slot);
@@ -2375,16 +2392,20 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
 
       if (old)
 	{
-	  /* Slide decl into the type slot, keep old unaltered  */
+	  /* Put DECL into the type slot.  */
+	  gcc_checking_assert (!to_type);
 	  to_type = decl;
 	  to_val = old;
 	}
+
       goto done;
     }
 
   if (old && DECL_IMPLICIT_TYPEDEF_P (old))
     {
-      /* Slide old into the type slot.  */
+      /* OLD is an implicit typedef.  Move it to to_type.  */
+      gcc_checking_assert (!to_type);
+
       to_type = old;
       old = NULL_TREE;
     }
@@ -2428,60 +2449,66 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
 	warning (OPT_Wshadow, "%q#D hides constructor for %q#D",
 		 decl, to_type);
 
+      local_overload = old && level->kind != sk_namespace;
       to_val = ovl_insert (decl, old);
     }
-  else if (!old)
-    ;
-  else if (TREE_CODE (old) != TREE_CODE (decl))
-    /* Different kinds of decls conflict.  */
-    goto conflict;
-  else if (TREE_CODE (old) == TYPE_DECL)
-    {
-      if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
-	/* Two type decls to the same type.  Do nothing.  */
-	return old;
-      else
-	goto conflict;
-    }
-  else if (TREE_CODE (old) == NAMESPACE_DECL)
+  else if (old)
     {
-      /* Two maybe-aliased namespaces.  If they're to the same target
-	 namespace, that's ok.  */
-      if (ORIGINAL_NAMESPACE (old) != ORIGINAL_NAMESPACE (decl))
+      if (TREE_CODE (old) != TREE_CODE (decl))
+	/* Different kinds of decls conflict.  */
 	goto conflict;
-
-      /* The new one must be an alias at this point.  */
-      gcc_assert (DECL_NAMESPACE_ALIAS (decl));
-      return old;
-    }
-  else if (TREE_CODE (old) == VAR_DECL)
-    {
-      /* There can be two block-scope declarations of the same
-	 variable, so long as they are `extern' declarations.  */
-      if (!DECL_EXTERNAL (old) || !DECL_EXTERNAL (decl))
-	goto conflict;
-      else if (tree match = duplicate_decls (decl, old))
-	return match;
+      else if (TREE_CODE (old) == TYPE_DECL)
+	{
+	  if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
+	    {
+	      /* Two type decls to the same type.  Do nothing.  */
+	      gcc_checking_assert (!hiding);
+	      return old;
+	    }
+	  else
+	    goto conflict;
+	}
+      else if (TREE_CODE (old) == NAMESPACE_DECL)
+	{
+	  /* Two maybe-aliased namespaces.  If they're to the same target
+	     namespace, that's ok.  */
+	  if (ORIGINAL_NAMESPACE (old) != ORIGINAL_NAMESPACE (decl))
+	    goto conflict;
+
+	  /* The new one must be an alias at this point.  */
+	  gcc_assert (DECL_NAMESPACE_ALIAS (decl) && !hiding);
+	  return old;
+	}
+      else if (TREE_CODE (old) == VAR_DECL)
+	{
+	  /* There can be two block-scope declarations of the same
+	     variable, so long as they are `extern' declarations.  */
+	  // FIXME: This is DECL_LOCAL_DECL_P type stuff.
+	  if (!DECL_EXTERNAL (old) || !DECL_EXTERNAL (decl))
+	    goto conflict;
+	  else if (tree match = duplicate_decls (decl, old))
+	    return match;
+	  else
+	    goto conflict;
+	}
       else
-	goto conflict;
-    }
-  else
-    {
-    conflict:
-      diagnose_name_conflict (decl, old);
-      to_val = NULL_TREE;
+	{
+	conflict:
+	  diagnose_name_conflict (decl, old);
+	  to_val = NULL_TREE;
+	}
     }
 
  done:
   if (to_val)
     {
-      if (level->kind == sk_namespace || to_type == decl || to_val == decl)
-	add_decl_to_level (level, decl);
-      else
+      if (local_overload)
 	{
 	  gcc_checking_assert (binding->value && OVL_P (binding->value));
 	  update_local_overload (binding, to_val);
 	}
+      else
+	add_decl_to_level (level, decl);
 
       if (slot)
 	{
@@ -3059,12 +3086,8 @@ do_pushdecl (tree decl, bool hiding)
 		tree head = iter.reveal_node (old);
 		if (head != old)
 		  {
-		    if (!ns)
-		      {
-			update_local_overload (binding, head);
-			binding->value = head;
-		      }
-		    else if (STAT_HACK_P (*slot))
+		    gcc_checking_assert (ns);
+		    if (STAT_HACK_P (*slot))
 		      STAT_DECL (*slot) = head;
 		    else
 		      *slot = head;
@@ -3859,7 +3882,7 @@ do_pushdecl_with_scope (tree x, cp_binding_level *level, bool hiding = false)
 	current_function_decl = NULL_TREE;
       b = current_binding_level;
       current_binding_level = level;
-      x = pushdecl (x, hiding);
+      x = do_pushdecl (x, hiding);
       current_binding_level = b;
       current_function_decl = function_decl;
     }
@@ -4398,8 +4421,6 @@ get_class_binding (tree name, cp_binding_level *scope)
 				   value_binding,
 				   type_binding,
 				   scope);
-      /* This is a class-scope binding, not a block-scope binding.  */
-      LOCAL_BINDING_P (binding) = 0;
       set_inherited_value_binding_p (binding, value_binding, class_type);
     }
   else
diff --git i/gcc/cp/pt.c w/gcc/cp/pt.c
index 199fe658f71..a09633751ca 100644
--- i/gcc/cp/pt.c
+++ w/gcc/cp/pt.c
@@ -6018,16 +6018,16 @@ push_template_decl (tree decl, bool is_friend)
       if (!ctx
 	  && !(is_friend && template_class_depth (current_class_type) > 0))
 	{
-	  tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
-	  if (tmpl == error_mark_node)
-	    return error_mark_node;
-
 	  /* Hide template friend classes that haven't been declared yet.  */
 	  if (is_friend && TREE_CODE (decl) == TYPE_DECL)
 	    {
 	      DECL_ANTICIPATED (tmpl) = 1;
 	      DECL_FRIEND_P (tmpl) = 1;
 	    }
+
+	  tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
+	  if (tmpl == error_mark_node)
+	    return error_mark_node;
 	}
     }
   else

Reply via email to