public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter
@ 2021-09-10 19:06 dangelog at gmail dot com
  2021-09-15 16:16 ` [Bug c++/102283] " ppalka at gcc dot gnu.org
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: dangelog at gmail dot com @ 2021-09-10 19:06 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

            Bug ID: 102283
           Summary: Inconsistent/wrong overload resolution when using an
                    initializer list and a defaulted template parameter
           Product: gcc
           Version: 11.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hello,

The following testcase has an "inconsistent" overload resolution:


template <typename U>
struct helper {};

struct data {};

template <typename T, typename E>
struct S 
{
    template <typename T2=T>
    void f(T2 &&); // #1

    template <typename E2=E>
    void f(const helper<E2> &); // #2
};

int main() {
    S<int, int> s1;
    S<data, int> s2;
    s1.f({});
    s2.f({});
}


https://gcc.godbolt.org/z/nsj48M7af


On GCC 11, the the first call to f() resolves to #1, but the second call
resolves to #2. I cannot find any reason for this inconsistency in the ranking
of the overloads; no warnings are emitted under -Wall -Wextra. 

Clang and MSVC both always call #1.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter
  2021-09-10 19:06 [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter dangelog at gmail dot com
@ 2021-09-15 16:16 ` ppalka at gcc dot gnu.org
  2021-09-15 20:29 ` dangelog at gmail dot com
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: ppalka at gcc dot gnu.org @ 2021-09-15 16:16 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ppalka at gcc dot gnu.org

--- Comment #1 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Reduced testcase:

struct A { };
struct B { };

void f(A&&); // #1
void f(const B&) = delete; // #2

int main() {
  f({});
}

It seems Clang and MSVC consider the ICS for #1 to be better than that for #2,
but I'm not sure why.

According to http://eel.is/c++draft/over.ics.rank#3.3 the two ICSes should be
incomparable since they initialize different classes, so at least according to
that paragraph it appears GCC is behaving correctly here.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter
  2021-09-10 19:06 [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter dangelog at gmail dot com
  2021-09-15 16:16 ` [Bug c++/102283] " ppalka at gcc dot gnu.org
@ 2021-09-15 20:29 ` dangelog at gmail dot com
  2021-09-16 13:40 ` ppalka at gcc dot gnu.org
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: dangelog at gmail dot com @ 2021-09-15 20:29 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

--- Comment #2 from Giuseppe D'Angelo <dangelog at gmail dot com> ---
Hi,

Do you think that in my original testcase the call should be rejected as
ambiguous as well? (It seems "reasonable" to me, but maybe I'm missing some
niche detail about overload resolution when combined with template deduction.)


This small variation over the testcase:


struct A { };
struct B { };

template <typename T = A>
void f(T &&); // #1
void f(const B&) = delete; // #2

int main() {
  f({});
}

This now makes GCC select #2, and fail to compile because it's deleted; Clang
and MSVC still select #1. But a further, minor change:


struct A { };
struct B { };

template <typename T = int> // <-- changed this
void f(T &&); // #1
void f(const B&) = delete; // #2

int main() {
  f({});
}

makes GCC select #1...

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter
  2021-09-10 19:06 [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter dangelog at gmail dot com
  2021-09-15 16:16 ` [Bug c++/102283] " ppalka at gcc dot gnu.org
  2021-09-15 20:29 ` dangelog at gmail dot com
@ 2021-09-16 13:40 ` ppalka at gcc dot gnu.org
  2021-09-16 17:46 ` jason at gcc dot gnu.org
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: ppalka at gcc dot gnu.org @ 2021-09-16 13:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

--- Comment #3 from Patrick Palka <ppalka at gcc dot gnu.org> ---
(In reply to Giuseppe D'Angelo from comment #2)
> Hi,
> 
> Do you think that in my original testcase the call should be rejected as
> ambiguous as well? (It seems "reasonable" to me, but maybe I'm missing some
> niche detail about overload resolution when combined with template
> deduction.)
> 
> 
> This small variation over the testcase:
> 
> 
> struct A { };
> struct B { };
> 
> template <typename T = A>
> void f(T &&); // #1
> void f(const B&) = delete; // #2
> 
> int main() {
>   f({});
> }
> 
> This now makes GCC select #2, and fail to compile because it's deleted;

I think this is because GCC considers the two ICSes to be incomparable, but
then #2 wins over #1 anyway because non-templates are preferred over templates
(as per [over.match.best]).

Whereas with Clang/MSVC, I presume they consider the ICS for #1 to be better
than that for #2 (though I haven't found the wording in the standard that
supports this), so #1 wins during the ICS comparison stage of overload
resolution.

> Clang and MSVC still select #1. But a further, minor change:
> 
> 
> struct A { };
> struct B { };
> 
> template <typename T = int> // <-- changed this
> void f(T &&); // #1
> void f(const B&) = delete; // #2
> 
> int main() {
>   f({});
> }
> 
> makes GCC select #1...

This example is a different because the ICS for #1 is a standard conversion
sequence (since the {} initializes a non-class) whereas for #2 it's a
user-defined conversion sequence (since the {} initializes a class), and the
former kind is always better than the latter.  So #1 wins due to having the
better ICS.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter
  2021-09-10 19:06 [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter dangelog at gmail dot com
                   ` (2 preceding siblings ...)
  2021-09-16 13:40 ` ppalka at gcc dot gnu.org
@ 2021-09-16 17:46 ` jason at gcc dot gnu.org
  2021-10-01 17:30 ` dangelog at gmail dot com
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: jason at gcc dot gnu.org @ 2021-09-16 17:46 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

Jason Merrill <jason at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason at gcc dot gnu.org

--- Comment #4 from Jason Merrill <jason at gcc dot gnu.org> ---
(In reply to Patrick Palka from comment #1)
> According to http://eel.is/c++draft/over.ics.rank#3.3 the two ICSes should
> be incomparable since they initialize different classes, so at least
> according to that paragraph it appears GCC is behaving correctly here.

I agree with your reading.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter
  2021-09-10 19:06 [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter dangelog at gmail dot com
                   ` (3 preceding siblings ...)
  2021-09-16 17:46 ` jason at gcc dot gnu.org
@ 2021-10-01 17:30 ` dangelog at gmail dot com
  2021-10-12 13:40 ` ppalka at gcc dot gnu.org
  2021-10-12 13:47 ` ppalka at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: dangelog at gmail dot com @ 2021-10-01 17:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

--- Comment #5 from Giuseppe D'Angelo <dangelog at gmail dot com> ---
(Sorry for the delay)

Thank you for the analysis. I'm now not really sure if GCC is doing something
wrong (vs Clang/MSVC). Feel free to close/suspend this task if you strongly
believe GCC is right here.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter
  2021-09-10 19:06 [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter dangelog at gmail dot com
                   ` (4 preceding siblings ...)
  2021-10-01 17:30 ` dangelog at gmail dot com
@ 2021-10-12 13:40 ` ppalka at gcc dot gnu.org
  2021-10-12 13:47 ` ppalka at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: ppalka at gcc dot gnu.org @ 2021-10-12 13:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fchelnokov at gmail dot com

--- Comment #6 from Patrick Palka <ppalka at gcc dot gnu.org> ---
*** Bug 102691 has been marked as a duplicate of this bug. ***

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter
  2021-09-10 19:06 [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter dangelog at gmail dot com
                   ` (5 preceding siblings ...)
  2021-10-12 13:40 ` ppalka at gcc dot gnu.org
@ 2021-10-12 13:47 ` ppalka at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: ppalka at gcc dot gnu.org @ 2021-10-12 13:47 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

--- Comment #7 from Patrick Palka <ppalka at gcc dot gnu.org> ---
(In reply to Fedor Chelnokov from comment #0 in PR102691)
> This code is valid:
> ```
> struct Foo {};
> struct Bar {};
> 
> constexpr int Baz(const Foo&) { return 0; }
> constexpr int Baz(Bar&&) { return 1; }
> 
> int main()
> {
>   static_assert( Baz({}) == 1 );
> }
> ```
> Here Baz(Bar&&) must be preferred according to [over.ics.rank]/(3.2), as
> Clang does.

But according to [over.ics.list]/8, isn't the conversion from {} to an
aggregate type a user-defined conversion sequence and not a standard conversion
sequence?  And according to [over.ics.rank]/3.3, two such user-defined
conversion sequences to different types are incomparable.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-10-12 13:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-10 19:06 [Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter dangelog at gmail dot com
2021-09-15 16:16 ` [Bug c++/102283] " ppalka at gcc dot gnu.org
2021-09-15 20:29 ` dangelog at gmail dot com
2021-09-16 13:40 ` ppalka at gcc dot gnu.org
2021-09-16 17:46 ` jason at gcc dot gnu.org
2021-10-01 17:30 ` dangelog at gmail dot com
2021-10-12 13:40 ` ppalka at gcc dot gnu.org
2021-10-12 13:47 ` ppalka at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).