Hi! My reading of insert_late_enum_def_bindings etc. is that it intentionally appends stuff into the vector without checking if the trees are already present there (on the testcase below in particular CONST_DECLs for the e1 and e2 enumerators which are already there before), then qsorts the vector and finally member_vec_dedup removes the duplicates that are now next to each other.
But the qsort checking really requires that the entries (if ever can be present multiple times) must compare 0, or we'd need to say enter into the vector pairs of tree and original position and then sort on the original position as additional sorting key. Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-11-22 Jakub Jelinek <ja...@redhat.com> PR c++/82401 * name-lookup.c (member_name_cmp): Return 0 if a == b. * g++.dg/cpp0x/pr82401.C: New test. --- gcc/cp/name-lookup.c.jj 2017-11-21 08:43:50.000000000 +0100 +++ gcc/cp/name-lookup.c 2017-11-22 16:15:59.770611816 +0100 @@ -1469,7 +1469,10 @@ member_name_cmp (const void *a_p, const how we order these. Use UID as a proxy for source ordering, so that identically-located decls still have a well-defined stable ordering. */ - return DECL_UID (a) < DECL_UID (b) ? -1 : +1; + if (DECL_UID (a) != DECL_UID (b)) + return DECL_UID (a) < DECL_UID (b) ? -1 : +1; + gcc_assert (a == b); + return 0; } static struct { --- gcc/testsuite/g++.dg/cpp0x/pr82401.C.jj 2017-11-22 16:47:39.384050804 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr82401.C 2017-11-22 16:53:43.860805879 +0100 @@ -0,0 +1,16 @@ +// PR c++/82401 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +template <typename T> struct A +{ + enum E : T; + void h (); +}; +template <typename T> enum A<T>::E : T { e1, e2 }; +template <> enum A<long long>::E : long long {}; +template <typename T> struct C +{ + enum class E : T; +}; +C<int>::E c3 = C<int>::E::e1; // { dg-error "is not a member of" } Jakub