This patch fixes the bootstrap breakage reported by Rainer and David. Thanks for giving this one a spin.

We're somewhat overzealous about pushing artificial tags, and excessive cleverness in my creation of update_binding failed to cope with that.

nathan
--
Nathan Sidwell
2017-05-30  Nathan Sidwell  <nat...@acm.org>

	PR c++/80913
	* name-lookup.c (add_decl_to_level): Assert not making a circular
	chain.
	(update_binding): Don't prematurely slide artificial decl.

	* g++.dg/lookup/pr80913.C: New.

Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 248681)
+++ cp/name-lookup.c	(working copy)
@@ -132,6 +132,11 @@ add_decl_to_level (cp_binding_level *b,
     }
   else
     {
+      /* Make sure we don't create a circular list.  xref_tag can end
+	 up pushing the same artificial decl more than once.  We
+	 should have already detected that in update_binding.  */
+      gcc_assert (b->names != decl);
+
       /* We build up the list in reverse order, and reverse it later if
 	 necessary.  */
       TREE_CHAIN (decl) = b->names;
@@ -1720,17 +1725,43 @@ update_binding (cp_binding_level *level,
 		tree old, tree decl, bool is_friend)
 {
   tree to_val = decl;
-  tree to_type = NULL_TREE;
+  tree old_type = slot ? MAYBE_STAT_TYPE (*slot) : binding->type;
+  tree to_type = old_type;
 
   gcc_assert (level->kind == sk_namespace ? !binding
 	      : level->kind != sk_class && !slot);
   if (old == error_mark_node)
     old = NULL_TREE;
 
+  if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+    {
+      tree other = to_type;
+
+      if (old && TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
+	other = old;
+
+      /* Pushing an artificial typedef.  See if this matches either
+	 the type slot or the old value slot.  */
+      if (!other)
+	;
+      else if (same_type_p (TREE_TYPE (other), TREE_TYPE (decl)))
+	/* Two artificial decls to same type.  Do nothing.  */
+	return other;
+      else
+	goto conflict;
+
+      if (old)
+	{
+	  /* Slide decl into the type slot, keep old unaltered  */
+	  to_type = decl;
+	  to_val = old;
+	  goto done;
+	}
+    }
+
   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.  */
+      /* Slide old into the type slot.  */
       to_type = old;
       old = NULL_TREE;
     }
@@ -1767,39 +1798,14 @@ update_binding (cp_binding_level *level,
 
       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)))
+      if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
 	/* Two type decls to the same type.  Do nothing.  */
 	return old;
       else
@@ -1835,6 +1841,7 @@ update_binding (cp_binding_level *level,
       to_val = NULL_TREE;
     }
 
+ done:
   if (to_val)
     {
       if (level->kind != sk_namespace
@@ -1854,12 +1861,10 @@ update_binding (cp_binding_level *level,
 	  add_decl_to_level (level, to_add);
 	}
 
-      if (to_type == (slot ? MAYBE_STAT_TYPE (*slot) : binding->type))
-	to_type = NULL_TREE;
-
-      if (to_type)
+      if (to_type != old_type)
 	{
-	  gcc_checking_assert (TREE_CODE (to_type) == TYPE_DECL
+	  gcc_checking_assert (!old_type
+			       && TREE_CODE (to_type) == TYPE_DECL
 			       && DECL_ARTIFICIAL (to_type));
 
 	  tree type = TREE_TYPE (to_type);
@@ -1875,8 +1880,7 @@ update_binding (cp_binding_level *level,
 	{
 	  if (STAT_HACK_P (*slot))
 	    {
-	      if (to_type)
-		STAT_TYPE (*slot) = to_type;
+	      STAT_TYPE (*slot) = to_type;
 	      STAT_DECL (*slot) = to_val;
 	    }
 	  else if (to_type)
@@ -1886,8 +1890,7 @@ update_binding (cp_binding_level *level,
 	}
       else
 	{
-	  if (to_type)
-	    binding->type = to_type;
+	  binding->type = to_type;
 	  binding->value = to_val;
 	}
     }
Index: testsuite/g++.dg/lookup/pr80913.C
===================================================================
--- testsuite/g++.dg/lookup/pr80913.C	(revision 0)
+++ testsuite/g++.dg/lookup/pr80913.C	(working copy)
@@ -0,0 +1,11 @@
+// PR 80913 infinite look on spelling corrector caused by incorrectly
+// chained decl
+
+extern int meminfo ();
+struct meminfo {};
+
+void frob ()
+{
+  meminf (); // { dg-error "not declared" }
+  // { dg-message "suggested alternative" "" { target *-*-* } .-1 }
+}

Reply via email to