diff mbox

[C++] PR 80891 #1

Message ID 454b3711-2d2f-2343-c69e-2b20db357855@acm.org
State New
Headers show

Commit Message

Nathan Sidwell May 29, 2017, 2:13 p.m. UTC
This patch fixes the first testcase in 80891.  That was a case af a 
using declaration and a using directive bringing in the same function 
during lookup.  the template specialization machinery wasn't prepared 
for that, and reasonably thought neither instance was more specialized.

This patch teaches most_specialized_template to ignore duplicates.

However, I think my decision to permit lookup to return duplicates was 
wrong.  It should try harder not to -- as (a) it appears to be more 
common than I'd guessed and (b) the cost of returning duplicates is 
high, as both go through the instantiation machinery when there are 
templates involved.

Now that using declarations are ordered wrt regular functions, we can do 
better than before -- and even if we couldn't we can do no worse.

I've committed this patch, to unbreak things, but I'm going to leave the 
defect open and fixup lookup shortly, along with turning this patch into 
an appropriate assert.

nathan
diff mbox

Patch

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

	PR c++/80891 (#1)
	* pt.c (most_specialized_instantiation): Cope with duplicate
	instantiations.

	PR c++/80891 (#1)
	* g++.dg/lookup/pr80891-1.C: New.

Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 248571)
+++ cp/pt.c	(working copy)
@@ -21728,31 +21728,32 @@  most_specialized_instantiation (tree tem
 
   champ = templates;
   for (fn = TREE_CHAIN (templates); fn; fn = TREE_CHAIN (fn))
-    {
-      int fate = more_specialized_inst (TREE_VALUE (champ), TREE_VALUE (fn));
-      if (fate == -1)
-	champ = fn;
-      else if (!fate)
-	{
-	  /* Equally specialized, move to next function.  If there
-	     is no next function, nothing's most specialized.  */
-	  fn = TREE_CHAIN (fn);
+    if (TREE_VALUE (champ) != TREE_VALUE (fn))
+      {
+	int fate = more_specialized_inst (TREE_VALUE (champ), TREE_VALUE (fn));
+	if (fate == -1)
 	  champ = fn;
-	  if (!fn)
-	    break;
-	}
-    }
+	else if (!fate)
+	  {
+	    /* Equally specialized, move to next function.  If there
+	       is no next function, nothing's most specialized.  */
+	    fn = TREE_CHAIN (fn);
+	    champ = fn;
+	    if (!fn)
+	      break;
+	  }
+      }
 
   if (champ)
     /* Now verify that champ is better than everything earlier in the
        instantiation list.  */
-    for (fn = templates; fn != champ; fn = TREE_CHAIN (fn)) {
-      if (more_specialized_inst (TREE_VALUE (champ), TREE_VALUE (fn)) != 1)
-      {
-        champ = NULL_TREE;
-        break;
-      }
-    }
+    for (fn = templates; fn != champ; fn = TREE_CHAIN (fn))
+      if (TREE_VALUE (champ) != TREE_VALUE (fn)
+	  && more_specialized_inst (TREE_VALUE (champ), TREE_VALUE (fn)) != 1)
+	{
+	  champ = NULL_TREE;
+	  break;
+	}
 
   processing_template_decl--;
 
Index: testsuite/g++.dg/lookup/pr80891-1.C
===================================================================
--- testsuite/g++.dg/lookup/pr80891-1.C	(revision 0)
+++ testsuite/g++.dg/lookup/pr80891-1.C	(working copy)
@@ -0,0 +1,19 @@ 
+// PR c++/80891 part 1
+// std::endl is found via two paths and most_specialized_instantiation
+// gets confused.
+
+namespace std {
+  struct A {
+    void operator<<(A(A));
+  };
+  template <typename _CharT, typename _Traits> _CharT endl(_Traits);
+  A a;
+}
+
+using std::endl;
+
+void chi_squared_sample_sized()
+{
+  using namespace std;
+  a << endl;
+}