cp-tree.h (PUSH_GLOBAL, [...]): Delete.
authorNathan Sidwell <nathan@acm.org>
Tue, 23 May 2017 21:15:48 +0000 (21:15 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 23 May 2017 21:15:48 +0000 (21:15 +0000)
* cp-tree.h (PUSH_GLOBAL, PUSH_LOCAL, PUSH_USING): Delete.
* name-lookup.c (create_local_binding): New.
(update_binding): New.
(pushdecl_maybe_friend_1): Rename to ...
(do_pushdecl): ... this.  Reimplement.
(pushdecl): Adjust.
(push_overloaded_decl_1, push_overloaded_decl): Delete.

From-SVN: r248387

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/name-lookup.c

index 2f15c9b177983dbad410d62be743f7dbf1ed9f6d..4a72b655318f4335ef99eb5e78c7f7815a6b9c99 100644 (file)
@@ -1,3 +1,13 @@
+2017-05-23  Nathan Sidwell  <nathan@acm.org>
+
+       * cp-tree.h (PUSH_GLOBAL, PUSH_LOCAL, PUSH_USING): Delete.
+       * name-lookup.c (create_local_binding): New.
+       (update_binding): New.
+       (pushdecl_maybe_friend_1): Rename to ...
+       (do_pushdecl): ... this.  Reimplement.
+       (pushdecl): Adjust.
+       (push_overloaded_decl_1, push_overloaded_decl): Delete.
+
 2017-05-23  Jason Merrill  <jason@redhat.com>
 
        PR c++/80396 - built-in for make_integer_sequence.
index 98ef023db61ae99767d058278b82d37b04104c0b..2ed9e5aa4738174768318a4628949a0c9eccef19 100644 (file)
@@ -5312,14 +5312,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
                                   will be identical to
                                   COMPARE_STRICT.  */
 
-/* Used with push_overloaded_decl.  */
-#define PUSH_GLOBAL         0  /* Push the DECL into namespace scope,
-                                  regardless of the current scope.  */
-#define PUSH_LOCAL          1  /* Push the DECL into the current
-                                  scope.  */
-#define PUSH_USING          2  /* We are pushing this DECL as the
-                                  result of a using declaration.  */
-
 /* Used with start function.  */
 #define SF_DEFAULT          0  /* No flags.  */
 #define SF_PRE_PARSED       1  /* The function declaration has
index 12024216bc81dd62cd9c66beb76a80a35a44c115..89d4e2ad1dbea229294cbbc6ba0a85babff30c43 100644 (file)
@@ -48,7 +48,6 @@ struct scope_binding {
 };
 #define EMPTY_SCOPE_BINDING { NULL_TREE, NULL_TREE }
 
-static tree push_overloaded_decl (tree, int, bool);
 static bool lookup_using_namespace (tree, struct scope_binding *, tree,
                                    tree, int);
 static bool qualified_lookup_using_namespace (tree, tree,
@@ -61,6 +60,23 @@ static void consider_binding_level (tree name,
 static tree push_using_directive (tree);
 static void diagnose_name_conflict (tree, tree);
 
+/* Create a local binding level for NAME.  */
+
+static cxx_binding *
+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);
+
+  IDENTIFIER_BINDING (name) = binding;
+  
+  return binding;
+}
+
 /* Find the binding for NAME in namespace NS.  If CREATE_P is true,
    make an empty binding if there wasn't one.  */
 
@@ -1281,6 +1297,173 @@ matching_fn_p (tree one, tree two)
   return true;
 }
 
+/* Push DECL into nonclass LEVEL BINDING.  OLD is the current
+   binding value (possibly with anticipated builtins stripped).
+   Diagnose conflicts and return updated decl.  */
+
+static tree
+update_binding (cp_binding_level *level, cxx_binding *binding,
+               tree old, tree decl, bool is_friend)
+{
+  tree to_val = decl;
+  tree to_type = NULL_TREE;
+
+  gcc_assert (level->kind != sk_class);
+  if (old == error_mark_node)
+    old = NULL_TREE;
+
+  if (old && TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
+    {
+      /* Slide the tdef out of the way.  We'll undo this below, if
+        we're pushing a matching tdef.  */
+      to_type = old;
+      old = NULL_TREE;
+    }
+
+  if (DECL_DECLARES_FUNCTION_P (decl))
+    {
+      if (!old)
+       ;
+      else if (OVL_P (old))
+       {
+         for (ovl_iterator iter (old); iter; ++iter)
+           {
+             tree fn = *iter;
+
+             if (iter.using_p () && matching_fn_p (fn, decl))
+               {
+                 /* If a function declaration in namespace scope or
+                    block scope has the same name and the same
+                    parameter-type- list (8.3.5) as a function
+                    introduced by a using-declaration, and the
+                    declarations do not declare the same function,
+                    the program is ill-formed.  [namespace.udecl]/14 */
+                 if (tree match = duplicate_decls (decl, fn, is_friend))
+                   return match;
+                 else
+                   /* FIXME: To preserve existing error behavior, we
+                      still push the decl.  This might change.  */
+                   diagnose_name_conflict (decl, fn);
+               }
+           }
+       }
+      else
+       goto conflict;
+
+      to_val = ovl_insert (decl, old);
+    }
+  else if (to_type && TREE_CODE (decl) == TYPE_DECL)
+    {
+      /* We thought we wanted to slide an artificial typedef out of
+        the way, to make way for another typedef.  That's not always
+        what we want to do.  */
+      if (!DECL_ARTIFICIAL (decl))
+       ; /* Slide.  */
+      else if (same_type_p (TREE_TYPE (to_type), TREE_TYPE (decl)))
+       /* Two artificial decls to same type.  Do nothing.  */
+       return to_type;
+      else
+       goto conflict;
+    }
+  else if (!old)
+    ;
+  else if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+    {
+      /* Slide DECL into the type slot.  */
+      to_type = decl;
+      to_val = old;
+    }
+  else if (TREE_CODE (old) != TREE_CODE (decl))
+    /* Different kinds of decls conflict.  */
+    goto conflict;
+  else if (TREE_CODE (old) == TYPE_DECL)
+    {
+      if (DECL_ARTIFICIAL (decl))
+       {
+         /* Slide DECL into the type slot instead.  */
+         to_type = decl;
+         to_val = old;
+       }
+      else 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)
+    {
+      if (DECL_NAMESPACE_ALIAS (old) && DECL_NAMESPACE_ALIAS (decl)
+         && ORIGINAL_NAMESPACE (old) == ORIGINAL_NAMESPACE (decl))
+       /* In a declarative region, a namespace-alias-definition can be
+          used to redefine a namespace-alias declared in that declarative
+          region to refer only to the namespace to which it already
+          refers.  [namespace.alias] */
+       return old;
+      else
+       goto conflict;
+    }
+  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, false))
+       return match;
+      else
+       goto conflict;
+    }
+  else
+    {
+    conflict:
+      diagnose_name_conflict (decl, old);
+      to_val = NULL_TREE;
+    }
+
+  if (to_val)
+    {
+      if (level->kind != sk_namespace
+         && !to_type && binding->value && OVL_P (to_val))
+       update_local_overload (binding, to_val);
+      else
+       {
+         tree to_add = to_val;
+      
+         if (level->kind == sk_namespace)
+           to_add = decl;
+         else if (to_type == decl)
+           to_add = decl;
+         else if (TREE_CODE (to_add) == OVERLOAD)
+           to_add = build_tree_list (NULL_TREE, to_add);
+
+         add_decl_to_level (level, to_add);
+       }
+
+      if (to_type == binding->type)
+       to_type = NULL_TREE;
+
+      if (to_type)
+       {
+         gcc_checking_assert (TREE_CODE (to_type) == TYPE_DECL
+                              && DECL_ARTIFICIAL (to_type));
+
+         tree type = TREE_TYPE (to_type);
+         if (to_type != decl
+             && MAYBE_CLASS_TYPE_P (type) && warn_shadow
+             && (!DECL_IN_SYSTEM_HEADER (decl)
+                 || !DECL_IN_SYSTEM_HEADER (to_type)))
+           warning (OPT_Wshadow, "%q#D hides constructor for %q#T",
+                    decl, type);
+       }
+
+      if (to_type)
+       binding->type = to_type;
+      binding->value = to_val;
+    }
+
+  return decl;
+}
+
 /* Map of identifiers to extern C functions (or LISTS thereof).  */
 
 static GTY(()) hash_map<lang_identifier *, tree> *extern_c_fns;
@@ -1690,338 +1873,146 @@ set_local_extern_decl_linkage (tree decl, bool shadowed)
     }
 }
 
-/* Record a decl-node X as belonging to the current lexical scope.
-   Check for errors (such as an incompatible declaration for the same
-   name already seen in the same scope).  IS_FRIEND is true if X is
+/* Record DECL as belonging to the current lexical scope.  Check for
+   errors (such as an incompatible declaration for the same name
+   already seen in the same scope).  IS_FRIEND is true if DECL is
    declared as a friend.
 
-   Returns either X or an old decl for the same name.
-   If an old decl is returned, it may have been smashed
-   to agree with what X says.  */
+   Returns either DECL or an old decl for the same name.  If an old
+   decl is returned, it may have been smashed to agree with what DECL
+   says.  */
 
 static tree
-pushdecl_maybe_friend_1 (tree x, bool is_friend)
+do_pushdecl (tree decl, bool is_friend)
 {
-  tree t;
-  tree name;
-  int need_new_binding;
-
-  if (x == error_mark_node)
+  if (decl == error_mark_node)
     return error_mark_node;
 
-  need_new_binding = 1;
+  if (!DECL_TEMPLATE_PARM_P (decl) && current_function_decl)
+    set_decl_context_in_fn (current_function_decl, decl);
 
-  if (!DECL_TEMPLATE_PARM_P (x) && current_function_decl)
-    set_decl_context_in_fn (current_function_decl, x);
+  /* The binding level we will be pushing into.  During local class
+     pushing, we want to push to the containing scope.  */
+  cp_binding_level *level = current_binding_level;
+  while (level->kind == sk_class)
+    level = level->level_chain;
 
-  name = DECL_NAME (x);
-  if (name)
+  if (tree name = DECL_NAME (decl))
     {
-      if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-       name = TREE_OPERAND (name, 0);
+      cxx_binding *binding = NULL;
+      tree ns = NULL_TREE; /* Searched namespace.  */
+      tree old = NULL_TREE;
 
-      /* In case this decl was explicitly namespace-qualified, look it
-        up in its namespace context.  */
-      if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
-       t = get_namespace_binding (CP_DECL_CONTEXT (x), name);
-      else
-       t = lookup_name_innermost_nonclass_level (name);
-
-      if (current_function_decl && VAR_OR_FUNCTION_DECL_P (x)
-         && DECL_EXTERNAL (x))
-       set_local_extern_decl_linkage (x, t != NULL_TREE);
-
-      /* If we are declaring a function, and the result of name-lookup
-        was an OVERLOAD, look for an overloaded instance that is
-        actually the same as the function we are declaring.  (If
-        there is one, we have to merge our declaration with the
-        previous declaration.)  */
-      if (t && TREE_CODE (t) == OVERLOAD)
+      if (level->kind == sk_namespace)
        {
-         tree match;
-
-         if (TREE_CODE (x) == FUNCTION_DECL)
-           for (match = t; match; match = OVL_NEXT (match))
-             {
-               if (decls_match (OVL_CURRENT (match), x))
-                 break;
-             }
-         else
-           /* Just choose one.  */
-           match = t;
-
-         if (match)
-           t = OVL_CURRENT (match);
-         else
-           t = NULL_TREE;
+         /* We look in the decl's namespace for an existing
+            declaration, even though we push into the current
+            namespace.  */
+         ns = (DECL_NAMESPACE_SCOPE_P (decl)
+               ? CP_DECL_CONTEXT (decl) : current_namespace);
+         /* Create the binding, if this is current namespace, because
+            that's where we'll be pushing anyway.  */
+         binding = find_namespace_binding (ns, name, ns == current_namespace);
        }
+      else
+       binding = find_local_binding (level, name);
 
-      if (t && t != error_mark_node)
-       {
-         if (TREE_CODE (t) == PARM_DECL)
-           {
-             /* Check for duplicate params.  */
-             tree d = duplicate_decls (x, t, is_friend);
-             if (d)
-               return d;
-           }
-         else if ((DECL_EXTERN_C_FUNCTION_P (x)
-                   || DECL_FUNCTION_TEMPLATE_P (x))
-                  && is_overloaded_fn (t))
-           /* Don't do anything just yet.  */;
-         else if (t == wchar_decl_node)
-           {
-             if (! DECL_IN_SYSTEM_HEADER (x))
-               pedwarn (input_location, OPT_Wpedantic, "redeclaration of %<wchar_t%> as %qT",
-                        TREE_TYPE (x));
-             
-             /* Throw away the redeclaration.  */
-             return t;
-           }
-         else
-           {
-             tree olddecl = duplicate_decls (x, t, is_friend);
-
-             /* If the redeclaration failed, we can stop at this
-                point.  */
-             if (olddecl == error_mark_node)
-               return error_mark_node;
-
-             if (olddecl)
-               {
-                 if (TREE_CODE (t) == TYPE_DECL)
-                   SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
+      if (binding)
+       old = binding->value;
 
-                 return t;
-               }
-             else if (DECL_MAIN_P (x) && TREE_CODE (t) == FUNCTION_DECL)
-               {
-                 /* A redeclaration of main, but not a duplicate of the
-                    previous one.
+      if (current_function_decl && VAR_OR_FUNCTION_DECL_P (decl)
+         && DECL_EXTERNAL (decl))
+       set_local_extern_decl_linkage (decl, old != NULL_TREE);
 
-                    [basic.start.main]
+      if (old == error_mark_node)
+       old = NULL_TREE;
 
-                    This function shall not be overloaded.  */
-                 error ("invalid redeclaration of %q+D", t);
-                 error ("as %qD", x);
-                 /* We don't try to push this declaration since that
-                    causes a crash.  */
-                 return x;
-               }
-           }
-       }
+      for (ovl_iterator iter (old); iter; ++iter)
+       if (iter.using_p ())
+         ; /* Ignore using decls here.  */
+       else if (tree match = duplicate_decls (decl, *iter, is_friend))
+         return match;
 
-      check_template_shadow (x);
+      /* We are pushing a new decl.  */
 
-      /* If this is a function conjured up by the back end, massage it
-        so it looks friendly.  */
-      if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_LANG_SPECIFIC (x))
-       {
-         retrofit_lang_decl (x);
-         SET_DECL_LANGUAGE (x, lang_c);
-       }
+      /* Skip a hidden builtin we failed to match already.  */
+      if (old && TREE_CODE (old) == FUNCTION_DECL
+         && DECL_ANTICIPATED (old)
+         && !DECL_HIDDEN_FRIEND_P (old))
+       old = NULL_TREE;
 
-      t = x;
-      if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_FUNCTION_MEMBER_P (x))
-       {
-         t = push_overloaded_decl (x, PUSH_LOCAL, is_friend);
-         if (!namespace_bindings_p ())
-           /* We do not need to create a binding for this name;
-              push_overloaded_decl will have already done so if
-              necessary.  */
-           need_new_binding = 0;
-       }
-      else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
-       {
-         t = push_overloaded_decl (x, PUSH_GLOBAL, is_friend);
-         if (t == x)
-           add_decl_to_level (NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)), x);
-       }
+      check_template_shadow (decl);
 
-      if (DECL_DECLARES_FUNCTION_P (t))
+      if (DECL_DECLARES_FUNCTION_P (decl))
        {
-         check_default_args (t);
+         check_default_args (decl);
 
-         if (is_friend && t == x && !flag_friend_injection)
+         if (is_friend)
            {
-             /* This is a new friend declaration of a function or a
-                function template, so hide it from ordinary function
-                lookup.  */
-             DECL_ANTICIPATED (t) = 1;
-             DECL_HIDDEN_FRIEND_P (t) = 1;
+             if (level->kind != sk_namespace)
+               /* In a local class, a friend function declaration must
+                  find a matching decl in the innermost non-class scope.
+                  [class.friend/11] */
+               error ("friend declaration %qD in local class without "
+                      "prior local declaration", decl);
+             else if (!flag_friend_injection)
+               /* Hide it from ordinary lookup.  */
+               DECL_ANTICIPATED (decl) = DECL_HIDDEN_FRIEND_P (decl) = true;
            }
        }
 
-      if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
-       return t;
-
-      /* If declaring a type as a typedef, copy the type (unless we're
-        at line 0), and install this TYPE_DECL as the new type's typedef
-        name.  See the extensive comment of set_underlying_type ().  */
-      if (TREE_CODE (x) == TYPE_DECL)
+      if (level->kind != sk_namespace)
        {
-         tree type = TREE_TYPE (x);
-
-         if (DECL_IS_BUILTIN (x)
-             || (TREE_TYPE (x) != error_mark_node
-                 && TYPE_NAME (type) != x
-                 /* We don't want to copy the type when all we're
-                    doing is making a TYPE_DECL for the purposes of
-                    inlining.  */
-                 && (!TYPE_NAME (type)
-                     || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-           set_underlying_type (x);
-
-         if (type != error_mark_node
-             && TYPE_IDENTIFIER (type))
-           set_identifier_type_value (DECL_NAME (x), x);
-
-         /* If this is a locally defined typedef in a function that
-            is not a template instantation, record it to implement
-            -Wunused-local-typedefs.  */
-         if (!instantiating_current_function_p ())
-           record_locally_defined_typedef (x);
-       }
-
-      /* Multiple external decls of the same identifier ought to match.
+         check_local_shadow (decl);
 
-        We get warnings about inline functions where they are defined.
-        We get warnings about other functions from push_overloaded_decl.
+         if (TREE_CODE (decl) == NAMESPACE_DECL)
+           /* A local namespace alias.  */
+           set_identifier_type_value (name, NULL_TREE);
 
-        Avoid duplicate warnings where they are used.  */
-      if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
-       {
-         tree decl;
-
-         decl = get_namespace_binding (current_namespace, name);
-         if (decl && TREE_CODE (decl) == OVERLOAD)
-           decl = OVL_FUNCTION (decl);
-
-         if (decl && decl != error_mark_node
-             && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
-             /* If different sort of thing, we already gave an error.  */
-             && TREE_CODE (decl) == TREE_CODE (x)
-             && !comptypes (TREE_TYPE (x), TREE_TYPE (decl),
-                            COMPARE_REDECLARATION))
-           {
-             if (permerror (input_location, "type mismatch with previous "
-                            "external decl of %q#D", x))
-               inform (DECL_SOURCE_LOCATION (decl),
-                       "previous external decl of %q#D", decl);
-           }
+         if (!binding)
+           binding = create_local_binding (level, name);
        }
-
-      /* This name is new in its binding level.
-        Install the new declaration and return it.  */
-      if (namespace_bindings_p ())
+      else if (!binding)
        {
-         /* Install a global value.  */
-
-         /* If the first global decl has external linkage,
-            warn if we later see static one.  */
-         if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
-           TREE_PUBLIC (name) = 1;
-
-         /* Bind the name for the entity.  */
-         if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
-               && t != NULL_TREE)
-             && (TREE_CODE (x) == TYPE_DECL
-                 || VAR_P (x)
-                 || TREE_CODE (x) == NAMESPACE_DECL
-                 || TREE_CODE (x) == CONST_DECL
-                 || TREE_CODE (x) == TEMPLATE_DECL))
-           set_namespace_binding (current_namespace, name, x);
-
-         /* If new decl is `static' and an `extern' was seen previously,
-            warn about it.  */
-         if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t))
-           warn_extern_redeclared_static (x, t);
+         ns = current_namespace;
+         binding = find_namespace_binding (ns, name, true);
        }
-      else
-       {
-         /* Here to install a non-global value.  */
-         tree oldglobal = get_namespace_binding (current_namespace, name);
-         tree oldlocal = NULL_TREE;
-         cxx_binding *oldbinding = outer_binding (name, NULL, true);
-         if (oldbinding)
-           oldlocal = oldbinding->value;
-
-         check_local_shadow (x);
-
-         if (need_new_binding)
-           {
-             push_local_binding (name, x, false);
-             /* Because push_local_binding will hook X on to the
-                current_binding_level's name list, we don't want to
-                do that again below.  */
-             need_new_binding = 0;
-           }
 
-         /* If this is a TYPE_DECL, push it into the type value slot.  */
-         if (TREE_CODE (x) == TYPE_DECL)
-           set_identifier_type_value (name, x);
+      old = update_binding (level, binding, old, decl, is_friend);
 
-         /* Clear out any TYPE_DECL shadowed by a namespace so that
-            we won't think this is a type.  The C struct hack doesn't
-            go through namespaces.  */
-         if (TREE_CODE (x) == NAMESPACE_DECL)
-           set_identifier_type_value (name, NULL_TREE);
+      if (old != decl)
+       /* An existing decl matched, use it.  */
+       decl = old;
+      else if (TREE_CODE (decl) == TYPE_DECL)
+       {
+         tree type = TREE_TYPE (decl);
 
-         if (oldlocal)
+         if (type != error_mark_node)
            {
-             tree d = oldlocal;
-
-             while (oldlocal
-                    && VAR_P (oldlocal)
-                    && DECL_DEAD_FOR_LOCAL (oldlocal))
-               oldlocal = DECL_SHADOWED_FOR_VAR (oldlocal);
-
-             if (oldlocal == NULL_TREE)
-               oldlocal
-                 = get_namespace_binding (current_namespace, DECL_NAME (d));
-           }
+             if (TYPE_NAME (type) != decl)
+               set_underlying_type (decl);
 
-         /* If this is an extern function declaration, see if we
-            have a global definition or declaration for the function.  */
-         if (oldlocal == NULL_TREE
-             && DECL_EXTERNAL (x)
-             && oldglobal != NULL_TREE
-             && TREE_CODE (x) == FUNCTION_DECL
-             && TREE_CODE (oldglobal) == FUNCTION_DECL)
-           {
-             /* We have one.  Their types must agree.  */
-             if (decls_match (x, oldglobal))
-               /* OK */;
+             if (!ns)
+               set_identifier_type_value_with_scope (name, decl, level);
              else
-               {
-                 warning (0, "extern declaration of %q#D doesn%'t match", x);
-                 warning_at (DECL_SOURCE_LOCATION (oldglobal), 0,
-                             "global declaration %q#D", oldglobal);
-               }
+               SET_IDENTIFIER_TYPE_VALUE (name, global_type_node);
            }
-         /* If we have a local external declaration,
-            and no file-scope declaration has yet been seen,
-            then if we later have a file-scope decl it must not be static.  */
-         if (oldlocal == NULL_TREE
-             && oldglobal == NULL_TREE
-             && DECL_EXTERNAL (x)
-             && TREE_PUBLIC (x))
-           TREE_PUBLIC (name) = 1;
-       }
 
-      if (VAR_P (x))
-       maybe_register_incomplete_var (x);
-      if (TREE_CODE (x) == FUNCTION_DECL && DECL_EXTERN_C_P (x))
-       /* We need to check and register the fn now.  */
-       check_extern_c_conflict (x);
+         /* If this is a locally defined typedef in a function that
+            is not a template instantation, record it to implement
+            -Wunused-local-typedefs.  */
+         if (!instantiating_current_function_p ())
+           record_locally_defined_typedef (decl);
+       }
+      else if (VAR_P (decl))
+       maybe_register_incomplete_var (decl);
+      else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_EXTERN_C_P (decl))
+       check_extern_c_conflict (decl);
     }
+  else
+    add_decl_to_level (level, decl);
 
-  if (need_new_binding)
-    add_decl_to_level (DECL_NAMESPACE_SCOPE_P (x)
-                      ? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
-                      : current_binding_level, x);
-
-  return x;
+  return decl;
 }
 
 /* Record a decl-node X as belonging to the current lexical scope.
@@ -2032,7 +2023,7 @@ pushdecl (tree x, bool is_friend)
 {
   tree ret;
   bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
-  ret = pushdecl_maybe_friend_1 (x, is_friend);
+  ret = do_pushdecl (x, is_friend);
   timevar_cond_stop (TV_NAME_LOOKUP, subtime);
   return ret;
 }
@@ -2924,151 +2915,6 @@ pushdecl_outermost_localscope (tree x)
   return ret;
 }
 
-/* DECL is a FUNCTION_DECL for a non-member function, which may have
-   other definitions already in place.  We get around this by making
-   the value of the identifier point to a list of all the things that
-   want to be referenced by that name.  It is then up to the users of
-   that name to decide what to do with that list.
-
-   DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its
-   DECL_TEMPLATE_RESULT.  It is dealt with the same way.
-
-   FLAGS is a bitwise-or of the following values:
-     PUSH_LOCAL: Bind DECL in the current scope, rather than at
-                namespace scope.
-     PUSH_USING: DECL is being pushed as the result of a using
-                declaration.
-
-   IS_FRIEND is true if this is a friend declaration.
-
-   The value returned may be a previous declaration if we guessed wrong
-   about what language DECL should belong to (C or C++).  Otherwise,
-   it's always DECL (and never something that's not a _DECL).  */
-
-static tree
-push_overloaded_decl_1 (tree decl, int flags, bool is_friend)
-{
-  tree name = DECL_NAME (decl);
-  tree old;
-  tree new_binding;
-  int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
-
-  if (doing_global)
-    old = get_namespace_binding (CP_DECL_CONTEXT (decl), name);
-  else
-    old = lookup_name_innermost_nonclass_level (name);
-
-  if (old)
-    {
-      if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
-       {
-         tree t = TREE_TYPE (old);
-         if (MAYBE_CLASS_TYPE_P (t) && warn_shadow
-             && (! DECL_IN_SYSTEM_HEADER (decl)
-                 || ! DECL_IN_SYSTEM_HEADER (old)))
-           warning (OPT_Wshadow, "%q#D hides constructor for %q#T", decl, t);
-         old = NULL_TREE;
-       }
-      else if (is_overloaded_fn (old))
-       {
-         tree tmp;
-
-         for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
-           {
-             tree fn = OVL_CURRENT (tmp);
-             tree dup;
-
-             if (TREE_CODE (tmp) == OVERLOAD && OVL_USING_P (tmp)
-                 && !(flags & PUSH_USING)
-                 && matching_fn_p (fn, decl)
-                 && ! decls_match (fn, decl))
-               diagnose_name_conflict (decl, fn);
-
-             dup = duplicate_decls (decl, fn, is_friend);
-             /* If DECL was a redeclaration of FN -- even an invalid
-                one -- pass that information along to our caller.  */
-             if (dup == fn || dup == error_mark_node)
-               return dup;
-           }
-
-         /* We don't overload implicit built-ins.  duplicate_decls()
-            may fail to merge the decls if the new decl is e.g. a
-            template function.  */
-         if (TREE_CODE (old) == FUNCTION_DECL
-             && DECL_ANTICIPATED (old)
-             && !DECL_HIDDEN_FRIEND_P (old))
-           old = NULL;
-       }
-      else if (old == error_mark_node)
-       /* Ignore the undefined symbol marker.  */
-       old = NULL_TREE;
-      else
-       {
-         error ("previous non-function declaration %q+#D", old);
-         error ("conflicts with function declaration %q#D", decl);
-         return decl;
-       }
-    }
-
-  new_binding = ovl_insert (decl, old, flags & PUSH_USING);
-
-  if (doing_global)
-    set_namespace_binding (current_namespace, name, new_binding);
-  else
-    {
-      /* We only create an OVERLOAD if there was a previous binding at
-        this level, or if decl is a template. In the former case, we
-        need to remove the old binding and replace it with the new
-        binding.  We must also run through the NAMES on the binding
-        level where the name was bound to update the chain.  */
-
-      if (TREE_CODE (new_binding) == OVERLOAD && old)
-       {
-         tree *d;
-
-         for (d = &IDENTIFIER_BINDING (name)->scope->names;
-              *d;
-              d = &TREE_CHAIN (*d))
-           if (*d == old
-               || (TREE_CODE (*d) == TREE_LIST
-                   && TREE_VALUE (*d) == old))
-             {
-               if (TREE_CODE (*d) == TREE_LIST)
-                 /* Just replace the old binding with the new.  */
-                 TREE_VALUE (*d) = new_binding;
-               else
-                 /* Build a TREE_LIST to wrap the OVERLOAD.  */
-                 *d = tree_cons (NULL_TREE, new_binding,
-                                 TREE_CHAIN (*d));
-
-               /* And update the cxx_binding node.  */
-               IDENTIFIER_BINDING (name)->value = new_binding;
-               return decl;
-             }
-
-         /* We should always find a previous binding in this case.  */
-         gcc_unreachable ();
-       }
-
-      /* Install the new binding.  */
-      push_local_binding (name, new_binding, flags);
-    }
-
-  return decl;
-}
-
-/* Wrapper for push_overloaded_decl_1.  */
-
-static tree
-push_overloaded_decl (tree decl, int flags, bool is_friend)
-{
-  tree ret;
-  bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
-  ret = push_overloaded_decl_1 (decl, flags, is_friend);
-  timevar_cond_stop (TV_NAME_LOOKUP, subtime);
-  return ret;
-}
-
 /* Check a non-member using-declaration. Return the name and scope
    being used, and the USING_DECL, or NULL_TREE on failure.  */