diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 18e4b9997b6b..01b8c4d6da60 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2017-10-04  Nathan Sidwell  <nathan@acm.org>
+
+	Move mangling aliases out of global namespace.
+	* cp-tree.h (record_mangling): New.
+	(maybe_remove_implicit_alias): Delete.
+	* decl2.c (mangled_decls): New hash map.
+	(generate_mangling_alias): Reimplement using mangled_decls.
+	(record_mangling): New.
+	* mangle.c (decl_implicit_alias_p,
+	maybe_remove_implicit_alias): Delete.
+	(mangle_decl): Use record_mangling.
+	* name-lookup.c (supplement_binding_1): Remove
+	maybe_remove_implicit_alias check.
+
 2017-10-04  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c++/82373
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a21c94853934..82ebc2831c58 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6142,6 +6142,7 @@ extern tree finish_case_label			(location_t, tree, tree);
 extern tree cxx_maybe_build_cleanup		(tree, tsubst_flags_t);
 
 /* in decl2.c */
+extern void record_mangling			(tree, bool);
 extern void note_mangling_alias			(tree, tree);
 extern void generate_mangling_aliases		(void);
 extern tree build_memfn_type			(tree, tree, cp_cv_quals, cp_ref_qualifier);
@@ -7154,7 +7155,6 @@ extern tree add_exception_specifier		(tree, tree, int);
 extern tree merge_exception_specifiers		(tree, tree);
 
 /* in mangle.c */
-extern bool maybe_remove_implicit_alias		(tree);
 extern void init_mangle				(void);
 extern void mangle_decl				(tree);
 extern const char *mangle_type_string		(tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index eb9c6a59e047..354d503da6d5 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -102,6 +102,10 @@ static GTY(()) vec<tree, va_gc> *no_linkage_decls;
    is to be an alias for the former if the former is defined.  */
 static GTY(()) vec<tree, va_gc> *mangling_aliases;
 
+/* A hash table of mangled names to decls.  Used to figure out if we
+   need compatibility aliases.  */
+static GTY(()) hash_map<lang_identifier *, tree> *mangled_decls;
+
 /* Nonzero if we're done parsing and into end-of-file activities.  */
 
 int at_eof;
@@ -4290,25 +4294,34 @@ handle_tls_init (void)
 static void
 generate_mangling_alias (tree decl, tree id2)
 {
+  struct cgraph_node *n = NULL;
+
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      n = cgraph_node::get (decl);
+      if (!n)
+	/* Don't create an alias to an unreferenced function.  */
+	return;
+    }
+
+  bool existed;
+  tree *slot = &mangled_decls->get_or_insert (id2, &existed);
+
   /* If there's a declaration already using this mangled name,
      don't create a compatibility alias that conflicts.  */
-  if (IDENTIFIER_GLOBAL_VALUE (id2))
-    return;
-
-  struct cgraph_node *n = NULL;
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && !(n = cgraph_node::get (decl)))
-    /* Don't create an alias to an unreferenced function.  */
+  if (existed)
     return;
 
   tree alias = make_alias_for (decl, id2);
-  SET_IDENTIFIER_GLOBAL_VALUE (id2, alias);
+  *slot = alias;
+
   DECL_IGNORED_P (alias) = 1;
   TREE_PUBLIC (alias) = TREE_PUBLIC (decl);
   DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl);
   if (vague_linkage_p (decl))
     DECL_WEAK (alias) = 1;
-  if (TREE_CODE (decl) == FUNCTION_DECL)
+
+  if (n)
     n->create_same_body_alias (alias, decl);
   else
     varpool_node::create_extra_name_alias (alias, decl);
@@ -4347,6 +4360,50 @@ generate_mangling_aliases ()
   defer_mangling_aliases = false;
 }
 
+/* Record a mangling of DECL, whose DECL_ASSEMBLER_NAME has just been
+   set.  NEED_WARNING is true if we must warn about collisions.  We do
+   this to spot changes in mangling that may require compatibility
+   aliases.  */
+
+void
+record_mangling (tree decl, bool need_warning)
+{
+  if (!mangled_decls)
+    mangled_decls = hash_map<lang_identifier *, tree>::create_ggc (499);
+
+  gcc_checking_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
+  tree id = DECL_ASSEMBLER_NAME (decl);
+  bool existed;
+  tree *slot = &mangled_decls->get_or_insert (id, &existed);
+
+  /* If this is already an alias, remove the alias, because the real
+     decl takes presidence.  */
+  if (!existed)
+    ;
+  else if (DECL_ARTIFICIAL (*slot) && DECL_IGNORED_P (*slot))
+    if (symtab_node *n = symtab_node::get (*slot))
+      if (n->cpp_implicit_alias)
+	{
+	  n->remove ();
+	  existed = false;
+	}
+
+  if (!existed)
+    *slot = decl;
+  else if (need_warning)
+    {
+      error_at (DECL_SOURCE_LOCATION (decl),
+		"mangling of %q#D as %qE conflicts with a previous mangle",
+		decl, id);
+      inform (DECL_SOURCE_LOCATION (*slot),
+	      "previous mangling %q#D", *slot);
+      inform (DECL_SOURCE_LOCATION (decl),
+	      "a later -fabi-version= (or =0)"
+	      " avoids this error with a change in mangling");
+      *slot = decl;
+    }
+}
+
 /* The entire file is now complete.  If requested, dump everything
    to a file.  */
 
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 33cd00e33147..6046906e77d7 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -3783,38 +3783,6 @@ get_mangled_id (tree decl)
   return targetm.mangle_decl_assembler_name (decl, id);
 }
 
-/* If DECL is an implicit mangling alias, return its symtab node; otherwise
-   return NULL.  */
-
-static symtab_node *
-decl_implicit_alias_p (tree decl)
-{
-  if (DECL_P (decl) && DECL_ARTIFICIAL (decl)
-      && DECL_IGNORED_P (decl)
-      && (TREE_CODE (decl) == FUNCTION_DECL
-	  || (VAR_P (decl) && TREE_STATIC (decl))))
-    {
-      symtab_node *n = symtab_node::get (decl);
-      if (n && n->cpp_implicit_alias)
-	return n;
-    }
-  return NULL;
-}
-
-/* If DECL is a mangling alias, remove it from the symbol table and return
-   true; otherwise return false.  */
-
-bool
-maybe_remove_implicit_alias (tree decl)
-{
-  if (symtab_node *n = decl_implicit_alias_p (decl))
-    {
-      n->remove();
-      return true;
-    }
-  return false;
-}
-
 /* Create an identifier for the external mangled name of DECL.  */
 
 void
@@ -3871,29 +3839,11 @@ mangle_decl (const tree decl)
 
       if (!DECL_REALLY_EXTERN (decl))
 	{
-	  bool set = false;
-
-	  /* Check IDENTIFIER_GLOBAL_VALUE before setting to avoid redundant
-	     errors from multiple definitions.  */
-	  tree d = IDENTIFIER_GLOBAL_VALUE (id);
-	  if (!d || decl_implicit_alias_p (d))
-	    {
-	      set = true;
-	      SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
-	    }
+	  record_mangling (decl, G.need_abi_warning);
 
 	  if (!G.need_abi_warning)
 	    return;
 
-	  /* If the mangling will change in the future, emit an alias with the
-	     future mangled name for forward-compatibility.  */
-	  if (!set)
-	    {
-	      SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
-	      inform (DECL_SOURCE_LOCATION (decl), "a later -fabi-version= (or "
-		      "=0) avoids this error with a change in mangling");
-	    }
-
 	  flag_abi_version = flag_abi_compat_version;
 	  id2 = mangle_decl_string (decl);
 	  id2 = targetm.mangle_decl_assembler_name (decl, id2);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 6763a5b9c682..0111d8de899c 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -2255,12 +2255,6 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
       region to refer only to the namespace to which it already
       refers.  */
     ok = false;
-  else if (maybe_remove_implicit_alias (bval))
-    {
-      /* There was a mangling compatibility alias using this mangled name,
-	 but now we have a real decl that wants to use it instead.  */
-      binding->value = decl;
-    }
   else
     {
       if (!error_operand_p (bval))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0153b3d0458c..26ca5563af42 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2017-10-04  Nathan Sidwell  <nathan@acm.org>
+
+	* g++.dg/abi/mangle41.C: Adjust diagnostics.
+
 2017-10-04  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c++/82373
diff --git a/gcc/testsuite/g++.dg/abi/mangle41.C b/gcc/testsuite/g++.dg/abi/mangle41.C
index 5fa47f165266..9da72f11feb6 100644
--- a/gcc/testsuite/g++.dg/abi/mangle41.C
+++ b/gcc/testsuite/g++.dg/abi/mangle41.C
@@ -3,6 +3,6 @@
 // { dg-options "-mavx -fabi-version=2" }
 
 #include <x86intrin.h>
-void f(__m128) { }		// { dg-message "previous declaration" }
-void f(__m256) { }		// { dg-error "conflicts" }
+void f(__m128) { }	// { dg-message "previous mangling" }
+void f(__m256) { }	// { dg-error "conflicts with a previous mangle" }
 // { dg-message "mangling" "" { target *-*-* } .-1 }
diff --git a/libcc1/ChangeLog b/libcc1/ChangeLog
index 4d8f40c83123..ea7a1aeb25b3 100644
--- a/libcc1/ChangeLog
+++ b/libcc1/ChangeLog
@@ -1,3 +1,8 @@
+2017-10-04  Nathan Sidwell  <nathan@acm.org>
+
+	* libcp1plugin.cc (supplement_binding): Don't use
+	maybe_remove_implicit_alias.
+
 2017-07-20  Nathan Sidwell  <nathan@acm.org>
 
 	Remove TYPE_METHODS.
diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
index d7bf5a29d6d0..12ea4ed84e0d 100644
--- a/libcc1/libcp1plugin.cc
+++ b/libcc1/libcp1plugin.cc
@@ -422,12 +422,6 @@ supplement_binding (cxx_binding *binding, tree decl)
       region to refer only to the namespace to which it already
       refers.  */
     ok = false;
-  else if (maybe_remove_implicit_alias (bval))
-    {
-      /* There was a mangling compatibility alias using this mangled name,
-	 but now we have a real decl that wants to use it instead.  */
-      binding->value = decl;
-    }
   else
     {
       // _1: diagnose_name_conflict (decl, bval);