Bug 78446 - Ambiguous member lookup for operator() in a function call expression treated as hard error in SFINAE context
Summary: Ambiguous member lookup for operator() in a function call expression treated ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: 11.0
Assignee: Patrick Palka
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2016-11-21 10:49 UTC by TC
Modified: 2020-05-14 17:03 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-05-09 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description TC 2016-11-21 10:49:22 UTC
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.
Comment 1 Patrick Palka 2020-05-09 16:46:18 UTC
Confirmed.  Not a regression -- this never worked properly.  I have a patch.
Comment 2 GCC Commits 2020-05-14 17:03:06 UTC
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.
Comment 3 Patrick Palka 2020-05-14 17:03:39 UTC
Fixed for GCC 11.