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
--
Nathan Sidwell
2017-05-29 Nathan Sidwell <nat...@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;
+}