Reduced from http://stackoverflow.com/q/40706399/2756719: struct A { void operator()(); }; struct B { void operator()(); }; struct C : A, B {}; template<class T> decltype(T()()) foo(int); template<class> int foo(...); using type = decltype(foo<C>(0)); using type = int; produces: prog.cc: In substitution of 'template<class T> decltype (T()()) foo(int) [with T = C]': prog.cc:10:31: required from here prog.cc:6:13: error: request for member 'operator()' is ambiguous decltype(T()()) foo(int); ~~~^~ prog.cc:2:17: note: candidates are: void B::operator()() struct B { void operator()(); }; ^~~~~~~~ prog.cc:1:17: note: void A::operator()() struct A { void operator()(); }; ^~~~~~~~ prog.cc: In substitution of 'template<class T> decltype (T()()) foo(int) [with T = C]': prog.cc:10:31: required from here prog.cc:6:13: error: request for member 'operator()' is ambiguous decltype(T()()) foo(int); ~~~^~ prog.cc:2:17: note: candidates are: void B::operator()() struct B { void operator()(); }; ^~~~~~~~ prog.cc:1:17: note: void A::operator()() struct A { void operator()(); }; ^~~~~~~~ (Yes, the error messages are repeated, see http://melpon.org/wandbox/permlink/nZj4Wn9ZgFMMm63l) Surprisingly enough, using 'decltype(T().operator()())' compiles (http://melpon.org/wandbox/permlink/2sJ0ZGcA4ZIvqfvn), so it seems that this doesn't affect all name lookup, only when the overloaded operator() is used by a function call expression.
Confirmed. Not a regression -- this never worked properly. I have a patch.
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:098cf31aa2631db6922d4de5661c1b0ce19af0aa commit r11-399-g098cf31aa2631db6922d4de5661c1b0ce19af0aa Author: Patrick Palka <ppalka@redhat.com> Date: Thu May 14 12:56:18 2020 -0400 c++: Missing SFINAE with lookup_fnfields [PR78446] Here we're failing to do SFINAE in build_op_call when looking up the class's operator() via lookup_fnfields, which calls lookup_member always with complain=tf_warning_or_error; from there we would complain about an ambiguous lookup for operator(). This patch fixes this by adding a tsubst_flags_t parameter to lookup_fnfields and adjusting all its callers appropriately. gcc/cp/ChangeLog: PR c++/78446 * call.c (build_op_call): Pass complain to lookup_fnfields. (build_special_member_call): Likewise. * class.c (type_requires_array_cookie): Pass tf_warning_or_error to lookup_fnfields. * cp-tree.h (lookup_fnfields): Add tsubst_flags_t parameter. * except.c (build_throw): Pass tf_warning_or_error to lookup_fnfields. * init.c (build_new_1): Pass complain to lookup_fnfields. * method.c (locate_fn_flags): Likewise. * name-lookup.c (lookup_name_real_1): Pass tf_warning_or_error to lookup_fnfields. * pt.c (tsubst_baselink): Pass complain to lookup_fnfields. * search.c (lookup_fnfields): New 'complain' parameter. Pass it to lookup_member. gcc/testsuite/ChangeLog: PR c++/78446 * g++.dg/template/sfinae31.C: New test.
Fixed for GCC 11.