c++: Name lookup simplifications
authorNathan Sidwell <nathan@acm.org>
Tue, 29 Sep 2020 16:38:34 +0000 (09:38 -0700)
committerNathan Sidwell <nathan@acm.org>
Tue, 29 Sep 2020 16:41:50 +0000 (09:41 -0700)
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.

gcc/cp/name-lookup.c
gcc/cp/pt.c

index f195e81280a8cc9c9e371f787a73b29fbeab0bf6..89f1a4c5d645205509a6c387f9d9a599fb2896ad 100644 (file)
@@ -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
index 199fe658f715e61d1fa647dfea90be568bfd9009..a09633751ca98f0eaa123e744508d56baf74fcfc 100644 (file)
@@ -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